diff --git a/react-ystemandchess/src/App.css b/react-ystemandchess/src/App.css index c083e43b..7c54c403 100644 --- a/react-ystemandchess/src/App.css +++ b/react-ystemandchess/src/App.css @@ -1,6 +1,4 @@ .App { - overflow-y: hidden; margin-top: 0; text-align: center; - height: 100%; } diff --git a/react-ystemandchess/src/App.tsx b/react-ystemandchess/src/App.tsx index 351e94a3..53281882 100644 --- a/react-ystemandchess/src/App.tsx +++ b/react-ystemandchess/src/App.tsx @@ -142,9 +142,11 @@ function App() { */ return ( -
+
- +
+ +
diff --git a/react-ystemandchess/src/AppRoutes.tsx b/react-ystemandchess/src/AppRoutes.tsx index a962f78d..adcacab0 100644 --- a/react-ystemandchess/src/AppRoutes.tsx +++ b/react-ystemandchess/src/AppRoutes.tsx @@ -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"; diff --git a/react-ystemandchess/src/components/modal/Modal.tsx b/react-ystemandchess/src/components/modal/Modal.tsx new file mode 100644 index 00000000..6c0c1f3f --- /dev/null +++ b/react-ystemandchess/src/components/modal/Modal.tsx @@ -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 = { + success: ( +
+ + + +
+ ), + error: ( +
+ + + +
+ ), + loading: ( +
+ ), +}; + +const Modal: React.FC = ({ + 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 ( +
+
+ {icons[type]} + + + + {message && ( +

{message}

+ )} + + {type !== "loading" && ( + + )} +
+
+ ); +}; + +export default Modal; diff --git a/react-ystemandchess/src/features/about-us/sponsors-partners/SponsorsPartners.scss b/react-ystemandchess/src/features/about-us/sponsors-partners/SponsorsPartners.scss index 7575c692..43885705 100644 --- a/react-ystemandchess/src/features/about-us/sponsors-partners/SponsorsPartners.scss +++ b/react-ystemandchess/src/features/about-us/sponsors-partners/SponsorsPartners.scss @@ -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; diff --git a/react-ystemandchess/src/features/auth/login/Login.scss b/react-ystemandchess/src/features/auth/login/Login.scss deleted file mode 100644 index 8271ceae..00000000 --- a/react-ystemandchess/src/features/auth/login/Login.scss +++ /dev/null @@ -1,113 +0,0 @@ -body { - margin: 0; - font-family: 'Poppins', sans-serif; -} - -.login-page { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - min-height: 100vh; - padding: 1rem; -} - -.login-title { - font-size: 2.5rem; - color: #1e293b; - margin-bottom: 2rem; - text-align: center; -} - -.login-error { - color: #ef4444; - font-weight: 600; - margin-bottom: 1rem; - text-align: center; -} - -.login-form { - display: flex; - flex-direction: column; - gap: 1.5rem; - width: 100%; - max-width: 360px; - background: white; - padding: 2rem; - border-radius: 20px; - box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1); -} - -.input-wrapper { - display: flex; - flex-direction: column; -} - -.input-wrapper label { - font-size: 1rem; - font-weight: 600; - color: #1e293b; - margin-bottom: 0.4rem; -} - -.input-wrapper input { - padding: 12px 16px; - font-size: 1rem; - width: 100%; - border-radius: 8px; - border: 2px solid #cbd5e1; - transition: border 0.3s ease; - background-color: #fff; - font-family: 'Comic Sans MS', cursive; - color: #334155; - box-sizing: border-box; -} - -.input-wrapper input:focus { - border-color: #3b82f6; - outline: none; -} - -.button-wrapper { - display: flex; - justify-content: center; - margin-top: 1rem; -} - -.login-form button { - padding: 12px 40px; - background-color: #3b82f6; - color: white; - font-weight: bold; - font-size: 1.1rem; - border: none; - border-radius: 25px; - box-shadow: 0 6px 10px rgba(0, 0, 0, 0.15); - transition: 0.3s; - cursor: pointer; -} - -.login-form button:hover { - background-color: #2563eb; - transform: scale(1.05); -} - -.login-links { - margin-top: 1.5rem; - display: flex; - justify-content: center; - gap: 2rem; - font-size: 1rem; - font-weight: 600; -} - -.login-links a { - color: #1e293b; - text-decoration: none; - border-bottom: 2px solid transparent; - transition: border-color 0.3s; -} - -.login-links a:hover { - border-color: #1e293b; -} diff --git a/react-ystemandchess/src/features/auth/login/Login.tsx b/react-ystemandchess/src/features/auth/login/Login.tsx index 1060c33b..a1cc874f 100644 --- a/react-ystemandchess/src/features/auth/login/Login.tsx +++ b/react-ystemandchess/src/features/auth/login/Login.tsx @@ -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'; @@ -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 ( -
-

Login

- {loginError &&
{loginError}
} +
+

Login

+ + {loginError && ( +

+ {loginError} +

+ )} -
-
- + +
+ { setUsername(e.target.value); //usernameVerification(); }} - aria-describedby='loginError-h3' + aria-describedby="loginError-h3" aria-invalid={usernameFlag} required + className={inputClass(usernameFlag)} />
-
- + +
+ { setPassword(e.target.value); //passwordVerification(); }} - aria-describedby='loginError-h3' + aria-describedby="loginError-h3" aria-invalid={passwordFlag} required + className={inputClass(passwordFlag)} />
-
- + +
+
-