@titas_mallick/wedding-site-gen 1.0.9 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. package/README.md +70 -184
  2. package/app/api/email-reminders/route.ts +240 -0
  3. package/app/couple/page.tsx +4 -4
  4. package/app/game/page.tsx +298 -0
  5. package/app/guestbook/page.tsx +270 -152
  6. package/app/invitation/[slug]/layout.tsx +4 -2
  7. package/app/invitation/[slug]/page.tsx +303 -84
  8. package/app/invitation/actions.ts +49 -0
  9. package/app/invitation/maker/auth.js +1 -1
  10. package/app/invitation/maker/guestAdder.js +4 -0
  11. package/app/invitation/maker/guestShower.js +39 -8
  12. package/app/invitation/maker/layout.tsx +1 -1
  13. package/app/invitation/maker/page.js +9 -7
  14. package/app/invitation/maker/rsvpViewer.js +90 -8
  15. package/app/layout.tsx +40 -14
  16. package/app/mark-the-dates/page.tsx +8 -2
  17. package/app/page.tsx +7 -1
  18. package/app/providers.tsx +1 -1
  19. package/app/sagun/page.tsx +224 -76
  20. package/app/song-requests/page.tsx +242 -105
  21. package/app/sukanya/page.tsx +9 -13
  22. package/app/titas/page.tsx +8 -24
  23. package/app/travel-guide/page.tsx +361 -120
  24. package/app/updates/maker/page.js +2 -2
  25. package/app/updates/overlay/page.tsx +65 -30
  26. package/app/updates/page.js +3 -3
  27. package/cli.mjs +49 -21
  28. package/components/AdminAuth.tsx +145 -0
  29. package/components/AdminLinks.tsx +120 -0
  30. package/components/ConciergeBot.tsx +104 -44
  31. package/components/CountdownTimer.tsx +37 -15
  32. package/components/Gallery.tsx +1 -1
  33. package/components/LiveVideos.tsx +27 -15
  34. package/components/OurStory.tsx +1 -1
  35. package/components/SchemaMarkup.tsx +74 -0
  36. package/components/certificate.jsx +287 -300
  37. package/components/footer.tsx +2 -0
  38. package/components/hero.tsx +47 -4
  39. package/components/icons.tsx +45 -0
  40. package/components/importantNews.js +168 -168
  41. package/components/navbar.tsx +113 -18
  42. package/components/updates.tsx +36 -26
  43. package/config/firebase-admin.js +14 -17
  44. package/config/firebase.ts +4 -2
  45. package/config/site.ts +10 -2
  46. package/firestore.rules +6 -1
  47. package/next-sitemap.config.js +21 -0
  48. package/package.json +4 -3
  49. package/public/corner1-01.svg +0 -0
  50. package/public/love-birds.png +0 -0
  51. package/public/next.svg +0 -0
  52. package/public/pubqr.png +0 -0
  53. package/public/pw/sample.jpg +0 -0
  54. package/public/qr.png +0 -0
  55. package/public/sample.jpg +0 -0
  56. package/public/vercel.svg +0 -0
  57. package/vercel.json +1 -0
  58. package/.recover +0 -9
  59. package/next-env.d.ts +0 -6
  60. package/public/DCV.gif +0 -0
  61. package/public/DCV2.gif +0 -0
  62. package/public/DCV3.gif +0 -0
  63. package/public/Images/1.jpg +0 -0
  64. package/public/Images/11.jpg +0 -0
  65. package/public/Images/12.jpg +0 -0
  66. package/public/Images/13.jpg +0 -0
  67. package/public/Images/14.jpg +0 -0
  68. package/public/Images/15.jpg +0 -0
  69. package/public/Images/16.jpg +0 -0
  70. package/public/Images/17.jpg +0 -0
  71. package/public/Images/18.jpg +0 -0
  72. package/public/Images/19.jpg +0 -0
  73. package/public/Images/2.jpg +0 -0
  74. package/public/Images/21.jpg +0 -0
  75. package/public/Images/22.jpg +0 -0
  76. package/public/Images/3.jpg +0 -0
  77. package/public/Images/4.jpg +0 -0
  78. package/public/Images/5.jpg +0 -0
  79. package/public/Images/6.jpg +0 -0
  80. package/public/Images/7.jpg +0 -0
  81. package/public/Images/8.jpg +0 -0
  82. package/public/Images/9.jpg +0 -0
  83. package/public/Images/9b.jpg +0 -0
  84. package/public/Images/Patipatra.jpeg +0 -0
  85. package/public/audio (1).mp3 +0 -0
  86. package/public/audio (2).mp3 +0 -0
  87. package/public/bride.jpg +0 -0
  88. package/public/groom.jpg +0 -0
  89. package/public/invite.png +0 -0
  90. package/public/pw/001.jpg +0 -0
  91. package/public/pw/002.jpg +0 -0
  92. package/public/pw/003.jpg +0 -0
  93. package/public/pw/004.jpg +0 -0
  94. package/public/pw/005.jpg +0 -0
  95. package/public/pw/006.jpg +0 -0
  96. package/public/pw/007.jpg +0 -0
  97. package/public/pw/008.jpg +0 -0
  98. package/public/pw/009.jpg +0 -0
  99. package/public/pw/010.jpg +0 -0
  100. package/public/pw/011.jpg +0 -0
  101. package/public/pw/012.jpg +0 -0
  102. package/public/pw/013.jpg +0 -0
  103. package/public/pw/014.jpg +0 -0
  104. package/public/pw/015.jpg +0 -0
  105. package/public/pw/016.jpg +0 -0
  106. package/public/pw/017.jpg +0 -0
  107. package/public/pw/018.jpg +0 -0
  108. package/public/pw/019.jpg +0 -0
  109. package/public/pw/020.jpg +0 -0
  110. package/public/pw/021.jpg +0 -0
  111. package/public/pw/022.jpg +0 -0
  112. package/public/pw/023.jpg +0 -0
  113. package/public/pw/024.jpg +0 -0
  114. package/public/pw/025.jpg +0 -0
  115. package/public/pw/026.jpg +0 -0
  116. package/public/pw/027.jpg +0 -0
  117. package/public/pw/028.jpg +0 -0
  118. package/public/pw/029.jpg +0 -0
  119. package/public/pw/030.jpg +0 -0
  120. package/public/pw/031.jpg +0 -0
  121. package/public/pw/032.jpg +0 -0
  122. package/tsconfig.tsbuildinfo +0 -1
  123. /package/public/Images/{20.jpg → sample.jpg} +0 -0
@@ -2,41 +2,35 @@
2
2
 
3
3
  import { useState, useEffect } from "react";
4
4
  import { motion, AnimatePresence } from "framer-motion";
5
- import {
6
- Card,
7
- CardBody,
8
- Input,
9
- Button,
10
- addToast,
11
- Divider,
5
+ import {
6
+ Card,
7
+ CardBody,
8
+ Input,
9
+ Button,
10
+ addToast,
11
+ Divider,
12
12
  Spinner,
13
- Table,
14
- TableHeader,
15
- TableColumn,
16
- TableBody,
17
- TableRow,
18
- TableCell,
19
13
  Chip,
20
14
  Tooltip,
21
15
  Modal,
22
16
  ModalContent,
23
- ModalHeader,
24
17
  ModalBody,
25
- ModalFooter
18
+ ModalFooter,
26
19
  } from "@heroui/react";
27
- import {
28
- getFirestore,
29
- collection,
30
- addDoc,
31
- serverTimestamp,
32
- onSnapshot,
33
- query,
34
- orderBy,
35
- deleteDoc,
36
- doc,
37
- updateDoc
20
+ import {
21
+ getFirestore,
22
+ collection,
23
+ addDoc,
24
+ serverTimestamp,
25
+ onSnapshot,
26
+ query,
27
+ orderBy,
28
+ deleteDoc,
29
+ doc,
30
+ updateDoc,
38
31
  } from "firebase/firestore";
39
32
  import { getAuth, onAuthStateChanged } from "firebase/auth";
33
+
40
34
  import firebaseApp from "@/config/firebase";
41
35
  import { fontCursive, fontSans, fontMono } from "@/config/fonts";
42
36
  import { HeartFilledIcon } from "@/components/icons";
@@ -45,7 +39,12 @@ const db = getFirestore(firebaseApp());
45
39
  const auth = getAuth(firebaseApp());
46
40
 
47
41
  export default function SongRequestsPage() {
48
- const [formData, setFormData] = useState({ name: "", song: "", artist: "", captcha: "" });
42
+ const [formData, setFormData] = useState({
43
+ name: "",
44
+ song: "",
45
+ artist: "",
46
+ captcha: "",
47
+ });
49
48
  const [loading, setLoading] = useState(false);
50
49
  const [user, setUser] = useState<any>(null);
51
50
  const [requests, setRequests] = useState<any[]>([]);
@@ -59,19 +58,25 @@ export default function SongRequestsPage() {
59
58
  const unsubscribeAuth = onAuthStateChanged(auth, (currentUser) => {
60
59
  setUser(currentUser);
61
60
  });
61
+
62
62
  return () => unsubscribeAuth();
63
63
  }, []);
64
64
 
65
65
  useEffect(() => {
66
- const q = query(collection(db, "song_requests"), orderBy("createdAt", "desc"));
66
+ const q = query(
67
+ collection(db, "song_requests"),
68
+ orderBy("createdAt", "desc"),
69
+ );
67
70
  const unsubscribeData = onSnapshot(q, (snapshot) => {
68
71
  const data = snapshot.docs.map((doc) => ({
69
72
  id: doc.id,
70
73
  ...doc.data(),
71
74
  }));
75
+
72
76
  setRequests(data);
73
77
  setListLoading(false);
74
78
  });
79
+
75
80
  return () => unsubscribeData();
76
81
  }, []);
77
82
 
@@ -84,6 +89,7 @@ export default function SongRequestsPage() {
84
89
  description: "Please answer the question correctly (Hint: 10 years!).",
85
90
  color: "warning",
86
91
  });
92
+
87
93
  return;
88
94
  }
89
95
 
@@ -99,7 +105,8 @@ export default function SongRequestsPage() {
99
105
  setFormData({ name: "", song: "", artist: "", captcha: "" });
100
106
  addToast({
101
107
  title: "Song Requested!",
102
- description: "We'll try our best to play your favorite track at the Reception.",
108
+ description:
109
+ "We'll try our best to play your favorite track at the Reception.",
103
110
  color: "success",
104
111
  });
105
112
  } catch (err) {
@@ -123,7 +130,11 @@ export default function SongRequestsPage() {
123
130
  if (!requestToDelete) return;
124
131
  try {
125
132
  await deleteDoc(doc(db, "song_requests", requestToDelete));
126
- addToast({ title: "Deleted", description: "Request removed.", color: "success" });
133
+ addToast({
134
+ title: "Deleted",
135
+ description: "Request removed.",
136
+ color: "success",
137
+ });
127
138
  } catch (err) {
128
139
  addToast({ title: "Error", color: "danger" });
129
140
  } finally {
@@ -135,7 +146,7 @@ export default function SongRequestsPage() {
135
146
  const toggleStatus = async (id: string, currentStatus: string) => {
136
147
  try {
137
148
  await updateDoc(doc(db, "song_requests", id), {
138
- status: currentStatus === "played" ? "pending" : "played"
149
+ status: currentStatus === "played" ? "pending" : "played",
139
150
  });
140
151
  addToast({ title: "Status Updated", color: "success" });
141
152
  } catch (err) {
@@ -143,103 +154,133 @@ export default function SongRequestsPage() {
143
154
  }
144
155
  };
145
156
 
146
- const isAdmin = user?.email === "titas@titas.titas";
157
+ const isAdmin = user?.email === process.env.NEXT_PUBLIC_ADMIN_EMAIL;
147
158
 
148
159
  return (
149
160
  <div className="min-h-screen pb-20 pt-10 px-4 max-w-6xl mx-auto flex flex-col items-center">
150
161
  {/* Header */}
151
- <motion.div
152
- initial={{ opacity: 0, scale: 0.95 }}
162
+ <motion.div
153
163
  animate={{ opacity: 1, scale: 1 }}
154
164
  className="text-center space-y-6 mb-12"
165
+ initial={{ opacity: 0, scale: 0.95 }}
155
166
  >
156
167
  <div className="bg-wedding-pink-100 dark:bg-wedding-pink-900/30 p-4 rounded-full w-fit mx-auto">
157
- <svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="text-wedding-pink-500">
158
- <path d="M9 18V5l12-2v13"></path>
159
- <circle cx="6" cy="18" r="3"></circle>
160
- <circle cx="18" cy="16" r="3"></circle>
161
- </svg>
168
+ <svg
169
+ className="text-wedding-pink-500"
170
+ fill="none"
171
+ height="32"
172
+ stroke="currentColor"
173
+ strokeLinecap="round"
174
+ strokeLinejoin="round"
175
+ strokeWidth="2"
176
+ viewBox="0 0 24 24"
177
+ width="32"
178
+ >
179
+ <path d="M9 18V5l12-2v13" />
180
+ <circle cx="6" cy="18" r="3" />
181
+ <circle cx="18" cy="16" r="3" />
182
+ </svg>
162
183
  </div>
163
- <h1 className={`${fontCursive.className} text-5xl md:text-7xl text-wedding-pink-600 dark:text-wedding-pink-400 py-2`}>
184
+ <h1
185
+ className={`${fontCursive.className} text-5xl md:text-7xl text-wedding-pink-600 dark:text-wedding-pink-400 py-2`}
186
+ >
164
187
  Reception Playlist
165
188
  </h1>
166
189
  <p className="text-default-500 max-w-xl mx-auto italic">
167
- &quot;Music is the soul of our celebration. Tell us which song makes you want to hit the dance floor!&quot;
190
+ &quot;Music is the soul of our celebration. Tell us which song makes
191
+ you want to hit the dance floor!&quot;
168
192
  </p>
169
193
  </motion.div>
170
194
 
171
195
  <div className="grid lg:grid-cols-2 gap-12 w-full items-start">
172
196
  {/* Left: Request Form */}
173
197
  <Card className="bg-white/80 dark:bg-zinc-900/80 backdrop-blur-xl border border-wedding-gold-200 dark:border-wedding-gold-800 shadow-2xl p-6 md:p-8 rounded-[40px]">
174
- <h2 className={`${fontSans.className} text-2xl font-bold mb-6 text-default-800 dark:text-white`}>Request a Song</h2>
175
- <form onSubmit={handleSubmit} className="space-y-6">
198
+ <h2
199
+ className={`${fontSans.className} text-2xl font-bold mb-6 text-default-800 dark:text-white`}
200
+ >
201
+ Request a Song
202
+ </h2>
203
+ <form className="space-y-6" onSubmit={handleSubmit}>
176
204
  <Input
177
205
  isRequired
178
- label="Your Name"
179
- labelPlacement="outside-top"
180
- placeholder="Who are we dancing with?"
181
- variant="bordered"
182
- value={formData.name}
183
- onChange={(e) => setFormData({ ...formData, name: e.target.value })}
184
206
  classNames={{
185
207
  label: "text-wedding-pink-600 font-bold",
186
208
  input: "outline-none",
187
- inputWrapper: "border-wedding-pink-100 focus-within:!border-wedding-pink-500 h-14"
209
+ inputWrapper:
210
+ "border-wedding-pink-100 focus-within:!border-wedding-pink-500 h-14",
188
211
  }}
212
+ label="Your Name"
213
+ labelPlacement="outside-top"
214
+ placeholder="Who are we dancing with?"
215
+ value={formData.name}
216
+ variant="bordered"
217
+ onChange={(e) =>
218
+ setFormData({ ...formData, name: e.target.value })
219
+ }
189
220
  />
190
221
  <div className="grid md:grid-cols-2 gap-4">
191
222
  <Input
192
223
  isRequired
224
+ classNames={{
225
+ label: "text-wedding-pink-600 font-bold",
226
+ input: "outline-none",
227
+ inputWrapper:
228
+ "border-wedding-pink-100 focus-within:!border-wedding-pink-500 h-14",
229
+ }}
193
230
  label="Song Title"
194
231
  labelPlacement="outside-top"
195
232
  placeholder="E.g. Kesariya"
196
- variant="bordered"
197
233
  value={formData.song}
198
- onChange={(e) => setFormData({ ...formData, song: e.target.value })}
234
+ variant="bordered"
235
+ onChange={(e) =>
236
+ setFormData({ ...formData, song: e.target.value })
237
+ }
238
+ />
239
+ <Input
199
240
  classNames={{
200
241
  label: "text-wedding-pink-600 font-bold",
201
242
  input: "outline-none",
202
- inputWrapper: "border-wedding-pink-100 focus-within:!border-wedding-pink-500 h-14"
243
+ inputWrapper:
244
+ "border-wedding-pink-100 focus-within:!border-wedding-pink-500 h-14",
203
245
  }}
204
- />
205
- <Input
206
246
  label="Artist (Optional)"
207
247
  labelPlacement="outside-top"
208
248
  placeholder="E.g. Arijit Singh"
209
- variant="bordered"
210
249
  value={formData.artist}
211
- onChange={(e) => setFormData({ ...formData, artist: e.target.value })}
212
- classNames={{
213
- label: "text-wedding-pink-600 font-bold",
214
- input: "outline-none",
215
- inputWrapper: "border-wedding-pink-100 focus-within:!border-wedding-pink-500 h-14"
216
- }}
250
+ variant="bordered"
251
+ onChange={(e) =>
252
+ setFormData({ ...formData, artist: e.target.value })
253
+ }
217
254
  />
218
255
  </div>
219
256
 
220
257
  <Divider className="opacity-50" />
221
258
 
222
259
  <div className="p-4 bg-wedding-pink-50 dark:bg-wedding-pink-900/10 rounded-2xl border border-wedding-pink-100 dark:border-wedding-pink-800/30">
223
- <p className="text-[10px] font-bold text-wedding-pink-600 dark:text-wedding-pink-400 uppercase tracking-widest mb-2">Bot Protection</p>
224
- <Input
260
+ <p className="text-[10px] font-bold text-wedding-pink-600 dark:text-wedding-pink-400 uppercase tracking-widest mb-2">
261
+ Bot Protection
262
+ </p>
263
+ <Input
225
264
  isRequired
226
- label="How many years have we been together?"
227
- labelPlacement="outside-top"
228
- placeholder="Answer in numbers"
229
- variant="underlined"
230
- value={formData.captcha}
231
- onChange={(e) => setFormData({ ...formData, captcha: e.target.value })}
232
265
  classNames={{
233
266
  label: "text-default-600 text-xs",
234
267
  input: "text-center font-bold text-xl outline-none",
235
268
  }}
269
+ label="How many years have we been together?"
270
+ labelPlacement="outside-top"
271
+ placeholder="Answer in numbers"
272
+ value={formData.captcha}
273
+ variant="underlined"
274
+ onChange={(e) =>
275
+ setFormData({ ...formData, captcha: e.target.value })
276
+ }
236
277
  />
237
278
  </div>
238
279
 
239
- <Button
240
- type="submit"
241
- isLoading={loading}
280
+ <Button
242
281
  className="w-full bg-gradient-to-r from-wedding-pink-500 to-wedding-gold-500 text-white font-black h-14 text-lg shadow-xl shadow-wedding-pink-500/20"
282
+ isLoading={loading}
283
+ type="submit"
243
284
  >
244
285
  Submit Song Request
245
286
  </Button>
@@ -249,51 +290,122 @@ export default function SongRequestsPage() {
249
290
  {/* Right: Requests Feed */}
250
291
  <div className="space-y-6">
251
292
  <div className="flex items-center justify-between px-2">
252
- <h2 className={`${fontSans.className} text-2xl font-bold text-default-800 dark:text-white`}>The Queue</h2>
253
- <Chip color="secondary" variant="flat" size="sm" className={fontMono.className}>
293
+ <h2
294
+ className={`${fontSans.className} text-2xl font-bold text-default-800 dark:text-white`}
295
+ >
296
+ The Queue
297
+ </h2>
298
+ <Chip
299
+ className={fontMono.className}
300
+ color="secondary"
301
+ size="sm"
302
+ variant="flat"
303
+ >
254
304
  {requests.length} Total
255
305
  </Chip>
256
306
  </div>
257
-
307
+
258
308
  <div className="space-y-4 max-h-[600px] overflow-y-auto pr-2 custom-scrollbar">
259
309
  {listLoading ? (
260
- <div className="flex justify-center py-10"><Spinner color="danger" /></div>
310
+ <div className="flex justify-center py-10">
311
+ <Spinner color="danger" />
312
+ </div>
261
313
  ) : requests.length === 0 ? (
262
- <p className="text-center py-10 text-default-400 italic font-medium bg-default-50 dark:bg-zinc-900/30 rounded-3xl border border-dashed border-default-200">The playlist is waiting for your touch!</p>
314
+ <p className="text-center py-10 text-default-400 italic font-medium bg-default-50 dark:bg-zinc-900/30 rounded-3xl border border-dashed border-default-200">
315
+ The playlist is waiting for your touch!
316
+ </p>
263
317
  ) : (
264
318
  <AnimatePresence>
265
319
  {requests.map((item, i) => (
266
320
  <motion.div
267
321
  key={item.id}
268
- initial={{ opacity: 0, x: 20 }}
269
322
  animate={{ opacity: 1, x: 0 }}
323
+ initial={{ opacity: 0, x: 20 }}
270
324
  transition={{ delay: i * 0.05 }}
271
325
  >
272
- <Card className={`border ${item.status === 'played' ? 'bg-default-50/50 dark:bg-zinc-900/20 opacity-60' : 'bg-white dark:bg-zinc-900 shadow-lg'} transition-all`}>
326
+ <Card
327
+ className={`border ${item.status === "played" ? "bg-default-50/50 dark:bg-zinc-900/20 opacity-60" : "bg-white dark:bg-zinc-900 shadow-lg"} transition-all`}
328
+ >
273
329
  <CardBody className="p-4 flex flex-row items-center justify-between gap-4">
274
330
  <div className="flex items-center gap-4 flex-1 overflow-hidden">
275
- <div className={`w-10 h-10 rounded-full flex items-center justify-center flex-shrink-0 ${item.status === 'played' ? 'bg-green-100 text-green-600' : 'bg-wedding-pink-100 text-wedding-pink-600'}`}>
276
- {item.status === 'played' ? (
277
- <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round"><polyline points="20 6 9 17 4 12"></polyline></svg>
331
+ <div
332
+ className={`w-10 h-10 rounded-full flex items-center justify-center flex-shrink-0 ${item.status === "played" ? "bg-green-100 text-green-600" : "bg-wedding-pink-100 text-wedding-pink-600"}`}
333
+ >
334
+ {item.status === "played" ? (
335
+ <svg
336
+ fill="none"
337
+ height="20"
338
+ stroke="currentColor"
339
+ strokeLinecap="round"
340
+ strokeLinejoin="round"
341
+ strokeWidth="3"
342
+ viewBox="0 0 24 24"
343
+ width="20"
344
+ >
345
+ <polyline points="20 6 9 17 4 12" />
346
+ </svg>
278
347
  ) : (
279
- <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><path d="M9 18V5l12-2v13"></path><circle cx="6" cy="18" r="3"></circle></svg>
348
+ <svg
349
+ fill="none"
350
+ height="20"
351
+ stroke="currentColor"
352
+ strokeLinecap="round"
353
+ strokeLinejoin="round"
354
+ strokeWidth="2.5"
355
+ viewBox="0 0 24 24"
356
+ width="20"
357
+ >
358
+ <path d="M9 18V5l12-2v13" />
359
+ <circle cx="6" cy="18" r="3" />
360
+ </svg>
280
361
  )}
281
362
  </div>
282
363
  <div className="flex flex-col overflow-hidden">
283
- <p className={`font-bold truncate ${item.status === 'played' ? 'line-through text-default-400' : 'text-default-800 dark:text-white'}`}>{item.song}</p>
284
- <p className="text-xs text-default-500 truncate italic">{item.artist || 'Unknown Artist'} Requested by {item.name}</p>
364
+ <p
365
+ className={`font-bold truncate ${item.status === "played" ? "line-through text-default-400" : "text-default-800 dark:text-white"}`}
366
+ >
367
+ {item.song}
368
+ </p>
369
+ <p className="text-xs text-default-500 truncate italic">
370
+ {item.artist || "Unknown Artist"} • Requested by{" "}
371
+ {item.name}
372
+ </p>
285
373
  </div>
286
374
  </div>
287
375
 
288
376
  {isAdmin && (
289
377
  <div className="flex gap-1">
290
- <Tooltip content={item.status === 'played' ? 'Mark Pending' : 'Mark Played'}>
291
- <Button isIconOnly size="sm" variant="flat" color={item.status === 'played' ? 'warning' : 'success'} onPress={() => toggleStatus(item.id, item.status)}>
292
- {item.status === 'played' ? '↺' : '✓'}
378
+ <Tooltip
379
+ content={
380
+ item.status === "played"
381
+ ? "Mark Pending"
382
+ : "Mark Played"
383
+ }
384
+ >
385
+ <Button
386
+ isIconOnly
387
+ color={
388
+ item.status === "played"
389
+ ? "warning"
390
+ : "success"
391
+ }
392
+ size="sm"
393
+ variant="flat"
394
+ onPress={() =>
395
+ toggleStatus(item.id, item.status)
396
+ }
397
+ >
398
+ {item.status === "played" ? "↺" : "✓"}
293
399
  </Button>
294
400
  </Tooltip>
295
401
  <Tooltip content="Delete">
296
- <Button isIconOnly size="sm" variant="flat" color="danger" onPress={() => handleDeleteClick(item.id)}>
402
+ <Button
403
+ isIconOnly
404
+ color="danger"
405
+ size="sm"
406
+ variant="flat"
407
+ onPress={() => handleDeleteClick(item.id)}
408
+ >
297
409
 
298
410
  </Button>
299
411
  </Tooltip>
@@ -310,38 +422,63 @@ export default function SongRequestsPage() {
310
422
  </div>
311
423
 
312
424
  <div className="mt-16 text-center text-default-400 space-y-2">
313
- <HeartFilledIcon className="w-6 h-6 mx-auto text-wedding-pink-200" />
314
- <p className={`${fontMono.className} text-[10px] uppercase tracking-widest`}>Let the music play</p>
425
+ <HeartFilledIcon className="w-6 h-6 mx-auto text-wedding-pink-200" />
426
+ <p
427
+ className={`${fontMono.className} text-[10px] uppercase tracking-widest`}
428
+ >
429
+ Let the music play
430
+ </p>
315
431
  </div>
316
432
 
317
433
  {/* Delete Confirmation Modal */}
318
- <Modal
319
- isOpen={isDeleteModalOpen}
320
- onOpenChange={setIsDeleteModalOpen}
434
+ <Modal
321
435
  backdrop="blur"
322
- size="xs"
323
436
  className="dark:bg-zinc-900 border border-default-100 dark:border-zinc-800"
437
+ isOpen={isDeleteModalOpen}
438
+ size="xs"
439
+ onOpenChange={setIsDeleteModalOpen}
324
440
  >
325
441
  <ModalContent>
326
442
  {(onClose) => (
327
443
  <>
328
444
  <ModalBody className="pt-8 pb-4 text-center space-y-4">
329
445
  <div className="w-16 h-16 bg-danger-50 dark:bg-danger-900/20 rounded-full flex items-center justify-center mx-auto text-danger animate-bounce">
330
- <svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
331
- <polyline points="3 6 5 6 21 6"></polyline>
332
- <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path>
333
- </svg>
446
+ <svg
447
+ fill="none"
448
+ height="32"
449
+ stroke="currentColor"
450
+ strokeLinecap="round"
451
+ strokeLinejoin="round"
452
+ strokeWidth="2"
453
+ viewBox="0 0 24 24"
454
+ width="32"
455
+ >
456
+ <polyline points="3 6 5 6 21 6" />
457
+ <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" />
458
+ </svg>
334
459
  </div>
335
460
  <div>
336
- <h3 className="text-xl font-bold text-default-900 dark:text-white">Delete Request?</h3>
337
- <p className="text-sm text-default-500 mt-2">Are you sure you want to remove this song from the queue?</p>
461
+ <h3 className="text-xl font-bold text-default-900 dark:text-white">
462
+ Delete Request?
463
+ </h3>
464
+ <p className="text-sm text-default-500 mt-2">
465
+ Are you sure you want to remove this song from the queue?
466
+ </p>
338
467
  </div>
339
468
  </ModalBody>
340
469
  <ModalFooter className="flex-col gap-2 pb-8">
341
- <Button color="danger" className="w-full font-bold h-12" onPress={handleConfirmDelete}>
470
+ <Button
471
+ className="w-full font-bold h-12"
472
+ color="danger"
473
+ onPress={handleConfirmDelete}
474
+ >
342
475
  Yes, Remove Request
343
476
  </Button>
344
- <Button variant="flat" className="w-full font-semibold h-12" onPress={onClose}>
477
+ <Button
478
+ className="w-full font-semibold h-12"
479
+ variant="flat"
480
+ onPress={onClose}
481
+ >
345
482
  Cancel
346
483
  </Button>
347
484
  </ModalFooter>
@@ -351,4 +488,4 @@ export default function SongRequestsPage() {
351
488
  </Modal>
352
489
  </div>
353
490
  );
354
- }
491
+ }
@@ -17,7 +17,7 @@ export default function SukanyaPage() {
17
17
  <div className="relative w-72 h-72 md:w-96 md:h-96">
18
18
  <div className="absolute inset-0 bg-wedding-pink-200 dark:bg-wedding-pink-800 rounded-full blur-2xl opacity-50 transform translate-x-4 translate-y-4" />
19
19
  <Image
20
- alt="Sukanya Saha"
20
+ alt="Bride"
21
21
  className="rounded-full object-cover w-full h-full border-4 border-white dark:border-default-100 shadow-2xl z-10"
22
22
  src="/bride.jpg"
23
23
  />
@@ -29,7 +29,7 @@ export default function SukanyaPage() {
29
29
  <h1
30
30
  className={`${fontCursive.className} text-6xl md:text-7xl text-wedding-pink-600 dark:text-wedding-pink-400`}
31
31
  >
32
- Sukanya Saha
32
+ Bride Name
33
33
  </h1>
34
34
  <p
35
35
  className={`${fontMono.className} text-xl md:text-2xl text-default-600 dark:text-white font-medium`}
@@ -60,17 +60,13 @@ export default function SukanyaPage() {
60
60
  <div className="md:col-span-8 space-y-4 text-default-700 dark:text-white text-lg leading-relaxed">
61
61
  <p>
62
62
  I strive to foster curiosity, empathy, and excellence in the
63
- classroom. My academic journey began at{" "}
64
- <strong>Serampore Girls High School</strong> and continued with
65
- Botany Honours at <strong>Raja Peary Mohan College</strong>. I
66
- earned my Master&apos;s from{" "}
67
- <strong>Lady Brabourne College</strong>, building a deep research
63
+ classroom. My academic journey began at a reputable girls' school and continued with
64
+ Botany Honours at college. I
65
+ earned my Master&apos;s from a leading women's college, building a deep research
68
66
  orientation.
69
67
  </p>
70
68
  <p>
71
- Currently, I am a school teacher at{" "}
72
- <strong>Rishra Narayana School</strong> and a teaching partner at{" "}
73
- <strong>EugenicsErudite</strong>, where I emphasize conceptual
69
+ Currently, I am a school teacher at a private school and a teaching partner at an educational firm, where I emphasize conceptual
74
70
  clarity and moral growth.
75
71
  </p>
76
72
  </div>
@@ -145,7 +141,7 @@ export default function SukanyaPage() {
145
141
  My Partner
146
142
  </h3>
147
143
  <p className="text-default-600 dark:text-white text-sm mb-4">
148
- I found a partner in Titas—someone who is sincere,
144
+ I found a partner in the Groom—someone who is sincere,
149
145
  intellectually inclined, and my steady companion.
150
146
  </p>
151
147
  <Button
@@ -154,7 +150,7 @@ export default function SukanyaPage() {
154
150
  href="/titas"
155
151
  size="sm"
156
152
  >
157
- Meet Titas
153
+ Meet Groom
158
154
  </Button>
159
155
  </div>
160
156
  </CardBody>
@@ -164,4 +160,4 @@ export default function SukanyaPage() {
164
160
  </section>
165
161
  </div>
166
162
  );
167
- }
163
+ }