diff --git a/css/index.css b/css/index.css index b3ca57a..d4bba80 100644 --- a/css/index.css +++ b/css/index.css @@ -4592,6 +4592,127 @@ body { font-weight: 600; } +.profile-modal { + position: fixed; + inset: 0; + background: rgba(0,0,0,0.45); + + display: none; + justify-content: center; + align-items: center; + + z-index: 10000; + backdrop-filter: blur(6px); +} + +.profile-content { + width: 420px; + max-width: 90vw; + + background: #ffffff; + border-radius: 20px; + + padding: 28px; + + box-shadow: + 0 20px 60px rgba(0,0,0,.18); + + animation: profileFade .2s ease; +} + +@keyframes profileFade { + from { + opacity: 0; + transform: translateY(12px); + } + + to { + opacity: 1; + transform: translateY(0); + } +} + +.profile-header { + display: flex; + align-items: center; + gap: 16px; + + margin-bottom: 24px; +} + +.profile-avatar { + width: 60px; + height: 60px; + + border-radius: 50%; + + background: #111; + color: white; + + display: flex; + align-items: center; + justify-content: center; + + font-size: 24px; + font-weight: 700; +} + +.profile-header h2 { + margin: 0; + font-size: 24px; +} + +.profile-subtitle { + margin-top: 4px; + color: #666; + font-size: 14px; +} + +.profile-info label { + display: block; + + color: #777; + + font-size: 13px; + margin-bottom: 6px; +} + +.profile-value { + background: #f6f6f6; + + padding: 14px; + border-radius: 10px; + + font-size: 15px; + font-weight: 500; +} + +.profile-actions { + display: flex; + justify-content: flex-end; + + margin-top: 24px; +} + +.profile-close-btn { + border: none; + + background: #111; + color: white; + + padding: 12px 20px; + border-radius: 10px; + + cursor: pointer; + font-weight: 600; + + transition: .2s; +} + +.profile-close-btn:hover { + transform: translateY(-1px); +} + /* Footer */ .site-footer { width: 100%; diff --git a/index.html b/index.html index cd7ef13..eb518a6 100644 --- a/index.html +++ b/index.html @@ -15,12 +15,12 @@
- +

Welcome back

Sign in to your StudyPlan account

- +
- -

Don't have an account? Sign Up @@ -61,11 +59,40 @@

StudyPlan

- +
+
@@ -233,12 +260,6 @@

StudyPlan

- -
- - @@ -318,6 +339,11 @@

{ + const user = JSON.parse(localStorage.getItem("studyplan_user")); + document.getElementById("profile-email").textContent = user?.email || "Unknown"; + const avatar = document.querySelector(".profile-avatar"); + avatar.textContent = (user?.email?.charAt(0) || "U").toUpperCase(); + profileModal.style.display = "flex"; + }); + closeProfile.addEventListener("click", () => { + profileModal.style.display = "none"; + }); + window.addEventListener("click", (e) => { + if (e.target === profileModal) { + profileModal.style.display = "none"; + } + }); + } // Settings Modal Logic const settingsModal = document.getElementById('settings-modal'); diff --git a/server.js b/server.js index 47e1429..809db84 100644 --- a/server.js +++ b/server.js @@ -511,11 +511,17 @@ Text: "${text}" // ================= AUTH ================= const users = {}; // Simple in-memory user store +// Email format validator (RFC 5321-compatible) +const EMAIL_REGEX = /^[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}$/; + app.post('/api/auth/signup', (req, res) => { const { email, password } = req.body; if (!email || !password) { return res.status(400).json({ error: 'Email and password required' }); } + if (!EMAIL_REGEX.test(email)) { + return res.status(400).json({ error: 'Invalid email address format' }); + } if (users[email]) { return res.status(400).json({ error: 'User already exists' }); } @@ -528,6 +534,9 @@ app.post('/api/auth/login', (req, res) => { if (!email || !password) { return res.status(400).json({ error: 'Email and password required' }); } + if (!EMAIL_REGEX.test(email)) { + return res.status(400).json({ error: 'Invalid email address format' }); + } const user = users[email]; if (!user || user.password !== password) { return res.status(401).json({ error: 'Invalid email or password' });