Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Frontend/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import PersonalInfoForm from "@/components/personalInfoForm";
import { toast } from "@/components/ui/use-toast";
import { useState } from "react";
import { useMutation } from "react-query";

export type Upload = {
selectedFile: File;
userId: string;
Expand Down
14 changes: 14 additions & 0 deletions Frontend/app/profile/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import ProfileCard from "@/components/profileCard";

export default function Profile() {
const user = {
name: 'John Doe',
email: '[email protected]',
};

return (
<main className="flex min-h-screen flex-col items-center justify-between p-24 ">
<ProfileCard user={user} />
</main>
);
}
48 changes: 48 additions & 0 deletions Frontend/components/cvList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import React from 'react';
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { Table, TableBody, TableCell, TableRow } from "@/components/ui/table"
import { Button } from "@/components/ui/button"
import { FileText, Share2, Trash2 } from 'lucide-react'

const CVList = ({ cvs, loading, onShareCV, onDeleteCV }) => {
return (
<Card className="w-full shadow-lg rounded-lg overflow-hidden min-h-[300px]">
<CardHeader className="bg-white py-6 px-8">
<CardTitle className="flex items-center text-xl font-semibold">
<FileText className="mr-3 h-6 w-6" />
Mes CVs générés
</CardTitle>
</CardHeader>
<CardContent className="px-8 py-6">
{loading ? (
<p className="text-center text-lg">Chargement des CVs...</p>
) : cvs.length > 0 ? (
<Table>
<TableBody>
{cvs.map((cv) => (
<TableRow key={cv.id}>
<TableCell className="font-medium text-lg">{cv.name}</TableCell>
<TableCell className="text-lg">{cv.date}</TableCell>
<TableCell className="text-right">
<Button variant="outline" size="lg" className="mr-2" onClick={() => onShareCV(cv.id)}>
<Share2 className="h-5 w-5 mr-2" />
Partager
</Button>
<Button variant="destructive" size="lg" onClick={() => onDeleteCV(cv.id)}>
<Trash2 className="h-5 w-5 mr-2" />
Supprimer
</Button>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
) : (
<p className="text-center text-lg">Aucun CV généré pour le moment.</p>
)}
</CardContent>
</Card>
);
};

export default CVList;
91 changes: 91 additions & 0 deletions Frontend/components/profileCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import React, { useState, useEffect } from 'react';
import { Card } from "@/components/ui/card"
import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs"
import { User, Edit } from 'lucide-react'
import ProfileView from './profileView';
import ProfileEdit from './profileEdit';
import CVList from './cvList';

const getmycv = async () => {
await new Promise(resolve => setTimeout(resolve, 1000));
return [
{ id: 1, name: 'CV_FrontEnd_Developer.pdf', date: '2023-09-15' },
{ id: 2, name: 'CV_FullStack_Engineer.pdf', date: '2023-10-20' },
{ id: 3, name: 'CV_React_Specialist.pdf', date: '2023-11-05' },
];
};

const ProfileCard = ({ user: initialUser }) => {
const [user, setUser] = useState(initialUser);
const [cvs, setCvs] = useState([]);
const [loading, setLoading] = useState(true);

useEffect(() => {
const fetchCVs = async () => {
try {
const fetchedCVs = await getmycv();
setCvs(fetchedCVs);
} catch (error) {
console.error("Erreur lors de la récupération des CVs:", error);
} finally {
setLoading(false);
}
};

fetchCVs();
}, []);

const handleUpdateUser = (updatedUser) => {
setUser(updatedUser);
console.log("Données du profil mises à jour:", updatedUser);
};

const handleShareCV = (cvId) => {
console.log(`Partager le CV avec l'ID: ${cvId}`);
};

const handleDeleteCV = (cvId) => {
console.log(`Supprimer le CV avec l'ID: ${cvId}`);
setCvs(prevCvs => prevCvs.filter(cv => cv.id !== cvId));
};

if (!user) {
return <div>Aucune donnée utilisateur disponible</div>;
}

return (
<div className="flex items-center justify-center min-h-screen bg-white p-6">
<div className="w-full max-w-4xl space-y-8">
<Card className="w-full shadow-lg rounded-lg overflow-hidden min-h-[300px]">
<Tabs defaultValue="profile" className="w-full h-full">
<TabsList className="grid w-full grid-cols-2">
<TabsTrigger value="profile" className="flex items-center justify-center py-4 text-lg">
<User className="mr-2 h-5 w-5" />
Profile
</TabsTrigger>
<TabsTrigger value="edit" className="flex items-center justify-center py-4 text-lg">
<Edit className="mr-2 h-5 w-5" />
Edit Profile
</TabsTrigger>
</TabsList>
<TabsContent value="profile" className="p-6">
<ProfileView user={user} />
</TabsContent>
<TabsContent value="edit" className="p-6">
<ProfileEdit user={user} onUpdateUser={handleUpdateUser} />
</TabsContent>
</Tabs>
</Card>

<CVList
cvs={cvs}
loading={loading}
onShareCV={handleShareCV}
onDeleteCV={handleDeleteCV}
/>
</div>
</div>
);
};

export default ProfileCard;
44 changes: 44 additions & 0 deletions Frontend/components/profileEdit.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import React, { useState } from 'react';
import { CardContent } from "@/components/ui/card"
import { Input } from "@/components/ui/input"
import { Button } from "@/components/ui/button"
import { Label } from "@/components/ui/label"

const ProfileEdit = ({ user, onUpdateUser }) => {
const [formData, setFormData] = useState(user);

const handleInputChange = (e) => {
const { name, value } = e.target;
setFormData(prevData => ({
...prevData,
[name]: value
}));
};

const handleSubmit = (e) => {
e.preventDefault();
onUpdateUser(formData);
};

return (
<CardContent className="p-6">
<form onSubmit={handleSubmit} className="space-y-4">
<div className="space-y-2">
<Label htmlFor="name">Nom</Label>
<Input id="name" name="name" value={formData.name} onChange={handleInputChange} />
</div>
<div className="space-y-2">
<Label htmlFor="email">Email</Label>
<Input id="email" name="email" type="email" value={formData.email} onChange={handleInputChange} />
</div>
<div className="space-y-2">
<Label htmlFor="password">Nouveau mot de passe</Label>
<Input id="password" name="password" type="password" onChange={handleInputChange} />
</div>
<Button type="submit">Mettre à jour le profil</Button>
</form>
</CardContent>
);
};

export default ProfileEdit;
37 changes: 37 additions & 0 deletions Frontend/components/profileView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React from 'react';
import { CardContent } from "@/components/ui/card"
import { Table, TableBody, TableCell, TableRow } from "@/components/ui/table"
import { Badge } from "@/components/ui/badge"

const ProfileView = ({ user }) => {
const { name = '', email = '', details = {} } = user;

return (
<CardContent className="p-6">
<div className="text-center mb-6">
<h2 className="text-2xl font-semibold mb-2">{name || 'Nom inconnu'}</h2>
<p className="text-gray-600">{email || 'Email non disponible'}</p>
</div>
<Table>
<TableBody>
{Object.entries(details).map(([key, value]) => (
<TableRow key={key}>
<TableCell className="font-medium">{key}</TableCell>
<TableCell className="text-right">
{typeof value === 'string' && ['Pending', 'Active'].includes(value) ? (
<Badge variant={value === 'Pending' ? 'warning' : 'success'}>
{value}
</Badge>
) : (
value || 'Non disponible'
)}
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</CardContent>
);
};

export default ProfileView;
50 changes: 50 additions & 0 deletions Frontend/components/ui/avatar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
"use client"

import * as React from "react"
import * as AvatarPrimitive from "@radix-ui/react-avatar"

import { cn } from "@/lib/utils"

const Avatar = React.forwardRef<
React.ElementRef<typeof AvatarPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>
>(({ className, ...props }, ref) => (
<AvatarPrimitive.Root
ref={ref}
className={cn(
"relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full",
className
)}
{...props}
/>
))
Avatar.displayName = AvatarPrimitive.Root.displayName

const AvatarImage = React.forwardRef<
React.ElementRef<typeof AvatarPrimitive.Image>,
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>
>(({ className, ...props }, ref) => (
<AvatarPrimitive.Image
ref={ref}
className={cn("aspect-square h-full w-full", className)}
{...props}
/>
))
AvatarImage.displayName = AvatarPrimitive.Image.displayName

const AvatarFallback = React.forwardRef<
React.ElementRef<typeof AvatarPrimitive.Fallback>,
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback>
>(({ className, ...props }, ref) => (
<AvatarPrimitive.Fallback
ref={ref}
className={cn(
"flex h-full w-full items-center justify-center rounded-full bg-muted",
className
)}
{...props}
/>
))
AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName

export { Avatar, AvatarImage, AvatarFallback }
36 changes: 36 additions & 0 deletions Frontend/components/ui/badge.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import * as React from "react"
import { cva, type VariantProps } from "class-variance-authority"

import { cn } from "@/lib/utils"

const badgeVariants = cva(
"inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
{
variants: {
variant: {
default:
"border-transparent bg-primary text-primary-foreground hover:bg-primary/80",
secondary:
"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
destructive:
"border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
outline: "text-foreground",
},
},
defaultVariants: {
variant: "default",
},
}
)

export interface BadgeProps
extends React.HTMLAttributes<HTMLDivElement>,
VariantProps<typeof badgeVariants> {}

function Badge({ className, variant, ...props }: BadgeProps) {
return (
<div className={cn(badgeVariants({ variant }), className)} {...props} />
)
}

export { Badge, badgeVariants }
Loading