diff --git a/app/components/talks/MyTalksList.tsx b/app/components/talks/MyTalksList.tsx index d6f3444..08be1a0 100644 --- a/app/components/talks/MyTalksList.tsx +++ b/app/components/talks/MyTalksList.tsx @@ -10,7 +10,7 @@ import { CardHeader, CardTitle, } from '@/components/ui/card'; -import { Talk, Room } from '@/lib/types'; +import { Talk } from '@/lib/types'; import { Pencil, Plus, Trash2, CalendarPlus } from 'lucide-react'; import { useSession } from 'next-auth/react'; import { useState, useMemo } from 'react'; diff --git a/app/components/talks/PendingTalksList.tsx b/app/components/talks/PendingTalksList.tsx index e37d1b2..c065187 100644 --- a/app/components/talks/PendingTalksList.tsx +++ b/app/components/talks/PendingTalksList.tsx @@ -10,7 +10,6 @@ import { CardHeader, CardTitle, } from '@/components/ui/card'; -import { levels } from '@/lib/mock-data'; import { Talk, TalkStatus } from '@/lib/types'; import { isOrganizer, isSpeaker } from '@/utils/auth.utils'; import { Pencil, Plus, Trash2 } from 'lucide-react'; @@ -126,7 +125,7 @@ export default function PendingTalksList({ {talk.subjects?.name} - {levels.find((l) => l.value === talk.level)?.label} + {talk.level} {talk.duration} min diff --git a/app/components/talks/ScheduledTalksList.tsx b/app/components/talks/ScheduledTalksList.tsx deleted file mode 100644 index 1c3de0c..0000000 --- a/app/components/talks/ScheduledTalksList.tsx +++ /dev/null @@ -1,46 +0,0 @@ -// components/talks/ScheduledTalksList.tsx -import { format } from 'date-fns'; -import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; -import StatusBadge from './StatusBadge'; -import { ScheduledTalk } from '@/lib/types'; - -interface ScheduledTalksListProps { - scheduledTalks: ScheduledTalk[]; -} - -export default function ScheduledTalksList({ scheduledTalks }: ScheduledTalksListProps) { - return ( - - - Talks programmés - - - {scheduledTalks.length === 0 ? ( -
- Aucun talk programmé pour le moment -
- ) : ( -
- {scheduledTalks.map((scheduledTalk, index) => ( -
-
-

{scheduledTalk.talk.title}

- -
-
-

Date: {format(scheduledTalk.slot.date, 'dd/MM/yyyy')}

-

- Horaire: {scheduledTalk.slot.startTime} - {scheduledTalk.slot.endTime} -

-

Salle: {scheduledTalk.room.name}

-

Durée: {scheduledTalk.talk.duration} min

-

Niveau: {scheduledTalk.talk.level}

-
-
- ))} -
- )} -
-
- ); -} diff --git a/app/components/talks/TalkDialog.tsx b/app/components/talks/TalkDialog.tsx index 55a86a8..ebe7ac5 100644 --- a/app/components/talks/TalkDialog.tsx +++ b/app/components/talks/TalkDialog.tsx @@ -19,28 +19,23 @@ import { SelectValue, } from '@/components/ui/select'; import { Textarea } from '@/components/ui/textarea'; -import { durations, emptyTalk, levels } from '@/lib/mock-data'; import { Talk, TalkLevel } from '@/lib/types'; import { useSession } from 'next-auth/react'; import { FormEvent, useEffect, useState } from 'react'; -// form subjects (must match your DB subjects.name) -export const subjects = [ - 'JavaScript', - 'TypeScript', - 'React', - 'Next.js', - 'Node.js', - 'Prisma', - 'GraphQL', - 'DevOps', - 'Architecture', - 'UX/UI', - 'Mobile', - 'Security', - 'Testing', - 'Performance', - 'Accessibility', +const durations = [ + { value: 30, label: '30 minutes' }, + { value: 60, label: '1 heure' }, + { value: 120, label: '2 heures' }, + { value: 180, label: '3 heures' }, + { value: 240, label: '4 heures' }, + { value: 300, label: '5 heures' }, + { value: 360, label: '6 heures' }, + { value: 420, label: '7 heures' }, + { value: 480, label: '8 heures' }, + { value: 540, label: '9 heures' }, + { value: 600, label: '10 heures' }, + { value: 660, label: '11 heures' }, ]; interface TalkDialogProps { @@ -53,17 +48,51 @@ interface TalkDialogProps { export default function TalkDialog({ isOpen, setIsOpen, talk, isNew, onSave }: TalkDialogProps) { const { data: session } = useSession(); - const [currentTalk, setCurrentTalk] = useState>(emptyTalk); + const emptyTalk = { + id: 0, + title: '', + description: '', + topic: '', + duration: 30, + level: 'beginner', + speakerId: 0, + }; + const [currentTalk, setCurrentTalk] = useState(emptyTalk); + const [subjects, setSubjects] = useState([]); + const [levels, setLevels] = useState<{ value: TalkLevel; label: string }[]>([]); useEffect(() => { if (!isOpen) return; if (!session?.user?.id) throw new Error('User ID is required'); - setCurrentTalk( - isNew ? { ...emptyTalk, speakerId: Number(session.user.id) } : { ...(talk as Talk) }, - ); + if (isNew) { + setCurrentTalk({ ...emptyTalk, speakerId: Number(session.user.id) }); + } else if (talk) { + setCurrentTalk({ + id: talk.id, + title: talk.title, + description: talk.description, + topic: talk.subjects?.name || '', + duration: talk.duration, + level: talk.level, + speakerId: talk.speakerId, + }); + } else { + setCurrentTalk(emptyTalk); + } + + // Fetch subjects + fetch('/api/references/subjects') + .then((res) => res.json()) + .then((data) => setSubjects(Array.isArray(data) ? data : [])) + .catch(() => setSubjects([])); + // Fetch levels + fetch('/api/references/talkLevels') + .then((res) => res.json()) + .then((data) => setLevels(Array.isArray(data) ? data : [])) + .catch(() => setLevels([])); }, [isOpen, isNew, talk, session]); - const handleInputChange = (field: keyof Omit, value: string | number | TalkLevel) => { + const handleInputChange = (field: string, value: string | number | TalkLevel) => { setCurrentTalk({ ...currentTalk, [field]: value }); }; diff --git a/app/components/talks/TalksList.tsx b/app/components/talks/TalksList.tsx index d6f3444..08be1a0 100644 --- a/app/components/talks/TalksList.tsx +++ b/app/components/talks/TalksList.tsx @@ -10,7 +10,7 @@ import { CardHeader, CardTitle, } from '@/components/ui/card'; -import { Talk, Room } from '@/lib/types'; +import { Talk } from '@/lib/types'; import { Pencil, Plus, Trash2, CalendarPlus } from 'lucide-react'; import { useSession } from 'next-auth/react'; import { useState, useMemo } from 'react'; diff --git a/app/components/talks/TalksSchedule.tsx b/app/components/talks/TalksSchedule.tsx index 4a69bdd..054285a 100644 --- a/app/components/talks/TalksSchedule.tsx +++ b/app/components/talks/TalksSchedule.tsx @@ -47,7 +47,7 @@ interface Slot { interface TalksScheduleProps { talks: Talk[]; - onScheduleTalk: (talkId: string, slotId: string) => void; + onScheduleTalk: (talkId: string) => void; } export default function TalksSchedule({ talks, onScheduleTalk }: TalksScheduleProps) { @@ -65,17 +65,6 @@ export default function TalksSchedule({ talks, onScheduleTalk }: TalksSchedulePr const [slots, setSlots] = useState([]); const [availableSlots, setAvailableSlots] = useState([]); - useEffect(() => { - const [dateParam] = selectedDate.toISOString().split('T'); - Promise.all([ - fetch(`/api/rooms/availability?date=${dateParam}`).then((r) => r.json()), - fetch(`/api/schedules?date=${dateParam}`).then((r) => r.json()), - ]).catch((err) => { - console.error(err); - alert('Erreur de chargement'); - }); - }, [selectedDate]); - // 1️⃣ Fetch rooms+slots once on mount useEffect(() => { const [dateParam] = selectedDate.toISOString().split('T'); // "2025-05-16" @@ -103,7 +92,7 @@ export default function TalksSchedule({ talks, onScheduleTalk }: TalksSchedulePr console.error(err); alert(err.message); }); - }, [selectedDate]); + }, [selectedDate, selectedTalk]); // 2️⃣ Compute availableSlots whenever date/room/slots change useEffect(() => { @@ -145,7 +134,7 @@ export default function TalksSchedule({ talks, onScheduleTalk }: TalksSchedulePr throw new Error(data.error || 'Échec de la planification'); } - onScheduleTalk(selectedTalk, selectedSlot); + onScheduleTalk(selectedTalk); const talk = talks.find((t) => t.id.toString() === selectedTalk)!; const room = rooms.find((r) => r.roomId === data.slot.roomId)!; @@ -162,8 +151,8 @@ export default function TalksSchedule({ talks, onScheduleTalk }: TalksSchedulePr setSelectedTalk(''); setSelectedSlot(''); - } catch (err: any) { - alert(err.message); + } catch (err) { + alert(err); } finally { setIsScheduling(false); } diff --git a/app/lib/mock-data.ts b/app/lib/mock-data.ts deleted file mode 100644 index 05096bd..0000000 --- a/app/lib/mock-data.ts +++ /dev/null @@ -1,154 +0,0 @@ -// lib/mock-data.ts -import { Talk, Room, Slot, LevelOption, DurationOption } from './types'; - -// Mock data pour le MVP -export const mockData: { - talks: Talk[]; - rooms: Room[]; - slots: Slot[]; -} = { - talks: [ - { - id: '1', - title: 'Introduction à React', - topic: 'Frontend', - description: 'Une introduction à React pour les débutants', - durationMinutes: 60, - level: 'beginner', - status: 'accepted', - speakerId: '1', - }, - { - id: '2', - title: 'Advanced TypeScript', - topic: 'Programming', - description: 'Découvrez les fonctionnalités avancées de TypeScript', - durationMinutes: 45, - level: 'advanced', - status: 'accepted', - speakerId: '2', - }, - { - id: '3', - title: 'M: CSS Grid Layout', - topic: 'Frontend', - description: 'Comment utiliser CSS Grid pour des mises en page complexes', - durationMinutes: 30, - level: 'intermediate', - status: 'accepted', - speakerId: '6', - }, - { - id: '4', - title: 'M: Introduction à Vue.js', - topic: 'Frontend', - description: 'Découvrez Vue.js et ses avantages', - durationMinutes: 45, - level: 'beginner', - status: 'pending', - speakerId: '6', - }, - { - id: '5', - title: 'DevOps pour débutants', - topic: 'Operations', - description: 'Les bases du DevOps et CI/CD', - durationMinutes: 60, - level: 'beginner', - status: 'pending', - speakerId: '5', - }, - ], - - rooms: [ - { id: '1', name: 'Salle A', capacity: 50 }, - { id: '2', name: 'Salle B', capacity: 100 }, - { id: '3', name: 'Salle C', capacity: 30 }, - { id: '4', name: 'Salle D', capacity: 200 }, - { id: '5', name: 'Salle E', capacity: 75 }, - ], - - slots: [ - { - id: '1', - date: new Date(2025, 4, 15), - startTime: '09:00', - endTime: '10:00', - roomId: '1', - talkId: null, - }, - { - id: '2', - date: new Date(2025, 4, 15), - startTime: '10:15', - endTime: '11:00', - roomId: '1', - talkId: null, - }, - { - id: '3', - date: new Date(2025, 4, 15), - startTime: '09:00', - endTime: '10:00', - roomId: '2', - talkId: null, - }, - { - id: '4', - date: new Date(2025, 4, 15), - startTime: '11:15', - endTime: '12:15', - roomId: '1', - talkId: null, - }, - { - id: '5', - date: new Date(2025, 4, 15), - startTime: '13:00', - endTime: '14:00', - roomId: '3', - talkId: null, - }, - { - id: '6', - date: new Date(2025, 4, 16), - startTime: '09:00', - endTime: '10:00', - roomId: '1', - talkId: null, - }, - { - id: '7', - date: new Date(2025, 4, 16), - startTime: '10:15', - endTime: '11:15', - roomId: '2', - talkId: null, - }, - ], -}; - -export const levels: LevelOption[] = [ - { value: 'beginner', label: 'Débutant' }, - { value: 'intermediate', label: 'Intermédiaire' }, - { value: 'advanced', label: 'Avancé' }, -]; - -export const durations: DurationOption[] = [ - { value: 15, label: '15 minutes' }, - { value: 30, label: '30 minutes' }, - { value: 45, label: '45 minutes' }, - { value: 60, label: '1 heure' }, - { value: 90, label: '1 heure 30' }, - { value: 120, label: '2 heures' }, -]; - -export const emptyTalk: Omit = { - title: '', - topic: '', - description: '', - durationMinutes: 30, - level: 'beginner', - status: 'pending', - speakerId: '', -}; diff --git a/app/pages/index.tsx b/app/pages/index.tsx index 48c1ebe..1b1a999 100644 --- a/app/pages/index.tsx +++ b/app/pages/index.tsx @@ -7,13 +7,10 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { Talk, TalkStatus } from '@/lib/types'; import { isOrganizer, isSpeaker } from '@/utils/auth.utils'; import { useSession } from 'next-auth/react'; -import { mockData } from '@/lib/mock-data'; -import MyTalksList from '@/components/talks/MyTalksList'; export default function TalksPage() { const { data: session, status } = useSession(); const [talks, setTalks] = useState([]); - // const [scheduledTalks, setScheduledTalks] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); @@ -52,18 +49,14 @@ export default function TalksPage() { }, [status, session?.user.roleId]); // Fonction pour programmer un talk - const scheduleTalk = (talkId: string, slotId: string) => { + const scheduleTalk = (talkId: string) => { const talk = talks.find((t) => String(t.id) === talkId); - const slot = mockData.slots.find((s) => s.id === slotId); - if (!talk || !slot) return; + if (!talk) return; const updatedTalk = { ...talk, status: 'scheduled' as const }; - const updatedSlot = { ...slot, talkId: talk.id }; setTalks((prev) => prev.map((t) => (t.id === talk.id ? updatedTalk : t))); - - return { updatedTalk, updatedSlot }; }; // Fonctions pour gérer les talks @@ -148,21 +141,12 @@ export default function TalksPage() { {/* Tab: Liste des talks */} - {isSpeaker(session?.user?.roleId) || isOrganizer(session?.user?.roleId) ? ( - - ) : ( - - )} + {/* Tab: Liste des talks en attente */}