Skip to content

Commit

Permalink
Feat/project stack (#527)
Browse files Browse the repository at this point in the history
* Refactor User model in schema.prisma

* Refactor user.profile.validator.ts: Add stack enum for projectSchema

* Refactor user-multistep-form: Add project stack selection

* Refactor project schema to add default value for stack field

* Refactor schema.prisma: Add cascade deletion for user relations

* Refactor project schema: Add projectThumbnail field and update projectSummary

* Refactor user.profile.validator.ts: Add optional projectThumbnail field to projectSchema

* Refactor profile pages: Add container and heading

* Refactor AddProject form: Add project thumbnail upload functionality

* Refactor UserProject component: Add project thumbnail display and link functionality

* Refactor project schema: Update ProjectStack enum values

* Refactor project schema: Update ProjectStack enum values

* Refactor icons.ts: Add loading spinner icon

* Refactor profile pages: Add "Add more" functionality

* Refactor project schema: Update ProjectStack enum values

* Refactor UserProject component: Add loading spinner and no projects found message

* Refactor UserExperience component: Improve loading and no experiences found handling
  • Loading branch information
CuriousCoder00 authored Oct 21, 2024
1 parent f2bff43 commit eb7fdc8
Show file tree
Hide file tree
Showing 10 changed files with 391 additions and 91 deletions.
74 changes: 43 additions & 31 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ datasource db {
}

model User {
id String @id @default(cuid())
name String
id String @id @default(cuid())
name String
password String?
avatar String?
Expand All @@ -19,34 +19,34 @@ model User {
email String @unique
emailVerified DateTime?
skills String[]
experience Experience[]
project Project[]
resume String?
oauthProvider OauthProvider? // Tracks OAuth provider (e.g., 'google')
oauthId String?
skills String[]
experience Experience[]
project Project[]
resume String?
oauthProvider OauthProvider? // Tracks OAuth provider (e.g., 'google')
oauthId String?
blockedByAdmin DateTime?
onBoard Boolean @default(false)
onBoard Boolean @default(false)
}

enum OauthProvider {
GOOGLE
}


model VerificationToken {
token String
token String
identifier String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
type TokenType
@@unique([token,identifier])
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
type TokenType
@@unique([token, identifier])
}

enum TokenType {
enum TokenType {
EMAIL_VERIFICATION
RESET_PASSWORD
}
Expand Down Expand Up @@ -80,32 +80,44 @@ model Job {
isVerifiedJob Boolean @default(false) @map("is_verified_job")
postedAt DateTime @default(now())
updatedAt DateTime @updatedAt
user User @relation(fields: [userId], references: [id],onDelete: Cascade)
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
}

model Experience {
id Int @id @default(autoincrement())
companyName String
id Int @id @default(autoincrement())
companyName String
designation String
EmploymentType EmployementType
address String
workMode WorkMode
currentWorkStatus Boolean
startDate DateTime
endDate DateTime?
description String
userId String
user User @relation(fields: [userId] ,references: [id])
description String
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
}

model Project {
id Int @id @default(autoincrement())
projectName String
projectSummary String
projectLiveLink String?
projectGithub String
userId String
user User @relation(fields: [userId] , references: [id])
id Int @id @default(autoincrement())
projectName String
projectThumbnail String?
projectSummary String
projectLiveLink String?
projectGithub String
stack ProjectStack @default(OTHERS)
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
}

enum ProjectStack {
GO
PYTHON
MERN
NEXTJS
AI_GPT_APIS
SPRINGBOOT
OTHERS
}

enum Currency {
Expand Down
24 changes: 23 additions & 1 deletion src/app/profile/experience/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
'use client';
import { UserExperience } from '@/components/profile/UserExperience';
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
DialogTrigger,
} from '@/components/ui/dialog';
import { AddExperience } from '@/components/user-multistep-form/addExperience-form';
import APP_PATHS from '@/config/path.config';
import { useSession } from 'next-auth/react';
import { useRouter } from 'next/navigation';
Expand All @@ -13,7 +21,21 @@ export default function AccountExperiencePage() {
router.push(`${APP_PATHS.SIGNIN}?redirectTo=/profile`);
}, [session.status, router]);
return (
<div>
<div className="md:container flex flex-col w-full gap-4">
<div className="flex md:justify-between justify-start items-center gap-5">
<span>Experience</span>
<Dialog>
<DialogTrigger>Add more</DialogTrigger>
<DialogContent className="max-w-md max-h-[90vh] flex flex-col p-0">
<DialogHeader className="p-6 pb-2">
<DialogTitle>Add Experience</DialogTitle>
</DialogHeader>
<div className="flex-grow overflow-y-auto px-6 pb-6">
<AddExperience />
</div>
</DialogContent>
</Dialog>
</div>
<UserExperience />
</div>
);
Expand Down
24 changes: 23 additions & 1 deletion src/app/profile/projects/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
'use client';
import { UserProjects } from '@/components/profile/UserProject';
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
DialogTrigger,
} from '@/components/ui/dialog';
import { AddProject } from '@/components/user-multistep-form/add-project-form';
import APP_PATHS from '@/config/path.config';
import { useSession } from 'next-auth/react';
import { useRouter } from 'next/navigation';
Expand All @@ -13,7 +21,21 @@ export default function AccountProjectPage() {
router.push(`${APP_PATHS.SIGNIN}?redirectTo=/profile`);
}, [session.status, router]);
return (
<div className="overflow-x-hidden">
<div className="md:container flex flex-col w-full gap-4">
<div className="flex md:justify-between justify-start gap-5 items-center">
<span>Projects</span>
<Dialog>
<DialogTrigger>Add more</DialogTrigger>
<DialogContent className="max-w-md max-h-[90vh] flex flex-col p-0">
<DialogHeader className="p-6 pb-2">
<DialogTitle>Add Project</DialogTitle>
</DialogHeader>
<div className="flex-grow overflow-y-auto px-6 pb-6">
<AddProject />
</div>
</DialogContent>
</Dialog>
</div>
<UserProjects />
</div>
);
Expand Down
5 changes: 4 additions & 1 deletion src/app/profile/resume/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ export default function AccountResumePage() {
router.push(`${APP_PATHS.SIGNIN}?redirectTo=/profile`);
}, [session.status, router]);
return (
<div className="m-auto">
<div className="md:container flex flex-col w-full gap-4">
<div className="flex justify-between items-center">
<span>Resume</span>
</div>
<UserResume />
</div>
);
Expand Down
24 changes: 23 additions & 1 deletion src/app/profile/skills/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
'use client';
import { UserSkills } from '@/components/profile/UserSkills';
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
DialogTrigger,
} from '@/components/ui/dialog';
import { AddSkills } from '@/components/user-multistep-form/add-skills-form';
import APP_PATHS from '@/config/path.config';
import { useSession } from 'next-auth/react';
import { useRouter } from 'next/navigation';
Expand All @@ -13,7 +21,21 @@ export default function AccountResumePage() {
router.push(`${APP_PATHS.SIGNIN}?redirectTo=/profile`);
}, [session.status, router]);
return (
<div>
<div className="md:container flex flex-col w-full gap-4">
<div className="flex md:justify-between justify-start items-center gap-5">
<span>Skills</span>
<Dialog>
<DialogTrigger>Add more</DialogTrigger>
<DialogContent className="max-w-md max-h-[90vh] flex flex-col p-0">
<DialogHeader className="p-6 pb-2">
<DialogTitle>Add Skills</DialogTitle>
</DialogHeader>
<div className="flex-grow overflow-y-auto px-6 pb-6">
<AddSkills />
</div>
</DialogContent>
</Dialog>
</div>
<UserSkills />
</div>
);
Expand Down
78 changes: 38 additions & 40 deletions src/components/profile/UserExperience.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@ 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';

import icons from '@/lib/icons';
export function UserExperience() {
const { toast } = useToast();
const [experiences, setExperiences] = useState<Experience[] | undefined>();
Expand Down Expand Up @@ -34,53 +33,52 @@ export function UserExperience() {
}, []);

if (!experiences) {
return null;
return (
<div className="flex items-center justify-center h-full w-full">
<icons.loading className="animate-spin w-10 h-10" />
</div>
);
}

return (
<div className="space-y-2 mb-2">
{experiences.map((item: Experience) => (
<Card
<div
key={item.id}
className="border-2 hover:bg-slate-100 dark:hover:bg-slate-900 text-black dark:text-white transition-shadow duration-300"
className="flex flex-col items-center justify-between md:col-span-2 col-span-4 border-2 hover:bg-slate-100 dark:hover:bg-slate-900 text-black dark:text-white transition-shadow duration-300 p-3 gap-2 rounded-2xl"
>
<CardHeader>
<CardTitle className="text-lg font-semibold">
<strong>Company Name: </strong>
{item.companyName}
</CardTitle>
</CardHeader>
<CardContent>
<p className="mb-2">
<strong>Designation:</strong> {item.designation}
</p>
<p className="mb-2">
<strong>Employment Type:</strong>{' '}
{_.startCase(item.EmploymentType)}
</p>
<p className="mb-2">
<strong>Work Mode:</strong> {item.workMode}
</p>
<p className="mb-2">
<strong>Current Status:</strong>{' '}
{item.currentWorkStatus
? 'Currently Employed here'
: 'Not Currently Employed here'}
</p>
<p className="mb-2">
<strong>Duration:</strong>{' '}
{new Date(item.startDate).toLocaleDateString()}{' '}
{item.endDate
? ` - ${new Date(item.endDate).toLocaleDateString()}`
: ' - Present'}
</p>
<p className="mb-4">
<strong>Description: </strong>
<div className="flex items-center justify-between w-full py-2">
<div className="flex flex-col justify-center items-start w-1/3">
<div className="font-semibold">
{new Date(item.startDate).toLocaleDateString()}
{item.endDate
? ` - ${new Date(item.endDate).toLocaleDateString()}`
: ' - Present'}
</div>
<div className="dark:text-slate-400 text-slate-700">
{_.startCase(item.EmploymentType)}, {_.startCase(item.workMode)}
</div>
</div>
<div className="flex flex-col justify-center items-start w-1/3 gap-1">
<span className="font-bold">{item.companyName}</span>
<p className="dark:text-slate-400 text-slate-700">
{item.designation}
</p>
</div>
</div>
<div className="w-full border-l-4 p-2 bg-slate-900/50">
<span className="dark:text-slate-400 text-slate-700">
{item.description}
</p>
</CardContent>
</Card>
</span>
</div>
</div>
))}
{experiences.length === 0 && (
<div className="flex items-center justify-center col-span-4 h-full">
<icons.alert size={24} />
<span className="ml-2">No Experiences Found</span>
</div>
)}
</div>
);
}
Loading

0 comments on commit eb7fdc8

Please sign in to comment.