431 lines
14 KiB
JavaScript
431 lines
14 KiB
JavaScript
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 Tooltip from "@mui/material/Tooltip";
|
|
import MenuIcon from "@mui/icons-material/Menu";
|
|
import CloseIcon from "@mui/icons-material/Close";
|
|
import Divider from "@mui/material/Divider";
|
|
import Modal from "@mui/material/Modal";
|
|
import Button from "@mui/material/Button";
|
|
import LazyImage from "./LazyImage";
|
|
import Logo from "../../assets/images/logo.png";
|
|
import { useNavigate } from "react-router-dom";
|
|
import { useState, useRef, useEffect } from "react";
|
|
import { useTheme, useMediaQuery, ListItemIcon } from "@mui/material";
|
|
import { Home, Users, Heart, MessageCircle, Search, Bell } from "lucide-react";
|
|
|
|
const NAV_LINKS = [
|
|
{ label: "Home", path: "/" },
|
|
{ label: "Matches", path: "/matches" },
|
|
{ label: "Interest", path: "/interest" },
|
|
{ label: "Messages", path: "/chat" },
|
|
{ label: "Search", path: "/matches" },
|
|
{ label: "Notifications", path: "/notifications" }
|
|
];
|
|
|
|
const PROFILE_MENU = [
|
|
{ label: "Dashboard", path: "/dashboard-home" },
|
|
{ label: "Profile", path: "/profile" },
|
|
{ label: "Subscription", path: "/subscription-plan" },
|
|
{ label: "Subscription History", path: "/subscription-history" },
|
|
{ label: "Change Password", path: "/change-password" },
|
|
{ label: "View Reports", path: "/block-report-profilelist" },
|
|
{ label: "Blocked Users", path: "/block-report-profilelist" }
|
|
];
|
|
|
|
const ACCOUNT_SETTINGS = [
|
|
{ label: "Privacy Settings", path: "/account-settings" },
|
|
{ label: "Privacy Policy", path: "/privacy-policy" },
|
|
{ label: "Terms & Conditions", path: "/terms" },
|
|
{ label: "Contact Us", path: "/contact" },
|
|
{ label: "Be Safe Online", path: "/safe-online" },
|
|
{ label: "Delete Account", action: "delete" },
|
|
{ label: "Logout", action: "logout" }
|
|
];
|
|
|
|
const SparkleNavbar = ({ items, color = "#0fec1eff", onItemClick }) => {
|
|
const [activeIndex, setActiveIndex] = useState(0);
|
|
const [indicatorStyle, setIndicatorStyle] = useState({});
|
|
const [isAnimating, setIsAnimating] = useState(false);
|
|
const navRef = useRef(null);
|
|
const buttonRefs = useRef([]);
|
|
|
|
useEffect(() => {
|
|
updateIndicator(activeIndex);
|
|
}, []);
|
|
|
|
const updateIndicator = (index) => {
|
|
const button = buttonRefs.current[index];
|
|
if (button && navRef.current) {
|
|
const navRect = navRef.current.getBoundingClientRect();
|
|
const btnRect = button.getBoundingClientRect();
|
|
setIndicatorStyle({
|
|
left: btnRect.left - navRect.left + btnRect.width / 2 - 18,
|
|
opacity: 1
|
|
});
|
|
}
|
|
};
|
|
|
|
const handleClick = (index) => {
|
|
if (index === activeIndex || isAnimating) return;
|
|
setIsAnimating(true);
|
|
const newButton = buttonRefs.current[index];
|
|
|
|
if (newButton && navRef.current) {
|
|
const navRect = navRef.current.getBoundingClientRect();
|
|
const newRect = newButton.getBoundingClientRect();
|
|
|
|
setIndicatorStyle(prev => ({
|
|
...prev,
|
|
left: newRect.left - navRect.left + newRect.width / 2 - 18,
|
|
}));
|
|
|
|
setTimeout(() => {
|
|
setActiveIndex(index);
|
|
setIsAnimating(false);
|
|
if (onItemClick) onItemClick(items[index], index);
|
|
}, 300);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<nav ref={navRef} className="relative flex items-center gap-8 px-6 py-4">
|
|
{items.map((item, index) => (
|
|
<button
|
|
key={item}
|
|
ref={el => buttonRefs.current[index] = el}
|
|
onClick={() => handleClick(index)}
|
|
className={`cursor-pointer relative uppercase text-sm font-medium transition-all duration-300 pb-2 ${
|
|
activeIndex === index ? 'text-black' : 'text-gray-900 hover:text-gray-600'
|
|
}`}
|
|
style={{
|
|
// textShadow: activeIndex === index
|
|
// ? `0 0 10px ${color}, 0 0 20px ${color}, 0 0 30px ${color}`
|
|
// : 'none'
|
|
}}
|
|
>
|
|
{item}
|
|
</button>
|
|
))}
|
|
|
|
<div
|
|
className="absolute bottom-3 h-[3px] w-9 rounded-full transition-all duration-300 ease-out"
|
|
style={{
|
|
left: indicatorStyle.left,
|
|
opacity: indicatorStyle.opacity,
|
|
backgroundColor: color,
|
|
boxShadow: `0 0 10px ${color}, 0 0 20px ${color}, 0 0 30px ${color}, 0 0 40px ${color}`,
|
|
}}
|
|
/>
|
|
</nav>
|
|
);
|
|
};
|
|
|
|
const ProfileHeader = () => {
|
|
const navigate = useNavigate();
|
|
const [mobileDrawerOpen, setMobileDrawerOpen] = useState(false);
|
|
const [profileDrawerOpen, setProfileDrawerOpen] = useState(false);
|
|
const [deleteModalOpen, setDeleteModalOpen] = useState(false);
|
|
const [logoutModalOpen, setLogoutModalOpen] = useState(false);
|
|
|
|
const theme = useTheme();
|
|
const isDesktop = useMediaQuery(theme.breakpoints.up("md"));
|
|
|
|
const toggleMobileDrawer = (open) => () => setMobileDrawerOpen(open);
|
|
const toggleProfileDrawer = (open) => () => setProfileDrawerOpen(open);
|
|
|
|
const [selectedItem, setSelectedItem] = useState("Home");
|
|
|
|
const handleMenuClick = (item) => {
|
|
if (item.action === "delete") {
|
|
setDeleteModalOpen(true);
|
|
setProfileDrawerOpen(false);
|
|
} else if (item.action === "logout") {
|
|
setLogoutModalOpen(true);
|
|
setProfileDrawerOpen(false);
|
|
} else if (item.path) {
|
|
navigate(item.path);
|
|
setProfileDrawerOpen(false);
|
|
}
|
|
};
|
|
|
|
const handleDeleteAccount = () => {
|
|
// Add your delete account logic here
|
|
console.log("Account deleted");
|
|
setDeleteModalOpen(false);
|
|
navigate("/");
|
|
};
|
|
|
|
const handleLogout = () => {
|
|
// Add your logout logic here
|
|
console.log("Logged out");
|
|
setLogoutModalOpen(false);
|
|
navigate("/login");
|
|
};
|
|
|
|
const modalStyle = {
|
|
position: 'absolute',
|
|
top: '50%',
|
|
left: '50%',
|
|
transform: 'translate(-50%, -50%)',
|
|
width: isDesktop ? 400 : '90%',
|
|
bgcolor: 'background.paper',
|
|
borderRadius: 2,
|
|
boxShadow: 24,
|
|
p: 4,
|
|
};
|
|
|
|
const getNavIcon = (index) => {
|
|
const icons = [Home, Users, Heart, MessageCircle, Search, Bell];
|
|
const IconComponent = icons[index % icons.length];
|
|
return <IconComponent size={20} />;
|
|
};
|
|
|
|
const ProfileDrawerContent = (
|
|
<Box sx={{ width: isDesktop ? 300 : 250 }}>
|
|
<Box
|
|
sx={{
|
|
p: 2,
|
|
display: "flex",
|
|
justifyContent: "space-between",
|
|
alignItems: "center",
|
|
}}
|
|
>
|
|
<Typography variant="h6">Account</Typography>
|
|
{!isDesktop && (
|
|
<IconButton onClick={toggleProfileDrawer(false)}>
|
|
<CloseIcon />
|
|
</IconButton>
|
|
)}
|
|
</Box>
|
|
|
|
<Divider />
|
|
|
|
<List>
|
|
{PROFILE_MENU.map((item) => (
|
|
<ListItem key={item.label} disablePadding>
|
|
<ListItemButton onClick={() => handleMenuClick(item)}>
|
|
<ListItemText primary={item.label} />
|
|
</ListItemButton>
|
|
</ListItem>
|
|
))}
|
|
</List>
|
|
|
|
<Typography sx={{ px: 2, py: 1, fontSize: "14px", opacity: 0.6 }}>
|
|
Account Settings
|
|
</Typography>
|
|
|
|
<List>
|
|
{ACCOUNT_SETTINGS.map((item) => (
|
|
<ListItem key={item.label} disablePadding>
|
|
<ListItemButton onClick={() => handleMenuClick(item)}>
|
|
<ListItemText primary={item.label} />
|
|
</ListItemButton>
|
|
</ListItem>
|
|
))}
|
|
</List>
|
|
</Box>
|
|
);
|
|
|
|
const MobileDrawerMenu = (
|
|
<Box sx={{ width: 250 }}>
|
|
<Box sx={{ p: 2, display: "flex", justifyContent: "space-between" }}>
|
|
<Typography variant="h6">Menu</Typography>
|
|
<IconButton onClick={toggleMobileDrawer(false)}>
|
|
<CloseIcon />
|
|
</IconButton>
|
|
</Box>
|
|
|
|
<Divider />
|
|
|
|
<List>
|
|
{NAV_LINKS.map(({ label, path }, index) => (
|
|
<ListItem key={label} disablePadding>
|
|
<ListItemButton
|
|
onClick={() => {
|
|
navigate(path);
|
|
toggleMobileDrawer(false)();
|
|
}}
|
|
>
|
|
<ListItemIcon>
|
|
{getNavIcon(index)}
|
|
</ListItemIcon>
|
|
<ListItemText primary={label} />
|
|
</ListItemButton>
|
|
</ListItem>
|
|
))}
|
|
</List>
|
|
</Box>
|
|
);
|
|
|
|
return (
|
|
<>
|
|
<AppBar position="sticky" sx={{ backgroundColor: "#fff" }}>
|
|
<Container maxWidth="xl">
|
|
<Toolbar disableGutters>
|
|
<Box sx={{ display: { xs: "none", md: "flex" }, mr: 1 }}>
|
|
<LazyImage
|
|
src={Logo}
|
|
className="w-full h-[70px] my-2 rounded-lg object-cover cursor-pointer"
|
|
onClick={() => navigate("/")}
|
|
/>
|
|
</Box>
|
|
|
|
<Box sx={{ flexGrow: 1, display: { xs: "flex", md: "none" } }}>
|
|
<IconButton onClick={toggleMobileDrawer(true)}>
|
|
<MenuIcon />
|
|
</IconButton>
|
|
</Box>
|
|
|
|
<Box
|
|
sx={{ display: { xs: "flex", md: "none" }, flexGrow: 1 }}
|
|
onClick={() => navigate("/")}
|
|
>
|
|
<LazyImage
|
|
src={Logo}
|
|
className="w-full h-[50px] rounded-lg object-cover"
|
|
/>
|
|
</Box>
|
|
|
|
<Box sx={{ flexGrow: 1, display: { xs: "none", md: "flex" } }}>
|
|
<SparkleNavbar
|
|
items={NAV_LINKS.map(link => link.label)}
|
|
color="#034E08"
|
|
onItemClick={(item) => {
|
|
setSelectedItem(item);
|
|
const link = NAV_LINKS.find(l => l.label === item);
|
|
if (link) navigate(link.path);
|
|
}}
|
|
/>
|
|
</Box>
|
|
|
|
<Box sx={{ flexGrow: 0 }}>
|
|
<Tooltip title="Account Menu">
|
|
<IconButton onClick={toggleProfileDrawer(true)}>
|
|
<Avatar src="/static/images/avatar/2.jpg" />
|
|
</IconButton>
|
|
</Tooltip>
|
|
</Box>
|
|
</Toolbar>
|
|
</Container>
|
|
</AppBar>
|
|
|
|
<SwipeableDrawer
|
|
anchor="left"
|
|
open={mobileDrawerOpen}
|
|
onOpen={toggleMobileDrawer(true)}
|
|
onClose={toggleMobileDrawer(false)}
|
|
>
|
|
{MobileDrawerMenu}
|
|
</SwipeableDrawer>
|
|
|
|
<SwipeableDrawer
|
|
anchor="right"
|
|
open={profileDrawerOpen}
|
|
onOpen={toggleProfileDrawer(true)}
|
|
onClose={toggleProfileDrawer(false)}
|
|
>
|
|
{ProfileDrawerContent}
|
|
</SwipeableDrawer>
|
|
|
|
{/* Delete Account Modal */}
|
|
<Modal
|
|
open={deleteModalOpen}
|
|
onClose={() => setDeleteModalOpen(false)}
|
|
aria-labelledby="delete-modal-title"
|
|
>
|
|
<Box sx={modalStyle}>
|
|
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 2 }}>
|
|
<Typography id="delete-modal-title" variant="h6" component="h2">
|
|
Delete Account
|
|
</Typography>
|
|
<IconButton onClick={() => setDeleteModalOpen(false)} size="small">
|
|
<CloseIcon />
|
|
</IconButton>
|
|
</Box>
|
|
<Typography sx={{ mb: 3 }}>
|
|
Are you sure you want to delete your account? This action cannot be undone.
|
|
</Typography>
|
|
<Box sx={{ display: 'flex', gap: 2, justifyContent: 'flex-end' }}>
|
|
<Button
|
|
variant="outlined"
|
|
onClick={() => setDeleteModalOpen(false)}
|
|
sx={{
|
|
color: '#4caf50',
|
|
borderColor: '#4caf50',
|
|
'&:hover': { borderColor: '#45a049', backgroundColor: 'rgba(76, 175, 80, 0.04)' }
|
|
}}
|
|
>
|
|
Cancel
|
|
</Button>
|
|
<Button
|
|
variant="contained"
|
|
onClick={handleDeleteAccount}
|
|
sx={{
|
|
bgcolor: '#f44336',
|
|
'&:hover': { bgcolor: '#d32f2f' }
|
|
}}
|
|
>
|
|
Delete
|
|
</Button>
|
|
</Box>
|
|
</Box>
|
|
</Modal>
|
|
|
|
{/* Logout Modal */}
|
|
<Modal
|
|
open={logoutModalOpen}
|
|
onClose={() => setLogoutModalOpen(false)}
|
|
aria-labelledby="logout-modal-title"
|
|
>
|
|
<Box sx={modalStyle}>
|
|
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 2 }}>
|
|
<Typography id="logout-modal-title" variant="h6" component="h2">
|
|
Logout
|
|
</Typography>
|
|
<IconButton onClick={() => setLogoutModalOpen(false)} size="small">
|
|
<CloseIcon />
|
|
</IconButton>
|
|
</Box>
|
|
<Typography sx={{ mb: 3 }}>
|
|
Are you sure you want to logout?
|
|
</Typography>
|
|
<Box sx={{ display: 'flex', gap: 2, justifyContent: 'flex-end' }}>
|
|
<Button
|
|
variant="outlined"
|
|
onClick={() => setLogoutModalOpen(false)}
|
|
sx={{
|
|
color: '#4caf50',
|
|
borderColor: '#4caf50',
|
|
'&:hover': { borderColor: '#45a049', backgroundColor: 'rgba(76, 175, 80, 0.04)' }
|
|
}}
|
|
>
|
|
Cancel
|
|
</Button>
|
|
<Button
|
|
variant="contained"
|
|
onClick={handleLogout}
|
|
sx={{
|
|
bgcolor: '#f44336',
|
|
'&:hover': { bgcolor: '#d32f2f' }
|
|
}}
|
|
>
|
|
Logout
|
|
</Button>
|
|
</Box>
|
|
</Box>
|
|
</Modal>
|
|
</>
|
|
);
|
|
};
|
|
|
|
export default ProfileHeader; |