ui: redesign login lobby, fix auth view transition timing
This commit is contained in:
@@ -364,28 +364,45 @@ function evidenceBlock(evidence = []) {
|
||||
return `<section><h2>Evidence</h2><ul class="small-list">${evidence.map((item) => `<li>${escapeHTML(item.quote || item.id)}</li>`).join("")}</ul></section>`;
|
||||
}
|
||||
|
||||
window.handleCredentialResponse = async (response) => {
|
||||
window._tutorGoogleCallback = async (response) => {
|
||||
console.log("[auth] Google callback fired");
|
||||
try {
|
||||
const res = await request("/api/v1/auth/google", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({ id_token: response.credential }),
|
||||
});
|
||||
console.log("[auth] Backend login success", res.user?.email);
|
||||
localStorage.setItem("tutor_token", res.token);
|
||||
localStorage.setItem("tutor_user", JSON.stringify(res.user));
|
||||
if (els.loginError) {
|
||||
els.loginError.textContent = "";
|
||||
els.loginError.classList.remove("visible");
|
||||
}
|
||||
renderAuth();
|
||||
} catch (err) {
|
||||
if (els.loginError) els.loginError.textContent = err.message;
|
||||
console.error("[auth] Backend login failed", err);
|
||||
if (els.loginError) {
|
||||
els.loginError.textContent = err.message;
|
||||
els.loginError.classList.add("visible");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (window._tutorPendingGoogleResponse) {
|
||||
window._tutorGoogleCallback(window._tutorPendingGoogleResponse);
|
||||
window._tutorPendingGoogleResponse = null;
|
||||
}
|
||||
|
||||
function renderAuth() {
|
||||
const user = JSON.parse(localStorage.getItem("tutor_user") || "null");
|
||||
const token = localStorage.getItem("tutor_token");
|
||||
console.log("[auth] renderAuth", { hasUser: !!user, hasToken: !!token });
|
||||
if (user && token) {
|
||||
els.loginView.style.display = "none";
|
||||
els.workspaceView.style.display = "grid";
|
||||
els.userInfo.textContent = user.email;
|
||||
setStatus(`Signed in as ${user.email}`);
|
||||
els.userInfo.textContent = user.email || user.name || "User";
|
||||
setStatus(`Signed in as ${user.email || user.name}`);
|
||||
if (els.loginError) els.loginError.classList.remove("visible");
|
||||
} else {
|
||||
els.loginView.style.display = "flex";
|
||||
els.workspaceView.style.display = "none";
|
||||
|
||||
@@ -7,6 +7,17 @@
|
||||
<link rel="stylesheet" href="/assets/styles.css" />
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
window._tutorGoogleCallback = null;
|
||||
window._tutorPendingGoogleResponse = null;
|
||||
window.handleCredentialResponse = function(response) {
|
||||
if (window._tutorGoogleCallback) {
|
||||
window._tutorGoogleCallback(response);
|
||||
} else {
|
||||
window._tutorPendingGoogleResponse = response;
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<script src="https://accounts.google.com/gsi/client" async defer></script>
|
||||
|
||||
<section id="login-view" class="login-view">
|
||||
@@ -14,11 +25,13 @@
|
||||
<p class="eyebrow">Tutor Platform</p>
|
||||
<h1>Interview practice</h1>
|
||||
<p class="lede">Prove you are becoming more interview-ready after each short practice loop.</p>
|
||||
<div class="login-divider" data-label="Account"></div>
|
||||
<div id="auth-area" class="auth-area">
|
||||
<div id="g_id_onload" data-client_id="13671390758-bp1ed6psn43bl86r8a9kv81o40nkea90.apps.googleusercontent.com" data-callback="handleCredentialResponse" data-auto_prompt="false"></div>
|
||||
<div class="g_id_signin" data-type="standard" data-size="large" data-theme="outline" data-text="sign_in_with" data-shape="rectangular" data-logo_alignment="left"></div>
|
||||
</div>
|
||||
<p id="login-error" class="error-line" role="alert"></p>
|
||||
<p id="login-error" class="login-error" role="alert"></p>
|
||||
<p class="login-legal">By signing in, you agree to our <a href="#">Terms</a> and <a href="#">Privacy Policy</a>.</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ select {
|
||||
}
|
||||
|
||||
.workspace {
|
||||
display: grid;
|
||||
display: none;
|
||||
grid-template-columns: minmax(260px, 320px) minmax(360px, 1fr) minmax(280px, 360px);
|
||||
gap: 1px;
|
||||
min-height: 100vh;
|
||||
@@ -464,27 +464,94 @@ button.is-loading .btn-spinner {
|
||||
justify-content: center;
|
||||
min-height: 100vh;
|
||||
padding: 28px;
|
||||
background: var(--bg);
|
||||
background: linear-gradient(160deg, #f5f7f4 0%, #e8efe5 100%);
|
||||
}
|
||||
|
||||
.login-card {
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 12px;
|
||||
padding: 44px 36px;
|
||||
max-width: 420px;
|
||||
border-radius: 18px;
|
||||
padding: 52px 40px 44px;
|
||||
max-width: 440px;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
box-shadow: 0 12px 40px rgba(24, 32, 27, 0.07);
|
||||
}
|
||||
|
||||
.login-card .eyebrow {
|
||||
display: inline-block;
|
||||
letter-spacing: 0.14em;
|
||||
font-size: 11px;
|
||||
text-transform: uppercase;
|
||||
color: var(--accent);
|
||||
font-weight: 750;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
html[lang="ko"] .login-card .eyebrow {
|
||||
text-transform: none;
|
||||
letter-spacing: 0.04em;
|
||||
}
|
||||
|
||||
.login-card h1 {
|
||||
font-size: clamp(32px, 5vw, 52px);
|
||||
margin: 14px 0 18px;
|
||||
font-size: clamp(34px, 5.5vw, 56px);
|
||||
margin: 8px 0 18px;
|
||||
line-height: 1.05;
|
||||
}
|
||||
|
||||
.login-card .lede {
|
||||
margin: 0 auto 28px;
|
||||
max-width: 34ch;
|
||||
margin: 0 auto 32px;
|
||||
max-width: 32ch;
|
||||
color: var(--muted);
|
||||
font-size: 15px;
|
||||
line-height: 1.55;
|
||||
}
|
||||
|
||||
.login-divider {
|
||||
height: 1px;
|
||||
background: var(--line);
|
||||
margin: 28px 0 24px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.login-divider::before {
|
||||
content: attr(data-label);
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
background: var(--surface);
|
||||
padding: 0 12px;
|
||||
color: var(--muted);
|
||||
font-size: 11px;
|
||||
letter-spacing: 0.08em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.login-legal {
|
||||
margin-top: 18px;
|
||||
font-size: 12px;
|
||||
color: var(--muted);
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.login-legal a {
|
||||
color: var(--muted);
|
||||
text-decoration: underline;
|
||||
text-underline-offset: 2px;
|
||||
}
|
||||
|
||||
.login-error {
|
||||
margin-top: 14px;
|
||||
padding: 10px 14px;
|
||||
border-radius: 8px;
|
||||
background: var(--weak-bg);
|
||||
color: var(--weak);
|
||||
font-size: 13px;
|
||||
display: none;
|
||||
}
|
||||
.login-error.visible {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.user-bar {
|
||||
|
||||
Reference in New Issue
Block a user