Remove folders and files

This commit is contained in:
Ariful Alam 2022-03-18 23:30:10 +06:00
parent 6a9496aa51
commit 7b7502a118
38 changed files with 0 additions and 41846 deletions

23
.gitignore vendored
View File

@ -1,23 +0,0 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# production
/build
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*

201
LICENSE
View File

@ -1,201 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2022 Ariful Alam
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -1,10 +0,0 @@
module.exports = {
style: {
postcss: {
plugins: [
require('tailwindcss'),
require('autoprefixer'),
],
},
},
}

38305
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,79 +0,0 @@
{
"name": "ezprofile",
"version": "1.1.1",
"description": "Kickstart your personal portfolio with Github Api and blog",
"homepage": "https://arifszn.github.io/ezprofile",
"private": true,
"license": "Apache-2.0",
"author": "arifszn",
"repository": {
"type": "git",
"url": "https://github.com/arifszn/ezprofile.git"
},
"dependencies": {
"@craco/craco": "^6.2.0",
"@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^11.1.0",
"@testing-library/user-event": "^12.1.10",
"article-api": "^1.0.5",
"axios": "^0.23.0",
"daisyui": "^1.12.1",
"gh-pages": "^3.2.3",
"moment": "^2.29.1",
"prop-types": "^15.7.2",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-helmet-async": "^1.1.0",
"react-hotjar": "^3.0.1",
"react-icons": "^4.2.0",
"react-scripts": "4.0.3",
"sass": "^1.38.0",
"web-vitals": "^1.0.1"
},
"scripts": {
"start": "craco start",
"build": "craco build",
"test": "craco test",
"eject": "react-scripts eject",
"predeploy": "npm run build",
"deploy": "gh-pages -d build"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"autoprefixer": "^9.8.6",
"postcss": "^7.0.36",
"tailwindcss": "npm:@tailwindcss/postcss7-compat@^2.2.7"
},
"keywords": [
"personal-site",
"template",
"portfolio",
"personal-website",
"portfolio-website",
"portfolio-site",
"portfolio-template",
"portfolio-page",
"developer-portfolio",
"portfolio-project",
"github-portfolio",
"react-portfolio",
"github-api"
]
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 434 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 767 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

View File

@ -1,18 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="apple-touch-icon" href="%PUBLIC_URL%/apple-touch-icon.png" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<title>Portfolio</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

View File

@ -1,25 +0,0 @@
{
"short_name": "ezProfile",
"name": "Personal Portfolio",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "logo192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "logo512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#7a44ee",
"background_color": "#ffffff"
}

View File

@ -1,3 +0,0 @@
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:

View File

@ -1,178 +0,0 @@
import axios from "axios";
import { Fragment, useCallback, useContext, useEffect, useState } from "react";
import AvatarCard from "./components/AvatarCard";
import ErrorPage from "./components/ErrorPage";
import ThemeChanger from "./components/ThemeChanger";
import config from "./config";
import moment from 'moment';
import Details from "./components/Details";
import Skill from "./components/Skill";
import Experience from "./components/Experience";
import Education from "./components/Education";
import Project from "./components/Project";
import Blog from "./components/Blog";
import MetaTags from "./components/MetaTags";
import { LoadingContext } from "./contexts/LoadingContext";
import { ThemeContext } from "./contexts/ThemeContext";
function App() {
const [theme] = useContext(ThemeContext);
const [, setLoading] = useContext(LoadingContext);
const [profile, setProfile] = useState(null);
const [repo, setRepo] = useState(null);
const [error, setError] = useState(null);
const [rateLimit, setRateLimit] = useState(null);
useEffect(() => {
if (theme) {
document.documentElement.setAttribute('data-theme', theme);
}
}, [theme])
const loadData = useCallback(() => {
axios.get(`https://api.github.com/users/${config.github.username}`)
.then(response => {
let data = response.data;
let profileData = {
avatar: data.avatar_url,
name: data.name ? data.name : '',
bio: data.bio ? data.bio : '',
location: data.location ? data.location : '',
company: data.company ? data.company : ''
}
setProfile(profileData);
})
.then(() => {
let excludeRepo = ``;
config.github.exclude.projects.forEach(project => {
excludeRepo += `+-repo:${config.github.username}/${project}`;
});
let query = `user:${config.github.username}+fork:${!config.github.exclude.forks}${excludeRepo}`;
let url = `https://api.github.com/search/repositories?q=${query}&sort=${config.github.sortBy}&per_page=${config.github.limit}&type=Repositories`;
axios.get(url, {
headers: {
'Content-Type': 'application/vnd.github.v3+json'
}
})
.then(response => {
let data = response.data;
setRepo(data.items);
})
.catch((error) => {
handleError(error);
});
})
.catch((error) => {
handleError(error);
})
.finally(() => {
setLoading(false);
});
}, [setLoading])
useEffect(() => {
loadData();
}, [loadData])
const handleError = (error) => {
console.error('Error:', error);
try {
setRateLimit({
remaining: error.response.headers['x-ratelimit-remaining'],
reset: moment(new Date(error.response.headers['x-ratelimit-reset'] * 1000)).fromNow(),
});
if (error.response.status === 403) {
setError(429);
} else if (error.response.status === 404) {
setError(404);
} else {
setError(500);
}
} catch (error2) {
setError(500);
}
}
return (
<Fragment>
<MetaTags profile={profile}/>
<div className="fade-in h-screen">
{
error ? (
<ErrorPage
status={`${error}`}
title={(error === 404) ? 'The Github Username is Incorrect' : (
error === 429 ? 'Too Many Requests.' : `Ops!!`
)}
subTitle={
(error === 404) ? (
<p>
Please provide correct github username in <code>src\config.js</code>
</p>
) : (
error === 429 ? (
<p>
Oh no, you hit the{' '}
<a
href="https://developer.github.com/v3/rate_limit/"
target="_blank"
rel="noopener noreferrer"
>
rate limit
</a>
! Try again later{rateLimit && ` ${rateLimit.reset}`}.
</p>
) : `Something went wrong`
)
}
/>
) : (
<Fragment>
<div className="p-4 lg:p-10 min-h-full bg-base-200">
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6 rounded-box">
<div className="col-span-1">
<div className="grid grid-cols-1 gap-6">
{
!config.themeConfig.disableSwitch && (
<ThemeChanger/>
)
}
<AvatarCard profile={profile}/>
<Details profile={profile}/>
<Skill/>
<Experience/>
<Education/>
</div>
</div>
<div className="lg:col-span-2 col-span-1">
<div className="grid grid-cols-1 gap-6">
<Project repo={repo}/>
<Blog/>
</div>
</div>
</div>
</div>
{/* DO NOT REMOVE/MODIFY THE FOOTER. FOR MORE INFO https://github.com/arifszn/ezprofile#-please-read */}
<footer className="p-4 footer bg-base-200 text-base-content footer-center">
<div>
<p className="font-mono text-sm">Made with <a className="text-primary" href="https://github.com/arifszn/ezprofile" target="_blank" rel="noreferrer">ezProfile</a> and </p>
</div>
</footer>
</Fragment>
)
}
</div>
</Fragment>
);
}
export default App;

View File

@ -1,8 +0,0 @@
import { render, screen } from '@testing-library/react';
import App from './App';
test('renders learn react link', () => {
render(<App />);
const linkElement = screen.getByText(/learn react/i);
expect(linkElement).toBeInTheDocument();
});

View File

@ -1,71 +0,0 @@
import { fallbackImage, skeleton } from "../helpers/utils";
import LazyImage from "./LazyImage";
import PropTypes from 'prop-types';
import { useContext } from "react";
import { LoadingContext } from "../contexts/LoadingContext";
const AvatarCard = (props) => {
const [loading] = useContext(LoadingContext);
return (
<div className="card shadow-lg compact bg-base-100">
<div className="grid place-items-center py-8">
{
(loading || !props.profile) ? (
<div className="avatar opacity-90">
<div className="mb-8 rounded-full w-32 h-32">
{
skeleton({
width: 'w-full',
height: 'h-full',
shape: '',
})
}
</div>
</div>
) : (
<div className="avatar opacity-90">
<div className="mb-8 rounded-full w-32 h-32 ring ring-primary ring-offset-base-100 ring-offset-2">
{
<LazyImage
src={props.profile.avatar ? props.profile.avatar : fallbackImage}
alt={props.profile.name}
placeholder={
skeleton({
width: 'w-full',
height: 'h-full',
shape: '',
})
}
/>
}
</div>
</div>
)
}
<div className="text-center mx-auto px-8">
<h5 className="font-bold text-2xl">
{
(loading || !props.profile) ? (
skeleton({ width: 'w-48', height: 'h-8' })
) : <span className="opacity-70">{props.profile.name}</span>
}
</h5>
<div className="mt-3 text-base-content text-opacity-60">
{
(loading || !props.profile) ? (
skeleton({ width: 'w-48', height: 'h-5' })
) : props.profile.bio
}
</div>
</div>
</div>
</div>
)
}
AvatarCard.propTypes = {
profile: PropTypes.object
}
export default AvatarCard;

View File

@ -1,197 +0,0 @@
import { getDevtoArticle, getMediumArticle } from "article-api";
import moment from "moment";
import { Fragment, useContext, useEffect, useState } from "react";
import { CgHashtag } from 'react-icons/cg';
import config from "../config";
import { LoadingContext } from "../contexts/LoadingContext";
import { ga, skeleton } from "../helpers/utils";
import LazyImage from "./LazyImage";
const displaySection = () => {
if (
typeof config.blog !== 'undefined' &&
typeof config.blog.source !== 'undefined' &&
typeof config.blog.username !== 'undefined' &&
config.blog.source &&
config.blog.username
) {
return true;
} else {
return false;
}
}
const Blog = () => {
const [articles, setArticles] = useState(null);
const [loading] = useContext(LoadingContext);
useEffect(() => {
if (displaySection()) {
if (config.blog.source === 'medium') {
getMediumArticle({
user: config.blog.username
})
.then(res => {
setArticles(res);
});
} else if (config.blog.source === 'dev.to') {
getDevtoArticle({
user: config.blog.username
})
.then(res => {
setArticles(res);
});
}
}
}, [])
const renderSkeleton = () => {
let array = [];
for (let index = 0; index < config.blog.limit; index++) {
array.push((
<div className="card shadow-lg compact bg-base-100" key={index}>
<div className="p-8 h-full w-full">
<div className="flex items-center flex-col md:flex-row">
<div className="avatar mb-5 md:mb-0">
<div className="w-24 h-24 mask mask-squircle">
{
skeleton({
width: 'w-full',
height: 'h-full',
shape: '',
})
}
</div>
</div>
<div className="w-full">
<div className="flex items-start px-4">
<div className="w-full">
<h2>
{skeleton({ width: 'w-full', height: 'h-8', className: 'mb-2 mx-auto md:mx-0' })}
</h2>
{skeleton({ width: 'w-24', height: 'h-3', className: 'mx-auto md:mx-0' })}
<div className="mt-3">
{skeleton({ width: 'w-full', height: 'h-4', className: 'mx-auto md:mx-0' })}
</div>
<div className="mt-4 flex items-center flex-wrap justify-center md:justify-start">
{skeleton({ width: 'w-32', height: 'h-4', className: "md:mr-2 mx-auto md:mx-0" })}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
))
}
return array;
}
const renderArticles = () => {
return articles && articles.slice(0, config.blog.limit).map((article, index) => (
<div
className="card shadow-lg compact bg-base-100 cursor-pointer"
key={index}
onClick={() => {
try {
if (config.googleAnalytics?.id) {
ga.event({
action: "Click Blog Post",
params: {
post: article.title
}
});
}
} catch (error) {
console.error(error);
}
window.open(article.link, '_blank')
}}
>
<div className="p-8 h-full w-full">
<div className="flex items-center flex-col md:flex-row">
<div className="avatar mb-5 md:mb-0 opacity-90">
<div className="w-24 h-24 mask mask-squircle">
<LazyImage
src={article.thumbnail}
alt={'thumbnail'}
placeholder={
skeleton({
width: 'w-full',
height: 'h-full',
shape: '',
})
}
/>
</div>
</div>
<div className="w-full">
<div className="flex items-start px-4">
<div className="text-center md:text-left w-full">
<h2 className="font-semibold text-base-content opacity-60">{article.title}</h2>
<p className="opacity-50 text-xs">
{moment(article.publishedAt).fromNow()}
</p>
<p className="mt-3 text-base-content text-opacity-60 text-sm">
{article.description}
</p>
<div className="mt-4 flex items-center flex-wrap justify-center md:justify-start">
{
article.categories.map((category, index2) => (
<div key={index2} className="flex text-sm mr-3 items-center opacity-50 font-bold font-mono">
<span><CgHashtag /></span>
<span>{category}</span>
</div>
))
}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
))
}
return (
<Fragment>
{
displaySection() && (
<div className="col-span-1 lg:col-span-2">
<div className="grid grid-cols-2 gap-6">
<div className="col-span-2">
<div className="card compact bg-base-100 shadow-sm">
<div className="card-body">
<ul className="menu row-span-3 bg-base-100 text-base-content">
<li>
<div className="pb-0-important mx-4 flex items-center justify-between">
<h5 className="card-title">
{
(loading || !articles) ? skeleton({ width: 'w-28', height: 'h-8' }) : (
<span className="opacity-70">Recent Posts</span>
)
}
</h5>
</div>
</li>
</ul>
</div>
</div>
</div>
<div className="col-span-2">
<div className="grid grid-cols-1 gap-6">
{(loading || !articles) ? renderSkeleton() : renderArticles()}
</div>
</div>
</div>
</div>
)
}
</Fragment>
)
}
export default Blog;

View File

@ -1,307 +0,0 @@
import { MdLocationOn, MdMail } from 'react-icons/md';
import { AiFillGithub, AiFillMediumSquare } from 'react-icons/ai';
import { SiTwitter } from 'react-icons/si';
import { GrLinkedinOption } from 'react-icons/gr';
import { CgDribbble } from 'react-icons/cg';
import { RiPhoneFill } from 'react-icons/ri';
import { FaBehanceSquare, FaBuilding, FaDev, FaFacebook, FaGlobe } from 'react-icons/fa';
import config from '../config';
import { skeleton } from '../helpers/utils';
import PropTypes from 'prop-types';
import { useContext } from 'react';
import { LoadingContext } from '../contexts/LoadingContext';
const Details = (props) => {
const [loading] = useContext(LoadingContext);
const renderSkeleton = () => {
let array = [];
for (let index = 0; index < 4; index++) {
array.push((
<li key={index}>
<span>
{skeleton({ width: 'w-6', height: 'h-4', className: 'mr-2' })}
{skeleton({ width: 'w-32', height: 'h-4' })}
</span>
</li>
))
}
return array;
}
return (
<div className="card shadow-lg compact bg-base-100">
<div className="card-body">
<ul className="menu row-span-3 bg-base-100 text-base-content text-opacity-60">
{
(loading || !props.profile) ? renderSkeleton() : (
<>
{
props.profile.location && (
<li>
<span>
<div>
<MdLocationOn className="mr-2"/>
</div>
<div>
{props.profile.location}
</div>
</span>
</li>
)
}
{
props.profile.company && (
<li>
<span>
<div>
<FaBuilding className="mr-2"/>
</div>
<div>
{props.profile.company}
</div>
</span>
</li>
)
}
<li>
<span>
<div>
<AiFillGithub className="mr-2"/>
</div>
<div>
<a
href={`https://github.com/${config.github.username}`}
target="_blank"
rel="noreferrer"
className="text-base-content-important"
>
{config.github.username}
</a>
</div>
</span>
</li>
{
typeof config.social.linkedin !== 'undefined' && config.social.linkedin && (
<li>
<span>
<div>
<GrLinkedinOption className="mr-2"/>
</div>
<div>
<a
href={`https://www.linkedin.com/in/${config.social.linkedin}`}
target="_blank"
rel="noreferrer"
className="text-base-content-important"
>
{config.social.linkedin}
</a>
</div>
</span>
</li>
)
}
{
typeof config.social.twitter !== 'undefined' && config.social.twitter && (
<li>
<span>
<div>
<SiTwitter className="mr-2"/>
</div>
<div>
<a
href={`https://twitter.com/${config.social.twitter}`}
target="_blank"
rel="noreferrer"
className="text-base-content-important"
>
{config.social.twitter}
</a>
</div>
</span>
</li>
)
}
{
typeof config.social.dribbble !== 'undefined' && config.social.dribbble && (
<li>
<span>
<div>
<CgDribbble className="mr-2"/>
</div>
<div>
<a
href={`https://dribbble.com/${config.social.dribbble}`}
target="_blank"
rel="noreferrer"
className="text-base-content-important"
>
{config.social.dribbble}
</a>
</div>
</span>
</li>
)
}
{
typeof config.social.behance !== 'undefined' && config.social.behance && (
<li>
<span>
<div>
<FaBehanceSquare className="mr-2"/>
</div>
<div>
<a
href={`https://www.behance.net/${config.social.behance}`}
target="_blank"
rel="noreferrer"
className="text-base-content-important"
>
{config.social.behance}
</a>
</div>
</span>
</li>
)
}
{
typeof config.social.facebook !== 'undefined' && config.social.facebook && (
<li>
<span>
<div>
<FaFacebook className="mr-2"/>
</div>
<div>
<a
href={`https://www.facebook.com/${config.social.facebook}`}
target="_blank"
rel="noreferrer"
className="text-base-content-important"
>
{config.social.facebook}
</a>
</div>
</span>
</li>
)
}
{
typeof config.social.medium !== 'undefined' && config.social.medium && (
<li>
<span>
<div>
<AiFillMediumSquare className="mr-2"/>
</div>
<div>
<a
href={`https://medium.com/@${config.social.medium}`}
target="_blank"
rel="noreferrer"
className="text-base-content-important"
>
{config.social.medium}
</a>
</div>
</span>
</li>
)
}
{
typeof config.social.devto !== 'undefined' && config.social.devto && (
<li>
<span>
<div>
<FaDev className="mr-2"/>
</div>
<div>
<a
href={`https://dev.to/${config.social.devto}`}
target="_blank"
rel="noreferrer"
className="text-base-content-important"
>
{config.social.devto}
</a>
</div>
</span>
</li>
)
}
{
typeof config.social.website !== 'undefined' && config.social.website && (
<li>
<span>
<div>
<FaGlobe className="mr-2"/>
</div>
<div>
<a
href={`${config.social.website}`}
target="_blank"
rel="noreferrer"
className="text-base-content-important"
>
{config.social.website}
</a>
</div>
</span>
</li>
)
}
{
typeof config.social.phone !== 'undefined' && config.social.phone && (
<li>
<span>
<div>
<RiPhoneFill className="mr-2"/>
</div>
<div>
<a
href={`tel:${config.social.phone}`}
rel="noreferrer"
className="text-base-content-important"
>
{config.social.phone}
</a>
</div>
</span>
</li>
)
}
{
typeof config.social.email !== 'undefined' && config.social.email && (
<li>
<span>
<div>
<MdMail className="mr-2"/>
</div>
<div>
<a
href={`mailto:${config.social.email}`}
target="_blank"
rel="noreferrer"
className="text-base-content-important"
>
{config.social.email}
</a>
</div>
</span>
</li>
)
}
</>
)
}
</ul>
</div>
</div>
)
}
Details.propTypes = {
profile: PropTypes.object
}
export default Details;

View File

@ -1,91 +0,0 @@
import config from "../config";
import { GoPrimitiveDot } from 'react-icons/go';
import { skeleton } from "../helpers/utils";
import { useContext } from "react";
import { LoadingContext } from "../contexts/LoadingContext";
const Education = () => {
const [loading] = useContext(LoadingContext);
const renderSkeleton = () => {
let array = [];
for (let index = 0; index < 2; index++) {
array.push((
<li key={index}>
<span>
{skeleton({ width: 'w-2', height: 'h-2', className: "mr-2" })}
<div className="w-full">
<div className="block justify-between">
<div>
{skeleton({ width: 'w-9/12', height: 'h-4', className: "mb-2" })}
</div>
<div>
{skeleton({ width: 'w-6/12', height: 'h-4', className: "mb-2" })}
</div>
</div>
<div>
{skeleton({ width: 'w-6/12', height: 'h-3' })}
</div>
</div>
</span>
</li>
))
}
return array;
}
return (
<>
{
(typeof config.education !== 'undefined' && config.education.length !== 0) && (
<div className="card shadow-lg compact bg-base-100">
<div className="card-body">
<ul className="menu row-span-3 bg-base-100 text-base-content">
<li>
<div className="pb-0-important mx-3">
<h5 className="card-title">
{
loading ? skeleton({width: 'w-32', height: 'h-8'}) : (
<span className="opacity-70">Education</span>
)
}
</h5>
</div>
</li>
{
loading ? renderSkeleton() : (
config.education.map((item, index) => (
<li key={index}>
<span>
<div>
<GoPrimitiveDot className="mr-2 opacity-40"/>
</div>
<div>
<div className="block justify-between">
<div className="font-medium opacity-70">
{item.institution}
</div>
<div className="opacity-50">
{item.from} - {item.to}
</div>
</div>
<div className="opacity-70">
{item.degree}
</div>
</div>
</span>
</li>
))
)
}
</ul>
</div>
</div>
)
}
</>
)
}
export default Education;

View File

@ -1,27 +0,0 @@
import PropTypes from 'prop-types';
const ErrorPage = (props) => {
return (
<div className="min-w-screen min-h-screen bg-base-200 flex items-center p-5 lg:p-20 overflow-hidden relative">
<div className="flex-1 min-h-full min-w-full rounded-3xl bg-base-100 shadow-xl p-10 lg:p-20 text-gray-800 relative md:flex items-center text-center md:text-left">
<div className="w-full">
<div className="mb-10 md:mb-20 mt-10 md:mt-20 text-gray-600 font-light">
<h1 className="font-black uppercase text-3xl lg:text-5xl text-primary mb-10">{props.status}</h1>
<p className="text-lg pb-2 text-base-content">{props.title}</p>
<p className="text-base-content text-opacity-60">{props.subTitle}</p>
</div>
</div>
</div>
<div className="w-64 md:w-96 h-96 md:h-full bg-accent bg-opacity-10 absolute -top-64 md:-top-96 right-20 md:right-32 rounded-full pointer-events-none -rotate-45 transform"></div>
<div className="w-96 h-full bg-secondary bg-opacity-10 absolute -bottom-96 right-64 rounded-full pointer-events-none -rotate-45 transform"></div>
</div>
)
}
ErrorPage.propTypes = {
status: PropTypes.string.isRequired,
title: PropTypes.string.isRequired,
subTitle: PropTypes.string.isRequired
}
export default ErrorPage;

View File

@ -1,91 +0,0 @@
import config from "../config";
import { GoPrimitiveDot } from 'react-icons/go';
import { skeleton } from "../helpers/utils";
import { useContext } from "react";
import { LoadingContext } from "../contexts/LoadingContext";
const Experience = () => {
const [loading] = useContext(LoadingContext);
const renderSkeleton = () => {
let array = [];
for (let index = 0; index < 2; index++) {
array.push((
<li key={index}>
<span>
{skeleton({ width: 'w-2', height: 'h-2', className: "mr-2" })}
<div className="w-full">
<div className="block justify-between">
<div>
{skeleton({ width: 'w-9/12', height: 'h-4', className: "mb-2" })}
</div>
<div>
{skeleton({ width: 'w-6/12', height: 'h-4', className: "mb-2" })}
</div>
</div>
<div>
{skeleton({ width: 'w-6/12', height: 'h-3' })}
</div>
</div>
</span>
</li>
))
}
return array;
}
return (
<>
{
(typeof config.experiences !== 'undefined' && config.experiences.length !== 0) && (
<div className="card shadow-lg compact bg-base-100">
<div className="card-body">
<ul className="menu row-span-3 bg-base-100 text-base-content">
<li>
<div className="pb-0-important mx-3">
<h5 className="card-title">
{
loading ? skeleton({width: 'w-32', height: 'h-8'}) : (
<span className="opacity-70">Experience</span>
)
}
</h5>
</div>
</li>
{
loading ? renderSkeleton() : (
config.experiences.map((experience, index) => (
<li key={index}>
<span>
<div>
<GoPrimitiveDot className="mr-2 opacity-40"/>
</div>
<div>
<div className="block justify-between">
<div className="font-medium opacity-70">
{experience.company}
</div>
<div className="opacity-50">
{experience.from} - {experience.to}
</div>
</div>
<div className="opacity-70">
{experience.position}
</div>
</div>
</span>
</li>
))
)
}
</ul>
</div>
</div>
)
}
</>
)
}
export default Experience;

View File

@ -1,30 +0,0 @@
import { useState, Fragment, useEffect } from 'react';
const LazyImage = ({ placeholder, src, alt, ...rest }) => {
const [loading, setLoading] = useState(true);
useEffect(() => {
const imageToLoad = new Image();
imageToLoad.src = src;
imageToLoad.onload = () => {
setLoading(false);
}
}, [src])
return (
<Fragment>
{
loading ? placeholder : (
<img
src={src}
alt={alt}
{...rest}
/>
)
}
</Fragment>
)
}
export default LazyImage;

View File

@ -1,66 +0,0 @@
import React, { Fragment, useContext } from 'react';
import { Helmet } from "react-helmet-async";
import config from '../config';
import { isThemeDarkish } from '../helpers/utils';
import PropTypes from 'prop-types';
import { ThemeContext } from '../contexts/ThemeContext';
const MetaTags = (props) => {
const [theme] = useContext(ThemeContext);
return (
<Fragment>
{
props.profile && (
<Helmet>
{
config.googleAnalytics?.id && (
<script async src={`https://www.googletagmanager.com/gtag/js?id=${config.googleAnalytics.id}`}></script>
)
}
{
config.googleAnalytics?.id && (
<script>
{
`
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '${config.googleAnalytics.id}');
`
}
</script>
)
}
<title>Portfolio of {props.profile.name}</title>
<meta name="theme-color" content={isThemeDarkish(theme) ? '#000000' : '#ffffff'}/>
<meta name="description" content={props.profile.bio} />
<meta itemprop="name" content={`Portfolio of ${props.profile.name}`} />
<meta itemprop="description" content={props.profile.bio} />
<meta itemprop="image" content={props.profile.avatar} />
<meta property="og:url" content={typeof config.social.website !== 'undefined' ? config.social.website : ''} />
<meta property="og:type" content="website" />
<meta property="og:title" content={`Portfolio of ${props.profile.name}`} />
<meta property="og:description" content={props.profile.bio} />
<meta property="og:image" content={props.profile.avatar} />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content={`Portfolio of ${props.profile.name}`} />
<meta name="twitter:description" content={props.profile.bio} />
<meta name="twitter:image" content={props.profile.avatar} />
</Helmet>
)
}
</Fragment>
)
}
MetaTags.propTypes = {
profile: PropTypes.object
}
export default MetaTags;

View File

@ -1,162 +0,0 @@
import { Fragment, useContext } from "react";
import { ga, languageColor, skeleton } from "../helpers/utils";
import { AiOutlineStar, AiOutlineFork } from 'react-icons/ai';
import config from "../config";
import PropTypes from 'prop-types';
import { LoadingContext } from "../contexts/LoadingContext";
const Project = (props) => {
const [loading] = useContext(LoadingContext);
const renderSkeleton = () => {
let array = [];
for (let index = 0; index < config.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">
<div>
<div className="flex items-center">
<span>
<h5 className="card-title text-lg">
{skeleton({ width: 'w-32', height: 'h-8' })}
</h5>
</span>
</div>
<div className="mb-5 mt-1">
{skeleton({ width: 'w-full', height: 'h-4', className: 'mb-2' })}
{skeleton({ width: 'w-full', height: 'h-4' })}
</div>
</div>
<div className="flex justify-between">
<div className="flex flex-grow">
<span className="mr-3 flex items-center">
{skeleton({ width: 'w-12', height: 'h-4' })}
</span>
<span className="flex items-center">
{skeleton({ width: 'w-12', height: 'h-4' })}
</span>
</div>
<div>
<span className="flex items-center">
{skeleton({ width: 'w-12', height: 'h-4' })}
</span>
</div>
</div>
</div>
</div>
))
}
return array;
}
const renderProjects = () => {
return props.repo.map((item, index) => (
<div
className="card shadow-lg compact bg-base-100 cursor-pointer"
key={index}
onClick={() => {
try {
if (config.googleAnalytics?.id) {
ga.event({
action: "Click project",
params: {
project: item.name
}
});
}
} catch (error) {
console.error(error);
}
window.open(item.html_url, '_blank')
}}
>
<div className="flex justify-between flex-col p-8 h-full w-full">
<div>
<div className="flex items-center opacity-60">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" className="inline-block w-5 h-5 mr-2 stroke-current"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z"></path></svg>
<span>
<h5 className="card-title text-lg">
{item.name}
</h5>
</span>
</div>
<p className="mb-5 mt-1 text-base-content text-opacity-60 text-sm">
{item.description}
</p>
</div>
<div className="flex justify-between text-sm text-base-content text-opacity-60">
<div className="flex flex-grow">
<span className="mr-3 flex items-center">
<AiOutlineStar className="mr-0.5" />
<span>{item.stargazers_count}</span>
</span>
<span className="flex items-center">
<AiOutlineFork className="mr-0.5" />
<span>{item.forks_count}</span>
</span>
</div>
<div>
<span className="flex items-center">
<div className="w-3 h-3 rounded-full mr-1 opacity-60" style={{ backgroundColor: languageColor(item.language) }} />
<span>{item.language}</span>
</span>
</div>
</div>
</div>
</div>
));
}
return (
<Fragment>
<div className="col-span-1 lg:col-span-2">
<div className="grid grid-cols-2 gap-6">
<div className="col-span-2">
<div className="card compact bg-base-100 shadow-sm">
<div className="card-body">
<ul className="menu row-span-3 bg-base-100 text-base-content">
<li>
<div className="pb-0-important mx-4 flex items-center justify-between">
<h5 className="card-title">
{
loading ? skeleton({ width: 'w-28', height: 'h-8' }) : (
<span className="opacity-70">My Projects</span>
)
}
</h5>
{
loading ? skeleton({ width: 'w-10', height: 'h-5' }) : (
<a
href={`https://github.com/${config.github.username}?tab=repositories`}
target="_blank"
rel="noreferrer"
className="opacity-50"
>
See All
</a>
)
}
</div>
</li>
</ul>
</div>
</div>
</div>
<div className="col-span-2">
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{(loading || !props.repo) ? renderSkeleton() : renderProjects()}
</div>
</div>
</div>
</div>
</Fragment>
)
}
Project.propTypes = {
repo: PropTypes.array
}
export default Project;

View File

@ -1,58 +0,0 @@
import { useContext } from "react";
import config from "../config";
import { LoadingContext } from "../contexts/LoadingContext";
import { skeleton } from "../helpers/utils";
const Skill = () => {
const [loading] = useContext(LoadingContext);
const renderSkeleton = () => {
let array = [];
for (let index = 0; index < 12; index++) {
array.push((
<div key={index}>
{skeleton({ width: 'w-16', height: 'h-4', className: 'm-1' })}
</div>
))
}
return array;
}
return (
<>
{
(typeof config.skills !== 'undefined' && config.skills.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">Tech Stack</span>
)
}
</h5>
</div>
<div className="p-3 flow-root">
<div className="-m-1 flex flex-wrap">
{
loading ? renderSkeleton() : (
config.skills.map((skill, index) => (
<div key={index} className="m-1 text-xs inline-flex items-center font-bold leading-sm uppercase px-3 py-1 badge-primary bg-opacity-75 rounded-full">
{skill}
</div>
))
)
}
</div>
</div>
</div>
</div>
)
}
</>
)
}
export default Skill;

View File

@ -1,78 +0,0 @@
import config from '../config';
import { skeleton } from '../helpers/utils';
import { AiOutlineControl } from 'react-icons/ai';
import { useContext } from 'react';
import { ThemeContext } from '../contexts/ThemeContext';
import { LoadingContext } from '../contexts/LoadingContext';
const ThemeChanger = () => {
const [theme, setTheme] = useContext(ThemeContext);
const [loading] = useContext(LoadingContext);
const changeTheme = (e, selectedTheme) => {
e.preventDefault();
document.querySelector('html').setAttribute('data-theme', selectedTheme);
localStorage.setItem('ezprofile-theme', selectedTheme);
setTheme(selectedTheme);
}
return (
<div className="card overflow-visible shadow-lg compact bg-base-100">
<div className="flex-row items-center space-x-4 flex pl-6 pr-2 py-4">
<div className="flex-1">
<h5 className="card-title">
{
loading ? skeleton({ width: 'w-20', height: 'h-8' }) : (
<span className="opacity-70">Theme</span>
)
}
</h5>
<span className="text-base-content text-opacity-40 capitalize text-sm">
{
loading ? skeleton({ width: 'w-16', height: 'h-5' }) : (theme === config.themeConfig.default ? 'Default' : theme)
}
</span>
</div>
<div className="flex-0">
{
loading ? skeleton({ width: 'w-14 md:w-28', height: 'h-10', className: 'mr-6' }) : (
<div title="Change Theme" className="dropdown dropdown-end">
<div tabIndex={0} className="btn btn-ghost m-1 normal-case opacity-50">
<AiOutlineControl className="inline-block w-5 h-5 stroke-current md:mr-2"/>
<span className="hidden md:inline">
Change Theme
</span>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1792 1792" className="inline-block w-4 h-4 ml-1 fill-current">
<path d="M1395 736q0 13-10 23l-466 466q-10 10-23 10t-23-10l-466-466q-10-10-10-23t10-23l50-50q10-10 23-10t23 10l393 393 393-393q10-10 23-10t23 10l50 50q10 10 10 23z" />
</svg>
</div>
<div tabIndex={0} className="mt-16 overflow-y-auto shadow-2xl top-px dropdown-content h-96 w-52 rounded-b-box bg-base-200 text-base-content">
<ul className="p-4 menu compact">
{
[config.themeConfig.default, ...config.themeConfig.themes.filter(item => item !== config.themeConfig.default)].map((item, index) => (
<li key={index}>
{/* eslint-disable-next-line */}
<a
onClick={(e) => changeTheme(e, item)}
className={`${theme === item ? 'active' : ''}`}
>
<span className="opacity-60 capitalize">
{item === config.themeConfig.default ? 'Default' : item}
</span>
</a>
</li>
))
}
</ul>
</div>
</div>
)
}
</div>
</div>
</div>
)
}
export default ThemeChanger;

View File

@ -1,128 +0,0 @@
// config.js
module.exports = {
github: {
username: 'arifszn', // Your GitHub org/user name. (Required)
sortBy: 'stars', // stars | updated
limit: 8, // How many projects to display.
exclude: {
forks: false, // Forked projects will not be displayed if set to true.
projects: ['laravel-ecommerce'] // These projects will not be displayed. example: ['my-project1', 'my-project2']
}
},
social: {
linkedin: 'ariful-alam',
twitter: 'arif_szn',
facebook: '',
dribbble: '',
behance: '',
medium: '',
devto: 'arifszn',
website: 'https://arifszn.github.io',
phone: '',
email: 'arifulalamszn@gmail.com'
},
skills: [
'PHP',
'Laravel',
'JavaScript',
'React.js',
'Node.js',
'MySQL',
'Git',
'Docker',
'CSS',
'Antd',
'Tailwind',
'Bootstrap',
],
experiences: [
{
company: 'Monstarlab Bangladesh',
position: 'Backend Engineer II',
from: 'September 2021',
to: 'Present'
},
{
company: 'Orangetoolz',
position: 'Jr. Full Stack Engineer',
from: 'July 2019',
to: 'August 2021'
},
{
company: 'Techvillage',
position: 'Jr. Software Engineer',
from: 'January 2019',
to: ' June 2019'
}
],
education: [
{
institution: 'American International University-Bangladesh',
degree: 'Bachelor of Science',
from: '2015',
to: '2019'
},
{
institution: 'Cantonment College, Jessore',
degree: 'Higher Secondary Certificate (HSC)',
from: '2012',
to: '2014',
},
{
institution: 'Chowgacha Shahadat Pilot High School',
degree: 'Secondary School Certificate (SSC)',
from: '2007',
to: '2012'
}
],
blog: {
// Display blog posts from your medium or dev.to account. (Optional)
source: 'dev.to', // medium | dev.to
username: 'arifszn',
limit: 3 // How many posts to display. Max is 10.
},
googleAnalytics: {
// GA3 tracking id/GA4 tag id UA-XXXXXXXXX-X | G-XXXXXXXXXX
id: 'G-WLLB5E14M6' // Please remove this and use your own tag id or keep it empty
},
hotjar: {
id: '2617601', // Please remove this and use your own id or keep it empty
snippetVersion : 6
},
themeConfig: {
default: 'light',
// Hides the switch in the navbar
// Useful if you want to support a single color mode
disableSwitch: false,
// Should we use the prefers-color-scheme media-query,
// using user system preferences, instead of the hardcoded default
respectPrefersColorScheme: true,
// Available themes. To remove any theme, exclude from here.
themes: [
'light',
'dark',
'cupcake',
'bumblebee',
'emerald',
'corporate',
'synthwave',
'retro',
'cyberpunk',
'valentine',
'halloween',
'garden',
'forest',
'aqua',
'lofi',
'pastel',
'fantasy',
'wireframe',
'black',
'luxury',
'dracula'
]
}
}

View File

@ -1,15 +0,0 @@
import { createContext, useState } from "react";
const initialValue = true;
export const LoadingContext = createContext();
export const LoadingProvider = (props) => {
const [loading, setLoading] = useState(initialValue);
return (
<LoadingContext.Provider value={[loading, setLoading]}>
{props.children}
</LoadingContext.Provider>
);
}

View File

@ -1,16 +0,0 @@
import { createContext, useState } from "react";
import { getInitialTheme } from "../helpers/utils";
const initialValue = getInitialTheme();
export const ThemeContext = createContext();
export const ThemeProvider = (props) => {
const [theme, setTheme] = useState(initialValue);
return (
<ThemeContext.Provider value={[theme, setTheme]}>
{props.children}
</ThemeContext.Provider>
);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,79 +0,0 @@
import config from "../config";
import colors from './colors.json';
import { hotjar } from 'react-hotjar';
export const getInitialTheme = () => {
if (config.themeConfig.disableSwitch) {
return config.themeConfig.default;
}
if (localStorage.hasOwnProperty('ezprofile-theme')) {
let theme = localStorage.getItem('ezprofile-theme');
return theme;
}
if (config.themeConfig.respectPrefersColorScheme && !config.themeConfig.disableSwitch) {
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : config.themeConfig.default;
}
return config.themeConfig.default;
}
export const skeleton = ({width = null, height = null, style = {}, shape = 'rounded-full', className = null}) => {
return <div className={`bg-base-300 animate-pulse ${shape}${className ? ` ${className}` : ''}${width ? ` ${width}` : ''}${height ? ` ${height}` : ''}`} style={style}/>;
}
export const languageColor = (language) => {
if (typeof colors[language] !== 'undefined') {
return colors[language].color;
} else {
return 'gray';
}
}
export const fallbackImage = (
"data:image/png;base64,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"
)
export const ga = {
// initialize google analytic
initialize: (id) => {
try {
window.gtag('js', new Date());
window.gtag('config', id);
} catch (error) {
console.error(error);
}
},
// log specific events happening
event: ({ action, params }) => {
try {
window.gtag('event', action, params);
} catch (error) {
console.error(error);
}
}
}
export const isThemeDarkish = (theme) => {
if (
theme === 'dark' ||
theme === 'halloween' ||
theme === 'forest' ||
theme === 'black' ||
theme === 'luxury' ||
theme === 'dracula'
) {
return true;
} else {
return false;
}
}
export const setupHotjar = () => {
if (config.hotjar?.id) {
let snippetVersion = config.hotjar?.snippetVersion ? config.hotjar?.snippetVersion : 6;
hotjar.initialize(config.hotjar.id, snippetVersion);
}
}

View File

@ -1,87 +0,0 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
* {
scrollbar-width: thin;
}
::-webkit-scrollbar-track {
box-shadow: inset 0 0 6px rgba(0,0,0,0.3);
-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3);
-moz-box-shadow: inset 0 0 6px rgba(0,0,0,0.3);
}
@media screen and (min-width: 966px) {
::-webkit-scrollbar, .scroller {
width: 8px;
height: 8px;
background-color: #f1f1f1;
}
}
::-webkit-scrollbar-thumb {
background-color: #888;
border-radius: 10px;
}
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
}
.text-base-content-important {
color: hsla(var(--bc) / var(--tw-text-opacity)) !important;
}
svg {
vertical-align: unset
}
.z-hover {
transition: all ease-in-out 0.3s !important;
}
.z-hover:hover,
.z-hover:focus,
.z-hover:active {
transition: transform 0.3s !important;
-ms-transform: scale(1.01) !important;
-webkit-transform: scale(1.01) !important;
transform: scale(1.01) !important;
}
.pb-0-important {
padding-bottom: 0 !important;
}
.fade-in {
opacity: 1;
animation-name: fadeIn;
animation-iteration-count: 1;
animation-timing-function: ease-in;
animation-duration: 1s;
}
@keyframes fadeIn {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
@-webkit-keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}

View File

@ -1,25 +0,0 @@
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { HelmetProvider } from 'react-helmet-async';
import { ThemeProvider } from './contexts/ThemeContext';
import { LoadingProvider } from './contexts/LoadingContext';
import { setupHotjar } from './helpers/utils';
ReactDOM.render(
<React.StrictMode>
<ThemeProvider>
<LoadingProvider>
<HelmetProvider>
<App/>
</HelmetProvider>
</LoadingProvider>
</ThemeProvider>
</React.StrictMode>,
document.getElementById('root')
);
reportWebVitals();
setupHotjar();

View File

@ -1,13 +0,0 @@
const reportWebVitals = onPerfEntry => {
if (onPerfEntry && onPerfEntry instanceof Function) {
import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
getCLS(onPerfEntry);
getFID(onPerfEntry);
getFCP(onPerfEntry);
getLCP(onPerfEntry);
getTTFB(onPerfEntry);
});
}
};
export default reportWebVitals;

View File

@ -1,5 +0,0 @@
// jest-dom adds custom jest matchers for asserting on DOM nodes.
// allows you to do things like:
// expect(element).toHaveTextContent(/react/i)
// learn more: https://github.com/testing-library/jest-dom
import '@testing-library/jest-dom';

View File

@ -1,16 +0,0 @@
module.exports = {
purge: ['./src/**/*.{js,jsx,ts,tsx}', './public/index.html'],
darkMode: false, // or 'media' or 'class'
theme: {
extend: {},
},
variants: {
extend: {},
},
plugins: [
require('daisyui')
],
daisyui: {
logs: false
},
}