From f6ba241062e47a00f5c1dbc6915f8c13f40b6433 Mon Sep 17 00:00:00 2001 From: uroma Date: Wed, 21 Jan 2026 14:46:19 +0000 Subject: [PATCH] Add login modal to landing page - Show login modal when user is not authenticated - Add handleLogin, showLoginModal, closeLoginModal functions - Add login modal HTML with username/password form - Add CSS styles for modal Co-Authored-By: Claude Sonnet 4.5 --- database.sqlite-shm | Bin 32768 -> 32768 bytes database.sqlite-wal | Bin 3695672 -> 3745112 bytes public/claude-ide/projects-landing.css | 112 +++++++++++++++++++++++++ public/claude-ide/projects-landing.js | 67 ++++++++++++++- public/claude-landing.html | 24 ++++++ 5 files changed, 201 insertions(+), 2 deletions(-) diff --git a/database.sqlite-shm b/database.sqlite-shm index cf50792cbe323447b82f9f7bf2106ed013babeb8..cfb6ac3ce7e397be96342412c1a03ff1d50ca66f 100644 GIT binary patch delta 214 zcmZo@U}|V!s+V}A%K!o#K+MR%AkfRqz`zM)yX5;FU%ERyd2edWM(K`{<7twanhDA7 z`J}1`nGFIUbN?d&h$zFxdS1TC0*nTmd-$A8Hvea-s2AlsmaWPF6a{sdVkE;;lW+9(9jGKRX X@PJsK7&rg$W@80Pe%t&dkVg*y+;Tt) diff --git a/database.sqlite-wal b/database.sqlite-wal index 8159e1e4b88ad4de7f2a4b4eb94bdf82e468c51d..e530162eee6e2bcb5bf1c102bcb92830fb7e6b7e 100644 GIT binary patch delta 421 zcmdmS;vwUWQ%@KhS{PfHT9{i{T3B1yTG(4SS~y#{TDV(yT6kOdTKHQ8S_E5!T7+9f zT0~pKTEtr*?8k;5fg40B6VCNkNhOWo~h8Ke&mJUw|Vk zDA2K!Zyne6gk6RL0vsm}<=QofZfnLcm zruNmh9{$_z@W%+qee3upWQX66a14VOfd+{~4eIy=G>Ee_cBjM7?52+}C+$D1D_{Fx vEOz?`DUeAH-t3`!eH^k;Oagip1Q;ctCMht2oOIkT-z7PG_tNDG)D@Y+ewj>`)Fe>nCMj>{ek9Tmpzk-XvmymB^5m7O5 z2}vnw8Cf}b1w|!g6;(BL4NWa=9bG?u_4Ex4jg0-7n3|beSX%kFwz0LdcW}I(PUjCO CS}9Th diff --git a/public/claude-ide/projects-landing.css b/public/claude-ide/projects-landing.css index ed05810d..8dfd483e 100644 --- a/public/claude-ide/projects-landing.css +++ b/public/claude-ide/projects-landing.css @@ -417,3 +417,115 @@ body.sessions-page { padding-top: 80px; } } + +/* === Login Modal === */ +.modal { + display: none; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.8); + justify-content: center; + align-items: center; + z-index: 10000; +} + +.modal-content { + background: #1a1a1a; + border: 1px solid #333; + border-radius: 12px; + padding: 0; + width: 100%; + max-width: 400px; + box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5); +} + +.modal-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 20px 24px; + border-bottom: 1px solid #333; +} + +.modal-header h2 { + margin: 0; + font-size: 18px; + color: #e0e0e0; +} + +.modal-close { + background: none; + border: none; + color: #888; + font-size: 24px; + cursor: pointer; + padding: 0; + width: 32px; + height: 32px; + display: flex; + align-items: center; + justify-content: center; +} + +.modal-close:hover { + color: #fff; +} + +.modal-body { + padding: 24px; +} + +.form-group { + margin-bottom: 16px; +} + +.form-group label { + display: block; + margin-bottom: 6px; + color: #aaa; + font-size: 13px; +} + +.form-group input { + width: 100%; + padding: 10px 12px; + background: #0d0d0d; + border: 1px solid #333; + border-radius: 6px; + color: #e0e0e0; + font-size: 14px; +} + +.form-group input:focus { + outline: none; + border-color: #4a9eff; +} + +.btn-primary { + width: 100%; + padding: 12px; + background: #4a9eff; + color: white; + border: none; + border-radius: 6px; + font-size: 14px; + font-weight: 600; + cursor: pointer; +} + +.btn-primary:hover { + background: #3a8eef; +} + +.login-error { + margin-bottom: 16px; + padding: 10px 12px; + background: rgba(255, 107, 107, 0.1); + border: 1px solid #ff6b6b; + border-radius: 6px; + color: #ff6b6b; + font-size: 13px; +} diff --git a/public/claude-ide/projects-landing.js b/public/claude-ide/projects-landing.js index 975ec59d..34df7a95 100644 --- a/public/claude-ide/projects-landing.js +++ b/public/claude-ide/projects-landing.js @@ -27,10 +27,73 @@ async function checkAuth() { const data = await res.json(); if (!data.authenticated) { - window.location.href = '/claude/login.html'; + // Show login modal instead of redirecting + showLoginModal(); + return; + } + + // Update nav with username + if (data.username) { + document.querySelector('.nav-logo').textContent = `Claude Code (${data.username})`; } } catch (error) { - console.error('Auth check failed:', error); + console.error('[checkAuth] Error:', error); + showLoginModal(); + } +} + +// Show login modal +function showLoginModal() { + const modal = document.getElementById('login-modal'); + if (modal) { + modal.style.display = 'flex'; + } +} + +// Close login modal +function closeLoginModal() { + const modal = document.getElementById('login-modal'); + if (modal) { + modal.style.display = 'none'; + } +} + +// Handle login form submission +async function handleLogin(event) { + event.preventDefault(); + + const username = document.getElementById('login-username').value; + const password = document.getElementById('login-password').value; + const errorDiv = document.getElementById('login-error'); + + try { + const res = await fetch('/claude/api/login', { + method: 'POST', + credentials: 'same-origin', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ username, password }) + }); + + const data = await res.json(); + + if (data.success) { + // Login successful + closeLoginModal(); + loadProjects(); + + // Update nav with username + if (data.username) { + document.querySelector('.nav-logo').textContent = `Claude Code (${data.username})`; + } + } else { + // Show error + errorDiv.textContent = data.error || 'Login failed'; + errorDiv.style.display = 'block'; + } + } catch (error) { + console.error('[handleLogin] Error:', error); + errorDiv.textContent = 'Login failed. Please try again.'; + errorDiv.style.display = 'block'; } } diff --git a/public/claude-landing.html b/public/claude-landing.html index 8062eb71..3b0ed886 100644 --- a/public/claude-landing.html +++ b/public/claude-landing.html @@ -65,6 +65,30 @@ + + +