SolarumAsteridion commited on
Commit
4898051
·
verified ·
1 Parent(s): 1e9ce14

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +101 -172
index.html CHANGED
@@ -3,151 +3,112 @@
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Nebula Exam Countdown</title>
7
  <link rel="preconnect" href="https://fonts.googleapis.com">
8
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
9
- <link href="https://fonts.googleapis.com/css2?family=Outfit:wght@200;400;600&display=swap" rel="stylesheet">
10
 
11
  <style>
12
- @import url('https://fonts.googleapis.com/css2?family=Outfit:wght@200;600&display=swap');
13
 
14
  * { margin: 0; padding: 0; box-sizing: border-box; }
15
 
16
  body {
17
- background: #020012;
18
  color: #fff;
19
- font-family: 'Outfit', sans-serif;
20
  min-height: 100vh;
21
- overflow-x: hidden;
22
  }
23
 
24
- /* Nebula Background Effects */
25
- .nebula-bg {
26
- position: fixed;
27
- top: 0; left: 0; width: 100%; height: 100%;
28
- z-index: -1;
29
- overflow: hidden;
30
- }
31
- .bg-glow {
32
- position: absolute;
33
- width: 600px; height: 600px;
34
- background: radial-gradient(circle, rgba(100,50,255,0.2) 0%, rgba(0,212,255,0) 70%);
35
- filter: blur(60px);
36
- animation: pulse 12s infinite alternate;
37
- }
38
- .bg-glow:nth-child(2) { top: -200px; right: -100px; background: radial-gradient(circle, rgba(0,212,255,0.15) 0%, rgba(0,212,255,0) 70%); animation-delay: -4s; }
39
- .bg-glow:nth-child(3) { bottom: -200px; left: -100px; background: radial-gradient(circle, rgba(255,50,150,0.1) 0%, rgba(0,212,255,0) 70%); animation-delay: -8s; }
40
-
41
- @keyframes pulse { 0% { transform: scale(1) translate(0, 0); opacity: 0.5; } 100% { transform: scale(1.3) translate(50px, 50px); opacity: 0.8; } }
42
 
43
- .container { width: 100%; max-width: 1200px; margin: 0 auto; padding: 4rem 2rem; position: relative; z-index: 1; }
 
44
 
45
- header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 4rem; }
46
- h1 { font-weight: 200; letter-spacing: 0.3em; text-transform: uppercase; font-size: 1.5rem; color: #00d4ff; }
47
-
48
- /* Add Button */
49
- .add-trigger {
50
- background: rgba(255, 255, 255, 0.05); border: 1px solid rgba(255, 255, 255, 0.1);
51
- color: white; padding: 12px 24px; border-radius: 50px; cursor: pointer; backdrop-filter: blur(10px);
52
- transition: all 0.3s ease; font-family: 'Outfit'; font-size: 0.9rem; letter-spacing: 0.1em;
53
  }
54
- .add-trigger:hover { background: rgba(0, 212, 255, 0.2); border-color: #00d4ff; transform: translateY(-3px); }
55
 
56
  /* Grid */
57
- .exams-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(380px, 1fr)); gap: 3rem; }
58
-
59
- /* Nebula Card */
60
- .glass-card {
61
- background: rgba(255, 255, 255, 0.02);
62
- backdrop-filter: blur(20px);
63
- border: 1px solid rgba(255, 255, 255, 0.08);
64
- border-radius: 40px;
65
- padding: 40px;
66
- position: relative;
67
- box-shadow: 0 8px 32px 0 rgba(0,0,0,0.4);
68
- transition: transform 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275);
69
- text-align: center;
70
  cursor: pointer;
71
  }
72
- .glass-card:hover { transform: translateY(-10px) rotateX(5deg); background: rgba(255, 255, 255, 0.05); border-color: rgba(0,212,255,0.3); }
73
-
74
- .subject { font-size: 0.8rem; letter-spacing: 0.4em; color: #00d4ff; font-weight: 200; margin-bottom: 15px; text-transform: uppercase; }
75
- .counter {
76
- font-size: 6rem; font-weight: 600; line-height: 1;
77
- background: linear-gradient(180deg, #fff 30%, rgba(255,255,255,0.2) 100%);
78
- -webkit-background-clip: text; -webkit-text-fill-color: transparent;
79
- filter: drop-shadow(0 0 20px rgba(0,212,255,0.2));
80
- }
81
- .sub-text { font-size: 1rem; opacity: 0.5; margin-bottom: 25px; font-weight: 200; letter-spacing: 0.2em; }
82
- .footer-date { font-size: 0.75rem; letter-spacing: 0.1em; color: rgba(255,255,255,0.3); }
83
 
84
- /* Delete Button */
85
- .delete-btn {
86
- position: absolute; top: 20px; right: 25px; background: none; border: none; color: rgba(255,255,255,0.2);
87
- cursor: pointer; font-size: 1.2rem; transition: color 0.3s; z-index: 5;
88
  }
89
- .delete-btn:hover { color: #ff4b2b; }
90
 
91
- /* Modal Styling */
92
- .modal { display: none; position: fixed; inset: 0; background: rgba(0,0,0,0.8); backdrop-filter: blur(15px); z-index: 100; align-items: center; justify-content: center; padding: 20px; opacity: 0; transition: opacity 0.3s ease; }
93
- .modal.active { display: flex; opacity: 1; }
94
- .modal-content { background: #0a0a1a; border: 1px solid rgba(0,212,255,0.2); padding: 40px; border-radius: 30px; width: 100%; max-width: 500px; box-shadow: 0 0 50px rgba(0,212,255,0.1); }
95
 
96
- input, textarea { width: 100%; background: rgba(255,255,255,0.05); border: 1px solid rgba(255,255,255,0.1); padding: 15px; border-radius: 12px; color: white; font-family: 'Outfit'; margin-top: 10px; margin-bottom: 20px; outline: none; }
97
- input:focus { border-color: #00d4ff; }
98
- label { font-size: 0.8rem; color: #00d4ff; letter-spacing: 0.1em; }
99
 
100
- .save-btn { width: 100%; padding: 15px; border-radius: 12px; border: none; background: #00d4ff; color: #020012; font-weight: 600; cursor: pointer; transition: 0.3s; text-transform: uppercase; letter-spacing: 0.1em; }
101
- .save-btn:hover { background: #fff; transform: scale(1.02); }
102
 
103
- .empty-state { text-align: center; padding: 100px; opacity: 0.5; font-weight: 200; letter-spacing: 0.2em; }
 
 
104
 
105
- @media (max-width: 600px) {
 
 
 
 
 
 
 
 
 
 
106
  .exams-grid { grid-template-columns: 1fr; }
107
- .counter { font-size: 4.5rem; }
108
  }
109
  </style>
110
  </head>
111
  <body>
112
- <div class="nebula-bg">
113
- <div class="bg-glow"></div>
114
- <div class="bg-glow"></div>
115
- <div class="bg-glow"></div>
116
- </div>
117
-
118
  <div class="container">
119
  <header>
120
- <h1>Exams</h1>
121
- <button class="add-trigger" id="openModalBtn">+ ADD EXAM</button>
122
  </header>
123
-
124
  <div id="examsGrid" class="exams-grid"></div>
125
- <div id="emptyState" class="empty-state">NO EXAMS SCHEDULED</div>
126
  </div>
127
 
128
- <!-- Modals (Add & Syllabus) same structure as original but with new CSS -->
129
- <div class="modal" id="modal">
130
- <div class="modal-content">
131
- <h2 style="font-weight: 200; margin-bottom: 20px; letter-spacing: 2px;">NEW SCHEDULE</h2>
132
- <form id="addExamForm">
133
- <label>EXAM NAME</label>
134
- <input type="text" id="examName" required placeholder="e.g. Physics Midterm">
135
- <label>DATE</label>
136
- <input type="date" id="examDate" required>
137
- <button type="submit" class="save-btn">Initialize</button>
138
  </form>
139
  </div>
140
  </div>
141
 
142
- <div class="modal" id="syllabusModal">
143
- <div class="modal-content" style="max-width: 700px;">
144
- <h2 id="syllabusExamName" style="font-weight: 200; color: #00d4ff; letter-spacing: 2px;"></h2>
145
- <p id="syllabusExamDate" style="font-size: 0.8rem; opacity: 0.5; margin-bottom: 20px;"></p>
146
- <form id="syllabusForm">
147
- <textarea id="syllabusContent" rows="10" placeholder="Enter study topics..."></textarea>
148
- <input type="hidden" id="syllabusExamId">
149
- <button type="submit" class="save-btn">Update Syllabus</button>
150
- <div id="savedIndicator" style="display:none; color: #00d4ff; text-align: center; margin-top: 10px; font-size: 0.8rem;">Saved successfully</div>
151
  </form>
152
  </div>
153
  </div>
@@ -169,83 +130,51 @@
169
  const app = initializeApp(firebaseConfig);
170
  const database = getDatabase(app);
171
  const examsRef = ref(database, 'exams');
172
- let examsData = [];
173
-
174
- const elements = {
175
- modal: document.getElementById('modal'),
176
- openModalBtn: document.getElementById('openModalBtn'),
177
- addExamForm: document.getElementById('addExamForm'),
178
- examsGrid: document.getElementById('examsGrid'),
179
- emptyState: document.getElementById('emptyState'),
180
- syllabusModal: document.getElementById('syllabusModal'),
181
- syllabusForm: document.getElementById('syllabusForm'),
182
- syllabusContent: document.getElementById('syllabusContent'),
183
- syllabusExamId: document.getElementById('syllabusExamId'),
184
- syllabusExamName: document.getElementById('syllabusExamName'),
185
- syllabusExamDate: document.getElementById('syllabusExamDate'),
186
- savedIndicator: document.getElementById('savedIndicator')
187
- };
188
-
189
- const calculateCountdown = (examDate) => {
190
- const now = new Date(); now.setHours(0,0,0,0);
191
- const target = new Date(examDate); target.setHours(0,0,0,0);
192
- const diff = target.getTime() - now.getTime();
193
- const days = Math.ceil(diff / (1000 * 60 * 60 * 24));
194
- return days < 0 ? { days: '✔', label: 'COMPLETE' } : { days, label: 'DAYS REMAINING' };
195
- };
196
-
197
- onValue(examsRef, (snapshot) => {
198
- const data = snapshot.val();
199
- examsData = data ? Object.entries(data).map(([id, val]) => ({ id, ...val })) : [];
200
- renderExams();
201
- });
202
-
203
- function renderExams() {
204
- elements.emptyState.style.display = examsData.length ? 'none' : 'block';
205
- elements.examsGrid.innerHTML = examsData.sort((a,b) => a.date - b.date).map(exam => {
206
- const count = calculateCountdown(exam.date);
207
- const dateStr = new Date(exam.date).toLocaleDateString('en-US', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' });
208
  return `
209
- <div class="glass-card" onclick="openSyllabus('${exam.id}')">
210
- <button class="delete-btn" onclick="event.stopPropagation(); deleteExam('${exam.id}')"></button>
211
- <div class="subject">${exam.name}</div>
212
- <div class="counter">${count.days}</div>
213
- <div class="sub-text">${count.label}</div>
214
- <div class="footer-date">${dateStr}</div>
215
  </div>`;
216
  }).join('');
217
- }
218
-
219
- window.openSyllabus = (id) => {
220
- const exam = examsData.find(e => e.id === id);
221
- elements.syllabusExamName.textContent = exam.name;
222
- elements.syllabusExamDate.textContent = new Date(exam.date).toDateString();
223
- elements.syllabusContent.value = exam.syllabus || '';
224
- elements.syllabusExamId.value = id;
225
- elements.syllabusModal.classList.add('active');
226
- };
227
-
228
- window.deleteExam = (id) => { if(confirm('Remove this exam?')) remove(ref(database, `exams/${id}`)); };
229
 
230
- elements.openModalBtn.onclick = () => elements.modal.classList.add('active');
231
- window.onclick = (e) => { if(e.target.classList.contains('modal')) { e.target.classList.remove('active'); elements.savedIndicator.style.display='none'; }};
 
 
 
 
 
 
232
 
233
- elements.addExamForm.onsubmit = (e) => {
 
 
 
234
  e.preventDefault();
235
- push(examsRef, {
236
- name: document.getElementById('examName').value,
237
- date: new Date(document.getElementById('examDate').value).getTime(),
238
- syllabus: ''
239
- });
240
- elements.modal.classList.remove('active');
241
- elements.addExamForm.reset();
242
  };
243
 
244
- elements.syllabusForm.onsubmit = (e) => {
245
  e.preventDefault();
246
- update(ref(database, `exams/${elements.syllabusExamId.value}`), { syllabus: elements.syllabusContent.value });
247
- elements.savedIndicator.style.display = 'block';
248
- setTimeout(() => elements.syllabusModal.classList.remove('active'), 1000);
249
  };
250
  </script>
251
  </body>
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Industrial Exam Tracker</title>
7
  <link rel="preconnect" href="https://fonts.googleapis.com">
8
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
9
+ <link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;700&display=swap" rel="stylesheet">
10
 
11
  <style>
12
+ :root { --metal: #1a1a1c; --brass: #c5a059; --etch: #4a4a4f; }
13
 
14
  * { margin: 0; padding: 0; box-sizing: border-box; }
15
 
16
  body {
17
+ background: #0a0a0b;
18
  color: #fff;
19
+ font-family: 'Space Grotesk', sans-serif;
20
  min-height: 100vh;
21
+ padding: 40px;
22
  }
23
 
24
+ .container { max-width: 1200px; margin: 0 auto; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
 
26
+ header { border-bottom: 2px solid var(--etch); padding-bottom: 20px; margin-bottom: 50px; display: flex; justify-content: space-between; align-items: center; }
27
+ h1 { font-weight: 300; letter-spacing: 0.3em; text-transform: uppercase; color: var(--brass); }
28
 
29
+ .add-btn {
30
+ background: none; border: 1px solid var(--brass); color: var(--brass);
31
+ padding: 10px 25px; cursor: pointer; font-family: inherit; font-size: 0.8rem;
32
+ transition: 0.3s;
 
 
 
 
33
  }
34
+ .add-btn:hover { background: var(--brass); color: #000; }
35
 
36
  /* Grid */
37
+ .exams-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(420px, 1fr)); gap: 40px; }
38
+
39
+ /* Industrial Card */
40
+ .brushed-plate {
41
+ position: relative; padding: 40px;
42
+ background: linear-gradient(135deg, #222, #111);
43
+ border: 2px solid var(--etch);
44
+ box-shadow: 15px 15px 40px #000, inset 1px 1px 0px rgba(255,255,255,0.05);
45
+ border-radius: 4px;
46
+ transition: 0.3s;
 
 
 
47
  cursor: pointer;
48
  }
49
+ .brushed-plate:hover { transform: scale(1.02); border-color: var(--brass); }
 
 
 
 
 
 
 
 
 
 
50
 
51
+ .rotating-bezel {
52
+ position: absolute; top: -8px; left: -8px; right: -8px; bottom: -8px;
53
+ border: 1px dashed var(--brass); border-radius: 8px; opacity: 0.15;
54
+ animation: rotate 20s linear infinite; pointer-events: none;
55
  }
56
+ @keyframes rotate { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
57
 
58
+ .card-header { font-weight: 300; letter-spacing: 0.2em; text-transform: uppercase; border-bottom: 1px solid var(--etch); padding-bottom: 15px; color: var(--brass); font-size: 0.9rem; }
 
 
 
59
 
60
+ .digit-flipper { font-size: 8rem; font-weight: 700; line-height: 0.8; margin: 30px 0; color: #fff; text-shadow: 0 0 20px rgba(255,255,255,0.1); }
61
+ .digit-flipper small { display: block; font-size: 0.9rem; letter-spacing: 0.4em; margin-top: 15px; opacity: 0.4; }
 
62
 
63
+ footer { font-family: monospace; opacity: 0.3; letter-spacing: 1px; font-size: 0.8rem; margin-top: 20px; text-transform: uppercase; }
 
64
 
65
+ /* Delete */
66
+ .del { position: absolute; top: 15px; right: 15px; color: var(--etch); background: none; border: none; cursor: pointer; font-size: 1.2rem; }
67
+ .del:hover { color: #ff4b2b; }
68
 
69
+ /* Modal */
70
+ .modal { display: none; position: fixed; inset: 0; background: rgba(0,0,0,0.9); z-index: 100; align-items: center; justify-content: center; }
71
+ .modal.active { display: flex; }
72
+ .modal-box { background: #1a1a1c; border: 2px solid var(--etch); padding: 40px; width: 100%; max-width: 500px; position: relative; }
73
+
74
+ input, textarea { width: 100%; background: #000; border: 1px solid var(--etch); padding: 15px; color: #fff; font-family: inherit; margin: 15px 0; outline: none; }
75
+ input:focus { border-color: var(--brass); }
76
+
77
+ .action-btn { background: var(--brass); color: #000; border: none; padding: 15px; width: 100%; font-weight: 700; cursor: pointer; text-transform: uppercase; }
78
+
79
+ @media (max-width: 500px) {
80
  .exams-grid { grid-template-columns: 1fr; }
81
+ .digit-flipper { font-size: 6rem; }
82
  }
83
  </style>
84
  </head>
85
  <body>
 
 
 
 
 
 
86
  <div class="container">
87
  <header>
88
+ <h1>SYSTEM.EXAMS</h1>
89
+ <button class="add-btn" id="openBtn">INSTANTIATE NEW</button>
90
  </header>
 
91
  <div id="examsGrid" class="exams-grid"></div>
 
92
  </div>
93
 
94
+ <div class="modal" id="addModal">
95
+ <div class="modal-box">
96
+ <h2 style="color: var(--brass); letter-spacing: 3px;">ADD_ENTRY</h2>
97
+ <form id="addForm">
98
+ <input type="text" id="nameIn" placeholder="IDENTIFIER" required>
99
+ <input type="date" id="dateIn" required>
100
+ <button type="submit" class="action-btn">COMMIT</button>
 
 
 
101
  </form>
102
  </div>
103
  </div>
104
 
105
+ <div class="modal" id="syllModal">
106
+ <div class="modal-box" style="max-width: 700px;">
107
+ <h2 id="syllTitle" style="color: var(--brass);"></h2>
108
+ <form id="syllForm">
109
+ <textarea id="syllArea" rows="12" placeholder="TOPICS_LIST..."></textarea>
110
+ <input type="hidden" id="syllId">
111
+ <button type="submit" class="action-btn">SAVE_DATA</button>
 
 
112
  </form>
113
  </div>
114
  </div>
 
130
  const app = initializeApp(firebaseConfig);
131
  const database = getDatabase(app);
132
  const examsRef = ref(database, 'exams');
133
+ let dataStore = [];
134
+
135
+ onValue(examsRef, (s) => {
136
+ const d = s.val();
137
+ dataStore = d ? Object.entries(d).map(([id, v]) => ({ id, ...v })) : [];
138
+ const grid = document.getElementById('examsGrid');
139
+ grid.innerHTML = dataStore.sort((a,b)=>a.date-b.date).map(e => {
140
+ const now = new Date(); now.setHours(0,0,0,0);
141
+ const target = new Date(e.date); target.setHours(0,0,0,0);
142
+ const diff = Math.ceil((target - now) / 86400000);
143
+ const val = diff < 0 ? 'OK' : diff;
144
+ const label = diff < 0 ? 'COMPLETED' : 'DAYS LEFT';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
145
  return `
146
+ <div class="brushed-plate" onclick="showSyll('${e.id}')">
147
+ <div class="rotating-bezel"></div>
148
+ <button class="del" onclick="event.stopPropagation(); window.delEx('${e.id}')">×</button>
149
+ <div class="card-header">${e.name}</div>
150
+ <div class="digit-flipper">${val}<small>${label}</small></div>
151
+ <footer>${new Date(e.date).toDateString()}</footer>
152
  </div>`;
153
  }).join('');
154
+ });
 
 
 
 
 
 
 
 
 
 
 
155
 
156
+ window.delEx = (id) => remove(ref(database, `exams/${id}`));
157
+ window.showSyll = (id) => {
158
+ const e = dataStore.find(x=>x.id===id);
159
+ document.getElementById('syllTitle').innerText = e.name;
160
+ document.getElementById('syllArea').value = e.syllabus || '';
161
+ document.getElementById('syllId').value = id;
162
+ document.getElementById('syllModal').classList.add('active');
163
+ };
164
 
165
+ document.getElementById('openBtn').onclick = () => document.getElementById('addModal').classList.add('active');
166
+ window.onclick = (e) => { if(e.target.classList.contains('modal')) e.target.classList.remove('active'); };
167
+
168
+ document.getElementById('addForm').onsubmit = (e) => {
169
  e.preventDefault();
170
+ push(examsRef, { name: document.getElementById('nameIn').value, date: new Date(document.getElementById('dateIn').value).getTime(), syllabus:'' });
171
+ document.getElementById('addModal').classList.remove('active');
 
 
 
 
 
172
  };
173
 
174
+ document.getElementById('syllForm').onsubmit = (e) => {
175
  e.preventDefault();
176
+ update(ref(database, `exams/${document.getElementById('syllId').value}`), { syllabus: document.getElementById('syllArea').value });
177
+ document.getElementById('syllModal').classList.remove('active');
 
178
  };
179
  </script>
180
  </body>