├── jsconfig.json ├── next.config.js ├── postcss.config.js ├── src ├── app │ ├── favicon.ico │ ├── layout.js │ ├── api │ │ ├── home │ │ │ ├── get │ │ │ │ └── route.js │ │ │ ├── add │ │ │ │ └── route.js │ │ │ └── update │ │ │ │ └── route.js │ │ ├── about │ │ │ ├── get │ │ │ │ └── route.js │ │ │ ├── add │ │ │ │ └── route.js │ │ │ └── update │ │ │ │ └── route.js │ │ ├── contact │ │ │ ├── get │ │ │ │ └── route.js │ │ │ └── add │ │ │ │ └── route.js │ │ ├── project │ │ │ ├── get │ │ │ │ └── route.js │ │ │ └── add │ │ │ │ └── route.js │ │ ├── education │ │ │ ├── get │ │ │ │ └── route.js │ │ │ └── add │ │ │ │ └── route.js │ │ ├── experience │ │ │ ├── get │ │ │ │ └── route.js │ │ │ └── add │ │ │ │ └── route.js │ │ └── login │ │ │ └── route.js │ ├── page.js │ ├── globals.css │ └── admin │ │ └── page.js ├── assets │ ├── ai-image.png │ └── about-image.png ├── models │ ├── Home.js │ ├── User.js │ ├── Contact.js │ ├── Education.js │ ├── Project.js │ ├── About.js │ └── Experience.js ├── database │ └── index.js ├── components │ ├── client-view │ │ ├── common-layout │ │ │ └── index.js │ │ ├── animation-wrapper │ │ │ └── index.js │ │ ├── navbar │ │ │ └── index.js │ │ ├── project │ │ │ └── index.js │ │ ├── home │ │ │ └── index.js │ │ ├── about │ │ │ └── index.js │ │ ├── contact │ │ │ └── index.js │ │ └── experience │ │ │ └── index.js │ └── admin-view │ │ ├── contact │ │ └── index.js │ │ ├── form-controls │ │ └── index.js │ │ ├── login │ │ └── index.js │ │ ├── home │ │ └── index.js │ │ ├── about │ │ └── index.js │ │ ├── education │ │ └── index.js │ │ ├── project │ │ └── index.js │ │ └── experience │ │ └── index.js └── services │ └── index.js ├── .gitignore ├── public ├── vercel.svg └── next.svg ├── package.json ├── README.md └── tailwind.config.js /jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "paths": { 4 | "@/*": ["./src/*"] 5 | } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /next.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = {} 3 | 4 | module.exports = nextConfig 5 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /src/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sangammukherjee/NextJS-Fullstack-Portfolio-2023/HEAD/src/app/favicon.ico -------------------------------------------------------------------------------- /src/assets/ai-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sangammukherjee/NextJS-Fullstack-Portfolio-2023/HEAD/src/assets/ai-image.png -------------------------------------------------------------------------------- /src/assets/about-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sangammukherjee/NextJS-Fullstack-Portfolio-2023/HEAD/src/assets/about-image.png -------------------------------------------------------------------------------- /src/models/Home.js: -------------------------------------------------------------------------------- 1 | import mongoose from "mongoose"; 2 | 3 | const HomeSchema = new mongoose.Schema( 4 | { 5 | heading: String, 6 | summary: String, 7 | }, 8 | { timestamps: true } 9 | ); 10 | 11 | const Home = mongoose.models.Home || mongoose.model("Home", HomeSchema); 12 | 13 | export default Home; 14 | -------------------------------------------------------------------------------- /src/models/User.js: -------------------------------------------------------------------------------- 1 | import mongoose from "mongoose"; 2 | 3 | const UserSchema = new mongoose.Schema( 4 | { 5 | username: String, 6 | password: String, 7 | }, 8 | { timestamps: true } 9 | ); 10 | 11 | const User = mongoose.models.User || mongoose.model("User", UserSchema); 12 | 13 | export default User; 14 | -------------------------------------------------------------------------------- /src/models/Contact.js: -------------------------------------------------------------------------------- 1 | import mongoose from "mongoose"; 2 | 3 | const ContactSchema = new mongoose.Schema({ 4 | name : String, 5 | email : String, 6 | message : String 7 | }, {timestamps : true}) 8 | 9 | const Contact = mongoose.models.Contacts || mongoose.model('Contacts', ContactSchema) 10 | 11 | export default Contact; -------------------------------------------------------------------------------- /src/database/index.js: -------------------------------------------------------------------------------- 1 | import mongoose from "mongoose"; 2 | 3 | export default async function connectToDB() { 4 | try { 5 | await mongoose.connect( 6 | "mongodb+srv://sangam:sangam2023@cluster0.7aauitj.mongodb.net/" 7 | ); 8 | console.log("Database connected successfully"); 9 | } catch (e) { 10 | console.log(e); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/models/Education.js: -------------------------------------------------------------------------------- 1 | import mongoose from "mongoose"; 2 | 3 | const EducationSchema = new mongoose.Schema( 4 | { 5 | degree: String, 6 | year: String, 7 | college: String, 8 | }, 9 | { timestamps: true } 10 | ); 11 | 12 | const Education = mongoose.models.Education || mongoose.model("Education", EducationSchema); 13 | 14 | export default Education; -------------------------------------------------------------------------------- /src/components/client-view/common-layout/index.js: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import { usePathname } from "next/navigation"; 3 | import Navbar from "../navbar"; 4 | 5 | export default function CommonLayout({ children }) { 6 | const pathName = usePathname(); 7 | return ( 8 | <> 9 | {pathName !== "/admin" ? : null} 10 | {children} 11 | 12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /src/models/Project.js: -------------------------------------------------------------------------------- 1 | import mongoose from "mongoose"; 2 | 3 | const ProjectSchema = new mongoose.Schema( 4 | { 5 | name: String, 6 | website: String, 7 | technologies: String, 8 | github: String, 9 | }, 10 | { timestamps: true } 11 | ); 12 | 13 | const Project = 14 | mongoose.models.Project || mongoose.model("Project", ProjectSchema); 15 | 16 | export default Project; 17 | -------------------------------------------------------------------------------- /src/models/About.js: -------------------------------------------------------------------------------- 1 | import mongoose from "mongoose"; 2 | 3 | const AboutSchema = new mongoose.Schema( 4 | { 5 | aboutme: String, 6 | noofprojects: String, 7 | yearofexperience: String, 8 | noofclients: String, 9 | skills: String, 10 | }, 11 | { timestamps: true } 12 | ); 13 | 14 | const About = mongoose.models.About || mongoose.model("About", AboutSchema); 15 | 16 | export default About; -------------------------------------------------------------------------------- /src/models/Experience.js: -------------------------------------------------------------------------------- 1 | import mongoose from "mongoose"; 2 | 3 | const ExperienceSchema = new mongoose.Schema( 4 | { 5 | position: String, 6 | company: String, 7 | duration: String, 8 | location: String, 9 | jobprofile: String, 10 | }, 11 | { timestamps: true } 12 | ); 13 | 14 | const Experience = mongoose.models.Experience || mongoose.model("Experience", ExperienceSchema); 15 | 16 | export default Experience; -------------------------------------------------------------------------------- /src/components/client-view/animation-wrapper/index.js: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import { motion } from "framer-motion"; 3 | 4 | export default function AnimationWrapper({ children, className, ...props }) { 5 | return ( 6 | 13 | {children} 14 | 15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /src/components/admin-view/contact/index.js: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | export default function AdminContactView({ data }) { 4 | return ( 5 |
6 | {data && data.length 7 | ? data.map((item) => ( 8 |
9 |

{item.name}

10 |

{item.email}

11 |

{item.message}

12 |
13 | )) 14 | : null} 15 |
16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | 27 | # local env files 28 | .env*.local 29 | 30 | # vercel 31 | .vercel 32 | 33 | # typescript 34 | *.tsbuildinfo 35 | next-env.d.ts 36 | -------------------------------------------------------------------------------- /src/app/layout.js: -------------------------------------------------------------------------------- 1 | import CommonLayout from '@/components/client-view/common-layout' 2 | import './globals.css' 3 | import { Inter } from 'next/font/google' 4 | 5 | const inter = Inter({ subsets: ['latin'] }) 6 | 7 | export const metadata = { 8 | title: 'Create Next App', 9 | description: 'Generated by create next app', 10 | } 11 | 12 | export default function RootLayout({ children }) { 13 | return ( 14 | 15 | 16 | {children} 17 | 18 | 19 | ) 20 | } 21 | -------------------------------------------------------------------------------- /public/vercel.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/api/home/get/route.js: -------------------------------------------------------------------------------- 1 | import connectToDB from "@/database"; 2 | import Home from "@/models/Home"; 3 | import { NextResponse } from "next/server"; 4 | 5 | export const dynamic = "force-dynamic"; 6 | 7 | export async function GET(req) { 8 | try { 9 | await connectToDB(); 10 | const extractData = await Home.find({}); 11 | 12 | if (extractData) { 13 | return NextResponse.json({ 14 | success: true, 15 | data: extractData, 16 | }); 17 | } else { 18 | return NextResponse.json({ 19 | success: false, 20 | message: "Something went wrong !Please try again", 21 | }); 22 | } 23 | } catch (e) { 24 | console.log(e); 25 | 26 | return NextResponse.json({ 27 | success: false, 28 | message: "Something went wrong !Please try again", 29 | }); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/app/api/about/get/route.js: -------------------------------------------------------------------------------- 1 | import connectToDB from "@/database"; 2 | import About from "@/models/About"; 3 | import { NextResponse } from "next/server"; 4 | 5 | export const dynamic = "force-dynamic"; 6 | 7 | export async function GET(req) { 8 | try { 9 | await connectToDB(); 10 | const extractData = await About.find({}); 11 | 12 | if (extractData) { 13 | return NextResponse.json({ 14 | success: true, 15 | data: extractData, 16 | }); 17 | } else { 18 | return NextResponse.json({ 19 | success: false, 20 | message: "Something went wrong !Please try again", 21 | }); 22 | } 23 | } catch (e) { 24 | console.log(e); 25 | 26 | return NextResponse.json({ 27 | success: false, 28 | message: "Something went wrong !Please try again", 29 | }); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/app/api/contact/get/route.js: -------------------------------------------------------------------------------- 1 | import connectToDB from "@/database"; 2 | import Contact from "@/models/Contact"; 3 | import { NextResponse } from "next/server"; 4 | 5 | export const dynamic = "force-dynamic"; 6 | 7 | export async function GET(req) { 8 | try { 9 | await connectToDB(); 10 | const extractData = await Contact.find({}); 11 | 12 | if (extractData) { 13 | return NextResponse.json({ 14 | success: true, 15 | data: extractData, 16 | }); 17 | } else { 18 | return NextResponse.json({ 19 | success: false, 20 | message: "Something went wrong !Please try again", 21 | }); 22 | } 23 | } catch (e) { 24 | console.log(e); 25 | 26 | return NextResponse.json({ 27 | success: false, 28 | message: "Something went wrong !Please try again", 29 | }); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/app/api/project/get/route.js: -------------------------------------------------------------------------------- 1 | import connectToDB from "@/database"; 2 | import Project from "@/models/Project"; 3 | import { NextResponse } from "next/server"; 4 | 5 | export const dynamic = "force-dynamic"; 6 | 7 | export async function GET(req) { 8 | try { 9 | await connectToDB(); 10 | const extractData = await Project.find({}); 11 | 12 | if (extractData) { 13 | return NextResponse.json({ 14 | success: true, 15 | data: extractData, 16 | }); 17 | } else { 18 | return NextResponse.json({ 19 | success: false, 20 | message: "Something went wrong !Please try again", 21 | }); 22 | } 23 | } catch (e) { 24 | console.log(e); 25 | 26 | return NextResponse.json({ 27 | success: false, 28 | message: "Something went wrong !Please try again", 29 | }); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/app/api/education/get/route.js: -------------------------------------------------------------------------------- 1 | import connectToDB from "@/database"; 2 | import Education from "@/models/Education"; 3 | import { NextResponse } from "next/server"; 4 | 5 | export const dynamic = "force-dynamic"; 6 | 7 | export async function GET(req) { 8 | try { 9 | await connectToDB(); 10 | const extractData = await Education.find({}); 11 | 12 | if (extractData) { 13 | return NextResponse.json({ 14 | success: true, 15 | data: extractData, 16 | }); 17 | } else { 18 | return NextResponse.json({ 19 | success: false, 20 | message: "Something went wrong !Please try again", 21 | }); 22 | } 23 | } catch (e) { 24 | console.log(e); 25 | 26 | return NextResponse.json({ 27 | success: false, 28 | message: "Something went wrong !Please try again", 29 | }); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nextjs-portfolio-2023", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "build": "next build", 8 | "start": "next start", 9 | "lint": "next lint" 10 | }, 11 | "dependencies": { 12 | "@emotion/react": "^11.11.1", 13 | "@emotion/styled": "^11.11.0", 14 | "@fullhuman/postcss-purgecss": "^5.0.0", 15 | "@mui/lab": "^5.0.0-alpha.142", 16 | "@mui/material": "^5.14.7", 17 | "autoprefixer": "10.4.15", 18 | "bcryptjs": "^2.4.3", 19 | "framer-motion": "^10.16.2", 20 | "mongoose": "^7.5.0", 21 | "next": "13.4.19", 22 | "postcss": "8.4.29", 23 | "react": "18.2.0", 24 | "react-dom": "18.2.0", 25 | "react-icons": "^4.10.1", 26 | "react-scroll": "^1.8.9", 27 | "react-slick": "^0.29.0", 28 | "tailwindcss": "3.3.3" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/app/api/experience/get/route.js: -------------------------------------------------------------------------------- 1 | import connectToDB from "@/database"; 2 | import Experience from "@/models/Experience"; 3 | import { NextResponse } from "next/server"; 4 | 5 | export const dynamic = "force-dynamic"; 6 | 7 | export async function GET(req) { 8 | try { 9 | await connectToDB(); 10 | const extractData = await Experience.find({}); 11 | 12 | if (extractData) { 13 | return NextResponse.json({ 14 | success: true, 15 | data: extractData, 16 | }); 17 | } else { 18 | return NextResponse.json({ 19 | success: false, 20 | message: "Something went wrong !Please try again", 21 | }); 22 | } 23 | } catch (e) { 24 | console.log(e); 25 | 26 | return NextResponse.json({ 27 | success: false, 28 | message: "Something went wrong !Please try again", 29 | }); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/app/api/home/add/route.js: -------------------------------------------------------------------------------- 1 | import connectToDB from "@/database"; 2 | import Home from "@/models/Home"; 3 | import { NextResponse } from "next/server"; 4 | 5 | export const dynamic = "force-dynamic"; 6 | 7 | export async function POST(req) { 8 | try { 9 | await connectToDB(); 10 | const extractData = await req.json(); 11 | const saveData = await Home.create(extractData); 12 | 13 | if (saveData) { 14 | return NextResponse.json({ 15 | success: true, 16 | message: "Data saved successfully", 17 | }); 18 | } else { 19 | return NextResponse.json({ 20 | success: false, 21 | message: "Something goes wrong !Please try again", 22 | }); 23 | } 24 | } catch (e) { 25 | console.log(e); 26 | 27 | return NextResponse.json({ 28 | success: false, 29 | message: "Something goes wrong !Please try again", 30 | }); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/components/admin-view/form-controls/index.js: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | export default function FormControls({ controls, formData, setFormData }) { 4 | return controls.map((controlItem) => ( 5 |
6 | 9 | { 16 | setFormData({ 17 | ...formData, 18 | [controlItem.name]: e.target.value, 19 | }); 20 | }} 21 | className="shadow border rounded w-full py-2 px-3 text-gray-700 tracking-wide focus:outline-none focus:shadow-outline" 22 | /> 23 |
24 | )); 25 | } 26 | -------------------------------------------------------------------------------- /src/app/api/about/add/route.js: -------------------------------------------------------------------------------- 1 | import connectToDB from "@/database"; 2 | import About from "@/models/About"; 3 | import { NextResponse } from "next/server"; 4 | 5 | export const dynamic = "force-dynamic"; 6 | 7 | export async function POST(req) { 8 | try { 9 | await connectToDB(); 10 | const extractData = await req.json(); 11 | const saveData = await About.create(extractData); 12 | 13 | if (saveData) { 14 | return NextResponse.json({ 15 | success: true, 16 | message: "Data saved successfully", 17 | }); 18 | } else { 19 | return NextResponse.json({ 20 | success: false, 21 | message: "Something goes wrong !Please try again", 22 | }); 23 | } 24 | } catch (e) { 25 | console.log(e); 26 | 27 | return NextResponse.json({ 28 | success: false, 29 | message: "Something goes wrong !Please try again", 30 | }); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/app/api/contact/add/route.js: -------------------------------------------------------------------------------- 1 | import connectToDB from "@/database"; 2 | import Contact from "@/models/Contact"; 3 | import { NextResponse } from "next/server"; 4 | 5 | export const dynamic = "force-dynamic"; 6 | 7 | export async function POST(req) { 8 | try { 9 | await connectToDB(); 10 | const extractData = await req.json(); 11 | const saveData = await Contact.create(extractData); 12 | 13 | if (saveData) { 14 | return NextResponse.json({ 15 | success: true, 16 | message: "Data saved successfully", 17 | }); 18 | } else { 19 | return NextResponse.json({ 20 | success: false, 21 | message: "Something goes wrong !Please try again", 22 | }); 23 | } 24 | } catch (e) { 25 | console.log(e); 26 | 27 | return NextResponse.json({ 28 | success: false, 29 | message: "Something goes wrong !Please try again", 30 | }); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/app/api/project/add/route.js: -------------------------------------------------------------------------------- 1 | import connectToDB from "@/database"; 2 | import Project from "@/models/Project"; 3 | import { NextResponse } from "next/server"; 4 | 5 | export const dynamic = "force-dynamic"; 6 | 7 | export async function POST(req) { 8 | try { 9 | await connectToDB(); 10 | const extractData = await req.json(); 11 | const saveData = await Project.create(extractData); 12 | 13 | if (saveData) { 14 | return NextResponse.json({ 15 | success: true, 16 | message: "Data saved successfully", 17 | }); 18 | } else { 19 | return NextResponse.json({ 20 | success: false, 21 | message: "Something goes wrong !Please try again", 22 | }); 23 | } 24 | } catch (e) { 25 | console.log(e); 26 | 27 | return NextResponse.json({ 28 | success: false, 29 | message: "Something goes wrong !Please try again", 30 | }); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/app/api/education/add/route.js: -------------------------------------------------------------------------------- 1 | import connectToDB from "@/database"; 2 | import Education from "@/models/Education"; 3 | import { NextResponse } from "next/server"; 4 | 5 | export const dynamic = "force-dynamic"; 6 | 7 | export async function POST(req) { 8 | try { 9 | await connectToDB(); 10 | const extractData = await req.json(); 11 | const saveData = await Education.create(extractData); 12 | 13 | if (saveData) { 14 | return NextResponse.json({ 15 | success: true, 16 | message: "Data saved successfully", 17 | }); 18 | } else { 19 | return NextResponse.json({ 20 | success: false, 21 | message: "Something goes wrong !Please try again", 22 | }); 23 | } 24 | } catch (e) { 25 | console.log(e); 26 | 27 | return NextResponse.json({ 28 | success: false, 29 | message: "Something goes wrong !Please try again", 30 | }); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/app/api/experience/add/route.js: -------------------------------------------------------------------------------- 1 | import connectToDB from "@/database"; 2 | import Experience from "@/models/Experience"; 3 | import { NextResponse } from "next/server"; 4 | 5 | export const dynamic = "force-dynamic"; 6 | 7 | export async function POST(req) { 8 | try { 9 | await connectToDB(); 10 | const extractData = await req.json(); 11 | const saveData = await Experience.create(extractData); 12 | 13 | if (saveData) { 14 | return NextResponse.json({ 15 | success: true, 16 | message: "Data saved successfully", 17 | }); 18 | } else { 19 | return NextResponse.json({ 20 | success: false, 21 | message: "Something goes wrong !Please try again", 22 | }); 23 | } 24 | } catch (e) { 25 | console.log(e); 26 | 27 | return NextResponse.json({ 28 | success: false, 29 | message: "Something goes wrong !Please try again", 30 | }); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/components/admin-view/login/index.js: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import FormControls from "../form-controls"; 4 | 5 | const controls = [ 6 | { 7 | name: "username", 8 | placeholder: "Enter User name", 9 | type: "text", 10 | label: "Enter User name", 11 | }, 12 | { 13 | name: "password", 14 | placeholder: "Enter Password", 15 | type: "password", 16 | label: "Enter Password", 17 | }, 18 | ]; 19 | 20 | export default function Login({ formData, setFormData, handleLogin }) { 21 | return ( 22 |
23 |
24 | 29 | 35 |
36 |
37 | ); 38 | } 39 | -------------------------------------------------------------------------------- /src/components/admin-view/home/index.js: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import FormControls from "../form-controls"; 4 | 5 | const controls = [ 6 | { 7 | name: "heading", 8 | placeholder: "Enter heading text", 9 | type: "text", 10 | label: "Enter heading text", 11 | }, 12 | { 13 | name: "summary", 14 | placeholder: "Enter Career summary", 15 | type: "text", 16 | label: "Enter Career summary", 17 | }, 18 | ]; 19 | 20 | export default function AdminHomeView({ formData, setFormData, handleSaveData }) { 21 | console.log(formData); 22 | return ( 23 |
24 |
25 | 30 | 33 |
34 |
35 | ); 36 | } 37 | -------------------------------------------------------------------------------- /src/app/api/home/update/route.js: -------------------------------------------------------------------------------- 1 | import connectToDB from "@/database"; 2 | import About from "@/models/About"; 3 | import Home from "@/models/Home"; 4 | import { NextResponse } from "next/server"; 5 | 6 | export const dynamic = "force-dynamic"; 7 | 8 | export async function PUT(req) { 9 | try { 10 | await connectToDB(); 11 | 12 | const extractData = await req.json(); 13 | const { _id, heading, summary } = extractData; 14 | 15 | const updateData = await Home.findOneAndUpdate( 16 | { 17 | _id: _id, 18 | }, 19 | { heading, summary }, 20 | { new: true } 21 | ); 22 | 23 | if (updateData) { 24 | return NextResponse.json({ 25 | success: true, 26 | message: "updated successfully", 27 | }); 28 | } else { 29 | return NextResponse.json({ 30 | success: false, 31 | message: "Something went wrong !Please try again", 32 | }); 33 | } 34 | } catch (e) { 35 | console.log(e); 36 | return NextResponse.json({ 37 | success: false, 38 | message: "Something went wrong !Please try again", 39 | }); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/app/api/about/update/route.js: -------------------------------------------------------------------------------- 1 | import connectToDB from "@/database"; 2 | import About from "@/models/About"; 3 | import { NextResponse } from "next/server"; 4 | 5 | export const dynamic = "force-dynamic"; 6 | 7 | export async function PUT(req) { 8 | try { 9 | await connectToDB(); 10 | 11 | const extractData = await req.json(); 12 | const { 13 | _id, 14 | aboutme, 15 | noofprojects, 16 | yearofexperience, 17 | nooflclients, 18 | skills, 19 | } = extractData; 20 | 21 | const updateData = await About.findOneAndUpdate( 22 | { 23 | _id: _id, 24 | }, 25 | { aboutme, noofprojects, yearofexperience, nooflclients, skills }, 26 | { new: true } 27 | ); 28 | 29 | if (updateData) { 30 | return NextResponse.json({ 31 | success: true, 32 | message: "updated successfully", 33 | }); 34 | } else { 35 | return NextResponse.json({ 36 | success: false, 37 | message: "Something went wrong !Please try again", 38 | }); 39 | } 40 | } catch (e) { 41 | console.log(e); 42 | return NextResponse.json({ 43 | success: false, 44 | message: "Something went wrong !Please try again", 45 | }); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/app/api/login/route.js: -------------------------------------------------------------------------------- 1 | import connectToDB from "@/database"; 2 | import User from "@/models/User"; 3 | import { compare, hash } from "bcryptjs"; 4 | import { NextResponse } from "next/server"; 5 | 6 | export const dynamic = "force-dynamic"; 7 | 8 | export async function POST(req) { 9 | try { 10 | await connectToDB(); 11 | const { username, password } = await req.json(); 12 | 13 | const checkUser = await User.findOne({ username }); 14 | 15 | if (!checkUser) { 16 | return NextResponse.json({ 17 | success: false, 18 | message: "User name is not present !Please try again", 19 | }); 20 | } 21 | 22 | const hashPassword = await hash(checkUser.password, 12); 23 | const checkPassword = await compare(password, hashPassword); 24 | 25 | if (!checkPassword) { 26 | return NextResponse.json({ 27 | success: false, 28 | message: "Wrong password. Please try again", 29 | }); 30 | } 31 | return NextResponse.json({ 32 | success: true, 33 | message: "Login successfull", 34 | }); 35 | } catch (e) { 36 | console.log(e); 37 | 38 | return NextResponse.json({ 39 | success: false, 40 | message: "Something goes wrong !Please try again", 41 | }); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /public/next.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/admin-view/about/index.js: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import FormControls from "../form-controls"; 4 | 5 | const controls = [ 6 | { 7 | name: "aboutme", 8 | placeholder: "About Me", 9 | type: "text", 10 | label: "About Me", 11 | }, 12 | { 13 | name: "noofprojects", 14 | placeholder: "No of projects", 15 | type: "text", 16 | label: "Enter no of projects", 17 | }, 18 | { 19 | name: "yearofexperience", 20 | placeholder: "No of experience", 21 | type: "text", 22 | label: "Enter no of experience", 23 | }, 24 | { 25 | name: "noofclients", 26 | placeholder: "No of clients", 27 | type: "text", 28 | label: "Enter no of clients", 29 | }, 30 | { 31 | name: "skills", 32 | placeholder: "skills", 33 | type: "text", 34 | label: "Skills", 35 | }, 36 | ]; 37 | 38 | export default function AdminAboutView({formData, setFormData , handleSaveData}) { 39 | return ( 40 |
41 |
42 | 47 | 50 |
51 |
52 | ); 53 | } 54 | -------------------------------------------------------------------------------- /src/components/admin-view/education/index.js: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import FormControls from "../form-controls"; 4 | 5 | 6 | const controls = [ 7 | { 8 | name: "degree", 9 | placeholder: "Degree Name", 10 | type: "text", 11 | label: "Enter Degree Name", 12 | }, 13 | { 14 | name: "year", 15 | placeholder: "Year", 16 | type: "text", 17 | label: "Year", 18 | }, 19 | { 20 | name: "college", 21 | placeholder: "College Name", 22 | type: "text", 23 | label: "Enter College Name", 24 | }, 25 | ]; 26 | 27 | 28 | export default function AdminEducationView({handleSaveData, formData, setFormData , data}) { 29 | return
30 |
31 |
32 | {data && data.length 33 | ? data.map((item) => ( 34 |
35 |

{item.degree}

36 |

{item.college}

37 |

{item.year}

38 |
39 | )) 40 | : null} 41 |
42 | 47 | 50 |
51 |
52 | } 53 | -------------------------------------------------------------------------------- /src/app/page.js: -------------------------------------------------------------------------------- 1 | import ClientAboutView from "@/components/client-view/about"; 2 | import ClientContactView from "@/components/client-view/contact"; 3 | import ClientExperienceAndEducationView from "@/components/client-view/experience"; 4 | import ClientHomeView from "@/components/client-view/home"; 5 | import ClientProjectView from "@/components/client-view/project"; 6 | 7 | async function extractAllDatas(currentSection) { 8 | const res = await fetch(`http://localhost:3000/api/${currentSection}/get`, { 9 | method: "GET", 10 | cache: "no-store", 11 | }); 12 | 13 | const data = await res.json(); 14 | 15 | return data && data.data; 16 | } 17 | 18 | export default async function Home() { 19 | const homeSectionData = await extractAllDatas("home"); 20 | const aboutSectionData = await extractAllDatas("about"); 21 | const experienceSectionData = await extractAllDatas("experience"); 22 | const educationSectionData = await extractAllDatas("education"); 23 | const projectSectionData = await extractAllDatas("project"); 24 | 25 | return ( 26 |
27 | 28 | 33 | 37 | 38 | 39 |
40 | ); 41 | } 42 | -------------------------------------------------------------------------------- /src/services/index.js: -------------------------------------------------------------------------------- 1 | export async function addData(currentTab, formData) { 2 | try { 3 | const response = await fetch(`/api/${currentTab}/add`, { 4 | method: "POST", 5 | headers: { 6 | "Content-Type": "application/json", 7 | }, 8 | body: JSON.stringify(formData), 9 | }); 10 | 11 | const result = await response.json(); 12 | 13 | return result; 14 | } catch (e) { 15 | console.log(e); 16 | } 17 | } 18 | 19 | export async function getData(currentTab) { 20 | try { 21 | const response = await fetch(`/api/${currentTab}/get`, { 22 | method: "GET", 23 | }); 24 | 25 | const result = await response.json(); 26 | 27 | return result; 28 | } catch (e) { 29 | console.log(e); 30 | } 31 | } 32 | 33 | export async function updateData(currentTab, formData) { 34 | try { 35 | const response = await fetch(`/api/${currentTab}/update`, { 36 | method: "PUT", 37 | headers: { 38 | "Content-Type": "application/json", 39 | }, 40 | body: JSON.stringify(formData), 41 | }); 42 | 43 | const result = await response.json(); 44 | 45 | return result; 46 | } catch (e) { 47 | console.log(e); 48 | } 49 | } 50 | 51 | export async function login(formData) { 52 | try { 53 | const response = await fetch(`/api/login`, { 54 | method: "POST", 55 | headers: { 56 | "Content-Type": "application/json", 57 | }, 58 | body: JSON.stringify(formData), 59 | }); 60 | 61 | const result = await response.json(); 62 | 63 | return result; 64 | } catch (e) { 65 | console.log(e); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). 2 | 3 | ## Getting Started 4 | 5 | First, run the development server: 6 | 7 | ```bash 8 | npm run dev 9 | # or 10 | yarn dev 11 | # or 12 | pnpm dev 13 | ``` 14 | 15 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 16 | 17 | You can start editing the page by modifying `app/page.js`. The page auto-updates as you edit the file. 18 | 19 | This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. 20 | 21 | ## Learn More 22 | 23 | To learn more about Next.js, take a look at the following resources: 24 | 25 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. 26 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. 27 | 28 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! 29 | 30 | ## Deploy on Vercel 31 | 32 | The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. 33 | 34 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. 35 | @emotion/react @emotion/styled @fullhuman/postcss-purgecss @mui/lab @mui/material bcryptjs framer-motion mongoose react-slick react-scroll 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/components/admin-view/project/index.js: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import FormControls from "../form-controls"; 4 | 5 | const controls = [ 6 | { 7 | name: "name", 8 | placeholder: "Project Name", 9 | type: "text", 10 | label: "Project Name", 11 | }, 12 | { 13 | name: "technologies", 14 | placeholder: "Enter Technologies", 15 | type: "text", 16 | label: "Enter Technologies", 17 | }, 18 | { 19 | name: "website", 20 | placeholder: "Website", 21 | type: "text", 22 | label: "Website", 23 | }, 24 | { 25 | name: "github", 26 | placeholder: "Github", 27 | type: "text", 28 | label: "github", 29 | }, 30 | ]; 31 | 32 | export default function AdminProjectView({ formData, setFormData , handleSaveData , data }) { 33 | return ( 34 |
35 |
36 |
37 | {data && data.length 38 | ? data.map((item) => ( 39 |
40 |

{item.name}

41 |

{item.technologies}

42 |

{item.website}

43 |

{item.github}

44 |
45 | )) 46 | : null} 47 |
48 | 53 | 56 |
57 |
58 | ); 59 | } 60 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: [ 4 | './src/pages/**/*.{js,ts,jsx,tsx,mdx}', 5 | './src/components/**/*.{js,ts,jsx,tsx,mdx}', 6 | './src/app/**/*.{js,ts,jsx,tsx,mdx}', 7 | ], 8 | theme: { 9 | boxShadow: { 10 | sm: "0 1px 2px 0 rgba(0, 0, 0, 0.05)", 11 | DEFAULT: 12 | "0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06)", 13 | md: "0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)", 14 | lg: "0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)", 15 | xl: "0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)", 16 | t: "0 -1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06)", 17 | orange: "0px 20px 20px -15px rgba(245,56,56,0.81) ", 18 | "green-md": "0px 20px 40px -15px rgba(245,56,56,0.81) ", 19 | "green-md" : "0px 20px 40px -15px rgba(13, 183, 96, 0.81)", 20 | none: "none", 21 | }, 22 | colors: { 23 | transparent: "transparent", 24 | black: { 25 | 900 : "#000000", 26 | 500: "#4F5665", 27 | 600: "#0B132A", 28 | }, 29 | orange: { 30 | 100: "#FFECEC", 31 | 500: "#F53855", 32 | }, 33 | green: { 34 | 500: "#2FAB73", 35 | main : "#0DB760" 36 | }, 37 | white: { 38 | 300: "#F8F8F8", 39 | 500: "#fff", 40 | }, 41 | gray: { 42 | 100: "#EEEFF2", 43 | 400: "#AFB5C0", 44 | 500: "#DDDDDD", 45 | }, 46 | }, 47 | extend: {}, 48 | }, 49 | variants: { 50 | extend: { 51 | boxShadow: ["active", "hover"], 52 | }, 53 | }, 54 | plugins: [], 55 | } 56 | -------------------------------------------------------------------------------- /src/components/admin-view/experience/index.js: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import FormControls from "../form-controls"; 4 | 5 | const controls = [ 6 | { 7 | name: "position", 8 | placeholder: "Position", 9 | type: "text", 10 | label: "Position", 11 | }, 12 | { 13 | name: "company", 14 | placeholder: "Company", 15 | type: "text", 16 | label: "Company", 17 | }, 18 | { 19 | name: "duration", 20 | placeholder: "Duration", 21 | type: "text", 22 | label: "Duration", 23 | }, 24 | { 25 | name: "location", 26 | placeholder: "Location", 27 | type: "text", 28 | label: "Location", 29 | }, 30 | { 31 | name: "jobprofile", 32 | placeholder: "Job Profile", 33 | type: "text", 34 | label: "Job Profile", 35 | }, 36 | ]; 37 | 38 | export default function AdminExperienceView({ 39 | formData, 40 | handleSaveData, 41 | setFormData, 42 | data, 43 | }) { 44 | return ( 45 |
46 |
47 |
48 | {data && data.length 49 | ? data.map((item) => ( 50 |
51 |

{item.position}

52 |

{item.company}

53 |

{item.duration}

54 |

{item.location}

55 |

{item.jobprofile}

56 |
57 | )) 58 | : null} 59 |
60 | 65 | 71 |
72 |
73 | ); 74 | } 75 | -------------------------------------------------------------------------------- /src/app/globals.css: -------------------------------------------------------------------------------- 1 | 2 | /* purgecss start ignore */ 3 | 4 | @tailwind base; 5 | @tailwind components; 6 | 7 | html { 8 | font-family: "Rubik", sans-serif; 9 | } 10 | body { 11 | background: bg-white-500 12 | } 13 | p { 14 | color: #000000 15 | } 16 | .animation-hover:after { 17 | background: none repeat scroll 0 0 transparent; 18 | content: ""; 19 | height: 2px; 20 | transition: width 0.3s ease 0s, left 0.3s ease 0s; 21 | @apply w-0 bg-green-main left-1/2 block bottom-0 absolute; 22 | } 23 | .animation-active:after { 24 | @apply left-0 w-full; 25 | } 26 | .animation-hover:hover:after { 27 | @apply left-0 w-full; 28 | } 29 | 30 | li.custom-list:before { 31 | content: "\2022"; /* bullet point, for screen readers */ 32 | text-indent: -9999999px; /* move the bullet point out of sight */ 33 | 34 | width: 0.4em; 35 | height: 1em; 36 | background-repeat: no-repeat; 37 | 38 | background-size: 0.4em 0.7em; 39 | background-position: 0 0.3em; 40 | font-size: 300%; 41 | top: -0.35em; 42 | @apply absolute block; 43 | } 44 | li.circle-check:before { 45 | background-image: url("/assets/Icon/checklist.svg"); 46 | left: -0.7em; 47 | top: -0.4em; 48 | } 49 | li.check:before { 50 | left: -0.5em; 51 | background-image: url("/assets/Icon/jam_check.svg"); 52 | top: -0.5em; 53 | font-size: 400%; 54 | } 55 | /* Slideshow */ 56 | .slick-dots li { 57 | @apply inline-block; 58 | } 59 | .slick-dots span { 60 | @apply bg-gray-500; 61 | } 62 | .slick-dots .slick-active span { 63 | @apply bg-orange-500 rounded-l-full rounded-r-full w-12; 64 | } 65 | 66 | /* purgecss end ignore */ 67 | @tailwind utilities; 68 | /* purgecss start ignore */ 69 | /* purgecss end ignore */ 70 | 71 | body::-webkit-scrollbar { 72 | width: 5px; 73 | } 74 | 75 | body::-webkit-scrollbar-track { 76 | box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3); 77 | } 78 | 79 | body::-webkit-scrollbar-thumb { 80 | background-color: darkgrey; 81 | outline: 1px solid slategrey; 82 | } 83 | 84 | .progress-bar { 85 | position: fixed; 86 | top: 0; 87 | left: 0; 88 | right: 0; 89 | height: 10px; 90 | background: var(--red); 91 | transform-origin: 0%; 92 | } 93 | 94 | .project-wrapper{ 95 | display: flex; 96 | list-style: none; 97 | height: 350px; 98 | overflow-x: scroll; 99 | padding: 20px 0; 100 | flex: 0 0 600px; 101 | } 102 | 103 | .project-wrapper li { 104 | flex: 0 0 300px; 105 | margin: 0 20px 0 0; 106 | } 107 | 108 | .project-wrapper li:last-of-type { 109 | margin: 0; 110 | } 111 | 112 | .bg { 113 | stroke: #fff; 114 | opacity: 0.3; 115 | } 116 | 117 | ::-webkit-scrollbar { 118 | height: 5px; 119 | width: 5px; 120 | background: #fff3; 121 | -webkit-border-radius: 1ex; 122 | } 123 | 124 | ::-webkit-scrollbar-thumb { 125 | background: green; 126 | -webkit-border-radius: 1ex; 127 | } 128 | 129 | ::-webkit-scrollbar-corner { 130 | background: #fff3; 131 | } 132 | 133 | #progress { 134 | 135 | transform: rotate(-90deg); 136 | } 137 | 138 | circle { 139 | stroke-dashoffset: 0; 140 | stroke-width: 15%; 141 | fill: none; 142 | } 143 | 144 | .bg { 145 | stroke: blue; 146 | opacity: 0.3; 147 | } 148 | 149 | #progress .indicator { 150 | stroke: red; 151 | } 152 | 153 | .MuiTimelineItem-root::before{ 154 | flex: 0 !important; 155 | } 156 | 157 | .MuiTimelineDot-root{ 158 | background-color: rgba(47, 171, 115, 1) !important; 159 | } 160 | 161 | .MuiTimelineConnector-root{ 162 | background-color: rgba(47, 171, 115, 1) !important; 163 | } 164 | 165 | 166 | 167 | 168 | 169 | -------------------------------------------------------------------------------- /src/components/client-view/navbar/index.js: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { useEffect, useState } from "react"; 4 | import { Link as LinkScroll, scroller } from "react-scroll"; 5 | 6 | const menuItems = [ 7 | { 8 | id: "home", 9 | label: "Home", 10 | }, 11 | { 12 | id: "about", 13 | label: "About", 14 | }, 15 | { 16 | id: "experience", 17 | label: "Experience", 18 | }, 19 | { 20 | id: "project", 21 | label: "projects", 22 | }, 23 | { 24 | id: "contact", 25 | label: "Contact", 26 | }, 27 | ]; 28 | 29 | function CreateMenus({ activeLink, getMenuItems, setActiveLink }) { 30 | return getMenuItems.map((item) => ( 31 | setActiveLink(item.id)} 38 | className={`px-4 py-2 mx-2 cursor-pointer animation-hover inline-block relative 39 | ${ 40 | activeLink === item.id 41 | ? "text-green-main animation-active shadow-green-main" 42 | : "text-[#000] font-bold hover:text-green-main" 43 | } 44 | `} 45 | > 46 | {item.label} 47 | 48 | )); 49 | } 50 | 51 | export default function Navbar() { 52 | const [activeLink, setActiveLink] = useState("home"); 53 | const [scrollActive, setScrollActive] = useState(false); 54 | 55 | useEffect(() => { 56 | window.addEventListener("scroll", () => { 57 | setScrollActive(window.screenY > 20); 58 | }); 59 | }, []); 60 | 61 | return ( 62 | <> 63 |
68 | 99 |
100 | 111 | 112 | ); 113 | } 114 | -------------------------------------------------------------------------------- /src/components/client-view/project/index.js: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { useRef } from "react"; 4 | import AnimationWrapper from "../animation-wrapper"; 5 | import { motion, useScroll } from "framer-motion"; 6 | import { useRouter } from "next/navigation"; 7 | 8 | 9 | 10 | export default function ClientProjectView({ data }) { 11 | const containerRef = useRef(null); 12 | const { scrollXProgress } = useScroll({ container: containerRef }); 13 | const router = useRouter() 14 | 15 | return ( 16 |
20 | 21 |
22 |

23 | {"My Projects".split(" ").map((item, index) => ( 24 | 27 | {item}{" "} 28 | 29 | ))} 30 |

31 | 32 | 39 | 47 | 48 |
49 |
50 | 51 |
    52 | {data && data.length 53 | ? data.map((item, index) => ( 54 |
  • 58 |
    59 |
    60 |
    61 |
    62 |

    63 | {item.name} 64 |

    65 |

    66 | {item.createdAt.split("T")[0]} 67 |

    68 |
    69 | {item?.technologies.split(",").map((techItem) => ( 70 |
    71 | 74 |
    75 | ))} 76 |
    77 |
    78 |
    79 |
    80 |
    81 | 84 | 87 |
    88 |
    89 |
  • 90 | )) 91 | : null} 92 |
93 |
94 |
95 | ); 96 | } 97 | -------------------------------------------------------------------------------- /src/components/client-view/home/index.js: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { useMemo, useRef } from "react"; 4 | import AnimationWrapper from "../animation-wrapper"; 5 | import { motion } from "framer-motion"; 6 | import { 7 | FaFacebookF, 8 | FaLinkedinIn, 9 | FaInstagram, 10 | FaTwitter, 11 | } from "react-icons/fa"; 12 | import Image from "next/image"; 13 | import aiImage from "../../../assets/ai-image.png"; 14 | 15 | function variants() { 16 | return { 17 | offscreen: { 18 | y: 150, 19 | opacity: 0, 20 | }, 21 | onscreen: ({ duration = 2 } = {}) => ({ 22 | y: 0, 23 | opacity: 1, 24 | transition: { 25 | type: "spring", 26 | duration, 27 | }, 28 | }), 29 | }; 30 | } 31 | 32 | const socialIcons = [ 33 | { 34 | id: "facebook", 35 | icon: ( 36 | 40 | ), 41 | }, 42 | { 43 | id: "twitter", 44 | icon: ( 45 | 46 | ), 47 | }, 48 | { 49 | id: "linkedin", 50 | icon: ( 51 | 55 | ), 56 | }, 57 | { 58 | id: "instagram", 59 | icon: ( 60 | 64 | ), 65 | }, 66 | ]; 67 | 68 | export default function ClientHomeView({ data }) { 69 | console.log(data, "ClientHomeView"); 70 | 71 | const setVariants = useMemo(() => variants(), []); 72 | const containerRef = useRef(null); 73 | 74 | return ( 75 |
76 | 77 | 83 |
84 |

85 | {data && data.length 86 | ? data[0]?.heading 87 | .split(" ") 88 | .map((item, index) => ( 89 | 96 | {item}{" "} 97 | 98 | )) 99 | : null} 100 |

101 |

102 | {data && data.length ? data[0]?.summary : null} 103 |

104 | 105 | {socialIcons.map((item) => ( 106 | 119 | {item.icon} 120 | 121 | ))} 122 | 123 |
124 | 125 | 130 |
131 | Profile Picture 140 |
141 |
142 |
143 |
144 |
145 | ); 146 | } 147 | -------------------------------------------------------------------------------- /src/components/client-view/about/index.js: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { useMemo } from "react"; 4 | import AnimationWrapper from "../animation-wrapper"; 5 | import { motion } from "framer-motion"; 6 | import Image from "next/image"; 7 | import aboutMeImage from "../../../assets/about-image.png"; 8 | 9 | function variants() { 10 | return { 11 | offscreen: { 12 | y: 150, 13 | opacity: 0, 14 | }, 15 | onscreen: ({ duration = 2 } = {}) => ({ 16 | y: 0, 17 | opacity: 1, 18 | transition: { 19 | type: "spring", 20 | duration, 21 | }, 22 | }), 23 | }; 24 | } 25 | 26 | const skillItemVariant = { 27 | hidden: { y: 20, opacity: 0 }, 28 | visible: { 29 | y: 0, 30 | opacity: 1, 31 | }, 32 | }; 33 | 34 | export default function ClientAboutView({ data }) { 35 | console.log(data, "aboutdata"); 36 | 37 | const setVariants = useMemo(() => variants(), []); 38 | 39 | const aboutDataInfo = [ 40 | { 41 | label: "Client", 42 | value: data?.noofclients || "0", 43 | }, 44 | { 45 | label: "Projects", 46 | value: data?.noofprojects || "0", 47 | }, 48 | { 49 | label: "Experience", 50 | value: data?.yearofexperience || "0", 51 | }, 52 | ]; 53 | 54 | const headingText = "Why Hire Me For Your Next Project ?"; 55 | 56 | return ( 57 |
58 |
59 | 60 | {aboutDataInfo.map((infoItem, index) => ( 61 | 75 |
76 |
77 |

78 | {infoItem.value}+ 79 |

80 |

81 | {infoItem.label} 82 |

83 |
84 |
85 |
86 | ))} 87 |
88 |
89 | 90 |
91 |

92 | {headingText.split(" ").map((item, index) => ( 93 | 96 | {item}{" "} 97 | 98 | ))} 99 |

100 |

{data?.aboutme}

101 |
102 |
103 |
104 | 105 | 106 | About Me 114 | 115 | 116 | 117 | 121 | {data?.skills.split(",").map((skill) => ( 122 | 126 | 129 | 130 | ))} 131 | 132 | 133 |
134 |
135 | ); 136 | } 137 | -------------------------------------------------------------------------------- /src/components/client-view/contact/index.js: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { useEffect, useState } from "react"; 4 | import AnimationWrapper from "../animation-wrapper"; 5 | import { addData } from "@/services"; 6 | 7 | const controls = [ 8 | { 9 | name: "name", 10 | placeholder: "Enter your name", 11 | type: "text", 12 | label: "Name", 13 | }, 14 | { 15 | name: "email", 16 | placeholder: "Enter your email", 17 | type: "email", 18 | label: "Email", 19 | }, 20 | { 21 | name: "message", 22 | placeholder: "Enter your message", 23 | type: "text", 24 | label: "Message", 25 | }, 26 | ]; 27 | 28 | const initialFormData = { 29 | name: "", 30 | email: "", 31 | message: "", 32 | }; 33 | 34 | export default function ClientContactView() { 35 | const [formData, setFormData] = useState(initialFormData); 36 | const [showSuccessMessage, setShowSuccessMessage] = useState(false); 37 | 38 | async function handleSendMessage() { 39 | const res = await addData("contact", formData); 40 | console.log(res,'contact-res'); 41 | 42 | if(res && res.success) { 43 | setFormData(initialFormData) 44 | setShowSuccessMessage(true) 45 | } 46 | } 47 | 48 | useEffect(()=>{ 49 | if(showSuccessMessage) { 50 | setTimeout(()=>{ 51 | setShowSuccessMessage(false) 52 | },1500) 53 | } 54 | 55 | },[showSuccessMessage]) 56 | 57 | const isValidForm = () => { 58 | return formData && 59 | formData.name !== "" && 60 | formData.email !== "" && 61 | formData.message !== "" 62 | ? true 63 | : false; 64 | }; 65 | 66 | console.log(isValidForm(), 'isValidForm()'); 67 | 68 | return ( 69 |
73 | 74 |
75 |

76 | {"Contact Me".split(" ").map((item, index) => ( 77 | 80 | {item}{" "} 81 | 82 | ))} 83 |

84 |
85 |
86 |
87 |
88 |
89 |
90 | {controls.map((controlItem) => 91 | controlItem.name === "message" ? ( 92 |
93 |
94 | 97 | 109 |
110 |
111 | ) : ( 112 |
113 |
114 | 117 | 122 | setFormData({ 123 | ...formData, 124 | [controlItem.name]: e.target.value, 125 | }) 126 | } 127 | className="w-full border-green-main border-[2px] bg-[#ffffff] rounded text-base outline-none text-[#000000] py-1 px-3 leading-6" 128 | /> 129 |
130 |
131 | ) 132 | )} 133 | { 134 | showSuccessMessage &&

Your message is successfully delivered !

135 | } 136 |
137 | 144 |
145 |
146 |
147 |
148 |
149 |
150 | ); 151 | } 152 | -------------------------------------------------------------------------------- /src/components/client-view/experience/index.js: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { 4 | Timeline, 5 | TimelineConnector, 6 | TimelineContent, 7 | TimelineDot, 8 | TimelineItem, 9 | TimelineSeparator, 10 | } from "@mui/lab"; 11 | import AnimationWrapper from "../animation-wrapper"; 12 | import { motion } from "framer-motion"; 13 | 14 | export default function ClientExperienceAndEducationView({ 15 | educationData, 16 | experienceData, 17 | }) { 18 | console.log(educationData, experienceData, "experienceData"); 19 | 20 | return ( 21 |
25 |
26 |
27 | 28 |
29 |

30 | {"My Experince".split(" ").map((item, index) => ( 31 | 36 | {item}{" "} 37 | 38 | ))} 39 |

40 |
41 |
42 | 43 |
44 | 45 | 46 | {experienceData && experienceData.length 47 | ? experienceData.map((experienceItem) => ( 48 | 49 | 50 | 51 | 52 | 53 | 54 |
55 |

56 | {experienceItem.duration} 57 |

58 |

59 | {experienceItem.company},{" "} 60 | {experienceItem.location} 61 |

62 |

63 | {experienceItem.position} 64 |

65 |

66 | {experienceItem.jobprofile} 67 |

68 |
69 |
70 |
71 | )) 72 | : null} 73 |
74 |
75 |
76 |
77 |
78 |
79 | 80 |
81 |

82 | {"My Education".split(" ").map((item, index) => ( 83 | 88 | {item}{" "} 89 | 90 | ))} 91 |

92 |
93 |
94 | 95 |
96 | 97 | 98 | {educationData && educationData.length 99 | ? educationData.map((educationItem) => ( 100 | 101 | 102 | 103 | 104 | 105 | 106 |
107 |

108 | {educationItem.year} 109 |

110 |

111 | {educationItem.college} 112 |

113 |

114 | {educationItem.degree} 115 |

116 |
117 |
118 |
119 | )) 120 | : null} 121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 | ); 129 | } 130 | -------------------------------------------------------------------------------- /src/app/admin/page.js: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import AdminAboutView from "@/components/admin-view/about"; 4 | import AdminContactView from "@/components/admin-view/contact"; 5 | import AdminEducationView from "@/components/admin-view/education"; 6 | import AdminExperienceView from "@/components/admin-view/experience"; 7 | import AdminHomeView from "@/components/admin-view/home"; 8 | import Login from "@/components/admin-view/login"; 9 | import AdminProjectView from "@/components/admin-view/project"; 10 | import { addData, getData, login, updateData } from "@/services"; 11 | import { useEffect, useState } from "react"; 12 | 13 | const initialHomeFormData = { 14 | heading: "", 15 | summary: "", 16 | }; 17 | 18 | const initialAboutFormData = { 19 | aboutme: "", 20 | noofprojects: "", 21 | yearofexperience: "", 22 | noofclients: "", 23 | skills: "", 24 | }; 25 | 26 | const initialExperienceFormData = { 27 | position: "", 28 | company: "", 29 | duration: "", 30 | location: "", 31 | jobprofile: "", 32 | }; 33 | 34 | const initialEducationFormData = { 35 | degree: "", 36 | year: "", 37 | college: "", 38 | }; 39 | 40 | const initialProjectFormData = { 41 | name: "", 42 | website: "", 43 | technologies: "", 44 | github: "", 45 | }; 46 | 47 | const initialLoginFormData = { 48 | username: "", 49 | password: "", 50 | }; 51 | 52 | export default function AdminView() { 53 | const [currentSelectedTab, setCurrentSelectedTab] = useState("home"); 54 | const [homeViewFormData, setHomeViewFormData] = useState(initialHomeFormData); 55 | const [aboutViewFormData, setAboutViewFormData] = 56 | useState(initialAboutFormData); 57 | const [experienceViewFormData, setExperienceViewFormData] = useState( 58 | initialExperienceFormData 59 | ); 60 | const [educationViewFormData, setEducationViewFormData] = useState( 61 | initialEducationFormData 62 | ); 63 | const [projectViewFormData, setProjectViewFormData] = useState( 64 | initialProjectFormData 65 | ); 66 | 67 | 68 | const [allData, setAllData] = useState({}); 69 | const [update, setUpdate] = useState(false); 70 | const [authUser, setAuthUser] = useState(false); 71 | const [loginFormData, setLoginFormData] = useState(initialLoginFormData); 72 | 73 | const menuItems = [ 74 | { 75 | id: "home", 76 | label: "Home", 77 | component: ( 78 | 83 | ), 84 | }, 85 | { 86 | id: "about", 87 | label: "About", 88 | component: ( 89 | 94 | ), 95 | }, 96 | { 97 | id: "experience", 98 | label: "Experience", 99 | component: ( 100 | 106 | ), 107 | }, 108 | { 109 | id: "education", 110 | label: "Education", 111 | component: ( 112 | 118 | ), 119 | }, 120 | { 121 | id: "project", 122 | label: "Project", 123 | component: ( 124 | 130 | ), 131 | }, 132 | { 133 | id: "contact", 134 | label: "Contact", 135 | component: , 138 | }, 139 | ]; 140 | 141 | async function extractAllDatas() { 142 | const response = await getData(currentSelectedTab); 143 | 144 | if ( 145 | currentSelectedTab === "home" && 146 | response && 147 | response.data && 148 | response.data.length 149 | ) { 150 | setHomeViewFormData(response && response.data[0]); 151 | setUpdate(true); 152 | } 153 | 154 | if ( 155 | currentSelectedTab === "about" && 156 | response && 157 | response.data && 158 | response.data.length 159 | ) { 160 | setAboutViewFormData(response && response.data[0]); 161 | setUpdate(true); 162 | } 163 | 164 | if (response?.success) { 165 | setAllData({ 166 | ...allData, 167 | [currentSelectedTab]: response && response.data, 168 | }); 169 | } 170 | } 171 | 172 | console.log(allData, 'allData'); 173 | 174 | 175 | async function handleSaveData() { 176 | const dataMap = { 177 | home: homeViewFormData, 178 | about: aboutViewFormData, 179 | education: educationViewFormData, 180 | experience: experienceViewFormData, 181 | project: projectViewFormData, 182 | }; 183 | 184 | const response = update 185 | ? await updateData(currentSelectedTab, dataMap[currentSelectedTab]) 186 | : await addData(currentSelectedTab, dataMap[currentSelectedTab]); 187 | console.log(response, "response"); 188 | 189 | if (response.success) { 190 | resetFormDatas(); 191 | extractAllDatas(); 192 | } 193 | } 194 | 195 | useEffect(() => { 196 | extractAllDatas(); 197 | }, [currentSelectedTab]); 198 | 199 | function resetFormDatas() { 200 | setHomeViewFormData(initialHomeFormData); 201 | setAboutViewFormData(initialAboutFormData); 202 | setExperienceViewFormData(initialExperienceFormData); 203 | setEducationViewFormData(initialEducationFormData); 204 | setProjectViewFormData(initialProjectFormData); 205 | } 206 | 207 | console.log(allData, homeViewFormData, "homeViewFormData"); 208 | 209 | useEffect(() => { 210 | setAuthUser(JSON.parse(sessionStorage.getItem("authUser"))); 211 | }, []); 212 | 213 | async function handleLogin() { 214 | const res = await login(loginFormData); 215 | 216 | console.log(res, "login"); 217 | 218 | if (res?.success) { 219 | setAuthUser(true); 220 | sessionStorage.setItem("authUser", JSON.stringify(true)); 221 | } 222 | } 223 | 224 | if (!authUser) 225 | return ( 226 | 231 | ); 232 | 233 | return ( 234 |
235 | 260 |
261 | {menuItems.map( 262 | (item) => item.id === currentSelectedTab && item.component 263 | )} 264 |
265 |
266 | ); 267 | } 268 | --------------------------------------------------------------------------------