Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 48 additions & 1 deletion frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"lucide-react": "^1.17.0",
"react": "^19.2.4",
"react-dom": "^19.2.4",
"react-helmet-async": "^3.0.0",
"react-markdown": "^10.1.0",
"react-router-dom": "^7.13.2",
"recharts": "^3.8.1",
Expand Down
8 changes: 7 additions & 1 deletion frontend/src/components/auth/ForgotPassword.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ export default function ForgotPassword() {
<input
type="email"
id="email"
name="email"
value={email}
autoComplete="email"
aria-describedby={
Expand Down Expand Up @@ -212,13 +213,16 @@ export default function ForgotPassword() {
</p>

<div className="flex flex-col space-y-3">
<label className="text-sm font-black uppercase tracking-widest text-black">
<label
htmlFor="otp"
className="text-sm font-black uppercase tracking-widest text-black">
Verification Code
</label>
<input
type="text"
value={otp}
id="otp"
name="otp"
inputMode="text"
aria-invalid={otp.length > 0 && !isOtpValid}
onChange={(e) =>
Expand Down Expand Up @@ -257,6 +261,7 @@ export default function ForgotPassword() {
aria-invalid={newPassword.length > 0 && !isPasswordValid}
value={newPassword}
id="new-password"
name="newPassword"
onChange={(e) => setNewPassword(e.target.value)}
className="w-full p-5 border-4 border-black rounded-none text-black font-bold focus:outline-none focus:ring-0 focus:border-gray-500"
placeholder="β€’β€’β€’β€’β€’β€’β€’β€’"
Expand Down Expand Up @@ -285,6 +290,7 @@ export default function ForgotPassword() {
aria-invalid={confirmPassword.length > 0 && !doPasswordsMatch}
value={confirmPassword}
id="confirm-password"
name="confirmPassword"
onChange={(e) => setConfirmPassword(e.target.value)}
className="w-full p-5 border-4 border-black rounded-none text-black font-bold focus:outline-none focus:ring-0 focus:border-gray-500"
placeholder="β€’β€’β€’β€’β€’β€’β€’β€’"
Expand Down
64 changes: 44 additions & 20 deletions frontend/src/components/codeforces/VerifyModal.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ export default function VerifyModal({
<h2 className="text-2xl sm:text-3xl font-black uppercase tracking-tighter leading-none">
{step === 1 ? "Connect Codeforces" : "Verify Identity"}
</h2>

<button
onClick={onClose}
className="text-2xl font-black hover:bg-black hover:text-white w-10 h-10 flex items-center justify-center border-[3px] border-black transition-colors"
Expand All @@ -78,27 +79,46 @@ export default function VerifyModal({

{/* Body */}
<div className="px-8 py-10 space-y-8">

{step === 1 && (
<>
<p className="font-bold uppercase tracking-widest text-sm leading-relaxed text-gray-700">
Enter your Codeforces handle below. We will generate a unique code for you to set as your Codeforces Last Name to prove ownership.
</p>
<div className="flex flex-col sm:flex-row gap-0">
<input
type="text"
placeholder="e.g. tourist"
value={handle}
onChange={(e) => setHandle(e.target.value)}
onKeyDown={(e) => e.key === "Enter" && handleInitiate()}
className="flex-1 px-6 py-4 border-[4px] border-black text-lg font-bold uppercase tracking-widest focus:outline-none bg-gray-50 rounded-none"
/>
<button
onClick={handleInitiate}
disabled={connectLoading}
className="px-8 py-4 bg-black text-white font-black uppercase tracking-widest border-[4px] border-black sm:border-l-0 hover:bg-gray-800 transition-colors disabled:opacity-50 rounded-none"

<div className="space-y-2">
<label
htmlFor="handle"
className="font-bold uppercase tracking-widest text-sm text-gray-700"
>
{connectLoading ? "Checking..." : "Generate Code β†’"}
</button>
Codeforces Handle
</label>

<div className="flex flex-col sm:flex-row gap-0">
<input
type="text"
id="handle"
name="handle"
placeholder="e.g. tourist"
value={handle}
onChange={(e) => setHandle(e.target.value)}
onKeyDown={(e) => {
if (e.key === "Enter") {
e.preventDefault();
handleInitiate();
}
}}
className="flex-1 px-6 py-4 border-[4px] border-black text-lg font-black uppercase tracking-widest focus:outline-none bg-gray-50 rounded-none"
/>

<button
onClick={handleInitiate}
disabled={connectLoading}
className="px-8 py-4 bg-black text-white font-black uppercase tracking-widest border-[4px] border-black sm:border-l-0 hover:bg-gray-800 transition-colors disabled:opacity-50 rounded-none"
>
{connectLoading ? "Checking..." : "Generate Code β†’"}
</button>
</div>
</div>
</>
)}
Expand All @@ -108,19 +128,20 @@ export default function VerifyModal({
<p className="font-bold uppercase tracking-widest text-sm leading-relaxed text-gray-700">
Follow these steps carefully:
</p>

<ol className="space-y-4 list-none">
{[
`Go to codeforces.com/settings`,
`Set your Last Name to the code below`,
`Click Save and return here`,
`Click Verify β€” we will check and link your account`,
].map((step, i) => (
].map((stepText, i) => (
<li key={i} className="flex items-start gap-4">
<span className="flex-shrink-0 w-8 h-8 bg-black text-white font-black text-sm flex items-center justify-center">
{i + 1}
</span>
<span className="font-bold uppercase tracking-widest text-sm leading-relaxed pt-1">
{step}
{stepText}
</span>
</li>
))}
Expand All @@ -146,6 +167,7 @@ export default function VerifyModal({
>
← Back
</button>

<button
onClick={handleVerify}
disabled={connectLoading}
Expand All @@ -157,14 +179,16 @@ export default function VerifyModal({
</>
)}

{/* Error */}
{error && (
<div className="border-[3px] border-black bg-black text-white px-6 py-4">
<p className="font-black uppercase tracking-widest text-sm">{error}</p>
<p className="font-black uppercase tracking-widest text-sm">
{error}
</p>
</div>
)}

</div>
</div>
</div>
);
}
}
6 changes: 6 additions & 0 deletions frontend/src/components/explore/SubscribeNewsletter.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,13 @@ export default function SubscribeNewsletter() {
onSubmit={handleSubmit}
className="w-full max-w-3xl mx-auto flex flex-col sm:flex-row gap-4 sm:gap-0"
>

<label htmlFor="newsletter-email" className="sr-only">
Email address
</label>

<input
id="newsletter-email"
type="email"
autoComplete="email"
placeholder="YOUR@EMAIL.COM"
Expand Down
42 changes: 42 additions & 0 deletions frontend/src/components/faq/AccessibilityFAQ.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { accessibilityFaqs } from "../../data/faqs/accessibility";

export default function AccessibilityFAQ() {
return (
<section
aria-labelledby="accessibility-title"
className="py-20 px-6 bg-white text-black border-b-4 border-black"
>

<h2
id="accessibility-title"
className="text-4xl font-black uppercase mb-8"
>
Accessibility
</h2>

<div className="space-y-0">

{accessibilityFaqs.map((faq) => (

<div
key={faq.id}
className="border-t-4 border-black py-8"
>

<h3 className="text-2xl font-black uppercase">
{faq.q}
</h3>

<p className="mt-4 text-base font-bold leading-relaxed normal-case max-w-4xl">
{faq.a}
</p>

</div>

))}

</div>

</section>
);
}
42 changes: 42 additions & 0 deletions frontend/src/components/faq/AccountManagementFAQ.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { accountManagementFaqs } from "../../data/faqs/accountManagement";

export default function AccountManagementFAQ() {
return (
<section
aria-labelledby="account-title"
className="py-20 px-6 bg-white text-black border-b-4 border-black"
>

<h2
id="account-title"
className="text-4xl font-black uppercase mb-8"
>
Account Management
</h2>

<div className="space-y-6">

{accountManagementFaqs.map((faq) => (

<div
key={faq.id}
className="border-4 border-black p-6 bg-white shadow-[8px_8px_0_0_rgba(0,0,0,1)]"
>

<h3 className="text-2xl font-black uppercase">
{faq.q}
</h3>

<p className="mt-4 text-base font-bold leading-relaxed normal-case">
{faq.a}
</p>

</div>

))}

</div>

</section>
);
}
Loading
Loading