refactor: redesign web UX with progressive disclosure and cleaned layout
This commit is contained in:
@@ -1,167 +1,160 @@
|
||||
<!doctype html>
|
||||
<html lang="ko">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>Tutor Platform</title>
|
||||
<link rel="stylesheet" href="/assets/styles.css" />
|
||||
<style>
|
||||
#workspace-view { display: none; }
|
||||
</style>
|
||||
</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>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>Tutor Platform</title>
|
||||
<link rel="stylesheet" href="/assets/styles.css?v=4" />
|
||||
</head>
|
||||
<body>
|
||||
<!-- Google auth bridge (unchanged) -->
|
||||
<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">
|
||||
<div class="login-card">
|
||||
<div class="login-header">
|
||||
<p class="eyebrow" data-i18n="eyebrow">Tutor Platform</p>
|
||||
<div class="lang-switch" role="group" aria-label="Language">
|
||||
<button type="button" data-lang="ko" class="lang-btn is-active">KO</button>
|
||||
<button type="button" data-lang="en" class="lang-btn">EN</button>
|
||||
</div>
|
||||
</div>
|
||||
<h1 data-i18n="titleLogin">Interview practice</h1>
|
||||
<p class="lede" data-i18n="subtitleLogin">
|
||||
Prove you are becoming more interview-ready after each short practice loop.
|
||||
</p>
|
||||
<div class="login-divider" data-i18n="accountDivider" 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="login-error" role="alert"></p>
|
||||
<p class="login-legal" data-i18n="legalLogin">
|
||||
By signing in, you agree to our <a href="#">Terms</a> and
|
||||
<a href="#">Privacy Policy</a>.
|
||||
</p>
|
||||
<!-- ============ LOGIN VIEW ============ -->
|
||||
<main id="login-view" class="login-page">
|
||||
<div class="login-card">
|
||||
<div class="login-brand" data-i18n="eyebrow">Tutor Platform</div>
|
||||
<h1 class="login-heading" data-i18n="loginHeading">Turn answers into evidence</h1>
|
||||
<p class="login-desc" data-i18n="loginDesc">짧은 연습 루프로 면접 준비도를 눈으로 확인하세요.</p>
|
||||
<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>
|
||||
</section>
|
||||
<p id="login-error" class="login-error" role="alert"></p>
|
||||
<div class="lang-switch login-lang" role="group" aria-label="Language">
|
||||
<button type="button" data-lang="ko" class="lang-btn is-active">KO</button>
|
||||
<button type="button" data-lang="en" class="lang-btn">EN</button>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<main id="workspace-view" class="workspace" style="display: none">
|
||||
<aside class="setup-pane" aria-label="Diagnostic setup">
|
||||
<div class="workspace-header">
|
||||
<p class="eyebrow" data-i18n="eyebrow">Tutor Platform</p>
|
||||
<div class="lang-switch" role="group" aria-label="Language">
|
||||
<button type="button" data-lang="ko" class="lang-btn is-active">KO</button>
|
||||
<button type="button" data-lang="en" class="lang-btn">EN</button>
|
||||
<!-- ============ WORKSPACE VIEW ============ -->
|
||||
<div id="workspace-view" class="workspace" style="display:none">
|
||||
|
||||
<!-- Top bar -->
|
||||
<header class="topbar">
|
||||
<span class="topbar-brand" data-i18n="eyebrow">Tutor Platform</span>
|
||||
<nav class="topbar-center">
|
||||
<span id="step-indicator" class="step-indicator"></span>
|
||||
</nav>
|
||||
<div class="topbar-right">
|
||||
<button id="tools-toggle" class="icon-btn" type="button" aria-label="Tools" title="Tools">⚙</button>
|
||||
<div class="lang-switch" role="group" aria-label="Language">
|
||||
<button type="button" data-lang="ko" class="lang-btn is-active">KO</button>
|
||||
<button type="button" data-lang="en" class="lang-btn">EN</button>
|
||||
</div>
|
||||
<div class="user-menu">
|
||||
<span id="user-info" class="user-name"></span>
|
||||
<button id="logout-button" class="link-btn" data-i18n="signOut">Sign out</button>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Main area: 2-column -->
|
||||
<div class="main-grid">
|
||||
|
||||
<!-- LEFT: Practice -->
|
||||
<section class="main-pane">
|
||||
|
||||
<!-- Session setup card (shows when no session active) -->
|
||||
<div id="setup-card" class="setup-card">
|
||||
<div class="card-header">
|
||||
<h2 data-i18n="startSession">Start diagnostic</h2>
|
||||
<p class="card-hint" data-i18n="startHint">면접 질문을 생성하고 첫 답변을 만들어보세요.</p>
|
||||
</div>
|
||||
</div>
|
||||
<h1 data-i18n="titleWorkspace">Interview practice</h1>
|
||||
<p class="lede" data-i18n="subtitleWorkspace">
|
||||
Start a focused backend interview loop and turn one answer into evidence.
|
||||
</p>
|
||||
|
||||
<div class="user-bar">
|
||||
<div id="user-info" class="user-info"></div>
|
||||
<button id="logout-button" class="small-button" type="button" data-i18n="signOut">
|
||||
Sign out
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<form id="session-form" class="stacked-form">
|
||||
<label>
|
||||
<span data-i18n="userId">User ID</span>
|
||||
<input id="user-id" name="user_id" value="" readonly autocomplete="off" />
|
||||
</label>
|
||||
<label>
|
||||
<span data-i18n="targetRole">Target role</span>
|
||||
<input id="target-role" name="target_role" value="junior backend developer" />
|
||||
</label>
|
||||
<label>
|
||||
<span data-i18n="stack">Stack</span>
|
||||
<input id="stack" name="stack" value="go, postgres" />
|
||||
</label>
|
||||
<label>
|
||||
<span data-i18n="timeline">Timeline</span>
|
||||
<input id="timeline" name="interview_timeline" value="30 days" />
|
||||
</label>
|
||||
<button id="start-button" type="submit">
|
||||
<span class="btn-text" data-i18n="startDiagnostic">Start diagnostic</span>
|
||||
<span class="btn-spinner" aria-hidden="true"></span>
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<p id="status-line" class="status-line" role="status">
|
||||
<span class="status-icon" aria-hidden="true"></span>
|
||||
<span class="status-text" data-i18n="ready">Ready</span>
|
||||
</p>
|
||||
<p id="error-line" class="error-line" role="alert"></p>
|
||||
</aside>
|
||||
|
||||
<section class="practice-pane" aria-label="Diagnostic practice">
|
||||
<div class="section-heading">
|
||||
<div>
|
||||
<p class="eyebrow" data-i18n="diagnosticEyebrow">Diagnostic</p>
|
||||
<h2 id="session-title" data-i18n="noActiveSession">No active session</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div id="questions" class="question-list empty-state">
|
||||
<span class="empty-hint" data-i18n="emptyQuestions"
|
||||
>Start a diagnostic session to load interview questions.</span
|
||||
>
|
||||
</div>
|
||||
|
||||
<form id="answer-form" class="answer-form">
|
||||
<label for="answer-text" data-i18n="answerLabel">Answer</label>
|
||||
<textarea
|
||||
id="answer-text"
|
||||
rows="7"
|
||||
data-i18n-placeholder="answerPlaceholder"
|
||||
placeholder="Select a question, then answer with concrete production reasoning."
|
||||
></textarea>
|
||||
<button id="answer-button" type="submit" disabled>
|
||||
<span class="btn-text" data-i18n="submitAnswer">Submit answer</span>
|
||||
<span class="btn-spinner" aria-hidden="true"></span>
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<section class="content-workspace" aria-label="Material and asset workspace">
|
||||
<div class="section-heading">
|
||||
<div>
|
||||
<p class="eyebrow" data-i18n="contentEyebrow">Content operations</p>
|
||||
<h2 data-i18n="contentTitle">Source to asset prompt</h2>
|
||||
<form id="session-form" class="inline-form">
|
||||
<div class="field-row">
|
||||
<label>
|
||||
<span data-i18n="targetRole">Target role</span>
|
||||
<input id="target-role" name="target_role" value="junior backend developer" />
|
||||
</label>
|
||||
<label>
|
||||
<span data-i18n="stack">Stack</span>
|
||||
<input id="stack" name="stack" value="go, postgres" />
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<button id="start-button" type="submit">
|
||||
<span class="btn-text" data-i18n="startDiagnostic">Start diagnostic</span>
|
||||
<span class="btn-spinner" aria-hidden="true"></span>
|
||||
</button>
|
||||
</form>
|
||||
<p id="status-line" class="status-line" role="status">
|
||||
<span class="status-dot" aria-hidden="true"></span>
|
||||
<span class="status-text" data-i18n="ready">Ready</span>
|
||||
</p>
|
||||
<p id="error-line" class="error-line" role="alert"></p>
|
||||
</div>
|
||||
|
||||
<form id="material-form" class="material-form">
|
||||
<!-- Question selector (shows after session starts) -->
|
||||
<div id="question-bar" class="question-bar" style="display:none">
|
||||
<div class="bar-label" data-i18n="questions">Questions</div>
|
||||
<div id="questions" class="question-tabs" role="tablist"></div>
|
||||
</div>
|
||||
|
||||
<!-- Answer area (shows after session starts) -->
|
||||
<div id="answer-area" class="answer-area" style="display:none">
|
||||
<form id="answer-form" class="answer-form">
|
||||
<div class="answer-header">
|
||||
<label for="answer-text" data-i18n="yourAnswer">Your answer</label>
|
||||
<span id="answer-hint" class="answer-hint" data-i18n="answerHint">구체적인 프로덕션 관점에서 답변하세요.</span>
|
||||
</div>
|
||||
<textarea
|
||||
id="answer-text"
|
||||
rows="8"
|
||||
data-i18n-placeholder="answerPlaceholder"
|
||||
placeholder="Select a question, then answer with concrete production reasoning."
|
||||
></textarea>
|
||||
<button id="answer-button" type="submit" disabled>
|
||||
<span class="btn-text" data-i18n="submitAnswer">Submit answer</span>
|
||||
<span class="btn-spinner" aria-hidden="true"></span>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Content tools panel (hidden by default) -->
|
||||
<div id="tools-panel" class="tools-panel" style="display:none">
|
||||
<div class="tools-divider"></div>
|
||||
<h2 data-i18n="contentTitle">Source to asset prompt</h2>
|
||||
|
||||
<form id="material-form" class="stacked-form">
|
||||
<div class="field-row">
|
||||
<label>
|
||||
<span data-i18n="materialTitle">Material title</span>
|
||||
<input id="material-title" value="Backend interview notes" />
|
||||
</label>
|
||||
<label>
|
||||
<span data-i18n="sourceType">Source type</span>
|
||||
<input id="material-source" value="markdown" />
|
||||
</label>
|
||||
</div>
|
||||
<label>
|
||||
<span data-i18n="materialTitle">Material title</span>
|
||||
<input id="material-title" value="Backend interview notes" />
|
||||
</label>
|
||||
<label>
|
||||
<span data-i18n="sourceType">Source type</span>
|
||||
<input id="material-source" value="markdown" />
|
||||
</label>
|
||||
<label class="wide-field">
|
||||
<span data-i18n="sourceMaterial">Source material</span>
|
||||
<textarea id="material-body" rows="5">
|
||||
Idempotent API retries need transactions. Cache invalidation uses TTL tradeoffs and database indexes support query plans.</textarea
|
||||
>
|
||||
<textarea id="material-body" rows="4">
|
||||
Idempotent API retries need transactions. Cache invalidation uses TTL tradeoffs and database indexes support query plans.</textarea>
|
||||
</label>
|
||||
<button id="material-button" type="submit">
|
||||
<span class="btn-text" data-i18n="ingestMaterial">Ingest material</span>
|
||||
@@ -170,12 +163,10 @@ Idempotent API retries need transactions. Cache invalidation uses TTL tradeoffs
|
||||
</form>
|
||||
|
||||
<div id="ontology" class="ontology-view empty-state">
|
||||
<span class="empty-hint" data-i18n="emptyOntology"
|
||||
>Ingest material to inspect ontology candidates.</span
|
||||
>
|
||||
<span class="empty-hint" data-i18n="emptyOntology">Ingest material to inspect ontology candidates.</span>
|
||||
</div>
|
||||
|
||||
<form id="asset-form" class="asset-form">
|
||||
<form id="asset-form" class="inline-form">
|
||||
<label>
|
||||
<span data-i18n="concept">Concept</span>
|
||||
<select id="asset-concept" disabled>
|
||||
@@ -198,42 +189,57 @@ Idempotent API retries need transactions. Cache invalidation uses TTL tradeoffs
|
||||
</form>
|
||||
|
||||
<div id="asset-output" class="ontology-view empty-state">
|
||||
<span class="empty-hint" data-i18n="emptyAsset"
|
||||
>Generate a prompt to inspect model key, review state, and evidence.</span
|
||||
>
|
||||
<span class="empty-hint" data-i18n="emptyAsset">Generate a prompt to inspect model key, review state, and evidence.</span>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
||||
<aside class="feedback-pane" aria-label="Feedback">
|
||||
<div class="section-heading">
|
||||
<div>
|
||||
<p class="eyebrow" data-i18n="feedbackEyebrow">Feedback</p>
|
||||
<h2 data-i18n="rubricResult">Rubric result</h2>
|
||||
<!-- RIGHT: Feedback sidebar -->
|
||||
<aside class="feedback-sidebar">
|
||||
|
||||
<!-- Empty state -->
|
||||
<div id="feedback-empty" class="sidebar-empty">
|
||||
<div class="empty-icon"></div>
|
||||
<p data-i18n="feedbackEmpty">답변을 제출하면 채점 결과가 여기에 표시됩니다.</p>
|
||||
</div>
|
||||
|
||||
<!-- Feedback content (hidden until answer submitted) -->
|
||||
<div id="feedback-content" class="feedback-content" style="display:none">
|
||||
<div class="feedback-grade">
|
||||
<div id="grade-display" class="grade-badge"></div>
|
||||
<p id="grade-strength" class="grade-summary"></p>
|
||||
</div>
|
||||
|
||||
<div id="score-metrics" class="score-metrics"></div>
|
||||
|
||||
<div id="gaps-block" class="feedback-block"></div>
|
||||
<div id="followup-block" class="feedback-block"></div>
|
||||
<div id="evidence-block" class="feedback-block"></div>
|
||||
</div>
|
||||
<div id="feedback" class="feedback empty-state">
|
||||
<span class="empty-hint" data-i18n="emptyFeedback"
|
||||
>Submit an answer to see grade, evidence, and follow-up.</span
|
||||
>
|
||||
</div>
|
||||
<div class="section-heading progress-heading">
|
||||
<div>
|
||||
<p class="eyebrow" data-i18n="progressEyebrow">Progress</p>
|
||||
<h2 data-i18n="learningState">Learning state</h2>
|
||||
|
||||
<!-- Divider -->
|
||||
<div class="sidebar-divider" id="progress-divider" style="display:none"></div>
|
||||
|
||||
<!-- Progress section -->
|
||||
<div id="progress-content" class="progress-content" style="display:none">
|
||||
<div class="progress-header">
|
||||
<h3 data-i18n="learningState">Learning state</h3>
|
||||
<button id="refresh-progress" class="link-btn" type="button" disabled data-i18n="refresh">Refresh</button>
|
||||
</div>
|
||||
<button id="refresh-progress" class="small-button" type="button" disabled data-i18n="refresh">
|
||||
Refresh
|
||||
</button>
|
||||
</div>
|
||||
<div id="progress" class="feedback empty-state">
|
||||
<span class="empty-hint" data-i18n="emptyProgress"
|
||||
>Answer once to update learner memory and readiness.</span
|
||||
>
|
||||
<div class="progress-bar-wrap">
|
||||
<div id="progress-bar" class="progress-bar" style="width:0%"></div>
|
||||
<span id="readiness-pct" class="progress-pct">0%</span>
|
||||
</div>
|
||||
<div id="concept-memory" class="concept-list"></div>
|
||||
<div id="next-challenge-block" class="challenge-block"></div>
|
||||
</div>
|
||||
|
||||
</aside>
|
||||
</main>
|
||||
<script src="/assets/i18n.js?v=3"></script>
|
||||
<script src="/assets/app.js?v=3"></script>
|
||||
</body>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="/assets/i18n.js?v=4"></script>
|
||||
<script src="/assets/app.js?v=4"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user