diff --git a/Frontend/app/page.tsx b/Frontend/app/page.tsx index 38d6a1c..dbec3be 100644 --- a/Frontend/app/page.tsx +++ b/Frontend/app/page.tsx @@ -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; diff --git a/Frontend/app/profile/page.tsx b/Frontend/app/profile/page.tsx new file mode 100644 index 0000000..13812b9 --- /dev/null +++ b/Frontend/app/profile/page.tsx @@ -0,0 +1,14 @@ +import ProfileCard from "@/components/profileCard"; + +export default function Profile() { + const user = { + name: 'John Doe', + email: 'johndoe45@gmail.com', + }; + + return ( +
+ +
+ ); +} diff --git a/Frontend/components/cvList.tsx b/Frontend/components/cvList.tsx new file mode 100644 index 0000000..b9d81c4 --- /dev/null +++ b/Frontend/components/cvList.tsx @@ -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 ( + + + + + Mes CVs générés + + + + {loading ? ( +

Chargement des CVs...

+ ) : cvs.length > 0 ? ( + + + {cvs.map((cv) => ( + + {cv.name} + {cv.date} + + + + + + ))} + +
+ ) : ( +

Aucun CV généré pour le moment.

+ )} +
+
+ ); +}; + +export default CVList; \ No newline at end of file diff --git a/Frontend/components/profileCard.tsx b/Frontend/components/profileCard.tsx new file mode 100644 index 0000000..9884008 --- /dev/null +++ b/Frontend/components/profileCard.tsx @@ -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
Aucune donnée utilisateur disponible
; + } + + return ( +
+
+ + + + + + Profile + + + + Edit Profile + + + + + + + + + + + + +
+
+ ); +}; + +export default ProfileCard; \ No newline at end of file diff --git a/Frontend/components/profileEdit.tsx b/Frontend/components/profileEdit.tsx new file mode 100644 index 0000000..facbceb --- /dev/null +++ b/Frontend/components/profileEdit.tsx @@ -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 ( + +
+
+ + +
+
+ + +
+
+ + +
+ +
+
+ ); +}; + +export default ProfileEdit; \ No newline at end of file diff --git a/Frontend/components/profileView.tsx b/Frontend/components/profileView.tsx new file mode 100644 index 0000000..794b64f --- /dev/null +++ b/Frontend/components/profileView.tsx @@ -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 ( + +
+

{name || 'Nom inconnu'}

+

{email || 'Email non disponible'}

+
+ + + {Object.entries(details).map(([key, value]) => ( + + {key} + + {typeof value === 'string' && ['Pending', 'Active'].includes(value) ? ( + + {value} + + ) : ( + value || 'Non disponible' + )} + + + ))} + +
+
+ ); +}; + +export default ProfileView; \ No newline at end of file diff --git a/Frontend/components/ui/avatar.tsx b/Frontend/components/ui/avatar.tsx new file mode 100644 index 0000000..51e507b --- /dev/null +++ b/Frontend/components/ui/avatar.tsx @@ -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, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +Avatar.displayName = AvatarPrimitive.Root.displayName + +const AvatarImage = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AvatarImage.displayName = AvatarPrimitive.Image.displayName + +const AvatarFallback = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName + +export { Avatar, AvatarImage, AvatarFallback } diff --git a/Frontend/components/ui/badge.tsx b/Frontend/components/ui/badge.tsx new file mode 100644 index 0000000..f000e3e --- /dev/null +++ b/Frontend/components/ui/badge.tsx @@ -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, + VariantProps {} + +function Badge({ className, variant, ...props }: BadgeProps) { + return ( +
+ ) +} + +export { Badge, badgeVariants } diff --git a/Frontend/components/ui/table.tsx b/Frontend/components/ui/table.tsx new file mode 100644 index 0000000..7f3502f --- /dev/null +++ b/Frontend/components/ui/table.tsx @@ -0,0 +1,117 @@ +import * as React from "react" + +import { cn } from "@/lib/utils" + +const Table = React.forwardRef< + HTMLTableElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+ + +)) +Table.displayName = "Table" + +const TableHeader = React.forwardRef< + HTMLTableSectionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + +)) +TableHeader.displayName = "TableHeader" + +const TableBody = React.forwardRef< + HTMLTableSectionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + +)) +TableBody.displayName = "TableBody" + +const TableFooter = React.forwardRef< + HTMLTableSectionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + tr]:last:border-b-0", + className + )} + {...props} + /> +)) +TableFooter.displayName = "TableFooter" + +const TableRow = React.forwardRef< + HTMLTableRowElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + +)) +TableRow.displayName = "TableRow" + +const TableHead = React.forwardRef< + HTMLTableCellElement, + React.ThHTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +TableHead.displayName = "TableHead" + +const TableCell = React.forwardRef< + HTMLTableCellElement, + React.TdHTMLAttributes +>(({ className, ...props }, ref) => ( + +)) +TableCell.displayName = "TableCell" + +const TableCaption = React.forwardRef< + HTMLTableCaptionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +TableCaption.displayName = "TableCaption" + +export { + Table, + TableHeader, + TableBody, + TableFooter, + TableHead, + TableRow, + TableCell, + TableCaption, +} diff --git a/Frontend/components/ui/tabs.tsx b/Frontend/components/ui/tabs.tsx new file mode 100644 index 0000000..26eb109 --- /dev/null +++ b/Frontend/components/ui/tabs.tsx @@ -0,0 +1,55 @@ +"use client" + +import * as React from "react" +import * as TabsPrimitive from "@radix-ui/react-tabs" + +import { cn } from "@/lib/utils" + +const Tabs = TabsPrimitive.Root + +const TabsList = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +TabsList.displayName = TabsPrimitive.List.displayName + +const TabsTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +TabsTrigger.displayName = TabsPrimitive.Trigger.displayName + +const TabsContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +TabsContent.displayName = TabsPrimitive.Content.displayName + +export { Tabs, TabsList, TabsTrigger, TabsContent } diff --git a/Frontend/package-lock.json b/Frontend/package-lock.json index 36ac746..9dc940f 100644 --- a/Frontend/package-lock.json +++ b/Frontend/package-lock.json @@ -10,7 +10,9 @@ "dependencies": { "@hookform/resolvers": "^3.9.0", "@nanostores/persistent": "^0.10.2", + "@radix-ui/react-avatar": "^1.1.0", "@radix-ui/react-slot": "^1.0.2", + "@radix-ui/react-tabs": "^1.1.0", "@radix-ui/themes": "^3.1.3", "axios": "^1.7.7", "class-variance-authority": "^0.7.0", @@ -603,6 +605,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-avatar/-/react-avatar-1.1.0.tgz", "integrity": "sha512-Q/PbuSMk/vyAd/UoIShVGZ7StHHeRFYU7wXmi5GV+8cLXflZAEpHL/F697H1klrzxKXNtZ97vWiC0q3RKUH8UA==", + "license": "MIT", "dependencies": { "@radix-ui/react-context": "1.1.0", "@radix-ui/react-primitive": "2.0.0", @@ -1416,6 +1419,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.0.tgz", "integrity": "sha512-bZgOKB/LtZIij75FSuPzyEti/XBhJH52ExgtdVqjCIh+Nx/FW+LhnbXtbCzIi34ccyMsyOja8T0thCzoHFXNKA==", + "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.0", "@radix-ui/react-context": "1.1.0", diff --git a/Frontend/package.json b/Frontend/package.json index 11fbacb..29e6f37 100644 --- a/Frontend/package.json +++ b/Frontend/package.json @@ -11,7 +11,9 @@ "dependencies": { "@hookform/resolvers": "^3.9.0", "@nanostores/persistent": "^0.10.2", + "@radix-ui/react-avatar": "^1.1.0", "@radix-ui/react-slot": "^1.0.2", + "@radix-ui/react-tabs": "^1.1.0", "@radix-ui/themes": "^3.1.3", "axios": "^1.7.7", "class-variance-authority": "^0.7.0",