tamhonvotri commited on
Commit
2b17e0f
·
unverified ·
1 Parent(s): 58c8101

Upload apps/cong-thuc/src/App.svelte with huggingface_hub

Browse files
Files changed (1) hide show
  1. apps/cong-thuc/src/App.svelte +118 -0
apps/cong-thuc/src/App.svelte CHANGED
@@ -32,6 +32,18 @@
32
  let startPanX = 0;
33
  let startPanY = 0;
34
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  const latexTemplates = [
36
  { cat: 'Cơ bản', name: 'Phân số', code: '$$ \\frac{a}{b} $$', icon: 'a/b' },
37
  { cat: 'Cơ bản', name: 'Căn bậc n', code: '$$ \\sqrt[n]{x} $$', icon: 'ⁿ√x' },
@@ -151,8 +163,38 @@ $ A = mat(1, 2; 3, 4) $
151
  onMount(() => {
152
  codeInput = defaultLatex;
153
  renderContent();
 
 
 
 
154
  });
155
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
156
  function setMode(newMode: 'latex' | 'typst') {
157
  if (mode === newMode) return;
158
  mode = newMode;
@@ -418,6 +460,8 @@ $ A = mat(1, 2; 3, 4) $
418
  <div class="w-px h-4 bg-zinc-600 mx-1"></div>
419
  <button class="w-8 h-8 flex items-center justify-center rounded text-zinc-400 hover:text-white hover:bg-zinc-700 transition-colors font-sans font-bold" on:click={() => insertText('\n## Tiêu đề\n')} title="Tiêu đề (Heading)">H</button>
420
  <button class="w-8 h-8 flex items-center justify-center rounded text-zinc-400 hover:text-white hover:bg-zinc-700 transition-colors" on:click={() => insertText('\n- Danh sách\n')} title="Danh sách (List)">•</button>
 
 
421
  </div>
422
 
423
  <div class="flex gap-3">
@@ -515,6 +559,80 @@ $ A = mat(1, 2; 3, 4) $
515
 
516
  </div>
517
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
518
  <style>
519
  .custom-scrollbar::-webkit-scrollbar {
520
  width: 8px;
 
32
  let startPanX = 0;
33
  let startPanY = 0;
34
 
35
+ // Saved Formulas State
36
+ interface SavedFormula {
37
+ id: string;
38
+ name: string;
39
+ code: string;
40
+ mode: 'latex' | 'typst';
41
+ timestamp: number;
42
+ }
43
+ let savedFormulas: SavedFormula[] = [];
44
+ let isManagerOpen = false;
45
+ let newFormulaName = '';
46
+
47
  const latexTemplates = [
48
  { cat: 'Cơ bản', name: 'Phân số', code: '$$ \\frac{a}{b} $$', icon: 'a/b' },
49
  { cat: 'Cơ bản', name: 'Căn bậc n', code: '$$ \\sqrt[n]{x} $$', icon: 'ⁿ√x' },
 
163
  onMount(() => {
164
  codeInput = defaultLatex;
165
  renderContent();
166
+ const saved = localStorage.getItem('linhhuong-saved-formulas');
167
+ if (saved) {
168
+ try { savedFormulas = JSON.parse(saved); } catch (e) {}
169
+ }
170
  });
171
 
172
+ function saveCurrentFormula() {
173
+ if (!newFormulaName.trim() || !codeInput.trim()) return;
174
+ const newFormula: SavedFormula = {
175
+ id: crypto.randomUUID(),
176
+ name: newFormulaName.trim(),
177
+ code: codeInput,
178
+ mode: mode,
179
+ timestamp: Date.now()
180
+ };
181
+ savedFormulas = [newFormula, ...savedFormulas];
182
+ localStorage.setItem('linhhuong-saved-formulas', JSON.stringify(savedFormulas));
183
+ newFormulaName = '';
184
+ }
185
+
186
+ function deleteFormula(id: string) {
187
+ savedFormulas = savedFormulas.filter(f => f.id !== id);
188
+ localStorage.setItem('linhhuong-saved-formulas', JSON.stringify(savedFormulas));
189
+ }
190
+
191
+ function loadFormula(formula: SavedFormula) {
192
+ setMode(formula.mode);
193
+ codeInput = formula.code;
194
+ renderContent();
195
+ isManagerOpen = false;
196
+ }
197
+
198
  function setMode(newMode: 'latex' | 'typst') {
199
  if (mode === newMode) return;
200
  mode = newMode;
 
460
  <div class="w-px h-4 bg-zinc-600 mx-1"></div>
461
  <button class="w-8 h-8 flex items-center justify-center rounded text-zinc-400 hover:text-white hover:bg-zinc-700 transition-colors font-sans font-bold" on:click={() => insertText('\n## Tiêu đề\n')} title="Tiêu đề (Heading)">H</button>
462
  <button class="w-8 h-8 flex items-center justify-center rounded text-zinc-400 hover:text-white hover:bg-zinc-700 transition-colors" on:click={() => insertText('\n- Danh sách\n')} title="Danh sách (List)">•</button>
463
+ <div class="w-px h-4 bg-zinc-600 mx-1"></div>
464
+ <button class="w-8 h-8 flex items-center justify-center rounded text-amber-400 hover:text-amber-300 hover:bg-zinc-700 transition-colors" on:click={() => isManagerOpen = true} title="Quản lý Thư viện Công thức">📚</button>
465
  </div>
466
 
467
  <div class="flex gap-3">
 
559
 
560
  </div>
561
 
562
+ <!-- Manager Popup -->
563
+ {#if isManagerOpen}
564
+ <div class="fixed inset-0 z-[100] flex items-center justify-center bg-black/60 backdrop-blur-sm p-8">
565
+ <div class="bg-[#1e1e1e] w-full max-w-4xl h-[80vh] rounded-2xl shadow-2xl flex flex-col overflow-hidden border border-zinc-700">
566
+
567
+ <div class="h-16 border-b border-zinc-700 flex items-center px-6 justify-between bg-zinc-800/50 shrink-0">
568
+ <h2 class="text-lg font-bold text-white flex items-center gap-2"><span>📚</span> Thư viện Công thức</h2>
569
+ <button class="w-8 h-8 flex items-center justify-center rounded-full hover:bg-white/10 text-zinc-400 hover:text-white transition-colors" on:click={() => isManagerOpen = false}>✕</button>
570
+ </div>
571
+
572
+ <div class="flex-1 flex overflow-hidden">
573
+ <div class="w-1/3 border-r border-zinc-700 p-6 flex flex-col bg-zinc-900/30">
574
+ <h3 class="text-sm font-bold text-zinc-300 mb-4 uppercase tracking-wider">Lưu công thức hiện tại</h3>
575
+ <input
576
+ type="text"
577
+ bind:value={newFormulaName}
578
+ placeholder="Nhập tên công thức..."
579
+ class="w-full bg-zinc-800 border border-zinc-700 rounded-lg px-4 py-2.5 text-sm text-white placeholder:text-zinc-500 focus:outline-none focus:border-indigo-500 transition-colors mb-4"
580
+ on:keydown={(e) => e.key === 'Enter' && saveCurrentFormula()}
581
+ />
582
+ <button
583
+ class="w-full py-2.5 bg-indigo-600 hover:bg-indigo-500 text-white font-bold rounded-lg shadow-lg transition-colors flex justify-center items-center gap-2 disabled:opacity-50"
584
+ on:click={saveCurrentFormula}
585
+ disabled={!newFormulaName.trim() || !codeInput.trim()}
586
+ >
587
+ <span>💾</span> Lưu vào Thư viện
588
+ </button>
589
+
590
+ <div class="mt-8">
591
+ <h3 class="text-sm font-bold text-zinc-300 mb-2 uppercase tracking-wider">Thống kê</h3>
592
+ <div class="flex gap-4 text-xs text-zinc-500">
593
+ <div class="bg-zinc-800 px-3 py-2 rounded border border-zinc-700">LaTeX: {savedFormulas.filter(f => f.mode === 'latex').length}</div>
594
+ <div class="bg-zinc-800 px-3 py-2 rounded border border-zinc-700">Typst: {savedFormulas.filter(f => f.mode === 'typst').length}</div>
595
+ </div>
596
+ </div>
597
+ </div>
598
+
599
+ <div class="w-2/3 p-6 overflow-y-auto custom-scrollbar bg-[#1e1e1e]">
600
+ <h3 class="text-sm font-bold text-zinc-300 mb-4 uppercase tracking-wider">Thư viện của tôi ({savedFormulas.length})</h3>
601
+ {#if savedFormulas.length === 0}
602
+ <div class="flex flex-col items-center justify-center h-48 text-zinc-500 border-2 border-dashed border-zinc-700 rounded-xl">
603
+ <span class="text-3xl mb-2">📭</span>
604
+ <p>Chưa có công thức nào được lưu.</p>
605
+ </div>
606
+ {:else}
607
+ <div class="grid grid-cols-2 gap-4">
608
+ {#each savedFormulas as formula}
609
+ <div class="bg-zinc-800/80 border border-zinc-700 hover:border-indigo-500/50 rounded-xl p-4 flex flex-col group transition-all">
610
+ <div class="flex items-center justify-between mb-2">
611
+ <div class="flex items-center gap-2 overflow-hidden">
612
+ <span class="px-1.5 py-0.5 rounded text-[10px] font-bold uppercase {formula.mode === 'latex' ? 'bg-blue-500/20 text-blue-400' : 'bg-emerald-500/20 text-emerald-400'}">
613
+ {formula.mode}
614
+ </span>
615
+ <h4 class="font-bold text-sm text-zinc-200 truncate" title={formula.name}>{formula.name}</h4>
616
+ </div>
617
+ <button class="text-zinc-500 hover:text-rose-400 opacity-0 group-hover:opacity-100 transition-opacity shrink-0" title="Xóa" on:click={() => deleteFormula(formula.id)}>🗑️</button>
618
+ </div>
619
+ <div class="flex-1 bg-zinc-900 rounded p-2 mb-3 overflow-hidden relative h-20">
620
+ <pre class="text-[10px] text-zinc-400 font-mono whitespace-pre-wrap">{formula.code}</pre>
621
+ <div class="absolute bottom-0 left-0 w-full h-8 bg-gradient-to-t from-zinc-900 to-transparent"></div>
622
+ </div>
623
+ <button class="w-full py-1.5 bg-zinc-700 hover:bg-indigo-600 text-xs font-bold text-white rounded transition-colors" on:click={() => loadFormula(formula)}>
624
+ Mở trong Editor
625
+ </button>
626
+ </div>
627
+ {/each}
628
+ </div>
629
+ {/if}
630
+ </div>
631
+ </div>
632
+ </div>
633
+ </div>
634
+ {/if}
635
+
636
  <style>
637
  .custom-scrollbar::-webkit-scrollbar {
638
  width: 8px;