@titas_mallick/wedding-site-gen 1.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.
- package/.eslintignore +20 -0
- package/.eslintrc.json +93 -0
- package/.recover +9 -0
- package/.vscode/settings.json +3 -0
- package/LICENSE +21 -0
- package/README.md +83 -0
- package/app/Neo-Lucentism/layout.tsx +7 -0
- package/app/Neo-Lucentism/page.tsx +259 -0
- package/app/couple/layout.tsx +7 -0
- package/app/couple/page.tsx +164 -0
- package/app/error.tsx +31 -0
- package/app/guestbook/page.tsx +470 -0
- package/app/invitation/[slug]/layout.tsx +36 -0
- package/app/invitation/[slug]/page.tsx +462 -0
- package/app/invitation/maker/auth.js +165 -0
- package/app/invitation/maker/dashboard.js +81 -0
- package/app/invitation/maker/guestAdder.js +204 -0
- package/app/invitation/maker/guestShower.js +287 -0
- package/app/invitation/maker/layout.tsx +11 -0
- package/app/invitation/maker/page.js +168 -0
- package/app/invitation/maker/rsvpViewer.js +122 -0
- package/app/layout.tsx +98 -0
- package/app/mark-the-dates/layout.tsx +7 -0
- package/app/mark-the-dates/page.tsx +196 -0
- package/app/memories/layout.tsx +7 -0
- package/app/memories/page.tsx +29 -0
- package/app/page.tsx +5 -0
- package/app/providers.tsx +33 -0
- package/app/sagun/layout.tsx +7 -0
- package/app/sagun/page.tsx +348 -0
- package/app/song-requests/page.tsx +354 -0
- package/app/sukanya/layout.tsx +7 -0
- package/app/sukanya/page.tsx +167 -0
- package/app/titas/layout.tsx +7 -0
- package/app/titas/page.tsx +175 -0
- package/app/travel-guide/page.tsx +400 -0
- package/app/updates/maker/page.js +323 -0
- package/app/updates/overlay/page.tsx +144 -0
- package/app/updates/page.js +207 -0
- package/cli.mjs +196 -0
- package/components/ConciergeBot.tsx +203 -0
- package/components/CountdownTimer.tsx +137 -0
- package/components/Gallery.tsx +372 -0
- package/components/LiveVideos.tsx +173 -0
- package/components/OurStory.tsx +160 -0
- package/components/certificate.jsx +300 -0
- package/components/counter.tsx +14 -0
- package/components/footer.tsx +89 -0
- package/components/hero.tsx +136 -0
- package/components/icons.tsx +283 -0
- package/components/importantNews.js +168 -0
- package/components/navbar.tsx +106 -0
- package/components/primitives.ts +53 -0
- package/components/sagun.js +22 -0
- package/components/theme-switch.tsx +81 -0
- package/components/updates.tsx +118 -0
- package/components/weddingcard.js +68 -0
- package/components/weddingcard2.js +58 -0
- package/config/firebase-admin.js +17 -0
- package/config/firebase.ts +36 -0
- package/config/fonts.ts +21 -0
- package/config/site.ts +74 -0
- package/next-env.d.ts +6 -0
- package/next.config.js +4 -0
- package/package.json +64 -0
- package/postcss.config.js +6 -0
- 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/20.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/corner1-01.svg +1 -0
- package/public/favicon.ico +0 -0
- package/public/groom.jpg +0 -0
- package/public/invite.png +0 -0
- package/public/love-birds.png +0 -0
- package/public/next.svg +1 -0
- package/public/pubqr.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/public/qr.png +0 -0
- package/public/vercel.svg +1 -0
- package/styles/globals.css +3 -0
- package/tailwind.config.js +51 -0
- package/tsconfig.json +45 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/types/index.ts +5 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { tv } from "tailwind-variants";
|
|
2
|
+
|
|
3
|
+
export const title = tv({
|
|
4
|
+
base: "tracking-tight inline font-semibold",
|
|
5
|
+
variants: {
|
|
6
|
+
color: {
|
|
7
|
+
violet: "from-[#FF1CF7] to-[#b249f8]",
|
|
8
|
+
yellow: "from-[#FF705B] to-[#FFB457]",
|
|
9
|
+
blue: "from-[#5EA2EF] to-[#0072F5]",
|
|
10
|
+
cyan: "from-[#00b7fa] to-[#01cfea]",
|
|
11
|
+
green: "from-[#6FEE8D] to-[#17c964]",
|
|
12
|
+
pink: "from-[#FF72E1] to-[#F54C7A]",
|
|
13
|
+
foreground: "dark:from-[#FFFFFF] dark:to-[#4B4B4B]",
|
|
14
|
+
},
|
|
15
|
+
size: {
|
|
16
|
+
sm: "text-3xl lg:text-4xl",
|
|
17
|
+
md: "text-[2.3rem] lg:text-5xl leading-9",
|
|
18
|
+
lg: "text-4xl lg:text-6xl",
|
|
19
|
+
},
|
|
20
|
+
fullWidth: {
|
|
21
|
+
true: "w-full block",
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
defaultVariants: {
|
|
25
|
+
size: "md",
|
|
26
|
+
},
|
|
27
|
+
compoundVariants: [
|
|
28
|
+
{
|
|
29
|
+
color: [
|
|
30
|
+
"violet",
|
|
31
|
+
"yellow",
|
|
32
|
+
"blue",
|
|
33
|
+
"cyan",
|
|
34
|
+
"green",
|
|
35
|
+
"pink",
|
|
36
|
+
"foreground",
|
|
37
|
+
],
|
|
38
|
+
class: "bg-clip-text text-transparent bg-gradient-to-b",
|
|
39
|
+
},
|
|
40
|
+
],
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
export const subtitle = tv({
|
|
44
|
+
base: "w-full md:w-1/2 my-2 text-lg lg:text-xl text-default-600 block max-w-full",
|
|
45
|
+
variants: {
|
|
46
|
+
fullWidth: {
|
|
47
|
+
true: "!w-full",
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
defaultVariants: {
|
|
51
|
+
fullWidth: true,
|
|
52
|
+
},
|
|
53
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Button } from "@heroui/button";
|
|
3
|
+
import { Link } from "@heroui/link";
|
|
4
|
+
import { HeartFilledIcon } from "@/components/icons";
|
|
5
|
+
const Sagun = () => {
|
|
6
|
+
return (
|
|
7
|
+
<main>
|
|
8
|
+
<Button
|
|
9
|
+
isExternal
|
|
10
|
+
as={Link}
|
|
11
|
+
className="text-sm font-normal text-default-600 bg-default-100"
|
|
12
|
+
href={"/sagun"}
|
|
13
|
+
startContent={<HeartFilledIcon className="text-danger" />}
|
|
14
|
+
variant="flat"
|
|
15
|
+
>
|
|
16
|
+
Sagun
|
|
17
|
+
</Button>
|
|
18
|
+
</main>
|
|
19
|
+
);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export default Sagun;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { FC } from "react";
|
|
4
|
+
import { VisuallyHidden } from "@react-aria/visually-hidden";
|
|
5
|
+
import { SwitchProps, useSwitch } from "@heroui/switch";
|
|
6
|
+
import { useTheme } from "next-themes";
|
|
7
|
+
import { useIsSSR } from "@react-aria/ssr";
|
|
8
|
+
import clsx from "clsx";
|
|
9
|
+
|
|
10
|
+
import { SunFilledIcon, MoonFilledIcon } from "@/components/icons";
|
|
11
|
+
|
|
12
|
+
export interface ThemeSwitchProps {
|
|
13
|
+
className?: string;
|
|
14
|
+
classNames?: SwitchProps["classNames"];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const ThemeSwitch: FC<ThemeSwitchProps> = ({
|
|
18
|
+
className,
|
|
19
|
+
classNames,
|
|
20
|
+
}) => {
|
|
21
|
+
const { theme, setTheme } = useTheme();
|
|
22
|
+
const isSSR = useIsSSR();
|
|
23
|
+
|
|
24
|
+
const onChange = () => {
|
|
25
|
+
theme === "light" ? setTheme("dark") : setTheme("light");
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const {
|
|
29
|
+
Component,
|
|
30
|
+
slots,
|
|
31
|
+
isSelected,
|
|
32
|
+
getBaseProps,
|
|
33
|
+
getInputProps,
|
|
34
|
+
getWrapperProps,
|
|
35
|
+
} = useSwitch({
|
|
36
|
+
isSelected: theme === "light" || isSSR,
|
|
37
|
+
"aria-label": `Switch to ${theme === "light" || isSSR ? "dark" : "light"} mode`,
|
|
38
|
+
onChange,
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<Component
|
|
43
|
+
{...getBaseProps({
|
|
44
|
+
className: clsx(
|
|
45
|
+
"px-px transition-opacity hover:opacity-80 cursor-pointer",
|
|
46
|
+
className,
|
|
47
|
+
classNames?.base,
|
|
48
|
+
),
|
|
49
|
+
})}
|
|
50
|
+
>
|
|
51
|
+
<VisuallyHidden>
|
|
52
|
+
<input {...getInputProps()} />
|
|
53
|
+
</VisuallyHidden>
|
|
54
|
+
<div
|
|
55
|
+
{...getWrapperProps()}
|
|
56
|
+
className={slots.wrapper({
|
|
57
|
+
class: clsx(
|
|
58
|
+
[
|
|
59
|
+
"w-auto h-auto",
|
|
60
|
+
"bg-transparent",
|
|
61
|
+
"rounded-lg",
|
|
62
|
+
"flex items-center justify-center",
|
|
63
|
+
"group-data-[selected=true]:bg-transparent",
|
|
64
|
+
"!text-default-500",
|
|
65
|
+
"pt-px",
|
|
66
|
+
"px-0",
|
|
67
|
+
"mx-0",
|
|
68
|
+
],
|
|
69
|
+
classNames?.wrapper,
|
|
70
|
+
),
|
|
71
|
+
})}
|
|
72
|
+
>
|
|
73
|
+
{!isSelected || isSSR ? (
|
|
74
|
+
<SunFilledIcon size={22} />
|
|
75
|
+
) : (
|
|
76
|
+
<MoonFilledIcon size={22} />
|
|
77
|
+
)}
|
|
78
|
+
</div>
|
|
79
|
+
</Component>
|
|
80
|
+
);
|
|
81
|
+
};
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useEffect, useState } from "react";
|
|
4
|
+
import {
|
|
5
|
+
getFirestore,
|
|
6
|
+
collection,
|
|
7
|
+
onSnapshot,
|
|
8
|
+
query,
|
|
9
|
+
orderBy,
|
|
10
|
+
limit,
|
|
11
|
+
} from "firebase/firestore";
|
|
12
|
+
import { motion, AnimatePresence } from "framer-motion";
|
|
13
|
+
import Link from "next/link";
|
|
14
|
+
import { Chip } from "@heroui/react";
|
|
15
|
+
|
|
16
|
+
import firebaseApp from "@/config/firebase";
|
|
17
|
+
import { fontMono } from "@/config/fonts";
|
|
18
|
+
import { ClockIcon } from "./icons";
|
|
19
|
+
|
|
20
|
+
const db = getFirestore(firebaseApp());
|
|
21
|
+
|
|
22
|
+
const timeAgo = (timestamp: any) => {
|
|
23
|
+
if (!timestamp?.toDate) return "Just now";
|
|
24
|
+
const now = new Date();
|
|
25
|
+
const diff = (now.getTime() - timestamp.toDate().getTime()) / 1000;
|
|
26
|
+
if (diff < 60) return `${Math.floor(diff)}s ago`;
|
|
27
|
+
if (diff < 3600) return `${Math.floor(diff / 60)}m ago`;
|
|
28
|
+
if (diff < 86400) return `${Math.floor(diff / 3600)}h ago`;
|
|
29
|
+
return `${Math.floor(diff / 86400)}d ago`;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const Updates = () => {
|
|
33
|
+
const [latestUpdate, setLatestUpdate] = useState<any>(null);
|
|
34
|
+
const [loading, setLoading] = useState(true);
|
|
35
|
+
|
|
36
|
+
useEffect(() => {
|
|
37
|
+
const q = query(
|
|
38
|
+
collection(db, "updates"),
|
|
39
|
+
orderBy("createdAt", "desc"),
|
|
40
|
+
limit(1)
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
const unsubscribe = onSnapshot(q, (snapshot) => {
|
|
44
|
+
if (!snapshot.empty) {
|
|
45
|
+
setLatestUpdate({
|
|
46
|
+
id: snapshot.docs[0].id,
|
|
47
|
+
...snapshot.docs[0].data(),
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
setLoading(false);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
return () => unsubscribe();
|
|
54
|
+
}, []);
|
|
55
|
+
|
|
56
|
+
if (loading || !latestUpdate) return null;
|
|
57
|
+
|
|
58
|
+
return (
|
|
59
|
+
<AnimatePresence>
|
|
60
|
+
<motion.div
|
|
61
|
+
initial={{ opacity: 0, y: -20 }}
|
|
62
|
+
animate={{ opacity: 1, y: 0 }}
|
|
63
|
+
exit={{ opacity: 0, y: -20 }}
|
|
64
|
+
className="w-full max-w-3xl mx-auto px-4 z-50"
|
|
65
|
+
>
|
|
66
|
+
<div className="relative group">
|
|
67
|
+
{/* Animated Background Glow */}
|
|
68
|
+
<div className="absolute -inset-0.5 bg-gradient-to-r from-wedding-pink-500 to-wedding-gold-500 rounded-full blur opacity-20 group-hover:opacity-40 transition duration-1000 group-hover:duration-200"></div>
|
|
69
|
+
|
|
70
|
+
<Link
|
|
71
|
+
href="/updates"
|
|
72
|
+
className="relative flex items-center gap-2 sm:gap-3 bg-white/90 dark:bg-zinc-900/90 backdrop-blur-xl border border-wedding-gold-200/50 dark:border-wedding-gold-800/50 p-1 sm:p-1.5 pr-4 sm:pr-6 rounded-full shadow-xl transition-all duration-300 group-hover:border-wedding-pink-400"
|
|
73
|
+
>
|
|
74
|
+
<div className="flex items-center bg-wedding-pink-500 text-white px-2 sm:px-3 py-1 rounded-full text-[9px] sm:text-[10px] font-black tracking-widest shadow-lg shadow-wedding-pink-500/20">
|
|
75
|
+
UPDATE
|
|
76
|
+
</div>
|
|
77
|
+
|
|
78
|
+
<p className="flex-1 text-xs sm:text-sm font-semibold text-zinc-800 dark:text-zinc-100 truncate">
|
|
79
|
+
{latestUpdate.text}
|
|
80
|
+
</p>
|
|
81
|
+
|
|
82
|
+
<div className="hidden sm:flex items-center gap-4">
|
|
83
|
+
<div className="flex items-center gap-1.5 text-[10px] uppercase tracking-wider text-zinc-400 font-mono whitespace-nowrap border-x border-default-200 dark:border-default-800 px-4">
|
|
84
|
+
<ClockIcon size={12} className="text-wedding-gold-500" />
|
|
85
|
+
{timeAgo(latestUpdate.createdAt)}
|
|
86
|
+
</div>
|
|
87
|
+
|
|
88
|
+
<div className="flex items-center gap-1 text-xs font-bold text-wedding-pink-500 whitespace-nowrap group-hover:translate-x-1 transition-transform">
|
|
89
|
+
View All
|
|
90
|
+
<svg
|
|
91
|
+
width="14"
|
|
92
|
+
height="14"
|
|
93
|
+
viewBox="0 0 24 24"
|
|
94
|
+
fill="none"
|
|
95
|
+
stroke="currentColor"
|
|
96
|
+
strokeWidth="3"
|
|
97
|
+
strokeLinecap="round"
|
|
98
|
+
strokeLinejoin="round"
|
|
99
|
+
>
|
|
100
|
+
<polyline points="9 18 15 12 9 6"></polyline>
|
|
101
|
+
</svg>
|
|
102
|
+
</div>
|
|
103
|
+
</div>
|
|
104
|
+
|
|
105
|
+
{/* Mobile Arrow */}
|
|
106
|
+
<div className="sm:hidden text-wedding-pink-500 flex-shrink-0">
|
|
107
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round">
|
|
108
|
+
<polyline points="9 18 15 12 9 6"></polyline>
|
|
109
|
+
</svg>
|
|
110
|
+
</div>
|
|
111
|
+
</Link>
|
|
112
|
+
</div>
|
|
113
|
+
</motion.div>
|
|
114
|
+
</AnimatePresence>
|
|
115
|
+
);
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
export default Updates;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
Card,
|
|
5
|
+
CardFooter,
|
|
6
|
+
Image,
|
|
7
|
+
Button,
|
|
8
|
+
CardHeader,
|
|
9
|
+
CardBody,
|
|
10
|
+
Link,
|
|
11
|
+
} from "@heroui/react";
|
|
12
|
+
|
|
13
|
+
const WeddingCard = () => {
|
|
14
|
+
return (
|
|
15
|
+
<section className="relative w-full h-[500px] overflow-hidden rounded-2xl bg-black">
|
|
16
|
+
{/* Background Video */}
|
|
17
|
+
<div className="absolute inset-0 w-full h-full pointer-events-none">
|
|
18
|
+
<iframe
|
|
19
|
+
className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 pointer-events-none border-none"
|
|
20
|
+
style={{
|
|
21
|
+
width: '100vw',
|
|
22
|
+
height: '56.25vw', /* 16:9 Aspect Ratio */
|
|
23
|
+
minHeight: '100%',
|
|
24
|
+
minWidth: '177.77vh', /* 100 / 9 * 16 */
|
|
25
|
+
transform: 'translate(-50%, -50%) scale(1.1)', /* Extra scale to ensure no edge bleed */
|
|
26
|
+
}}
|
|
27
|
+
src="https://www.youtube.com/embed/a_RV8HevyBE?autoplay=1&mute=1&loop=1&playlist=a_RV8HevyBE&controls=0&showinfo=0&modestbranding=1&rel=0"
|
|
28
|
+
title="Pre Wedding Video"
|
|
29
|
+
allow="autoplay; encrypted-media"
|
|
30
|
+
/>
|
|
31
|
+
</div>
|
|
32
|
+
|
|
33
|
+
{/* Soft overlay */}
|
|
34
|
+
<div className="absolute inset-0 bg-black/30" />
|
|
35
|
+
|
|
36
|
+
{/* Card */}
|
|
37
|
+
<div className="relative z-10 flex items-center justify-center h-full">
|
|
38
|
+
<Card className="py-4">
|
|
39
|
+
<CardHeader className="pb-0 pt-2 px-4 flex-col items-start">
|
|
40
|
+
<p className="text-tiny uppercase font-bold">Social Marriage</p>
|
|
41
|
+
<small className="text-default-500">23 January, 2026</small>
|
|
42
|
+
<h4 className="font-bold text-large">
|
|
43
|
+
Anandamoyee Bhawan, Serampore
|
|
44
|
+
</h4>
|
|
45
|
+
</CardHeader>
|
|
46
|
+
<CardBody className="overflow-visible py-2">
|
|
47
|
+
<Image
|
|
48
|
+
alt="Card background"
|
|
49
|
+
className="object-cover rounded-xl"
|
|
50
|
+
src="/DCV2.gif"
|
|
51
|
+
width={320}
|
|
52
|
+
/>
|
|
53
|
+
<Link
|
|
54
|
+
href="https://maps.app.goo.gl/G5R3bkcTwwa2d54R8"
|
|
55
|
+
showAnchorIcon
|
|
56
|
+
color="warning"
|
|
57
|
+
className="w-full mx-auto text-center mt-2"
|
|
58
|
+
>
|
|
59
|
+
Location
|
|
60
|
+
</Link>
|
|
61
|
+
</CardBody>
|
|
62
|
+
</Card>
|
|
63
|
+
</div>
|
|
64
|
+
</section>
|
|
65
|
+
);
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export default WeddingCard;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { Card, CardFooter, Image, Button, CardHeader, CardBody, Link } from "@heroui/react";
|
|
4
|
+
|
|
5
|
+
const WeddingCard2 = () => {
|
|
6
|
+
return (
|
|
7
|
+
<section className="relative w-full h-[500px] overflow-hidden rounded-2xl bg-black">
|
|
8
|
+
{/* Background Video */}
|
|
9
|
+
<div className="absolute inset-0 w-full h-full pointer-events-none">
|
|
10
|
+
<iframe
|
|
11
|
+
className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 pointer-events-none border-none"
|
|
12
|
+
style={{
|
|
13
|
+
width: '100vw',
|
|
14
|
+
height: '56.25vw', /* 16:9 Aspect Ratio */
|
|
15
|
+
minHeight: '100%',
|
|
16
|
+
minWidth: '177.77vh', /* 100 / 9 * 16 */
|
|
17
|
+
transform: 'translate(-50%, -50%) scale(1.1)', /* Extra scale to ensure no edge bleed */
|
|
18
|
+
}}
|
|
19
|
+
src="https://www.youtube.com/embed/a_RV8HevyBE?autoplay=1&mute=1&loop=1&playlist=a_RV8HevyBE&controls=0&showinfo=0&modestbranding=1&rel=0"
|
|
20
|
+
title="Pre Wedding Video"
|
|
21
|
+
allow="autoplay; encrypted-media"
|
|
22
|
+
/>
|
|
23
|
+
</div>
|
|
24
|
+
|
|
25
|
+
{/* Soft overlay */}
|
|
26
|
+
<div className="absolute inset-0 bg-black/30" />
|
|
27
|
+
|
|
28
|
+
{/* Card */}
|
|
29
|
+
<div className="relative z-10 flex items-center justify-center h-full">
|
|
30
|
+
<Card className="py-4">
|
|
31
|
+
<CardHeader className="pb-0 pt-2 px-4 flex-col items-start">
|
|
32
|
+
<p className="text-tiny uppercase font-bold">Reception</p>
|
|
33
|
+
<small className="text-default-500">25 January, 2026</small>
|
|
34
|
+
<h4 className="font-bold text-large">Friend's Union Club, Konnagar</h4>
|
|
35
|
+
</CardHeader>
|
|
36
|
+
<CardBody className="overflow-visible py-2">
|
|
37
|
+
<Image
|
|
38
|
+
alt="Card background"
|
|
39
|
+
className="object-cover rounded-xl"
|
|
40
|
+
src="/DCV3.gif"
|
|
41
|
+
width={320}
|
|
42
|
+
/>
|
|
43
|
+
<Link
|
|
44
|
+
href="https://maps.app.goo.gl/ubdTsy6tnYMsvSSXA"
|
|
45
|
+
showAnchorIcon
|
|
46
|
+
color="warning"
|
|
47
|
+
className="w-full mx-auto text-center mt-2"
|
|
48
|
+
>
|
|
49
|
+
Location
|
|
50
|
+
</Link>
|
|
51
|
+
</CardBody>
|
|
52
|
+
</Card>
|
|
53
|
+
</div>
|
|
54
|
+
</section>
|
|
55
|
+
);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export default WeddingCard2;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const adminCred = {
|
|
2
|
+
type: "service_account",
|
|
3
|
+
project_id: "wedding-forever-titas-sukanya",
|
|
4
|
+
private_key_id: "6d71529b4b898a03b0534024eb58ddabdc76548d",
|
|
5
|
+
private_key:
|
|
6
|
+
"-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC5hjvkXTkczAT3\nkoLvJdxeXt/1V4rAp0xpNb9xoJDME74ciig1oUUusZ/l6v0KD9Li4RInS8evb55W\n9OsPUwz0N5TUnKmmJ3Kz22pG6Cz13M9kOnlpkbrD14aU9M34OWUpmKwMpqc1wHHJ\nTRX7VQ11HQ/OGX6SsJkX0JDaaRenH4IMz1c2+Ci+6p2LpzMaM5yiw7l34aeHWWjV\nFffeFmqHMKhIcS0Ib1yTv8cjhm731ouYXztDYApAdu4DHENrZm2ygyFoAQYnp2L3\n/GimwDKPGDsBLZEOyucvPzYvWW6d/jqWfgFaxSX2hrtJ8dNwD340Wz8H+Zc1VRkM\n8mUwU+ExAgMBAAECggEABZScwevD8gfOW8a+cC8gB9QBbJcrh0wA/REu0bOAvNgY\nhIdAr7b1e8gVWox3prvUc2/4ZHzfuXk5YWg7QdoVA6uVqyeN5X+Tmwa4larE33MQ\nPKA9qAfy1D1Ba8L0Bx7C2j4gvr4B6ENXqN8hZXlTeaMG0gOWTmydePKUc4gXEWHQ\nxwQtQN1e6shlhMfYT0KFT+B0l6C1J1ZvVKZmZsvgUE9EcJrPu5wOhIk8mGu54BYb\nTeeYjKCGgSe6l8THFR5O5fwNk80nXL12kZfzWqGKvrkeIeILtzWMi95pKrwSYFoQ\n3Zzk+Way0nAXW2DtGltc3K0MV4lpgEXcmpg5fyXxmQKBgQDno3XFzVI4mnCk3PN0\n5pjWmVoqrPJMtDUZma3tWSdDwYtbBXgz0o3zuJ8qGHog7vmiqVG7/cwp199Bmrrf\nzdpx5B2NUijp95cmBt5nlX09DYoRatubhfsmdBH6pDqvDmNbV1aYgKFypaODgLHi\n5W3BBQO/UN1XB8FfjS3iEcyD6wKBgQDNCTcTklf2h27v9W3ovTyBrZZXolYEVMwA\n6iXvWk24MU/Xn7RGue78NwO5T5K3VU9wrkPOi3oEYNtoQKNVsMJDc6FI9TKEAQhz\nFjCq7+aUKYbzx/2Z8vXglFqMsBl/AhXSj99Nt0rjvI3LuUiI1QZwj8wRmnx5GSRG\nup35jDRUUwKBgEinkK02NW/joSlU1Ff6bD4DY7C3BljgvTcGaPNlX1d1QYyPLqCy\njiu/4MyHWOczjcFjcmuQs5T8TN569dp06uuGLW7CMmsQaaxXwzKiROH9eSz1Y2Ro\npdnt1iXTlUSLMsbXoiW7Uuhu49a/awxMAhzkwcQkTQibOiAKXDXod0l5AoGACgVQ\nRsmZOPhHiLzDAWP2SBQ2y9OoRo/qZIUNE5SjRcRLNaudgPNnZbY+nVjxP7qQpl4t\n/DM+5GXjc0Xtdaus4uUM1eb98Auo4Q8Nk90jtMwOx21XzKVeNPqrLkMRC+8LJ/5W\nGJNDurulZnaIv/9BUFEG1TlqqfR7nGVUgTTD/fcCgYEAwSo1mr03BIGOENuhxv7C\naSYSUjVEH6kdNo2nrK899ez2OxXHdfrvCg/I6Vpz2qFDQ7ZrENYeoljQzlFwYSzK\n2H6jZnt/6uZ7mXENZgxUXscrlu7znn0eQ1xo+acqIK03YTzvh5UnoBpvfy12bEiV\nlBOrdL+oEYBSHrhq38XQG80=\n-----END PRIVATE KEY-----\n",
|
|
7
|
+
client_email:
|
|
8
|
+
"firebase-adminsdk-fbsvc@wedding-forever-titas-sukanya.iam.gserviceaccount.com",
|
|
9
|
+
client_id: "108512120143007143022",
|
|
10
|
+
auth_uri: "https://accounts.google.com/o/oauth2/auth",
|
|
11
|
+
token_uri: "https://oauth2.googleapis.com/token",
|
|
12
|
+
auth_provider_x509_cert_url: "https://www.googleapis.com/oauth2/v1/certs",
|
|
13
|
+
client_x509_cert_url:
|
|
14
|
+
"https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-fbsvc%40wedding-forever-titas-sukanya.iam.gserviceaccount.com",
|
|
15
|
+
universe_domain: "googleapis.com",
|
|
16
|
+
};
|
|
17
|
+
export default adminCred;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { initializeApp, getApps, getApp, FirebaseApp } from "firebase/app";
|
|
3
|
+
import { getAnalytics } from "firebase/analytics";
|
|
4
|
+
import { initializeAppCheck, ReCaptchaV3Provider } from "firebase/app-check";
|
|
5
|
+
|
|
6
|
+
const firebaseConfig = {
|
|
7
|
+
apiKey: process.env.NEXT_PUBLIC_APIKEY,
|
|
8
|
+
authDomain: process.env.NEXT_PUBLIC_AUTHDOMAIN,
|
|
9
|
+
projectId: process.env.NEXT_PUBLIC_PROJECTID,
|
|
10
|
+
storageBucket: process.env.NEXT_PUBLIC_STORAGEBUCKET,
|
|
11
|
+
messagingSenderId: process.env.NEXT_PUBLIC_SENDERID,
|
|
12
|
+
appId: process.env.NEXT_PUBLIC_APPID,
|
|
13
|
+
measurementId: process.env.NEXT_PUBLIC_MEASUREMENTID,
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const firebaseApp = (): FirebaseApp => {
|
|
17
|
+
let app: FirebaseApp;
|
|
18
|
+
if (!getApps().length) {
|
|
19
|
+
app = initializeApp(firebaseConfig);
|
|
20
|
+
|
|
21
|
+
if (typeof window !== "undefined") {
|
|
22
|
+
getAnalytics(app);
|
|
23
|
+
initializeAppCheck(app, {
|
|
24
|
+
provider: new ReCaptchaV3Provider(
|
|
25
|
+
process.env.NEXT_PUBLIC_RECAPTCHA_SITE_KEY as string
|
|
26
|
+
),
|
|
27
|
+
isTokenAutoRefreshEnabled: true,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
} else {
|
|
31
|
+
app = getApp();
|
|
32
|
+
}
|
|
33
|
+
return app;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export default firebaseApp;
|
package/config/fonts.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Geist as FontSans,
|
|
3
|
+
Geist_Mono as FontMono,
|
|
4
|
+
Great_Vibes as FontCursive,
|
|
5
|
+
} from "next/font/google";
|
|
6
|
+
|
|
7
|
+
export const fontSans = FontSans({
|
|
8
|
+
subsets: ["latin"],
|
|
9
|
+
variable: "--font-sans",
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
export const fontMono = FontMono({
|
|
13
|
+
subsets: ["latin"],
|
|
14
|
+
variable: "--font-mono",
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
export const fontCursive = FontCursive({
|
|
18
|
+
subsets: ["latin"],
|
|
19
|
+
weight: "400", // Great Vibes only comes in 400
|
|
20
|
+
variable: "--font-cursive",
|
|
21
|
+
});
|
package/config/site.ts
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
export type SiteConfig = typeof siteConfig;
|
|
2
|
+
|
|
3
|
+
export const siteConfig = {
|
|
4
|
+
name: "Titas & Sukanya",
|
|
5
|
+
description:
|
|
6
|
+
"Join us in celebrating the wedding of Titas and Sukanya. Save the date and be part of our journey.",
|
|
7
|
+
navItems: [
|
|
8
|
+
{
|
|
9
|
+
label: "Home",
|
|
10
|
+
href: "/",
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
label: "Our Story",
|
|
14
|
+
href: "/couple",
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
label: "Events",
|
|
18
|
+
href: "/mark-the-dates",
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
label: "Guestbook",
|
|
22
|
+
href: "/guestbook",
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
label: "Songs",
|
|
26
|
+
href: "/song-requests",
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
label: "Travel Guide",
|
|
30
|
+
href: "/travel-guide",
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
label: "Gallery",
|
|
34
|
+
href: "/memories",
|
|
35
|
+
},
|
|
36
|
+
],
|
|
37
|
+
navMenuItems: [
|
|
38
|
+
{
|
|
39
|
+
label: "Home",
|
|
40
|
+
href: "/",
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
label: "Our Story",
|
|
44
|
+
href: "/couple",
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
label: "Events",
|
|
48
|
+
href: "/mark-the-dates",
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
label: "Guestbook",
|
|
52
|
+
href: "/guestbook",
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
label: "Gallery",
|
|
56
|
+
href: "/memories",
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
label: "Song Requests",
|
|
60
|
+
href: "/song-requests",
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
label: "Travel Guide",
|
|
64
|
+
href: "/travel-guide",
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
label: "Send Wishes",
|
|
68
|
+
href: "/sagun",
|
|
69
|
+
},
|
|
70
|
+
],
|
|
71
|
+
links: {
|
|
72
|
+
// Keep empty or relevant social links if needed later
|
|
73
|
+
},
|
|
74
|
+
};
|
package/next-env.d.ts
ADDED
package/next.config.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@titas_mallick/wedding-site-gen",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"bin": {
|
|
5
|
+
"create-wedding-site": "./cli.mjs"
|
|
6
|
+
},
|
|
7
|
+
"scripts": {
|
|
8
|
+
"dev": "next dev --turbopack",
|
|
9
|
+
"build": "next build --turbopack",
|
|
10
|
+
"start": "next start",
|
|
11
|
+
"lint": "eslint . --ext .ts,.tsx -c .eslintrc.json --fix"
|
|
12
|
+
},
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"@heroui/button": "2.2.17",
|
|
15
|
+
"@heroui/code": "2.2.12",
|
|
16
|
+
"@heroui/input": "2.4.17",
|
|
17
|
+
"@heroui/kbd": "2.2.13",
|
|
18
|
+
"@heroui/link": "2.2.14",
|
|
19
|
+
"@heroui/listbox": "2.3.16",
|
|
20
|
+
"@heroui/navbar": "2.2.15",
|
|
21
|
+
"@heroui/react": "^2.7.8",
|
|
22
|
+
"@heroui/snippet": "2.2.18",
|
|
23
|
+
"@heroui/switch": "2.2.15",
|
|
24
|
+
"@heroui/system": "2.4.13",
|
|
25
|
+
"@heroui/theme": "2.4.13",
|
|
26
|
+
"@react-aria/ssr": "3.9.7",
|
|
27
|
+
"@react-aria/visually-hidden": "3.8.21",
|
|
28
|
+
"@vercel/analytics": "^1.6.1",
|
|
29
|
+
"clsx": "2.1.1",
|
|
30
|
+
"firebase": "^11.7.3",
|
|
31
|
+
"firebase-admin": "^13.4.0",
|
|
32
|
+
"framer-motion": "11.13.1",
|
|
33
|
+
"intl-messageformat": "^10.5.0",
|
|
34
|
+
"next": "^16.0.1",
|
|
35
|
+
"next-themes": "^0.4.4",
|
|
36
|
+
"react": "^18.3.1",
|
|
37
|
+
"react-dom": "^18.3.1"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@next/eslint-plugin-next": "15.0.4",
|
|
41
|
+
"@react-types/shared": "3.25.0",
|
|
42
|
+
"@types/node": "20.5.7",
|
|
43
|
+
"@types/react": "18.3.3",
|
|
44
|
+
"@types/react-dom": "18.3.0",
|
|
45
|
+
"@typescript-eslint/eslint-plugin": "8.11.0",
|
|
46
|
+
"@typescript-eslint/parser": "8.11.0",
|
|
47
|
+
"autoprefixer": "10.4.19",
|
|
48
|
+
"eslint": "^8.57.0",
|
|
49
|
+
"eslint-config-next": "^15.3.1",
|
|
50
|
+
"eslint-config-prettier": "9.1.0",
|
|
51
|
+
"eslint-plugin-import": "^2.26.0",
|
|
52
|
+
"eslint-plugin-jsx-a11y": "^6.4.1",
|
|
53
|
+
"eslint-plugin-node": "^11.1.0",
|
|
54
|
+
"eslint-plugin-prettier": "5.2.1",
|
|
55
|
+
"eslint-plugin-react": "^7.23.2",
|
|
56
|
+
"eslint-plugin-react-hooks": "^4.6.0",
|
|
57
|
+
"eslint-plugin-unused-imports": "4.1.4",
|
|
58
|
+
"postcss": "8.4.49",
|
|
59
|
+
"prettier": "3.3.3",
|
|
60
|
+
"tailwind-variants": "0.3.0",
|
|
61
|
+
"tailwindcss": "3.4.16",
|
|
62
|
+
"typescript": "5.6.3"
|
|
63
|
+
}
|
|
64
|
+
}
|
package/public/DCV.gif
ADDED
|
Binary file
|
package/public/DCV2.gif
ADDED
|
Binary file
|
package/public/DCV3.gif
ADDED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|