Skip to content
Merged
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
2 changes: 0 additions & 2 deletions react-ystemandchess/src/App.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
.App {
overflow-y: hidden;
margin-top: 0;
text-align: center;
height: 100%;
}
6 changes: 4 additions & 2 deletions react-ystemandchess/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,11 @@ function App() {
*/
return (
<Router>
<div className="App">
<div className="App flex flex-col min-h-screen">
<NavBar />
<AppRoutes />
<main className="flex-1">
<AppRoutes />
</main>
<Footer />
</div>
</Router>
Expand Down
2 changes: 1 addition & 1 deletion react-ystemandchess/src/AppRoutes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import AboutUs from "./features/about-us/aboutus/AboutUs";
// Educational content pages
import PlayComputer from "./features/engine/PlayComputer";
import Lessons from "./features/lessons/lessons-main/Lessons";
import Puzzles from './features/puzzles/puzzles-page/Puzzles';
import Puzzles from './features/puzzles/Puzzles';
import LessonSelection from "./features/lessons/lessons-selection/LessonsSelection";
import LessonOverlay from "./features/lessons/piece-lessons/lesson-overlay/Lesson-overlay";

Expand Down
97 changes: 97 additions & 0 deletions react-ystemandchess/src/components/modal/Modal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import React, { useEffect } from "react";

export type ModalType = "success" | "error" | "loading";

export interface ModalProps {
type: ModalType;
title: string;
message?: string;
confirmText?: string;
/** Called after the modal closes itself (button click). Not used for loading. */
onConfirm?: () => void;
}

interface Props extends ModalProps {
/** Called by the modal to close itself — pass your state setter here. */
onClose: () => void;
}

const icons: Record<ModalType, React.ReactNode> = {
success: (
<div className="w-16 h-16 rounded-full bg-primary/20 flex items-center justify-center">
<svg className="w-8 h-8 text-primary" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2.5} d="M5 13l4 4L19 7" />
</svg>
</div>
),
error: (
<div className="w-16 h-16 rounded-full bg-redLight flex items-center justify-center">
<svg className="w-8 h-8 text-red" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2.5} d="M6 18L18 6M6 6l12 12" />
</svg>
</div>
),
loading: (
<div className="w-16 h-16 rounded-full border-4 border-soft border-t-primary animate-spin" />
),
};

const Modal: React.FC<Props> = ({
type,
title,
message,
confirmText = "OK",
onConfirm,
onClose,
}) => {
// Allow ESC to dismiss non-loading modals
useEffect(() => {
if (type === "loading") return;
const handleKey = (e: KeyboardEvent) => {
if (e.key === "Escape") {
onClose();
onConfirm?.();
}
};
window.addEventListener("keydown", handleKey);
return () => window.removeEventListener("keydown", handleKey);
}, [type, onClose, onConfirm]);

const handleConfirm = () => {
onClose();
onConfirm?.();
};

return (
<div
className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-dark/50"
role="dialog"
aria-modal="true"
aria-labelledby="modal-title"
>
<div className="bg-light w-full max-w-sm rounded-2xl shadow-xl p-8 flex flex-col items-center gap-5 animate-modal-in">
{icons[type]}

<h2 id="modal-title" className="text-xl font-bold text-dark text-center">
{title}
</h2>

{message && (
<p className="text-sm text-gray text-center leading-relaxed">{message}</p>
)}

{type !== "loading" && (
<button
className="btn-green w-full mt-1"
onClick={handleConfirm}
autoFocus
>
{confirmText}
</button>
)}
</div>
</div>
);
};

export default Modal;
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,18 @@
line-height: 1.5;
}

.logo-break {
display: flex;
justify-content: center;
margin: 30px 0;

img {
display: block;
max-width: 100%;
height: auto;
}
}

.sponsors-partners-section {
margin-top: 0;

Expand Down
113 changes: 0 additions & 113 deletions react-ystemandchess/src/features/auth/login/Login.scss

This file was deleted.

78 changes: 57 additions & 21 deletions react-ystemandchess/src/features/auth/login/Login.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import React from "react";
// import { Link } from 'react-router-dom';
import './Login.scss';
import { useState } from 'react';
import { environment } from "../../../environments/environment";
import { useCookies } from 'react-cookie';
Expand Down Expand Up @@ -109,14 +107,32 @@ const Login = () => {
});
};

const inputClass = (invalid: boolean) =>
`w-full rounded-lg border-2 px-4 py-3 text-sm text-dark bg-white caret-dark
focus:outline-none focus:shadow-none transition-colors ${
invalid ? "border-red" : "border-borderLight focus:border-primary"
}`;

return (
<div className='login-page'>
<h1 className='login-title'>Login</h1>
{loginError && <div className='login-error' role="alert">{loginError}</div>}
<div className="min-h-[71vh] flex flex-col items-center justify-center px-4 py-12">
<h1 className="text-3xl font-bold text-dark mb-6 text-center">Login</h1>

{loginError && (
<p className="text-red font-semibold mb-4 text-center" role="alert">
{loginError}
</p>
)}

<form className='login-form' aria-label="Login Form" aria-busy={isLoading} onSubmit={submitLogin}>
<div className='input-wrapper'>
<label htmlFor='username' id="username-label">Username</label>
<form
className="w-full max-w-sm bg-light rounded-2xl border-2 border-dark shadow-md p-8 flex flex-col gap-6"
aria-label="Login Form"
aria-busy={isLoading}
onSubmit={submitLogin}
>
<div className="flex flex-col gap-1.5">
<label htmlFor="username" id="username-label" className="text-sm font-bold text-dark">
Username
</label>
<input
type="text"
name="username"
Expand All @@ -127,45 +143,65 @@ const Login = () => {
setUsername(e.target.value);
//usernameVerification();
}}
aria-describedby='loginError-h3'
aria-describedby="loginError-h3"
aria-invalid={usernameFlag}
required
className={inputClass(usernameFlag)}
/>
</div>
<div className='input-wrapper'>
<label htmlFor='password' id="password-label">Password</label>

<div className="flex flex-col gap-1.5">
<label htmlFor="password" id="password-label" className="text-sm font-bold text-dark">
Password
</label>
<input
type="password"
name="password"
placeholder="Password"
id="password"
placeholder="Password"
value={password}
onChange={(e) => {
setPassword(e.target.value);
//passwordVerification();
}}
aria-describedby='loginError-h3'
aria-describedby="loginError-h3"
aria-invalid={passwordFlag}
required
className={inputClass(passwordFlag)}
/>
</div>
<div className='button-wrapper'>
<button type='submit' aria-label='Login Button' disabled={isLoading}>
Enter
</button>

<div className="flex justify-center pt-2">
<button
type="submit"
aria-label="Login Button"
disabled={isLoading}
className="btn-green px-10"
>
Enter
</button>
</div>
</form>

<nav className='login-links' aria-label="Account Options">
<a href='/signup'>
<nav
className="mt-6 flex flex-wrap justify-center gap-6 text-sm font-bold"
aria-label="Account Options"
>
<a
href="/signup"
className="text-dark border-b-2 border-transparent hover:border-dark transition-colors"
>
Create a new account
</a>
<a href='/reset-password'>
<a
href="/reset-password"
className="text-dark border-b-2 border-transparent hover:border-dark transition-colors"
>
Forgot password?
</a>
</nav>
</div>
);
};

export default Login;
export default Login;
Loading
Loading