banao-tech commited on
Commit
99e5a74
·
verified ·
1 Parent(s): 7dae4c8

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +623 -19
index.html CHANGED
@@ -1,19 +1,623 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Problem Solver — AI Intern Tool</title>
7
+ <link rel="preconnect" href="https://fonts.googleapis.com" />
8
+ <link href="https://fonts.googleapis.com/css2?family=Fraunces:ital,wght@0,300;0,500;0,700;1,300&family=Geist+Mono:wght@400;500&family=Plus+Jakarta+Sans:wght@400;500;600&display=swap" rel="stylesheet" />
9
+ <style>
10
+ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
11
+
12
+ :root {
13
+ --bg: #f7f6f2;
14
+ --white: #ffffff;
15
+ --surface: #f0eeea;
16
+ --border: #e2dfd8;
17
+ --border2: #d4d0c8;
18
+ --ink: #1a1916;
19
+ --ink2: #3d3b35;
20
+ --muted: #7a776e;
21
+ --muted2: #a09d95;
22
+ --accent: #d4621a;
23
+ --accent2: #b8501a;
24
+ --accent-bg: #fdf1ea;
25
+ --green: #2d7a4f;
26
+ --green-bg: #eaf4ee;
27
+ --font-head: 'Fraunces', Georgia, serif;
28
+ --font-body: 'Plus Jakarta Sans', sans-serif;
29
+ --font-mono: 'Geist Mono', monospace;
30
+ }
31
+
32
+ html { scroll-behavior: smooth; }
33
+ body {
34
+ font-family: var(--font-body);
35
+ background: var(--bg);
36
+ color: var(--ink);
37
+ min-height: 100vh;
38
+ font-size: 14px;
39
+ }
40
+
41
+ /* ── App Shell ───────────────────────────────────────────── */
42
+ .app {
43
+ display: grid;
44
+ grid-template-columns: 400px 1fr;
45
+ grid-template-rows: 56px 1fr;
46
+ height: 100vh;
47
+ overflow: hidden;
48
+ }
49
+
50
+ /* ── Top Bar ─────────────────────────────────────────────── */
51
+ .topbar {
52
+ grid-column: 1 / -1;
53
+ display: flex;
54
+ align-items: center;
55
+ justify-content: space-between;
56
+ padding: 0 28px;
57
+ border-bottom: 1px solid var(--border);
58
+ background: var(--white);
59
+ }
60
+ .topbar-logo {
61
+ font-family: var(--font-head);
62
+ font-size: 17px;
63
+ font-weight: 700;
64
+ color: var(--ink);
65
+ letter-spacing: -.02em;
66
+ display: flex;
67
+ align-items: center;
68
+ gap: 8px;
69
+ }
70
+ .topbar-logo .dot { width: 8px; height: 8px; background: var(--accent); border-radius: 50%; }
71
+ .topbar-meta { font-size: 12px; color: var(--muted); font-family: var(--font-mono); letter-spacing: .02em; }
72
+
73
+ /* ── Left Panel ──────────────────────────────────────────── */
74
+ .panel-left {
75
+ border-right: 1px solid var(--border);
76
+ background: var(--white);
77
+ display: flex;
78
+ flex-direction: column;
79
+ overflow: hidden;
80
+ }
81
+ .panel-inner { flex: 1; overflow-y: auto; padding: 28px 24px; }
82
+ .panel-inner::-webkit-scrollbar { width: 3px; }
83
+ .panel-inner::-webkit-scrollbar-thumb { background: var(--border2); }
84
+
85
+ .section-label {
86
+ font-family: var(--font-mono);
87
+ font-size: 10px;
88
+ font-weight: 500;
89
+ letter-spacing: .12em;
90
+ text-transform: uppercase;
91
+ color: var(--muted2);
92
+ margin-bottom: 12px;
93
+ }
94
+
95
+ /* ── Fields ──────────────────────────────────────────────── */
96
+ .fields-row { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-bottom: 24px; }
97
+ .field label { display: block; font-size: 11px; font-weight: 600; color: var(--muted); margin-bottom: 5px; letter-spacing: .03em; }
98
+ input[type="text"] {
99
+ width: 100%;
100
+ background: var(--surface);
101
+ border: 1px solid var(--border);
102
+ border-radius: 8px;
103
+ color: var(--ink);
104
+ font-family: var(--font-body);
105
+ font-size: 13px;
106
+ padding: 9px 12px;
107
+ transition: border-color .15s, box-shadow .15s;
108
+ outline: none;
109
+ }
110
+ input[type="text"]:focus { border-color: var(--accent); box-shadow: 0 0 0 3px rgba(212,98,26,.1); background: var(--white); }
111
+ input::placeholder { color: var(--muted2); }
112
+
113
+ /* ── Tabs ────────────────────────────────────────────────── */
114
+ .tabs {
115
+ display: flex; gap: 2px;
116
+ background: var(--surface);
117
+ border-radius: 10px; padding: 3px;
118
+ margin-bottom: 14px;
119
+ }
120
+ .tab {
121
+ flex: 1; padding: 8px; text-align: center;
122
+ font-size: 12px; font-weight: 600; color: var(--muted);
123
+ border-radius: 8px; cursor: pointer;
124
+ transition: background .15s, color .15s; user-select: none;
125
+ }
126
+ .tab.active { background: var(--white); color: var(--ink); box-shadow: 0 1px 4px rgba(0,0,0,.08); }
127
+
128
+ #pastePane, #uploadPane { display: none; }
129
+ #pastePane.shown, #uploadPane.shown { display: block; }
130
+
131
+ textarea {
132
+ width: 100%;
133
+ background: var(--surface); border: 1px solid var(--border);
134
+ border-radius: 10px; color: var(--ink);
135
+ font-family: var(--font-body); font-size: 13px; line-height: 1.7;
136
+ padding: 14px; min-height: 210px; resize: none; outline: none;
137
+ transition: border-color .15s, box-shadow .15s;
138
+ }
139
+ textarea:focus { border-color: var(--accent); box-shadow: 0 0 0 3px rgba(212,98,26,.1); background: var(--white); }
140
+ textarea::placeholder { color: var(--muted2); }
141
+
142
+ /* ── Upload ──────────────────────────────────────────────── */
143
+ .upload-zone {
144
+ border: 1.5px dashed var(--border2); border-radius: 10px;
145
+ padding: 36px 20px; text-align: center; cursor: pointer;
146
+ transition: border-color .2s, background .2s; background: var(--surface);
147
+ }
148
+ .upload-zone:hover, .upload-zone.drag { border-color: var(--accent); background: var(--accent-bg); }
149
+ .upload-zone .icon { font-size: 26px; margin-bottom: 10px; }
150
+ .upload-zone p { font-size: 13px; color: var(--muted); line-height: 1.6; }
151
+ .upload-zone p strong { color: var(--ink2); }
152
+ .upload-zone .formats { font-family: var(--font-mono); font-size: 10px; color: var(--muted2); margin-top: 8px; letter-spacing: .06em; }
153
+ .file-chosen {
154
+ display: none; align-items: center; gap: 10px;
155
+ padding: 10px 14px; background: var(--green-bg);
156
+ border: 1px solid #b6dfca; border-radius: 8px; margin-top: 10px;
157
+ font-size: 12px; color: var(--green); font-weight: 500;
158
+ }
159
+ .file-chosen.show { display: flex; }
160
+ .file-chosen .fname { flex: 1; font-family: var(--font-mono); font-size: 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
161
+ .file-clear { cursor: pointer; font-size: 15px; color: var(--muted); flex-shrink: 0; }
162
+ input[type="file"] { display: none; }
163
+
164
+ /* ── Buttons ─────────────────────────────────────────────── */
165
+ .panel-footer { padding: 16px 24px; border-top: 1px solid var(--border); background: var(--white); }
166
+ .btn-run {
167
+ width: 100%; background: var(--accent); color: #fff; border: none;
168
+ border-radius: 10px; padding: 13px; font-family: var(--font-body);
169
+ font-size: 14px; font-weight: 600; cursor: pointer;
170
+ display: flex; align-items: center; justify-content: center; gap: 8px;
171
+ transition: background .15s, box-shadow .15s, transform .1s;
172
+ }
173
+ .btn-run:hover:not(:disabled) { background: var(--accent2); box-shadow: 0 4px 16px rgba(212,98,26,.28); }
174
+ .btn-run:active:not(:disabled) { transform: scale(.98); }
175
+ .btn-run:disabled { opacity: .45; cursor: not-allowed; }
176
+
177
+ .btn-pdf {
178
+ width: 100%; margin-top: 8px; background: transparent;
179
+ color: var(--green); border: 1.5px solid #b6dfca;
180
+ border-radius: 10px; padding: 10px; font-family: var(--font-body);
181
+ font-size: 13px; font-weight: 600; cursor: pointer;
182
+ display: flex; align-items: center; justify-content: center; gap: 7px;
183
+ transition: background .15s;
184
+ }
185
+ .btn-pdf:hover:not(:disabled) { background: var(--green-bg); }
186
+ .btn-pdf:disabled { opacity: .35; cursor: not-allowed; }
187
+
188
+ /* ── Right Panel ─────────────────────────────────────────── */
189
+ .panel-right { display: flex; flex-direction: column; overflow: hidden; background: var(--bg); }
190
+
191
+ .status-strip {
192
+ display: flex; align-items: center; gap: 10px;
193
+ padding: 0 28px; height: 42px;
194
+ border-bottom: 1px solid var(--border); background: var(--white); flex-shrink: 0;
195
+ }
196
+ .status-pill { display: flex; align-items: center; gap: 6px; font-family: var(--font-mono); font-size: 11px; color: var(--muted); }
197
+ .status-pill .s-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--border2); }
198
+ .status-pill.running .s-dot { background: var(--accent); animation: pulse .8s infinite; }
199
+ .status-pill.done .s-dot { background: var(--green); }
200
+ .status-pill.error .s-dot { background: #c53030; }
201
+ @keyframes pulse { 0%,100%{opacity:1} 50%{opacity:.3} }
202
+
203
+ .pipe-track { margin-left: auto; display: flex; align-items: center; gap: 4px; }
204
+ .p-node {
205
+ font-family: var(--font-mono); font-size: 10px; color: var(--muted2);
206
+ padding: 3px 8px; border-radius: 4px;
207
+ background: var(--surface); border: 1px solid var(--border);
208
+ transition: all .2s;
209
+ }
210
+ .p-node.active { color: var(--accent); border-color: var(--accent); background: var(--accent-bg); }
211
+ .p-node.done { color: var(--green); border-color: #b6dfca; background: var(--green-bg); }
212
+ .p-sep { color: var(--border2); font-size: 10px; }
213
+
214
+ .output-scroll { flex: 1; overflow-y: auto; padding: 28px 32px; }
215
+ .output-scroll::-webkit-scrollbar { width: 4px; }
216
+ .output-scroll::-webkit-scrollbar-thumb { background: var(--border2); border-radius: 4px; }
217
+
218
+ /* ── Empty state ─────────────────────────────────────────── */
219
+ .empty {
220
+ display: flex; flex-direction: column; align-items: center;
221
+ justify-content: center; height: 100%; text-align: center;
222
+ color: var(--muted2); gap: 12px; padding-bottom: 60px;
223
+ }
224
+ .empty-icon {
225
+ width: 52px; height: 52px; border-radius: 14px;
226
+ background: var(--white); border: 1px solid var(--border);
227
+ display: flex; align-items: center; justify-content: center; font-size: 22px;
228
+ }
229
+ .empty h3 { font-family: var(--font-head); font-size: 20px; font-weight: 500; color: var(--ink2); font-style: italic; }
230
+ .empty p { font-size: 13px; max-width: 280px; line-height: 1.6; }
231
+
232
+ /* ── Agent blocks ────────────────────────────────────────── */
233
+ .agent-block {
234
+ background: var(--white); border: 1px solid var(--border);
235
+ border-radius: 12px; margin-bottom: 16px; overflow: hidden;
236
+ opacity: 0; transform: translateY(10px);
237
+ transition: opacity .35s, transform .35s;
238
+ }
239
+ .agent-block.in { opacity: 1; transform: translateY(0); }
240
+
241
+ .agent-head {
242
+ display: flex; align-items: center; gap: 10px;
243
+ padding: 12px 18px; border-bottom: 1px solid var(--border);
244
+ }
245
+ .agent-num {
246
+ width: 22px; height: 22px; border-radius: 6px;
247
+ display: flex; align-items: center; justify-content: center;
248
+ font-family: var(--font-mono); font-size: 11px; font-weight: 500; flex-shrink: 0;
249
+ }
250
+ .agent-name { font-size: 12px; font-weight: 600; letter-spacing: .02em; flex: 1; }
251
+ .agent-spinner {
252
+ width: 14px; height: 14px; border: 1.5px solid currentColor;
253
+ border-top-color: transparent; border-radius: 50%;
254
+ animation: spin .7s linear infinite; opacity: .6;
255
+ }
256
+ @keyframes spin { to { transform: rotate(360deg); } }
257
+ .agent-check { font-size: 14px; }
258
+
259
+ .ag-1 .agent-head { background: #fdf8f5; }
260
+ .ag-1 .agent-num { background: #fde8d8; color: #c45518; }
261
+ .ag-1 .agent-name { color: #c45518; }
262
+ .ag-1 .agent-spinner, .ag-1 .agent-check { color: #c45518; }
263
+
264
+ .ag-2 .agent-head { background: #f5fbf7; }
265
+ .ag-2 .agent-num { background: #d6f0e2; color: #2d7a4f; }
266
+ .ag-2 .agent-name { color: #2d7a4f; }
267
+ .ag-2 .agent-spinner, .ag-2 .agent-check { color: #2d7a4f; }
268
+
269
+ .ag-3 .agent-head { background: #f6f5fd; }
270
+ .ag-3 .agent-num { background: #e0ddfb; color: #5b4fcf; }
271
+ .ag-3 .agent-name { color: #5b4fcf; }
272
+ .ag-3 .agent-spinner, .ag-3 .agent-check { color: #5b4fcf; }
273
+
274
+ .ag-4 .agent-head { background: #fdf9f2; }
275
+ .ag-4 .agent-num { background: #fdedc8; color: #b07c10; }
276
+ .ag-4 .agent-name { color: #b07c10; }
277
+ .ag-4 .agent-spinner, .ag-4 .agent-check { color: #b07c10; }
278
+
279
+ .ag-5 .agent-head { background: #fdf5f5; }
280
+ .ag-5 .agent-num { background: #fdd8d8; color: #c53030; }
281
+ .ag-5 .agent-name { color: #c53030; }
282
+ .ag-5 .agent-spinner, .ag-5 .agent-check { color: #c53030; }
283
+
284
+ .agent-body { padding: 18px 20px; font-size: 13.5px; line-height: 1.78; color: var(--ink2); }
285
+ .agent-body h2 {
286
+ font-family: var(--font-head); font-size: 16px; font-weight: 500;
287
+ font-style: italic; color: var(--ink); margin: 14px 0 6px;
288
+ padding-bottom: 6px; border-bottom: 1px solid var(--border);
289
+ }
290
+ .agent-body h2:first-child { margin-top: 0; }
291
+ .agent-body h3 { font-size: 13px; font-weight: 600; color: var(--ink); margin: 10px 0 4px; }
292
+ .agent-body strong { font-weight: 600; color: var(--ink); }
293
+ .agent-body ul, .agent-body ol { padding-left: 18px; margin: 4px 0 8px; }
294
+ .agent-body li { margin-bottom: 3px; }
295
+
296
+ /* ── Toast ───────────────────────────────────────────────── */
297
+ .toast {
298
+ position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%);
299
+ background: var(--ink); color: #fff; padding: 10px 20px;
300
+ border-radius: 8px; font-size: 13px; z-index: 100;
301
+ display: none; white-space: nowrap; box-shadow: 0 4px 16px rgba(0,0,0,.18);
302
+ }
303
+ .toast.err { background: #c53030; }
304
+
305
+ @media (max-width: 800px) {
306
+ .app { grid-template-columns: 1fr; grid-template-rows: 56px auto 1fr; height: auto; }
307
+ .panel-left { border-right: none; border-bottom: 1px solid var(--border); }
308
+ .panel-right { min-height: 60vh; }
309
+ .pipe-track { display: none; }
310
+ .output-scroll { padding: 20px; }
311
+ }
312
+ </style>
313
+ </head>
314
+ <body>
315
+ <div class="app">
316
+
317
+ <header class="topbar">
318
+ <div class="topbar-logo"><span class="dot"></span>Problem Solver</div>
319
+ <div class="topbar-meta">5-agent pipeline</div>
320
+ </header>
321
+
322
+ <!-- LEFT -->
323
+ <aside class="panel-left">
324
+ <div class="panel-inner">
325
+
326
+ <div class="section-label">Your details</div>
327
+ <div class="fields-row">
328
+ <div class="field">
329
+ <label>Name</label>
330
+ <input type="text" id="internName" placeholder="Your name" />
331
+ </div>
332
+ <div class="field">
333
+ <label>Role</label>
334
+ <input type="text" id="internRole" value="AI Developer Intern" />
335
+ </div>
336
+ </div>
337
+
338
+ <div class="section-label">Problem input</div>
339
+ <div class="tabs">
340
+ <div class="tab active" id="tabPaste" onclick="switchTab('paste')">Paste Text</div>
341
+ <div class="tab" id="tabUpload" onclick="switchTab('upload')">Upload File</div>
342
+ </div>
343
+
344
+ <div id="pastePane" class="shown">
345
+ <textarea id="pasteText" placeholder="Paste your meeting transcript, problem description, or blocker here…" rows="10"></textarea>
346
+ </div>
347
+
348
+ <div id="uploadPane">
349
+ <div class="upload-zone" id="dropZone"
350
+ onclick="document.getElementById('fileInput').click()"
351
+ ondragover="onDrag(event,true)"
352
+ ondragleave="onDrag(event,false)"
353
+ ondrop="onDrop(event)">
354
+ <div class="icon">📄</div>
355
+ <p><strong>Click to upload</strong> or drag & drop</p>
356
+ <div class="formats">PDF · TXT · MD</div>
357
+ </div>
358
+ <div class="file-chosen" id="fileChosen">
359
+ <span>📎</span>
360
+ <span class="fname" id="fileName">—</span>
361
+ <span class="file-clear" onclick="clearFile()">✕</span>
362
+ </div>
363
+ <input type="file" id="fileInput" accept=".pdf,.txt,.md" onchange="onFileSelect(event)" />
364
+ </div>
365
+
366
+ </div>
367
+
368
+ <div class="panel-footer">
369
+ <button class="btn-run" id="btnRun" onclick="runAnalysis()">
370
+ <svg width="14" height="14" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2.5"><path d="M5 3l14 9-14 9V3z"/></svg>
371
+ Analyze Problem
372
+ </button>
373
+ <button class="btn-pdf" id="btnPdf" disabled onclick="downloadPDF()">
374
+ <svg width="13" height="13" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path d="M12 15V3m0 12l-4-4m4 4l4-4M3 17v2a2 2 0 002 2h14a2 2 0 002-2v-2"/></svg>
375
+ Download PDF Report
376
+ </button>
377
+ </div>
378
+ </aside>
379
+
380
+ <!-- RIGHT -->
381
+ <main class="panel-right">
382
+ <div class="status-strip">
383
+ <div class="status-pill" id="statusPill">
384
+ <span class="s-dot"></span>
385
+ <span id="statusText">Ready</span>
386
+ </div>
387
+ <div class="pipe-track">
388
+ <div class="p-node" id="pn-analyst">Analyst</div>
389
+ <div class="p-sep">›</div>
390
+ <div class="p-node" id="pn-root_cause">Root Cause</div>
391
+ <div class="p-sep">›</div>
392
+ <div class="p-node" id="pn-solutions">Solutions</div>
393
+ <div class="p-sep">›</div>
394
+ <div class="p-node" id="pn-action_plan">Action Plan</div>
395
+ <div class="p-sep">›</div>
396
+ <div class="p-node" id="pn-thinking">Coach</div>
397
+ </div>
398
+ </div>
399
+
400
+ <div class="output-scroll" id="outputScroll">
401
+ <div class="empty" id="emptyState">
402
+ <div class="empty-icon">✦</div>
403
+ <h3>Start with a problem.</h3>
404
+ <p>Paste a transcript, meeting notes, or blocker — five agents will analyze it and hand you a plan.</p>
405
+ </div>
406
+ </div>
407
+ </main>
408
+ </div>
409
+
410
+ <div class="toast" id="toast"></div>
411
+
412
+ <script>
413
+ // ── Config — update this to your HF Space URL ─────────────
414
+ const API_URL = 'http://localhost:7860';
415
+
416
+ const AGENTS = [
417
+ { key: 'analyst', label: 'Problem Analyst', cls: 'ag-1', num: '1' },
418
+ { key: 'root_cause', label: 'Root Cause Analyst', cls: 'ag-2', num: '2' },
419
+ { key: 'solutions', label: 'Solution Brainstorm', cls: 'ag-3', num: '3' },
420
+ { key: 'action_plan', label: 'Action Planner', cls: 'ag-4', num: '4' },
421
+ { key: 'thinking', label: 'Thinking Coach', cls: 'ag-5', num: '5' },
422
+ ];
423
+
424
+ let running = false, selectedFile = null, lastPayload = null, activeTab = 'paste';
425
+
426
+ function switchTab(tab) {
427
+ activeTab = tab;
428
+ document.getElementById('tabPaste').classList.toggle('active', tab === 'paste');
429
+ document.getElementById('tabUpload').classList.toggle('active', tab === 'upload');
430
+ document.getElementById('pastePane').classList.toggle('shown', tab === 'paste');
431
+ document.getElementById('uploadPane').classList.toggle('shown', tab === 'upload');
432
+ }
433
+
434
+ function onDrag(e, over) {
435
+ e.preventDefault();
436
+ document.getElementById('dropZone').classList.toggle('drag', over);
437
+ }
438
+ function onDrop(e) {
439
+ e.preventDefault();
440
+ document.getElementById('dropZone').classList.remove('drag');
441
+ const f = e.dataTransfer.files[0];
442
+ if (f) setFile(f);
443
+ }
444
+ function onFileSelect(e) { const f = e.target.files[0]; if (f) setFile(f); }
445
+ function setFile(f) {
446
+ selectedFile = f;
447
+ document.getElementById('fileName').textContent = f.name;
448
+ document.getElementById('fileChosen').classList.add('show');
449
+ }
450
+ function clearFile() {
451
+ selectedFile = null;
452
+ document.getElementById('fileName').textContent = '—';
453
+ document.getElementById('fileChosen').classList.remove('show');
454
+ document.getElementById('fileInput').value = '';
455
+ }
456
+
457
+ async function readFile(file) {
458
+ if (file.name.endsWith('.pdf')) {
459
+ return new Promise((res, rej) => {
460
+ const r = new FileReader();
461
+ r.onload = () => res('__PDF_BASE64__' + r.result.split(',')[1]);
462
+ r.onerror = rej;
463
+ r.readAsDataURL(file);
464
+ });
465
+ }
466
+ return new Promise((res, rej) => {
467
+ const r = new FileReader();
468
+ r.onload = () => res(r.result);
469
+ r.onerror = rej;
470
+ r.readAsText(file);
471
+ });
472
+ }
473
+
474
+ function toast(msg, isErr = false) {
475
+ const t = document.getElementById('toast');
476
+ t.textContent = msg;
477
+ t.className = 'toast' + (isErr ? ' err' : '');
478
+ t.style.display = 'block';
479
+ setTimeout(() => t.style.display = 'none', 4000);
480
+ }
481
+ function setStatus(text, state = '') {
482
+ document.getElementById('statusText').textContent = text;
483
+ document.getElementById('statusPill').className = 'status-pill ' + state;
484
+ }
485
+ function setPipe(key, state) {
486
+ const el = document.getElementById('pn-' + key);
487
+ if (el) el.className = 'p-node ' + state;
488
+ }
489
+ function resetPipe() { AGENTS.forEach(a => setPipe(a.key, '')); }
490
+
491
+ function renderMd(text) {
492
+ return text
493
+ .replace(/^## (.+)$/gm, '<h2>$1</h2>')
494
+ .replace(/^### (.+)$/gm, '<h3>$1</h3>')
495
+ .replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>')
496
+ .replace(/^[-*] (.+)$/gm, '<li>$1</li>')
497
+ .replace(/(<li>.*<\/li>\n?)+/g, s => `<ul>${s}</ul>`)
498
+ .replace(/\n/g, '<br>');
499
+ }
500
+
501
+ async function runAnalysis() {
502
+ if (running) return;
503
+
504
+ const name = document.getElementById('internName').value.trim() || 'Intern';
505
+ const role = document.getElementById('internRole').value.trim() || 'AI Developer Intern';
506
+ let content = '';
507
+
508
+ if (activeTab === 'paste') {
509
+ content = document.getElementById('pasteText').value.trim();
510
+ if (!content) { toast('Paste a problem or transcript first.', true); return; }
511
+ } else {
512
+ if (!selectedFile) { toast('Select a file first.', true); return; }
513
+ try { content = await readFile(selectedFile); }
514
+ catch { toast('Could not read file.', true); return; }
515
+ }
516
+
517
+ running = true;
518
+ lastPayload = { content, intern_name: name, intern_role: role };
519
+ document.getElementById('btnRun').disabled = true;
520
+ document.getElementById('btnPdf').disabled = true;
521
+ resetPipe();
522
+
523
+ const scroll = document.getElementById('outputScroll');
524
+ scroll.innerHTML = '';
525
+ setStatus('Starting pipeline…', 'running');
526
+
527
+ AGENTS.forEach(a => {
528
+ const div = document.createElement('div');
529
+ div.className = `agent-block ${a.cls}`;
530
+ div.id = `ab-${a.key}`;
531
+ div.innerHTML = `
532
+ <div class="agent-head">
533
+ <div class="agent-num">${a.num}</div>
534
+ <div class="agent-name">${a.label}</div>
535
+ <div class="agent-spinner" id="spin-${a.key}"></div>
536
+ </div>
537
+ <div class="agent-body" id="body-${a.key}"></div>`;
538
+ scroll.appendChild(div);
539
+ });
540
+
541
+ try {
542
+ const res = await fetch(`${API_URL}/analyze/stream`, {
543
+ method: 'POST',
544
+ headers: { 'Content-Type': 'application/json' },
545
+ body: JSON.stringify(lastPayload),
546
+ });
547
+ if (!res.ok) {
548
+ const e = await res.json().catch(() => ({ detail: res.statusText }));
549
+ throw new Error(e.detail || 'Server error');
550
+ }
551
+
552
+ const reader = res.body.getReader();
553
+ const dec = new TextDecoder();
554
+ let buf = '', current = null;
555
+
556
+ while (true) {
557
+ const { done, value } = await reader.read();
558
+ if (done) break;
559
+ buf += dec.decode(value, { stream: true });
560
+ const lines = buf.split('\n');
561
+ buf = lines.pop();
562
+
563
+ for (const line of lines) {
564
+ if (!line.startsWith('data: ')) continue;
565
+ try {
566
+ const msg = JSON.parse(line.slice(6));
567
+ if (msg.event === 'agent_start') {
568
+ current = msg.agent;
569
+ setPipe(current, 'active');
570
+ const block = document.getElementById(`ab-${current}`);
571
+ block.classList.add('in');
572
+ setStatus(`Running: ${msg.label}…`, 'running');
573
+ block.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
574
+ } else if (msg.event === 'token' && msg.agent === current) {
575
+ const body = document.getElementById(`body-${msg.agent}`);
576
+ if (body) {
577
+ body.dataset.raw = (body.dataset.raw || '') + msg.text;
578
+ body.innerHTML = renderMd(body.dataset.raw);
579
+ }
580
+ } else if (msg.event === 'agent_done') {
581
+ const spin = document.getElementById(`spin-${msg.agent}`);
582
+ if (spin) spin.outerHTML = `<span class="agent-check">✓</span>`;
583
+ setPipe(msg.agent, 'done');
584
+ } else if (msg.event === 'done') {
585
+ setStatus('Analysis complete.', 'done');
586
+ document.getElementById('btnPdf').disabled = false;
587
+ }
588
+ } catch {}
589
+ }
590
+ }
591
+ } catch (err) {
592
+ setStatus('Error — ' + err.message, 'error');
593
+ toast(err.message, true);
594
+ }
595
+
596
+ running = false;
597
+ document.getElementById('btnRun').disabled = false;
598
+ }
599
+
600
+ async function downloadPDF() {
601
+ if (!lastPayload) return;
602
+ const btn = document.getElementById('btnPdf');
603
+ btn.textContent = 'Generating…';
604
+ btn.disabled = true;
605
+ try {
606
+ const res = await fetch(`${API_URL}/analyze/pdf`, {
607
+ method: 'POST',
608
+ headers: { 'Content-Type': 'application/json' },
609
+ body: JSON.stringify(lastPayload),
610
+ });
611
+ if (!res.ok) throw new Error('PDF generation failed');
612
+ const blob = await res.blob();
613
+ const a = document.createElement('a');
614
+ a.href = URL.createObjectURL(blob);
615
+ a.download = `analysis_${Date.now()}.pdf`;
616
+ a.click();
617
+ } catch (e) { toast(e.message, true); }
618
+ btn.innerHTML = `<svg width="13" height="13" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path d="M12 15V3m0 12l-4-4m4 4l4-4M3 17v2a2 2 0 002 2h14a2 2 0 002-2v-2"/></svg> Download PDF Report`;
619
+ btn.disabled = false;
620
+ }
621
+ </script>
622
+ </body>
623
+ </html>