marquee
3009
package-lock.json
generated
@ -4,7 +4,7 @@
|
|||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite --host",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"lint": "eslint .",
|
"lint": "eslint .",
|
||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
@ -17,6 +17,8 @@
|
|||||||
"@mui/styled-engine-sc": "^7.3.5",
|
"@mui/styled-engine-sc": "^7.3.5",
|
||||||
"@tailwindcss/vite": "^4.1.17",
|
"@tailwindcss/vite": "^4.1.17",
|
||||||
"axios": "^1.13.2",
|
"axios": "^1.13.2",
|
||||||
|
"framer-motion": "^12.23.24",
|
||||||
|
"lightswind": "^3.1.15",
|
||||||
"lucide-react": "^0.553.0",
|
"lucide-react": "^0.553.0",
|
||||||
"react": "^19.2.0",
|
"react": "^19.2.0",
|
||||||
"react-dom": "^19.2.0",
|
"react-dom": "^19.2.0",
|
||||||
|
|||||||
42
src/App.css
@ -1,42 +0,0 @@
|
|||||||
#root {
|
|
||||||
max-width: 1280px;
|
|
||||||
margin: 0 auto;
|
|
||||||
padding: 2rem;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.logo {
|
|
||||||
height: 6em;
|
|
||||||
padding: 1.5em;
|
|
||||||
will-change: filter;
|
|
||||||
transition: filter 300ms;
|
|
||||||
}
|
|
||||||
.logo:hover {
|
|
||||||
filter: drop-shadow(0 0 2em #646cffaa);
|
|
||||||
}
|
|
||||||
.logo.react:hover {
|
|
||||||
filter: drop-shadow(0 0 2em #61dafbaa);
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes logo-spin {
|
|
||||||
from {
|
|
||||||
transform: rotate(0deg);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
transform: rotate(360deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (prefers-reduced-motion: no-preference) {
|
|
||||||
a:nth-of-type(2) .logo {
|
|
||||||
animation: logo-spin infinite 20s linear;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.card {
|
|
||||||
padding: 2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.read-the-docs {
|
|
||||||
color: #888;
|
|
||||||
}
|
|
||||||
41
src/App.jsx
@ -1,39 +1,14 @@
|
|||||||
import { useState } from 'react'
|
import "./App.css";
|
||||||
import reactLogo from './assets/react.svg'
|
import { BrowserRouter as Router } from "react-router-dom";
|
||||||
import viteLogo from '/vite.svg'
|
import AppRoutes from "./routes/AppRoutes";
|
||||||
import './App.css'
|
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const [count, setCount] = useState(0)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div>
|
<Router>
|
||||||
<a href="https://vite.dev" target="_blank">
|
<AppRoutes />
|
||||||
<img src={viteLogo} className="logo" alt="Vite logo" />
|
</Router>
|
||||||
</a>
|
|
||||||
<a href="https://react.dev" target="_blank">
|
|
||||||
<img src={reactLogo} className="logo react" alt="React logo" />
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<h1>Vite + React</h1>
|
|
||||||
<div className="card">
|
|
||||||
<button onClick={() => setCount((count) => count + 1)}>
|
|
||||||
count is {count}
|
|
||||||
</button>
|
|
||||||
<p>
|
|
||||||
Edit <code>src/App.jsx</code> and save to test HMR
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<p className="read-the-docs">
|
|
||||||
Click on the Vite and React logos to learn more
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<h1 class="text-3xl font-bold underline">
|
|
||||||
Hello world!
|
|
||||||
</h1>
|
|
||||||
</>
|
</>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default App
|
export default App;
|
||||||
|
|||||||
BIN
src/assets/images/appstore.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
src/assets/images/logo.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
57
src/assets/images/match-hour.svg
Normal file
|
After Width: | Height: | Size: 753 KiB |
BIN
src/assets/images/mobile.png
Normal file
|
After Width: | Height: | Size: 323 KiB |
BIN
src/assets/images/playstore.png
Normal file
|
After Width: | Height: | Size: 4.0 KiB |
BIN
src/assets/images/scanner.png
Normal file
|
After Width: | Height: | Size: 91 KiB |
77
src/assets/images/video-profile.svg
Normal file
|
After Width: | Height: | Size: 153 KiB |
73
src/assets/images/voice-call.svg
Normal file
|
After Width: | Height: | Size: 402 KiB |
BIN
src/assets/images/wedding1.jpg
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
src/assets/images/wedding10.jpg
Normal file
|
After Width: | Height: | Size: 109 KiB |
BIN
src/assets/images/wedding11.jpg
Normal file
|
After Width: | Height: | Size: 49 KiB |
BIN
src/assets/images/wedding12.avif
Normal file
BIN
src/assets/images/wedding2.jpg
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
src/assets/images/wedding3.jpg
Normal file
|
After Width: | Height: | Size: 50 KiB |
BIN
src/assets/images/wedding4.webp
Normal file
|
After Width: | Height: | Size: 862 KiB |
BIN
src/assets/images/wedding5.webp
Normal file
|
After Width: | Height: | Size: 69 KiB |
BIN
src/assets/images/wedding6.jpeg
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
src/assets/images/wedding7.jpg
Normal file
|
After Width: | Height: | Size: 6.5 KiB |
BIN
src/assets/images/wedding8.jpg
Normal file
|
After Width: | Height: | Size: 49 KiB |
BIN
src/assets/images/wedding9.avif
Normal file
203
src/components/common/LandingHeader.jsx
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
import { useState } from "react";
|
||||||
|
import * as React from "react";
|
||||||
|
import AppBar from "@mui/material/AppBar";
|
||||||
|
import Box from "@mui/material/Box";
|
||||||
|
import Toolbar from "@mui/material/Toolbar";
|
||||||
|
import IconButton from "@mui/material/IconButton";
|
||||||
|
import Typography from "@mui/material/Typography";
|
||||||
|
import SwipeableDrawer from "@mui/material/SwipeableDrawer";
|
||||||
|
import List from "@mui/material/List";
|
||||||
|
import ListItem from "@mui/material/ListItem";
|
||||||
|
import ListItemButton from "@mui/material/ListItemButton";
|
||||||
|
import ListItemText from "@mui/material/ListItemText";
|
||||||
|
import Avatar from "@mui/material/Avatar";
|
||||||
|
import Container from "@mui/material/Container";
|
||||||
|
import Button from "@mui/material/Button";
|
||||||
|
import Tooltip from "@mui/material/Tooltip";
|
||||||
|
import MenuItem from "@mui/material/MenuItem";
|
||||||
|
import Menu from "@mui/material/Menu";
|
||||||
|
import MenuIcon from "@mui/icons-material/Menu";
|
||||||
|
import CloseIcon from "@mui/icons-material/Close"; // <-- Added
|
||||||
|
import Divider from "@mui/material/Divider";
|
||||||
|
import AdbIcon from "@mui/icons-material/Adb";
|
||||||
|
import ListItemIcon from "@mui/material/ListItemIcon";
|
||||||
|
import { InboxIcon, MailIcon } from "lucide-react";
|
||||||
|
|
||||||
|
const pages = ["Matches", "Search", "Help"];
|
||||||
|
const settings = ["Profile", "Account", "Dashboard", "Logout"];
|
||||||
|
|
||||||
|
const LandingHeader = () => {
|
||||||
|
const [drawerOpen, setDrawerOpen] = useState(false);
|
||||||
|
const [anchorElUser, setAnchorElUser] = React.useState(null);
|
||||||
|
|
||||||
|
const toggleDrawer = (open) => () => {
|
||||||
|
setDrawerOpen(open);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleOpenUserMenu = (event) => {
|
||||||
|
setAnchorElUser(event.currentTarget);
|
||||||
|
};
|
||||||
|
const handleCloseUserMenu = () => {
|
||||||
|
setAnchorElUser(null);
|
||||||
|
};
|
||||||
|
|
||||||
|
const DrawerList = (
|
||||||
|
<Box
|
||||||
|
sx={{ width: 250 }}
|
||||||
|
role="presentation"
|
||||||
|
onKeyDown={toggleDrawer(false)}
|
||||||
|
>
|
||||||
|
{/* Drawer Header + Close Button */}
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
alignItems: "center",
|
||||||
|
px: 2,
|
||||||
|
py: 1.5,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography variant="h6">Menu</Typography>
|
||||||
|
|
||||||
|
{/* Close Button */}
|
||||||
|
<IconButton onClick={toggleDrawer(false)}>
|
||||||
|
<CloseIcon />
|
||||||
|
</IconButton>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Divider />
|
||||||
|
|
||||||
|
<List>
|
||||||
|
{["Matches", "Search", "Chat", "Mail"].map((text, index) => (
|
||||||
|
<ListItem key={text} disablePadding>
|
||||||
|
<ListItemButton>
|
||||||
|
<ListItemIcon>
|
||||||
|
{index % 2 === 0 ? <InboxIcon /> : <MailIcon />}
|
||||||
|
</ListItemIcon>
|
||||||
|
<ListItemText primary={text} />
|
||||||
|
</ListItemButton>
|
||||||
|
</ListItem>
|
||||||
|
))}
|
||||||
|
</List>
|
||||||
|
|
||||||
|
{/* <Divider />
|
||||||
|
|
||||||
|
<List>
|
||||||
|
{["All mail", "Trash", "Spam"].map((text, index) => (
|
||||||
|
<ListItem key={text} disablePadding>
|
||||||
|
<ListItemButton>
|
||||||
|
<ListItemIcon>
|
||||||
|
{index % 2 === 0 ? <InboxIcon /> : <MailIcon />}
|
||||||
|
</ListItemIcon>
|
||||||
|
<ListItemText primary={text} />
|
||||||
|
</ListItemButton>
|
||||||
|
</ListItem>
|
||||||
|
))}
|
||||||
|
</List> */}
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<AppBar position="sticky">
|
||||||
|
<Container maxWidth="xl">
|
||||||
|
<Toolbar disableGutters>
|
||||||
|
{/* Desktop Logo */}
|
||||||
|
<AdbIcon sx={{ display: { xs: "none", md: "flex" }, mr: 1 }} />
|
||||||
|
<Typography
|
||||||
|
variant="h6"
|
||||||
|
noWrap
|
||||||
|
component="a"
|
||||||
|
href="#"
|
||||||
|
sx={{
|
||||||
|
mr: 2,
|
||||||
|
display: { xs: "none", md: "flex" },
|
||||||
|
fontFamily: "monospace",
|
||||||
|
fontWeight: 700,
|
||||||
|
letterSpacing: ".3rem",
|
||||||
|
color: "inherit",
|
||||||
|
textDecoration: "none",
|
||||||
|
position:"sticky",
|
||||||
|
zIndex:"99"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
LOGO
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
{/* Mobile Drawer Button */}
|
||||||
|
<Box sx={{ flexGrow: 1, display: { xs: "flex", md: "none" } }}>
|
||||||
|
<IconButton size="large" color="inherit" onClick={toggleDrawer(true)}>
|
||||||
|
<MenuIcon />
|
||||||
|
</IconButton>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
{/* Mobile Logo */}
|
||||||
|
<AdbIcon sx={{ display: { xs: "flex", md: "none" }, mr: 1 }} />
|
||||||
|
<Typography
|
||||||
|
variant="h5"
|
||||||
|
noWrap
|
||||||
|
component="a"
|
||||||
|
href="#"
|
||||||
|
sx={{
|
||||||
|
mr: 2,
|
||||||
|
display: { xs: "flex", md: "none" },
|
||||||
|
flexGrow: 1,
|
||||||
|
fontFamily: "monospace",
|
||||||
|
fontWeight: 700,
|
||||||
|
letterSpacing: ".3rem",
|
||||||
|
color: "inherit",
|
||||||
|
textDecoration: "none",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
LOGO
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
{/* Desktop Menu */}
|
||||||
|
<Box sx={{ flexGrow: 1, display: { xs: "none", md: "flex" } }}>
|
||||||
|
{pages.map((page) => (
|
||||||
|
<Button key={page} sx={{ my: 2, color: "white", display: "block" }}>
|
||||||
|
{page}
|
||||||
|
</Button>
|
||||||
|
))}
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
{/* Avatar Menu */}
|
||||||
|
<Box sx={{ flexGrow: 0 }}>
|
||||||
|
<Tooltip title="Open settings">
|
||||||
|
<IconButton onClick={handleOpenUserMenu} sx={{ p: 0 }}>
|
||||||
|
<Avatar alt="User" src="/static/images/avatar/2.jpg" />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
<Menu
|
||||||
|
sx={{ mt: "45px" }}
|
||||||
|
anchorEl={anchorElUser}
|
||||||
|
open={Boolean(anchorElUser)}
|
||||||
|
onClose={handleCloseUserMenu}
|
||||||
|
anchorOrigin={{ vertical: "top", horizontal: "right" }}
|
||||||
|
transformOrigin={{ vertical: "top", horizontal: "right" }}
|
||||||
|
>
|
||||||
|
{settings.map((setting) => (
|
||||||
|
<MenuItem key={setting} onClick={handleCloseUserMenu}>
|
||||||
|
<Typography textAlign="center">{setting}</Typography>
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
|
</Menu>
|
||||||
|
</Box>
|
||||||
|
</Toolbar>
|
||||||
|
</Container>
|
||||||
|
</AppBar>
|
||||||
|
|
||||||
|
{/* Drawer */}
|
||||||
|
<SwipeableDrawer
|
||||||
|
anchor="left"
|
||||||
|
open={drawerOpen}
|
||||||
|
onClose={toggleDrawer(false)}
|
||||||
|
onOpen={toggleDrawer(true)}
|
||||||
|
>
|
||||||
|
{DrawerList}
|
||||||
|
</SwipeableDrawer>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default LandingHeader;
|
||||||
341
src/components/landing/AppPromoteSection.jsx
Normal file
@ -0,0 +1,341 @@
|
|||||||
|
|
||||||
|
import { useState, useEffect } from 'react';
|
||||||
|
import { motion } from 'framer-motion';
|
||||||
|
import { Users, Shield, Lock, Download, Smartphone, QrCode } from 'lucide-react';
|
||||||
|
|
||||||
|
const AppPromoteSection = () => {
|
||||||
|
|
||||||
|
const [isVisible, setIsVisible] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setIsVisible(true);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const fadeInUp = {
|
||||||
|
hidden: { opacity: 0, y: 60 },
|
||||||
|
visible: {
|
||||||
|
opacity: 1,
|
||||||
|
y: 0,
|
||||||
|
transition: { duration: 0.6, ease: "easeOut" }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const staggerContainer = {
|
||||||
|
hidden: { opacity: 0 },
|
||||||
|
visible: {
|
||||||
|
opacity: 1,
|
||||||
|
transition: {
|
||||||
|
staggerChildren: 0.2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const scaleIn = {
|
||||||
|
hidden: { opacity: 0, scale: 0.8 },
|
||||||
|
visible: {
|
||||||
|
opacity: 1,
|
||||||
|
scale: 1,
|
||||||
|
transition: { duration: 0.5 }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const features = [
|
||||||
|
{
|
||||||
|
icon: <Users className="w-8 h-8 text-pink-500" />,
|
||||||
|
title: "100% Screened Profiles",
|
||||||
|
description: "Search by location, community, profession & more from lakhs of active profiles",
|
||||||
|
color: "bg-pink-50 dark:bg-pink-900/20"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: <Shield className="w-8 h-8 text-blue-500" />,
|
||||||
|
title: "Verifications by Personal Visit",
|
||||||
|
description: "Special listing for profiles verified by our agents through personal visits",
|
||||||
|
color: "bg-blue-50 dark:bg-blue-900/20"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: <Lock className="w-8 h-8 text-purple-500" />,
|
||||||
|
title: "Control over Privacy",
|
||||||
|
description: "Restrict unwanted access to contact details & photos/videos",
|
||||||
|
color: "bg-purple-50 dark:bg-purple-900/20"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
|
||||||
|
<div className="min-h-screen bg-gradient-to-br from-gray-50 to-pink-50 dark:from-gray-900 dark:to-pink-900/20">
|
||||||
|
{/* Hero Section */}
|
||||||
|
<section className="relative min-h-screen flex items-center justify-center overflow-hidden">
|
||||||
|
{/* Background Image with Overlay */}
|
||||||
|
<div
|
||||||
|
className="absolute inset-0 z-0"
|
||||||
|
style={{
|
||||||
|
backgroundImage: 'url(https://images.unsplash.com/photo-1519741497674-611481863552?w=1200)',
|
||||||
|
backgroundSize: 'cover',
|
||||||
|
backgroundPosition: 'center',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className="absolute inset-0 bg-gradient-to-r from-black/70 to-black/50"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Content */}
|
||||||
|
<div className="relative z-10 max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-20">
|
||||||
|
<motion.div
|
||||||
|
initial="hidden"
|
||||||
|
animate={isVisible ? "visible" : "hidden"}
|
||||||
|
variants={fadeInUp}
|
||||||
|
className="text-center"
|
||||||
|
>
|
||||||
|
<motion.p
|
||||||
|
variants={fadeInUp}
|
||||||
|
className="text-pink-300 text-sm font-medium tracking-wider uppercase mb-4"
|
||||||
|
>
|
||||||
|
MORE THAN 25 YEARS OF
|
||||||
|
</motion.p>
|
||||||
|
<motion.h1
|
||||||
|
variants={fadeInUp}
|
||||||
|
className="text-5xl md:text-7xl font-bold text-white mb-8"
|
||||||
|
>
|
||||||
|
Bringing People <span className="text-pink-400">Together</span>
|
||||||
|
</motion.h1>
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
{/* Features Grid */}
|
||||||
|
<motion.div
|
||||||
|
variants={staggerContainer}
|
||||||
|
initial="hidden"
|
||||||
|
animate={isVisible ? "visible" : "hidden"}
|
||||||
|
className="grid grid-cols-1 md:grid-cols-3 gap-6 mt-16 max-w-6xl mx-auto"
|
||||||
|
>
|
||||||
|
{features.map((feature, index) => (
|
||||||
|
<motion.div
|
||||||
|
key={index}
|
||||||
|
variants={scaleIn}
|
||||||
|
whileHover={{ scale: 1.05, y: -5 }}
|
||||||
|
className="bg-white dark:bg-gray-800 rounded-2xl p-8 shadow-xl hover:shadow-2xl transition-all duration-300"
|
||||||
|
>
|
||||||
|
<motion.div
|
||||||
|
className={`${feature.color} w-16 h-16 rounded-full flex items-center justify-center mb-6`}
|
||||||
|
whileHover={{ rotate: 360 }}
|
||||||
|
transition={{ duration: 0.6 }}
|
||||||
|
>
|
||||||
|
{feature.icon}
|
||||||
|
</motion.div>
|
||||||
|
<h3 className="text-xl font-bold text-gray-900 dark:text-white mb-3">
|
||||||
|
{feature.title}
|
||||||
|
</h3>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 leading-relaxed">
|
||||||
|
{feature.description}
|
||||||
|
</p>
|
||||||
|
</motion.div>
|
||||||
|
))}
|
||||||
|
</motion.div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* App Download Section */}
|
||||||
|
<section className="relative py-20 bg-gradient-to-br from-pink-50 to-rose-100 dark:from-pink-900/10 dark:to-rose-900/20">
|
||||||
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
|
||||||
|
{/* Left Content */}
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, x: -50 }}
|
||||||
|
whileInView={{ opacity: 1, x: 0 }}
|
||||||
|
viewport={{ once: true }}
|
||||||
|
transition={{ duration: 0.6 }}
|
||||||
|
>
|
||||||
|
<h2 className="text-4xl md:text-5xl font-bold text-gray-900 dark:text-white mb-4">
|
||||||
|
Download the Jeevansathi app
|
||||||
|
</h2>
|
||||||
|
<p className="text-xl text-gray-600 dark:text-gray-300 mb-8">
|
||||||
|
Connect with your matches anytime, anywhere
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="bg-white dark:bg-gray-800 rounded-2xl p-8 shadow-xl">
|
||||||
|
<p className="text-center text-gray-700 dark:text-gray-300 mb-6 font-medium">
|
||||||
|
Point your phone camera at the QR code or use<br />one of the download links below
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{/* QR Code */}
|
||||||
|
<div className="flex justify-center mb-6">
|
||||||
|
<motion.div
|
||||||
|
className="bg-white p-4 rounded-xl shadow-lg"
|
||||||
|
whileHover={{ scale: 1.05 }}
|
||||||
|
>
|
||||||
|
<div className="w-32 h-32 bg-gray-900 rounded-lg flex items-center justify-center">
|
||||||
|
<QrCode className="w-24 h-24 text-white" />
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Download Buttons */}
|
||||||
|
<div className="flex flex-col sm:flex-row gap-4 justify-center">
|
||||||
|
<motion.button
|
||||||
|
whileHover={{ scale: 1.05 }}
|
||||||
|
whileTap={{ scale: 0.95 }}
|
||||||
|
className="bg-black text-white px-6 py-3 rounded-lg flex items-center justify-center space-x-2 hover:bg-gray-800 transition-colors"
|
||||||
|
>
|
||||||
|
<Smartphone className="w-5 h-5" />
|
||||||
|
<div className="text-left">
|
||||||
|
<div className="text-xs">GET IT ON</div>
|
||||||
|
<div className="font-bold">Google Play</div>
|
||||||
|
</div>
|
||||||
|
</motion.button>
|
||||||
|
|
||||||
|
<motion.button
|
||||||
|
whileHover={{ scale: 1.05 }}
|
||||||
|
whileTap={{ scale: 0.95 }}
|
||||||
|
className="bg-black text-white px-6 py-3 rounded-lg flex items-center justify-center space-x-2 hover:bg-gray-800 transition-colors"
|
||||||
|
>
|
||||||
|
<Download className="w-5 h-5" />
|
||||||
|
<div className="text-left">
|
||||||
|
<div className="text-xs">Download on the</div>
|
||||||
|
<div className="font-bold">App Store</div>
|
||||||
|
</div>
|
||||||
|
</motion.button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p className="text-center mt-6">
|
||||||
|
<span className="text-pink-600 dark:text-pink-400 font-medium">
|
||||||
|
Or get a download link
|
||||||
|
</span>
|
||||||
|
<span className="text-gray-600 dark:text-gray-400"> on your SMS/Email</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
{/* Right - Phone Mockup */}
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, x: 50 }}
|
||||||
|
whileInView={{ opacity: 1, x: 0 }}
|
||||||
|
viewport={{ once: true }}
|
||||||
|
transition={{ duration: 0.6 }}
|
||||||
|
className="relative"
|
||||||
|
>
|
||||||
|
<div className="relative">
|
||||||
|
{/* Phone Frame */}
|
||||||
|
<motion.div
|
||||||
|
className="relative mx-auto w-full max-w-sm"
|
||||||
|
animate={{ y: [0, -10, 0] }}
|
||||||
|
transition={{ duration: 3, repeat: Infinity, ease: "easeInOut" }}
|
||||||
|
>
|
||||||
|
<div className="bg-gray-900 rounded-[3rem] p-4 shadow-2xl">
|
||||||
|
<div className="bg-white dark:bg-gray-800 rounded-[2.5rem] overflow-hidden">
|
||||||
|
{/* Phone Screen Content */}
|
||||||
|
<div className="aspect-[9/19] bg-gradient-to-br from-pink-100 to-purple-100 dark:from-pink-900/20 dark:to-purple-900/20 p-6">
|
||||||
|
<div className="flex items-center justify-between mb-6">
|
||||||
|
<h3 className="font-bold text-gray-900 dark:text-white">My Matches</h3>
|
||||||
|
<div className="flex space-x-2">
|
||||||
|
<div className="w-8 h-8 rounded-full bg-pink-400"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Profile Cards */}
|
||||||
|
<div className="space-y-4">
|
||||||
|
{[1, 2].map((i) => (
|
||||||
|
<motion.div
|
||||||
|
key={i}
|
||||||
|
initial={{ opacity: 0, y: 20 }}
|
||||||
|
animate={{ opacity: 1, y: 0 }}
|
||||||
|
transition={{ delay: i * 0.2 }}
|
||||||
|
className="bg-white dark:bg-gray-700 rounded-2xl p-4 shadow-lg"
|
||||||
|
>
|
||||||
|
<div className="flex items-center space-x-3 mb-3">
|
||||||
|
<div className="w-16 h-16 rounded-full bg-gradient-to-br from-pink-400 to-purple-500"></div>
|
||||||
|
<div className="flex-1">
|
||||||
|
<h4 className="font-semibold text-gray-900 dark:text-white">Profile Name</h4>
|
||||||
|
<p className="text-sm text-gray-600 dark:text-gray-400">25 yrs, 5'6"</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex space-x-2">
|
||||||
|
<button className="flex-1 bg-pink-500 text-white py-2 rounded-lg text-sm font-medium">
|
||||||
|
Connect
|
||||||
|
</button>
|
||||||
|
<button className="px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg">
|
||||||
|
<span className="text-xl">💬</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Features Tags */}
|
||||||
|
<div className="mt-6 space-y-2">
|
||||||
|
<motion.div
|
||||||
|
className="bg-white dark:bg-gray-700 rounded-full px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 inline-block"
|
||||||
|
animate={{ x: [0, 5, 0] }}
|
||||||
|
transition={{ duration: 2, repeat: Infinity }}
|
||||||
|
>
|
||||||
|
✓ Easy Verification
|
||||||
|
</motion.div>
|
||||||
|
<motion.div
|
||||||
|
className="bg-white dark:bg-gray-700 rounded-full px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 inline-block ml-2"
|
||||||
|
animate={{ x: [0, -5, 0] }}
|
||||||
|
transition={{ duration: 2, repeat: Infinity, delay: 0.3 }}
|
||||||
|
>
|
||||||
|
✓ Voice & Video Calls
|
||||||
|
</motion.div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
{/* Download Badge */}
|
||||||
|
<motion.div
|
||||||
|
className="absolute -bottom-4 -right-4 bg-white dark:bg-gray-800 rounded-2xl px-6 py-3 shadow-xl"
|
||||||
|
initial={{ opacity: 0, scale: 0 }}
|
||||||
|
whileInView={{ opacity: 1, scale: 1 }}
|
||||||
|
viewport={{ once: true }}
|
||||||
|
transition={{ delay: 0.5 }}
|
||||||
|
>
|
||||||
|
<p className="text-sm text-gray-600 dark:text-gray-400">10M+ downloads</p>
|
||||||
|
</motion.div>
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Stats Section */}
|
||||||
|
<motion.section
|
||||||
|
className="py-16 bg-white dark:bg-gray-900"
|
||||||
|
initial={{ opacity: 0 }}
|
||||||
|
whileInView={{ opacity: 1 }}
|
||||||
|
viewport={{ once: true }}
|
||||||
|
>
|
||||||
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
|
<div className="grid grid-cols-2 md:grid-cols-4 gap-8">
|
||||||
|
{[
|
||||||
|
{ number: "25+", label: "Years of Trust" },
|
||||||
|
{ number: "10M+", label: "Happy Users" },
|
||||||
|
{ number: "100%", label: "Verified Profiles" },
|
||||||
|
{ number: "24/7", label: "Support" }
|
||||||
|
].map((stat, index) => (
|
||||||
|
<motion.div
|
||||||
|
key={index}
|
||||||
|
className="text-center"
|
||||||
|
initial={{ opacity: 0, y: 20 }}
|
||||||
|
whileInView={{ opacity: 1, y: 0 }}
|
||||||
|
viewport={{ once: true }}
|
||||||
|
transition={{ delay: index * 0.1 }}
|
||||||
|
>
|
||||||
|
<motion.h3
|
||||||
|
className="text-4xl md:text-5xl font-bold text-pink-500 mb-2"
|
||||||
|
whileHover={{ scale: 1.1 }}
|
||||||
|
>
|
||||||
|
{stat.number}
|
||||||
|
</motion.h3>
|
||||||
|
<p className="text-gray-600 dark:text-gray-400 font-medium">{stat.label}</p>
|
||||||
|
</motion.div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</motion.section>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AppPromoteSection
|
||||||
98
src/components/ui/ThreeDMarquee.jsx
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
import Button from "@mui/material/Button";
|
||||||
|
import { motion } from "framer-motion";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
const ThreeDMarquee = ({ images = [], className = "", cols = 4, onImageClick }) => {
|
||||||
|
// Clone the image list twice
|
||||||
|
const duplicatedImages = [...images, ...images];
|
||||||
|
|
||||||
|
const groupSize = Math.ceil(duplicatedImages.length / cols);
|
||||||
|
const imageGroups = Array.from({ length: cols }, (_, index) =>
|
||||||
|
duplicatedImages.slice(index * groupSize, (index + 1) * groupSize)
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleImageClick = (image, globalIndex) => {
|
||||||
|
if (onImageClick) {
|
||||||
|
onImageClick(image, globalIndex);
|
||||||
|
} else if (image.href) {
|
||||||
|
window.open(image.href, image.target || "_self");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section
|
||||||
|
className={`mx-auto block h-[600px] max-sm:h-[400px]
|
||||||
|
overflow-hidden bg-[#034E08] relative ${className} max-w-[1400px] ` }
|
||||||
|
|
||||||
|
style={{background: "linear-gradient(rgba(255, 255, 255, 0) 0%, rgba(2, 77, 14, 1) 70%)"}}
|
||||||
|
>
|
||||||
|
<div className="absolute bottom-0 left-0 w-full h-[300px] " style={{background: "linear-gradient(rgba(255, 255, 255, 0) 0%, rgb(255, 255, 255) 70%)"}} />
|
||||||
|
<div className="absolute top-0 left-0 w-full h-[200px] " style={{background: "linear-gradient(rgba(255, 255, 255, 0.88) 10%, rgba(255, 255, 255, 0) 70% )"}} />
|
||||||
|
<div className="text-white rounded-[0px] md:rounded-[10px] p-[20px] absolute md:top-[40%] md:left-[30%] w-full md:max-w-[600px] h-[100%] md:h-[230px] z-9 backdrop-blur-[5px] bg-black/50">
|
||||||
|
|
||||||
|
<h2 className="text-center text-[45px] font-900 pb-2">Now, chat for free !</h2>
|
||||||
|
<p className="text-center text-[22px] font-900 pb-4">Finding your perfect match just become easier</p>
|
||||||
|
<div className="flex itemes-center justify-center ">
|
||||||
|
<Button variant="contained" size="medium" sx={{width:"fit-content", padding:"10px 20px"}}>Regsiter Now</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className="flex w-full h-full items-center justify-center"
|
||||||
|
style={{
|
||||||
|
transform: "rotateX(55deg) rotateY(0deg) rotateZ(45deg)",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className="w-full overflow-hidden scale-90 sm:scale-100">
|
||||||
|
<div
|
||||||
|
className={`relative grid h-full w-full origin-center
|
||||||
|
grid-cols-4 sm:grid-cols-${cols} gap-4 transform
|
||||||
|
`}
|
||||||
|
>
|
||||||
|
{imageGroups.map((imagesInGroup, idx) => (
|
||||||
|
<motion.div
|
||||||
|
key={`column-${idx}`}
|
||||||
|
animate={{ y: idx % 2 === 0 ? 100 : -100 }}
|
||||||
|
transition={{
|
||||||
|
// duration: idx % 2 === 0 ? 20 : 15,
|
||||||
|
duration: idx % 2 === 0 ? 5 : 4,
|
||||||
|
ease: "linear",
|
||||||
|
repeat: Infinity,
|
||||||
|
repeatType: "reverse",
|
||||||
|
}}
|
||||||
|
className="flex flex-col items-center gap-6 relative"
|
||||||
|
>
|
||||||
|
<div className="absolute left-0 top-0 h-full w-0.5 " />
|
||||||
|
{imagesInGroup.map((image, imgIdx) => {
|
||||||
|
const globalIndex = idx * groupSize + imgIdx;
|
||||||
|
const isClickable = image.href || onImageClick;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div key={`img-${imgIdx}`} className="relative">
|
||||||
|
<div className="absolute top-0 left-0 w-full h-0.5 " />
|
||||||
|
<div className="max-w-[300px] h-[290px] rounded-lg overflow-hidden bg-white">
|
||||||
|
<motion.img
|
||||||
|
whileHover={{ y: -10 }}
|
||||||
|
transition={{ duration: 0.3, ease: "easeInOut" }}
|
||||||
|
src={image.src}
|
||||||
|
alt={image.alt}
|
||||||
|
width={970}
|
||||||
|
height={700}
|
||||||
|
className={`aspect-[970/700] w-full h-full object-cover shadow-xl hover:shadow-2xl transition-shadow duration-300 ${
|
||||||
|
isClickable ? "cursor-pointer" : ""
|
||||||
|
}`}
|
||||||
|
onClick={() => handleImageClick(image, globalIndex)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</motion.div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ThreeDMarquee;
|
||||||
@ -1,71 +1,3 @@
|
|||||||
@import "tailwindcss";
|
@import "tailwindcss";
|
||||||
|
|
||||||
|
|
||||||
:root {
|
|
||||||
font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
|
|
||||||
line-height: 1.5;
|
|
||||||
font-weight: 400;
|
|
||||||
|
|
||||||
color-scheme: light dark;
|
|
||||||
color: rgba(255, 255, 255, 0.87);
|
|
||||||
background-color: #242424;
|
|
||||||
|
|
||||||
font-synthesis: none;
|
|
||||||
text-rendering: optimizeLegibility;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
-moz-osx-font-smoothing: grayscale;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
font-weight: 500;
|
|
||||||
color: #646cff;
|
|
||||||
text-decoration: inherit;
|
|
||||||
}
|
|
||||||
a:hover {
|
|
||||||
color: #535bf2;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
display: flex;
|
|
||||||
place-items: center;
|
|
||||||
min-width: 320px;
|
|
||||||
min-height: 100vh;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-size: 3.2em;
|
|
||||||
line-height: 1.1;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
border-radius: 8px;
|
|
||||||
border: 1px solid transparent;
|
|
||||||
padding: 0.6em 1.2em;
|
|
||||||
font-size: 1em;
|
|
||||||
font-weight: 500;
|
|
||||||
font-family: inherit;
|
|
||||||
background-color: #1a1a1a;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: border-color 0.25s;
|
|
||||||
}
|
|
||||||
button:hover {
|
|
||||||
border-color: #646cff;
|
|
||||||
}
|
|
||||||
button:focus,
|
|
||||||
button:focus-visible {
|
|
||||||
outline: 4px auto -webkit-focus-ring-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (prefers-color-scheme: light) {
|
|
||||||
:root {
|
|
||||||
color: #213547;
|
|
||||||
background-color: #ffffff;
|
|
||||||
}
|
|
||||||
a:hover {
|
|
||||||
color: #747bff;
|
|
||||||
}
|
|
||||||
button {
|
|
||||||
background-color: #f9f9f9;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
14
src/layout/LandingLayout.jsx
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { Outlet } from "react-router-dom";
|
||||||
|
import LandingHeader from "../components/common/LandingHeader";
|
||||||
|
const LandingLayout = () => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<LandingHeader/>
|
||||||
|
<div className="body-container" style={{ marginBottom:'90px' }}>
|
||||||
|
<Outlet />
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default LandingLayout
|
||||||
20
src/main.jsx
@ -1,10 +1,14 @@
|
|||||||
import { StrictMode } from 'react'
|
import React from "react";
|
||||||
import { createRoot } from 'react-dom/client'
|
import ReactDOM from "react-dom/client";
|
||||||
import './index.css'
|
|
||||||
import App from './App.jsx'
|
|
||||||
|
|
||||||
createRoot(document.getElementById('root')).render(
|
import "./index.css";
|
||||||
<StrictMode>
|
import App from "./App.jsx";
|
||||||
|
import { ThemeProvider } from "@mui/material/styles";
|
||||||
|
import theme from "./theme";
|
||||||
|
ReactDOM.createRoot(document.getElementById("root")).render(
|
||||||
|
<React.StrictMode>
|
||||||
|
<ThemeProvider theme={theme}>
|
||||||
<App />
|
<App />
|
||||||
</StrictMode>,
|
</ThemeProvider>
|
||||||
)
|
</React.StrictMode>
|
||||||
|
);
|
||||||
|
|||||||
72
src/pages/HomePage.jsx
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
import AppPromoteSection from "../components/landing/AppPromoteSection";
|
||||||
|
import ThreeDMarquee from "../components/ui/ThreeDMarquee";
|
||||||
|
import wedding1 from "../assets/images/wedding1.jpg";
|
||||||
|
import wedding2 from "../assets/images/wedding2.jpg";
|
||||||
|
import wedding3 from "../assets/images/wedding3.jpg";
|
||||||
|
import wedding4 from "../assets/images/wedding4.webp";
|
||||||
|
import wedding5 from "../assets/images/wedding5.webp";
|
||||||
|
import wedding6 from "../assets/images/wedding6.jpeg";
|
||||||
|
import wedding7 from "../assets/images/wedding7.jpg";
|
||||||
|
import wedding8 from "../assets/images/wedding8.jpg";
|
||||||
|
import wedding9 from "../assets/images/wedding9.avif";
|
||||||
|
import wedding10 from "../assets/images/wedding10.jpg";
|
||||||
|
import wedding11 from "../assets/images/wedding11.jpg";
|
||||||
|
import wedding12 from "../assets/images/wedding12.avif";
|
||||||
|
|
||||||
|
|
||||||
|
const HomePage = () => {
|
||||||
|
const images = [
|
||||||
|
{
|
||||||
|
src: wedding1,
|
||||||
|
alt: "Wedding Image",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: wedding2,
|
||||||
|
alt: "Couple",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src:wedding3,
|
||||||
|
alt: "Engagement",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: wedding4,
|
||||||
|
alt: "Wedding Image",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: wedding5,
|
||||||
|
alt: "Couple",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: wedding6,
|
||||||
|
alt: "Engagement",
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
src: wedding7,
|
||||||
|
alt: "Wedding Image",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: wedding8,
|
||||||
|
alt: "Couple",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: wedding9,
|
||||||
|
alt: "Engagement",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
src: wedding10,
|
||||||
|
alt: "Engagement",
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="">
|
||||||
|
<ThreeDMarquee images={images} cols = {4} />
|
||||||
|
<AppPromoteSection/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default HomePage;
|
||||||
10
src/pages/LandingPage.jsx
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
|
||||||
|
const LandingPage = () => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default LandingPage
|
||||||
19
src/routes/AppRoutes.jsx
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import { Route, Routes } from 'react-router-dom';
|
||||||
|
import UserRoutes from './UserRoutes';
|
||||||
|
import PublicRoutes from './PublicRoutes';
|
||||||
|
|
||||||
|
|
||||||
|
const AppRoutes = () => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{/* Wrap UserRoutes inside AuthProvider separately */}
|
||||||
|
<Routes>
|
||||||
|
{UserRoutes()}
|
||||||
|
{PublicRoutes()}
|
||||||
|
|
||||||
|
</Routes>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AppRoutes;
|
||||||
15
src/routes/PublicRoutes.jsx
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { Route } from "react-router-dom";
|
||||||
|
import HomePage from "../pages/HomePage";
|
||||||
|
import LandingLayout from "../layout/LandingLayout";
|
||||||
|
const PublicRoutes = () => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Route element={<LandingLayout />}>
|
||||||
|
<Route path="/" element={<HomePage />} />
|
||||||
|
</Route>
|
||||||
|
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PublicRoutes
|
||||||
13
src/routes/UserRoutes.jsx
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { Route, useNavigate } from "react-router-dom";
|
||||||
|
const UserRoutes = () => {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{/* <Route element={<MasterLayout />}>
|
||||||
|
<Route path="/" element={<HomePage />} />
|
||||||
|
</Route> */}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default UserRoutes
|
||||||
17
src/theme.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
|
||||||
|
import { createTheme, ThemeProvider } from "@mui/material/styles";
|
||||||
|
|
||||||
|
const theme = createTheme({
|
||||||
|
palette: {
|
||||||
|
primary: {
|
||||||
|
main: "#034E08", // Indigo
|
||||||
|
contrastText: "#ffffff",
|
||||||
|
},
|
||||||
|
secondary: {
|
||||||
|
main: "#A70710", // Pink
|
||||||
|
contrastText: "#ffffff",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default theme;
|
||||||
@ -1,7 +1,13 @@
|
|||||||
import { defineConfig } from 'vite'
|
import { defineConfig } from 'vite'
|
||||||
import react from '@vitejs/plugin-react'
|
import react from '@vitejs/plugin-react'
|
||||||
|
import path from "path"
|
||||||
import tailwindcss from '@tailwindcss/vite'
|
import tailwindcss from '@tailwindcss/vite'
|
||||||
// https://vite.dev/config/
|
// https://vite.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [react(), tailwindcss(),],
|
plugins: [react(), tailwindcss(),],
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
"@": path.resolve(__dirname, "src"),
|
||||||
|
},
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|||||||