├── .gitignore
├── src
├── data
│ ├── index.js
│ └── icons.js
├── utils
│ ├── index.js
│ ├── Input
│ │ ├── input.css
│ │ └── Input.jsx
│ ├── Button
│ │ ├── button.jsx
│ │ └── button.css
│ ├── pointer.jsx
│ ├── Loading
│ │ ├── Loading.jsx
│ │ └── loading.css
│ ├── functions.js
│ ├── Hover
│ │ ├── Hover.jsx
│ │ └── hover.css
│ ├── Loading2
│ │ ├── Loading.jsx
│ │ └── loading.css
│ ├── Cursor
│ │ ├── cursor.css
│ │ └── cursor.jsx
│ └── Components.jsx
├── assets
│ ├── bg_1.jpg
│ ├── image1.jpg
│ ├── image2.jpg
│ ├── image3.jpg
│ ├── people1.jpg
│ ├── people2.jpg
│ ├── people3.jpg
│ ├── profile.png
│ ├── project1.jpg
│ ├── project2.jpg
│ ├── project3.jpg
│ ├── project4.jpg
│ ├── project5.jpg
│ ├── project6.jpg
│ ├── faveicon1.ico
│ ├── index.js
│ └── quotes.svg
├── constant.js
├── Admin
│ ├── components
│ │ ├── Error.jsx
│ │ ├── Loading.jsx
│ │ ├── index.jsx
│ │ ├── SubHeading.jsx
│ │ ├── Heading.jsx
│ │ ├── Table.jsx
│ │ ├── Textarea.jsx
│ │ ├── Navbar.jsx
│ │ ├── Slider.jsx
│ │ └── DropDown.jsx
│ ├── pages
│ │ ├── index.jsx
│ │ ├── Blogs
│ │ │ ├── Delete.jsx
│ │ │ ├── View.jsx
│ │ │ └── Blogs.jsx
│ │ ├── Skills
│ │ │ ├── Delete.jsx
│ │ │ ├── View.jsx
│ │ │ ├── Skills.jsx
│ │ │ └── Create.jsx
│ │ ├── Freelancing
│ │ │ ├── Delete.jsx
│ │ │ ├── View.jsx
│ │ │ └── Freelancing.jsx
│ │ ├── Resumes
│ │ │ ├── Delete.jsx
│ │ │ ├── View.jsx
│ │ │ └── Resumes.jsx
│ │ ├── Projects
│ │ │ ├── Delete.jsx
│ │ │ └── View.jsx
│ │ ├── Services
│ │ │ ├── Delete.jsx
│ │ │ ├── View.jsx
│ │ │ └── Services.jsx
│ │ ├── Testimonials
│ │ │ ├── Delete.jsx
│ │ │ ├── View.jsx
│ │ │ └── Testimonials.jsx
│ │ └── Contact
│ │ │ ├── View.jsx
│ │ │ └── Contact.jsx
│ └── Admin.jsx
├── User
│ ├── components
│ │ ├── index.jsx
│ │ ├── Button.jsx
│ │ ├── NavigationDots.jsx
│ │ ├── MainHeading.jsx
│ │ ├── SocialLinks.jsx
│ │ ├── Input.jsx
│ │ └── HeaderText.jsx
│ ├── pages
│ │ ├── Projects
│ │ │ ├── pagination.css
│ │ │ ├── Projects.jsx
│ │ │ └── Project.jsx
│ │ ├── Testimonials
│ │ │ ├── testimonial.jsx
│ │ │ ├── swiper.css
│ │ │ └── TestimonialsCard.jsx
│ │ ├── Resume
│ │ │ └── ResumeCard.jsx
│ │ ├── Skills
│ │ │ ├── Skillbar.jsx
│ │ │ └── Skills.jsx
│ │ ├── index.jsx
│ │ ├── Contact
│ │ │ ├── ContactCard.jsx
│ │ │ └── Contact.jsx
│ │ ├── Auth
│ │ │ ├── login.css
│ │ │ ├── login.jsx
│ │ │ └── Register.jsx
│ │ ├── Services
│ │ │ ├── ServiceCard.jsx
│ │ │ ├── Services.jsx
│ │ │ └── service.css
│ │ ├── Account
│ │ │ └── Account.jsx
│ │ ├── Freelancing
│ │ │ └── Confirm.jsx
│ │ ├── Home
│ │ │ └── Home.jsx
│ │ ├── About
│ │ │ └── About.jsx
│ │ └── Blogs
│ │ │ ├── Blogs.jsx
│ │ │ └── BlogCard.jsx
│ └── User.jsx
├── App.jsx
├── index.jsx
├── redux
│ ├── actions
│ │ ├── contact.js
│ │ ├── general.js
│ │ ├── user.js
│ │ ├── blog.js
│ │ ├── freelancing.js
│ │ ├── skill.js
│ │ ├── resume.js
│ │ ├── service.js
│ │ ├── project.js
│ │ └── testimonial.js
│ ├── reducers
│ │ ├── general.js
│ │ ├── contact.js
│ │ ├── user.js
│ │ ├── blog.js
│ │ ├── skill.js
│ │ ├── freelancing.js
│ │ ├── resume.js
│ │ ├── service.js
│ │ ├── project.js
│ │ └── testimonial.js
│ ├── store.js
│ └── api
│ │ └── index.js
├── contexts
│ └── ContextProvider.jsx
└── index.css
├── postcss.config.js
├── vite.config.js
├── index.html
├── tailwind.config.js
├── README.md
└── package.json
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/src/data/index.js:
--------------------------------------------------------------------------------
1 | export { default as icons } from './icons'
--------------------------------------------------------------------------------
/src/utils/index.js:
--------------------------------------------------------------------------------
1 | export { default as Input } from './Input/Input'
--------------------------------------------------------------------------------
/src/assets/bg_1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naumanch969/mern-orange-portfolio-client/HEAD/src/assets/bg_1.jpg
--------------------------------------------------------------------------------
/src/assets/image1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naumanch969/mern-orange-portfolio-client/HEAD/src/assets/image1.jpg
--------------------------------------------------------------------------------
/src/assets/image2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naumanch969/mern-orange-portfolio-client/HEAD/src/assets/image2.jpg
--------------------------------------------------------------------------------
/src/assets/image3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naumanch969/mern-orange-portfolio-client/HEAD/src/assets/image3.jpg
--------------------------------------------------------------------------------
/src/assets/people1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naumanch969/mern-orange-portfolio-client/HEAD/src/assets/people1.jpg
--------------------------------------------------------------------------------
/src/assets/people2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naumanch969/mern-orange-portfolio-client/HEAD/src/assets/people2.jpg
--------------------------------------------------------------------------------
/src/assets/people3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naumanch969/mern-orange-portfolio-client/HEAD/src/assets/people3.jpg
--------------------------------------------------------------------------------
/src/assets/profile.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naumanch969/mern-orange-portfolio-client/HEAD/src/assets/profile.png
--------------------------------------------------------------------------------
/src/assets/project1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naumanch969/mern-orange-portfolio-client/HEAD/src/assets/project1.jpg
--------------------------------------------------------------------------------
/src/assets/project2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naumanch969/mern-orange-portfolio-client/HEAD/src/assets/project2.jpg
--------------------------------------------------------------------------------
/src/assets/project3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naumanch969/mern-orange-portfolio-client/HEAD/src/assets/project3.jpg
--------------------------------------------------------------------------------
/src/assets/project4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naumanch969/mern-orange-portfolio-client/HEAD/src/assets/project4.jpg
--------------------------------------------------------------------------------
/src/assets/project5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naumanch969/mern-orange-portfolio-client/HEAD/src/assets/project5.jpg
--------------------------------------------------------------------------------
/src/assets/project6.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naumanch969/mern-orange-portfolio-client/HEAD/src/assets/project6.jpg
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | };
7 |
--------------------------------------------------------------------------------
/src/assets/faveicon1.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naumanch969/mern-orange-portfolio-client/HEAD/src/assets/faveicon1.ico
--------------------------------------------------------------------------------
/src/utils/Input/input.css:
--------------------------------------------------------------------------------
1 | .inputBox input:focus~label,
2 | textarea:valid~label {
3 | transform: translateX(0px) translateY(-34px);
4 | }
--------------------------------------------------------------------------------
/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite';
2 | import react from '@vitejs/plugin-react';
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react()],
7 | });
8 |
--------------------------------------------------------------------------------
/src/constant.js:
--------------------------------------------------------------------------------
1 | export const baseURL = 'http://localhost:5000'
2 | // export const baseURL = 'https://naumanchportfolio.glitch.me'
3 | // export const baseURL = 'https://mern-orange-portfolio-server.vercel.app'
--------------------------------------------------------------------------------
/src/Admin/components/Error.jsx:
--------------------------------------------------------------------------------
1 |
2 | const Error = ({ error }) => {
3 |
4 |
5 | return (
6 |
9 | )
10 | }
11 |
12 | export default Error;
--------------------------------------------------------------------------------
/src/utils/Button/button.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import './button.css'
3 |
4 | const Button = () => {
5 | return (
6 |
14 | )
15 | }
16 |
17 | export default Button
--------------------------------------------------------------------------------
/src/User/components/index.jsx:
--------------------------------------------------------------------------------
1 | export { default as Navbar } from "./Navbar"
2 | export { default as MainHeading } from "./MainHeading"
3 | export { default as Button } from "./Button"
4 | export { default as HeaderText } from "./HeaderText"
5 | export { default as Input } from "./Input"
6 |
7 | export { default as NavigationDots } from "./NavigationDots"
8 | export { default as SocialLinks } from "./SocialLinks"
--------------------------------------------------------------------------------
/src/User/pages/Projects/pagination.css:
--------------------------------------------------------------------------------
1 | .MuiPagination-ul>li>button {
2 | background-color: #222222;
3 | color: white;
4 | }
5 |
6 | .MuiButtonBase-root.MuiPaginationItem-root.MuiPaginationItem-sizeMedium.MuiPaginationItem-text.MuiPaginationItem-circular.Mui-selected.MuiPaginationItem-page.css-yuzg60-MuiButtonBase-root-MuiPaginationItem-root {
7 | background-color: #feb931;
8 | color: #ffffff;
9 | }
10 |
11 |
--------------------------------------------------------------------------------
/src/Admin/pages/index.jsx:
--------------------------------------------------------------------------------
1 | export { default as Resumes } from "./Resumes/Resumes"
2 | export { default as Services } from "./Services/Services"
3 | export { default as Skills } from "./Skills/Skills"
4 | export { default as Projects } from "./Projects/Projects"
5 | export { default as Blogs } from "./Blogs/Blogs"
6 | export { default as Testimonials } from "./Testimonials/Testimonials"
7 | export { default as Freelancing } from "./Freelancing/Freelancing"
8 | export { default as Contact } from "./Contact/Contact"
--------------------------------------------------------------------------------
/src/Admin/components/Loading.jsx:
--------------------------------------------------------------------------------
1 | import { CircularProgress } from '@mui/material'
2 |
3 | const Loading = ({ title }) => {
4 | return (
5 |
6 |
7 |
{title ? title : 'Fetching Data...'}
8 |
9 | )
10 | }
11 | export default Loading;
--------------------------------------------------------------------------------
/src/App.jsx:
--------------------------------------------------------------------------------
1 | import { useStateContext } from "./contexts/ContextProvider"
2 |
3 | import Admin from "./Admin/Admin"
4 | import User from "./User/User"
5 |
6 | const App = () => {
7 |
8 | const { mode } = useStateContext()
9 |
10 | return (
11 |
12 |
13 |
14 | {
15 | mode == 'admin'
16 | ?
17 |
18 | :
19 |
20 | }
21 |
22 |
23 | );
24 | };
25 |
26 | export default App;
--------------------------------------------------------------------------------
/src/Admin/components/index.jsx:
--------------------------------------------------------------------------------
1 | export { default as Sidebar } from "./Sidebar"
2 | export { default as Navbar } from "./Navbar"
3 | export { default as Heading } from "./Heading"
4 | export { default as SubHeading } from "./SubHeading"
5 | export { default as Textarea } from "./Textarea"
6 | export { default as Loading } from "./Loading"
7 | export { default as Error } from "./Error"
8 | export { default as Slider } from "./Slider"
9 | export { default as DropDown } from "./DropDown"
10 | export { default as Table } from "./Table"
--------------------------------------------------------------------------------
/src/User/pages/Testimonials/testimonial.jsx:
--------------------------------------------------------------------------------
1 | import React, { useRef, useState } from 'react';
2 | import { Swiper, SwiperSlide } from 'swiper/react';
3 | import 'swiper/css';
4 | import 'swiper/css/effect-coverflow';
5 | import 'swiper/css/pagination';
6 | import './testimonial.css';
7 | import { EffectCoverflow } from 'swiper/modules';
8 |
9 | const testimonials = () => {
10 | return (
11 |
12 |
13 |
14 | );
15 | }
16 |
17 |
18 | export default testimonials
--------------------------------------------------------------------------------
/src/User/components/Button.jsx:
--------------------------------------------------------------------------------
1 | import { Link } from 'react-scroll'
2 |
3 | const Button = ({ to, text, color, background, onClick, border, disabled }) => {
4 |
5 | return (
6 |
7 | {text}
8 |
9 | )
10 | }
11 |
12 | export default Button;
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | Nauman Chaudhry
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/assets/index.js:
--------------------------------------------------------------------------------
1 | export { default as bg } from "./bg_1.jpg"
2 | export { default as blog1 } from "./image1.jpg"
3 | export { default as blog2 } from "./image2.jpg"
4 | export { default as blog3 } from "./image3.jpg"
5 | export { default as project1 } from "./project1.jpg"
6 | export { default as project2 } from "./project2.jpg"
7 | export { default as project3 } from "./project3.jpg"
8 | export { default as project4 } from "./project4.jpg"
9 | export { default as project5 } from "./project5.jpg"
10 | export { default as project6 } from "./project6.jpg"
11 | export { default as profile } from "./profile.png"
12 | export { default as quotes } from "./quotes.svg"
--------------------------------------------------------------------------------
/src/Admin/components/SubHeading.jsx:
--------------------------------------------------------------------------------
1 |
2 |
3 | const SubHeading = ({ title }) => {
4 |
5 | ////////////////////////////// VARIABLES //////////////////////////////////////
6 |
7 | ////////////////////////////// STATES /////////////////////////////////////////
8 |
9 | ////////////////////////////// USE EFFECTS ////////////////////////////////////
10 |
11 | ////////////////////////////// FUNCTIONS ///////////////////////////////////////
12 |
13 | return (
14 |
15 |
{title}
16 |
17 | )
18 | }
19 |
20 | export default SubHeading;
--------------------------------------------------------------------------------
/src/assets/quotes.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/index.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom/client';
3 | import './index.css';
4 | import App from './App';
5 | import { BrowserRouter } from "react-router-dom"
6 | import { Provider } from "react-redux"
7 | import { store } from './redux/store'
8 | import { ContextProvider } from "./contexts/ContextProvider"
9 | // import Hover from './utils/Hover/Hover';
10 |
11 |
12 | ReactDOM.createRoot(document.getElementById('root')).render(
13 | {/* react-redux */}
14 | {/* context-api */}
15 | {/* react-router-dom */}
16 |
17 | {/* */}
18 |
19 |
20 |
21 | );
22 |
--------------------------------------------------------------------------------
/src/utils/pointer.jsx:
--------------------------------------------------------------------------------
1 | import { useState, RefObject, useEffect } from "react";
2 |
3 | export function useFollowPointer(ref) {
4 | const [point, setPoint] = useState({ x: 0, y: 0 });
5 | useEffect(() => {
6 | if (!ref.current) return;
7 |
8 | const handlePointerMove = ({ clientX, clientY }) => {
9 | const element = ref.current;
10 | const x = clientX - element.offsetLeft - element.offsetWidth / 2;
11 | const y = clientY - element.offsetTop - element.offsetHeight / 2;
12 | setPoint({ x, y });
13 | };
14 |
15 | window.addEventListener("pointermove", handlePointerMove);
16 |
17 | return () => window.removeEventListener("pointermove", handlePointerMove);
18 | }, []);
19 |
20 | return point;
21 | }
22 |
--------------------------------------------------------------------------------
/src/redux/actions/contact.js:
--------------------------------------------------------------------------------
1 | import * as api from '../api'
2 | import { start, end, error, getContactUsersReducer, formSubmitReducer, } from '../reducers/contact'
3 |
4 | export const getContactUsers = () => async (dispatch) => {
5 | try {
6 | dispatch(start())
7 | const { data } = await api.getContactUsers()
8 | dispatch(getContactUsersReducer(data.result))
9 | dispatch(end())
10 | } catch (err) {
11 | dispatch(error(err.message))
12 | }
13 | }
14 | export const formSubmit = () => async (dispatch) => {
15 | try {
16 | dispatch(start())
17 | const { data } = await api.formSubmit()
18 | dispatch(formSubmitReducer(data.result))
19 | dispatch(end())
20 | } catch (err) {
21 | dispatch(error(err.message))
22 | }
23 | }
--------------------------------------------------------------------------------
/src/redux/actions/general.js:
--------------------------------------------------------------------------------
1 | import * as api from '../api'
2 | import { start, end, error, uploadImageReducer, deleteImageReducer } from '../reducers/general'
3 |
4 | export const uploadImage = (formData) => async (dispatch) => {
5 | try {
6 | dispatch(start())
7 | const { data } = await api.uploadImage(formData)
8 | dispatch(uploadImageReducer(data.result))
9 | dispatch(end())
10 | } catch (err) {
11 | dispatch(error(err.message))
12 | }
13 | }
14 | export const deleteImage = (filename) => async (dispatch) => {
15 | try {
16 | dispatch(start())
17 | const { data } = await api.deleteImage(filename)
18 | dispatch(deleteImageReducer())
19 | dispatch(end())
20 | } catch (err) {
21 | dispatch(error(err.message))
22 | }
23 | }
--------------------------------------------------------------------------------
/src/redux/reducers/general.js:
--------------------------------------------------------------------------------
1 | import { createSlice } from "@reduxjs/toolkit";
2 |
3 | const generalSlice = createSlice({
4 | name: 'general',
5 | initialState: {
6 | isFetching: false,
7 | error: null,
8 | url: null,
9 | },
10 | reducers: {
11 | start: (state) => { state.isFetching = true, state.error = null },
12 | end: (state) => { state.isFetching = false, state.error = null },
13 | error: (state, action) => { state.isFetching = false, state.error = action.payload },
14 | uploadImageReducer: (state, action) => { state.url = action.payload },
15 | deleteImageReducer: (state) => { state.url = null },
16 | }
17 | })
18 |
19 | export const { start, end, error, uploadImageReducer, deleteImageReducer } = generalSlice.actions
20 | export default generalSlice.reducer
--------------------------------------------------------------------------------
/src/redux/reducers/contact.js:
--------------------------------------------------------------------------------
1 | import { createSlice } from "@reduxjs/toolkit";
2 |
3 | const contactSlice = createSlice({
4 | name: 'contact',
5 | initialState: {
6 | isFetching: false,
7 | error: null,
8 | contactUsers: [],
9 | },
10 | reducers: {
11 | start: (state) => { state.isFetching = true, state.error = null },
12 | end: (state) => { state.isFetching = false, state.error = null },
13 | error: (state, action) => { state.isFetching = false, state.error = action.payload },
14 | getContactUsersReducer: (state, action) => { state.contactUsers = action.payload },
15 | formSubmitReducer: (state, action) => { },
16 | }
17 | })
18 |
19 | export const { start, end, error, getContactUsersReducer, formSubmitReducer, } = contactSlice.actions
20 | export default contactSlice.reducer
--------------------------------------------------------------------------------
/src/User/pages/Resume/ResumeCard.jsx:
--------------------------------------------------------------------------------
1 |
2 |
3 | const ResumeCard = ({ title, subTitle, detail, year }) => {
4 |
5 | return (
6 |
7 |
{year}
8 |
{title}
9 |
{detail}
10 |
11 |
{subTitle}
12 |
13 |
14 | )
15 | }
16 |
17 | export default ResumeCard
--------------------------------------------------------------------------------
/src/User/pages/Skills/Skillbar.jsx:
--------------------------------------------------------------------------------
1 |
2 |
3 | const Skillbar = ({ skill }) => {
4 |
5 | return (
6 |
7 |
8 |
{skill.skill}
9 | {skill.percentage}%
10 |
11 |
12 |
13 |
14 |
15 | )
16 | }
17 |
18 | export default Skillbar;
--------------------------------------------------------------------------------
/src/data/icons.js:
--------------------------------------------------------------------------------
1 | import { Web, Palette, Code, Storage, DesktopMac, WebAsset, Phone, Email, LocationOn, Instagram, FacebookOutlined, Twitter, LinkedIn, GitHub } from '@mui/icons-material';
2 |
3 | const icons = [
4 | { icon: Web, name: 'web' },
5 | { icon: Palette, name: 'palette' },
6 | { icon: Code, name: 'code' },
7 | { icon: Storage, name: 'storage' },
8 | { icon: DesktopMac, name: 'desktopMac' },
9 | { icon: WebAsset, name: 'webAsset' },
10 | { icon: Phone, name: 'phone' },
11 | { icon: Email, name: 'email' },
12 | { icon: LocationOn, name: 'locationOn' },
13 | { icon: Instagram, name: 'instagram' },
14 | { icon: FacebookOutlined, name: 'facebook' },
15 | { icon: Twitter, name: 'twitter' },
16 | { icon: LinkedIn, name: 'linkedin' },
17 | { icon: GitHub, name: 'github' },
18 | ]
19 | export default icons;
--------------------------------------------------------------------------------
/src/User/pages/index.jsx:
--------------------------------------------------------------------------------
1 | // client pages
2 | export { default as Home } from "./Home/Home"
3 | export { default as About } from "./About/About"
4 | export { default as Resume } from "./Resume/Resume"
5 | export { default as Services } from "./Services/Services"
6 | export { default as Skills } from "./Skills/Skills"
7 | export { default as Projects } from "./Projects/Projects"
8 | export { default as Blogs } from "./Blogs/Blogs"
9 | export { default as Freelancing } from "./Freelancing/Freelancing"
10 | export { default as Testimonials } from "./Testimonials/Testimonials"
11 | export { default as Contact } from "./Contact/Contact"
12 | export { default as Footer } from "./Footer/Footer"
13 | // export { default as Login} from "./Auth/Login"
14 | export { default as Login} from "./Auth/Login"
15 | export { default as Register} from "./Auth/Register"
16 | export { default as Account } from "./Account/Account"
--------------------------------------------------------------------------------
/src/User/pages/Contact/ContactCard.jsx:
--------------------------------------------------------------------------------
1 | import { icons } from '../../../data'
2 |
3 | const ContactCard = ({ card }) => (
4 |
5 |
6 | {icons.map((icon, index) => (
7 | icon.name.toLowerCase() == card.icon.toLowerCase()
8 | &&
9 |
10 | ))}
11 |
12 |
{card.title}
13 |
{card.detail}
14 |
15 | )
16 |
17 |
18 | export default ContactCard;
--------------------------------------------------------------------------------
/src/User/pages/Auth/login.css:
--------------------------------------------------------------------------------
1 |
2 |
3 | /* main login_wrapper */
4 | .login_wrapper::before {
5 | content: '';
6 | position: absolute;
7 | top: -50%;
8 | left: -50%;
9 | width: 380px;
10 | height: 420px;
11 | background: linear-gradient(0deg, transparent, #feb931, #feb931);
12 | transform-origin: bottom right;
13 | animation: animate 6s linear infinite;
14 | }
15 |
16 | .login_wrapper::after {
17 | content: '';
18 | position: absolute;
19 | top: -50%;
20 | left: -50%;
21 | width: 380px;
22 | height: 420px;
23 | background: linear-gradient(0deg, transparent, #feb931, #feb931);
24 | transform-origin: bottom right;
25 | animation: animate 6s linear infinite;
26 | animation-delay: -3s;
27 | }
28 |
29 | @keyframes animate {
30 | 0% {
31 | transform: rotate(0deg);
32 | }
33 |
34 | 100% {
35 | transform: rotate(360deg);
36 | }
37 | }
38 |
39 |
40 |
--------------------------------------------------------------------------------
/src/utils/Loading/Loading.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import './loading.css'
3 | const Loading = () => {
4 | return (
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
Loading...
21 |
22 | )
23 | }
24 |
25 | export default Loading
--------------------------------------------------------------------------------
/src/contexts/ContextProvider.jsx:
--------------------------------------------------------------------------------
1 | import { createContext, useContext, useState } from "react"
2 |
3 | const StateContext = createContext();
4 |
5 | export const ContextProvider = ({ children }) => {
6 |
7 |
8 | const [mode, setMode] = useState(localStorage.getItem('mode') || 'user')
9 | const [showSidebar, setShowSidebar] = useState(true)
10 | const [activeNavLink, setActiveNavLink] = useState('overview')
11 | const [windowSize, setWindowSize] = useState({ width: window.innerWidth, height: window.innerHeight })
12 |
13 | return (
14 |
24 | {children}
25 |
26 | )
27 | }
28 |
29 |
30 |
31 | export const useStateContext = () => useContext(StateContext)
--------------------------------------------------------------------------------
/src/redux/store.js:
--------------------------------------------------------------------------------
1 | import { combineReducers, configureStore } from '@reduxjs/toolkit'
2 |
3 | import generalReducer from './reducers/general'
4 | import blogReducer from './reducers/blog'
5 | import contactReducer from './reducers/contact'
6 | import freelancingReducer from './reducers/freelancing'
7 | import projectReducer from './reducers/project'
8 | import resumeReducer from './reducers/resume'
9 | import serviceReducer from './reducers/service'
10 | import skillReducer from './reducers/skill'
11 | import testimonialReducer from './reducers/testimonial'
12 | import userReducer from './reducers/user'
13 |
14 | const rootReducer = combineReducers({
15 | general: generalReducer,
16 | blog: blogReducer,
17 | contact: contactReducer,
18 | freelancing: freelancingReducer,
19 | project: projectReducer,
20 | resume: resumeReducer,
21 | service: serviceReducer,
22 | skill: skillReducer,
23 | testimonial: testimonialReducer,
24 | user: userReducer,
25 | })
26 |
27 | export const store = configureStore({
28 | reducer: rootReducer
29 | })
--------------------------------------------------------------------------------
/src/utils/functions.js:
--------------------------------------------------------------------------------
1 |
2 | // 1)
3 | export const limitText = (str, limit) => {
4 | if (str) {
5 | if (str.split("").length > limit) {
6 | const strArr = str.slice(0, limit).trim().split(" ")
7 | const string = strArr.slice(0, strArr.length).join(" ") // strArr.length - 1
8 | return string
9 | }
10 | else {
11 | return str
12 | }
13 | }
14 | }
15 |
16 |
17 | // 2)
18 | export const Capitalize = (str) => {
19 | return str && str.charAt(0).toUpperCase() + str.slice(1);
20 | }
21 |
22 |
23 | // 3)
24 | export const LightenDarkenColor = (col, amt) => {
25 | var num = parseInt(col, 16);
26 | var r = (num >> 16) + amt;
27 | var b = ((num >> 8) & 0x00FF) + amt;
28 | var g = (num & 0x0000FF) + amt;
29 | var newColor = g | (b << 8) | (r << 16);
30 | return newColor.toString(16);
31 | }
32 |
33 | // 4)
34 | export const generateRandom = (from, to) => {
35 | let random = Math.floor(Math.random() * to) + from // random from 1 to 10
36 | return random
37 | }
--------------------------------------------------------------------------------
/src/utils/Hover/Hover.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | const Hover = () => {
4 |
5 | let text = document.querySelectorAll('ul li a').forEach(text => {
6 | text.innerHTML = text.innerText
7 | .split('')
8 | .map((letters, index) =>
9 | `${letters} `
10 | ).join('')
11 | })
12 |
13 | let cursor = document.querySelector('#cursor')
14 | document.addEventListener('mousemove', (e) => {
15 | if (cursor) {
16 | cursor.style.top = e.pageY + 'px'
17 | cursor.style.left = e.pageX + 'px'
18 | }
19 | })
20 |
21 |
22 |
23 |
24 | return (
25 | <>
26 |
27 |
35 | >
36 | )
37 | }
38 |
39 | export default Hover
--------------------------------------------------------------------------------
/src/redux/reducers/user.js:
--------------------------------------------------------------------------------
1 | import { createSlice } from "@reduxjs/toolkit";
2 |
3 | const userSlice = createSlice({
4 | name: 'user',
5 | initialState: {
6 | isFetching: false,
7 | error: null,
8 | users: [],
9 | currentUser: null,
10 | loggedUser: null
11 | },
12 | reducers: {
13 | start: (state) => { state.isFetching = true, state.error = null },
14 | end: (state) => { state.isFetching = false, state.error = null },
15 | error: (state, action) => { state.isFetching = false, state.error = action.payload },
16 | registerReducer: (state, action) => { state.users = [...state.users, action.payload] },
17 | loginReducer: (state, action) => { state.loggedUser = action.payload },
18 | logoutReducer: (state, action) => { state.loggedUser = null },
19 | getUsersReducer: (state, action) => { state.users = action.payload },
20 | }
21 | })
22 |
23 | export const { start, end, error, registerReducer, loginReducer, logoutReducer, getUsersReducer, } = userSlice.actions
24 | export default userSlice.reducer
--------------------------------------------------------------------------------
/src/utils/Loading2/Loading.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import './loading.css'
3 |
4 | const Loading = () => {
5 | return (
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | )
27 | }
28 |
29 | export default Loading
--------------------------------------------------------------------------------
/src/User/pages/Services/ServiceCard.jsx:
--------------------------------------------------------------------------------
1 | import React from "react"
2 | import { Brush, Code, Search } from "@mui/icons-material"
3 | import { icons } from "../../../data"
4 |
5 |
6 | const service = ({ service }) => {
7 |
8 |
9 | return (
10 |
11 |
12 |
13 | {icons.map((icon, index) => (
14 | icon.name.toLowerCase() == service.icon.toLowerCase()
15 | &&
16 |
17 | ))}
18 |
19 |
20 |
{service.service}
21 | {/*
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Unde, illo.
*/}
22 | {/*
Read More */}
23 |
24 |
25 |
26 |
27 | )
28 | }
29 |
30 | export default service
--------------------------------------------------------------------------------
/src/User/components/NavigationDots.jsx:
--------------------------------------------------------------------------------
1 | import { Link } from 'react-scroll'
2 |
3 |
4 | const NavigationDots = () => {
5 | return (
6 | <>
7 | {
8 | links.map((item, index) => (
9 |
20 | {item.title}
21 |
22 | ))
23 | }
24 | >
25 | )
26 | }
27 |
28 | export default NavigationDots
29 |
30 | const links = [
31 | 'home',
32 | 'about',
33 | 'resume',
34 | 'services',
35 | 'skills',
36 | 'projects',
37 | 'blog',
38 | 'testimonials',
39 | 'contact'
40 | ]
--------------------------------------------------------------------------------
/src/User/pages/Testimonials/swiper.css:
--------------------------------------------------------------------------------
1 | /* Swiper bullets */
2 |
3 | .swiper-pagination-bullets {
4 | position: sticky !important;
5 | bottom: -.4rem !important;
6 | display: flex;
7 | justify-content: center;
8 | align-items: center;
9 | height: 3rem;
10 | gap: 6px;
11 | }
12 |
13 |
14 | .swiper-pagination-bullet {
15 | width: 32px !important;
16 | height: 32px !important;
17 | display: flex;
18 | justify-content: center;
19 | align-items: center;
20 | background: black;
21 | color: var(--orange);
22 | font-size: 1.4rem;
23 | font-weight: 600;
24 | border: 2px outset var(--orange);
25 | }
26 |
27 | .swiper-pagination-bullet-active {
28 | display: flex;
29 | justify-content: center;
30 | align-items: center;
31 | background: var(--orange) !important;
32 | color: black;
33 | font-size: 1.4rem;
34 | font-weight: 600;
35 | border: 2px outset black;
36 | }
37 |
38 | .swiper-pagination-bullet:hover {
39 | width: 32px !important;
40 | height: 32px !important;
41 | background: var(--orange);
42 | border: 2px outset black;
43 | color: black;
44 | }
--------------------------------------------------------------------------------
/src/redux/reducers/blog.js:
--------------------------------------------------------------------------------
1 | import { createSlice } from "@reduxjs/toolkit";
2 |
3 | const blogSlice = createSlice({
4 | name: 'blog',
5 | initialState: {
6 | isFetching: false,
7 | error: null,
8 | blogs: [],
9 | currentBlog: null
10 | },
11 | reducers: {
12 | start: (state) => { state.isFetching = true, state.error = null },
13 | end: (state) => { state.isFetching = false, state.error = null },
14 | error: (state, action) => { state.isFetching = false, state.error = action.payload },
15 | getBlogsReducer: (state, action) => { state.blogs = action.payload },
16 | createBlogReducer: (state, action) => { state.blogs = [action.payload, ...state.blogs] },
17 | updateBlogReducer: (state, action) => { state.blogs = state.blogs.map(b => b = b._id == action.payload._id ? action.payload : b) },
18 | deleteBlogReducer: (state, action) => { state.blogs = state.blogs.filter(b=>b._id != action.payload._id ) },
19 | }
20 | })
21 |
22 | export const { start, end, error, getBlogsReducer, createBlogReducer, updateBlogReducer, deleteBlogReducer, } = blogSlice.actions
23 | export default blogSlice.reducer
--------------------------------------------------------------------------------
/src/redux/reducers/skill.js:
--------------------------------------------------------------------------------
1 | import { createSlice } from "@reduxjs/toolkit";
2 |
3 | const skillSlice = createSlice({
4 | name: 'skill',
5 | initialState: {
6 | isFetching: false,
7 | error: null,
8 | skills: [],
9 | currentSkill: null
10 | },
11 | reducers: {
12 | start: (state) => { state.isFetching = true, state.error = null },
13 | end: (state) => { state.isFetching = false, state.error = null },
14 | error: (state, action) => { state.isFetching = false, state.error = action.payload },
15 | getSkillsReducer: (state, action) => { state.skills = action.payload },
16 | createSkillReducer: (state, action) => { state.skills = [action.payload, ...state.skills] },
17 | updateSkillReducer: (state, action) => { state.skills = state.skills.map(s => s = s._id == action.payload._id ? action.payload : s) },
18 | deleteSkillReducer: (state, action) => { state.skills = state.skills.filter(s => s._id != action.payload._id) },
19 | }
20 | })
21 |
22 | export const { start, end, error, getSkillsReducer, createSkillReducer, updateSkillReducer, deleteSkillReducer, } = skillSlice.actions
23 | export default skillSlice.reducer
--------------------------------------------------------------------------------
/tailwind.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('tailwindcss').Config} */
2 | module.exports = {
3 | content: ['./index.html', './src/**/*.{vue,js,ts,jsx,tsx}'],
4 | theme: {
5 | extend: {
6 | colors: {
7 | 'orange': '#feb931',
8 | 'gray': '#9f9e9d',
9 | 'white': '#fff',
10 | 'linkBlue': '#71a5ea',
11 | 'textGray': '#797979',
12 | 'darkGray': '#1a1a1a',
13 | 'lightGray': '#222222',
14 | 'red': '#ff0000',
15 | },
16 | backgroundColor: {
17 | 'gray-background': '#191919',
18 | 'black': '#000',
19 | },
20 | backgroundImage: {
21 | 'parallax-image': "url('/assets/bg_1.png')",
22 | },
23 | animation: {
24 | slideup: 'slideup 1s ease-in-out',
25 | },
26 | keyframes: {
27 | slideup: {
28 | from: { opacity: 0, transform: 'translateY(25%)' },
29 | to: { opacity: 1, transform: 'none' },
30 | },
31 | wave: {
32 | '0%': { transform: 'scale(0)' },
33 | '50%': { transform: 'scale(1)' },
34 | '100%': { transform: 'scale(0)' },
35 | },
36 | },
37 | },
38 | },
39 | variants: {},
40 | plugins: [],
41 | };
--------------------------------------------------------------------------------
/src/redux/reducers/freelancing.js:
--------------------------------------------------------------------------------
1 | import { createSlice } from "@reduxjs/toolkit";
2 |
3 | const freelancingSlice = createSlice({
4 | name: 'freelancing',
5 | initialState: {
6 | isFetching: false,
7 | error: null,
8 | cards: [],
9 | currentFreelancing: null
10 | },
11 | reducers: {
12 | start: (state) => { state.isFetching = true, state.error = null },
13 | end: (state) => { state.isFetching = false, state.error = null },
14 | error: (state, action) => { state.isFetching = false, state.error = action.payload },
15 | getCardsReducer: (state, action) => { state.cards = action.payload },
16 | createCardReducer: (state, action) => { state.cards = [action.payload, ...state.cards] },
17 | updateCardReducer: (state, action) => { state.cards = state.cards.map(c => c = c._id == action.payload._id ? action.payload : c) },
18 | deleteCardReducer: (state, action) => { state.cards = state.cards.filter(c => c._id != action.payload._id) },
19 | }
20 | })
21 |
22 | export const { start, end, error, getCardsReducer, createCardReducer, updateCardReducer, deleteCardReducer, } = freelancingSlice.actions
23 | export default freelancingSlice.reducer
--------------------------------------------------------------------------------
/src/redux/reducers/resume.js:
--------------------------------------------------------------------------------
1 | import { createSlice } from "@reduxjs/toolkit";
2 |
3 | const resumeSlice = createSlice({
4 | name: 'resume',
5 | initialState: {
6 | isFetching: false,
7 | error: null,
8 | resumes: [],
9 | currentResume: null
10 | },
11 | reducers: {
12 | start: (state) => { state.isFetching = true, state.error = null },
13 | end: (state) => { state.isFetching = false, state.error = null },
14 | error: (state, action) => { state.isFetching = false, state.error = action.payload },
15 | getResumesReducer: (state, action) => { state.resumes = action.payload },
16 | createResumeReducer: (state, action) => { state.resumes = [action.payload, ...state.resumes] },
17 | updateResumeReducer: (state, action) => { state.resumes = state.resumes.map(r => r = r._id == action.payload._id ? action.payload : r) },
18 | deleteResumeReducer: (state, action) => { state.resumes = state.resumes.filter(r => r._id != action.payload._id) },
19 | }
20 | })
21 |
22 | export const { start, end, error, getResumesReducer, createResumeReducer, updateResumeReducer, deleteResumeReducer, } = resumeSlice.actions
23 | export default resumeSlice.reducer
--------------------------------------------------------------------------------
/src/redux/reducers/service.js:
--------------------------------------------------------------------------------
1 | import { createSlice } from "@reduxjs/toolkit";
2 |
3 | const serviceSlice = createSlice({
4 | name: 'service',
5 | initialState: {
6 | isFetching: false,
7 | error: null,
8 | services: [],
9 | currentService: null
10 | },
11 | reducers: {
12 | start: (state) => { state.isFetching = true, state.error = null },
13 | end: (state) => { state.isFetching = false, state.error = null },
14 | error: (state, action) => { state.isFetching = false, state.error = action.payload },
15 | getServicesReducer: (state, action) => { state.services = action.payload },
16 | createServiceReducer: (state, action) => { state.services = [action.payload, ...state.services] },
17 | updateServiceReducer: (state, action) => { state.services = state.services.map(s => s = s._id == action.payload._id ? action.payload : s) },
18 | deleteServiceReducer: (state, action) => { state.services = state.services.filter(s => s._id != action.payload._id) },
19 | }
20 | })
21 |
22 | export const { start, end, error, getServicesReducer, createServiceReducer, updateServiceReducer, deleteServiceReducer, } = serviceSlice.actions
23 | export default serviceSlice.reducer
--------------------------------------------------------------------------------
/src/User/pages/Testimonials/TestimonialsCard.jsx:
--------------------------------------------------------------------------------
1 | import { FormatQuote } from "@mui/icons-material"
2 |
3 | const TestimonialsCard = ({ content, name, designation, image }) => {
4 | return (
5 |
6 |
7 |
8 |
9 |
10 | {content}
11 |
12 |
13 |
14 |
15 |
16 |
{name}
17 |
{designation}
18 |
19 |
20 |
21 | )
22 | }
23 |
24 | export default TestimonialsCard
25 |
--------------------------------------------------------------------------------
/src/redux/reducers/project.js:
--------------------------------------------------------------------------------
1 | import { createSlice } from "@reduxjs/toolkit";
2 |
3 | const projectSlice = createSlice({
4 | name: 'project',
5 | initialState: {
6 | isFetching: false,
7 | error: null,
8 | projects: [],
9 | currentProject: null
10 | },
11 | reducers: {
12 | start: (state) => { state.isFetching = true, state.error = null },
13 | end: (state) => { state.isFetching = false, state.error = null },
14 | error: (state, action) => { state.isFetching = false, state.error = action.payload },
15 | getProjectsReducer: (state, action) => { state.projects = action.payload },
16 | createProjectReducer: (state, action) => { state.projects = [action.payload, ...state.projects] },
17 | updateProjectReducer: (state, action) => { state.projects = state.projects.map(p => p = p._id == action.payload._id ? action.payload : p) },
18 | deleteProjectReducer: (state, action) => { state.projects = state.projects.filter(p => p._id != action.payload._id) },
19 | }
20 | })
21 |
22 | export const { start, end, error, getProjectsReducer, createProjectReducer, uploadProjectImageReducer, updateProjectReducer, deleteProjectReducer, } = projectSlice.actions
23 | export default projectSlice.reducer
--------------------------------------------------------------------------------
/src/redux/reducers/testimonial.js:
--------------------------------------------------------------------------------
1 | import { createSlice } from "@reduxjs/toolkit";
2 |
3 | const testimonialSlice = createSlice({
4 | name: 'testimonial',
5 | initialState: {
6 | isFetching: false,
7 | error: null,
8 | testimonials: [],
9 | currentTestimonial: null
10 | },
11 | reducers: {
12 | start: (state) => { state.isFetching = true, state.error = null },
13 | end: (state) => { state.isFetching = false, state.error = null },
14 | error: (state, action) => { state.isFetching = false, state.error = action.payload },
15 | getTestimonialsReducer: (state, action) => { state.testimonials = action.payload },
16 | createTestimonialReducer: (state, action) => { state.testimonials = [action.payload, ...state.testimonials] },
17 | updateTestimonialReducer: (state, action) => { state.testimonials = state.testimonials.map(t => t = t._id == action.payload._id ? action.payload : t) },
18 | deleteTestimonialReducer: (state, action) => { state.testimonials = state.testimonials.filter(t => t._id != action.payload._id) },
19 | }
20 | })
21 |
22 | export const { start, end, error, getTestimonialsReducer, createTestimonialReducer, updateTestimonialReducer, deleteTestimonialReducer, } = testimonialSlice.actions
23 | export default testimonialSlice.reducer
--------------------------------------------------------------------------------
/src/Admin/components/Heading.jsx:
--------------------------------------------------------------------------------
1 | import { Add, MoreVert } from '@mui/icons-material'
2 | import { useState } from 'react'
3 |
4 | const Heading = ({ title, setOpen }) => {
5 |
6 | ////////////////////////////// VARIABLES //////////////////////////////////////
7 |
8 | ////////////////////////////// STATES /////////////////////////////////////////
9 | const [showMenu, setShowMenu] = useState(false)
10 | ////////////////////////////// USE EFFECTS ////////////////////////////////////
11 |
12 | ////////////////////////////// FUNCTIONS ///////////////////////////////////////
13 |
14 |
15 |
16 | return (
17 |
18 |
19 |
{title}
20 |
21 |
22 | {
23 | setOpen
24 | ?
25 |
26 |
setOpen(true)} className="w-[40px] h-[40px] bg-orange text-white rounded-full shadow-xl " >
27 |
28 | :
29 | ''
30 | }
31 |
32 | )
33 | }
34 |
35 | export default Heading;
--------------------------------------------------------------------------------
/src/utils/Hover/hover.css:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | box-sizing: border-box;
5 | }
6 |
7 | /* body {
8 | display: flex;
9 | justify-content: center;
10 | align-items: center;
11 | min-height: 100vh;
12 | background: #222;
13 | cursor: none;
14 | } */
15 |
16 | ul {
17 | position: relative;
18 | display: flex;
19 | justify-content: center;
20 | align-items: center;
21 | flex-direction: column;
22 | }
23 |
24 | ul li {
25 | position: relative;
26 | padding: 10px 0;
27 | text-align: center;
28 | list-style: none;
29 | }
30 |
31 | ul li a {
32 | text-decoration: none;
33 | color: #555;
34 | cursor: none;
35 | }
36 |
37 | ul li a span {
38 | position: relative;
39 | font-size: 2.5em;
40 | letter-spacing: 0.05em;
41 | transition: 0.25s;
42 | text-transform: uppercase;
43 | }
44 |
45 | ul li:hover a span {
46 | color: #fff;
47 | text-shadow: 0 0 5px #fff,
48 | 0 0 15px #fff,
49 | 0 0 30px #fff,
50 | 0 0 60px #fff,
51 | 0 0 100px #fff;
52 | }
53 |
54 | #cursor {
55 | position: fixed;
56 | width: 20px;
57 | height: 20px;
58 | border-radius: 50%;
59 | background: #fff;
60 | box-shadow: 0 0 5px #fff,
61 | 0 0 15px #fff,
62 | 0 0 30px #fff,
63 | 0 0 60px #fff;
64 | transform: translate(-50%, -50%);
65 | pointer-events: none;
66 | opacity: 0;
67 | }
68 |
69 | /* body:hover #cursor {
70 | opacity: 1;
71 | } */
--------------------------------------------------------------------------------
/src/utils/Cursor/cursor.css:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | box-sizing: border-box;
5 | }
6 |
7 |
8 |
9 | /* body {
10 | min-height: 100vh;
11 | overflow: hidden;
12 | background: #222;
13 | background-image:
14 | linear-gradient(to right, #333 1px, transparent 1px),
15 | linear-gradient(to bottom, #333 1px, transparent 1px);
16 | background-size: 40px 40px;
17 | cursor: none;
18 | } */
19 |
20 | #cursor {
21 | position: fixed;
22 | width: 25px;
23 | height: 25px;
24 | border-top: 5px solid #0f0;
25 | border-left: 5px solid #0f0;
26 | transform-origin: top;
27 | transform: translate(-1px, 5px) rotate(15deg);
28 | transition: transform 0.5s;
29 | pointer-events: none;
30 | filter: drop-shadow(0 0 5px #0f0) drop-shadow(0 0 15px #0f0) drop-shadow(0 0 35px #0f0) hue-rotate(60deg);
31 | }
32 |
33 | #cursor::before {
34 | content: '';
35 | position: absolute;
36 | left: -2.5px;
37 | width: 5px;
38 | height: 40px;
39 | background: #0f0;
40 | transform-origin: top;
41 | transform: rotate(315deg);
42 |
43 | }
44 |
45 | body:hover #cursor {
46 | transform: translate(-1px, 5px) rotate(15deg) scale(1);
47 | }
48 |
49 |
50 | .element {
51 | position: absolute;
52 | transform: translate(-50%, -50%);
53 | color: #0f0;
54 | pointer-events: none;
55 | width: 10px;
56 | height: 10px;
57 | font-size: 2em;
58 | transition: 1s;
59 | filter: drop-shadow(0 0 5px #0f0) drop-shadow(0 0 25px #0f0) hue-rotate(60deg);
60 | }
--------------------------------------------------------------------------------
/src/User/pages/Account/Account.jsx:
--------------------------------------------------------------------------------
1 | import { CircularProgress } from '@mui/material'
2 | import { useDispatch, useSelector } from 'react-redux'
3 | import { useNavigate } from 'react-router-dom'
4 | import { Button } from "../../components"
5 | import { logout } from '../../../redux/actions/user'
6 |
7 |
8 | const Account = () => {
9 | const { loggedUser, isFetching, error } = useSelector(state => state.user)
10 |
11 | //////////////////////////////////////////////////// Variables ///////////////////////////////////////////////////////
12 | const navigate = useNavigate()
13 | const dispatch = useDispatch()
14 |
15 | //////////////////////////////////////////////////// States ///////////////////////////////////////////////////////
16 |
17 | //////////////////////////////////////////////////// useEffect ///////////////////////////////////////////////////////
18 |
19 | //////////////////////////////////////////////////// Functions ///////////////////////////////////////////////////////
20 | const logoutFunc = () => {
21 | dispatch(logout(navigate))
22 | }
23 |
24 | return (
25 | <>
26 | {
27 | isFetching
28 | ?
29 |
30 | :
31 |
32 | }
33 | >
34 | )
35 | }
36 |
37 | export default Account
38 |
39 |
40 |
--------------------------------------------------------------------------------
/src/redux/actions/user.js:
--------------------------------------------------------------------------------
1 | import Cookies from 'js-cookie'
2 | import * as api from '../api'
3 | import { start, end, error, registerReducer, loginReducer, logoutReducer, getUsersReducer, } from '../reducers/user'
4 |
5 |
6 | export const register = (userData, navigate) => async (dispatch) => {
7 | try {
8 | dispatch(start())
9 | const { data } = await api.register(userData)
10 | dispatch(registerReducer(data.result))
11 | navigate('/auth/login')
12 | dispatch(end())
13 | }
14 | catch (err) {
15 | dispatch(error(err.message))
16 | }
17 | }
18 | export const login = (userData, navigate) => async (dispatch) => {
19 | try {
20 | dispatch(start())
21 | const { data } = await api.login(userData)
22 | dispatch(loginReducer(data.result))
23 | navigate('/')
24 | dispatch(end())
25 | }
26 | catch (err) {
27 | dispatch(error(err.message))
28 | }
29 | }
30 | export const logout = () => async (dispatch) => {
31 | try {
32 | dispatch(start())
33 | dispatch(logoutReducer())
34 | Cookies.remove('iamnauman_profile')
35 | dispatch(end())
36 | }
37 | catch (err) {
38 | dispatch(error(err.message))
39 | }
40 | }
41 | export const getUsers = () => async (dispatch) => {
42 | try {
43 | dispatch(start())
44 | const { data } = await api.getUsers()
45 | dispatch(getUsersReducer(data.result))
46 | dispatch(end())
47 | }
48 | catch (err) {
49 | dispatch(error(err.message))
50 | }
51 | }
--------------------------------------------------------------------------------
/src/User/components/MainHeading.jsx:
--------------------------------------------------------------------------------
1 |
2 |
3 | const MainHeading = ({ forwardHeading, backHeading, detail, alignStart, small }) => {
4 |
5 | return (
6 |
7 | {/* backHeading */}
8 |
{backHeading}
9 | {/* forwardHeading */}
10 |
{forwardHeading}
11 | {/* text */}
12 |
13 | {alignStart
14 | ?
15 |
16 | {detail?.split(' ').map((detail, index) => (
17 | {detail}
18 | ))}
19 |
20 | :
21 | detail
22 | }
23 |
24 |
25 | )
26 | }
27 |
28 | export default MainHeading;
--------------------------------------------------------------------------------
/src/utils/Button/button.css:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | box-sizing: border-box;
5 | }
6 |
7 | :root {
8 | --clr: #1e9bff;
9 | }
10 |
11 | a {
12 | position: relative;
13 | background: #fff;
14 | color: #fff;
15 | text-decoration: none;
16 | text-transform: uppercase;
17 | font-size: 1.5em;
18 | letter-spacing: 0.1em;
19 | font-weight: 400;
20 | padding: 12px 25px;
21 | transition: 0.5s;
22 | }
23 |
24 | a:hover {
25 | background: var(--clr);
26 | color: var(--clr);
27 | box-shadow: 0 0 25px var(--clr);
28 | letter-spacing: 0.25em;
29 | }
30 |
31 | a::before {
32 | content: '';
33 | position: absolute;
34 | inset: 2px;
35 | background: #27282c;
36 | }
37 |
38 | a span {
39 | position: relative;
40 | z-index: 1;
41 | }
42 |
43 | a i {
44 | position: absolute;
45 | inset: 0;
46 | display: block;
47 | }
48 |
49 | a i::before {
50 | content: '';
51 | position: absolute;
52 | top: 0;
53 | left: 80%;
54 | width: 10px;
55 | height: 4px;
56 | background: #27282c;
57 | transform: translateX(-50%) skewX(325deg);
58 | transition: 0.5s;
59 | }
60 |
61 | a:hover i::before {
62 | width: 20px;
63 | left: 20%;
64 | }
65 |
66 | a i::after {
67 | content: '';
68 | position: absolute;
69 | bottom: 0;
70 | left: 20%;
71 | width: 10px;
72 | height: 4px;
73 | background: #27282c;
74 | transform: translateX(-50%) skewX(325deg);
75 | transition: 0.5s;
76 | }
77 |
78 | a:hover i::after {
79 | width: 20px;
80 | left: 80%;
81 | }
--------------------------------------------------------------------------------
/src/redux/actions/blog.js:
--------------------------------------------------------------------------------
1 | import * as api from '../api'
2 | import { start, end, error, getBlogsReducer, createBlogReducer, updateBlogReducer, deleteBlogReducer, } from '../reducers/blog'
3 |
4 |
5 | export const getBlogs = () => async (dispatch) => {
6 | try {
7 | dispatch(start())
8 | const { data } = await api.getBlogs()
9 | dispatch(getBlogsReducer(data.result))
10 | dispatch(end())
11 | } catch (err) {
12 | dispatch(error(err.message))
13 | }
14 | }
15 | export const createBlog = (blogData, setOpen) => async (dispatch) => {
16 | try {
17 | dispatch(start())
18 | const { data } = await api.createBlog(blogData)
19 | dispatch(createBlogReducer(data.result))
20 | dispatch(end())
21 | setOpen(false)
22 | } catch (err) {
23 | dispatch(error(err.message))
24 | }
25 | }
26 | export const updateBlog = (blogId, blogData, setOpen) => async (dispatch) => {
27 | try {
28 | dispatch(start())
29 | const { data } = await api.updateBlog(blogId, blogData)
30 | dispatch(updateBlogReducer(data.result))
31 | dispatch(end())
32 | setOpen(false)
33 | } catch (err) {
34 | dispatch(error(err.message))
35 | }
36 | }
37 | export const deleteBlog = (blogId, setOpen) => async (dispatch) => {
38 | try {
39 | dispatch(start())
40 | const { data } = await api.deleteBlog(blogId)
41 | dispatch(deleteBlogReducer(data.result))
42 | dispatch(end())
43 | setOpen(false)
44 | } catch (err) {
45 | dispatch(error(err.message))
46 | }
47 | }
--------------------------------------------------------------------------------
/src/User/pages/Freelancing/Confirm.jsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import Button from '@mui/material/Button';
3 | import Dialog from '@mui/material/Dialog';
4 | import DialogActions from '@mui/material/DialogActions';
5 | import DialogContent from '@mui/material/DialogContent';
6 | import DialogContentText from '@mui/material/DialogContentText';
7 | import DialogTitle from '@mui/material/DialogTitle';
8 | import { Link } from 'react-router-dom';
9 |
10 | const Confirm = ({ link, title, open, setOpen }) => {
11 |
12 | const handleClose = () => {
13 | setOpen(false);
14 | };
15 |
16 | return (
17 |
23 |
24 | Continue to {title}?
25 |
26 |
27 |
28 | By clicking Continue, you will leave this website and navigate to {title}.com
29 |
30 |
31 |
32 | Cancel
33 |
34 | setOpen(false)} >Continue
35 |
36 |
37 |
38 | );
39 | }
40 |
41 | export default Confirm
--------------------------------------------------------------------------------
/src/redux/actions/freelancing.js:
--------------------------------------------------------------------------------
1 | import * as api from '../api'
2 | import { start, end, error, getCardsReducer, createCardReducer, updateCardReducer, deleteCardReducer, } from '../reducers/freelancing'
3 |
4 |
5 | export const getCards = () => async (dispatch) => {
6 | try {
7 | dispatch(start())
8 | const { data } = await api.getCards()
9 | dispatch(getCardsReducer(data.result))
10 | dispatch(end())
11 | } catch (err) {
12 | dispatch(error(err.message))
13 | }
14 | }
15 | export const createCard = (cardData, setOpen) => async (dispatch) => {
16 | try {
17 | dispatch(start())
18 | const { data } = await api.createCard(cardData)
19 | dispatch(createCardReducer(data.result))
20 | dispatch(end())
21 | setOpen(false)
22 | } catch (err) {
23 | dispatch(error(err.message))
24 | }
25 | }
26 | export const updateCard = (cardId,cardData, setOpen) => async (dispatch) => {
27 | try {
28 | dispatch(start())
29 | const { data } = await api.updateCard(cardId, cardData)
30 | dispatch(updateCardReducer(data.result))
31 | dispatch(end())
32 | setOpen(false)
33 | } catch (err) {
34 | dispatch(error(err.message))
35 | }
36 | }
37 | export const deleteCard = (cardId, setOpen) => async (dispatch) => {
38 | try {
39 | dispatch(start())
40 | const { data } = await api.deleteCard(cardId)
41 | dispatch(deleteCardReducer(data.result))
42 | dispatch(end())
43 | setOpen(false)
44 | } catch (err) {
45 | dispatch(error(err.message))
46 | }
47 | }
--------------------------------------------------------------------------------
/src/redux/actions/skill.js:
--------------------------------------------------------------------------------
1 | import * as api from '../api'
2 | import { start, end, error, getSkillsReducer, createSkillReducer, updateSkillReducer, deleteSkillReducer, } from '../reducers/skill'
3 |
4 |
5 | export const getSkills = () => async (dispatch) => {
6 | try {
7 | dispatch(start())
8 | const { data } = await api.getSkills()
9 | dispatch(getSkillsReducer(data.result))
10 | dispatch(end())
11 | } catch (err) {
12 | dispatch(error(err.message))
13 | }
14 | }
15 | export const createSkill = (skillData, setOpen) => async (dispatch) => {
16 | try {
17 | dispatch(start())
18 | const { data } = await api.createSkill(skillData)
19 | dispatch(createSkillReducer(data.result))
20 | dispatch(end())
21 | setOpen(false)
22 | } catch (err) {
23 | dispatch(error(err.message))
24 | }
25 | }
26 | export const updateSkill = (skillId, skillData, setOpen) => async (dispatch) => {
27 | try {
28 | dispatch(start())
29 | const { data } = await api.updateSkill(skillId, skillData)
30 | dispatch(updateSkillReducer(data.result))
31 | dispatch(end())
32 | setOpen(false)
33 | } catch (err) {
34 | dispatch(error(err.message))
35 | }
36 | }
37 | export const deleteSkill = (skillId,setOpen) => async (dispatch) => {
38 | try {
39 | dispatch(start())
40 | const { data } = await api.deleteSkill(skillId)
41 | dispatch(deleteSkillReducer(data.result))
42 | dispatch(end())
43 | setOpen(false)
44 | } catch (err) {
45 | dispatch(error(err.message))
46 | }
47 | }
--------------------------------------------------------------------------------
/src/redux/actions/resume.js:
--------------------------------------------------------------------------------
1 | import * as api from '../api'
2 | import { start, end, error, getResumesReducer, createResumeReducer, updateResumeReducer, deleteResumeReducer, } from '../reducers/resume'
3 |
4 |
5 | export const getResumes = () => async (dispatch) => {
6 | try {
7 | dispatch(start())
8 | const { data } = await api.getResumes()
9 | dispatch(getResumesReducer(data.result))
10 | dispatch(end())
11 | } catch (err) {
12 | dispatch(error(err.message))
13 | }
14 | }
15 | export const createResume = (resumeData, setOpen) => async (dispatch) => {
16 | try {
17 | dispatch(start())
18 | const { data } = await api.createResume(resumeData)
19 | dispatch(createResumeReducer(data.result))
20 | dispatch(end())
21 | setOpen(false)
22 | } catch (err) {
23 | dispatch(error(err.message))
24 | }
25 | }
26 | export const updateResume = (resumeId, resumeData, setOpen) => async (dispatch) => {
27 | try {
28 | dispatch(start())
29 | const { data } = await api.updateResume(resumeId, resumeData)
30 | dispatch(updateResumeReducer(data.result))
31 | dispatch(end())
32 | setOpen(false)
33 | } catch (err) {
34 | dispatch(error(err.message))
35 | }
36 | }
37 | export const deleteResume = (resumeId, setOpen) => async (dispatch) => {
38 | try {
39 | dispatch(start())
40 | const { data } = await api.deleteResume(resumeId)
41 | dispatch(deleteResumeReducer(data.result))
42 | dispatch(end())
43 | setOpen(false)
44 | } catch (err) {
45 | dispatch(error(err.message))
46 | }
47 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Full Stack Developer Portfolio Website
2 |
3 | This project, built using MERN and Framer Motion, is a full stack portfolio application with complete management of website content through associated admin panel.
4 |
5 | ### Main Sections
6 |
7 | - Header
8 | - About
9 | - Services
10 | - Skills
11 | - Projects
12 | - Testimonials
13 | - Freelancing
14 | - Contact
15 | - Get Notified
16 |
17 | ### Admin Panel
18 |
19 | With the admin panel, admin gain complete control over the website to manage projects, services, testimonials, contact users, website content, and more—all from one convenient dashboard.
20 |
21 | ## Tech Stack
22 |
23 | - Frontend: React, Framer Motion, Tailwind CSS, Material UI
24 | - Backend: MERN Stack (MongoDB, Express.js, React.js, Node.js)
25 |
26 | ## Getting Started
27 |
28 | 1. Clone the repository:
29 |
30 | ```bash
31 | git clone https://github.com/naumanch969/fullstack-portfolio.git
32 | ```
33 |
34 | 2. Install dependencies:
35 |
36 | ```bash
37 | cd your-portfolio
38 | npm install
39 | ```
40 |
41 | 3. Start the development server:
42 |
43 | ```bash
44 | npm start
45 | ```
46 |
47 | 4. Open your browser and visit `http://localhost:3000` to view the website locally.
48 |
49 | ## Contributing
50 |
51 | Contributions are welcome! If you have any suggestions, enhancements, or bug fixes, feel free to open an issue or submit a pull request.
52 |
53 | ## Contact
54 |
55 | Have questions or feedback? Feel free to reach out to me:
56 |
57 | - Email: naumanch969@gmail.com
58 | - LinkedIn: [My LinkedIn Profile](https://www.linkedin.com/in/naumanch/)
59 |
60 | Thank you for visiting my repository and exploring my portfolio website! 😊🚀
61 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "elagant-music-app",
3 | "private": true,
4 | "version": "0.0.0",
5 | "scripts": {
6 | "dev": "vite",
7 | "build": "vite build",
8 | "preview": "vite preview"
9 | },
10 | "dependencies": {
11 | "@emotion/react": "^11.10.4",
12 | "@emotion/styled": "^11.10.4",
13 | "@mui/icons-material": "^5.10.9",
14 | "@mui/material": "^5.10.10",
15 | "@mui/x-data-grid": "^6.11.1",
16 | "@reduxjs/toolkit": "^1.9.5",
17 | "axios": "^0.27.2",
18 | "elagant-music-app": "file:",
19 | "email-validator": "^2.0.4",
20 | "framer-motion": "^7.6.1",
21 | "js-cookie": "^3.0.1",
22 | "react": "^18.2.0",
23 | "react-date-picker": "^9.2.0",
24 | "react-datetime": "^3.2.0",
25 | "react-dom": "^18.2.0",
26 | "react-file-base64": "^1.0.3",
27 | "react-icons": "^4.4.0",
28 | "react-phone-number-input": "^3.2.19",
29 | "react-redux": "^8.1.2",
30 | "react-router-dom": "^6.3.0",
31 | "react-scroll": "^1.8.7",
32 | "react-textarea-autosize": "^8.4.0",
33 | "redux": "^4.2.1",
34 | "redux-thunk": "^2.4.2",
35 | "swiper": "^8.4.7"
36 | },
37 | "devDependencies": {
38 | "@types/react": "^18.0.0",
39 | "@types/react-dom": "^18.0.0",
40 | "@vitejs/plugin-react": "^1.3.0",
41 | "autoprefixer": "^10.4.7",
42 | "eslint": "^8.18.0",
43 | "eslint-config-airbnb": "^19.0.4",
44 | "eslint-plugin-import": "^2.26.0",
45 | "eslint-plugin-jsx-a11y": "^6.5.1",
46 | "eslint-plugin-react": "^7.30.0",
47 | "eslint-plugin-react-hooks": "^4.6.0",
48 | "postcss": "^8.4.14",
49 | "tailwindcss": "^3.1.3",
50 | "vite": "^2.9.9"
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/redux/actions/service.js:
--------------------------------------------------------------------------------
1 | import * as api from '../api'
2 | import { start, end, error, getServicesReducer, createServiceReducer, updateServiceReducer, deleteServiceReducer, } from '../reducers/service'
3 |
4 |
5 | export const getServices = () => async (dispatch) => {
6 | try {
7 | dispatch(start())
8 | const { data } = await api.getServices()
9 | dispatch(getServicesReducer(data.result))
10 | dispatch(end())
11 | } catch (err) {
12 | dispatch(error(err.message))
13 | }
14 | }
15 | export const createService = (serviceData, setOpen) => async (dispatch) => {
16 | try {
17 | dispatch(start())
18 | const { data } = await api.createService(serviceData)
19 | dispatch(createServiceReducer(data.result))
20 | dispatch(end())
21 | setOpen(false)
22 | } catch (err) {
23 | dispatch(error(err.message))
24 | }
25 | }
26 | export const updateService = (serviceId, serviceData, setOpen) => async (dispatch) => {
27 | try {
28 | dispatch(start())
29 | const { data } = await api.updateService(serviceId, serviceData)
30 | dispatch(updateServiceReducer(data.result))
31 | dispatch(end())
32 | setOpen(false)
33 | } catch (err) {
34 | dispatch(error(err.message))
35 | }
36 | }
37 | export const deleteService = (serviceId, setOpen) => async (dispatch) => {
38 | try {
39 | dispatch(start())
40 | const { data } = await api.deleteService(serviceId)
41 | dispatch(deleteServiceReducer(data.result))
42 | dispatch(end())
43 | setOpen(false)
44 | } catch (err) {
45 | dispatch(error(err.message))
46 | }
47 | }
--------------------------------------------------------------------------------
/src/Admin/pages/Blogs/Delete.jsx:
--------------------------------------------------------------------------------
1 | import { Dialog, DialogTitle, DialogContent, DialogActions, Button, DialogContentText } from '@mui/material'
2 | import React from 'react'
3 | import { useDispatch, useSelector } from 'react-redux'
4 | import { deleteBlog } from '../../../redux/actions/blog'
5 |
6 | const DeleteModal = ({ open, setOpen, blogId }) => {
7 |
8 | ////////////////////////////////////// VARIABLES ///////////////////////////////////////
9 | const dispatch = useDispatch()
10 | const { isFetching } = useSelector(state => state.blog)
11 |
12 | ////////////////////////////////////// FUNCTIONS ///////////////////////////////////////
13 | const handleClose = () => {
14 | setOpen(false)
15 | }
16 | const handleDelete = () => {
17 | dispatch(deleteBlog(blogId, setOpen))
18 | setOpen(false)
19 | }
20 |
21 | return (
22 | setOpen(false)}
25 | >
26 |
27 | Delete the Blog?
28 |
29 |
30 |
31 | Are you sure you want to delete this blog?
32 |
33 |
34 |
35 | Close
36 |
37 | {isFetching ? 'Deleting' : 'Delete'}
38 |
39 |
40 |
41 | )
42 | }
43 |
44 | export default DeleteModal
--------------------------------------------------------------------------------
/src/Admin/pages/Skills/Delete.jsx:
--------------------------------------------------------------------------------
1 | import { Dialog, DialogTitle, DialogContent, DialogActions, Button, DialogContentText } from '@mui/material'
2 | import React from 'react'
3 | import { useDispatch, useSelector } from 'react-redux'
4 | import { deleteSkill } from '../../../redux/actions/skill'
5 |
6 | const DeleteModal = ({ open, setOpen, skillId }) => {
7 |
8 | ////////////////////////////////////// VARIABLES ///////////////////////////////////////
9 | const dispatch = useDispatch()
10 | const { isFetching } = useSelector(state => state.skill)
11 |
12 | ////////////////////////////////////// FUNCTIONS ///////////////////////////////////////
13 | const handleClose = () => {
14 | setOpen(false)
15 | }
16 | const handleDelete = () => {
17 | dispatch(deleteSkill(skillId, setOpen))
18 | setOpen(false)
19 | }
20 |
21 | return (
22 | setOpen(false)}
25 | >
26 |
27 | Delete the Skill?
28 |
29 |
30 |
31 | Are you sure you want to delete this skill?
32 |
33 |
34 |
35 | Close
36 |
37 | {isFetching ? 'Deleting' : 'Delete'}
38 |
39 |
40 |
41 | )
42 | }
43 |
44 | export default DeleteModal
--------------------------------------------------------------------------------
/src/Admin/pages/Freelancing/Delete.jsx:
--------------------------------------------------------------------------------
1 | import { Dialog, DialogTitle, DialogContent, DialogActions, Button, DialogContentText } from '@mui/material'
2 | import React from 'react'
3 | import { useDispatch, useSelector } from 'react-redux'
4 | import { deleteCard } from '../../../redux/actions/freelancing'
5 |
6 | const DeleteModal = ({ open, setOpen, cardId }) => {
7 |
8 | ////////////////////////////////////// VARIABLES ///////////////////////////////////////
9 | const dispatch = useDispatch()
10 | const { isFetching } = useSelector(state => state.freelancing)
11 |
12 | ////////////////////////////////////// FUNCTIONS ///////////////////////////////////////
13 | const handleClose = () => {
14 | setOpen(false)
15 | }
16 | const handleDelete = () => {
17 | dispatch(deleteCard(cardId, setOpen))
18 | setOpen(false)
19 | }
20 |
21 | return (
22 | setOpen(false)}
25 | >
26 |
27 | Delete the Card?
28 |
29 |
30 |
31 | Are you sure you want to delete this card?
32 |
33 |
34 |
35 | Close
36 |
37 | {isFetching ? 'Deleting' : 'Delete'}
38 |
39 |
40 |
41 | )
42 | }
43 |
44 | export default DeleteModal
--------------------------------------------------------------------------------
/src/Admin/pages/Resumes/Delete.jsx:
--------------------------------------------------------------------------------
1 | import { Dialog, DialogTitle, DialogContent, DialogActions, Button, DialogContentText } from '@mui/material'
2 | import React from 'react'
3 | import { useDispatch, useSelector } from 'react-redux'
4 | import { deleteResume } from '../../../redux/actions/resume'
5 |
6 | const DeleteModal = ({ open, setOpen, resumeId }) => {
7 |
8 | ////////////////////////////////////// VARIABLES ///////////////////////////////////////
9 | const dispatch = useDispatch()
10 | const { isFetching } = useSelector(state => state.resume)
11 |
12 | ////////////////////////////////////// FUNCTIONS ///////////////////////////////////////
13 | const handleClose = () => {
14 | setOpen(false)
15 | }
16 | const handleDelete = () => {
17 | dispatch(deleteResume(resumeId, setOpen))
18 | setOpen(false)
19 | }
20 |
21 | return (
22 | setOpen(false)}
25 | >
26 |
27 | Delete the Resume?
28 |
29 |
30 |
31 | Are you sure you want to delete this resume?
32 |
33 |
34 |
35 | Close
36 |
37 | {isFetching ? 'Deleting' : 'Delete'}
38 |
39 |
40 |
41 | )
42 | }
43 |
44 | export default DeleteModal
--------------------------------------------------------------------------------
/src/redux/actions/project.js:
--------------------------------------------------------------------------------
1 | import * as api from '../api'
2 | import { start, end, error, getProjectsReducer, createProjectReducer, uploadProjectImageReducer, updateProjectReducer, deleteProjectReducer, } from '../reducers/project'
3 |
4 |
5 | export const getProjects = () => async (dispatch) => {
6 | try {
7 | dispatch(start())
8 | const { data } = await api.getProjects()
9 | dispatch(getProjectsReducer(data.result))
10 | dispatch(end())
11 | } catch (err) {
12 | dispatch(error(err.message))
13 | }
14 | }
15 | export const createProject = (projectData, setOpen) => async (dispatch) => {
16 | try {
17 | dispatch(start())
18 | const { data } = await api.createProject(projectData)
19 | dispatch(createProjectReducer(data.result))
20 | dispatch(end())
21 | setOpen(false)
22 | } catch (err) {
23 | dispatch(error(err.message))
24 | }
25 | }
26 | export const updateProject = (projectId, projectData, setOpen) => async (dispatch) => {
27 | try {
28 | dispatch(start())
29 | const { data } = await api.updateProject(projectId, projectData)
30 | dispatch(updateProjectReducer(data.result))
31 | dispatch(end())
32 | setOpen(false)
33 | } catch (err) {
34 | dispatch(error(err.message))
35 | }
36 | }
37 | export const deleteProject = (projectId, setOpen) => async (dispatch) => {
38 | try {
39 | dispatch(start())
40 | const { data } = await api.deleteProject(projectId)
41 | dispatch(deleteProjectReducer(data.result))
42 | dispatch(end())
43 | setOpen(false)
44 | } catch (err) {
45 | dispatch(error(err.message))
46 | }
47 | }
--------------------------------------------------------------------------------
/src/utils/Input/Input.jsx:
--------------------------------------------------------------------------------
1 | import { useState } from 'react'
2 | import { VisibilityOff, RemoveRedEye } from '@mui/icons-material'
3 |
4 | const Input = ({ type, placeholder, attribute, blurFunction, showEyeIcon, formData, setFormData, textarea, rows }) => { // attribute may either of 'email', 'name', 'password', 'confirmPassword'
5 |
6 | const [showPassword, setShowPassword] = useState(false)
7 |
8 | const handleChange = (e) => {
9 | setFormData({ ...formData, [attribute]: e.target.value })
10 | }
11 |
12 | const attributes = {
13 | autoComplete: 'off',
14 | type: showPassword ? 'text' : type,
15 | placeholder: placeholder,
16 | name: attribute,
17 | value: formData[attribute],
18 | onChange: handleChange,
19 | onBlur: blurFunction,
20 | className: 'bg-inherit w-full text-textGray border-b-[1px] border-textGray p-[6px] outline-none pl-0',
21 | required: true
22 | }
23 |
24 | return (
25 |
26 |
27 |
28 | {
29 | textarea
30 | ?
31 |
32 | :
33 |
34 | }
35 | {showEyeIcon && setShowPassword(pre => !pre)} className="absolute right-0 top-[50%] transform translate-y-[-50%] " > {showPassword ? : } }
36 |
37 |
38 |
39 |
40 |
41 | )
42 |
43 | }
44 |
45 | export default Input
--------------------------------------------------------------------------------
/src/Admin/pages/Projects/Delete.jsx:
--------------------------------------------------------------------------------
1 | import { Dialog, DialogTitle, DialogContent, DialogActions, Button, DialogContentText } from '@mui/material'
2 | import React from 'react'
3 | import { useDispatch, useSelector } from 'react-redux'
4 | import { deleteProject } from '../../../redux/actions/project'
5 |
6 | const DeleteModal = ({ open, setOpen, projectId }) => {
7 |
8 | ////////////////////////////////////// VARIABLES ///////////////////////////////////////
9 | const dispatch = useDispatch()
10 | const { isFetching } = useSelector(state => state.project)
11 |
12 | ////////////////////////////////////// FUNCTIONS ///////////////////////////////////////
13 | const handleClose = () => {
14 | setOpen(false)
15 | }
16 | const handleDelete = () => {
17 | dispatch(deleteProject(projectId, setOpen))
18 | setOpen(false)
19 | }
20 |
21 | return (
22 | setOpen(false)}
25 | >
26 |
27 | Delete the Project?
28 |
29 |
30 |
31 | Are you sure you want to delete this project?
32 |
33 |
34 |
35 | Close
36 |
37 | {isFetching ? 'Deleting' : 'Delete'}
38 |
39 |
40 |
41 | )
42 | }
43 |
44 | export default DeleteModal
--------------------------------------------------------------------------------
/src/Admin/pages/Services/Delete.jsx:
--------------------------------------------------------------------------------
1 | import { Dialog, DialogTitle, DialogContent, DialogActions, Button, DialogContentText } from '@mui/material'
2 | import React from 'react'
3 | import { useDispatch, useSelector } from 'react-redux'
4 | import { deleteService } from '../../../redux/actions/service'
5 |
6 | const DeleteModal = ({ open, setOpen, serviceId }) => {
7 |
8 | ////////////////////////////////////// VARIABLES ///////////////////////////////////////
9 | const dispatch = useDispatch()
10 | const { isFetching } = useSelector(state => state.service)
11 |
12 | ////////////////////////////////////// FUNCTIONS ///////////////////////////////////////
13 | const handleClose = () => {
14 | setOpen(false)
15 | }
16 | const handleDelete = () => {
17 | dispatch(deleteService(serviceId, setOpen))
18 | setOpen(false)
19 | }
20 |
21 | return (
22 | setOpen(false)}
25 | >
26 |
27 | Delete the Service?
28 |
29 |
30 |
31 | Are you sure you want to delete this service?
32 |
33 |
34 |
35 | Close
36 |
37 | {isFetching ? 'Deleting' : 'Delete'}
38 |
39 |
40 |
41 | )
42 | }
43 |
44 | export default DeleteModal
--------------------------------------------------------------------------------
/src/Admin/pages/Testimonials/Delete.jsx:
--------------------------------------------------------------------------------
1 | import { Dialog, DialogTitle, DialogContent, DialogActions, Button, DialogContentText } from '@mui/material'
2 | import React from 'react'
3 | import { useDispatch, useSelector } from 'react-redux'
4 | import { deleteTestimonial } from '../../../redux/actions/testimonial'
5 |
6 | const DeleteModal = ({ open, setOpen, testimonialId }) => {
7 |
8 | ////////////////////////////////////// VARIABLES ///////////////////////////////////////
9 | const dispatch = useDispatch()
10 | const { isFetching } = useSelector(state => state.testimonial)
11 |
12 | ////////////////////////////////////// FUNCTIONS ///////////////////////////////////////
13 | const handleClose = () => {
14 | setOpen(false)
15 | }
16 | const handleDelete = () => {
17 | dispatch(deleteTestimonial(testimonialId, setOpen))
18 | setOpen(false)
19 | }
20 |
21 | return (
22 | setOpen(false)}
25 | >
26 |
27 | Delete the Testimonial?
28 |
29 |
30 |
31 | Are you sure you want to delete this testimonial?
32 |
33 |
34 |
35 | Close
36 |
37 | {isFetching ? 'Deleting' : 'Delete'}
38 |
39 |
40 |
41 | )
42 | }
43 |
44 | export default DeleteModal
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 | @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;500;600;700;800;900&display=swap');
2 | @tailwind base;
3 | @tailwind components;
4 | @tailwind utilities;
5 |
6 | * {
7 | margin: 0;
8 | padding: 0;
9 | box-sizing: border-box;
10 | font-family: 'Courier New', Courier, monospace;
11 | }
12 |
13 | body {
14 | font-family: "Poppins", Arial, sans-serif;
15 | margin: 0;
16 | padding: 0;
17 | background-color: black;
18 | padding-bottom: 100px;
19 | }
20 |
21 | :root {
22 | --orange: #feb931;
23 | }
24 |
25 | /* body scrollbar */
26 | ::-webkit-scrollbar {
27 | width: 5px;
28 | }
29 |
30 | /* body scrollbar */
31 | .thinScrollbar::-webkit-scrollbar {
32 | width: 1px;
33 | }
34 |
35 | ::-webkit-scrollbar-track {
36 | box-shadow: inset 0 0 5px var(--gray-400);
37 | border-radius: 6px;
38 | }
39 |
40 | ::-webkit-scrollbar-thumb {
41 | background: var(--orange);
42 | border-radius: 10px;
43 | }
44 |
45 |
46 |
47 | .active {
48 | color: var(--orange);
49 | position: relative;
50 | display: block;
51 | }
52 |
53 | .activeBullet {
54 | background: var(--orange);
55 | }
56 |
57 | #link:hover {
58 | color: var(--orange);
59 | position: relative;
60 | display: block;
61 |
62 | }
63 |
64 | .progress-bar {
65 | position: sticky;
66 | top: 0;
67 | left: 0;
68 | right: 0;
69 | height: 5px;
70 | background: var(--orange);
71 | z-index: 60;
72 | transform-origin: 0%;
73 | }
74 |
75 |
76 | section {
77 | min-height: 100vh;
78 | margin-top: 9rem;
79 | margin-bottom: 4rem;
80 | }
81 |
82 | p {
83 | font-family: "Poppins", Arial, sans-serif;
84 | }
85 |
86 |
87 | /* to get rid of the extra unknown height of login/register page */
88 | #shadow-host-companion{
89 | display: none;
90 | }
--------------------------------------------------------------------------------
/src/redux/actions/testimonial.js:
--------------------------------------------------------------------------------
1 | import * as api from '../api'
2 | import { start, end, error, getTestimonialsReducer, createTestimonialReducer, updateTestimonialReducer, deleteTestimonialReducer, } from '../reducers/testimonial'
3 |
4 |
5 | export const getTestimonials = () => async (dispatch) => {
6 | try {
7 | dispatch(start())
8 | const { data } = await api.getTestimonials()
9 | dispatch(getTestimonialsReducer(data.result))
10 | dispatch(end())
11 | } catch (err) {
12 | dispatch(error(err.message))
13 | }
14 | }
15 | export const createTestimonial = (testimonialData, setOpen) => async (dispatch) => {
16 | try {
17 | dispatch(start())
18 | const { data } = await api.createTestimonial(testimonialData)
19 | dispatch(createTestimonialReducer(data.result))
20 | dispatch(end())
21 | setOpen(false)
22 | } catch (err) {
23 | dispatch(error(err.message))
24 | }
25 | }
26 | export const updateTestimonial = (testimonialId, testimonialData, setOpen) => async (dispatch) => {
27 | try {
28 | dispatch(start())
29 | const { data } = await api.updateTestimonial(testimonialId, testimonialData)
30 | dispatch(updateTestimonialReducer(data.result))
31 | dispatch(end())
32 | setOpen(false)
33 | } catch (err) {
34 | dispatch(error(err.message))
35 | }
36 | }
37 | export const deleteTestimonial = (testimonialId, setOpen) => async (dispatch) => {
38 | try {
39 | dispatch(start())
40 | const { data } = await api.deleteTestimonial(testimonialId)
41 | dispatch(deleteTestimonialReducer(data.result))
42 | dispatch(end())
43 | setOpen(false)
44 | } catch (err) {
45 | dispatch(error(err.message))
46 | }
47 | }
--------------------------------------------------------------------------------
/src/User/components/SocialLinks.jsx:
--------------------------------------------------------------------------------
1 | import { Facebook, GitHub, Instagram, LinkedIn, Twitter } from '@mui/icons-material'
2 | import { icons } from '../../data'
3 | import { motion } from 'framer-motion'
4 |
5 | const SocialMedia = () => {
6 | const socialMedia = [
7 | {
8 | name: "Facebook",
9 | link: "https://www.facebook.com/profile.php?id=100072770904288",
10 | icon:
11 | },
12 | {
13 | name: "Instagram",
14 | link: "https://www.instagram.com/naumanch969/",
15 | icon:
16 | },
17 | {
18 | name: "LinkedIn",
19 | link: "https://www.linkedin.com/in/nauman-ch-a68668256/",
20 | icon:
21 | },
22 | {
23 | name: "Github",
24 | link: "https://github.com/naumanch969",
25 | icon:
26 | },
27 | {
28 | name: "Twitter",
29 | link: "https://twitter.com/Naumanch969",
30 | icon:
31 | }
32 | ]
33 |
34 | return (
35 | <>
36 | {
37 | socialMedia.map((sLink, index) => (
38 |
45 | {sLink.icon}
46 |
47 | ))
48 | }
49 | >
50 | )
51 | }
52 |
53 | export default SocialMedia;
--------------------------------------------------------------------------------
/src/User/components/Input.jsx:
--------------------------------------------------------------------------------
1 | import { useState } from 'react'
2 | import { VisibilityOff, RemoveRedEye } from '@mui/icons-material'
3 |
4 | const Input = ({ type, label, placeholder, attribute, blurFunction, showEyeIcon, formData, setFormData, textarea, light, rows }) => { // attribute may either of 'email', 'name', 'password', 'confirmPassword'
5 |
6 | const [showPassword, setShowPassword] = useState(false)
7 |
8 | const handleChange = (e) => {
9 | setFormData({ ...formData, [attribute]: e.target.value })
10 | }
11 |
12 | const attributes = {
13 | autoComplete: 'off',
14 | type: showPassword ? 'text' : type,
15 | placeholder: placeholder,
16 | name: attribute,
17 | value: formData[attribute],
18 | onChange: handleChange,
19 | onBlur: blurFunction,
20 | className: `bg-inherit w-full ${textarea ? 'h-auto ' : 'h-[40px] '} ${light ? 'bg-white text-black ' : 'bg-lightGray text-white'} border-[1px] border-textGray rounded-[4px] px-[6px] outline-none`,
21 | required: true
22 | }
23 |
24 | return (
25 |
26 |
27 | {label &&
28 |
{label}:
29 | }
30 |
31 |
32 | {
33 | textarea
34 | ?
35 |
36 | :
37 |
38 | }
39 | {showEyeIcon && setShowPassword(pre => !pre)} className="absolute right-0 top-[50%] transform translate-y-[-50%] " > {showPassword ? : } }
40 |
41 |
42 |
43 |
44 |
45 | )
46 |
47 | }
48 |
49 | export default Input
--------------------------------------------------------------------------------
/src/Admin/pages/Skills/View.jsx:
--------------------------------------------------------------------------------
1 | import { Close } from "@mui/icons-material";
2 | import { IconButton, Modal } from "@mui/material";
3 |
4 | const View = ({ skill, open, setOpen }) => {
5 |
6 | ////////////////////////////// VARIABLES //////////////////////////////////////
7 |
8 | ////////////////////////////// STATES /////////////////////////////////////////
9 |
10 | ////////////////////////////// USE EFFECTS ////////////////////////////////////
11 |
12 | ////////////////////////////// FUNCTIONS ///////////////////////////////////////
13 |
14 | return (
15 | setOpen(false)} className='w-screen h-screen flex justify-center items-center ' >
16 |
17 |
18 |
setOpen(false)} className="absolute top-[5px] right-[5px] rounded-full p-[2px] bg-black " >
19 |
20 |
21 |
22 |
Skill:
23 |
24 | {skill?.skill}
25 |
26 |
27 |
28 |
Percentage:
29 |
30 | {skill?.percentage}
31 |
32 |
33 |
34 |
35 |
36 | )
37 | }
38 |
39 | export default View;
--------------------------------------------------------------------------------
/src/Admin/components/Table.jsx:
--------------------------------------------------------------------------------
1 | import { Search } from '@mui/icons-material';
2 | import { CircularProgress } from '@mui/material';
3 | import { DataGrid } from '@mui/x-data-grid';
4 | import { useState } from 'react';
5 |
6 | const Table = ({ columns, rows, isFetching, error, rowsPerPage }) => {
7 |
8 | //////////////////////////////////////// VARIABLES ///////////////////////////////////
9 |
10 | //////////////////////////////////////// STATES ///////////////////////////////////
11 | const [searchValue, setSearchValue] = useState('')
12 |
13 | //////////////////////////////////////// FUNCTIONS ///////////////////////////////////
14 |
15 |
16 |
17 | return (
18 |
19 |
20 | {
21 | isFetching
22 | &&
23 |
24 |
25 |
26 | }
27 | {
28 | error
29 | &&
30 |
31 | {error}
32 |
33 | }
34 | {
35 | (!isFetching && !error) &&
36 |
row._id}
46 | pageSizeOptions={[10]}
47 | checkboxSelection
48 | disableRowSelectionOnClick
49 | />
50 | }
51 |
52 | );
53 | }
54 |
55 | export default Table
--------------------------------------------------------------------------------
/src/utils/Cursor/cursor.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import './cursor.css'
3 |
4 | const Cursor = () => {
5 |
6 | let cursor = document.querySelector('#cursor')
7 | let body = document.querySelector('body')
8 | document.onmousemove = (e) => {
9 | // move cursor
10 | cursor.style.top = e.pageY + 'px'
11 | cursor.style.left = e.pageX + 'px'
12 |
13 | // animate background
14 | body.style.backgroundPositionX = e.pageX - 4 + 'px'
15 | body.style.backgroundPositionY = e.pageY - 4 + 'px'
16 |
17 | // add elements to body
18 | let element = document.createElement('div')
19 | element.className = 'element'
20 | body.prepend(element)
21 |
22 | // move elmeents randomly across x and y axis
23 | element.style.left = cursor.getBoundingClientRect().x + 'px'
24 | element.style.top = cursor.getBoundingClientRect().y - 50 + 'px'
25 |
26 | setTimeout(function () {
27 | let text = document.querySelectorAll('.element')[0],
28 | directionX = Math.random() < .5 ? -1 : 1,
29 | directionY = Math.random() < .5 ? -1 : 1
30 |
31 | text.style.left = parseInt(text.style.left) - (directionX * (Math.random() * 200)) + 'px'
32 | text.style.top = parseInt(text.style.top) - (directionY * (Math.random() * 200)) + 'px'
33 |
34 | text.style.opacity = 0
35 | text.style.transform = 'scale(0.25deg)'
36 | text.innerHTML = randomText()
37 |
38 | // remove element
39 | setTimeout(function () {
40 | element.remove()
41 | }, 1000)
42 |
43 | }, 10)
44 |
45 | }
46 |
47 | const randomText = () => {
48 | var text = ('abcdefghijklmnopqrstuvwxyz1234567890').split('')
49 | var letter = text[Math.floor(Math.random() * text.length)]
50 | return letter
51 | }
52 |
53 | return (
54 |
55 | )
56 | }
57 |
58 | export default Cursor
--------------------------------------------------------------------------------
/src/utils/Loading/loading.css:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | box-sizing: border-box;
5 | }
6 |
7 | /* body {
8 | display: flex;
9 | justify-content: center;
10 | align-content: center;
11 | min-height: 100vh;
12 | background-color: #222;
13 | } */
14 |
15 | .loader {
16 | position: relative;
17 | width: 150px;
18 | height: 150px;
19 | animation: animate 24s steps(12) infinite;
20 | }
21 |
22 | @keyframes animate {
23 | 0% {
24 | transform: rotate(0deg);
25 | }
26 |
27 | 100% {
28 | transform: rotate(360deg);
29 | }
30 | }
31 |
32 | .box h3 {
33 | position: absolute;
34 | top: 50%;
35 | left: 50%;
36 | transform: translate(-50%, -50%);
37 | font-size: 0.85em;
38 | font-weight: 300;
39 | color: rgba(255, 255, 255, 0.25);
40 | text-transform: uppercase;
41 | }
42 |
43 | h3 b {
44 | color: #fff;
45 | font-weight: 500;
46 | text-shadow: 0 0 10px #fff,
47 | 0 0 20px #fff,
48 | 0 0 30px #fff,
49 | 0 0 40px #fff,
50 | 0 0 50px #fff;
51 | }
52 |
53 | .loader span {
54 | position: absolute;
55 | top: 0;
56 | left: 0;
57 | width: 100%;
58 | height: 100%;
59 | /* border: 2px solid #fff; */
60 | transform: rotate(calc(30deg * var(--i)));
61 | }
62 |
63 | .loader span::before {
64 | content: '';
65 | position: absolute;
66 | top: 0;
67 | left: 0;
68 | width: 20px;
69 | height: 20px;
70 | background: rgba(255, 255, 255, 0.15);
71 | }
72 |
73 | .loader span:nth-child(3n+3)::before {
74 | background: #fff;
75 | box-shadow: 0 0 10px #fff,
76 | 0 0 20px #fff,
77 | 0 0 30px #fff,
78 | 0 0 40px #fff,
79 | 0 0 50px #fff;
80 | animation: animateSquare 2s linear infinite;
81 | transform-origin: 75px;
82 | }
83 |
84 | @keyframes animateSquare {
85 |
86 | 0%,
87 | 25% {
88 | transform: rotate(0deg);
89 | }
90 |
91 | 75%,
92 | 90%,
93 | 100% {
94 | transform: rotate(180deg);
95 | }
96 | }
--------------------------------------------------------------------------------
/src/User/pages/Services/Services.jsx:
--------------------------------------------------------------------------------
1 | import { motion } from "framer-motion"
2 | import ServiceCard from './ServiceCard'
3 | import { MainHeading } from "../../components"
4 | import { useEffect } from "react"
5 | import './service.css'
6 | import { useDispatch, useSelector } from "react-redux"
7 | import { getServices } from '../../../redux/actions/service'
8 |
9 | const Services = () => {
10 |
11 | ////////////////////////////////////// VARIABLES /////////////////////////////////////////
12 | const dispatch = useDispatch()
13 | const { services } = useSelector(state => state.service)
14 |
15 | ////////////////////////////////////// USE EFFECTS ///////////////////////////////////////
16 | useEffect(() => {
17 | dispatch(getServices())
18 | }, [])
19 |
20 | return (
21 |
28 |
29 |
30 |
35 |
36 |
37 |
38 | {
39 | services.map((service, index) => (
40 | <>
41 |
46 | >
47 | ))
48 | }
49 |
50 |
51 |
52 |
53 |
54 | )
55 | }
56 |
57 | export default Services
--------------------------------------------------------------------------------
/src/User/components/HeaderText.jsx:
--------------------------------------------------------------------------------
1 | import Button from "./Button"
2 | import { motion } from "framer-motion"
3 | import { Link } from "react-scroll"
4 |
5 |
6 |
7 | const HeaderText = ({ first }) => {
8 |
9 | return (
10 |
16 |
17 |
Hello!
18 |
19 | {
20 | first ?
21 | <>
22 |
23 | I'm Nauman Chaudhry
24 |
25 |
A Freelance Web Designer
26 | >
27 | :
28 | <>
29 |
30 | I'm a MERN stack developer based in Lahore.
31 |
32 | >
33 | }
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | )
43 | }
44 |
45 |
46 | export default HeaderText;
--------------------------------------------------------------------------------
/src/utils/Loading2/loading.css:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | box-sizing: border-box;
5 | }
6 |
7 | /* body {
8 | display: flex;
9 | justify-self: center;
10 | align-items: center;
11 | min-height: 100vh;
12 | background: #111;
13 | } */
14 |
15 | .container {
16 | position: relative;
17 | width: 100%;
18 | display: flex;
19 | justify-content: center;
20 | align-items: center;
21 | }
22 |
23 | .container .square {
24 | position: absolute;
25 | width: 200px;
26 | height: 200px;
27 | }
28 |
29 | .container .square:nth-child(2) {
30 | transform: translate(-25%, -25%) rotateX(180deg);
31 | filter: hue-rotate(60deg);
32 | }
33 |
34 | .container .square:nth-child(3) {
35 | transform: translate(25%, 25%) rotate(180deg);
36 | filter: hue-rotate(180deg);
37 | }
38 |
39 | .container .square::before {
40 | content: '';
41 | position: absolute;
42 | width: 20px;
43 | height: 20px;
44 | background: #0f0;
45 | box-shadow: 0 0 0 8px #0f03, 0 0 0 15px #0f03;
46 | animation: animateSquare 4s linear infinite;
47 | }
48 |
49 | @keyframes animateSquare {
50 | 0% {
51 | transform: translate(2px 2px);
52 | }
53 |
54 | 25% {
55 | transform: translate(178px, 2px);
56 | }
57 |
58 | 50% {
59 | transform: translate(178px, 178px);
60 | }
61 |
62 | 75% {
63 | transform: translate(2px, 178px);
64 | }
65 |
66 | 100% {
67 | transform: translate(2px, 2px);
68 | }
69 | }
70 |
71 |
72 | .container .square span {
73 | position: absolute;
74 | inset: 10px;
75 | overflow: hidden;
76 | transform: rotate(calc(90deg * var(--i)));
77 | }
78 |
79 | .container .square span::before {
80 | content: '';
81 | position: absolute;
82 | width: 100%;
83 | height: 4px;
84 | background: #0f0;
85 | transform: translateX(-100%);
86 | animation: animate 4s linear infinite;
87 | animation-delay: calc(1s * var(--i));
88 | }
89 |
90 | @keyframes animate {
91 | 0% {
92 | transform: translateX(-100%);
93 | }
94 |
95 | 50%,
96 | 100% {
97 | transform: translateX(100%);
98 | }
99 | }
--------------------------------------------------------------------------------
/src/Admin/components/Textarea.jsx:
--------------------------------------------------------------------------------
1 | import TextareaAutosize from "react-textarea-autosize"
2 | import { useSelector } from "react-redux"
3 |
4 | const Textarea = ({ heading, placeholder, blurFunction, attribute, state, setState, id, subAttribute }) => {
5 | // attribute is the key/field/element of state (state may be about,contact,footer,projects etc.)
6 | // subAttribute is the key/field/element of findedObject (whose _id = id) of array which is key/field/element of home/about/skills/projects/footer/blogs
7 | const { loggedUser } = useSelector(state => state.user)
8 |
9 | ////////////////////////////// VARIABLES //////////////////////////////////////
10 | let findedObj = subAttribute ? state[attribute].find(att => att._id == id) : state
11 |
12 | const isAdmin = loggedUser?.tokens?.find(token => token.name == 'admin_auth_token' || token.name == 'main_admin_auth_token')
13 | ////////////////////////////// STATES /////////////////////////////////////////
14 |
15 | ////////////////////////////// USE EFFECTS ////////////////////////////////////
16 |
17 | ////////////////////////////// FUNCTIONS ///////////////////////////////////////
18 | const blur = (e) => {
19 | blurFunction(e.target.value)
20 | }
21 |
22 | const handleChange = (e) => {
23 | findedObj[subAttribute ? subAttribute : attribute] = e.target.value
24 | setState({ ...state })
25 | }
26 |
27 | return (
28 |
29 |
{heading}:
30 |
41 |
42 |
43 | )
44 | }
45 |
46 | export default Textarea;
--------------------------------------------------------------------------------
/src/Admin/pages/Services/View.jsx:
--------------------------------------------------------------------------------
1 | import { Close } from "@mui/icons-material";
2 | import { IconButton, Modal } from "@mui/material";
3 |
4 | const View = ({ service, open, setOpen }) => {
5 |
6 | ////////////////////////////// VARIABLES //////////////////////////////////////
7 |
8 | ////////////////////////////// STATES /////////////////////////////////////////
9 |
10 | ////////////////////////////// USE EFFECTS ////////////////////////////////////
11 |
12 | ////////////////////////////// FUNCTIONS ///////////////////////////////////////
13 |
14 | return (
15 | setOpen(false)} className='w-screen h-screen flex justify-center items-center ' >
16 |
17 |
18 |
setOpen(false)} className="absolute top-[5px] right-[5px] rounded-full p-[2px] bg-black " >
19 |
20 |
21 |
22 |
Service:
23 |
24 | {service?.service}
25 |
26 |
27 |
28 |
Link:
29 |
30 | {service?.link}
31 |
32 |
33 |
34 |
Icon:
35 |
36 | {service?.icon}
37 |
38 |
39 |
40 |
41 |
42 | )
43 | }
44 |
45 | export default View;
--------------------------------------------------------------------------------
/src/Admin/pages/Resumes/View.jsx:
--------------------------------------------------------------------------------
1 | import { Close } from "@mui/icons-material";
2 | import { IconButton, Modal } from "@mui/material";
3 |
4 | const View = ({ resume, open, setOpen }) => {
5 |
6 | ////////////////////////////// VARIABLES //////////////////////////////////////
7 |
8 | ////////////////////////////// STATES /////////////////////////////////////////
9 |
10 | ////////////////////////////// USE EFFECTS ////////////////////////////////////
11 |
12 | ////////////////////////////// FUNCTIONS ///////////////////////////////////////
13 |
14 | return (
15 | setOpen(false)} className='w-screen h-screen flex justify-center items-center ' >
16 |
17 |
18 |
setOpen(false)} className="absolute top-[5px] right-[5px] rounded-full p-[2px] bg-black " >
19 |
20 |
21 |
22 |
Title:
23 |
24 | {resume?.title}
25 |
26 |
27 |
28 |
Sub Title:
29 |
30 | {resume?.subTitle}
31 |
32 |
33 |
34 |
Detail:
35 |
36 | {resume?.detail}
37 |
38 |
39 |
40 |
41 |
42 | )
43 | }
44 |
45 | export default View;
--------------------------------------------------------------------------------
/src/User/pages/Home/Home.jsx:
--------------------------------------------------------------------------------
1 | import { Button } from "../../components"
2 | import { profile } from "../../../assets"
3 | import { Link } from "react-scroll"
4 |
5 | const Home = () => {
6 |
7 | ////////////////////////////// VARIABLES //////////////////////////////////////
8 |
9 | ////////////////////////////// STATES /////////////////////////////////////////
10 |
11 | ////////////////////////////// USE EFFECTS ////////////////////////////////////
12 |
13 | ////////////////////////////// FUNCTIONS ///////////////////////////////////////
14 |
15 |
16 | return (
17 |
18 |
19 |
20 |
Hey
21 |
22 |
23 | I'm Nauman Chaudhry
24 |
25 |
26 | A Freelance MERN Stack Developer
27 |
28 |
29 |
30 |
31 | Contact Me
32 |
33 |
34 | My Work
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | )
45 | }
46 |
47 | export default Home
--------------------------------------------------------------------------------
/src/Admin/pages/Blogs/View.jsx:
--------------------------------------------------------------------------------
1 | import { BrokenImage, Close } from "@mui/icons-material";
2 | import { IconButton, Modal } from "@mui/material";
3 |
4 | const View = ({ blog, open, setOpen }) => {
5 |
6 | ////////////////////////////// VARIABLES //////////////////////////////////////
7 |
8 | ////////////////////////////// STATES /////////////////////////////////////////
9 |
10 | ////////////////////////////// USE EFFECTS ////////////////////////////////////
11 |
12 | ////////////////////////////// FUNCTIONS ///////////////////////////////////////
13 |
14 |
15 | return (
16 | setOpen(false)} className='w-screen h-screen flex justify-center items-center ' >
17 |
18 |
19 |
setOpen(false)} className="absolute top-[5px] right-[5px] rounded-full p-[2px] bg-black " >
20 |
21 |
22 | {
23 | blog?.image
24 | ?
25 |
26 | :
27 |
28 | }
29 |
30 |
Blog:
31 |
32 | {blog?.blog}
33 |
34 |
35 |
36 |
Link:
37 |
38 | {blog?.link}
39 |
40 |
41 |
42 |
Icon:
43 |
44 | {blog?.icon}
45 |
46 |
47 |
48 |
49 |
50 | )
51 | }
52 |
53 | export default View;
--------------------------------------------------------------------------------
/src/User/pages/Skills/Skills.jsx:
--------------------------------------------------------------------------------
1 | import { motion } from "framer-motion"
2 |
3 | import { MainHeading } from "../../components"
4 | import Skillbar from './Skillbar'
5 | import { useEffect } from "react"
6 | import { useDispatch, useSelector } from "react-redux"
7 | import { getSkills } from '../../../redux/actions/skill'
8 |
9 | const Skills = () => {
10 |
11 | ////////////////////////////// VARIABLES //////////////////////////////////////
12 | const dispatch = useDispatch()
13 | const { skills } = useSelector(state => state.skill)
14 |
15 | ////////////////////////////// STATES /////////////////////////////////////////
16 |
17 | ////////////////////////////// USE EFFECTS ////////////////////////////////////
18 | useEffect(() => {
19 | dispatch(getSkills())
20 | }, [])
21 |
22 | ////////////////////////////// FUNCTIONS ///////////////////////////////////////
23 |
24 |
25 |
26 | return (
27 |
33 |
34 |
35 |
40 |
41 |
42 |
43 | {
44 | skills.map((skill, index) => (
45 |
46 | ))
47 | }
48 |
49 |
50 |
51 |
52 | )
53 | }
54 |
55 | export default Skills;
56 |
57 |
58 | const skills = [
59 | {
60 | title: 'HTML5',
61 | percentage: '95'
62 | },
63 | {
64 | title: 'CSS3',
65 | percentage: '90'
66 | },
67 | {
68 | title: 'Javascript',
69 | percentage: '65'
70 | },
71 | {
72 | title: 'React JS',
73 | percentage: '85'
74 | },
75 | {
76 | title: 'React Redux',
77 | percentage: '75'
78 | },
79 | {
80 | title: 'Material UI',
81 | percentage: '85'
82 | },
83 | {
84 | title: 'Tailwind CSS',
85 | percentage: '75'
86 | },
87 | {
88 | title: 'Mongo DB',
89 | percentage: '65'
90 | },
91 | ]
--------------------------------------------------------------------------------
/src/Admin/pages/Contact/View.jsx:
--------------------------------------------------------------------------------
1 | import { Close } from "@mui/icons-material";
2 | import { IconButton, Modal } from "@mui/material";
3 |
4 | const View = ({ contactUser, open, setOpen }) => {
5 |
6 | ////////////////////////////// VARIABLES //////////////////////////////////////
7 |
8 | ////////////////////////////// STATES /////////////////////////////////////////
9 |
10 | ////////////////////////////// USE EFFECTS ////////////////////////////////////
11 |
12 | ////////////////////////////// FUNCTIONS ///////////////////////////////////////
13 |
14 | return (
15 | setOpen(false)} className='w-screen h-screen flex justify-center items-center ' >
16 |
17 |
18 |
setOpen(false)} className="absolute top-[5px] right-[5px] rounded-full p-[2px] bg-black " >
19 |
20 |
21 |
22 |
Name:
23 |
24 | {contactUser?.name}
25 |
26 |
27 |
28 |
Email:
29 |
30 | {contactUser?.email}
31 |
32 |
33 |
34 |
Subject:
35 |
36 | {contactUser?.subject}
37 |
38 |
39 |
40 |
Message:
41 |
42 | {contactUser?.message}
43 |
44 |
45 |
46 |
47 |
48 | )
49 | }
50 |
51 | export default View;
--------------------------------------------------------------------------------
/src/Admin/pages/Testimonials/View.jsx:
--------------------------------------------------------------------------------
1 | import { BrokenImage, Close } from "@mui/icons-material";
2 | import { IconButton, Modal } from "@mui/material";
3 |
4 | const View = ({ testimonial, open, setOpen }) => {
5 |
6 | ////////////////////////////// VARIABLES //////////////////////////////////////
7 |
8 | ////////////////////////////// STATES /////////////////////////////////////////
9 |
10 | ////////////////////////////// USE EFFECTS ////////////////////////////////////
11 |
12 | ////////////////////////////// FUNCTIONS ///////////////////////////////////////
13 |
14 |
15 | return (
16 | setOpen(false)} className='w-screen h-screen flex justify-center items-center ' >
17 |
18 |
19 |
setOpen(false)} className="absolute top-[5px] right-[5px] rounded-full p-[2px] bg-black " >
20 |
21 |
22 | {
23 | testimonial?.image
24 | ?
25 |
26 | :
27 |
28 | }
29 |
30 |
Testimonial:
31 |
32 | {testimonial?.testimonial}
33 |
34 |
35 |
36 |
Link:
37 |
38 | {testimonial?.link}
39 |
40 |
41 |
42 |
Icon:
43 |
44 | {testimonial?.icon}
45 |
46 |
47 |
48 |
49 |
50 | )
51 | }
52 |
53 | export default View;
--------------------------------------------------------------------------------
/src/Admin/pages/Contact/Contact.jsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from "react"
2 | import { useDispatch, useSelector } from 'react-redux'
3 | import { Heading, Error, Table } from "../../components"
4 | import { Loading } from '../../../utils/Components'
5 | import { getContactUsers } from "../../../redux/actions/contact"
6 | import View from "./View"
7 | import { Delete as DeleteIcon, Edit, Visibility } from "@mui/icons-material"
8 | import { IconButton } from "@mui/material"
9 |
10 | const ContactUsers = () => {
11 |
12 | ////////////////////////////// VARIABLES //////////////////////////////////////
13 | const dispatch = useDispatch()
14 | const { contactUsers, isFetching, error } = useSelector(state => state.contact)
15 | const columns = [
16 | { field: '_id', headerName: 'ID', width: 90 },
17 | { field: 'name', headerName: 'Name', width: 200, },
18 | { field: 'email', headerName: 'Email', width: 200, },
19 | { field: 'subject', headerName: 'Subject', width: 200, },
20 | { field: 'message', headerName: 'Message', width: 300, },
21 | {
22 | field: 'action', headerName: 'Action', width: 160, renderCell: (params) => (
23 |
24 | { setOpenViewModal(true); setCurrentContactUser(params.row) }} >
25 |
26 | )
27 | },
28 | ];
29 |
30 | ////////////////////////////// STATES /////////////////////////////////////////
31 | const [openViewModal, setOpenViewModal] = useState(false)
32 | const [currentContactUser, setCurrentContactUser] = useState(null)
33 |
34 | ////////////////////////////// USE EFFECTS ////////////////////////////////////
35 | useEffect(() => {
36 | dispatch(getContactUsers())
37 | }, [])
38 |
39 |
40 | ////////////////////////////// FUNCTIONS ///////////////////////////////////////
41 |
42 | if (isFetching) return
43 | if (error) return
44 |
45 | return (
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
63 |
64 |
65 |
66 | )
67 | }
68 |
69 | export default ContactUsers
--------------------------------------------------------------------------------
/src/Admin/components/Navbar.jsx:
--------------------------------------------------------------------------------
1 | import { useStateContext } from '../../contexts/ContextProvider'
2 | import { motion } from 'framer-motion'
3 | import { Person, SwitchLeftOutlined, Dehaze } from '@mui/icons-material'
4 | import { useState } from 'react'
5 | import { Link } from 'react-router-dom'
6 | import { useNavigate } from 'react-router-dom'
7 | import { useSelector } from 'react-redux'
8 |
9 |
10 | const Navbar = ({ navbarMenuRef, showMenu, setShowMenu }) => {
11 | const navigate = useNavigate()
12 | const { setMode, setShowSidebar } = useStateContext()
13 | const { loggedUser } = useSelector(state => state.user)
14 |
15 | const navigateToAccount = () => {
16 | navigate('/auth')
17 | setShowMenu(false)
18 | }
19 |
20 | const switchMode = () => {
21 | navigate('/')
22 | setShowMenu(false)
23 | localStorage.setItem('mode', 'user')
24 | setMode('user')
25 | }
26 |
27 | return (
28 |
29 |
30 |
31 | setShowSidebar(pre => !pre)} >
32 |
{ navigate('/') }} style={{ fontFamily: 'cursive' }} className=" text-3xl font-bold cursor-pointer text-orange " >Nauman
33 |
34 |
35 |
36 |
{loggedUser?.name}
37 |
38 |
setShowMenu(pre => !pre)} className="flex justify-center items-center bg-orange rounded-[50%] w-[40px] h-[40px] text-[24px] capitalize cursor-pointer " >{loggedUser?.name?.charAt(0) || 'U'}
39 | {
40 | showMenu &&
41 |
45 | {/* Account */}
46 | Switch Mode
47 |
48 | }
49 |
50 |
51 |
52 |
53 | )
54 | }
55 |
56 | export default Navbar
--------------------------------------------------------------------------------
/src/User/pages/About/About.jsx:
--------------------------------------------------------------------------------
1 | import { profile } from "../../../assets"
2 | import { MainHeading, Button } from "../../components"
3 | import { motion } from "framer-motion"
4 |
5 | const About = () => {
6 |
7 | /////////////////////////////////////////////////////////////// VARIABLES ///////////////////////////////////////////////////////////////////////
8 |
9 | /////////////////////////////////////////////////////////////// STATES //////////////////////////////////////////////////////////////////////////
10 |
11 | /////////////////////////////////////////////////////////////// USE EFFECTS /////////////////////////////////////////////////////////////////////
12 |
13 | /////////////////////////////////////////////////////////////// FUNCTIONS ////////////////////////////////////////////////////////////////////////
14 |
15 | return (
16 |
23 |
24 | {/* left side */}
25 |
26 |
27 |
28 |
29 | {/* right side */}
30 |
31 |
32 | {/* main heading */}
33 |
34 |
40 | I'm Nauman Chaudhry, a seasoned MERN stack developer with a passion for crafting exceptional digital experiences. With over a year of dedicated experience, I've had the privilege of working on a diverse range of projects. These include comprehensive full-stack web applications and meticulously designed RESTful APIs, all powered by technologies like MongoDB, Express.js, React.js, and Node.js.
41 |
42 | My commitment to continuous learning keeps me at the forefront of industry trends. I thrive on exploring new horizons in technology and contributing to open-source projects. Being an active part of coding communities brings me joy and enriches my knowledge.
43 |
44 | I sincerely appreciate your presence on my portfolio. Whether you have inquiries or a collaborative project in mind, please don't hesitate to reach out. Together, we can shape the future of the digital landscape.
45 |
46 | Best regards,
47 | Nauman Chaudhry
48 |
49 | `}
50 | alignStart
51 | />
52 |
53 |
54 |
55 |
56 |
57 | )
58 | }
59 |
60 | export default About
61 |
--------------------------------------------------------------------------------
/src/User/pages/Blogs/Blogs.jsx:
--------------------------------------------------------------------------------
1 | import { motion } from "framer-motion"
2 | import { Swiper, SwiperSlide } from "swiper/react";
3 | import "swiper/css";
4 | import "swiper/css/pagination";
5 | import { Pagination } from "swiper";
6 |
7 | import { MainHeading } from "../../components"
8 | import BlogCard from './BlogCard'
9 | import { useDispatch, useSelector } from "react-redux";
10 | import { useEffect } from "react";
11 | import { getBlogs } from "../../../redux/actions/blog";
12 |
13 |
14 |
15 | const Blogs = () => {
16 |
17 | ////////////////////////////// VARIABLES //////////////////////////////////////
18 | const dispatch = useDispatch()
19 | const { blogs } = useSelector(state => state.blog)
20 |
21 | ////////////////////////////// STATES /////////////////////////////////////////
22 |
23 | ////////////////////////////// USE EFFECTS ////////////////////////////////////
24 | useEffect(() => {
25 | dispatch(getBlogs())
26 | }, [])
27 |
28 | ////////////////////////////// FUNCTIONS ///////////////////////////////////////
29 |
30 | return (
31 |
38 |
39 |
40 |
45 |
46 |
47 |
70 | {
71 | blogs.map((blog, index) => (
72 |
73 |
74 |
75 | ))
76 | }
77 |
78 |
79 |
80 | )
81 | }
82 |
83 | export default Blogs
84 |
85 |
--------------------------------------------------------------------------------
/src/User/pages/Blogs/BlogCard.jsx:
--------------------------------------------------------------------------------
1 |
2 | import { Grid } from "@mui/material"
3 | import { Modal } from '@mui/material'
4 | import { useState } from 'react'
5 |
6 | import { limitText } from '../../../utils/functions'
7 |
8 | const BlogCard = ({ blog }) => {
9 |
10 | ////////////////////////////// VARIABLES //////////////////////////////////////
11 |
12 | ////////////////////////////// STATES /////////////////////////////////////////
13 | const [openModal, setOpenModal] = useState(false)
14 |
15 | ////////////////////////////// USE EFFECTS ////////////////////////////////////
16 |
17 | ////////////////////////////// FUNCTIONS ///////////////////////////////////////
18 |
19 |
20 | return (
21 | <>
22 |
23 | setOpenModal(true)} className="flex flex-col justify-start bg-darkGray gap-2 my-4 min-h-[450px] rounded-[8px] sm:w-fit w-[80%] " >
24 |
25 |
26 |
27 |
28 |
{blog.date}
29 |
{blog.title}
30 |
{limitText(blog.description, 170)}
31 |
{blog.name}
32 |
33 |
34 |
35 |
36 |
37 | setOpenModal(false)}>
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
{blog.date}
46 |
{blog.title}
47 |
{blog.description}
48 |
51 |
52 |
53 |
54 |
55 |
56 |
57 | >
58 | )
59 | }
60 |
61 | {/* */ }
62 |
63 | export default BlogCard;
--------------------------------------------------------------------------------
/src/User/pages/Auth/login.jsx:
--------------------------------------------------------------------------------
1 | import { Person } from '@mui/icons-material'
2 | import React, { useState } from 'react'
3 | import { Input } from '../../components'
4 | import { login } from '../../../redux/actions/user'
5 | import { Link, useNavigate } from 'react-router-dom'
6 | import { useDispatch, useSelector } from 'react-redux'
7 |
8 | const Login = () => {
9 |
10 | //////////////////////////////////// STATES //////////////////////////////////////////
11 | const initialUserState = { email: '', password: '' }
12 | const [userData, setUserData] = useState(initialUserState)
13 | const navigate = useNavigate()
14 | const dispatch = useDispatch()
15 | const { isFetching, error } = useSelector(state => state.user)
16 |
17 |
18 | const handleLogin = () => {
19 | dispatch(login(userData, navigate))
20 | }
21 |
22 |
23 | return (
24 |
25 |
26 |
27 |
30 |
31 |
32 |
40 |
49 |
50 |
51 |
52 |
53 |
54 | {isFetching ? 'Submitting...' : 'Login'}
55 |
56 |
57 | Don't have account?
58 | Register here
59 |
60 |
61 |
62 |
63 | {error &&
{error}
}
64 |
65 |
66 |
67 | )
68 | }
69 |
70 | export default Login
--------------------------------------------------------------------------------
/src/User/pages/Contact/Contact.jsx:
--------------------------------------------------------------------------------
1 |
2 | import { Home, Phone, Mail, Public } from "@mui/icons-material"
3 | import { motion } from "framer-motion"
4 |
5 | import { MainHeading } from "../../components"
6 | import ContactCard from './ContactCard'
7 | import ContactForm from './ContactForm'
8 | import { useDispatch, useSelector } from "react-redux"
9 | import { } from '../../../redux/actions/contact'
10 |
11 | const Contact = () => {
12 |
13 | ////////////////////////////// VARIABLES //////////////////////////////////////
14 | const dispatch = useDispatch()
15 | const { cards } = useSelector(state => state.contact)
16 |
17 | ////////////////////////////// STATES /////////////////////////////////////////
18 |
19 | ////////////////////////////// USE EFFECTS ////////////////////////////////////
20 |
21 | ////////////////////////////// FUNCTIONS ///////////////////////////////////////
22 |
23 | return (
24 |
31 |
32 |
33 | {/* contact main heading */}
34 |
35 |
40 |
41 |
42 | {/* contact buttons */}
43 |
44 |
45 | {
46 | cards?.map((card, index) => (
47 |
48 | ))
49 | }
50 |
51 |
52 |
53 | {/* contact form */}
54 |
55 |
56 |
57 |
58 |
59 | )
60 | }
61 | export default Contact;
62 |
63 |
64 | const contacts = [
65 | {
66 | icon: ,
67 | title: 'Address',
68 | detail: 'Lahore Pakistan'
69 | },
70 | {
71 | icon: ,
72 | title: 'Contact Number',
73 | detail: '+3055712534'
74 | },
75 | {
76 | icon: ,
77 | title: 'Email Address',
78 | detail: 'naumanch969@gmail.com'
79 | },
80 | {
81 | icon: ,
82 | title: 'Website',
83 | detail: 'naumanch.info'
84 | },
85 | ]
--------------------------------------------------------------------------------
/src/User/pages/Services/service.css:
--------------------------------------------------------------------------------
1 | :root {
2 | --clr: #feb931;
3 | --bg-gray: #2e2e2e;
4 | --text-gray: #888;
5 | }
6 |
7 | .container {
8 | position: relative;
9 | display: flex;
10 | justify-content: center;
11 | align-items: center;
12 | flex-wrap: wrap;
13 | gap: 60px;
14 | padding: 60px 0;
15 | }
16 |
17 | .container .swiper_card::before {
18 | content: '';
19 | position: absolute;
20 | inset: -10px 50px;
21 | border-top: 4px solid var(--clr);
22 | border-bottom: 4px solid var(--clr);
23 | z-index: -1;
24 | transform: skewY(10deg);
25 | transition: 0.5s ease-in-out;
26 | }
27 |
28 | .container .swiper_card:hover::before {
29 | transform: skewY(0deg);
30 | inset: -10px 40px;
31 | }
32 |
33 | .container .swiper_card::after {
34 | content: '';
35 | position: absolute;
36 | inset: 60px -10px;
37 | border-left: 4px solid var(--clr);
38 | border-right: 4px solid var(--clr);
39 | z-index: -1;
40 | transform: skewX(10deg);
41 | transition: 0.5s ease-in-out;
42 | }
43 |
44 | .container .swiper_card:hover::after {
45 | transform: skewX(0deg);
46 | inset: 40px -10px;
47 | }
48 |
49 | .container .swiper_card .content {
50 | position: relative;
51 | display: flex;
52 | justify-content: center;
53 | align-items: center;
54 | flex-direction: column;
55 | text-align: center;
56 | gap: 20px;
57 | padding: 0 20px;
58 | width: 100%;
59 | height: 100%;
60 | overflow: hidden;
61 | }
62 |
63 | .container .swiper_card .content .icon {
64 | color: var(--clr);
65 | width: 80px;
66 | height: 80px;
67 | box-shadow: 0 0 0 4px var(--bg-gray), 0 0 0 6px var(--clr);
68 | display: flex;
69 | justify-content: center;
70 | align-items: center;
71 | font-size: 2.5em;
72 | background-color: var(--bg-gray);
73 | transition: 0.5s ease-in-out;
74 | }
75 |
76 | .container .swiper_card:hover .content .icon {
77 | background: var(--clr);
78 | color: var(--bg-gray);
79 | box-shadow: 0 0 0 4px var(--bg-gray), 0 0 0 300px var(--clr);
80 | }
81 |
82 |
83 | .container .swiper_card .content .text h3 {
84 | font-size: 1.5em;
85 | color: white;
86 | font-weight: 500;
87 | transition: 0.5s ease-in-out;
88 | }
89 |
90 | .container .swiper_card:hover .content .text h3 {
91 | color: var(--bg-gray);
92 | }
93 |
94 |
95 |
96 | .container .swiper_card .content .text p {
97 | color: var(--text-gray);
98 | transition: 0.5s ease-in-out;
99 | }
100 |
101 | .container .swiper_card:hover .content .text p {
102 | color: var(--bg-gray);
103 | }
104 |
105 |
106 | .container .swiper_card .content .text a {
107 | position: relative;
108 | background-color: var(--clr);
109 | color: var(--bg-gray);
110 | padding: 8px 15px;
111 | display: inline-block;
112 | text-decoration: none;
113 | font-weight: 500;
114 | margin-top: 10px;
115 | transition: 0.5s ease-in-out;
116 | }
117 |
118 | .container .swiper_card:hover .content .text a {
119 | background-color: var(--bg-gray);
120 | color: var(--clr);
121 | }
--------------------------------------------------------------------------------
/src/User/pages/Projects/Projects.jsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from "react";
2 | import { motion } from "framer-motion";
3 | import { MainHeading } from "../../components";
4 | import ProjectCard from "./Project"; // Import your ProjectCard component
5 | import { useDispatch, useSelector } from "react-redux";
6 | import { getProjects } from "../../../redux/actions/project";
7 | import Pagination from "@mui/material/Pagination";
8 | import './pagination.css'
9 |
10 | const Projects = () => {
11 | ////////////////////////////// VARIABLES //////////////////////////////////////
12 | const dispatch = useDispatch();
13 | const { projects } = useSelector((state) => state.project);
14 | const projectsPerPage = 9; // Number of projects per page
15 | const [currentPage, setCurrentPage] = useState(1);
16 |
17 | ////////////////////////////// STATES /////////////////////////////////////////
18 |
19 | ////////////////////////////// USE EFFECTS ////////////////////////////////////
20 | useEffect(() => {
21 | dispatch(getProjects());
22 | }, []);
23 |
24 | ////////////////////////////// FUNCTIONS ///////////////////////////////////////
25 | const handlePageChange = (event, page) => {
26 | setCurrentPage(page);
27 | };
28 |
29 | const indexOfLastProject = currentPage * projectsPerPage;
30 | const indexOfFirstProject = indexOfLastProject - projectsPerPage;
31 | const currentProjects = projects.slice(
32 | indexOfFirstProject,
33 | indexOfLastProject
34 | );
35 |
36 | return (
37 |
44 |
45 |
50 |
51 |
52 |
53 |
54 |
55 | {currentProjects.map((project, index) => (
56 |
57 | ))}
58 |
59 | {
60 | projects.length > projectsPerPage &&
61 |
68 | }
69 |
70 |
71 |
72 | );
73 | };
74 |
75 | export default Projects;
76 |
--------------------------------------------------------------------------------
/src/utils/Components.jsx:
--------------------------------------------------------------------------------
1 | import { Camera, Clear } from '@mui/icons-material'
2 | import { CircularProgress } from '@mui/material'
3 | import { useRef, useState } from 'react'
4 | import { deleteImage, uploadImage } from '../redux/actions/general'
5 | import { useDispatch, useSelector } from 'react-redux'
6 |
7 | export const Error = ({ error }) => {
8 | return (
9 |
12 | )
13 | }
14 |
15 |
16 | export const Loading = ({ title, color }) => {
17 | return (
18 |
19 |
20 |
{title || 'Loading...'}
21 |
22 | )
23 | }
24 |
25 |
26 |
27 | export const Upload = ({ image }) => {
28 |
29 | const dispatch = useDispatch()
30 | const lastSlashIndex = image?.lastIndexOf('/');
31 | const filename = image?.substring(lastSlashIndex + 1);
32 | const imageRef = useRef(null)
33 |
34 |
35 | const { isFetching } = useSelector(state => state.general)
36 |
37 | const handleUploadImage = (e) => {
38 | const image = e.target.files[0]
39 | const formData = new FormData();
40 | formData.append('image', image);
41 | dispatch(uploadImage(formData));
42 |
43 | };
44 |
45 | const handleDelete = () => {
46 | dispatch(deleteImage(filename))
47 | }
48 |
49 | return (
50 | <>
51 | {
52 | isFetching
53 | ?
54 |
55 |
56 |
57 | :
58 | <>
59 | {
60 | image
61 | ?
62 |
63 |
64 |
65 |
66 | :
67 |
68 |
69 | imageRef.current.click()} className="flex flex-col justify-center items-center text-textGray " >
70 |
71 | Upload Image
72 |
73 |
74 | }
75 | >
76 | }
77 | >
78 | )
79 | }
--------------------------------------------------------------------------------
/src/Admin/Admin.jsx:
--------------------------------------------------------------------------------
1 | import { Routes, Route, Navigate } from "react-router-dom"
2 | import { Sidebar, Navbar } from "./components"
3 | import "react-datetime/css/react-datetime.css";
4 | import { Resumes, Services, Skills, Projects, Blogs, Testimonials, Freelancing, Contact, } from "./pages"
5 | import { useStateContext } from '../contexts/ContextProvider'
6 | import { motion } from 'framer-motion'
7 | import { useRef, useState, useEffect } from 'react'
8 |
9 | const Admin = () => {
10 |
11 | ////////////////////////////////////// VARIABLES ////////////////////////////////////
12 | const navbarMenuRef = useRef(null)
13 | const { showSidebar, setShowSidebar, windowSize, setWindowSize } = useStateContext()
14 |
15 | ////////////////////////////////////// VARIABLES ////////////////////////////////////
16 | const [showMenu, setShowMenu] = useState(false)
17 |
18 | ////////////////////////////////////// USE EFFECTS //////////////////////////////////
19 | useEffect(() => {
20 | function handleResize() {
21 | setWindowSize({ width: window.innerWidth, height: window.innerHeight })
22 | }
23 | window.addEventListener('resize', handleResize)
24 | return () => window.removeEventListener('resize', handleResize)
25 | }, [])
26 |
27 | useEffect(() => {
28 | if (windowSize.width < 786) {
29 | setShowSidebar(false)
30 | }
31 | }, [windowSize])
32 |
33 | ////////////////////////////////////// FUNCTIONS //////////////////////////////////
34 | const pageClick = (event) => {
35 | if (navbarMenuRef.current && !navbarMenuRef.current.contains(event.target)) {
36 | setShowMenu(false)
37 | }
38 | }
39 |
40 |
41 |
42 | return (
43 |
44 |
45 |
46 |
47 |
48 | {
49 | showSidebar &&
50 |
53 |
54 |
55 | }
56 |
57 |
58 | } />
59 | } />
60 | } />
61 | } />
62 | } />
63 | } />
64 | } />
65 | } />
66 | } />
67 |
68 |
69 |
70 |
71 |
72 | );
73 | };
74 |
75 | export default Admin;
76 |
--------------------------------------------------------------------------------
/src/Admin/pages/Skills/Skills.jsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from "react"
2 | import { useDispatch, useSelector } from 'react-redux'
3 | import { Heading, Error, Table } from "../../components"
4 | import { Loading } from '../../../utils/Components'
5 | import { getSkills } from "../../../redux/actions/skill"
6 | import Create from "./Create"
7 | import Update from "./Update"
8 | import Delete from "./Delete"
9 | import View from "./View"
10 | import { Delete as DeleteIcon, Edit, Visibility } from "@mui/icons-material"
11 | import { IconButton } from "@mui/material"
12 |
13 | const Skills = () => {
14 |
15 | ////////////////////////////// VARIABLES //////////////////////////////////////
16 | const dispatch = useDispatch()
17 | const { skills, isFetching, error } = useSelector(state => state.skill)
18 |
19 | const columns = [
20 | { field: '_id', headerName: 'ID', width: 120 },
21 | { field: 'skill', headerName: 'Skill', width: 150, },
22 | { field: 'percentage', headerName: 'Percentage', width: 150, },
23 | {
24 | field: 'action', headerName: 'Action', width: 160, renderCell: (params) => (
25 |
26 | { setOpenViewModal(true); setCurrentSkill(params.row) }} >
27 | { setOpenUpdateModal(true); setCurrentSkill(params.row) }} >
28 | { setOpenDeleteModal(true); setCurrentSkill(params.row) }} >
29 |
30 | )
31 | },
32 | ];
33 |
34 | ////////////////////////////// STATES /////////////////////////////////////////
35 | const [openCreateModal, setOpenCreateModal] = useState(false)
36 | const [openViewModal, setOpenViewModal] = useState(false)
37 | const [openUpdateModal, setOpenUpdateModal] = useState(false)
38 | const [openDeleteModal, setOpenDeleteModal] = useState(false)
39 | const [currentSkill, setCurrentSkill] = useState(null)
40 |
41 | ////////////////////////////// USE EFFECTS ////////////////////////////////////
42 | useEffect(() => {
43 | dispatch(getSkills())
44 | }, [])
45 |
46 |
47 | ////////////////////////////// FUNCTIONS ///////////////////////////////////////
48 |
49 | if (isFetching) return
50 | if (error) return
51 |
52 | return (
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
73 |
74 |
75 |
76 | )
77 | }
78 |
79 | export default Skills
--------------------------------------------------------------------------------
/src/Admin/pages/Freelancing/View.jsx:
--------------------------------------------------------------------------------
1 | import { BrokenImage, Close } from "@mui/icons-material";
2 | import { Modal } from "@mui/material";
3 | import React from "react";
4 |
5 | const View = ({ card, open, setOpen }) => {
6 |
7 | ////////////////////////////// VARIABLES //////////////////////////////////////
8 |
9 | ////////////////////////////// STATES /////////////////////////////////////////
10 |
11 | ////////////////////////////// USE EFFECTS ////////////////////////////////////
12 |
13 | ////////////////////////////// FUNCTIONS ///////////////////////////////////////
14 |
15 |
16 | return (
17 | setOpen(false)} className='w-screen h-screen flex justify-center items-center ' >
18 |
19 |
20 |
setOpen(false)} className="absolute top-[5px] right-[5px] rounded-full p-[2px] bg-black " >
21 |
22 |
23 | {
24 | card?.image
25 | ?
26 |
27 | :
28 |
29 | }
30 |
31 |
Title:
32 |
33 | {card?.title}
34 |
35 |
36 |
37 |
Description:
38 |
39 | {card?.description}
40 |
41 |
42 |
43 |
Link:
44 |
45 | {card?.link}
46 |
47 |
48 |
49 |
Parent:
50 |
51 | {card?.parent}
52 |
53 |
54 |
55 |
Category:
56 |
57 | {card?.category}
58 |
59 |
60 |
61 |
62 |
63 | )
64 | }
65 |
66 | export default View;
--------------------------------------------------------------------------------
/src/Admin/pages/Resumes/Resumes.jsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from "react"
2 | import { useDispatch, useSelector } from 'react-redux'
3 | import { Heading, Error, Table } from "../../components"
4 | import { Loading } from '../../../utils/Components'
5 | import { getResumes } from "../../../redux/actions/resume"
6 | import Create from "./Create"
7 | import Update from "./Update"
8 | import Delete from "./Delete"
9 | import View from "./View"
10 | import { Delete as DeleteIcon, Edit, Visibility } from "@mui/icons-material"
11 | import { IconButton } from "@mui/material"
12 |
13 | const Resumes = () => {
14 |
15 | ////////////////////////////// VARIABLES //////////////////////////////////////
16 | const dispatch = useDispatch()
17 | const { resumes, isFetching, error } = useSelector(state => state.resume)
18 | const columns = [
19 | { field: '_id', headerName: 'ID', width: 90 },
20 | { field: 'title', headerName: 'Title', width: 250, },
21 | { field: 'subTitle', headerName: 'Sub Title', width: 200, },
22 | { field: 'detail', headerName: 'Detail', width: 300, },
23 | {
24 | field: 'action', headerName: 'Action', width: 160, renderCell: (params) => (
25 |
26 | { setOpenViewModal(true); setCurrentResume(params.row) }} >
27 | { setOpenUpdateModal(true); setCurrentResume(params.row) }} >
28 | { setOpenDeleteModal(true); setCurrentResume(params.row) }} >
29 |
30 | )
31 | },
32 | ];
33 |
34 | ////////////////////////////// STATES /////////////////////////////////////////
35 | const [openCreateModal, setOpenCreateModal] = useState(false)
36 | const [openViewModal, setOpenViewModal] = useState(false)
37 | const [openUpdateModal, setOpenUpdateModal] = useState(false)
38 | const [openDeleteModal, setOpenDeleteModal] = useState(false)
39 | const [currentResume, setCurrentResume] = useState(null)
40 |
41 | ////////////////////////////// USE EFFECTS ////////////////////////////////////
42 | useEffect(() => {
43 | dispatch(getResumes())
44 | }, [])
45 |
46 |
47 | ////////////////////////////// FUNCTIONS ///////////////////////////////////////
48 |
49 | if (isFetching) return
50 | if (error) return
51 |
52 | return (
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
73 |
74 |
75 |
76 | )
77 | }
78 |
79 | export default Resumes
--------------------------------------------------------------------------------
/src/User/User.jsx:
--------------------------------------------------------------------------------
1 | // for top horizontal scroll bar
2 | import { motion, useScroll, useSpring } from "framer-motion";
3 | // import { useFollowPointer } from "./utils/pointer";
4 | import { useDispatch, useSelector } from 'react-redux'
5 | import { useEffect, useRef, useState } from 'react'
6 | import { Routes, Route, Navigate } from "react-router-dom";
7 | import { Navbar, NavigationDots, SocialLinks } from "./components"
8 | import { Home, About, Resume, Services, Skills, Projects, Blogs, Freelancing, Testimonials, Contact, Footer, Account, Register, Login } from "./pages"
9 | import 'react-phone-number-input/style.css'
10 |
11 | const User = () => {
12 |
13 | ////////////////////////////////////// VARIABLES ////////////////////////////////////
14 | const dispatch = useDispatch()
15 | const navbarMenuRef = useRef(null)
16 |
17 | ////////////////////////////////////// STATES //////////////////////////////////////
18 | const [showMenu, setShowMenu] = useState(false)
19 |
20 | ////////////////////////////////////// USE EFFECTS /////////////////////////////////
21 | useEffect(() => {
22 |
23 | }, [])
24 |
25 | ////////////////////////////////////// FUNCTIONS ///////////////////////////////////
26 | const pageClick = () => {
27 | if (navbarMenuRef.current && !navbarMenuRef.current.contains(event.target)) {
28 | setShowMenu(false)
29 | }
30 | }
31 |
32 | // for top horizontal scroll bar
33 | const { scrollYProgress } = useScroll();
34 | const scaleX = useSpring(scrollYProgress, {
35 | stiffness: 100,
36 | damping: 30,
37 | restDelta: 0.001
38 | });
39 |
40 |
41 | const App = () => (
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 | {/*
*/}
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 | )
64 |
65 |
66 | return (
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | } />
76 | } />
77 | } />
78 | } />
79 | } />
80 |
81 |
82 |
83 |
84 | );
85 | };
86 |
87 | export default User;
--------------------------------------------------------------------------------
/src/Admin/pages/Services/Services.jsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from "react"
2 | import { useDispatch, useSelector } from 'react-redux'
3 | import { Heading, Error, Table } from "../../components"
4 | import { Loading } from '../../../utils/Components'
5 | import { getServices } from "../../../redux/actions/service"
6 | import Create from "./Create"
7 | import Update from "./Update"
8 | import Delete from "./Delete"
9 | import View from "./View"
10 | import { Delete as DeleteIcon, Edit, Visibility } from "@mui/icons-material"
11 | import { IconButton } from "@mui/material"
12 |
13 | const Services = () => {
14 |
15 | ////////////////////////////// VARIABLES //////////////////////////////////////
16 | const dispatch = useDispatch()
17 | const { services, isFetching, error } = useSelector(state => state.service)
18 | const columns = [
19 | { field: '_id', headerName: 'ID', width: 90 },
20 | { field: 'service', headerName: 'Service', width: 150, },
21 | { field: 'link', headerName: 'Link', width: 100, },
22 | { field: 'icon', headerName: 'Icon', width: 100, },
23 | {
24 | field: 'action', headerName: 'Action', width: 160, renderCell: (params) => (
25 |
26 | { setOpenViewModal(true); setCurrentService(params.row) }} >
27 | { setOpenUpdateModal(true); setCurrentService(params.row) }} >
28 | { setOpenDeleteModal(true); setCurrentService(params.row) }} >
29 |
30 | )
31 | },
32 | ];
33 |
34 | ////////////////////////////// STATES /////////////////////////////////////////
35 | const [openCreateModal, setOpenCreateModal] = useState(false)
36 | const [openViewModal, setOpenViewModal] = useState(false)
37 | const [openUpdateModal, setOpenUpdateModal] = useState(false)
38 | const [openDeleteModal, setOpenDeleteModal] = useState(false)
39 | const [currentService, setCurrentService] = useState(null)
40 |
41 | ////////////////////////////// USE EFFECTS ////////////////////////////////////
42 | useEffect(() => {
43 | dispatch(getServices())
44 | }, [])
45 |
46 |
47 | ////////////////////////////// FUNCTIONS ///////////////////////////////////////
48 |
49 | if (isFetching) return
50 | if (error) return
51 |
52 | return (
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
73 |
74 |
75 |
76 | )
77 | }
78 |
79 | export default Services
--------------------------------------------------------------------------------
/src/Admin/pages/Projects/View.jsx:
--------------------------------------------------------------------------------
1 | import { BrokenImage, Close } from "@mui/icons-material";
2 | import { Modal } from "@mui/material";
3 | import React from "react";
4 |
5 | const View = ({ project, open, setOpen }) => {
6 |
7 | ////////////////////////////// VARIABLES //////////////////////////////////////
8 |
9 | ////////////////////////////// STATES /////////////////////////////////////////
10 |
11 | ////////////////////////////// USE EFFECTS ////////////////////////////////////
12 |
13 | ////////////////////////////// FUNCTIONS ///////////////////////////////////////
14 |
15 |
16 | return (
17 | setOpen(false)} className='w-screen h-screen flex justify-center items-center ' >
18 |
19 |
20 |
setOpen(false)} className="absolute top-[5px] right-[5px] rounded-full p-[2px] bg-black " >
21 |
22 |
23 | {
24 | project?.image
25 | ?
26 |
27 | :
28 |
29 | }
30 |
31 |
Title:
32 |
33 | {project?.title}
34 |
35 |
36 |
37 |
Detail:
38 |
39 | {project?.detail}
40 |
41 |
42 |
43 |
Link:
44 |
45 | {project?.link}
46 |
47 |
48 |
49 |
Github:
50 |
51 | {project?.github}
52 |
53 |
54 |
55 |
Icon:
56 |
57 | {project?.technologies.map((tech, index) => #{tech} )}
58 |
59 |
60 |
61 |
62 |
63 | )
64 | }
65 |
66 | export default View;
--------------------------------------------------------------------------------
/src/Admin/components/Slider.jsx:
--------------------------------------------------------------------------------
1 | import { Loading } from './'
2 | import FileBase64 from 'react-file-base64'
3 | import { ArrowLeft, Camera, ArrowRight, Add, Delete } from '@mui/icons-material'
4 | import { useState, useEffect, useRef } from 'react'
5 |
6 | const Slider = ({ images, deleteImageFunc, addImageFunc, sliderInModal, subFreelancingCardId }) => {
7 |
8 | const imagesLength = images.length
9 | ////////////////////////////// VARIABLES //////////////////////////////////////
10 | const fileBase64Ref = useRef(null)
11 |
12 | ////////////////////////////// STATES /////////////////////////////////////////
13 | const [currentImageIndex, setCurrentImageIndex] = useState(0)
14 |
15 | ////////////////////////////// USE EFFECTS ////////////////////////////////////
16 |
17 |
18 | ////////////////////////////// FUNCTIONS ///////////////////////////////////////
19 | const nextImage = () => {
20 | const isLastImage = currentImageIndex == imagesLength - 1
21 | isLastImage
22 | ?
23 | setCurrentImageIndex(0)
24 | :
25 | setCurrentImageIndex(currentImageIndex + 1)
26 | }
27 |
28 | const prevImage = () => {
29 | const isFirstImage = currentImageIndex == 0
30 | isFirstImage
31 | ?
32 | setCurrentImageIndex(imagesLength - 1)
33 | :
34 | setCurrentImageIndex(currentImageIndex - 1)
35 | }
36 |
37 | const handleImageButtonClick = () => {
38 | fileBase64Ref.current.querySelector('input[type="file"]').click();
39 | }
40 |
41 | const addImage = (files) => {
42 | subFreelancingCardId
43 | ?
44 | addImageFunc(subFreelancingCardId, files)
45 | :
46 | addImageFunc(files)
47 |
48 | }
49 | const deleteImage = () => {
50 | subFreelancingCardId
51 | ?
52 | deleteImageFunc(subFreelancingCardId, images[currentImageIndex]._id)
53 | :
54 | deleteImageFunc(images[currentImageIndex]._id)
55 | }
56 |
57 | return (
58 |
59 | {images.length > 1 &&
}
60 |
61 | {
62 | sliderInModal &&
63 | <>
64 |
65 |
handleImageButtonClick()} className=" flex flex-col justify-center items-center text-white " >
66 |
67 |
68 |
addImage(filesArr)} />
69 |
70 |
71 | >
72 | }
73 |
74 |
75 | {images.length > 1 &&
}
76 |
77 | )
78 | }
79 | export default Slider;
--------------------------------------------------------------------------------
/src/redux/api/index.js:
--------------------------------------------------------------------------------
1 | import axios from "axios";
2 | import { baseURL } from '../../constant'
3 | import Cookies from "js-cookie";
4 |
5 | const API = axios.create({ baseURL })
6 |
7 | axios.interceptors.request.use(req => {
8 | // const tokenString = Cookies.get('iamnauman_profile')
9 | // if (tokenString) {
10 | // const parsedToken = JSON.parse(tokenString)
11 | // req.headers.authtoken = parsedToken
12 | // }
13 | return req
14 | })
15 |
16 |
17 | // GENERAL
18 | export const uploadImage = (formData) => API.post(`/upload_image`, formData)
19 | export const deleteImage = (filename) => API.delete(`/delete_image/${filename}`)
20 |
21 | // AUTH
22 | export const register = (userData) => API.post(`/auth/register`, userData)
23 | export const login = (userData) => API.put(`/auth/login`, userData)
24 | export const logout = () => API.put(`/logout`)
25 | export const getUsers = () => API.get(`/user/get`)
26 |
27 |
28 | // BLOG
29 | export const getBlogs = () => API.get(`/blog/get`)
30 | export const createBlog = (blogData) => API.post(`/blog/create`, blogData)
31 | export const updateBlog = (blogId, blogData) => API.put(`/blog/update/${blogId}`, blogData)
32 | export const deleteBlog = (blogId) => API.delete(`/blog/delete/${blogId}`)
33 |
34 |
35 | // CONTACT
36 | export const getContactUsers = () => API.get(`/contact/get`)
37 | export const formSubmit = (contactData) => API.post(`/contact/submit`, contactData)
38 |
39 |
40 | // FREELANCING
41 | export const getCards = () => API.get(`/freelancing/get`)
42 | export const createCard = (cardData) => API.post(`/freelancing/create`, cardData)
43 | export const updateCard = (cardId, cardData) => API.put(`/freelancing/update/${cardId}`, cardData)
44 | export const deleteCard = (cardId) => API.delete(`/freelancing/delete/${cardId}`)
45 |
46 |
47 | // PROJECT
48 | export const getProjects = () => API.get(`/project/get`)
49 | export const createProject = (projectData) => API.post(`/project/create`, projectData)
50 | export const updateProject = (projectId, projectData) => API.put(`/project/update/${projectId}`, projectData)
51 | export const deleteProject = (projectId) => API.delete(`/project/delete/${projectId}`)
52 |
53 |
54 | // RESUME
55 | export const getResumes = () => API.get(`/resume/get`)
56 | export const createResume = (resumeData) => API.post(`/resume/create`, resumeData)
57 | export const updateResume = (resumeId, resumeData) => API.put(`/resume/update/${resumeId}`, resumeData)
58 | export const deleteResume = (resumeId) => API.delete(`/resume/delete/${resumeId}`)
59 |
60 |
61 | // SERVICE
62 | export const getServices = () => API.get(`/service/get`)
63 | export const createService = (serviceData) => API.post(`/service/create`, serviceData)
64 | export const updateService = (serviceId, serviceData) => API.put(`/service/update/${serviceId}`, serviceData)
65 | export const deleteService = (serviceId) => API.delete(`/service/delete/${serviceId}`)
66 |
67 |
68 | // SKILL
69 | export const getSkills = () => API.get(`/skill/get`)
70 | export const createSkill = (skillData) => API.post(`/skill/create`, skillData)
71 | export const updateSkill = (skillId, skillData) => API.put(`/skill/update/${skillId}`, skillData)
72 | export const deleteSkill = (skillId) => API.delete(`/skill/delete/${skillId}`)
73 |
74 |
75 | // TESTIMONIALS
76 | export const getTestimonials = () => API.get(`/testimonial/get`)
77 | export const createTestimonial = (testimonialData) => API.post(`/testimonial/create`, testimonialData)
78 | export const updateTestimonial = (testimonialId, testimonialData) => API.put(`/testimonial/update/${testimonialId}`, testimonialData)
79 | export const deleteTestimonial = (testimonialId) => API.delete(`/testimonial/delete/${testimonialId}`)
--------------------------------------------------------------------------------
/src/Admin/pages/Blogs/Blogs.jsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from "react"
2 | import { useDispatch, useSelector } from 'react-redux'
3 | import { Heading, Error, Table } from "../../components"
4 | import { Loading } from '../../../utils/Components'
5 | import { getBlogs } from "../../../redux/actions/blog"
6 | import Create from "./Create"
7 | import Update from "./Update"
8 | import Delete from "./Delete"
9 | import View from "./View"
10 | import { Delete as DeleteIcon, Edit, Visibility } from "@mui/icons-material"
11 | import { IconButton } from "@mui/material"
12 |
13 | const Blogs = () => {
14 |
15 | ////////////////////////////// VARIABLES //////////////////////////////////////
16 | const dispatch = useDispatch()
17 | const { blogs, isFetching, error } = useSelector(state => state.blog)
18 |
19 | const columns = [
20 | { field: '_id', headerName: 'ID', width: 90 },
21 | { field: 'image', headerName: 'Image', width: 150, renderCell: (params) => ( ) },
22 | { field: 'name', headerName: 'Name', width: 100, },
23 | { field: 'title', headerName: 'Title', width: 100, },
24 | { field: 'description', headerName: 'Description', width: 100, },
25 | {
26 | field: 'action', headerName: 'Action', width: 160, renderCell: (params) => (
27 |
28 | { setOpenViewModal(true); setCurrentBlog(params.row) }} >
29 | { setOpenUpdateModal(true); setCurrentBlog(params.row) }} >
30 | { setOpenDeleteModal(true); setCurrentBlog(params.row) }} >
31 |
32 | )
33 | },
34 | ];
35 |
36 | ////////////////////////////// STATES /////////////////////////////////////////
37 | const [openCreateModal, setOpenCreateModal] = useState(false)
38 | const [openViewModal, setOpenViewModal] = useState(false)
39 | const [openUpdateModal, setOpenUpdateModal] = useState(false)
40 | const [openDeleteModal, setOpenDeleteModal] = useState(false)
41 | const [currentBlog, setCurrentBlog] = useState(null)
42 |
43 | ////////////////////////////// USE EFFECTS ////////////////////////////////////
44 | useEffect(() => {
45 | dispatch(getBlogs())
46 | }, [])
47 |
48 |
49 | ////////////////////////////// FUNCTIONS ///////////////////////////////////////
50 |
51 | if (isFetching) return
52 | if (error) return
53 |
54 | return (
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
75 |
76 |
77 |
78 | )
79 | }
80 |
81 | export default Blogs
--------------------------------------------------------------------------------
/src/Admin/pages/Skills/Create.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react'
2 | import { createSkill } from '../../../redux/actions/skill'
3 | import { useDispatch } from 'react-redux'
4 | import { Close } from '@mui/icons-material'
5 | import { Modal } from '@mui/material'
6 | import TextareaAutosize from 'react-textarea-autosize'
7 | import { DropDown } from '../../components'
8 | import { icons } from '../../../data'
9 |
10 | const Create = ({ open, setOpen }) => {
11 |
12 | /////////////////////////////////////// VARIABLES /////////////////////////////////////
13 | const dispatch = useDispatch()
14 |
15 | /////////////////////////////////////// STATES /////////////////////////////////////
16 | const [skillData, setSkillData] = useState({ skill: '', percentage: '' })
17 |
18 | /////////////////////////////////////// FUNCTIONS /////////////////////////////////////
19 | const handleCreateSkill = () => {
20 | dispatch(createSkill(skillData, setOpen))
21 | }
22 | const handleChange = (e) => {
23 | setSkillData({ ...skillData, [e.target.name]: e.target.value })
24 | }
25 |
26 |
27 | return (
28 | setOpen(false)} className='w-screen h-screen flex justify-center items-center ' >
29 |
30 |
31 |
32 |
Create Skill
33 |
34 |
35 |
36 |
37 |
Skill:
38 |
47 |
48 |
49 |
Percentage:
50 |
59 |
60 |
61 | setOpen(false)} className="bg-[#0d0d0d] text-white rounded-[4px] px-[6px] py-[4px]">
62 | Close
63 |
64 |
65 | Create
66 |
67 |
68 |
69 |
70 |
71 |
72 | )
73 | }
74 |
75 | export default Create
--------------------------------------------------------------------------------
/src/User/pages/Auth/Register.jsx:
--------------------------------------------------------------------------------
1 | import { Person } from '@mui/icons-material'
2 | import React, { useState } from 'react'
3 | import { Input } from '../../components'
4 | import { register } from '../../../redux/actions/user'
5 | import { Link, useNavigate } from 'react-router-dom'
6 | import { useDispatch, useSelector } from 'react-redux'
7 |
8 | const Register = () => {
9 |
10 | //////////////////////////////////// STATES //////////////////////////////////////////
11 | const initialUserState = { name: '', email: '', phone: '', password: '' }
12 | const [userData, setUserData] = useState(initialUserState)
13 | const navigate = useNavigate()
14 | const dispatch = useDispatch()
15 | const { isFetching, error } = useSelector(state => state.user)
16 |
17 |
18 | const handleRegister = () => {
19 | dispatch(register(userData, navigate))
20 | }
21 |
22 |
23 | return (
24 |
25 |
26 |
27 |
30 |
31 |
32 |
40 |
48 |
56 |
65 |
66 |
67 |
68 |
69 |
70 | {isFetching ? 'Submitting...' : 'Register'}
71 |
72 |
73 | Already have account?
74 | Login here
75 |
76 |
77 |
78 |
79 | {error &&
{error}
}
80 |
81 |
82 |
83 | )
84 | }
85 |
86 | export default Register
--------------------------------------------------------------------------------
/src/Admin/pages/Testimonials/Testimonials.jsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from "react"
2 | import { useDispatch, useSelector } from 'react-redux'
3 | import { Heading, Error, Table } from "../../components"
4 | import { Loading } from '../../../utils/Components'
5 | import { getTestimonials } from "../../../redux/actions/testimonial"
6 | import Create from "./Create"
7 | import Update from "./Update"
8 | import Delete from "./Delete"
9 | import View from "./View"
10 | import { Delete as DeleteIcon, Edit, Visibility } from "@mui/icons-material"
11 | import { IconButton } from "@mui/material"
12 |
13 | const Testimonials = () => {
14 |
15 | ////////////////////////////// VARIABLES //////////////////////////////////////
16 | const dispatch = useDispatch()
17 | const { testimonials, isFetching, error } = useSelector(state => state.testimonial)
18 |
19 | const columns = [
20 | { field: '_id', headerName: 'ID', width: 90 },
21 | { field: 'image', headerName: 'Image', width: 150, renderCell: (params) => ( ) },
22 | { field: 'name', headerName: 'Name', width: 100, },
23 | { field: 'designation', headerName: 'Designation', width: 100, },
24 | { field: 'content', headerName: 'Content', width: 100, },
25 | {
26 | field: 'action', headerName: 'Action', width: 160, renderCell: (params) => (
27 |
28 | { setOpenViewModal(true); setCurrentTestimonial(params.row) }} >
29 | { setOpenUpdateModal(true); setCurrentTestimonial(params.row) }} >
30 | { setOpenDeleteModal(true); setCurrentTestimonial(params.row) }} >
31 |
32 | )
33 | },
34 | ];
35 |
36 | ////////////////////////////// STATES /////////////////////////////////////////
37 | const [openCreateModal, setOpenCreateModal] = useState(false)
38 | const [openViewModal, setOpenViewModal] = useState(false)
39 | const [openUpdateModal, setOpenUpdateModal] = useState(false)
40 | const [openDeleteModal, setOpenDeleteModal] = useState(false)
41 | const [currentTestimonial, setCurrentTestimonial] = useState(null)
42 |
43 | ////////////////////////////// USE EFFECTS ////////////////////////////////////
44 | useEffect(() => {
45 | dispatch(getTestimonials())
46 | }, [])
47 |
48 |
49 | ////////////////////////////// FUNCTIONS ///////////////////////////////////////
50 |
51 | if (isFetching) return
52 | if (error) return
53 |
54 | return (
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
75 |
76 |
77 |
78 | )
79 | }
80 |
81 | export default Testimonials
--------------------------------------------------------------------------------
/src/Admin/pages/Freelancing/Freelancing.jsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from "react"
2 | import { useDispatch, useSelector } from 'react-redux'
3 | import { Heading, Error, Table } from "../../components"
4 | import { Loading } from '../../../utils/Components'
5 | import { getCards } from "../../../redux/actions/freelancing"
6 | import Create from "./Create"
7 | import Update from "./Update"
8 | import Delete from "./Delete"
9 | import View from "./View"
10 | import { Delete as DeleteIcon, Edit, Visibility } from "@mui/icons-material"
11 | import { IconButton } from "@mui/material"
12 |
13 | const Freelancing = () => {
14 |
15 | ////////////////////////////// VARIABLES //////////////////////////////////////
16 | const dispatch = useDispatch()
17 | const { cards, isFetching, error } = useSelector(state => state.freelancing)
18 | const columns = [
19 | { field: '_id', headerName: 'ID', width: 90 },
20 | { field: 'image', headerName: 'Image', width: 150, renderCell: (params) => ( ) },
21 | { field: 'title', headerName: 'Title', width: 150, },
22 | { field: 'description', headerName: 'Descrition', width: 200, },
23 | { field: 'link', headerName: 'Link', width: 100, },
24 | { field: 'parent', headerName: 'Parent', width: 100, },
25 | { field: 'category', headerName: 'Category', width: 100, },
26 | {
27 | field: 'action', headerName: 'Action', width: 160, renderCell: (params) => (
28 |
29 | { setOpenViewModal(true); setCurrentCard(params.row) }} >
30 | { setOpenUpdateModal(true); setCurrentCard(params.row) }} >
31 | { setOpenDeleteModal(true); setCurrentCard(params.row) }} >
32 |
33 | )
34 | },
35 | ];
36 |
37 | ////////////////////////////// STATES /////////////////////////////////////////
38 | const [openCreateModal, setOpenCreateModal] = useState(false)
39 | const [openViewModal, setOpenViewModal] = useState(false)
40 | const [openUpdateModal, setOpenUpdateModal] = useState(false)
41 | const [openDeleteModal, setOpenDeleteModal] = useState(false)
42 | const [currentCard, setCurrentCard] = useState(null)
43 |
44 | ////////////////////////////// USE EFFECTS ////////////////////////////////////
45 | useEffect(() => {
46 | dispatch(getCards())
47 | }, [])
48 |
49 | ////////////////////////////// FUNCTIONS ///////////////////////////////////////
50 |
51 | if (isFetching) return
52 | if (error) return
53 |
54 | return (
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
75 |
76 |
77 |
78 | )
79 | }
80 |
81 | export default Freelancing
--------------------------------------------------------------------------------
/src/Admin/components/DropDown.jsx:
--------------------------------------------------------------------------------
1 | import { useState } from 'react';
2 | import { ArrowDropDown } from '@mui/icons-material';
3 |
4 | const DropDown = ({ icons, item, setItem }) => {
5 |
6 | const [inputText, setInputText] = useState(item?.icon);
7 | const [selectedIcon, setSelectedIcon] = useState(icons.find(icon => icon.name == item?.icon) || null);
8 | const [showMenu, setShowMenu] = useState(false);
9 | const [filteredIcons, setFilteredIcons] = useState(icons);
10 |
11 | const handleInputChange = (e) => {
12 | const inputValue = e.target.value.toLowerCase();
13 | const filtered = icons.filter(icon => icon.name.toLowerCase().includes(inputValue));
14 | setFilteredIcons(filtered)
15 | setSelectedIcon(filtered.length === 1 ? filtered[0] : null);
16 | setInputText(inputValue);
17 | setShowMenu(true);
18 | };
19 |
20 | const handleSelectIcon = (icon) => {
21 | setItem({ ...item, icon: icon.name })
22 | setSelectedIcon(icon);
23 | setInputText(icon.name);
24 | setShowMenu(false);
25 | };
26 |
27 | const handleInputClick = () => {
28 | setShowMenu(true);
29 | };
30 |
31 | const toggleShowMenu = () => {
32 | setShowMenu(pre => !pre)
33 | }
34 |
35 | return (
36 |
37 |
38 | {
39 | selectedIcon?.icon &&
40 |
41 | }
42 |
50 |
51 |
52 |
53 |
54 | {showMenu && (
55 |
56 | {selectedIcon ? (
57 |
{ handleSelectIcon(null) }} className="px-3 py-2 cursor-pointer hover:bg-orange-200">
58 | Clear selection
59 |
60 | ) : null}
61 | {selectedIcon || filteredIcons.length === 0 ? null : (
62 |
63 | Select an icon:
64 |
65 | )}
66 |
67 | {filteredIcons.map((icon, index) => (
68 |
handleSelectIcon(icon)}
72 | >
73 |
74 | {icon.name}
75 |
76 | ))}
77 |
78 |
79 | )}
80 |
81 | );
82 | };
83 |
84 | export default DropDown;
--------------------------------------------------------------------------------
/src/User/pages/Projects/Project.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react'
2 | import { project1 } from '../../../assets'
3 | import { IconButton, Modal, Tooltip } from '@mui/material'
4 | import { Close, GitHub, Visibility } from '@mui/icons-material'
5 |
6 | const Project = ({ project }) => {
7 |
8 | const [openModal, setOpenModal] = useState(false)
9 |
10 |
11 | return (
12 | <>
13 | setOpenModal(true)} className='md:w-[32%] sm:w-full w-full hover:scale-105 cursor-pointer transition-all h-[15rem] bg-lightGray rounded-[8px] relative border-[1px] border-orange overflow-hidden ' >
14 |
15 |
16 |
17 |
18 |
19 | {project.title}
20 |
21 |
22 |
23 |
24 |
25 |
26 | setOpenModal(false)}>
27 |
28 |
29 |
setOpenModal(false)} style={{ position: 'absolute' }} className='absolute top-[2px] right-[2px] ' >
30 |
31 |
32 |
33 |
34 |
35 |
36 |
{project.title}
37 |
{project.detail}
38 |
39 |
51 |
{project.technologies.map(tech => `#${tech} `)}
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 | >
60 | )
61 | }
62 |
63 | export default Project
--------------------------------------------------------------------------------