Skip to content

Commit fb1becc

Browse files
feat: vast majority of light/dark theme work
1 parent f85a0e0 commit fb1becc

28 files changed

+1089
-124
lines changed

app/exam/page.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,8 @@ const Exam: NextPage<{ searchParams: { url: string; name: string } }> = ({
9797
// Block access if trial expired
9898
if (isAccessBlocked) {
9999
return (
100-
<div className="py-10 px-5 mb-6 mx-auto w-[90vw] lg:w-[60vw] 2xl:w-[45%] bg-slate-800 border-2 border-slate-700 rounded-lg text-center">
101-
<div className="text-red-400 text-lg mb-4">
100+
<div className="py-10 px-5 mb-6 mx-auto w-[90vw] lg:w-[60vw] 2xl:w-[45%] bg-white dark:bg-gray-800 border-2 border-gray-200 dark:border-gray-700 rounded-lg text-center">
101+
<div className="text-red-500 dark:text-red-400 text-lg mb-4">
102102
⏰ Trial expired. Please sign in to continue taking exams.
103103
</div>
104104
<button
@@ -117,7 +117,7 @@ const Exam: NextPage<{ searchParams: { url: string; name: string } }> = ({
117117
const numberOfQuestions = data.randomQuestions.length || 0;
118118

119119
return (
120-
<div className="py-10 px-5 mb-6 mx-auto w-[90vw] lg:w-[60vw] 2xl:w-[45%] bg-slate-800 border-2 border-slate-700 rounded-lg">
120+
<div className="py-10 px-5 mb-6 mx-auto w-[90vw] lg:w-[60vw] 2xl:w-[45%] bg-white dark:bg-gray-800 border-2 border-gray-200 dark:border-gray-700 rounded-lg mt-8">
121121
{isInTrial && (
122122
<div className="mb-6 p-4 bg-amber-600/20 border border-amber-600/40 rounded-lg">
123123
<div className="flex items-center gap-2 text-amber-300">
@@ -142,13 +142,13 @@ const Exam: NextPage<{ searchParams: { url: string; name: string } }> = ({
142142
)}
143143
<div>
144144
<div className="px-2 sm:px-10 w-full flex flex-row justify-between items-center">
145-
<p className="text-white font-bold text-sm sm:text-2xl">
145+
<p className="text-gray-900 dark:text-white font-bold text-sm sm:text-2xl">
146146
{countAnswered}/{numberOfQuestions}
147147
</p>
148-
<h1 className="text-white font-bold text-lg sm:text-3xl">
148+
<h1 className="text-gray-900 dark:text-white font-bold text-lg sm:text-3xl">
149149
PRACTICE EXAM
150150
</h1>
151-
<p className="text-white font-bold text-sm sm:text-2xl">
151+
<p className="text-gray-900 dark:text-white font-bold text-sm sm:text-2xl">
152152
{remainingTime}
153153
</p>
154154
</div>
@@ -202,7 +202,7 @@ const Exam: NextPage<{ searchParams: { url: string; name: string } }> = ({
202202
c0.53,0,0.97,0.43,0.97,0.97V29.35z"
203203
/>
204204
</svg>
205-
<p className="text-white text-center pt-6 px-6">
205+
<p className="text-gray-900 dark:text-white text-center pt-6 px-6">
206206
Practice Exam help you practice skills, assess your knowledge,
207207
and identify the areas where you need additional preparation
208208
to accelerate your chances of succeeding on certification
@@ -211,7 +211,7 @@ const Exam: NextPage<{ searchParams: { url: string; name: string } }> = ({
211211
are likely to experience on Azure Fundamentals real exam.
212212
</p>
213213
</div>
214-
<p className="text-white font-bold text-xl text-center pt-20 px-6 mb-40">
214+
<p className="text-gray-900 dark:text-white font-bold text-xl text-center pt-20 px-6 mb-40">
215215
This Practice Exam contains {numberOfQuestions} random questions
216216
(seen in upper left corner) and has a completion time limit of{" "}
217217
{remainingTime.split(":")[0]} minutes (seen in upper right

app/layout.tsx

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import Footer from "@azure-fundamentals/components/Footer";
55
import ApolloProvider from "@azure-fundamentals/components/ApolloProvider";
66
import Cookie from "@azure-fundamentals/components/Cookie";
77
import { AuthProvider } from "@azure-fundamentals/contexts/AuthContext";
8+
import { ThemeProvider } from "@azure-fundamentals/contexts/ThemeContext";
89
import { TrialWarning } from "@azure-fundamentals/components/TrialWarning";
910
import "styles/globals.css";
1011

@@ -105,19 +106,21 @@ type RootLayoutProps = {
105106

106107
export default function RootLayout({ children }: RootLayoutProps) {
107108
return (
108-
<html lang="en">
109-
<body className="bg-slate-900">
110-
<ApolloProvider>
111-
<AuthProvider>
112-
<Header />
113-
<main className="flex flex-col justify-between min-h-[calc(100vh-4rem)]">
114-
{children}
115-
<Footer />
116-
<Cookie />
117-
<TrialWarning />
118-
</main>
119-
</AuthProvider>
120-
</ApolloProvider>
109+
<html lang="en" className="dark">
110+
<body className="bg-gray-50 dark:bg-gray-950 text-gray-900 dark:text-gray-100 transition-colors duration-200">
111+
<ThemeProvider>
112+
<ApolloProvider>
113+
<AuthProvider>
114+
<Header />
115+
<main className="flex flex-col justify-between min-h-[calc(100vh-4rem)]">
116+
{children}
117+
<Footer />
118+
<Cookie />
119+
<TrialWarning />
120+
</main>
121+
</AuthProvider>
122+
</ApolloProvider>
123+
</ThemeProvider>
121124
</body>
122125
</html>
123126
);

app/modes/page.tsx

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ const Modes: NextPage<{ searchParams: { url: string; name: string } }> = ({
88

99
return (
1010
<div className="mx-auto mb-6 w-full md:w-[90vw] lg:w-[70vw] 2xl:w-[45%] text-center">
11-
<h2 className="text-white text-4xl text-leading font-bold uppercase md:mt-14">
11+
<h2 className="text-gray-900 dark:text-gray-100 text-4xl text-leading font-bold uppercase md:mt-14">
1212
{name}
1313
</h2>
14-
<p className="text-white text-lg mt-4 mb-14 px-5 leading-6">
14+
<p className="text-gray-900 dark:text-gray-100 text-lg mt-4 mb-14 px-5 leading-6">
1515
Test your knowledge under pressure with our timed exam mode or explore
1616
and master all the questions at your own pace with our practice mode.
1717
</p>
@@ -24,8 +24,6 @@ const Modes: NextPage<{ searchParams: { url: string; name: string } }> = ({
2424
heading="Practice mode"
2525
paragraph="Learn and familiarize yourself with the questions and answers without any time constraint."
2626
subparagraph="You can copy URL to comeback to the same question later."
27-
wrapperClassNames="from-[#0284C7] to-[#2DD48F]"
28-
headingClassNames="group-hover:from-[#0284C7] group-hover:to-[#2DD48F]"
2927
/>
3028
<ExamLink
3129
href={{
@@ -35,8 +33,6 @@ const Modes: NextPage<{ searchParams: { url: string; name: string } }> = ({
3533
heading="Exam mode"
3634
paragraph="Put your knowledge to the test by answering a fixed number of randomly selected questions under a time
3735
limit."
38-
wrapperClassNames="from-[#F97316] to-[#FACC15]"
39-
headingClassNames="group-hover:from-[#F97316] group-hover:to-[#FACC15]"
4036
/>
4137
</div>
4238
</div>

app/not-found.tsx

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
"use client";
2+
3+
import Link from "next/link";
4+
5+
export default function NotFound() {
6+
return (
7+
<div className="min-h-screen bg-[var(--color-background)] flex flex-col items-center justify-center">
8+
{/* Header */}
9+
<h1 className="text-2xl font-semibold text-[var(--color-text-primary)] mb-4">
10+
Page Not Found
11+
</h1>
12+
13+
{/* Description */}
14+
<p className="zoom-area text-[var(--color-text-secondary)] text-lg mb-8 max-w-md text-center">
15+
Oops! The page you&apos;re looking for seems to have drifted off into
16+
space. Don&apos;t worry, our{" "}
17+
<b className="text-[var(--color-primary)]">practice exams</b> are still
18+
here waiting for you!
19+
</p>
20+
21+
{/* 404 Numbers */}
22+
<section className="error-container">
23+
<span className="four">
24+
<span className="screen-reader-text">4</span>
25+
</span>
26+
<span className="zero">
27+
<span className="screen-reader-text">0</span>
28+
</span>
29+
<span className="four">
30+
<span className="screen-reader-text">4</span>
31+
</span>
32+
</section>
33+
34+
{/* Action buttons */}
35+
<div className="link-container">
36+
<Link href="/" className="more-link">
37+
🚀 Return Home
38+
</Link>
39+
<Link href="/modes" className="more-link">
40+
📚 Browse Exams
41+
</Link>
42+
</div>
43+
</div>
44+
);
45+
}

app/page.tsx

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,18 @@ const Home: NextPage = () => {
2020

2121
return (
2222
<div className="mx-auto mb-6 w-full lg:w-[70vw] 2xl:w-[45%] text-center">
23-
<h2 className="text-white text-5xl font-bold uppercase">Welcome!</h2>
24-
<p className="text-white text-lg mt-4 mb-6 px-5 leading-6">
23+
<h2 className="text-gray-900 dark:text-gray-100 text-5xl font-bold uppercase">
24+
Welcome!
25+
</h2>
26+
<p className="text-gray-900 dark:text-gray-100 text-lg mt-4 mb-6 px-5 leading-6">
2527
Select an exam from the list below.
2628
</p>
2729
<input
2830
type="text"
2931
value={searchTerm}
3032
onChange={handleSearchChange}
3133
placeholder="Search exams"
32-
className="mb-6 px-4 py-2 border border-gray-300 rounded-md w-3/4 lg:w-1/2"
34+
className="mb-6 px-4 py-2 border border-gray-200 dark:border-gray-800 bg-gray-100 dark:bg-gray-800 text-gray-900 dark:text-gray-100 rounded-md w-3/4 lg:w-1/2"
3335
/>
3436
<div
3537
className={`grid ${
@@ -48,12 +50,12 @@ const Home: NextPage = () => {
4850
}}
4951
heading={exam.name}
5052
paragraph={exam.subtitle}
51-
wrapperClassNames="hover:bg-[#C7D2E2]"
52-
headingClassNames="group-hover:from-[#fff] group-hover:to-[#fff]"
53+
wrapperClassNames=""
54+
headingClassNames=""
5355
/>
5456
))
5557
) : (
56-
<p className="text-white text-lg mt-4">
58+
<p className="text-gray-900 dark:text-gray-100 text-lg mt-4">
5759
No exams were found for your query.
5860
</p>
5961
)}

app/practice/page.tsx

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,14 @@ const Practice: NextPage = () => {
7272
}, [seq]);
7373

7474
const handleNextQuestion = (questionNo: number) => {
75-
if (questionNo > 0 && questionNo - 1 < questionsData?.questions?.count) {
75+
// Fix off-by-one error: subtract 1 from the count since it's 1-indexed but count is 0-indexed
76+
const totalQuestions = Math.max(
77+
0,
78+
(questionsData?.questions?.count || 0) - 1,
79+
);
80+
81+
// Allow navigation to questions 1 through totalQuestions
82+
if (questionNo > 0 && questionNo <= totalQuestions) {
7683
setCurrentQuestionIndex(questionNo);
7784
setThisSeqIntoURL(questionNo);
7885
}
@@ -86,8 +93,8 @@ const Practice: NextPage = () => {
8693
// Block access if trial expired
8794
if (isAccessBlocked) {
8895
return (
89-
<div className="py-10 px-5 mb-6 sm:p-10 mx-auto w-[90vw] lg:w-[60vw] 2xl:w-[45%] bg-slate-800 border-2 border-slate-700 rounded-lg text-center">
90-
<div className="text-red-400 text-lg mb-4">
96+
<div className="py-10 px-5 mb-6 sm:p-10 mx-auto w-[90vw] lg:w-[60vw] 2xl:w-[45%] bg-white dark:bg-gray-800 border-2 border-gray-200 dark:border-gray-700 rounded-lg text-center">
97+
<div className="text-red-500 dark:text-red-400 text-lg mb-4">
9198
⏰ Trial expired. Please sign in to continue practicing.
9299
</div>
93100
<button
@@ -104,7 +111,7 @@ const Practice: NextPage = () => {
104111
if (questionsError) return <p>Oh no... {questionsError.message}</p>;
105112

106113
return (
107-
<div className="py-10 px-5 mb-6 sm:p-10 mx-auto w-[90vw] lg:w-[60vw] 2xl:w-[45%] bg-slate-800 border-2 border-slate-700 rounded-lg">
114+
<div className="py-10 px-5 mb-6 sm:p-10 mx-auto w-[90vw] lg:w-[60vw] 2xl:w-[45%] bg-white dark:bg-gray-800 border-2 border-gray-200 dark:border-gray-700 rounded-lg mt-8">
108115
{isInTrial && (
109116
<div className="mb-6 p-4 bg-amber-600/20 border border-amber-600/40 rounded-lg">
110117
<div className="flex items-center gap-2 text-amber-300">
@@ -131,7 +138,7 @@ const Practice: NextPage = () => {
131138
isLoading={loading || questionsLoading}
132139
questionSet={data?.questionById}
133140
handleNextQuestion={handleNextQuestion}
134-
totalQuestions={questionsData?.questions?.count}
141+
totalQuestions={Math.max(0, (questionsData?.questions?.count || 0) - 1)}
135142
currentQuestionIndex={currentQuestionIndex}
136143
link={editedUrl}
137144
/>

components/Button.tsx

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@ import React from "react";
44
const button = cva("button", {
55
variants: {
66
intent: {
7-
primary: ["btn-primary", "focus:ring-blue-800"],
7+
primary: ["btn-primary", "focus:ring-primary-800"],
88
secondary: [
9-
"bg-emerald-600/50",
10-
"border-emerald-600",
11-
"hover:bg-emerald-600/60",
12-
"focus:ring-green-800",
13-
"border-emerald-600",
9+
"bg-primary-500/20",
10+
"border-primary-500",
11+
"hover:bg-primary-500/30",
12+
"hover:border-primary-600",
13+
"focus:ring-primary-800",
14+
"text-primary-700 dark:text-primary-300",
1415
"sm:mr-2",
1516
],
1617
},
@@ -51,7 +52,7 @@ export const Button: React.FC<ButtonProps> = ({
5152
intent,
5253
size,
5354
variant,
54-
})} text-white rounded-lg focus:outline-none focus:ring-1 border mb-2 sm:mb-0 ${
55+
})} text-white rounded-lg focus:outline-none focus:ring-1 border mb-2 sm:mb-0 disabled:cursor-not-allowed disabled:opacity-50 ${
5556
className || ""
5657
}`}
5758
{...props}

components/Cookie.tsx

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,28 +4,38 @@ import "vanilla-cookieconsent/dist/cookieconsent.css";
44
import * as CookieConsent from "vanilla-cookieconsent";
55
import getConfig from "@azure-fundamentals/utils/CookieConfig";
66
import addCookieConsentListeners from "@azure-fundamentals/utils/CookieListeners";
7+
import { useTheme } from "../contexts/ThemeContext";
78
import Script from "next/script";
89

910
const Cookie: FC = () => {
1011
const GA_TRACKING_ID = process.env.NEXT_PUBLIC_GA_TRACKING_ID;
12+
const { theme } = useTheme();
1113

1214
useEffect(() => {
1315
addCookieConsentListeners();
1416
CookieConsent.run(getConfig());
1517
}, []);
1618

19+
const handleShowPreferences = () => {
20+
if (CookieConsent && typeof CookieConsent.showPreferences === "function") {
21+
CookieConsent.showPreferences();
22+
}
23+
};
24+
1725
return (
1826
<>
1927
<button
20-
className="w-fit self-center md:fixed bg-white p-2 rounded-2xl md:bottom-1 md:left-1"
28+
className={`w-fit self-center md:fixed p-2 rounded-2xl md:bottom-1 md:left-1 ${
29+
theme === "dark" ? "bg-white" : "bg-black"
30+
}`}
2131
type="button"
22-
onClick={CookieConsent.showPreferences}
32+
onClick={handleShowPreferences}
2333
>
2434
<svg
2535
xmlns="http://www.w3.org/2000/svg"
2636
width="16"
2737
height="16"
28-
fill="currentColor"
38+
fill={theme === "dark" ? "black" : "white"}
2939
viewBox="0 0 16 16"
3040
>
3141
<path d="M6 7.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0m4.5.5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3m-.5 3.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0" />

components/ExamLink.tsx

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,22 +24,35 @@ const ExamLink = ({
2424
<Link
2525
{...linkProps}
2626
className={clsx(
27+
"group rounded-xl w-full h-[350px] cursor-pointer transition-all duration-200",
28+
"bg-gray-200 dark:bg-gray-700 border border-gray-200 dark:border-gray-700",
29+
"hover:shadow-xl hover:shadow-primary-500/20 hover:scale-105 hover:border hover:border-primary-500 dark:hover:shadow-xl dark:hover:shadow-primary-500/20 dark:hover:border dark:hover:border-primary-500",
2730
wrapperClassNames,
28-
"group bg-slate-700 hover:bg-gradient-to-r rounded-xl p-[2px] w-full h-[350px] cursor-pointer",
2931
)}
3032
>
3133
<div
3234
className={clsx(
3335
headingClassNames,
34-
"flex flex-col justify-center items-center h-full bg-slate-800 rounded-xl px-7",
36+
"flex flex-col justify-center items-center h-full rounded-xl px-7 transition-colors duration-200",
37+
"bg-white dark:bg-gray-800",
3538
)}
3639
>
37-
<h2 className="text-white group-hover:bg-gradient-to-r group-hover:text-transparent bg-clip-text uppercase text-3xl font-bold">
40+
<h2
41+
className={clsx(
42+
"uppercase text-3xl font-bold transition-colors duration-200",
43+
"text-gray-900 dark:text-white",
44+
"group-hover:text-primary",
45+
)}
46+
>
3847
{heading}
3948
</h2>
40-
<p className="text-sm text-slate-400 mt-7">{paragraph}</p>
49+
<p className="text-sm text-gray-600 dark:text-gray-400 mt-7">
50+
{paragraph}
51+
</p>
4152
{subparagraph !== "" && (
42-
<p className="text-sm text-slate-400 mt-2">{subparagraph}</p>
53+
<p className="text-sm text-gray-600 dark:text-gray-400 mt-2">
54+
{subparagraph}
55+
</p>
4356
)}
4457
</div>
4558
</Link>

components/ExamResult.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,11 @@ const ExamResult: React.FC<Props> = ({
2626
)}
2727

2828
<div className="flex justify-center relative z-[1]">
29-
<span className="text-white opacity-10 font-bold text-7xl sm:text-6xl md:text-8xl lg:text-9xl -z-[1] select-none">
29+
<span className="text-gray-400 dark:text-white opacity-20 dark:opacity-10 font-bold text-7xl sm:text-6xl md:text-8xl lg:text-9xl -z-[1] select-none">
3030
POINTS
3131
</span>
3232

33-
<div className="absolute text-white text-4xl sm:text-6xl font-semibold text-center grid place-items-center top-0 bottom-0">
33+
<div className="absolute text-gray-900 dark:text-white text-4xl sm:text-6xl font-semibold text-center grid place-items-center top-0 bottom-0">
3434
<p>
3535
<span className={status ? "text-green-500" : "text-red-500"}>
3636
{points}
@@ -39,7 +39,7 @@ const ExamResult: React.FC<Props> = ({
3939
</p>
4040
</div>
4141
</div>
42-
<p className="text-white text-sm sm:text-lg mx-auto sm:w-[490px] text-center mt-5 mb-10 sm:mb-20">
42+
<p className="text-gray-900 dark:text-white text-sm sm:text-lg mx-auto sm:w-[490px] text-center mt-5 mb-10 sm:mb-20">
4343
{status ? (
4444
<>
4545
<p>Congratulations!</p>

0 commit comments

Comments
 (0)