Skip to content

Commit

Permalink
added share button + edge cases
Browse files Browse the repository at this point in the history
  • Loading branch information
devsharmagit committed Oct 31, 2024
1 parent f3258ec commit e44cf69
Show file tree
Hide file tree
Showing 24 changed files with 452 additions and 144 deletions.
11 changes: 11 additions & 0 deletions prisma/migrations/20241031043344_username_remove/migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*
Warnings:
- You are about to drop the column `username` on the `User` table. All the data in the column will be lost.
*/
-- DropIndex
DROP INDEX "User_username_key";

-- AlterTable
ALTER TABLE "User" DROP COLUMN "username";
2 changes: 0 additions & 2 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@ model User {
twitterLink String?
discordLink String?
username String @unique
contactEmail String?
aboutMe String?
Expand Down
5 changes: 1 addition & 4 deletions prisma/seed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,19 @@ import bcrypt from 'bcryptjs';
const prisma = new PrismaClient();

const users = [
{ id: '1', name: 'Jack', email: '[email protected]', username: 'jackcoder', role: Role.USER },
{ id: '1', name: 'Jack', email: '[email protected]', role: Role.USER },
{
id: '2',
name: 'Admin',
email: '[email protected]',
role: Role.ADMIN,
onBoard: true,
username: 'admincoder',
},
{
id: '3',
name: 'Hr',
email: '[email protected]',
role: Role.HR,
username: 'hrcoder',
},
];

Expand Down Expand Up @@ -334,7 +332,6 @@ async function seedUsers() {
password: hashedPassword,
role: u.role || Role.USER,
emailVerified: new Date(),
username: u.username,
},
});
console.log(`User created or updated: ${u.email}`);
Expand Down
3 changes: 1 addition & 2 deletions src/actions/auth.actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,7 @@ export const signUp = withServerActionAsyncCatcher<
await prisma.$transaction(
async (txn) => {
const user = await txn.user.create({
// todo username
data: { ...data, password: hashedPassword, username: 'asdif' },
data: { ...data, password: hashedPassword },
});

const verificationToken = await txn.verificationToken.create({
Expand Down
2 changes: 0 additions & 2 deletions src/actions/user.profile.actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,6 @@ export const getUserDetailsWithId = async (id: string) => {
id: id,
},
select: {
username: true,
name: true,
id: true,
skills: true,
Expand Down Expand Up @@ -419,7 +418,6 @@ export const updateUserDetails = withSession<
},
data: {
name: data.name,
username: data.username,
email: data.email,
contactEmail: data.contactEmail,
aboutMe: data.aboutMe,
Expand Down
5 changes: 3 additions & 2 deletions src/components/comboBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,10 @@ export function Combobox({
variant="outline"
role="combobox"
aria-expanded={open}
className="w-full justify-between border border-slate-200 dark:bg-gray-800 text-slate-500 rounded-[8px] dark:text-white"
className="w-full justify-between dark:bg-gray-800 border-none dark:text-white"
aria-label="skillset"
>
Enter Skills
Search skillset ...
<ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
</Button>
</PopoverTrigger>
Expand Down
8 changes: 4 additions & 4 deletions src/components/profile/AboutMe.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
'use client';
import { FileText, Pencil } from 'lucide-react';
import { SquareUserRound, Pencil } from 'lucide-react';
import React, { useState } from 'react';
import { Button } from '@/components/ui/button';
import SheetWrapper from './sheets/SheetWrapper';
import ReadMeForm from './forms/ReadMeForm';
import { SHEETS } from '@/lib/constant/profile.constant';
import ProfileEmptyContainers from './emptycontainers/ProfileEmptyContainers';
import AboutMeForm from './forms/ReadMeForm';

const ProfileAboutMe = ({
aboutMe,
Expand Down Expand Up @@ -55,7 +55,7 @@ const ProfileAboutMe = ({
? 'Share a brief introduction to let companies know who you are.'
: ''
}
Icon={FileText}
Icon={SquareUserRound}
/>
)}
{aboutMe && (
Expand All @@ -70,7 +70,7 @@ const ProfileAboutMe = ({
title={title}
description={SHEETS.aboutMe.description}
>
<ReadMeForm handleClose={handleClose} aboutMe={aboutMe} />
<AboutMeForm handleClose={handleClose} aboutMe={aboutMe} />
</SheetWrapper>
)}
</>
Expand Down
4 changes: 2 additions & 2 deletions src/components/profile/ProfileEducation.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
'use client';
import { Circle, Info, Pencil, Plus } from 'lucide-react';
import { Circle, BookOpenCheck, Pencil, Plus } from 'lucide-react';
import React, { useState } from 'react';
import { Button } from '../ui/button';
import SheetWrapper from './sheets/SheetWrapper';
Expand Down Expand Up @@ -68,7 +68,7 @@ const ProfileEducation = ({
? 'Provide your education background to complete your profile.'
: ''
}
Icon={Info}
Icon={BookOpenCheck}
/>
)}
{education.length !== 0 && (
Expand Down
4 changes: 2 additions & 2 deletions src/components/profile/ProfileExperience.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
'use client';
import { Circle, Info, Pencil, Plus } from 'lucide-react';
import { Circle, Building2, Pencil, Plus } from 'lucide-react';
import React, { useState } from 'react';
import { Button } from '../ui/button';
import SheetWrapper from './sheets/SheetWrapper';
Expand Down Expand Up @@ -73,7 +73,7 @@ const ProfileExperience = ({
? 'Share your experience to attract the right companies.'
: ''
}
Icon={Info}
Icon={Building2}
/>
)}

Expand Down
20 changes: 11 additions & 9 deletions src/components/profile/ProfileHeroSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@
import React, { useState } from 'react';
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
import { Button } from '@/components/ui/button';
import { Pencil, Settings, Share2 } from 'lucide-react';
import { Pencil, Settings, User } from 'lucide-react';
import SheetWrapper from './sheets/SheetWrapper';
import EditProfileForm from './forms/EditProfileForm';
import { SHEETS } from '@/lib/constant/profile.constant';
import AccountSeetingForm from './forms/AccountSeetingForm';
import { useSession } from 'next-auth/react';
import { UserType } from '@/types/user.types';
import ProfileSocials from './ProfileSocials';
import { ProfileShareDialog } from './ProfileShare';

const ProfileHeroSection = ({ userdetails }: { userdetails: UserType }) => {
const [isSheetOpen, setIsSheetOpen] = useState<boolean>(false);
Expand All @@ -31,11 +32,17 @@ const ProfileHeroSection = ({ userdetails }: { userdetails: UserType }) => {
<div className="border rounded-2xl min-h-72 overflow-hidden">
<div className="w-full h-32 bg-gradient-to-r from-blue-500 to-indigo-500"></div>
<div className="p-6 relative flex-col flex gap-y-3">
<Avatar className="h-32 w-32 absolute -top-16">
<Avatar className="h-32 w-32 absolute -top-16 bg-slate-100 dark:bg-slate-900">
{userdetails.avatar && (
<AvatarImage src={userdetails.avatar} alt="@shadcn" />
)}
<AvatarFallback>{userdetails.name[0]}</AvatarFallback>
<AvatarFallback>
<User
width={32}
height={32}
className="dark:text-slate-400 text-slate-500"
/>
</AvatarFallback>
</Avatar>
<div className="w-full flex justify-end gap-2 h-10">
{status === 'authenticated' && data.user.id === userdetails.id && (
Expand All @@ -54,17 +61,12 @@ const ProfileHeroSection = ({ userdetails }: { userdetails: UserType }) => {
>
<Settings height={16} width={16} />
</Button>
<Button variant={'outline'} className="px-3 py-2 rounded-sm">
<Share2 height={16} width={16} />
</Button>
</>
)}
<ProfileShareDialog />
</div>
<div>
<h2 className="text-4xl font-bold">{userdetails.name}</h2>
<a href="#" className="text-sm text-primary font-semibold">
@{userdetails.username}
</a>
</div>
<ProfileSocials userdetails={userdetails} />
</div>
Expand Down
58 changes: 25 additions & 33 deletions src/components/profile/ProfileProjects.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
'use client';
import { ChevronDown, ChevronUp, Info, Plus } from 'lucide-react';
import { ChevronDown, ChevronUp, FileStack, Plus } from 'lucide-react';
import React, { useMemo, useState } from 'react';
import { Button } from '@/components/ui/button';
import SheetWrapper from './sheets/SheetWrapper';
Expand Down Expand Up @@ -38,13 +38,16 @@ const ProfileProjects = ({
setIsSeeMore(!isSeeMore);
};

const featuredProjects = useMemo(() => {
return projects.filter((project) => project.isFeature === true);
}, [projects]);

const nonFeaturedProjects = useMemo(() => {
return projects.filter((project) => project.isFeature === false);
}, [projects]);
const allProjects = useMemo(() => {
return projects
.filter((project) => {
if (!isSeeMore) {
return project.isFeature === true;
}
return true;
})
.sort((a, b) => Number(b.isFeature) - Number(a.isFeature));
}, [projects, isSeeMore]);

const title = selectedProject
? SHEETS.project.title.replace('Add New', 'Edit')
Expand All @@ -65,7 +68,7 @@ const ProfileProjects = ({
)}
</div>

{featuredProjects.length === 0 && (
{projects.length === 0 && (
<ProfileEmptyContainers
isOwner={isOwner}
buttonText="Add Your Projects"
Expand All @@ -80,33 +83,13 @@ const ProfileProjects = ({
? 'Showcase your projects to demonstrate your skills and expertise.'
: ''
}
Icon={Info}
Icon={FileStack}
/>
)}
{featuredProjects.length !== 0 && !isSeeMore && (
{projects.length !== 0 && (
<>
<div className=" grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-x-6 gap-y-6 ">
{featuredProjects.map((project) => (
<ProfileProject
key={project.id}
project={project}
handleEditClick={handleEditClick}
isOwner={isOwner}
/>
))}
</div>
<Button
onClick={handleSeeMore}
className="dark:border-slate-800 px-3 bg-transparent hover:bg-transparent w-fit border py-2 text-base font-medium flex gap-2 rounded-[8px] border-slate-200 text-slate-500 dark:text-slate-400"
>
See more <ChevronDown height={16} width={16} />
</Button>
</>
)}
{projects.length !== 0 && isSeeMore && (
<>
<div className=" grid grid-cols-3 gap-x-6 gap-y-6 ">
{[...featuredProjects, ...nonFeaturedProjects].map((project) => (
{allProjects.map((project) => (
<ProfileProject
key={project.id}
project={project}
Expand All @@ -119,7 +102,16 @@ const ProfileProjects = ({
onClick={handleSeeMore}
className="dark:border-slate-800 px-3 bg-transparent hover:bg-transparent w-fit border py-2 text-base font-medium flex gap-2 rounded-[8px] border-slate-200 text-slate-500 dark:text-slate-400"
>
Hide <ChevronUp height={16} width={16} />
{isSeeMore
? 'Hide'
: allProjects.length === 0
? 'Show non featured projects'
: 'See More'}
{isSeeMore ? (
<ChevronUp height={16} width={16} />
) : (
<ChevronDown height={16} width={16} />
)}
</Button>
</>
)}
Expand Down
88 changes: 88 additions & 0 deletions src/components/profile/ProfileShare.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import React from 'react';
import { Button } from '@/components/ui/button';
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
DialogTrigger,
} from '@/components/ui/dialog';
import { Twitter, Linkedin, Share2, Copy } from 'lucide-react';
import { useToast } from '../ui/use-toast';

interface ShareOption {
name: string;
icon: React.ReactNode;
shareFunction: () => void;
}

export const ProfileShareDialog = () => {
const { toast } = useToast();

const shareOptions: ShareOption[] = [
{
name: 'Twitter',
icon: <Twitter className="h-5 w-5" />,
shareFunction: () => {
const text = encodeURIComponent(
`Check out my new profile at 100xdevs Job-Board: ${window.location.href}`
);
window.open(`https://twitter.com/intent/tweet?text=${text}`, '_blank');
},
},
{
name: 'LinkedIn',
icon: <Linkedin className="h-5 w-5" />,
shareFunction: () => {
const url = encodeURIComponent(window.location.href);
const title = encodeURIComponent('My New Profile');
const summary = encodeURIComponent(
`Excited to share my new profile on 100xdevs Job-Board! Check it out here: ${url} #JobSearch #Hiring #OpenToWork`
);
window.open(
`https://www.linkedin.com/sharing/share-offsite/?url=${url}&title=${title}&summary=${summary}`,
'_blank'
);
},
},
{
name: 'Copy',
icon: <Copy className="h-5 w-5" />,
shareFunction: () => {
window.navigator.clipboard.writeText(window.location.href);
toast({
variant: 'success',
description: 'Successfully copied the Profile Url.',
});
},
},
];

return (
<Dialog>
<DialogTrigger asChild>
<Button variant={'outline'} className="px-3 py-2 rounded-sm">
<Share2 height={16} width={16} />
</Button>
</DialogTrigger>
<DialogContent className="sm:max-w-md">
<DialogHeader>
<DialogTitle>Share Job</DialogTitle>
</DialogHeader>
<div className="flex flex-col space-y-4">
{shareOptions.map((option) => (
<Button
key={option.name}
variant="outline"
className="w-full justify-start gap-2"
onClick={() => option.shareFunction()}
>
{option.icon}
{option.name === 'Copy' ? 'Copy Url' : `Share on ${option.name}`}
</Button>
))}
</div>
</DialogContent>
</Dialog>
);
};
Loading

0 comments on commit e44cf69

Please sign in to comment.