diff --git a/src/actions/user.profile.actions.ts b/src/actions/user.profile.actions.ts
index e8921939..66d9e4d2 100644
--- a/src/actions/user.profile.actions.ts
+++ b/src/actions/user.profile.actions.ts
@@ -251,3 +251,69 @@ export const addUserResume = async (resume: string) => {
return new ErrorHandler('Internal server error', 'DATABASE_ERROR');
}
};
+
+export const getUserExperience = async () => {
+ const auth = await getServerSession(authOptions);
+
+ if (!auth || !auth?.user?.id)
+ throw new ErrorHandler('Not Authorized', 'UNAUTHORIZED');
+ try {
+ const res = await prisma.experience.findMany({
+ where: {
+ userId: auth.user.id,
+ },
+ });
+ return new SuccessResponse(
+ 'Experience SuccessFully Fetched',
+ 200,
+ res
+ ).serialize();
+ } catch (_error) {
+ return new ErrorHandler('Internal server error', 'DATABASE_ERROR');
+ }
+};
+export const getUserProjects = async () => {
+ const auth = await getServerSession(authOptions);
+
+ if (!auth || !auth?.user?.id)
+ throw new ErrorHandler('Not Authorized', 'UNAUTHORIZED');
+ try {
+ const res = await prisma.project.findMany({
+ where: {
+ userId: auth.user.id,
+ },
+ });
+ return new SuccessResponse(
+ 'Project SuccessFully Fetched',
+ 200,
+ res
+ ).serialize();
+ } catch (_error) {
+ return new ErrorHandler('Internal server error', 'DATABASE_ERROR');
+ }
+};
+
+export const getUserDetails = async () => {
+ const auth = await getServerSession(authOptions);
+
+ if (!auth || !auth?.user?.id)
+ throw new ErrorHandler('Not Authorized', 'UNAUTHORIZED');
+ try {
+ const res = await prisma.user.findFirst({
+ where: {
+ id: auth.user.id,
+ },
+ select: {
+ skills: true,
+ resume: true,
+ },
+ });
+ return new SuccessResponse(
+ 'Project SuccessFully Fetched',
+ 200,
+ res
+ ).serialize();
+ } catch (_error) {
+ return new ErrorHandler('Internal server error', 'DATABASE_ERROR');
+ }
+};
diff --git a/src/app/create-profile/page.tsx b/src/app/create-profile/page.tsx
index 0975521e..9dbc412a 100644
--- a/src/app/create-profile/page.tsx
+++ b/src/app/create-profile/page.tsx
@@ -6,7 +6,7 @@ import { redirect } from 'next/navigation';
export default async function Home() {
const session = await getServerSession(authOptions);
if (!session || session.user.role !== 'USER') redirect('/');
- if (session.user.onBoard === true) redirect('/profile');
+ if (session.user.onBoard === true) redirect('/jobs');
return (
diff --git a/src/app/page.tsx b/src/app/page.tsx
index a0669a33..bd78e16e 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -2,18 +2,8 @@ import Faqs from '@/components/Faqs';
import HeroSection from '@/components/hero-section';
import { JobLanding } from '@/components/job-landing';
import Testimonials from '@/components/Testimonials';
-import { authOptions } from '@/lib/authOptions';
-import { getServerSession } from 'next-auth';
-import { redirect } from 'next/navigation';
const HomePage = async () => {
- const session = await getServerSession(authOptions);
- {
- session &&
- session.user.role === 'USER' &&
- !session.user.onBoard &&
- redirect('/create-profile');
- }
return (
diff --git a/src/app/profile/experience/page.tsx b/src/app/profile/experience/page.tsx
new file mode 100644
index 00000000..adf6b8b0
--- /dev/null
+++ b/src/app/profile/experience/page.tsx
@@ -0,0 +1,20 @@
+'use client';
+import { UserExperience } from '@/components/profile/UserExperience';
+import APP_PATHS from '@/config/path.config';
+import { useSession } from 'next-auth/react';
+import { useRouter } from 'next/navigation';
+import React, { useEffect } from 'react';
+
+export default function AccountExperiencePage() {
+ const router = useRouter();
+ const session = useSession();
+ useEffect(() => {
+ if (session.status !== 'loading' && session.status === 'unauthenticated')
+ router.push(`${APP_PATHS.SIGNIN}?redirectTo=/profile`);
+ }, [session.status, router]);
+ return (
+
+
+
+ );
+}
diff --git a/src/app/profile/layout.tsx b/src/app/profile/layout.tsx
index f69e44ca..a7cba91d 100644
--- a/src/app/profile/layout.tsx
+++ b/src/app/profile/layout.tsx
@@ -1,4 +1,5 @@
'use client';
+import { getUserDetails } from '@/actions/user.profile.actions';
import Sidebar from '@/components/profile/sidebar';
import APP_PATHS from '@/config/path.config';
import { useSession } from 'next-auth/react';
@@ -11,7 +12,25 @@ const ProfileLayout = ({ children }: { children: React.ReactNode }) => {
useEffect(() => {
if (session.status !== 'loading' && session.status === 'unauthenticated')
router.push(`${APP_PATHS.SIGNIN}?redirectTo=/profile`);
- }, [session.status]);
+ }, [session.status, router]);
+ useEffect(() => {
+ async function fetchUserDetails() {
+ try {
+ const res = await getUserDetails();
+ if (res.status) {
+ localStorage.setItem(
+ 'skills',
+ JSON.stringify(res.additional?.skills)
+ );
+ localStorage.setItem(
+ 'resume',
+ JSON.stringify(res.additional?.resume)
+ );
+ }
+ } catch (_error) {}
+ }
+ fetchUserDetails();
+ }, []);
return (
diff --git a/src/app/profile/page.tsx b/src/app/profile/page.tsx
index d6213f14..30509244 100644
--- a/src/app/profile/page.tsx
+++ b/src/app/profile/page.tsx
@@ -14,7 +14,8 @@ const ProfilePage = () => {
useEffect(() => {
if (session.status !== 'loading' && session.status === 'unauthenticated')
router.push(`${APP_PATHS.SIGNIN}?redirectTo=/create`);
- }, [session.status]);
+ }, [session.status, router]);
+
return (
diff --git a/src/app/profile/projects/page.tsx b/src/app/profile/projects/page.tsx
new file mode 100644
index 00000000..e92c1775
--- /dev/null
+++ b/src/app/profile/projects/page.tsx
@@ -0,0 +1,20 @@
+'use client';
+import { UserProjects } from '@/components/profile/UserProject';
+import APP_PATHS from '@/config/path.config';
+import { useSession } from 'next-auth/react';
+import { useRouter } from 'next/navigation';
+import React, { useEffect } from 'react';
+
+export default function AccountProjectPage() {
+ const router = useRouter();
+ const session = useSession();
+ useEffect(() => {
+ if (session.status !== 'loading' && session.status === 'unauthenticated')
+ router.push(`${APP_PATHS.SIGNIN}?redirectTo=/profile`);
+ }, [session.status, router]);
+ return (
+
+
+
+ );
+}
diff --git a/src/app/profile/resume/page.tsx b/src/app/profile/resume/page.tsx
new file mode 100644
index 00000000..b0639fa9
--- /dev/null
+++ b/src/app/profile/resume/page.tsx
@@ -0,0 +1,20 @@
+'use client';
+import { UserResume } from '@/components/profile/UserResume';
+import APP_PATHS from '@/config/path.config';
+import { useSession } from 'next-auth/react';
+import { useRouter } from 'next/navigation';
+import React, { useEffect } from 'react';
+
+export default function AccountResumePage() {
+ const router = useRouter();
+ const session = useSession();
+ useEffect(() => {
+ if (session.status !== 'loading' && session.status === 'unauthenticated')
+ router.push(`${APP_PATHS.SIGNIN}?redirectTo=/profile`);
+ }, [session.status, router]);
+ return (
+
+
+
+ );
+}
diff --git a/src/app/profile/settings/page.tsx b/src/app/profile/settings/page.tsx
index 8ad13135..9cd66ff1 100644
--- a/src/app/profile/settings/page.tsx
+++ b/src/app/profile/settings/page.tsx
@@ -11,7 +11,7 @@ const AccountSettingsPage = () => {
useEffect(() => {
if (session.status !== 'loading' && session.status === 'unauthenticated')
router.push(`${APP_PATHS.SIGNIN}?redirectTo=/profile`);
- }, [session.status]);
+ }, [session.status, router]);
return (
diff --git a/src/app/profile/skills/page.tsx b/src/app/profile/skills/page.tsx
new file mode 100644
index 00000000..8a731a40
--- /dev/null
+++ b/src/app/profile/skills/page.tsx
@@ -0,0 +1,20 @@
+'use client';
+import { UserSkills } from '@/components/profile/UserSkills';
+import APP_PATHS from '@/config/path.config';
+import { useSession } from 'next-auth/react';
+import { useRouter } from 'next/navigation';
+import React, { useEffect } from 'react';
+
+export default function AccountResumePage() {
+ const router = useRouter();
+ const session = useSession();
+ useEffect(() => {
+ if (session.status !== 'loading' && session.status === 'unauthenticated')
+ router.push(`${APP_PATHS.SIGNIN}?redirectTo=/profile`);
+ }, [session.status, router]);
+ return (
+
+
+
+ );
+}
diff --git a/src/components/profile/UserExperience.tsx b/src/components/profile/UserExperience.tsx
new file mode 100644
index 00000000..366ef085
--- /dev/null
+++ b/src/components/profile/UserExperience.tsx
@@ -0,0 +1,86 @@
+import { getUserExperience } from '@/actions/user.profile.actions';
+import { useEffect, useState } from 'react';
+import { useToast } from '../ui/use-toast';
+import { Experience } from '@prisma/client';
+import { Card, CardContent, CardHeader, CardTitle } from '../ui/card';
+import _ from 'lodash';
+
+export function UserExperience() {
+ const { toast } = useToast();
+ const [experiences, setExperiences] = useState
();
+
+ useEffect(() => {
+ async function fetchExperience() {
+ try {
+ const res = await getUserExperience();
+ if (!res.status) {
+ toast({
+ title: 'Cannot Fetch Experiences! Please Try Again Later',
+ variant: 'destructive',
+ });
+ }
+ if (res.status) {
+ setExperiences(res.additional);
+ }
+ } catch (_error) {
+ toast({
+ title: 'Cannot Fetch Experiences! Please Try Again Later',
+ variant: 'destructive',
+ });
+ }
+ }
+
+ fetchExperience();
+ }, []);
+
+ if (!experiences) {
+ return null;
+ }
+
+ return (
+
+ {experiences.map((item: Experience) => (
+
+
+
+ Company Name:
+ {item.companyName}
+
+
+
+
+ Designation: {item.designation}
+
+
+ Employment Type:{' '}
+ {_.startCase(item.EmploymentType)}
+
+
+ Work Mode: {item.workMode}
+
+
+ Current Status:{' '}
+ {item.currentWorkStatus
+ ? 'Currently Employed here'
+ : 'Not Currently Employed here'}
+
+
+ Duration:{' '}
+ {new Date(item.startDate).toLocaleDateString()}{' '}
+ {item.endDate
+ ? ` - ${new Date(item.endDate).toLocaleDateString()}`
+ : ' - Present'}
+
+
+ Description:
+ {item.description}
+
+
+
+ ))}
+
+ );
+}
diff --git a/src/components/profile/UserProject.tsx b/src/components/profile/UserProject.tsx
new file mode 100644
index 00000000..5da4af54
--- /dev/null
+++ b/src/components/profile/UserProject.tsx
@@ -0,0 +1,80 @@
+import { getUserProjects } from '@/actions/user.profile.actions';
+import { useEffect, useState } from 'react';
+import { useToast } from '../ui/use-toast';
+import { Project } from '@prisma/client';
+import Link from 'next/link';
+import {
+ Card,
+ CardContent,
+ CardFooter,
+ CardHeader,
+ CardTitle,
+} from '../ui/card';
+
+export function UserProjects() {
+ const { toast } = useToast();
+ const [projects, setProjects] = useState();
+ useEffect(() => {
+ async function fetchProjects() {
+ try {
+ const res = await getUserProjects();
+ if (!res.status) {
+ toast({
+ title: 'Can not Fetch Projects! Please Try agian Later',
+ variant: 'destructive',
+ });
+ }
+ if (res.status) {
+ setProjects(res.additional);
+ }
+ } catch (_error) {
+ toast({
+ title: 'Can not Fetch Projects! Please Try agian Later',
+ variant: 'destructive',
+ });
+ }
+ }
+
+ fetchProjects();
+ }, [toast]);
+
+ if (!projects) {
+ return null;
+ }
+
+ return (
+
+ {projects.map((item: Project) => (
+
+
+
+ {item.projectName}
+
+
+
+ {item.projectSummary}
+
+
+ {item.projectLiveLink && (
+
+ Live Project
+
+ )}
+
+ GitHub Repository
+
+
+
+ ))}
+
+ );
+}
diff --git a/src/components/profile/UserResume.tsx b/src/components/profile/UserResume.tsx
new file mode 100644
index 00000000..914fce2e
--- /dev/null
+++ b/src/components/profile/UserResume.tsx
@@ -0,0 +1,30 @@
+import { File } from 'lucide-react';
+import Link from 'next/link';
+import { useEffect, useState } from 'react';
+
+export function UserResume() {
+ const [resumeLink, setResumeLink] = useState(null);
+
+ useEffect(() => {
+ const storedResume = localStorage.getItem('resume');
+ if (storedResume) setResumeLink(JSON.parse(storedResume));
+ }, []);
+
+ if (!resumeLink) {
+ return null;
+ }
+
+ return (
+
+
+
+
Click here
+
+
+ );
+}
diff --git a/src/components/profile/UserSkills.tsx b/src/components/profile/UserSkills.tsx
new file mode 100644
index 00000000..4871fbe9
--- /dev/null
+++ b/src/components/profile/UserSkills.tsx
@@ -0,0 +1,28 @@
+import { useEffect, useState } from 'react';
+
+export function UserSkills() {
+ const [skills, setSkills] = useState();
+ useEffect(() => {
+ const storedSkills = localStorage.getItem('skills');
+ if (storedSkills) {
+ setSkills(JSON.parse(storedSkills));
+ }
+ }, []);
+
+ if (!skills) {
+ return null;
+ }
+
+ return (
+
+ {skills.map((item, index) => (
+
+ {item}
+
+ ))}
+
+ );
+}
diff --git a/src/components/skills-combobox.tsx b/src/components/skills-combobox.tsx
index 3f724d5c..1a90f6ef 100644
--- a/src/components/skills-combobox.tsx
+++ b/src/components/skills-combobox.tsx
@@ -66,7 +66,10 @@ export function SkillsCombobox({
}, [debouncedComboboxValues]);
React.useEffect(() => {
- form.setValue('skills', comboBoxSelectedValues);
+ (form as UseFormReturn).setValue(
+ 'skills',
+ comboBoxSelectedValues
+ );
}, [comboBoxSelectedValues, form]);
return (
<>
diff --git a/src/components/user-multistep-form/user-multistep-form.tsx b/src/components/user-multistep-form/user-multistep-form.tsx
index a4631ee1..0535585a 100644
--- a/src/components/user-multistep-form/user-multistep-form.tsx
+++ b/src/components/user-multistep-form/user-multistep-form.tsx
@@ -22,6 +22,7 @@ import { useState } from 'react';
import { useToast } from '../ui/use-toast';
import { validateUserBoarding } from '@/actions/user.profile.actions';
import { useRouter } from 'next/navigation';
+import { useSession } from 'next-auth/react';
const forms = [
{
@@ -62,6 +63,7 @@ export default function VerticalLinearStepper() {
setActiveStep((prevActiveStep) => prevActiveStep - 1);
};
const { toast } = useToast();
+ const { data: session, update } = useSession();
const handleFinish = async () => {
try {
@@ -76,7 +78,12 @@ export default function VerticalLinearStepper() {
title: response.message,
variant: 'success',
});
- router.push('/jobs');
+ await update({
+ ...session,
+ user: {
+ onBoard: true,
+ },
+ });
router.refresh();
} catch (_error) {
toast({
diff --git a/src/config/path.config.ts b/src/config/path.config.ts
index 9809adc6..60bd264b 100644
--- a/src/config/path.config.ts
+++ b/src/config/path.config.ts
@@ -15,5 +15,9 @@ const APP_PATHS = {
PROFILE: '/profile',
EDIT_PROFILE: '/profile/edit',
ACCOUNT_SETTINGS: '/profile/settings',
+ PROJECTS: '/profile/projects',
+ RESUME: '/profile/resume',
+ EXPERIENCE: '/profile/experience',
+ SKILLS: '/profile/skills',
};
export default APP_PATHS;
diff --git a/src/lib/constant/app.constant.ts b/src/lib/constant/app.constant.ts
index 9cec8870..f296e2ae 100644
--- a/src/lib/constant/app.constant.ts
+++ b/src/lib/constant/app.constant.ts
@@ -40,6 +40,10 @@ export const userProfileNavbar = [
{ id: 1, label: 'My Account', path: APP_PATHS.PROFILE },
{ id: 2, label: 'Edit Profile', path: APP_PATHS.EDIT_PROFILE },
{ id: 3, label: 'Account Settings', path: APP_PATHS.ACCOUNT_SETTINGS },
+ { id: 4, label: 'Experience', path: APP_PATHS.EXPERIENCE },
+ { id: 5, label: 'Projects', path: APP_PATHS.PROJECTS },
+ { id: 6, label: 'Skills', path: APP_PATHS.SKILLS },
+ { id: 7, label: 'Resume', path: APP_PATHS.RESUME },
];
export const socials: {
href: string;
diff --git a/src/middleware.tsx b/src/middleware.ts
similarity index 79%
rename from src/middleware.tsx
rename to src/middleware.ts
index d306cac6..3e578f39 100644
--- a/src/middleware.tsx
+++ b/src/middleware.ts
@@ -15,6 +15,13 @@ export async function middleware(req: NextRequest) {
) {
return NextResponse.redirect(new URL('/', req.url));
}
+ if (
+ pathname !== '/create-profile' &&
+ token?.role === 'USER' &&
+ !token.onBoard
+ ) {
+ return NextResponse.redirect(new URL('/create-profile', req.url));
+ }
return NextResponse.next();
}