Skip to content

Commit f85a0e0

Browse files
Merge pull request #78 from Ditectrev/feature/last-page-exam
Feature/last page exam
2 parents 97da48f + 8823360 commit f85a0e0

File tree

8 files changed

+93
-125
lines changed

8 files changed

+93
-125
lines changed

app/auth/callback/page.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,14 @@ function AuthCallbackContent() {
1414
"loading",
1515
);
1616
const [message, setMessage] = useState("");
17+
const [isProcessing, setIsProcessing] = useState(false);
1718

1819
useEffect(() => {
1920
const handleCallback = async () => {
21+
// Prevent multiple simultaneous executions
22+
if (isProcessing) return;
23+
setIsProcessing(true);
24+
2025
try {
2126
// Check if this is an OAuth callback
2227
const success = searchParams.get("success");
@@ -67,11 +72,14 @@ function AuthCallbackContent() {
6772
"An error occurred during authentication. Please try again.",
6873
);
6974
setTimeout(() => router.push("/"), 3000);
75+
} finally {
76+
setIsProcessing(false);
7077
}
7178
};
7279

7380
handleCallback();
74-
}, [router, searchParams, refreshUser]);
81+
// eslint-disable-next-line react-hooks/exhaustive-deps
82+
}, [searchParams]);
7583

7684
if (status === "loading") {
7785
return (

components/AuthModal.tsx

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -143,23 +143,14 @@ export const AuthModal: React.FC<AuthModalProps> = ({
143143

144144
const handleAppleSignIn = async () => {
145145
setIsLoading(true);
146-
setMessage("Redirecting to Apple..."); // User feedback
147146
try {
148147
// Save last used method
149148
const method = { type: "apple", value: "Apple" };
150149
setLastUsedMethod(method);
151150
localStorage.setItem("lastUsedAuthMethod", JSON.stringify(method));
152-
153-
const result = await signInWithApple();
154-
155-
if (!result.success && result.error) {
156-
setMessage(result.error);
157-
setIsLoading(false);
158-
}
159-
// Note: For Apple OAuth, loading state will be reset when the modal auto-closes
160-
// or when the page redirects. Don't reset here for successful redirects.
151+
await signInWithApple();
161152
} catch (error) {
162-
setMessage("Failed to sign in with Apple. Please try again.");
153+
setMessage("Failed to sign in with Apple");
163154
setIsLoading(false);
164155
}
165156
};

components/Header.tsx

Lines changed: 7 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
"use client";
22

33
import React, { useEffect, useState } from "react";
4-
import HomeButton from "./HomeButton";
54
import Image from "next/image";
65
import { usePathname, useRouter } from "next/navigation";
76
import { useAuth } from "../contexts/AuthContext";
@@ -60,39 +59,21 @@ const Header = () => {
6059
<header className="sticky top-0 z-40 bg-slate-900/95 backdrop-blur supports-[backdrop-filter]:bg-slate-900/60 border-b border-slate-700">
6160
<div className="mx-auto max-w-7xl">
6261
<div className="flex h-16 items-center justify-between px-4 sm:px-6 lg:px-8">
63-
{/* Left section - Home button or logo */}
62+
{/* Left section - Logo */}
6463
<div className="flex items-center">
65-
{pathname !== "/" ? (
66-
<HomeButton
67-
handleReturnToMainPage={() => {
68-
router.push("/");
69-
}}
70-
/>
71-
) : (
72-
<div className="flex items-center">
73-
<Image
74-
src="/logo.svg"
75-
alt="Ditectrev Logo"
76-
className="h-8 w-auto"
77-
height={32}
78-
width={120}
79-
/>
80-
</div>
81-
)}
82-
</div>
83-
84-
{/* Center section - Logo on non-home pages */}
85-
{pathname !== "/" && (
86-
<div className="flex items-center absolute left-1/2 transform -translate-x-1/2 md:relative md:left-auto md:transform-none">
64+
<button
65+
onClick={() => router.push("/")}
66+
className="flex items-center cursor-pointer"
67+
>
8768
<Image
8869
src="/logo.svg"
8970
alt="Ditectrev Logo"
9071
className="h-8 w-auto"
9172
height={32}
9273
width={120}
9374
/>
94-
</div>
95-
)}
75+
</button>
76+
</div>
9677

9778
{/* Right section - Navigation and Auth */}
9879
<div className="flex items-center space-x-4">

components/HomeButton.tsx

Lines changed: 0 additions & 23 deletions
This file was deleted.

components/QuizForm.tsx

Lines changed: 40 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -325,33 +325,46 @@ const QuizForm: FC<Props> = ({
325325
{isThinking ? "Thinking..." : "Explain"}
326326
</Button>
327327
)}
328-
<Button
329-
type="button"
330-
intent="primary"
331-
size="medium"
332-
disabled={currentQuestionIndex < lastIndex}
333-
onClick={() => {
334-
if (!showCorrectAnswer) {
335-
setSavedAnswers((prev) => ({
336-
...prev,
337-
[currentQuestionIndex]: watchInput,
338-
}));
339-
}
340-
setShowCorrectAnswer(false);
341-
setExplanation(null);
342-
if (currentQuestionIndex === totalQuestions) {
343-
handleNextQuestion(1);
344-
setLastIndex(1);
345-
} else {
346-
handleNextQuestion(currentQuestionIndex + 1);
347-
setLastIndex(currentQuestionIndex + 1);
348-
}
349-
setCanGoBack(false);
350-
reset();
351-
}}
352-
>
353-
Next Question
354-
</Button>
328+
{currentQuestionIndex < totalQuestions ? (
329+
<Button
330+
type="button"
331+
intent="primary"
332+
size="medium"
333+
disabled={currentQuestionIndex < lastIndex}
334+
onClick={() => {
335+
if (!showCorrectAnswer) {
336+
setSavedAnswers((prev) => ({
337+
...prev,
338+
[currentQuestionIndex]: watchInput,
339+
}));
340+
}
341+
setShowCorrectAnswer(false);
342+
setExplanation(null);
343+
if (currentQuestionIndex === totalQuestions) {
344+
handleNextQuestion(1);
345+
setLastIndex(1);
346+
} else {
347+
handleNextQuestion(currentQuestionIndex + 1);
348+
setLastIndex(currentQuestionIndex + 1);
349+
}
350+
setCanGoBack(false);
351+
reset();
352+
}}
353+
>
354+
Next Question
355+
</Button>
356+
) : (
357+
<Button
358+
type="button"
359+
intent="primary"
360+
size="medium"
361+
onClick={() => {
362+
window.location.href = "/";
363+
}}
364+
>
365+
Go Home
366+
</Button>
367+
)}
355368
</div>
356369
</form>
357370
);

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "practice-exams-platform",
3-
"version": "1.4.3",
3+
"version": "1.4.4",
44
"private": true,
55
"engines": {
66
"node": "20.x"

styles/globals.css

Lines changed: 32 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -30,41 +30,39 @@ a[target="_blank"]:hover .external-link-icon {
3030
}
3131

3232
.loading-container {
33-
position: fixed;
34-
top: 0;
35-
left: 0;
36-
width: 100%;
37-
height: 100%;
38-
display: flex;
39-
justify-content: center;
40-
align-items: center;
41-
z-index: 9999;
42-
}
33+
position: fixed;
34+
top: 0;
35+
left: 0;
36+
width: 100%;
37+
height: 100%;
38+
display: flex;
39+
justify-content: center;
40+
align-items: center;
41+
z-index: 9999;
42+
}
4343

44-
.spinner {
45-
border: 8px solid rgba(255, 255, 255, 0.3);
46-
border-top: 8px solid #1E293B;
47-
border-radius: 50%;
48-
width: 60px;
49-
height: 60px;
50-
-webkit-animation: spin 1s linear infinite;
51-
animation: spin 1s linear infinite;
44+
.spinner {
45+
border: 8px solid rgba(255, 255, 255, 0.3);
46+
border-top: 8px solid #1E293B;
47+
border-radius: 50%;
48+
width: 60px;
49+
height: 60px;
50+
-webkit-animation: spin 1s linear infinite;
51+
animation: spin 1s linear infinite;
52+
}
53+
@-webkit-keyframes spin {
54+
0% {
55+
transform: rotate(0deg);
5256
}
53-
54-
@-webkit-keyframes spin {
55-
0% {
56-
transform: rotate(0deg);
57-
}
58-
100% {
59-
transform: rotate(360deg);
60-
}
57+
100% {
58+
transform: rotate(360deg);
6159
}
62-
63-
@keyframes spin {
64-
0% {
65-
transform: rotate(0deg);
66-
}
67-
100% {
68-
transform: rotate(360deg);
69-
}
60+
}
61+
@keyframes spin {
62+
0% {
63+
transform: rotate(0deg);
7064
}
65+
100% {
66+
transform: rotate(360deg);
67+
}
68+
}

0 commit comments

Comments
 (0)