Pass config as props

This commit is contained in:
Ariful Alam 2022-03-25 22:45:11 +06:00
parent c6066fd038
commit 82eb282e17
12 changed files with 317 additions and 248 deletions

View File

@ -1,7 +1,8 @@
import config from '../gitprofile.config';
import GitProfile from './components/GitProfile';
function App() {
return <GitProfile />;
return <GitProfile config={config} />;
}
export default App;

View File

@ -12,12 +12,12 @@ import Education from './education';
import Project from './project';
import Blog from './blog';
import { getInitialTheme, setupHotjar } from '../helpers/utils';
import config from '../../gitprofile.config';
import '../assets/index.css';
import { HelmetProvider } from 'react-helmet-async';
import PropTypes from 'prop-types';
import '../assets/index.css';
const GitProfile = () => {
const [theme, setTheme] = useState(getInitialTheme());
const GitProfile = ({ config }) => {
const [theme, setTheme] = useState(getInitialTheme(config.themeConfig));
const [loading, setLoading] = useState(true);
const [profile, setProfile] = useState(null);
const [repo, setRepo] = useState(null);
@ -31,7 +31,7 @@ const GitProfile = () => {
}, [theme]);
useEffect(() => {
setupHotjar();
setupHotjar(config.hotjar);
}, []);
const loadData = useCallback(() => {
@ -113,7 +113,12 @@ const GitProfile = () => {
return (
<HelmetProvider>
<HeadTagEditor profile={profile} theme={theme} />
<HeadTagEditor
profile={profile}
theme={theme}
googleAnalytics={config.googleAnalytics}
social={config.social}
/>
<div className="fade-in h-screen">
{error ? (
<ErrorPage
@ -128,8 +133,7 @@ const GitProfile = () => {
subTitle={
error === 404 ? (
<p>
Please provide correct github username in{' '}
<code>gitprofile.config.js</code>
Please provide correct github username in <code>config</code>
</p>
) : error === 429 ? (
<p>
@ -159,19 +163,37 @@ const GitProfile = () => {
theme={theme}
setTheme={setTheme}
loading={loading}
themeConfig={config.themeConfig}
/>
)}
<AvatarCard profile={profile} loading={loading} />
<Details profile={profile} loading={loading} />
<Skill loading={loading} />
<Experience loading={loading} />
<Education loading={loading} />
<Details
profile={profile}
loading={loading}
github={config.github}
social={config.social}
/>
<Skill loading={loading} skills={config.skills} />
<Experience
loading={loading}
experiences={config.experiences}
/>
<Education loading={loading} education={config.education} />
</div>
</div>
<div className="lg:col-span-2 col-span-1">
<div className="grid grid-cols-1 gap-6">
<Project repo={repo} loading={loading} />
<Blog loading={loading} />
<Project
repo={repo}
loading={loading}
github={config.github}
googleAnalytics={config.googleAnalytics}
/>
<Blog
loading={loading}
googleAnalytics={config.googleAnalytics}
blog={config.blog}
/>
</div>
</div>
</div>
@ -204,4 +226,66 @@ const GitProfile = () => {
);
};
GitProfile.propTypes = {
config: PropTypes.shape({
github: PropTypes.shape({
username: PropTypes.string.isRequired,
sortBy: PropTypes.oneOf(['stars', 'updated']).isRequired,
limit: PropTypes.number.isRequired,
exclude: PropTypes.shape({
forks: PropTypes.bool.isRequired,
projects: PropTypes.array.isRequired,
}).isRequired,
}).isRequired,
social: PropTypes.shape({
linkedin: PropTypes.string,
twitter: PropTypes.string,
facebook: PropTypes.string,
dribbble: PropTypes.string,
behance: PropTypes.string,
medium: PropTypes.string,
devto: PropTypes.string,
website: PropTypes.string,
phone: PropTypes.string,
email: PropTypes.string,
}).isRequired,
skills: PropTypes.array.isRequired,
experiences: PropTypes.arrayOf(
PropTypes.shape({
company: PropTypes.string,
position: PropTypes.string,
from: PropTypes.string,
to: PropTypes.string,
})
).isRequired,
education: PropTypes.arrayOf(
PropTypes.shape({
institution: PropTypes.string,
degree: PropTypes.string,
from: PropTypes.string,
to: PropTypes.string,
})
).isRequired,
blog: PropTypes.shape({
source: PropTypes.string,
username: PropTypes.string,
limit: PropTypes.number,
}).isRequired,
googleAnalytics: PropTypes.shape({
id: PropTypes.string,
}).isRequired,
hotjar: PropTypes.shape({
id: PropTypes.string,
snippetVersion: PropTypes.number,
}).isRequired,
themeConfig: PropTypes.shape({
default: PropTypes.string.isRequired,
disableSwitch: PropTypes.bool.isRequired,
respectPrefersColorScheme: PropTypes.bool.isRequired,
themes: PropTypes.array.isRequired,
customTheme: PropTypes.object.isRequired,
}).isRequired,
}).isRequired,
};
export default GitProfile;

View File

@ -54,7 +54,7 @@ const AvatarCard = ({ profile, loading }) => {
AvatarCard.propTypes = {
profile: PropTypes.object,
loading: PropTypes.bool,
loading: PropTypes.bool.isRequired,
};
export default AvatarCard;

View File

@ -4,15 +4,14 @@ import { Fragment, useEffect, useState } from 'react';
import { ga, skeleton } from '../../helpers/utils';
import LazyImage from '../lazy-image';
import PropTypes from 'prop-types';
import config from '../../../gitprofile.config';
const displaySection = () => {
const displaySection = (blog) => {
if (
typeof config.blog !== 'undefined' &&
typeof config.blog.source !== 'undefined' &&
typeof config.blog.username !== 'undefined' &&
config.blog.source &&
config.blog.username
typeof blog !== 'undefined' &&
typeof blog.source !== 'undefined' &&
typeof blog.username !== 'undefined' &&
blog.source &&
blog.username
) {
return true;
} else {
@ -20,20 +19,20 @@ const displaySection = () => {
}
};
const Blog = ({ loading }) => {
const Blog = ({ loading, blog, googleAnalytics }) => {
const [articles, setArticles] = useState(null);
useEffect(() => {
if (displaySection()) {
if (config.blog.source === 'medium') {
if (displaySection(blog)) {
if (blog.source === 'medium') {
getMediumArticle({
user: config.blog.username,
user: blog.username,
}).then((res) => {
setArticles(res);
});
} else if (config.blog.source === 'dev.to') {
} else if (blog.source === 'dev.to') {
getDevtoArticle({
user: config.blog.username,
user: blog.username,
}).then((res) => {
setArticles(res);
});
@ -43,7 +42,7 @@ const Blog = ({ loading }) => {
const renderSkeleton = () => {
let array = [];
for (let index = 0; index < config.blog.limit; index++) {
for (let index = 0; index < blog.limit; index++) {
array.push(
<div className="card shadow-lg compact bg-base-100" key={index}>
<div className="p-8 h-full w-full">
@ -101,7 +100,7 @@ const Blog = ({ loading }) => {
const renderArticles = () => {
return (
articles &&
articles.slice(0, config.blog.limit).map((article, index) => (
articles.slice(0, blog.limit).map((article, index) => (
<a
className="card shadow-lg compact bg-base-100 cursor-pointer"
key={index}
@ -110,7 +109,7 @@ const Blog = ({ loading }) => {
e.preventDefault();
try {
if (config.googleAnalytics?.id) {
if (googleAnalytics?.id) {
ga.event({
action: 'Click Blog Post',
params: {
@ -174,7 +173,7 @@ const Blog = ({ loading }) => {
return (
<Fragment>
{displaySection() && (
{displaySection(blog) && (
<div className="col-span-1 lg:col-span-2">
<div className="grid grid-cols-2 gap-6">
<div className="col-span-2">
@ -207,7 +206,9 @@ const Blog = ({ loading }) => {
};
Blog.propTypes = {
loading: PropTypes.bool,
loading: PropTypes.bool.isRequired,
blog: PropTypes.object.isRequired,
googleAnalytics: PropTypes.object.isRequired,
};
export default Blog;

View File

@ -14,7 +14,6 @@ import {
} from 'react-icons/fa';
import PropTypes from 'prop-types';
import { skeleton } from '../../helpers/utils';
import config from '../../../gitprofile.config';
const ListItem = ({ icon, title, value, link, skeleton = false }) => {
return (
@ -43,7 +42,7 @@ const ListItem = ({ icon, title, value, link, skeleton = false }) => {
);
};
const Details = ({ profile, loading }) => {
const Details = ({ profile, loading, social, github }) => {
const renderSkeleton = () => {
let array = [];
for (let index = 0; index < 4; index++) {
@ -86,99 +85,89 @@ const Details = ({ profile, loading }) => {
<ListItem
icon={<AiFillGithub className="mr-2" />}
title="GitHub:"
value={config.github.username}
link={`https://github.com/${config.github.username}`}
value={github.username}
link={`https://github.com/${github.username}`}
/>
{typeof config.social.twitter !== 'undefined' &&
config.social.twitter && (
<ListItem
icon={<SiTwitter className="mr-2" />}
title="Twitter:"
value={config.social.twitter}
link={`https://twitter.com/${config.social.twitter}`}
/>
)}
{typeof config.social.linkedin !== 'undefined' &&
config.social.linkedin && (
<ListItem
icon={<GrLinkedinOption className="mr-2" />}
title="LinkedIn:"
value={config.social.linkedin}
link={`https://www.linkedin.com/in/${config.social.linkedin}`}
/>
)}
{typeof config.social.dribbble !== 'undefined' &&
config.social.dribbble && (
<ListItem
icon={<CgDribbble className="mr-2" />}
title="Dribbble:"
value={config.social.dribbble}
link={`https://dribbble.com/${config.social.dribbble}`}
/>
)}
{typeof config.social.behance !== 'undefined' &&
config.social.behance && (
<ListItem
icon={<FaBehanceSquare className="mr-2" />}
title="Behance:"
value={config.social.behance}
link={`https://www.behance.net/${config.social.behance}`}
/>
)}
{typeof config.social.facebook !== 'undefined' &&
config.social.facebook && (
<ListItem
icon={<FaFacebook className="mr-2" />}
title="Facebook:"
value={config.social.facebook}
link={`https://www.facebook.com/${config.social.facebook}`}
/>
)}
{typeof config.social.medium !== 'undefined' &&
config.social.medium && (
<ListItem
icon={<AiFillMediumSquare className="mr-2" />}
title="Medium:"
value={config.social.medium}
link={`https://medium.com/@${config.social.medium}`}
/>
)}
{typeof config.social.devto !== 'undefined' &&
config.social.devto && (
<ListItem
icon={<FaDev className="mr-2" />}
title="Dev:"
value={config.social.devto}
link={`https://dev.to/${config.social.devto}`}
/>
)}
{typeof config.social.website !== 'undefined' &&
config.social.website && (
<ListItem
icon={<FaGlobe className="mr-2" />}
title="Website:"
value={config.social.website}
link={config.social.website}
/>
)}
{typeof config.social.phone !== 'undefined' &&
config.social.phone && (
<ListItem
icon={<RiPhoneFill className="mr-2" />}
title="Phone:"
value={config.social.phone}
link={`tel:${config.social.phone}`}
/>
)}
{typeof config.social.email !== 'undefined' &&
config.social.email && (
<ListItem
icon={<MdMail className="mr-2" />}
title="Email:"
value={config.social.email}
link={`mailto:${config.social.email}`}
/>
)}
{typeof social.twitter !== 'undefined' && social.twitter && (
<ListItem
icon={<SiTwitter className="mr-2" />}
title="Twitter:"
value={social.twitter}
link={`https://twitter.com/${social.twitter}`}
/>
)}
{typeof social.linkedin !== 'undefined' && social.linkedin && (
<ListItem
icon={<GrLinkedinOption className="mr-2" />}
title="LinkedIn:"
value={social.linkedin}
link={`https://www.linkedin.com/in/${social.linkedin}`}
/>
)}
{typeof social.dribbble !== 'undefined' && social.dribbble && (
<ListItem
icon={<CgDribbble className="mr-2" />}
title="Dribbble:"
value={social.dribbble}
link={`https://dribbble.com/${social.dribbble}`}
/>
)}
{typeof social.behance !== 'undefined' && social.behance && (
<ListItem
icon={<FaBehanceSquare className="mr-2" />}
title="Behance:"
value={social.behance}
link={`https://www.behance.net/${social.behance}`}
/>
)}
{typeof social.facebook !== 'undefined' && social.facebook && (
<ListItem
icon={<FaFacebook className="mr-2" />}
title="Facebook:"
value={social.facebook}
link={`https://www.facebook.com/${social.facebook}`}
/>
)}
{typeof social.medium !== 'undefined' && social.medium && (
<ListItem
icon={<AiFillMediumSquare className="mr-2" />}
title="Medium:"
value={social.medium}
link={`https://medium.com/@${social.medium}`}
/>
)}
{typeof social.devto !== 'undefined' && social.devto && (
<ListItem
icon={<FaDev className="mr-2" />}
title="Dev:"
value={social.devto}
link={`https://dev.to/${social.devto}`}
/>
)}
{typeof social.website !== 'undefined' && social.website && (
<ListItem
icon={<FaGlobe className="mr-2" />}
title="Website:"
value={social.website}
link={social.website}
/>
)}
{typeof social.phone !== 'undefined' && social.phone && (
<ListItem
icon={<RiPhoneFill className="mr-2" />}
title="Phone:"
value={social.phone}
link={`tel:${social.phone}`}
/>
)}
{typeof social.email !== 'undefined' && social.email && (
<ListItem
icon={<MdMail className="mr-2" />}
title="Email:"
value={social.email}
link={`mailto:${social.email}`}
/>
)}
</Fragment>
)}
</div>
@ -189,7 +178,9 @@ const Details = ({ profile, loading }) => {
Details.propTypes = {
profile: PropTypes.object,
loading: PropTypes.bool,
loading: PropTypes.bool.isRequired,
social: PropTypes.object.isRequired,
github: PropTypes.object.isRequired,
};
ListItem.propTypes = {

View File

@ -1,7 +1,6 @@
import { skeleton } from '../../helpers/utils';
import { Fragment } from 'react';
import PropTypes from 'prop-types';
import config from '../../../gitprofile.config';
const ListItem = ({ time, degree, institution }) => (
<li className="mb-5 ml-4">
@ -15,7 +14,7 @@ const ListItem = ({ time, degree, institution }) => (
</li>
);
const Education = ({ loading }) => {
const Education = ({ loading, education }) => {
const renderSkeleton = () => {
let array = [];
for (let index = 0; index < 2; index++) {
@ -41,46 +40,46 @@ const Education = ({ loading }) => {
return (
<>
{typeof config.education !== 'undefined' &&
config.education.length !== 0 && (
<div className="card shadow-lg compact bg-base-100">
<div className="card-body">
<div className="mx-3">
<h5 className="card-title">
{loading ? (
skeleton({ width: 'w-32', height: 'h-8' })
) : (
<span className="opacity-70">Education</span>
)}
</h5>
</div>
<div className="text-base-content text-opacity-60">
<ol className="relative border-l border-base-300 border-opacity-30 my-2 mx-4">
{loading ? (
renderSkeleton()
) : (
<Fragment>
{config.education.map((item, index) => (
<ListItem
key={index}
time={`${item.from} - ${item.to}`}
degree={item.degree}
institution={item.institution}
/>
))}
</Fragment>
)}
</ol>
</div>
{typeof education !== 'undefined' && education.length !== 0 && (
<div className="card shadow-lg compact bg-base-100">
<div className="card-body">
<div className="mx-3">
<h5 className="card-title">
{loading ? (
skeleton({ width: 'w-32', height: 'h-8' })
) : (
<span className="opacity-70">Education</span>
)}
</h5>
</div>
<div className="text-base-content text-opacity-60">
<ol className="relative border-l border-base-300 border-opacity-30 my-2 mx-4">
{loading ? (
renderSkeleton()
) : (
<Fragment>
{education.map((item, index) => (
<ListItem
key={index}
time={`${item.from} - ${item.to}`}
degree={item.degree}
institution={item.institution}
/>
))}
</Fragment>
)}
</ol>
</div>
</div>
)}
</div>
)}
</>
);
};
Education.propTypes = {
loading: PropTypes.bool,
loading: PropTypes.bool.isRequired,
education: PropTypes.array.isRequired,
};
ListItem.propTypes = {

View File

@ -1,7 +1,6 @@
import { skeleton } from '../../helpers/utils';
import { Fragment } from 'react';
import PropTypes from 'prop-types';
import config from '../../../gitprofile.config';
const ListItem = ({ time, position, company }) => (
<li className="mb-5 ml-4">
@ -15,7 +14,7 @@ const ListItem = ({ time, position, company }) => (
</li>
);
const Experience = ({ loading }) => {
const Experience = ({ experiences, loading }) => {
const renderSkeleton = () => {
let array = [];
for (let index = 0; index < 2; index++) {
@ -41,40 +40,39 @@ const Experience = ({ loading }) => {
return (
<>
{typeof config.experiences !== 'undefined' &&
config.experiences.length !== 0 && (
<div className="card shadow-lg compact bg-base-100">
<div className="card-body">
<div className="mx-3">
<h5 className="card-title">
{loading ? (
skeleton({ width: 'w-32', height: 'h-8' })
) : (
<span className="opacity-70">Experience</span>
)}
</h5>
</div>
<div className="text-base-content text-opacity-60">
<ol className="relative border-l border-base-300 border-opacity-30 my-2 mx-4">
{loading ? (
renderSkeleton()
) : (
<Fragment>
{config.experiences.map((experience, index) => (
<ListItem
key={index}
time={`${experience.from} - ${experience.to}`}
position={experience.position}
company={experience.company}
/>
))}
</Fragment>
)}
</ol>
</div>
{typeof experiences !== 'undefined' && experiences.length !== 0 && (
<div className="card shadow-lg compact bg-base-100">
<div className="card-body">
<div className="mx-3">
<h5 className="card-title">
{loading ? (
skeleton({ width: 'w-32', height: 'h-8' })
) : (
<span className="opacity-70">Experience</span>
)}
</h5>
</div>
<div className="text-base-content text-opacity-60">
<ol className="relative border-l border-base-300 border-opacity-30 my-2 mx-4">
{loading ? (
renderSkeleton()
) : (
<Fragment>
{experiences.map((experience, index) => (
<ListItem
key={index}
time={`${experience.from} - ${experience.to}`}
position={experience.position}
company={experience.company}
/>
))}
</Fragment>
)}
</ol>
</div>
</div>
)}
</div>
)}
</>
);
};
@ -86,7 +84,8 @@ ListItem.propTypes = {
};
Experience.propTypes = {
loading: PropTypes.bool,
experiences: PropTypes.array.isRequired,
loading: PropTypes.bool.isRequired,
};
export default Experience;

View File

@ -2,25 +2,24 @@ import { Fragment } from 'react';
import { Helmet } from 'react-helmet-async';
import PropTypes from 'prop-types';
import { isThemeDarkish } from '../../helpers/utils';
import config from '../../../gitprofile.config';
const HeadTagEditor = ({ profile, theme }) => {
const HeadTagEditor = ({ profile, theme, googleAnalytics, social }) => {
return (
<Fragment>
{profile && (
<Helmet>
{config.googleAnalytics?.id && (
{googleAnalytics?.id && (
<script
async
src={`https://www.googletagmanager.com/gtag/js?id=${config.googleAnalytics.id}`}
src={`https://www.googletagmanager.com/gtag/js?id=${googleAnalytics.id}`}
></script>
)}
{config.googleAnalytics?.id && (
{googleAnalytics?.id && (
<script>
{`window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '${config.googleAnalytics.id}');`}
gtag('config', '${googleAnalytics.id}');`}
</script>
)}
<title>Portfolio of {profile.name}</title>
@ -38,9 +37,7 @@ const HeadTagEditor = ({ profile, theme }) => {
<meta
property="og:url"
content={
typeof config.social.website !== 'undefined'
? config.social.website
: ''
typeof social.website !== 'undefined' ? social.website : ''
}
/>
<meta property="og:type" content="website" />
@ -60,7 +57,9 @@ const HeadTagEditor = ({ profile, theme }) => {
HeadTagEditor.propTypes = {
profile: PropTypes.object,
theme: PropTypes.string,
theme: PropTypes.string.isRequired,
googleAnalytics: PropTypes.object.isRequired,
social: PropTypes.object.isRequired,
};
export default HeadTagEditor;

View File

@ -2,12 +2,11 @@ import { Fragment } from 'react';
import { AiOutlineStar, AiOutlineFork } from 'react-icons/ai';
import PropTypes from 'prop-types';
import { ga, languageColor, skeleton } from '../../helpers/utils';
import config from '../../../gitprofile.config';
const Project = ({ repo, loading }) => {
const Project = ({ repo, loading, github, googleAnalytics }) => {
const renderSkeleton = () => {
let array = [];
for (let index = 0; index < config.github.limit; index++) {
for (let index = 0; index < github.limit; index++) {
array.push(
<div className="card shadow-lg compact bg-base-100" key={index}>
<div className="flex justify-between flex-col p-8 h-full w-full">
@ -61,7 +60,7 @@ const Project = ({ repo, loading }) => {
e.preventDefault();
try {
if (config.googleAnalytics?.id) {
if (googleAnalytics?.id) {
ga.event({
action: 'Click project',
params: {
@ -145,7 +144,7 @@ const Project = ({ repo, loading }) => {
skeleton({ width: 'w-10', height: 'h-5' })
) : (
<a
href={`https://github.com/${config.github.username}?tab=repositories`}
href={`https://github.com/${github.username}?tab=repositories`}
target="_blank"
rel="noreferrer"
className="opacity-50"
@ -170,7 +169,9 @@ const Project = ({ repo, loading }) => {
Project.propTypes = {
repo: PropTypes.array,
loading: PropTypes.bool,
loading: PropTypes.bool.isRequired,
github: PropTypes.object.isRequired,
googleAnalytics: PropTypes.object.isRequired,
};
export default Project;

View File

@ -1,8 +1,7 @@
import { skeleton } from '../../helpers/utils';
import PropTypes from 'prop-types';
import config from '../../../gitprofile.config';
const Skill = ({ loading }) => {
const Skill = ({ loading, skills }) => {
const renderSkeleton = () => {
let array = [];
for (let index = 0; index < 12; index++) {
@ -18,7 +17,7 @@ const Skill = ({ loading }) => {
return (
<>
{typeof config.skills !== 'undefined' && config.skills.length !== 0 && (
{typeof skills !== 'undefined' && skills.length !== 0 && (
<div className="card shadow-lg compact bg-base-100">
<div className="card-body">
<div className="mx-3">
@ -34,7 +33,7 @@ const Skill = ({ loading }) => {
<div className="-m-1 flex flex-wrap justify-center">
{loading
? renderSkeleton()
: config.skills.map((skill, index) => (
: skills.map((skill, index) => (
<div
key={index}
className="m-1 text-xs inline-flex items-center font-bold leading-sm px-3 py-1 badge-primary bg-opacity-90 rounded-full"
@ -52,7 +51,8 @@ const Skill = ({ loading }) => {
};
Skill.propTypes = {
loading: PropTypes.bool,
loading: PropTypes.bool.isRequired,
skills: PropTypes.array.isRequired,
};
export default Skill;

View File

@ -1,9 +1,8 @@
import { AiOutlineControl } from 'react-icons/ai';
import { skeleton } from '../../helpers/utils';
import PropTypes from 'prop-types';
import config from '../../../gitprofile.config';
const ThemeChanger = ({ theme, setTheme, loading }) => {
const ThemeChanger = ({ theme, setTheme, loading, themeConfig }) => {
const changeTheme = (e, selectedTheme) => {
e.preventDefault();
document.querySelector('html').setAttribute('data-theme', selectedTheme);
@ -28,7 +27,7 @@ const ThemeChanger = ({ theme, setTheme, loading }) => {
<span className="text-base-content text-opacity-40 capitalize text-sm">
{loading
? skeleton({ width: 'w-16', height: 'h-5' })
: theme === config.themeConfig.default
: theme === themeConfig.default
? 'Default'
: theme}
</span>
@ -62,9 +61,9 @@ const ThemeChanger = ({ theme, setTheme, loading }) => {
>
<ul className="p-4 menu compact">
{[
config.themeConfig.default,
...config.themeConfig.themes.filter(
(item) => item !== config.themeConfig.default
themeConfig.default,
...themeConfig.themes.filter(
(item) => item !== themeConfig.default
),
].map((item, index) => (
<li key={index}>
@ -74,9 +73,7 @@ const ThemeChanger = ({ theme, setTheme, loading }) => {
className={`${theme === item ? 'active' : ''}`}
>
<span className="opacity-60 capitalize">
{item === config.themeConfig.default
? 'Default'
: item}
{item === themeConfig.default ? 'Default' : item}
</span>
</a>
</li>
@ -92,9 +89,10 @@ const ThemeChanger = ({ theme, setTheme, loading }) => {
};
ThemeChanger.propTypes = {
theme: PropTypes.string,
setTheme: PropTypes.func,
loading: PropTypes.bool,
theme: PropTypes.string.isRequired,
setTheme: PropTypes.func.isRequired,
loading: PropTypes.bool.isRequired,
themeConfig: PropTypes.object.isRequired,
};
export default ThemeChanger;

View File

@ -1,32 +1,28 @@
import colors from '../data/colors.json';
import { hotjar } from 'react-hotjar';
import config from '../../gitprofile.config';
export const getInitialTheme = () => {
if (config.themeConfig.disableSwitch) {
return config.themeConfig.default;
export const getInitialTheme = (themeConfig) => {
if (themeConfig.disableSwitch) {
return themeConfig.default;
}
if (
typeof window !== 'undefined' &&
!(localStorage.getItem('gitprofile-theme') === null) &&
config.themeConfig.themes.includes(localStorage.getItem('gitprofile-theme'))
themeConfig.themes.includes(localStorage.getItem('gitprofile-theme'))
) {
let theme = localStorage.getItem('gitprofile-theme');
return theme;
}
if (
config.themeConfig.respectPrefersColorScheme &&
!config.themeConfig.disableSwitch
) {
if (themeConfig.respectPrefersColorScheme && !themeConfig.disableSwitch) {
return window.matchMedia('(prefers-color-scheme: dark)').matches
? 'dark'
: config.themeConfig.default;
: themeConfig.default;
}
return config.themeConfig.default;
return themeConfig.default;
};
export const skeleton = ({
@ -92,12 +88,12 @@ export const isThemeDarkish = (theme) => {
}
};
export const setupHotjar = () => {
if (config.hotjar?.id) {
let snippetVersion = config.hotjar?.snippetVersion
? config.hotjar?.snippetVersion
export const setupHotjar = (hotjarConfig) => {
if (hotjarConfig?.id) {
let snippetVersion = hotjarConfig?.snippetVersion
? hotjarConfig?.snippetVersion
: 6;
hotjar.initialize(config.hotjar.id, snippetVersion);
hotjar.initialize(hotjarConfig.id, snippetVersion);
}
};