@titas_mallick/wedding-site-gen 1.1.0 → 2.0.1
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.
- package/README.md +104 -170
- package/app/api/email-reminders/route.ts +240 -0
- package/app/couple/page.tsx +4 -4
- package/app/game/page.tsx +298 -0
- package/app/guestbook/page.tsx +270 -152
- package/app/invitation/[slug]/layout.tsx +4 -2
- package/app/invitation/[slug]/page.tsx +303 -84
- package/app/invitation/actions.ts +49 -0
- package/app/invitation/maker/auth.js +1 -1
- package/app/invitation/maker/guestAdder.js +4 -0
- package/app/invitation/maker/guestShower.js +39 -8
- package/app/invitation/maker/layout.tsx +1 -1
- package/app/invitation/maker/page.js +9 -7
- package/app/invitation/maker/rsvpViewer.js +90 -8
- package/app/layout.tsx +40 -14
- package/app/mark-the-dates/page.tsx +8 -2
- package/app/page.tsx +7 -1
- package/app/providers.tsx +1 -1
- package/app/sagun/page.tsx +224 -76
- package/app/song-requests/page.tsx +242 -105
- package/app/sukanya/page.tsx +9 -13
- package/app/titas/page.tsx +8 -24
- package/app/travel-guide/page.tsx +361 -120
- package/app/updates/maker/page.js +2 -2
- package/app/updates/overlay/page.tsx +65 -30
- package/app/updates/page.js +3 -3
- package/cli.mjs +26 -15
- package/components/AdminAuth.tsx +145 -0
- package/components/AdminLinks.tsx +120 -0
- package/components/ConciergeBot.tsx +104 -44
- package/components/CountdownTimer.tsx +37 -15
- package/components/Gallery.tsx +1 -1
- package/components/LiveVideos.tsx +27 -15
- package/components/OurStory.tsx +1 -1
- package/components/SchemaMarkup.tsx +74 -0
- package/components/certificate.jsx +287 -300
- package/components/footer.tsx +2 -0
- package/components/hero.tsx +47 -4
- package/components/icons.tsx +45 -0
- package/components/importantNews.js +168 -168
- package/components/navbar.tsx +113 -18
- package/components/updates.tsx +36 -26
- package/config/firebase-admin.js +14 -17
- package/config/firebase.ts +4 -2
- package/config/site.ts +10 -2
- package/firestore.rules +6 -1
- package/next-sitemap.config.js +21 -0
- package/package.json +4 -3
- package/public/corner1-01.svg +0 -0
- package/public/love-birds.png +0 -0
- package/public/next.svg +0 -0
- package/public/pubqr.png +0 -0
- package/public/pw/sample.jpg +0 -0
- package/public/qr.png +0 -0
- package/public/sample.jpg +0 -0
- package/public/vercel.svg +0 -0
- package/vercel.json +1 -0
- package/.recover +0 -9
- package/next-env.d.ts +0 -6
- package/public/DCV.gif +0 -0
- package/public/DCV2.gif +0 -0
- package/public/DCV3.gif +0 -0
- package/public/Images/1.jpg +0 -0
- package/public/Images/11.jpg +0 -0
- package/public/Images/12.jpg +0 -0
- package/public/Images/13.jpg +0 -0
- package/public/Images/14.jpg +0 -0
- package/public/Images/15.jpg +0 -0
- package/public/Images/16.jpg +0 -0
- package/public/Images/17.jpg +0 -0
- package/public/Images/18.jpg +0 -0
- package/public/Images/19.jpg +0 -0
- package/public/Images/2.jpg +0 -0
- package/public/Images/21.jpg +0 -0
- package/public/Images/22.jpg +0 -0
- package/public/Images/3.jpg +0 -0
- package/public/Images/4.jpg +0 -0
- package/public/Images/5.jpg +0 -0
- package/public/Images/6.jpg +0 -0
- package/public/Images/7.jpg +0 -0
- package/public/Images/8.jpg +0 -0
- package/public/Images/9.jpg +0 -0
- package/public/Images/9b.jpg +0 -0
- package/public/Images/Patipatra.jpeg +0 -0
- package/public/audio (1).mp3 +0 -0
- package/public/audio (2).mp3 +0 -0
- package/public/bride.jpg +0 -0
- package/public/groom.jpg +0 -0
- package/public/invite.png +0 -0
- package/public/pw/001.jpg +0 -0
- package/public/pw/002.jpg +0 -0
- package/public/pw/003.jpg +0 -0
- package/public/pw/004.jpg +0 -0
- package/public/pw/005.jpg +0 -0
- package/public/pw/006.jpg +0 -0
- package/public/pw/007.jpg +0 -0
- package/public/pw/008.jpg +0 -0
- package/public/pw/009.jpg +0 -0
- package/public/pw/010.jpg +0 -0
- package/public/pw/011.jpg +0 -0
- package/public/pw/012.jpg +0 -0
- package/public/pw/013.jpg +0 -0
- package/public/pw/014.jpg +0 -0
- package/public/pw/015.jpg +0 -0
- package/public/pw/016.jpg +0 -0
- package/public/pw/017.jpg +0 -0
- package/public/pw/018.jpg +0 -0
- package/public/pw/019.jpg +0 -0
- package/public/pw/020.jpg +0 -0
- package/public/pw/021.jpg +0 -0
- package/public/pw/022.jpg +0 -0
- package/public/pw/023.jpg +0 -0
- package/public/pw/024.jpg +0 -0
- package/public/pw/025.jpg +0 -0
- package/public/pw/026.jpg +0 -0
- package/public/pw/027.jpg +0 -0
- package/public/pw/028.jpg +0 -0
- package/public/pw/029.jpg +0 -0
- package/public/pw/030.jpg +0 -0
- package/public/pw/031.jpg +0 -0
- package/public/pw/032.jpg +0 -0
- package/tsconfig.tsbuildinfo +0 -1
- /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({
|
|
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(
|
|
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:
|
|
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({
|
|
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 ===
|
|
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
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
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
|
|
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
|
-
"Music is the soul of our celebration. Tell us which song makes
|
|
190
|
+
"Music is the soul of our celebration. Tell us which song makes
|
|
191
|
+
you want to hit the dance floor!"
|
|
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
|
|
175
|
-
|
|
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:
|
|
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
|
-
|
|
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:
|
|
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
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
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
|
-
|
|
224
|
-
|
|
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
|
|
253
|
-
|
|
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"
|
|
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">
|
|
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
|
|
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
|
|
276
|
-
{item.status ===
|
|
277
|
-
|
|
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
|
|
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
|
|
284
|
-
|
|
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
|
|
291
|
-
|
|
292
|
-
|
|
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
|
|
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
|
-
|
|
314
|
-
|
|
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
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
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">
|
|
337
|
-
|
|
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
|
|
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
|
|
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
|
+
}
|
package/app/sukanya/page.tsx
CHANGED
|
@@ -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="
|
|
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
|
-
|
|
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
|
-
|
|
65
|
-
|
|
66
|
-
earned my Master'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'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
|
|
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
|
|
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
|
+
}
|