diff --git a/client/src/components/auth/signInConfirmation/SignInConfirmation.tsx b/client/src/components/auth/signInConfirmation/SignInConfirmation.tsx index 3b7d1151..a7df259c 100644 --- a/client/src/components/auth/signInConfirmation/SignInConfirmation.tsx +++ b/client/src/components/auth/signInConfirmation/SignInConfirmation.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { useNavigate } from "react-router-dom"; +import { useLocation, useNavigate } from "react-router-dom"; import { authRoutesVariables } from "../../../router/routesVariables/pathVariables"; import SignInIcon from "../../icons/SignInIcon"; import Cross from "../../icons/Cross"; @@ -11,10 +11,14 @@ interface Props { export const SignInConfirmation: React.FC = ({ isOpen, onClose }) => { const navigate = useNavigate(); + const location = useLocation(); const handleSignIn = () => { + const redirectTo = `${location.pathname}${location.search}${location.hash}`; onClose(); - navigate(authRoutesVariables.loginStudent); + navigate(authRoutesVariables.loginStudent, { + state: { redirectTo }, + }); }; if (!isOpen) return null; diff --git a/client/src/components/teacherSection/teacherSchedule/TeacherSchedule.tsx b/client/src/components/teacherSection/teacherSchedule/TeacherSchedule.tsx index edc5b854..6d3ac7c8 100644 --- a/client/src/components/teacherSection/teacherSchedule/TeacherSchedule.tsx +++ b/client/src/components/teacherSection/teacherSchedule/TeacherSchedule.tsx @@ -1,4 +1,5 @@ import { useState, useMemo } from "react"; +import { useParams } from "react-router-dom"; import { Calendar } from "./Calendar/Calendar"; import { Time } from "./Time/Time"; import { TeacherType } from "../../../api/teacher/teacher.type"; @@ -13,15 +14,81 @@ interface TeacherScheduleProps { teacher?: TeacherType; } +type PendingBookingIntent = { + teacherId: string; + selectedDate: string; + selectedTime: string; + selectedSubject: string; + selectedLevel: string; + description: string; +}; + +const PENDING_BOOKING_INTENT_KEY = "pending-booking-intent"; + export default function TeacherSchedule({ teacher }: TeacherScheduleProps) { - const [selectedDate, setSelectedDate] = useState(null); - const [showTimeAndBook, setShowTimeAndBook] = useState(false); - const [selectedSubject, setSelectedSubject] = useState(""); - const [selectedLevel, setSelectedLevel] = useState(""); - const [selectedTime, setSelectedTime] = useState(null); - const [description, setDescription] = useState(""); + const params = useParams<{ id: string }>(); + + const [initialPendingBooking] = useState<{ + selectedDate: Date; + selectedTime: string; + selectedSubject: string; + selectedLevel: string; + description: string; + } | null>(() => { + const routeTeacherId = params.id; + const raw = sessionStorage.getItem(PENDING_BOOKING_INTENT_KEY); + + if (!routeTeacherId || !raw) { + return null; + } + + try { + const pending: PendingBookingIntent = JSON.parse(raw); + if (pending.teacherId !== routeTeacherId) { + return null; + } + + const restoredDate = new Date(pending.selectedDate); + if (Number.isNaN(restoredDate.getTime())) { + sessionStorage.removeItem(PENDING_BOOKING_INTENT_KEY); + return null; + } + + sessionStorage.removeItem(PENDING_BOOKING_INTENT_KEY); + + return { + selectedDate: restoredDate, + selectedTime: pending.selectedTime, + selectedSubject: pending.selectedSubject, + selectedLevel: pending.selectedLevel, + description: pending.description, + }; + } catch { + sessionStorage.removeItem(PENDING_BOOKING_INTENT_KEY); + return null; + } + }); + + const [selectedDate, setSelectedDate] = useState( + initialPendingBooking?.selectedDate ?? null, + ); + const [showTimeAndBook, setShowTimeAndBook] = useState( + Boolean(initialPendingBooking), + ); + const [selectedSubject, setSelectedSubject] = useState( + initialPendingBooking?.selectedSubject ?? "", + ); + const [selectedLevel, setSelectedLevel] = useState( + initialPendingBooking?.selectedLevel ?? "", + ); + const [selectedTime, setSelectedTime] = useState( + initialPendingBooking?.selectedTime ?? null, + ); + const [description, setDescription] = useState( + initialPendingBooking?.description ?? "", + ); const [showSubjectLevelSelection, setShowSubjectLevelSelection] = - useState(false); + useState(Boolean(initialPendingBooking?.selectedTime)); const { open: openModal } = useModalStore(); const user = useAuthSessionStore((state) => state.user); @@ -102,6 +169,20 @@ export default function TeacherSchedule({ teacher }: TeacherScheduleProps) { const handleTimeSelection = (time: string): void => { if (!isAuthenticated) { + if (teacher?.id && selectedDate) { + const pending: PendingBookingIntent = { + teacherId: teacher.id, + selectedDate: selectedDate.toISOString(), + selectedTime: time, + selectedSubject, + selectedLevel, + description, + }; + sessionStorage.setItem( + PENDING_BOOKING_INTENT_KEY, + JSON.stringify(pending), + ); + } openModal("signIn"); return; } diff --git a/client/src/features/auth/mutations/useLoginMutation.ts b/client/src/features/auth/mutations/useLoginMutation.ts index 6b29daba..67a51e3b 100644 --- a/client/src/features/auth/mutations/useLoginMutation.ts +++ b/client/src/features/auth/mutations/useLoginMutation.ts @@ -2,7 +2,7 @@ import { useMutation, useQueryClient } from "@tanstack/react-query"; import { useAuthSessionStore } from "../../../store/authSession.store"; import { loginApi } from "../../../api/auth/auth.api"; import { queryKeys } from "../../queryKeys"; -import { useNavigate } from "react-router-dom"; +import { useLocation, useNavigate } from "react-router-dom"; import { getErrorMessage } from "../../../util/ErrorUtil"; import { LoginFinalType } from "../../../api/auth/types"; import { useNotificationStore } from "../../../store/notification.store"; @@ -10,6 +10,7 @@ import { useNotificationStore } from "../../../store/notification.store"; export function useLoginMutation() { const qc = useQueryClient(); const navigate = useNavigate(); + const location = useLocation(); const setAccessToken = useAuthSessionStore((s) => s.setAccessToken); const success = useNotificationStore((s) => s.success); const notifyError = useNotificationStore((s) => s.error); @@ -17,10 +18,14 @@ export function useLoginMutation() { return useMutation({ mutationFn: (data: LoginFinalType) => loginApi(data), onSuccess: async ({ accessToken }) => { + const redirectTo = + ((location.state as { redirectTo?: string } | null)?.redirectTo ?? + "/") || + "/"; setAccessToken(accessToken); success("Successfully logged in"); localStorage.setItem("hadSession", "1"); - navigate("/", { replace: true }); + navigate(redirectTo, { replace: true }); await qc.invalidateQueries({ queryKey: queryKeys.me }); }, onError: (error) => {