From 26ff162224854c59568e8817faf4736bea9f03ca Mon Sep 17 00:00:00 2001 From: MujtabaIqra Date: Wed, 23 Apr 2025 15:08:06 +0400 Subject: [PATCH 1/3] feat: Add real-time countdown timer to parking booking --- src/pages/ConfirmationPage.tsx | 94 ++++++++++++++++++++++------------ 1 file changed, 60 insertions(+), 34 deletions(-) diff --git a/src/pages/ConfirmationPage.tsx b/src/pages/ConfirmationPage.tsx index 3845b4b..7c1adaf 100644 --- a/src/pages/ConfirmationPage.tsx +++ b/src/pages/ConfirmationPage.tsx @@ -1,4 +1,3 @@ - import React, { useEffect, useState } from 'react'; import { useLocation, useNavigate } from 'react-router-dom'; import { Button } from "@/components/ui/button"; @@ -17,40 +16,64 @@ type BookingDetails = { }; const ConfirmationPage = () => { - const navigate = useNavigate(); const location = useLocation(); - const [bookingDetails, setBookingDetails] = useState(null); - const [qrCode, setQrCode] = useState(''); - - useEffect(() => { - if (location.state) { - setBookingDetails(location.state as BookingDetails); - // Mock QR code generation - setQrCode(`https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=SPOTON-${Date.now()}`); - } else { - navigate('/book'); - } - }, [location, navigate]); - + const navigate = useNavigate(); + const [timeLeft, setTimeLeft] = useState({ hours: 0, minutes: 0, seconds: 0 }); + const [progress, setProgress] = useState(100); + + const bookingDetails = location.state as BookingDetails; if (!bookingDetails) { - return
Loading...
; + navigate('/book'); + return null; } - + + // Calculate end time + const startTime = new Date(`${bookingDetails.date}T${bookingDetails.startTime}`); + const endTime = new Date(startTime.getTime() + bookingDetails.duration * 60 * 60 * 1000); + const formattedEndTime = endTime.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit' }); + + // Mock QR code for now + const qrCode = 'https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=SPOTON-CONFIRMED'; + + // Timer effect + useEffect(() => { + const timer = setInterval(() => { + const now = new Date(); + const end = new Date(endTime); + const diff = end.getTime() - now.getTime(); + + if (diff <= 0) { + clearInterval(timer); + setTimeLeft({ hours: 0, minutes: 0, seconds: 0 }); + setProgress(0); + return; + } + + const hours = Math.floor(diff / (1000 * 60 * 60)); + const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60)); + const seconds = Math.floor((diff % (1000 * 60)) / 1000); + + setTimeLeft({ hours, minutes, seconds }); + + // Update progress + const totalDuration = bookingDetails.duration * 60 * 60; // duration in seconds + const remainingSeconds = hours * 3600 + minutes * 60 + seconds; + const newProgress = (remainingSeconds / totalDuration) * 100; + setProgress(newProgress); + }, 1000); + + return () => clearInterval(timer); + }, [endTime, bookingDetails.duration]); + const formatDate = (dateString: string) => { const options: Intl.DateTimeFormatOptions = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' }; return new Date(dateString).toLocaleDateString('en-US', options); }; - - const calculateEndTime = (startTime: string, durationHours: number) => { - const [hours, minutes] = startTime.split(':').map(Number); - const endDate = new Date(); - endDate.setHours(hours, minutes, 0); - endDate.setTime(endDate.getTime() + durationHours * 60 * 60 * 1000); - return `${endDate.getHours().toString().padStart(2, '0')}:${endDate.getMinutes().toString().padStart(2, '0')}`; + + const formatTime = (time: { hours: number, minutes: number, seconds: number }) => { + return `${time.hours.toString().padStart(2, '0')}:${time.minutes.toString().padStart(2, '0')}:${time.seconds.toString().padStart(2, '0')}`; }; - - const endTime = calculateEndTime(bookingDetails.startTime, bookingDetails.duration); - + return (
@@ -62,13 +85,16 @@ const ConfirmationPage = () => {
-
-

Ajman University

-

Parking Reservation

+
+
- - Booking Details + +
{formatTime(timeLeft)}
+

Time remaining

@@ -85,7 +111,7 @@ const ConfirmationPage = () => {

Time

- {bookingDetails.startTime} - {endTime} ({bookingDetails.duration} {bookingDetails.duration === 1 ? 'hour' : 'hours'}) + {bookingDetails.startTime} - {formattedEndTime} ({bookingDetails.duration} {bookingDetails.duration === 1 ? 'hour' : 'hours'})

@@ -121,7 +147,7 @@ const ConfirmationPage = () => { className="w-full bg-spoton-purple hover:bg-spoton-purple-dark" onClick={() => navigate('/active')} > - View Active Bookings + View Active Booking From bea90de85f1e62570f49d92197c124513cee29a1 Mon Sep 17 00:00:00 2001 From: MujtabaIqra Date: Sun, 27 Apr 2025 19:38:15 +0400 Subject: [PATCH 3/3] feat: Add authentication checks and detailed logging to UserProfilePage --- src/pages/UserProfilePage.tsx | 57 +++++++++++++++++++++++++++++------ 1 file changed, 48 insertions(+), 9 deletions(-) diff --git a/src/pages/UserProfilePage.tsx b/src/pages/UserProfilePage.tsx index de4f231..bdb8740 100644 --- a/src/pages/UserProfilePage.tsx +++ b/src/pages/UserProfilePage.tsx @@ -13,16 +13,51 @@ import { useUserProfile } from '@/integrations/supabase/useUserProfile'; const UserProfilePage = () => { const navigate = useNavigate(); const [userId, setUserId] = useState(); + const [isAuthenticated, setIsAuthenticated] = useState(false); const { profile, loading, error } = useUserProfile(userId); // Get user ID on mount useEffect(() => { - const checkUser = async () => { - const { data } = await supabase.auth.getUser(); - setUserId(data?.user?.id); + const checkAuth = async () => { + try { + console.log('Checking authentication...'); + const { data: { session }, error } = await supabase.auth.getSession(); + console.log('Session:', session); + console.log('Auth Error:', error); + + if (error) { + console.error('Auth Error:', error); + setIsAuthenticated(false); + navigate('/login'); + return; + } + + if (!session) { + console.log('No session found, redirecting to login'); + setIsAuthenticated(false); + navigate('/login'); + return; + } + + setIsAuthenticated(true); + console.log('User ID:', session.user.id); + setUserId(session.user.id); + } catch (err) { + console.error('Error checking auth:', err); + setIsAuthenticated(false); + navigate('/login'); + } }; - checkUser(); - }, []); + + checkAuth(); + }, [navigate]); + + useEffect(() => { + console.log('Profile Data:', profile); + console.log('Loading State:', loading); + console.log('Error State:', error); + console.log('Is Authenticated:', isAuthenticated); + }, [profile, loading, error, isAuthenticated]); // Mock vehicle data (you can replace this with real data from your database) const vehicle = { @@ -38,6 +73,10 @@ const UserProfilePage = () => { thisMonth: 8 }; + if (!isAuthenticated) { + return null; + } + if (loading) { return (
@@ -73,13 +112,13 @@ const UserProfilePage = () => {
- {profile.full_name.split(' ').map(name => name[0]).join('')} + {profile.full_name?.split(' ').map(name => name[0]).join('') || '?'}
-

{profile.full_name}

+

{profile.full_name || 'No Name Set'}

{profile.student_id || 'No ID'}

- {profile.user_type} + {profile.user_type || 'Unknown'}
@@ -98,7 +137,7 @@ const UserProfilePage = () => {
Account Type - {profile.user_type} + {profile.user_type || 'Not set'}
Total Bookings