Pass config as props
This commit is contained in:
parent
c6066fd038
commit
82eb282e17
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -54,7 +54,7 @@ const AvatarCard = ({ profile, loading }) => {
|
||||
|
||||
AvatarCard.propTypes = {
|
||||
profile: PropTypes.object,
|
||||
loading: PropTypes.bool,
|
||||
loading: PropTypes.bool.isRequired,
|
||||
};
|
||||
|
||||
export default AvatarCard;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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 = {
|
||||
|
||||
@ -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 = {
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user