File size: 14,221 Bytes
d0b8e8f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
import gleam/string

fn active_class(page: String, key: String) -> String {
  case page == key || string.starts_with(page, key <> "-") {
    True -> " active"
    False -> ""
  }
}

fn nav_item(page: String, key: String, href: String, icon: String, label: String) -> String {
  "<a class='nav-item" <> active_class(page, key) <> "' href='" <> href <> "'><i class='" <> icon <> "'></i><span>" <> label <> "</span></a>"
}

fn nav_html(page: String) -> String {
  let sidebar = "<sidebar-nav>
    <div class='brand-logo'><i class='fas fa-brain'></i><span>FlashSync</span></div>
    <div class='nav-section'><div class='nav-label'>Core</div>"
  let sidebar = sidebar <> nav_item(page, "hub", "/hub", "fas fa-home", "Dashboard")
  let sidebar = sidebar <> nav_item(page, "flashcards", "/flashcards", "fas fa-cards-blank", "Flashcards")
  let sidebar = sidebar <> nav_item(page, "education", "/education", "fas fa-graduation-cap", "Education Portal")
  let sidebar = sidebar <> "</div>
    <div class='nav-section'><div class='nav-label'>Intelligence</div>"
  let sidebar = sidebar <> nav_item(page, "tutor", "/tutor", "fas fa-robot", "AI Tutor")
  let sidebar = sidebar <> nav_item(page, "ai-solver", "/ai-solver", "fas fa-wand-magic-sparkles", "AI Solver")
  let sidebar = sidebar <> nav_item(page, "study-tools", "/study-tools", "fas fa-toolbox", "Study Tools")
  let sidebar = sidebar <> nav_item(page, "heatmap", "/heatmap", "fas fa-fire", "Heatmap")
  let sidebar = sidebar <> "</div>
    <div class='nav-section'><div class='nav-label'>Analytics</div>"
  let sidebar = sidebar <> nav_item(page, "biometric", "/biometric", "fas fa-heart", "Focus Track")
  let sidebar = sidebar <> nav_item(page, "exam", "/exams", "fas fa-clipboard-list", "Exams")
  let sidebar = sidebar <> nav_item(page, "timetravel", "/timetravel", "fas fa-hourglass-end", "Timeline")
  let sidebar = sidebar <> nav_item(page, "analytics", "/analytics", "fas fa-chart-line", "Analytics")
  let sidebar = sidebar <> "</div>
    <div class='nav-section'><div class='nav-label'>Personalization</div>"
  let sidebar = sidebar <> nav_item(page, "achievements", "/achievements", "fas fa-trophy", "Achievements")
  let sidebar = sidebar <> nav_item(page, "calendar", "/calendar", "fas fa-calendar", "Calendar")
  let sidebar = sidebar <> nav_item(page, "notes", "/notes", "fas fa-sticky-note", "Notes")
  let sidebar = sidebar <> nav_item(page, "vocabulary", "/vocabulary", "fas fa-book", "Vocabulary")
  let sidebar = sidebar <> nav_item(page, "pomodoro", "/pomodoro", "fas fa-clock", "Pomodoro")
  let sidebar = sidebar <> nav_item(page, "formulas", "/formulas", "fas fa-square-root-variable", "Formulas")
  let sidebar = sidebar <> nav_item(page, "profile", "/profile", "fas fa-user", "Profile")
  let sidebar = sidebar <> nav_item(page, "settings", "/settings", "fas fa-sliders", "Settings")
  sidebar <> "</div>
  </sidebar-nav>"
}

fn css_style() -> String {
  ":root { --primary: #00f2ff; --secondary: #bc13fe; --accent: #ff006e; --success: #00ff00; --warning: #ffaa00; --bg-dark: #010103; --bg-darker: #000; --glass: rgba(255,255,255,0.03); --glass-border: rgba(0,242,255,0.1); --page-bg: linear-gradient(135deg, #010103 0%, #0a0a1a 50%, #010103 100%); --text-main: #ffffff; }
    html[data-theme='light'] { --primary:#0065a3; --secondary:#7a2fc7; --accent:#cf2a4f; --success:#0b8f45; --warning:#b86a00; --glass: rgba(0,0,0,0.04); --glass-border: rgba(0,101,163,0.15); --page-bg: linear-gradient(135deg, #f4f8ff 0%, #eef3ff 50%, #f8fbff 100%); --text-main:#111827; }
    * { margin:0; padding:0; box-sizing:border-box; }
    html,body { width:100%; height:100%; background: var(--page-bg); color: var(--text-main); font-family: 'Segoe UI', 'Trebuchet MS', sans-serif; overflow-x: hidden; scroll-behavior: smooth; }
    body { display:flex; gap:0; }
    sidebar-nav { width:280px; background:linear-gradient(180deg,#0a0a0f 0%,#050508 100%); border-right:2px solid rgba(0,242,255,0.1); padding:30px 20px; height:100vh; overflow-y:auto; position:fixed; left:0; top:0; z-index:1000; }
    main-content { flex:1; margin-left:280px; padding:40px; overflow-y:auto; height:100vh; }
    .brand-logo { font-size:1.8rem; font-weight:900; color:var(--primary); margin-bottom:40px; display:flex; align-items:center; gap:12px; }
    .nav-section { margin-bottom:30px; }
    .nav-label { font-size:0.75rem; text-transform:uppercase; color:#666; letter-spacing:2px; margin-bottom:12px; font-weight:700; }
    .nav-item { display:flex; align-items:center; gap:12px; padding:14px 16px; margin:6px 0; border-radius:12px; color:#888; text-decoration:none; cursor:pointer; transition:all 0.3s; border-left:3px solid transparent; }
    .nav-item:hover { background:rgba(0,242,255,0.08); color:var(--primary); border-left-color:var(--primary); }
    .nav-item.active { background:rgba(0,242,255,0.15); color:var(--primary); border-left-color:var(--primary); font-weight:600; }
    h1 { font-size:clamp(2rem, 8vw, 3.5rem); font-weight:900; background:linear-gradient(135deg, #fff 0%, var(--primary) 100%); -webkit-background-clip:text; -webkit-text-fill-color:transparent; background-clip:text; margin-bottom:15px; }
    h2 { font-size:1.8rem; font-weight:800; margin:20px 0 15px; color:var(--primary); }
    h3 { font-size:1.3rem; font-weight:700; margin:15px 0 10px; color:#fff; }
    .subtitle { color:#999; font-size:1.1rem; margin-bottom:30px; }
    .stat-card { background:var(--glass); border:1px solid rgba(0,242,255,0.15); padding:25px; border-radius:16px; transition:all 0.4s; position:relative; }
    .stat-card:hover { border-color:var(--primary); transform:translateY(-4px); box-shadow:0 15px 40px rgba(0,242,255,0.15); }
    .grid-2 { display:grid; grid-template-columns:repeat(auto-fit, minmax(250px, 1fr)); gap:20px; margin:25px 0; }
    .grid-3 { display:grid; grid-template-columns:repeat(auto-fit, minmax(300px, 1fr)); gap:25px; margin:25px 0; }
    .grid-4 { display:grid; grid-template-columns:repeat(auto-fit, minmax(220px, 1fr)); gap:20px; margin:25px 0; }
    .premium-input { width:100%; background:rgba(0,0,0,0.4); border:2px solid rgba(0,242,255,0.2); padding:16px; border-radius:12px; color:#fff; font-size:1rem; transition:all 0.3s; }
    .premium-input:focus { outline:none; border-color:var(--primary); box-shadow:0 0 20px rgba(0,242,255,0.3); }
    .premium-button { background:linear-gradient(135deg, var(--primary) 0%, #0099cc 100%); color:#000; border:none; padding:14px 32px; border-radius:50px; font-weight:700; font-size:1rem; cursor:pointer; transition:all 0.3s; display:inline-flex; align-items:center; gap:8px; }
    .premium-button:hover { transform:translateY(-3px); box-shadow:0 10px 30px rgba(0,242,255,0.4); }
    .accent-button { background:linear-gradient(135deg, var(--secondary) 0%, #9a0099 100%); border:none; padding:14px 32px; border-radius:50px; font-weight:700; font-size:1rem; cursor:pointer; transition:all 0.3s; display:inline-flex; align-items:center; gap:8px; color:#fff; }
    .accent-button:hover { transform:translateY(-3px); box-shadow:0 10px 30px rgba(188,19,254,0.4); }
    .success-button { background:linear-gradient(135deg, var(--success) 0%, #00cc00 100%); border:none; padding:14px 32px; border-radius:50px; font-weight:700; font-size:1rem; cursor:pointer; transition:all 0.3s; display:inline-flex; align-items:center; gap:8px; color:#000; }
    .success-button:hover { transform:translateY(-3px); box-shadow:0 10px 30px rgba(0,255,0,0.4); }
    .feature-box { background:linear-gradient(135deg, rgba(0,242,255,0.05) 0%, rgba(188,19,254,0.05) 100%); border:1px solid rgba(0,242,255,0.2); padding:30px; border-radius:20px; margin:20px 0; }
    .chat-window { background:rgba(0,0,0,0.5); border:1px solid rgba(0,242,255,0.2); border-radius:20px; height:500px; display:flex; flex-direction:column; overflow:hidden; }
    .chat-messages { flex:1; overflow-y:auto; padding:20px; display:flex; flex-direction:column; gap:15px; }
    .message { padding:15px 20px; border-radius:15px; max-width:85%; line-height:1.5; }
    .message.user { background:linear-gradient(135deg, rgba(0,242,255,0.2), rgba(0,242,255,0.1)); border-left:3px solid var(--primary); margin-left:auto; }
    .message.ai { background:linear-gradient(135deg, rgba(188,19,254,0.2), rgba(188,19,254,0.1)); border-left:3px solid var(--secondary); }
    .chat-input { padding:20px; border-top:1px solid rgba(0,242,255,0.1); display:flex; gap:10px; }
    .chat-input input { flex:1; }
    .toast { position:fixed; bottom:30px; right:30px; padding:18px 28px; border-radius:14px; background:rgba(0,0,0,0.9); border:1px solid var(--primary); color:var(--primary); font-weight:600; transform:translateY(100px); opacity:0; transition:all 0.4s; z-index:10000; }
    .toast.show { transform:translateY(0); opacity:1; }
    .toast.success { border-color:var(--success); color:var(--success); }
    .toast.error { border-color:var(--accent); color:var(--accent); }
    .modal-overlay { position:fixed; top:0; left:0; width:100%; height:100%; background:rgba(0,0,0,0.7); z-index:9999; display:flex; align-items:center; justify-content:center; opacity:0; pointer-events:none; transition:opacity 0.3s; }
    .modal-overlay.show { opacity:1; pointer-events:auto; }
    .modal-box { background:linear-gradient(135deg, #0f1a30, #141f38); border:1px solid rgba(0,242,255,0.2); border-radius:24px; padding:40px; max-width:500px; width:90%; max-height:80vh; overflow-y:auto; transform:scale(0.9); transition:transform 0.3s; }
    .modal-overlay.show .modal-box { transform:scale(1); }
    .typing-indicator { display:flex; gap:6px; padding:8px 0; }
    .typing-indicator span { width:10px; height:10px; border-radius:50%; background:var(--secondary); animation:typing 1.4s infinite; }
    .typing-indicator span:nth-child(2) { animation-delay:0.2s; }
    .typing-indicator span:nth-child(3) { animation-delay:0.4s; }
    @keyframes typing { 0%,100% { transform:translateY(0); opacity:0.4; } 50% { transform:translateY(-10px); opacity:1; } }
    .flash-card { background:linear-gradient(135deg, #1c2b4e, #141f38); border:2px solid rgba(0,242,255,0.15); border-radius:20px; padding:40px; margin:20px 0; min-height:250px; display:flex; flex-direction:column; align-items:center; justify-content:center; cursor:pointer; transition:all 0.4s; text-align:center; }
    .flash-card:hover { border-color:var(--primary); }
    .flash-card .back { display:none; }
    .flash-card.flipped .front { display:none; }
    .flash-card.flipped .back { display:block; }
    .tag { display:inline-block; padding:4px 12px; border-radius:20px; font-size:0.75rem; font-weight:600; margin:3px; }
    .tag.primary { background:rgba(0,242,255,0.2); color:var(--primary); }
    .tag.success { background:rgba(0,255,0,0.2); color:var(--success); }
    .tag.warning { background:rgba(255,170,0,0.2); color:var(--warning); }
    .tag.accent { background:rgba(188,19,254,0.2); color:var(--secondary); }
    .study-progress-bar { height:8px; background:rgba(0,0,0,0.4); border-radius:4px; margin:15px 0; overflow:hidden; }
    .study-progress-fill { height:100%; background:linear-gradient(90deg, var(--primary), var(--secondary)); border-radius:4px; transition:width 0.5s; }
    .compact-btn { padding:8px 16px; font-size:0.85rem; border-radius:8px; border:none; cursor:pointer; font-weight:600; transition:all 0.2s; display:inline-flex; align-items:center; gap:6px; }
    .compact-btn:hover { transform:translateY(-2px); }
    .stats-row { display:flex; gap:20px; flex-wrap:wrap; margin:20px 0; }
    .stats-badge { background:rgba(0,242,255,0.08); padding:10px 18px; border-radius:10px; border:1px solid rgba(0,242,255,0.1); font-size:0.9rem; }
    .stats-badge strong { color:var(--primary); }
    .mode-toggle { display:flex; gap:10px; flex-wrap:wrap; }
    .mode-btn,.lang-btn { padding:10px 20px; border-radius:10px; border:1px solid rgba(0,242,255,0.2); background:rgba(0,0,0,0.3); color:#888; cursor:pointer; transition:all 0.3s; font-size:0.9rem; }
    .mode-btn:hover,.lang-btn:hover { border-color:var(--primary); color:var(--primary); }
    .mode-btn.active,.lang-btn.active { background:rgba(0,242,255,0.2); border-color:var(--primary); color:var(--primary); font-weight:600; }
    .language-selector { display:flex; gap:10px; flex-wrap:wrap; margin-top:10px; }
    @media (max-width:900px) { sidebar-nav { width:100px; padding:20px 10px; } main-content { margin-left:100px; padding:25px; } .nav-item span:not(:first-child) { display:none; } }
    .confetti { position:fixed; top:0; left:0; width:100%; height:100%; pointer-events:none; z-index:99999; overflow:hidden; }
    .confetti-piece { position:absolute; width:10px; height:10px; top:-10px; animation:confettiFall 3s ease-in forwards; }
    @keyframes confettiFall { 0% { transform:translateY(0) rotate(0deg); opacity:1; } 100% { transform:translateY(100vh) rotate(720deg); opacity:0; } }
    .exam-timer { font-size:2rem; font-weight:900; color:var(--primary); text-align:center; padding:20px; }
    .exam-timer.warning { color:var(--warning); animation:pulse 1s infinite; }
    .exam-timer.critical { color:var(--accent); animation:pulse 0.5s infinite; }
    @keyframes pulse { 0%,100% { opacity:1; } 50% { opacity:0.5; } }"
}

pub fn build_premium_html(page: String, content: String) -> String {
  let head_start = "<!DOCTYPE html>
<html lang='en'>
<head>
  <meta charset='UTF-8'>
  <meta name='viewport' content='width=device-width, initial-scale=1.0'>
  <title>FlashSync Pro</title>
  <link href='https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css' rel='stylesheet'>
  <style>"
  let style = css_style()
  let head_end = "</style>
</head>
<body>"
  let sidebar = nav_html(page)
  let modal_toast = "
  <div id='toast' class='toast'></div>
  <div id='modalOverlay' class='modal-overlay' onclick='closeModal(event)'>
    <div class='modal-box'><h2 id='modalTitle'></h2><div id='modalBody'></div>
      <button class='premium-button' onclick='closeModal()' style='margin-top:20px;width:100%;'>Close</button>
    </div>
  </div>
  <script src=\"/static/app.js\"></script>
</body>
</html>"
  head_start <> style <> head_end <> sidebar <> "<main-content>" <> content <> "</main-content>" <> modal_toast
}