Repository navigation
Expand file tree
/
Copy pathindex.html
More file actions
286 lines (262 loc) · 16.7 KB
/
Copy pathindex.html
File metadata and controls
286 lines (262 loc) · 16.7 KB
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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
<!doctype html>
<html lang="en" class="h-full dark">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>iCalShareHub - Open Calendar Directory</title>
<!-- Apply saved/default dark theme immediately to prevent flashing -->
<script>
if (localStorage.getItem("theme") === "light") {
document.documentElement.classList.remove("dark");
} else {
document.documentElement.classList.add("dark");
}
</script>
<!-- Tailwind CSS -->
<script src="https://cdn.tailwindcss.com"></script>
<!-- Google Fonts & FontAwesome -->
<link
href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;500;600&display=swap"
rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/js/all.min.js"></script>
<script>
tailwind.config = {
darkMode: "class",
theme: {
extend: {
fontFamily: {
sans: ["Inter", "sans-serif"],
mono: ["JetBrains Mono", "monospace"],
},
},
},
};
</script>
</head>
<body
class="h-full font-sans text-slate-800 dark:text-slate-100 bg-slate-50 dark:bg-slate-950 flex flex-col antialiased selection:bg-blue-500 selection:text-white transition-colors duration-200">
<!-- Top Navigation Header -->
<header
class="sticky top-0 z-30 bg-white/95 dark:bg-slate-900/95 backdrop-blur-md border-b border-slate-200 dark:border-slate-800 shadow-sm">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex justify-between items-center h-16">
<!-- Logo & Brand -->
<div class="flex items-center gap-3 cursor-pointer" id="brandLogo">
<div
class="w-10 h-10 rounded-xl bg-gradient-to-tr from-blue-600 to-indigo-600 flex items-center justify-center text-white shadow-md shadow-blue-500/20">
<i class="fa-solid fa-calendar-days text-xl"></i>
</div>
<div class="flex items-center gap-2">
<span
class="text-xl font-extrabold tracking-tight text-slate-900 dark:text-white">iCalShare<span
class="text-blue-600 dark:text-blue-400">Hub</span></span>
<span
class="hidden sm:inline-block px-2 py-0.5 text-[10px] font-semibold bg-blue-100 dark:bg-blue-900/40 text-blue-700 dark:text-blue-300 rounded-full tracking-wider uppercase">Git-Powered</span>
</div>
</div>
<!-- Action Buttons & Dark Mode Toggle -->
<div class="flex items-center gap-2 sm:gap-3">
<!-- Dark Mode Toggle Button -->
<button id="themeToggleBtn" aria-label="Toggle Theme"
class="p-2 rounded-xl text-slate-600 dark:text-slate-300 bg-slate-100 dark:bg-slate-800 hover:bg-slate-200 dark:hover:bg-slate-700 transition-colors">
<i id="themeToggleIcon" class="fa-solid fa-sun text-amber-400"></i>
</button>
<button id="openSubmitModalBtn"
class="hidden sm:inline-flex items-center gap-2 px-4 py-2 text-xs font-bold text-white bg-blue-600 hover:bg-blue-700 rounded-lg shadow-sm shadow-blue-500/30 transition-all hover:scale-[1.02]">
<i class="fa-solid fa-plus"></i>
<span>Submit Calendar</span>
</button>
<button id="openSubmitModalBtnMobile"
class="sm:hidden p-2 rounded-xl text-white bg-blue-600 hover:bg-blue-700 shadow-sm shadow-blue-500/30 transition-colors">
<i class="fa-solid fa-plus"></i>
</button>
</div>
</div>
</div>
</header>
<!-- Main App Container -->
<main class="flex-1 max-w-7xl w-full mx-auto px-4 sm:px-6 lg:px-8 py-8 flex flex-col gap-6">
<!-- Hero Banner -->
<div
class="relative bg-gradient-to-r from-slate-900 via-slate-800 to-slate-900 text-white rounded-3xl p-6 sm:p-10 shadow-xl overflow-hidden border border-slate-800">
<div class="absolute -right-10 -bottom-10 opacity-10 text-white pointer-events-none">
<i class="fa-solid fa-calendar-alt text-[280px]"></i>
</div>
<div class="relative z-10 max-w-2xl">
<span
class="inline-block px-3 py-1 bg-blue-500/20 border border-blue-400/30 text-blue-300 text-xs font-semibold rounded-full mb-3">Community-Driven
Directory</span>
<h1 class="text-3xl sm:text-4xl font-extrabold tracking-tight mb-3">Find and share curated <span
class="text-blue-400">.ics calendars</span>.</h1>
<p class="text-slate-300 text-sm sm:text-base mb-6 leading-relaxed">Subscribe to holidays, sports
schedules, movie release dates, and academic terms. Submit your own `.ics` file directly via GitHub
Issues—no backend server needed!</p>
<!-- Search Bar -->
<div class="relative">
<i class="fa-solid fa-magnifying-glass absolute left-4 top-1/2 -translate-y-1/2 text-slate-400"></i>
<input type="text" id="searchInput"
placeholder="Search calendars by keyword, team, or tag (e.g. NBA, Tech, Holidays)..."
class="w-full pl-11 pr-4 py-3 bg-white/10 backdrop-blur-md border border-white/20 rounded-xl text-white placeholder-slate-400 text-sm focus:outline-none focus:ring-2 focus:ring-blue-400 transition-all" />
</div>
</div>
</div>
<!-- Filter Controls Bar -->
<div class="flex flex-col sm:flex-row gap-4 justify-between items-start sm:items-center">
<!-- Category Filter Pills -->
<div class="flex items-center gap-2 overflow-x-auto w-full sm:w-auto pb-2 sm:pb-0" id="categoryList">
<select id="categoryFilter"
class="bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-800 rounded-xl px-3.5 py-2 text-xs font-semibold text-slate-700 dark:text-slate-200 focus:outline-none focus:ring-2 focus:ring-blue-500 shadow-sm cursor-pointer">
<option value="ALL">All Categories</option>
<option value="Tech">Tech</option>
<option value="Holidays">Holidays</option>
<option value="Sports">Sports</option>
<option value="TV & Movies">TV & Movies</option>
<option value="Gaming">Gaming</option>
<option value="Music">Music</option>
<option value="Finance">Finance</option>
<option value="Education">Education</option>
<option value="Health & Fitness">Health & Fitness</option>
<option value="Entertainment">Entertainment</option>
<option value="Science">Science</option>
<option value="Community">Community</option>
<option value="Other">Other</option>
</select>
</div>
<!-- Additional Utility Buttons -->
<div class="flex items-center gap-2 shrink-0 self-end sm:self-auto">
<label for="icsFileInput"
class="cursor-pointer inline-flex items-center gap-1.5 px-3 py-2 text-xs font-semibold text-slate-700 dark:text-slate-200 bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-800 hover:bg-slate-50 dark:hover:bg-slate-800 rounded-xl shadow-sm transition-colors">
<i class="fa-solid fa-file-arrow-up text-blue-600 dark:text-blue-400"></i>
<span>Test Local .ics File</span>
</label>
<input type="file" id="icsFileInput" accept=".ics,text/calendar" class="hidden" />
<button id="resetDataBtn"
class="inline-flex items-center gap-1.5 px-3 py-2 text-xs font-medium text-slate-500 dark:text-slate-400 hover:text-slate-800 dark:hover:text-slate-200 transition-colors">
<i class="fa-solid fa-rotate-right"></i>
<span>Reset Sample Data</span>
</button>
</div>
</div>
<!-- Results Header -->
<div class="flex justify-between items-center text-xs text-slate-500 dark:text-slate-400 font-medium pt-2">
<span id="resultsCount">Loading calendars...</span>
<span id="activeCategoryBadge"
class="bg-slate-200/60 dark:bg-slate-800 px-2.5 py-1 rounded-md text-slate-700 dark:text-slate-300 font-mono">Category:
ALL</span>
</div>
<!-- Cards Grid -->
<div id="calendarGrid" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
<!-- Dynamically populated cards via app.js -->
</div>
<!-- Empty Search State -->
<div id="emptyState"
class="hidden text-center py-16 bg-white dark:bg-slate-900 rounded-2xl border border-slate-200 dark:border-slate-800 shadow-sm">
<i class="fa-regular fa-calendar-xmark text-4xl text-slate-400 dark:text-slate-600 mb-3"></i>
<h3 class="text-base font-bold text-slate-800 dark:text-slate-200">No calendars found</h3>
<p class="text-xs text-slate-500 dark:text-slate-400 mt-1">Try adjusting your search criteria or category
filter.</p>
</div>
</main>
<!-- Preview & Subscribe Modal -->
<div id="previewModal"
class="fixed inset-0 bg-slate-900/60 backdrop-blur-sm z-50 hidden flex items-center justify-center p-4">
<div
class="bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-800 rounded-2xl max-w-lg w-full p-6 shadow-2xl relative max-h-[85vh] flex flex-col">
<div class="flex justify-between items-start mb-4">
<div>
<span id="modalCategory"
class="text-[10px] font-bold text-blue-700 dark:text-blue-300 bg-blue-100 dark:bg-blue-900/40 px-2.5 py-0.5 rounded-full uppercase tracking-wider">Category</span>
<h3 id="previewTitle" class="text-xl font-bold text-slate-900 dark:text-white mt-1.5">Calendar Title
</h3>
</div>
<button id="closePreviewModalBtn"
class="text-slate-400 hover:text-slate-600 dark:hover:text-slate-200 text-lg">
<i class="fa-solid fa-xmark"></i>
</button>
</div>
<p id="previewDesc" class="text-xs text-slate-600 dark:text-slate-300 mb-4 leading-relaxed"></p>
<div class="text-xs font-bold text-slate-400 dark:text-slate-500 uppercase tracking-wider mb-2">Upcoming
Events</div>
<div id="previewEvents"
class="flex-1 overflow-y-auto space-y-2 bg-slate-50 dark:bg-slate-950 border border-slate-200 dark:border-slate-800 p-3 rounded-xl mb-6 text-xs">
<!-- Dynamically populated events -->
</div>
<div class="flex gap-3">
<a id="downloadIcsBtn" href="#" download
class="flex-1 text-center py-2.5 bg-slate-900 dark:bg-slate-100 hover:bg-slate-800 dark:hover:bg-white text-white dark:text-slate-900 font-bold text-xs rounded-xl transition-all shadow-sm flex items-center justify-center gap-1.5">
<i class="fa-solid fa-download"></i>
<span>Download .ics</span>
</a>
<button id="copyWebcalBtn"
class="flex-1 py-2.5 bg-blue-600 hover:bg-blue-700 text-white font-bold text-xs rounded-xl transition-all shadow-sm flex items-center justify-center gap-1.5">
<i class="fa-solid fa-link"></i>
<span>Copy Webcal URL</span>
</button>
</div>
</div>
</div>
<!-- Submit Calendar Modal -->
<div id="submitModal"
class="fixed inset-0 bg-slate-900/60 backdrop-blur-sm z-50 hidden flex items-center justify-center p-4">
<div
class="bg-white dark:bg-slate-900 border border-slate-200 dark:border-slate-800 rounded-2xl max-w-lg w-full p-6 shadow-2xl relative">
<div class="flex justify-between items-center mb-4">
<h3 class="text-lg font-bold text-slate-900 dark:text-white">Submit New Calendar</h3>
<button id="closeSubmitModalBtn"
class="text-slate-400 hover:text-slate-600 dark:hover:text-slate-200 text-lg">
<i class="fa-solid fa-xmark"></i>
</button>
</div>
<p class="text-xs text-slate-500 dark:text-slate-400 mb-4 leading-relaxed">Submitting creates a pre-filled
GitHub issue. Automated GitHub Actions process and publish valid calendars automatically.</p>
<form id="submissionForm" class="space-y-3">
<div>
<label for="subTitle"
class="block text-[11px] font-bold uppercase text-slate-500 dark:text-slate-400 mb-1">Calendar
Title</label>
<input type="text" id="subTitle" required placeholder="e.g. Formula 1 2026 Season"
class="w-full bg-slate-50 dark:bg-slate-950 border border-slate-200 dark:border-slate-800 rounded-lg p-2.5 text-xs text-slate-900 dark:text-white focus:outline-none focus:ring-2 focus:ring-blue-500" />
</div>
<div>
<label for="subCategory"
class="block text-[11px] font-bold uppercase text-slate-500 dark:text-slate-400 mb-1">Category</label>
<select id="subCategory" required
class="w-full bg-slate-50 dark:bg-slate-950 border border-slate-200 dark:border-slate-800 rounded-lg p-2.5 text-xs text-slate-900 dark:text-white focus:outline-none focus:ring-2 focus:ring-blue-500">
<option value="Tech">Tech</option>
<option value="Holidays">Holidays</option>
<option value="Sports">Sports</option>
<option value="TV & Movies">TV & Movies</option>
<option value="Gaming">Gaming</option>
<option value="Music">Music</option>
<option value="Finance">Finance</option>
<option value="Education">Education</option>
<option value="Health & Fitness">Health & Fitness</option>
<option value="Entertainment">Entertainment</option>
<option value="Science">Science</option>
<option value="Community">Community</option>
<option value="Other">Other</option>
</select>
</div>
<div>
<label for="subDesc"
class="block text-[11px] font-bold uppercase text-slate-500 dark:text-slate-400 mb-1">Description</label>
<textarea id="subDesc" rows="2" required placeholder="Provide a short summary..."
class="w-full bg-slate-50 dark:bg-slate-950 border border-slate-200 dark:border-slate-800 rounded-lg p-2.5 text-xs text-slate-900 dark:text-white focus:outline-none focus:ring-2 focus:ring-blue-500"></textarea>
</div>
<div>
<label for="subIcsFile"
class="block text-[11px] font-bold uppercase text-slate-500 dark:text-slate-400 mb-1">Upload
.ICS File</label>
<input type="file" id="subIcsFile" accept=".ics,text/calendar" required
class="w-full bg-slate-50 dark:bg-slate-950 border border-slate-200 dark:border-slate-800 rounded-lg p-2.5 text-xs text-slate-900 dark:text-white file:mr-3 file:py-1 file:px-3 file:rounded-md file:border-0 file:text-xs file:font-semibold file:bg-blue-600 file:text-white hover:file:bg-blue-700 cursor-pointer focus:outline-none focus:ring-2 focus:ring-blue-500" />
</div>
<button type="submit"
class="w-full py-3 bg-blue-600 hover:bg-blue-700 text-white font-bold text-xs rounded-xl shadow-md transition-all mt-2">Submit
via GitHub Issue</button>
</form>
</div>
</div>
<!-- External JS File -->
<script src="app.js"></script>
</body>
</html>