From 2723806c49146bdd3fff9b31e283fced733e0e12 Mon Sep 17 00:00:00 2001 From: Minoti Date: Mon, 16 Feb 2026 00:42:58 +0530 Subject: [PATCH 1/4] Integrate event and schedule page --- build_log.txt | 2 + src/components/events/attendance-actions.tsx | 20 +- src/components/events/event-card.tsx | 27 +- src/components/events/mock-data.ts | 234 ++++++++---------- src/components/events/schedule-card.tsx | 22 +- src/hooks/use-attendance.ts | 24 +- src/hooks/use-events.ts | 19 +- src/lib/api-endpoints.ts | 2 +- src/routes/events/$eventId/index.tsx | 24 +- .../events/$eventId/schedules/$scheduleId.tsx | 92 ++++--- src/routes/events/index.tsx | 24 +- src/types/events.ts | 49 ++-- 12 files changed, 298 insertions(+), 241 deletions(-) create mode 100644 build_log.txt diff --git a/build_log.txt b/build_log.txt new file mode 100644 index 0000000..39f6be3 --- /dev/null +++ b/build_log.txt @@ -0,0 +1,2 @@ +src/components/events/attendance-actions.tsx(32,26): error TS2339: Property 'markingType' does not exist on type 'Schedule'. +src/hooks/use-attendance.ts(16,22): error TS2339: Property 'GET_EVENT_SCHEDULES' does not exist on type '{ readonly ORGANIZER_LOGIN: "/auth/organizer/login"; readonly ORGANIZER_LOGOUT: "/auth/organizer/logout"; readonly ORGANIZER_SESSION: "/auth/organizer/session"; readonly GET_ORGANIZER_EVENTS: "/attendance/list/event"; ... 21 more ...; readonly GATE_CHECKOUT: (hospId: string) => string; }'. diff --git a/src/components/events/attendance-actions.tsx b/src/components/events/attendance-actions.tsx index 6a4f574..e5a2c8b 100644 --- a/src/components/events/attendance-actions.tsx +++ b/src/components/events/attendance-actions.tsx @@ -14,22 +14,22 @@ import { LogIn, LogOut, } from "lucide-react" -import type { Schedule, Participant } from "@/types/events" +import type { Participant } from "@/types/events" interface AttendanceActionsProps { participant: Participant - schedule: Schedule + markingType: "SOLO" | "DUO" onMark: (type: "CHECKIN" | "CHECKOUT" | "BOTH") => void onUnmark: (type: "CHECKIN" | "CHECKOUT" | "BOTH") => void } export function AttendanceActions({ participant, - schedule, + markingType, onMark, onUnmark, }: AttendanceActionsProps) { - const isDuo = schedule.markingType === "DUO" + const isDuo = markingType === "DUO" // const isGroup = schedule.type === "GROUP" // Logic might differ if needed, but actions are similar return ( @@ -56,7 +56,7 @@ export function AttendanceActions({ {/* DUO MARKING: Check In / Check Out */} onMark("CHECKIN")} - disabled={participant.checkInStatus} + disabled={!!participant.check_in} className="focus:bg-green-900/50 focus:text-green-300 cursor-pointer" > @@ -65,7 +65,7 @@ export function AttendanceActions({ onMark("CHECKOUT")} - disabled={participant.checkOutStatus} + disabled={!!participant.check_out} className="focus:bg-blue-900/50 focus:text-blue-300 cursor-pointer" > @@ -76,7 +76,7 @@ export function AttendanceActions({ onUnmark("CHECKIN")} - disabled={!participant.checkInStatus} + disabled={!participant.check_in} className="focus:bg-red-900/50 focus:text-red-300 cursor-pointer" > @@ -85,7 +85,7 @@ export function AttendanceActions({ onUnmark("CHECKOUT")} - disabled={!participant.checkOutStatus} + disabled={!participant.check_out} className="focus:bg-red-900/50 focus:text-red-300 cursor-pointer" > @@ -97,7 +97,7 @@ export function AttendanceActions({ {/* SOLO MARKING: One time mark */} onMark("BOTH")} - disabled={participant.attendanceStatus} + disabled={!!participant.check_in} className="focus:bg-green-900/50 focus:text-green-300 cursor-pointer" > @@ -108,7 +108,7 @@ export function AttendanceActions({ onUnmark("BOTH")} - disabled={!participant.attendanceStatus} + disabled={!participant.check_in} className="focus:bg-red-900/50 focus:text-red-300 cursor-pointer" > diff --git a/src/components/events/event-card.tsx b/src/components/events/event-card.tsx index 65e6985..26c3a05 100644 --- a/src/components/events/event-card.tsx +++ b/src/components/events/event-card.tsx @@ -1,4 +1,5 @@ import { Link } from "@tanstack/react-router" +import { Building2 } from "lucide-react" import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" import { cn } from "@/lib/utils" import type { EventCardProps } from "@/types/events" @@ -8,12 +9,22 @@ export function EventCard({ className, isActive = false, }: EventCardProps) { - const isGroup = event.type === "GROUP" + const isGroup = event.is_group + + // Derive date from first schedule or fallback + const eventDate = event.schedules?.[0]?.event_date + + const formattedDate = eventDate + ? new Date(eventDate).toLocaleDateString("en-GB", { + day: "numeric", + month: "short", + }) + : "TBD" return (
- {event.name} + {event.event_name} {/* Type Badges - DISTINCT COLORS */} @@ -57,14 +68,20 @@ export function EventCard({
-
+
+ + {event.organizer || "Organizer TBD"} +
+
+ {" "} + {/* Added mt-2 for spacing */}
- {event.day} + {formattedDate}
diff --git a/src/components/events/mock-data.ts b/src/components/events/mock-data.ts index beb238e..dfc5a86 100644 --- a/src/components/events/mock-data.ts +++ b/src/components/events/mock-data.ts @@ -2,44 +2,84 @@ import type { Event, Schedule, Participant } from "@/types/events" export const MOOCK_EVENTS: Event[] = [ { - id: "1", - name: "Tech Talk 2024", + event_id: "1", + event_name: "Tech Talk 2024", organizer: "Computer Science Dept", - day: "20 Feb", - type: "INDIVIDUAL", - markingType: "SOLO", + is_group: false, + attendance_mode: "SOLO", + schedules: [ + { + id: "s1", + title: "Morning Session", + venue: "Auditorium A", + start_time: "10:00 AM", + end_time: "12:00 PM", + event_date: "20 Feb 2024", + eventId: "1", + }, + ], }, { - id: "2", - name: "Cultural Fest", + event_id: "2", + event_name: "Cultural Fest", organizer: "Arts Club", - day: "21 Feb", - type: "GROUP", - markingType: "SOLO", + is_group: true, + attendance_mode: "SOLO", + schedules: [ + { + id: "s2", + title: "Dance Competition", + venue: "Open Air Theatre", + start_time: "05:00 PM", + end_time: "08:00 PM", + event_date: "21 Feb 2024", + eventId: "2", + }, + ], }, { - id: "4", - name: "Coding Marathon", + event_id: "4", + event_name: "Coding Marathon", organizer: "Computer Science Dept", - day: "20 Feb", - type: "INDIVIDUAL", - markingType: "DUO", + is_group: false, + attendance_mode: "DUO", + schedules: [ + { + id: "s3", + title: "Hackathon Round 1", + venue: "Lab 201", + start_time: "09:00 AM", + end_time: "05:00 PM", + event_date: "20 Feb 2024", + eventId: "4", + }, + ], }, { - id: "5", - name: "Music Concert", + event_id: "5", + event_name: "Music Concert", organizer: "Music Club", - day: "21 Feb", - type: "GROUP", - markingType: "DUO", + is_group: true, + attendance_mode: "DUO", + schedules: [ + { + id: "s4", + title: "Band Rehearsals", + venue: "Music Room", + start_time: "02:00 PM", + end_time: "04:00 PM", + event_date: "21 Feb 2024", + eventId: "5", + }, + ], }, { - id: "7", - name: "AI Seminar", + event_id: "7", + event_name: "AI Seminar", organizer: "AI Research Group", - day: "20 Feb", - type: "INDIVIDUAL", - markingType: "SOLO", + is_group: false, + attendance_mode: "SOLO", + schedules: [], }, ] @@ -61,12 +101,10 @@ export const MOCK_SCHEDULES: Record = { id: "s1", title: "Morning Session", venue: "Auditorium A", - startTime: "10:00 AM", - endTime: "12:00 PM", - date: "20 Feb 2024", + start_time: "10:00 AM", + end_time: "12:00 PM", + event_date: "20 Feb 2024", eventId: "1", - type: "INDIVIDUAL", - markingType: "SOLO", }, ], "2": [ @@ -75,12 +113,10 @@ export const MOCK_SCHEDULES: Record = { id: "s2", title: "Dance Competition", venue: "Open Air Theatre", - startTime: "05:00 PM", - endTime: "08:00 PM", - date: "21 Feb 2024", + start_time: "05:00 PM", + end_time: "08:00 PM", + event_date: "21 Feb 2024", eventId: "2", - type: "GROUP", - markingType: "SOLO", }, ], "4": [ @@ -89,12 +125,10 @@ export const MOCK_SCHEDULES: Record = { id: "s3", title: "Hackathon Round 1", venue: "Lab 201", - startTime: "09:00 AM", - endTime: "05:00 PM", - date: "20 Feb 2024", + start_time: "09:00 AM", + end_time: "05:00 PM", + event_date: "20 Feb 2024", eventId: "4", - type: "INDIVIDUAL", - markingType: "DUO", }, ], "5": [ @@ -103,12 +137,10 @@ export const MOCK_SCHEDULES: Record = { id: "s4", title: "Band Rehearsals", venue: "Music Room", - startTime: "02:00 PM", - endTime: "04:00 PM", - date: "21 Feb 2024", + start_time: "02:00 PM", + end_time: "04:00 PM", + event_date: "21 Feb 2024", eventId: "5", - type: "GROUP", - markingType: "DUO", }, ], } @@ -118,97 +150,49 @@ export const MOCK_PARTICIPANTS: Record = { s1: [ // Individual, Solo { - id: "p1", - name: "Alice Johnson", - email: "alice@example.com", - checkInStatus: false, - checkOutStatus: false, - attendanceStatus: false, + attendance_id: "p1", + student_id: "s1", + student_name: "Alice Johnson", + student_email: "alice@example.com", + check_in: null, + check_out: null, }, { - id: "p2", - name: "Bob Smith", - email: "bob@example.com", - checkInStatus: false, - checkOutStatus: false, - attendanceStatus: true, + attendance_id: "p2", + student_id: "s2", + student_name: "Bob Smith", + student_email: "bob@example.com", + check_in: "2023-10-27T10:00:00Z", + check_out: null, }, { - id: "p3", - name: "Charlie Brown", - email: "charlie@example.com", - checkInStatus: false, - checkOutStatus: false, - attendanceStatus: false, - }, - ], - s2: [ - // Group, Solo - { - id: "g1", - name: "Team Alphas", - email: "leader@alphas.com", - teamName: "Alphas", - checkInStatus: false, - checkOutStatus: false, - attendanceStatus: true, - }, - { - id: "g2", - name: "Team Betas", - email: "contact@betas.com", - teamName: "Betas", - checkInStatus: false, - checkOutStatus: false, - attendanceStatus: false, - }, - ], - s3: [ - // Individual, Duo - { - id: "p4", - name: "David Lee", - email: "david@example.com", - checkInStatus: true, - checkOutStatus: false, - attendanceStatus: false, - }, - { - id: "p5", - name: "Eva Green", - email: "eva@example.com", - checkInStatus: true, - checkOutStatus: true, - attendanceStatus: true, - }, // Both marked - { - id: "p6", - name: "Frank White", - email: "frank@example.com", - checkInStatus: false, - checkOutStatus: false, - attendanceStatus: false, + attendance_id: "p3", + student_id: "s3", + student_name: "Charlie Brown", + student_email: "charlie@example.com", + check_in: null, + check_out: null, }, ], s4: [ // Group, Duo { - id: "g3", - name: "The Rockers", - email: "rockers@band.com", - teamName: "The Rockers", - checkInStatus: true, - checkOutStatus: false, - attendanceStatus: false, + attendance_id: "g3", + student_id: "s4", + student_name: "The Rockers", + student_email: "rockers@band.com", + team_name: "The Rockers", + check_in: "2023-10-27T14:00:00Z", + check_out: null, }, { - id: "g4", - name: "Jazz Hands", - email: "jazz@band.com", - teamName: "Jazz Hands", - checkInStatus: false, - checkOutStatus: false, - attendanceStatus: false, + attendance_id: "g4", + student_id: "s5", + student_name: "Jazz Hands", + student_email: "jazz@band.com", + team_name: "Jazz Hands", + check_in: null, + check_out: null, }, ], } diff --git a/src/components/events/schedule-card.tsx b/src/components/events/schedule-card.tsx index 254d6b8..6eea62c 100644 --- a/src/components/events/schedule-card.tsx +++ b/src/components/events/schedule-card.tsx @@ -1,6 +1,6 @@ import { Link } from "@tanstack/react-router" import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" -import { CalendarDays, Clock, MapPin } from "lucide-react" +import { CalendarDays, MapPin } from "lucide-react" import { cn } from "@/lib/utils" import type { Schedule } from "@/types/events" @@ -10,6 +10,14 @@ interface ScheduleCardProps { className?: string } +function formatTime(dateStr: string) { + return new Date(dateStr).toLocaleTimeString("en-US", { + hour: "numeric", + minute: "2-digit", + hour12: true, + }) +} + export function ScheduleCard({ schedule, eventId, @@ -33,7 +41,8 @@ export function ScheduleCard({
- {schedule.title} + {formatTime(schedule.start_time)} -{" "} + {formatTime(schedule.end_time)} {/* Badges removed as per user request */}
@@ -45,16 +54,9 @@ export function ScheduleCard({ {schedule.venue}
-
- - - {schedule.startTime} - {schedule.endTime} - -
-
- {schedule.date} + {schedule.event_date}
diff --git a/src/hooks/use-attendance.ts b/src/hooks/use-attendance.ts index 9d4398e..1a9fe5d 100644 --- a/src/hooks/use-attendance.ts +++ b/src/hooks/use-attendance.ts @@ -13,9 +13,18 @@ export function useParticipants(eventId: string, scheduleId: string) { // Fetch participants for a specific schedule // Note: Endpoint name GET_EVENT_SCHEDULES is confusing but based on usage it seems to be for this const response = await axiosClient.get( - apiEndpoints.GET_EVENT_SCHEDULES(eventId, scheduleId) + apiEndpoints.GET_EVENT_PARTICIPANTS(eventId, scheduleId) ) - return response.data as Participant[] + + // Safe parsing: Check if it's strictly an array or wrapped + const data = response.data + if (Array.isArray(data)) return data as Participant[] + if (data && Array.isArray(data.participants)) + return data.participants as Participant[] + if (data && Array.isArray(data.data)) return data.data as Participant[] + + console.warn("useParticipants: Expected array but got:", data) + return [] }, enabled: !!eventId && !!scheduleId, }) @@ -165,15 +174,8 @@ export function useUnmarkAttendance() { if (!endpoint) throw new Error("Invalid unmarking configuration") - // Unmarking usually is also a POST or DELETE? Assuming DELETE or POST based on typical conventions, - // but generated endpoints imply specific URLs. Most likely these are POST or DELETE. - // Checking api-endpoints.ts... it just gives the URL string. - // Typically 'unMark' implies a state change, likely DELETE or POST. - // I'll stick with POST for now unless I see otherwise in the backend docs (which I don't have). - // Or maybe DELETE? `axiosClient.delete(endpoint)` - // Let's assume POST for /unMark/... pattern unless commonly RESTful. - // Actually, safest is usually POST for RPC-style "unMark" URLs. - const response = await axiosClient.post(endpoint) + // Backend expects DELETE for unmark routes + const response = await axiosClient.delete(endpoint) return response.data }, onSuccess: (_, { scheduleId }) => { diff --git a/src/hooks/use-events.ts b/src/hooks/use-events.ts index e6f39e4..25912de 100644 --- a/src/hooks/use-events.ts +++ b/src/hooks/use-events.ts @@ -9,9 +9,22 @@ export function useOrganizerEvents() { queryFn: async () => { // Fetch organizer events const response = await axiosClient.get(apiEndpoints.GET_ORGANIZER_EVENTS) - // We assume the response data is the list of events directly or in a standard wrapper - // Adjust this if your API returns { data: [...] } or similiar - return response.data as Event[] + console.log("Events API Response:", response.data) // Debugging + + // Handle different response structures + if (Array.isArray(response.data)) { + return response.data as Event[] + } else if (response.data && Array.isArray((response.data as any).data)) { + return (response.data as any).data as Event[] + } else if ( + response.data && + Array.isArray((response.data as any).events) + ) { + return (response.data as any).events as Event[] + } + + console.error("Unexpected API response structure:", response.data) + return [] // Return empty array to prevent filter error }, }) } diff --git a/src/lib/api-endpoints.ts b/src/lib/api-endpoints.ts index d8204b9..29c2081 100644 --- a/src/lib/api-endpoints.ts +++ b/src/lib/api-endpoints.ts @@ -7,7 +7,7 @@ export const apiEndpoints = { GET_ORGANIZER_EVENTS: "/attendance/list/event", // schedules page - GET_EVENT_SCHEDULES: (eventId: string, scheduleId: string) => + GET_EVENT_PARTICIPANTS: (eventId: string, scheduleId: string) => `/attendance/list/${eventId}/${scheduleId}`, // ATTENDANCE SCANNER ENDPOINTS diff --git a/src/routes/events/$eventId/index.tsx b/src/routes/events/$eventId/index.tsx index bc75253..98a3b73 100644 --- a/src/routes/events/$eventId/index.tsx +++ b/src/routes/events/$eventId/index.tsx @@ -1,7 +1,6 @@ import { createFileRoute, Link } from "@tanstack/react-router" -import { ArrowLeft, CalendarDays, Building2, Loader2 } from "lucide-react" +import { ArrowLeft, CalendarDays, Loader2 } from "lucide-react" import { ScheduleCard } from "@/components/events/schedule-card" -import { MOCK_SCHEDULES } from "@/components/events/mock-data" import { useOrganizerEvents } from "@/hooks/use-events" import { useEventStore } from "@/store/event-store" import { useEffect, useMemo } from "react" @@ -18,11 +17,11 @@ function EventDetailPage() { const { data: events, isLoading, isError } = useOrganizerEvents() const event = useMemo(() => { - return events?.find((e) => e.id === eventId) + return events?.find((e) => e.event_id === eventId) }, [events, eventId]) // Mock schedules for now as endpoint is ambiguous - const schedules = MOCK_SCHEDULES[eventId] ?? [] + const schedules = event?.schedules ?? [] // Update store on load useEffect(() => { @@ -64,6 +63,15 @@ function EventDetailPage() { // Safe to assert event is defined here due to check above const safeEvent = event! + // Derive date + const eventDate = safeEvent.schedules?.[0]?.event_date + const formattedDate = eventDate + ? new Date(eventDate).toLocaleDateString("en-GB", { + day: "numeric", + month: "short", + }) + : "TBD" + return (

- {safeEvent.name} + {safeEvent.event_name}

-
- - {safeEvent.organizer} -
- {safeEvent.day} + {formattedDate}
diff --git a/src/routes/events/$eventId/schedules/$scheduleId.tsx b/src/routes/events/$eventId/schedules/$scheduleId.tsx index 2877d79..a4ad3a7 100644 --- a/src/routes/events/$eventId/schedules/$scheduleId.tsx +++ b/src/routes/events/$eventId/schedules/$scheduleId.tsx @@ -4,7 +4,6 @@ import { ArrowLeft, Search, Users, QrCode } from "lucide-react" import { useEventStore } from "@/store/event-store" import { SoloAttendanceScanner } from "@/components/events/solo-attendance-scanner" import { DuoAttendanceScanner } from "@/components/events/duo-attendance-scanner" -import { MOCK_SCHEDULES, MOOCK_EVENTS } from "@/components/events/mock-data" import { Input } from "@/components/ui/input" import { Table, @@ -28,6 +27,7 @@ import { useMarkAttendance, useUnmarkAttendance, } from "@/hooks/use-attendance" +import { useOrganizerEvents } from "@/hooks/use-events" import { Loader2 } from "lucide-react" // ... imports ... @@ -56,10 +56,19 @@ function ScheduleParticipantPage() { console.error("Failed to fetch participants") } - // Simulate Data Fetching for Event/Schedule (or use store if already populated) - // We use store or mock fetch for metadata as before, but participants come from API - const event = MOOCK_EVENTS.find((e) => e.id === eventId) - const schedule = MOCK_SCHEDULES[eventId]?.find((s) => s.id === scheduleId) + // Retrieve event from store or query (not ideal if deep linking without data, but for now relies on store/cache) + // In a real app, useQuery with select or similar. + // Accessing query client cache directly or using the hook again would be better. + const { data: events } = useOrganizerEvents() + + const event = useMemo( + () => events?.find((e) => e.event_id === eventId), + [events, eventId] + ) + const schedule = useMemo( + () => event?.schedules.find((s) => s.id === scheduleId), + [event, scheduleId] + ) // Local state for participants to handle optimistic updates or just syncing const [participants, setParticipants] = useState([]) @@ -86,12 +95,17 @@ function ScheduleParticipantPage() { // Filter Logic const filteredParticipants = useMemo(() => { + if (!Array.isArray(participants)) return [] return participants.filter( (p) => - p.name.toLowerCase().includes(searchQuery.toLowerCase()) || - p.email.toLowerCase().includes(searchQuery.toLowerCase()) || - (p.teamName && - p.teamName.toLowerCase().includes(searchQuery.toLowerCase())) + (p.student_name || "") + .toLowerCase() + .includes(searchQuery.toLowerCase()) || + (p.student_email || "") + .toLowerCase() + .includes(searchQuery.toLowerCase()) || + (p.team_name && + p.team_name.toLowerCase().includes(searchQuery.toLowerCase())) ) }, [participants, searchQuery]) @@ -107,11 +121,11 @@ function ScheduleParticipantPage() { participantId: string, type: "CHECKIN" | "CHECKOUT" | "BOTH" ) => { - if (!schedule) return + if (!schedule || !event) return const studentId = participantId // Assuming participantId is the studentId - const isTeam = schedule.type === "GROUP" - const markingType = schedule.markingType + const isTeam = event.is_group + const markingType = event.attendance_mode markAttendance({ studentId, @@ -126,11 +140,11 @@ function ScheduleParticipantPage() { participantId: string, type: "CHECKIN" | "CHECKOUT" | "BOTH" ) => { - if (!schedule) return + if (!schedule || !event) return const studentId = participantId - const isTeam = schedule.type === "GROUP" - const markingType = schedule.markingType + const isTeam = event.is_group + const markingType = event.attendance_mode unmarkAttendance({ studentId, @@ -159,8 +173,8 @@ function ScheduleParticipantPage() { ) } - const isGroup = schedule.type === "GROUP" - const isDuo = schedule.markingType === "DUO" + const isGroup = event?.is_group ?? false + const isDuo = event?.attendance_mode === "DUO" return (
- {selectedEvent?.name} + {selectedEvent?.event_name}

- {schedule.title} + {schedule.title || "Participant details"}

@@ -219,25 +233,27 @@ function ScheduleParticipantPage() { {paginatedParticipants.length > 0 ? ( paginatedParticipants.map((p) => (
- {p.name} + {p.student_name} + + + {p.student_email} - {p.email} - {/* Team Name badge moved here */} - {isGroup && p.teamName && ( + {/* Team Name badge - checking if team_name exists (it might not be in API yet) */} + {isGroup && p.team_name && (
- {p.teamName} + {p.team_name}
)} @@ -250,9 +266,9 @@ function ScheduleParticipantPage() { // DUO Status badges
) : ( - // SOLO Status badge + // SOLO Status badge (Present if check_in is not null) - {p.attendanceStatus ? "PRESENT" : "ABSENT"} + {p.check_in ? "PRESENT" : "ABSENT"} )}
@@ -288,9 +304,9 @@ function ScheduleParticipantPage() { handleMark(p.id, type)} - onUnmark={(type) => handleUnmark(p.id, type)} + markingType={event?.attendance_mode || "SOLO"} + onMark={(type) => handleMark(p.student_id, type)} + onUnmark={(type) => handleUnmark(p.student_id, type)} />
@@ -348,14 +364,14 @@ function ScheduleParticipantPage() { {showScanner && (isDuo ? ( setShowScanner(false)} isTeamEvent={isGroup} /> ) : ( setShowScanner(false)} isTeamEvent={isGroup} diff --git a/src/routes/events/index.tsx b/src/routes/events/index.tsx index f4675b4..92053f0 100644 --- a/src/routes/events/index.tsx +++ b/src/routes/events/index.tsx @@ -21,10 +21,26 @@ function EventsPage() { const filteredEvents = useMemo(() => { if (!events) return [] return events.filter((event) => { + const name = event.event_name || "" + const organizer = event.organizer || "" const matchesSearch = - event.name.toLowerCase().includes(searchQuery.toLowerCase()) || - event.organizer.toLowerCase().includes(searchQuery.toLowerCase()) - const matchesDay = selectedDay === "All" || event.day === selectedDay + name.toLowerCase().includes(searchQuery.toLowerCase()) || + organizer.toLowerCase().includes(searchQuery.toLowerCase()) + + // Check if any schedule matches the selected day + // Basic match for now: check if schedule date string contains selectedDay (e.g. "20 Feb") + // OR parse date properly. Assuming simpler string match or derived logic for now. + const hasMatchingDay = event.schedules?.some((s) => { + if (!s.event_date) return false + // Simple check: format date and check equality + const d = new Date(s.event_date).toLocaleDateString("en-GB", { + day: "numeric", + month: "short", + }) + return d === selectedDay + }) + + const matchesDay = selectedDay === "All" || hasMatchingDay return matchesSearch && matchesDay }) @@ -101,7 +117,7 @@ function EventsPage() {
{filteredEvents.length > 0 ? ( filteredEvents.map((event) => ( - + )) ) : (
diff --git a/src/types/events.ts b/src/types/events.ts index e119c57..8c31fb2 100644 --- a/src/types/events.ts +++ b/src/types/events.ts @@ -1,38 +1,39 @@ -// Event entity type export interface Event { - id: string - name: string - organizer: string - day: "20 Feb" | "21 Feb" - type: "INDIVIDUAL" | "GROUP" // <--- Added for badge on Event Card - markingType?: "SOLO" | "DUO" // <--- Optional, good for context + event_id: string + event_name: string + organizer?: string // Optional as per real API response + // event_date (or day) might come from schedules or be a derived property. + // Backend likely returns 'schedules' array. + schedules: Schedule[] + is_group: boolean + attendance_mode: "SOLO" | "DUO" + // kept for backward compat if needed, but likely removed/derived + // day: "20 Feb" | "21 Feb" } // Schedule entity type export interface Schedule { id: string - title: string + title?: string // Missing in real API, make optional venue: string - startTime: string - endTime: string - date: string - eventId: string - type: "INDIVIDUAL" | "GROUP" - markingType: "SOLO" | "DUO" + start_time: string + end_time: string + event_date: string + eventId?: string // Missing in nested API object + // type: "INDIVIDUAL" | "GROUP" // likely derived from Event + // markingType: "SOLO" | "DUO" // likely derived from Event } // Participant entity type export interface Participant { - id: string - name: string - email: string - teamName?: string // Only for Group events - // Attendance status - // For SOLO: "PRESENT" | "ABSENT" - // For DUO: checkInStatus, checkOutStatus - checkInStatus: boolean - checkOutStatus: boolean - attendanceStatus: boolean // For SOLO marking, typically maps to this + attendance_id: string | number + student_id: string + student_name: string + student_email: string + check_in: string | null // ISO timestamp or null + check_out: string | null // ISO timestamp or null + // computed or optional fields + team_name?: string // Not present in current backend query, keeping as optional } // Event card props From 7aac9c043c7588239e6230a02fe6af2230ec0494 Mon Sep 17 00:00:00 2001 From: Kiran Rajeev <145009677+KiranRajeev-KV@users.noreply.github.com> Date: Mon, 16 Feb 2026 12:22:32 +0530 Subject: [PATCH 2/4] Delete build_log.txt --- build_log.txt | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 build_log.txt diff --git a/build_log.txt b/build_log.txt deleted file mode 100644 index 39f6be3..0000000 --- a/build_log.txt +++ /dev/null @@ -1,2 +0,0 @@ -src/components/events/attendance-actions.tsx(32,26): error TS2339: Property 'markingType' does not exist on type 'Schedule'. -src/hooks/use-attendance.ts(16,22): error TS2339: Property 'GET_EVENT_SCHEDULES' does not exist on type '{ readonly ORGANIZER_LOGIN: "/auth/organizer/login"; readonly ORGANIZER_LOGOUT: "/auth/organizer/logout"; readonly ORGANIZER_SESSION: "/auth/organizer/session"; readonly GET_ORGANIZER_EVENTS: "/attendance/list/event"; ... 21 more ...; readonly GATE_CHECKOUT: (hospId: string) => string; }'. From 74bc396536e489a151aab615620b96a990a5921c Mon Sep 17 00:00:00 2001 From: KiranRajeev-KV Date: Mon, 16 Feb 2026 12:32:37 +0530 Subject: [PATCH 3/4] feat: integrate organizer session check and logout functionality in events routes --- src/components/events/event-card.tsx | 4 ++-- src/routes/events.tsx | 13 ++++++++++++- src/routes/events/index.tsx | 11 ++++++++--- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/components/events/event-card.tsx b/src/components/events/event-card.tsx index 26c3a05..85e57ce 100644 --- a/src/components/events/event-card.tsx +++ b/src/components/events/event-card.tsx @@ -68,10 +68,10 @@ export function EventCard({
-
+ {/*
{event.organizer || "Organizer TBD"} -
+
*/}
{" "} {/* Added mt-2 for spacing */} diff --git a/src/routes/events.tsx b/src/routes/events.tsx index f8563a2..4f668dd 100644 --- a/src/routes/events.tsx +++ b/src/routes/events.tsx @@ -1,7 +1,18 @@ -import { createFileRoute, Outlet } from "@tanstack/react-router" +import { apiEndpoints } from "@/lib/api-endpoints" +import axiosClient from "@/lib/axios" +import { createFileRoute, Outlet, redirect } from "@tanstack/react-router" export const Route = createFileRoute("/events")({ component: EventsLayout, + beforeLoad: async () => { + try { + await axiosClient.get(apiEndpoints.ORGANIZER_SESSION) + } catch (error) { + throw redirect({ + to: "/login", + }) + } + }, }) function EventsLayout() { diff --git a/src/routes/events/index.tsx b/src/routes/events/index.tsx index 92053f0..3937500 100644 --- a/src/routes/events/index.tsx +++ b/src/routes/events/index.tsx @@ -6,6 +6,8 @@ import { EventsFilter } from "@/components/events/events-filter" import { useOrganizerEvents } from "@/hooks/use-events" import { Button } from "@/components/ui/button" import type { DayFilter } from "@/types/events" +import axiosClient from "@/lib/axios" +import { apiEndpoints } from "@/lib/api-endpoints" export const Route = createFileRoute("/events/")({ component: EventsPage, @@ -46,9 +48,12 @@ function EventsPage() { }) }, [searchQuery, selectedDay, events]) - const handleLogout = () => { - // TODO: Implement actual logout logic - navigate({ to: "/login" }) + const handleLogout = async () => { + try { + await axiosClient.get(apiEndpoints.ORGANIZER_LOGOUT) + } finally { + navigate({ to: "/login" }) + } } if (isLoading) { From 21d1948b11d2200d8374759123d4560a71f138c9 Mon Sep 17 00:00:00 2001 From: KiranRajeev-KV Date: Mon, 16 Feb 2026 12:35:52 +0530 Subject: [PATCH 4/4] fix: build errors --- src/components/events/event-card.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/events/event-card.tsx b/src/components/events/event-card.tsx index 85e57ce..9a22481 100644 --- a/src/components/events/event-card.tsx +++ b/src/components/events/event-card.tsx @@ -1,5 +1,4 @@ import { Link } from "@tanstack/react-router" -import { Building2 } from "lucide-react" import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" import { cn } from "@/lib/utils" import type { EventCardProps } from "@/types/events"