profile pages done

This commit is contained in:
meena committed 2025-11-25 21:21:58 +05:30
1 parent 221ea3057b
commit 8a670b461a
38 files changed
+4402 -487

No files matched your search

+347
View File
@@ -0,0 +1,347 @@
import * as React from 'react';
import PropTypes from 'prop-types';
import Tabs from '@mui/material/Tabs';
import Tab from '@mui/material/Tab';
import Typography from '@mui/material/Typography';
import Box from '@mui/material/Box';
import Switch from '@mui/material/Switch';
import useMediaQuery from '@mui/material/useMediaQuery';
import { useTheme } from '@mui/material/styles';
import { Phone, MessageSquare, Shield, Bell, UserCheck, ChevronLeft } from 'lucide-react';
function TabPanel(props) {
const { children, value, index, ...other } = props;
return (
<div
role="tabpanel"
hidden={value !== index}
id={`tabpanel-${index}`}
aria-labelledby={`tab-${index}`}
{...other}
style={{ width: '100%' }}
>
{value === index && (
<Box sx={{ p: 0 }}>
{children}
</Box>
)}
</div>
);
}
TabPanel.propTypes = {
children: PropTypes.node,
index: PropTypes.number.isRequired,
value: PropTypes.number.isRequired,
};
function a11yProps(index, isMobile) {
return {
id: `${isMobile ? 'horizontal' : 'vertical'}-tab-${index}`,
'aria-controls': `${isMobile ? 'horizontal' : 'vertical'}-tabpanel-${index}`,
};
}
const SettingItem = ({ title, description, enabled, onToggle }) => (
<Box sx={{ py: 2, borderBottom: '1px solid #e5e7eb', '&:last-child': { borderBottom: 'none' } }}>
<Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', mb: 1 }}>
<Typography variant="body1" sx={{ fontWeight: 'bold', color: '#111827', fontSize: { xs: '0.875rem', sm: '1rem' } }}>
{title}
</Typography>
<Switch
checked={enabled}
onChange={onToggle}
sx={{
'& .MuiSwitch-switchBase.Mui-checked': {
color: '#fff',
},
'& .MuiSwitch-switchBase.Mui-checked + .MuiSwitch-track': {
backgroundColor: '#16a34a',
},
}}
/>
</Box>
<Typography variant="body2" sx={{ color: '#6b7280', lineHeight: 1.6, fontSize: { xs: '0.75rem', sm: '0.875rem' } }}>
{description}
</Typography>
</Box>
);
const TabContent = ({ title, settings, states, onToggle }) => (
<Box sx={{borderRadius:"10px", flex: 1, bgcolor: '#ebf7ff', height: { xs: 'auto', md: '100vh' }, overflow: 'auto', width:"100%", maxWidth:"600px", margin:"0 auto" }}>
<Box sx={{
position: 'sticky',
top: 0,
bgcolor: '#034E08',
borderBottom: '1px solid #e5e7eb',
px: { xs: 2, sm: 3 },
py: 2,
display: 'flex',
alignItems: 'center',
gap: 2,
zIndex: 10,
borderRadius:"10px",
}}>
<Typography variant="h6" sx={{ fontWeight: 'bold', color: '#fefefeff', fontSize: { xs: '1rem', sm: '1.25rem' } }}>
{title}
</Typography>
</Box>
<Box sx={{ px: { xs: 2, sm: 3 }, py: 2 }}>
{settings.map((setting, index) => (
<SettingItem
key={index}
title={setting.title}
description={setting.description}
enabled={states[setting.key]}
onToggle={() => onToggle(setting.key)}
/>
))}
</Box>
</Box>
);
export default function AccountSettingPage() {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down('md'));
const [value, setValue] = React.useState(0);
const [settings, setSettings] = React.useState({
phoneVisibility: true,
chatAlertsNotification: true,
chatProtection: true,
protectProfilePhoto: true,
callProtection: true,
matchAlerts: true,
profileViews: false,
messagePermission: true,
blockUnverified: false,
});
const handleChange = (event, newValue) => {
setValue(newValue);
};
const toggleSetting = (key) => {
setSettings(prev => ({ ...prev, [key]: !prev[key] }));
};
const tabs = [
{
id: 0,
label: 'Phone Number',
fullLabel: 'Phone Number Visibility Controls',
icon: <Phone size={20} />,
settings: [
{
key: 'phoneVisibility',
title: 'Phone Number Visibility',
description: 'You can control phone number visibility through temporary and permanent methods on your phone. For a single call, dial *67 before the number.',
},
],
},
{
id: 1,
label: 'Chat Alerts',
fullLabel: 'Chat Alerts',
icon: <MessageSquare size={20} />,
settings: [
{
key: 'chatAlertsNotification',
title: 'Chat Alerts Notification',
description: 'Matrimony sites send chat alerts with standard, automated content to notify you of new interactions related to your profile.',
},
{
key: 'chatProtection',
title: 'Chat Protection',
description: 'To protect yourself while using matrimonial sites, the primary "chat protection content" is restricting the personal and sensitive information you share both on your public profile and in early conversations.',
},
],
},
{
id: 2,
label: 'Profile',
fullLabel: 'Profile Protection',
icon: <Shield size={20} />,
settings: [
{
key: 'protectProfilePhoto',
title: 'Protect Profile photo to all',
description: 'The photograph privacy settings options are available in the \'My Photos\' section of the \'My Profile\' page.',
},
{
key: 'callProtection',
title: 'Call Protection',
description: 'To implement call protection, most major matrimony sites offer built-in privacy features that allow you to control who sees your contact details and photos.',
},
],
},
{
id: 3,
label: 'Match Alerts',
fullLabel: 'Match Alerts Preferences',
icon: <Bell size={20} />,
settings: [
{
key: 'matchAlerts',
title: 'Match Alert Notifications',
description: 'Receive notifications when new profiles match your preferences and requirements.',
},
{
key: 'profileViews',
title: 'Profile View Alerts',
description: 'Get notified when someone views your profile or shows interest in connecting with you.',
},
],
},
{
id: 4,
label: 'Messages',
fullLabel: 'Who Can Message Me?',
icon: <UserCheck size={20} />,
settings: [
{
key: 'messagePermission',
title: 'Message Permissions',
description: 'Control who can send you messages. You can restrict messages to only verified profiles or profiles that match your preferences.',
},
{
key: 'blockUnverified',
title: 'Block Unverified Profiles',
description: 'Automatically block messages from profiles that haven\'t completed verification process.',
},
],
},
];
return (
<Box sx={{ flexGrow: 1,
display: 'flex', flexDirection: { xs: 'column', md: 'row' }, gap:"20px",
minHeight: '90vh', marginTop:"50px", marginBottom:"50px" }}>
{/* Desktop: Vertical Sidebar */}
{!isMobile && (
<Box sx={{ width: 300, borderRadius:"10px" ,background:"#ffeac9", borderRight: '1px solid #e5e7eb', display: { xs: 'none', md: 'block' } }}>
<Box sx={{
position: 'sticky',
top: 0,
bgcolor: '#ffeac9',
borderBottom: '1px solid #e5e7eb',
px: 3,
py: 2,
zIndex: 10,
borderRadius:"10px" ,
}}>
<Typography variant="h5" sx={{ fontWeight: 'bold', color: '#111827' }}>
Settings
</Typography>
</Box>
<Tabs
orientation="vertical"
variant="scrollable"
value={value}
onChange={handleChange}
aria-label="Settings tabs"
sx={{
'& .MuiTabs-indicator': {
left: 0,
width: 4,
backgroundColor: '#A70710',
},
'& .MuiTab-root': {
// alignItems: 'flex-start',
// textAlign: 'left',
justifyContent:"left",
minHeight: 64,
px: 3,
py: 2,
textTransform: 'none',
fontSize: '0.875rem',
fontWeight: 500,
color: '#374151',
'&.Mui-selected': {
color: '#A70710',
backgroundColor: '#fff7ed',
},
'&:hover': {
backgroundColor: '#f9fafb',
},
},
}}
>
{tabs.map((tab, index) => (
<Tab
key={tab.id}
icon={tab.icon}
iconPosition="start"
label={tab.fullLabel}
{...a11yProps(index, false)}
/>
))}
</Tabs>
</Box>
)}
{/* Mobile: Horizontal Tabs */}
{isMobile && (
<Box sx={{ bgcolor: 'white', borderBottom: '1px solid #e5e7eb', display: { xs: 'block', md: 'none' } }}>
<Box sx={{ px: 2, py: 2 }}>
<Typography variant="h6" sx={{ fontWeight: 'bold', color: '#111827' }}>
Settings
</Typography>
</Box>
<Tabs
value={value}
onChange={handleChange}
variant="scrollable"
scrollButtons="auto"
aria-label="Settings tabs"
sx={{
'& .MuiTabs-indicator': {
backgroundColor: '#A70710',
height: 3,
},
'& .MuiTab-root': {
textTransform: 'none',
fontSize: '0.75rem',
fontWeight: 500,
minWidth: 'auto',
px: 2,
py: 1.5,
color: '#ffffffff',
'&.Mui-selected': {
color: '#A70710',
},
},
'& .MuiTabs-flexContainer': {
gap: 1,
},
}}
>
{tabs.map((tab, index) => (
<Tab
key={tab.id}
icon={tab.icon}
iconPosition="start"
label={tab.label}
{...a11yProps(index, true)}
/>
))}
</Tabs>
</Box>
)}
{/* Tab Content */}
<Box sx={{ flex: 1, width: '100%' }}>
{tabs.map((tab, index) => (
<TabPanel key={tab.id} value={value} index={index}>
<TabContent
title={tab.fullLabel}
settings={tab.settings}
states={settings}
onToggle={toggleSetting}
/>
</TabPanel>
))}
</Box>
</Box>
);
}
+340
View File
@@ -0,0 +1,340 @@
import React, { useState } from 'react';
import { Tabs, Tab, Box, Chip } from '@mui/material';
import { CheckCircle, Phone, ExpandMore } from '@mui/icons-material';
import { ChevronDown } from 'lucide-react';
const BlockedProfile = ({ profile }) => (
<div className="bg-white border border-1 border-red-100 rounded-lg shadow-sm p-6 mb-4">
<div className="flex items-start gap-4">
<div className="relative flex-shrink-0">
<img
src={profile.image}
alt={profile.name}
className="w-32 h-32 rounded-2xl object-cover border-2 border-[#A70710]"
/>
<button className="w-8 h-8 flex justify-center items-center absolute bottom-0 right-0 bg-[#A70710] text-white rounded-full shadow-lg">
<Phone className="w-4 h-4" />
</button>
</div>
<div className="flex-1">
<div className="flex items-center gap-2 mb-1">
<CheckCircle className="text-green-500 w-5 h-5" />
<span className="text-green-500 font-medium">Verified</span>
</div>
<h2 className="text-2xl font-bold text-gray-900 mb-1">{profile.name}</h2>
<p className="text-gray-500 text-sm mb-3">{profile.id} | Profile Created by Parent</p>
<div className="space-y-1 text-gray-700">
<p className="font-medium">{profile.age} yrs, {profile.height}, {profile.language},</p>
<p className="font-medium">{profile.location},</p>
<p className="font-medium">{profile.education}, {profile.occupation}, ₹ {profile.income}, {profile.state}, India</p>
</div>
</div>
</div>
<div className="mt-6 flex items-center justify-between border-t border-[#A70710] pt-4">
<p className="text-gray-600">You have blocked this profile</p>
<button className="bg-[#A70710] hover:bg-red-600 text-white px-8 py-2 rounded-full font-medium transition-colors">
UnBlock
</button>
</div>
</div>
);
const ReportedProfile = ({ profile, onViewReason }) => {
return (
<div className="bg-white rounded-lg shadow-md p-4 mb-1 border border-1 border-red-100 hover:shadow-lg transition-shadow">
<div className="flex flex-col sm:flex-row items-start gap-4">
<div className='overflow-hidden w-[100%] h-[100%] max-w-50 max-h-45 rounded-lg flex-shrink-0'>
<img
src={profile.image}
alt={profile.name}
className="w-full h-full object-cover "
/>
</div>
<div className="flex-1 w-full">
<h3 className="text-lg font-bold text-gray-900 mb-1">{profile.name}</h3>
<p className="text-sm text-gray-500 mb-2">
ID : {profile.id} <span className="text-xs ml-1">Last seen {profile.lastSeen}</span>
</p>
<div className="space-y-1.5 text-sm">
<div className="flex items-center gap-2 flex-wrap">
<span className="text-gray-400">•</span>
<span className="text-gray-600">Profile created by Parent</span>
<span className="text-gray-400">•</span>
<span className="text-gray-600">{profile.age} yrs</span>
</div>
<div className="flex items-center gap-2">
<span className="text-gray-400">•</span>
<span className="text-gray-600">{profile.caste}</span>
</div>
<div className="flex items-center gap-2 flex-wrap">
<span className="text-gray-400">•</span>
<span className="text-gray-600">{profile.occupation}</span>
<span className="text-gray-400">•</span>
<span className="text-gray-600">{profile.location}</span>
</div>
</div>
<button
onClick={() => onViewReason(profile)}
className="flex items-center gap-1 text-red-500 hover:text-red-600 mt-3 text-sm font-medium transition-colors"
>
View Report Reason
<ChevronDown className="w-4 h-4" />
</button>
</div>
</div>
</div>
);
};
const ReportReasonModal = ({ profile, onClose }) => {
if (!profile) return null;
return (
<div style={{backdropFilter:"blur(5px)"}} className="fixed inset-0 bg-[#0000006b] bg-opacity-50 flex items-center justify-center z-50 p-4 animate-fadeIn">
<div className="bg-white rounded-lg shadow-2xl max-w-md w-full p-6 animate-slideUp">
<div className="flex items-start gap-4 mb-4">
<img
src={profile.image}
alt={profile.name}
className="w-16 h-20 rounded-lg object-cover flex-shrink-0"
/>
<div>
<h3 className="text-lg font-bold text-gray-900">{profile.name}</h3>
<p className="text-sm text-gray-500">ID : {profile.id}</p>
</div>
</div>
<div className="border-t pt-4">
<h4 className="font-bold text-gray-900 mb-3">Reason For Report</h4>
<p className="text-sm text-gray-600 leading-relaxed bg-gray-50 p-3 rounded-lg mb-4">
{profile.reportReason}
</p>
</div>
<div className='w-full flex justify-center'>
<button
onClick={onClose}
className=" w-[fit-content] px-8 rounded-full bg-green-500 hover:bg-red-600 text-white py-2.5 font-medium transition-colors"
>
Close
</button>
</div>
</div>
</div>
);
};
function BlockedProfileListPage() {
const [activeTab, setActiveTab] = useState(0);
const [selectedReport, setSelectedReport] = useState(null);
const blockedProfiles = [
{
id: 'M6075010',
name: 'Aravindh Vinayak M',
age: 37,
height: "5'6\"",
language: 'Tamil',
location: 'Karuneegar',
education: 'BE',
occupation: 'Clerk',
income: '9 - 10 Lakhs',
state: 'Tamil Nadu',
image: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=300&h=300&fit=crop'
},
{
id: 'M6075010',
name: 'Aravindh Vinayak M',
age: 37,
height: "5'6\"",
language: 'Tamil',
location: 'Karuneegar',
education: 'BE',
occupation: 'Clerk',
income: '9 - 10 Lakhs',
state: 'Tamil Nadu',
image: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=300&h=300&fit=crop'
},
{
id: 'M6075010',
name: 'Aravindh Vinayak M',
age: 37,
height: "5'6\"",
language: 'Tamil',
location: 'Karuneegar',
education: 'BE',
occupation: 'Clerk',
income: '9 - 10 Lakhs',
state: 'Tamil Nadu',
image: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=300&h=300&fit=crop'
},
{
id: 'M6075010',
name: 'Aravindh Vinayak M',
age: 37,
height: "5'6\"",
language: 'Tamil',
location: 'Karuneegar',
education: 'BE',
occupation: 'Clerk',
income: '9 - 10 Lakhs',
state: 'Tamil Nadu',
image: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=300&h=300&fit=crop'
}
];
const reportedProfiles = [
{
id: 'TK52586A',
name: 'Pavilash . P',
age: 23,
lastSeen: 'Nov 25',
caste: 'Agamudayar / Arcot / Thuluva vellala',
occupation: 'Engineer-non – IT',
location: 'Chennai',
image: 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=300&h=400&fit=crop',
showReason: true,
reportReason: 'It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout.'
},
{
id: 'TK52586A',
name: 'Pavilash . P',
age: 23,
lastSeen: 'Nov 25',
caste: 'Agamudayar / Arcot / Thuluva vellala',
occupation: 'Engineer-non – IT',
location: 'Chennai',
image: 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=300&h=400&fit=crop',
showReason: true,
reportReason: 'It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout.'
},
{
id: 'TK52586A',
name: 'Pavilash . P',
age: 23,
lastSeen: 'Nov 25',
caste: 'Agamudayar / Arcot / Thuluva vellala',
occupation: 'Engineer-non – IT',
location: 'Chennai',
image: 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=300&h=400&fit=crop',
showReason: true,
reportReason: 'It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout.'
},
{
id: 'TK52586A',
name: 'Pavilash . P',
age: 23,
lastSeen: 'Nov 25',
caste: 'Agamudayar / Arcot / Thuluva vellala',
occupation: 'Engineer-non – IT',
location: 'Chennai',
image: 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=300&h=400&fit=crop',
showReason: true,
reportReason: 'It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout.'
}
];
const handleTabChange = (event, newValue) => {
setActiveTab(newValue);
};
return (
<div className=" py-4 md:py-8">
<div className="max-w-[1400px] mx-auto">
<h1 className="text-center text-[24px] font-bold text-green-900 mb-6">Blocked & Reported Profiles</h1>
<Box sx={{ mb: 3, width:"100%", maxWidth:"300px", marginRight:"auto", marginLeft:" auto" , marginBottom:"30px"}}>
<Tabs
value={activeTab}
onChange={handleTabChange}
sx={{
'& .MuiTab-root': {
textTransform: 'none',
fontSize: '1rem',
fontWeight: 600,
minWidth: 120,
},
'& .Mui-selected': {
color: '#fff',
background:"#A70710"
},
'& .MuiTabs-indicator': {
backgroundColor: '#A70710',
},
}}
>
<Tab label="Block List" />
<Tab label="Reported List" />
</Tabs>
</Box>
<div className="transition-all duration-300">
{activeTab === 0 && (
<div className='w-[100%] max-w-[1400px] mx-auto grid grid-cols-1 md:grid-cols-2 gap-2'>
{blockedProfiles.map((profile, index) => (
<BlockedProfile key={index} profile={profile} />
))}
</div>
)}
{activeTab === 1 && (
<div className='w-[100%] max-w-[1400px] mx-auto grid grid-cols-1 sm:grid-cols-2 md:grid-cols-2 gap-2'>
{reportedProfiles.map((profile, index) => (
<ReportedProfile
key={index}
profile={profile}
onViewReason={setSelectedReport}
/>
))}
</div>
)}
</div>
{/* Report Reason Modal */}
<ReportReasonModal
profile={selectedReport}
onClose={() => setSelectedReport(null)}
/>
</div>
<style jsx>{`
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes slideUp {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.animate-fadeIn {
animation: fadeIn 0.3s ease-out;
}
.animate-slideUp {
animation: slideUp 0.3s ease-out;
}
`}</style>
</div>
);
}
export default BlockedProfileListPage;
+416
View File
@@ -0,0 +1,416 @@
import * as React from "react";
import { useState } from "react";
import { Crown, Bookmark } from "lucide-react";
import Box from "@mui/material/Box";
import Tab from "@mui/material/Tab";
import TabContext from "@mui/lab/TabContext";
import TabList from "@mui/lab/TabList";
import TabPanel from "@mui/lab/TabPanel";
// Icons as inline SVG components
const CakeIcon = () => (
<svg className="w-4 h-4" viewBox="0 0 24 24" fill="currentColor">
<path d="M12 6c1.11 0 2-.9 2-2 0-.38-.1-.73-.29-1.03L12 0l-1.71 2.97c-.19.3-.29.65-.29 1.03 0 1.1.9 2 2 2zm4.6 9.99l-1.07-1.07-1.08 1.07c-1.3 1.3-3.58 1.31-4.89 0l-1.07-1.07-1.09 1.07C6.75 16.64 5.88 17 4.96 17c-.73 0-1.4-.23-1.96-.61V21c0 .55.45 1 1 1h16c.55 0 1-.45 1-1v-4.61c-.56.38-1.23.61-1.96.61-.92 0-1.79-.36-2.44-1.01zM18 9h-5V7h-2v2H6c-1.66 0-3 1.34-3 3v1.54c0 1.08.88 1.96 1.96 1.96.52 0 1.02-.2 1.38-.57l2.14-2.13 2.13 2.13c.74.74 2.03.74 2.77 0l2.14-2.13 2.13 2.13c.37.37.86.57 1.38.57 1.08 0 1.96-.88 1.96-1.96V12C21 10.34 19.66 9 18 9z" />
</svg>
);
const AccessibilityIcon = () => (
<svg className="w-4 h-4" viewBox="0 0 24 24" fill="currentColor">
<path d="M12 2c1.1 0 2 .9 2 2s-.9 2-2 2-2-.9-2-2 .9-2 2-2zm9 7h-6v13h-2v-6h-2v6H9V9H3V7h18v2z" />
</svg>
);
const GroupsIcon = () => (
<svg className="w-4 h-4" viewBox="0 0 24 24" fill="currentColor">
<path d="M12 12.75c1.63 0 3.07.39 4.24.9 1.08.48 1.76 1.56 1.76 2.73V18H6v-1.61c0-1.18.68-2.26 1.76-2.73 1.17-.52 2.61-.91 4.24-.91zM4 13c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm1.13 1.1c-.37-.06-.74-.1-1.13-.1-.99 0-1.93.21-2.78.58C.48 14.9 0 15.62 0 16.43V18h4.5v-1.61c0-.83.23-1.61.63-2.29zM20 13c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm4 3.43c0-.81-.48-1.53-1.22-1.85-.85-.37-1.79-.58-2.78-.58-.39 0-.76.04-1.13.1.4.68.63 1.46.63 2.29V18H24v-1.57zM12 6c1.66 0 3 1.34 3 3s-1.34 3-3 3-3-1.34-3-3 1.34-3 3-3z" />
</svg>
);
const SchoolIcon = () => (
<svg className="w-4 h-4" viewBox="0 0 24 24" fill="currentColor">
<path d="M5 13.18v4L12 21l7-3.82v-4L12 17l-7-3.82zM12 3L1 9l11 6 9-4.91V17h2V9L12 3z" />
</svg>
);
const LocationIcon = () => (
<svg className="w-4 h-4" viewBox="0 0 24 24" fill="currentColor">
<path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z" />
</svg>
);
// Profile Card Component
function ProfileCard({ profile,activeTab }) {
const [isLiked, setIsLiked] = useState(false);
return (
<div className="w-full rounded-[10px] shadow-xl overflow-hidden border border-green-200">
{/* Profile Image Section */}
<div className="relative">
{/* Premium Badge */}
{profile.isPremium && (
<div className="absolute top-4 left-4 z-10 bg-orange-500 rounded-full p-2 shadow-lg">
<Crown className="w-5 h-5 text-white" />
</div>
)}
{/* Shortlist Button */}
<button className="absolute top-4 right-4 z-10 bg-white rounded-full px-4 py-2 shadow-lg flex items-center space-x-2 hover:bg-gray-50 transition-colors">
<Bookmark className="w-4 h-4" />
<span className="text-[12px] font-medium">Shortlist</span>
</button>
<img
src={profile.image}
alt="Profile"
className="w-full h-80 object-cover"
/>
{/* White Gradient Overlay */}
<div
className="absolute bottom-0 left-0 right-0 h-35 pointer-events-none"
style={{
background:
"linear-gradient(rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.6) 40%, rgb(255, 255, 255) 100%)",
}}
></div>
{/* Profile Info Overlay */}
<div className="absolute bottom-0 left-0 right-0 p-6 text-gray-900">
<h1 className="text-[18px] text-green-900 font-bold mb-2">
{profile.name}
</h1>
<p className="text-[14px] text-gray-700 leading-relaxed">
Matrimony ID: {profile.matrimonyId}
</p>
</div>
</div>
{/* Profile Details */}
<div className="px-4 pt-2 pb-4 flex flex-col gap-2 bg-white">
<div className="flex items-center gap-4">
<div className="flex items-center gap-2">
<CakeIcon />
<span className="text-[14px] font-semibold text-gray-900">
Age: {profile.age}
</span>
</div>
<div className="flex items-center gap-2">
<AccessibilityIcon />
<span className="text-[14px] font-semibold text-gray-900">
Height: {profile.height}
</span>
</div>
</div>
<div className="flex items-center gap-2">
<GroupsIcon />
<span className="text-[14px] font-semibold text-gray-900">
{profile.religion}
</span>
</div>
<div className="flex items-center gap-2">
<SchoolIcon />
<span className="text-[14px] font-semibold text-gray-900">
{profile.education}
</span>
</div>
<div className="flex items-center gap-2">
<LocationIcon />
<span className="text-[14px] font-semibold text-gray-900">
{profile.location}
</span>
</div>
{/* Action Buttons */}
<div className="flex gap-3 my-2 justify-between">
{/* ❌ Cross button always visible */}
<button className="w-[60px] h-[60px] bg-[#A70710] hover:bg-red-300 text-white font-semibold rounded-full shadow-md hover:shadow-lg transition-all duration-300 flex items-center justify-center transform hover:scale-90">
<svg className="w-7 h-7" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
<path d="M18 6L6 18M6 6l12 12" strokeLinecap="round" strokeLinejoin="round" />
</svg>
</button>
{/* ❤️ Like Button → ONLY visible when tab = "2" (Sent Requests) */}
{activeTab === "2" && (
<button
className="w-[60px] h-[60px] bg-[#034E08] hover:bg-green-600 text-white font-semibold rounded-full shadow-lg hover:shadow-xl transition-all duration-300 transform hover:scale-105 flex items-center justify-center"
onClick={() => setIsLiked(!isLiked)}
>
{isLiked ? (
<svg className="w-7 h-7" viewBox="0 0 24 24" fill="currentColor">
<path d="M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5C2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3C19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z" fill="#EF4444" />
</svg>
) : (
<svg className="w-7 h-7" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
<path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67 10.94 4.61a5.5 5.5 0 0 0-7.78 7.78L4.22 13.45 12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z" strokeLinecap="round" strokeLinejoin="round" />
</svg>
)}
</button>
)}
</div>
</div>
</div>
);
}
// Main Component
export default function InterestSendPage() {
const [value, setValue] = useState("1");
const handleChange = (event, newValue) => {
setValue(newValue);
};
// Sample data for different categories
const profilesData = {
received: [
{
id: 1,
name: "Priya Sharma",
matrimonyId: "PS2847593",
age: 24,
height: "5.4",
religion: "Hindu / Brahmin",
education: "MBA / Marketing Manager",
location: "Mumbai",
image:
"https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=600&h=800&fit=crop",
isPremium: true,
},
{
id: 2,
name: "Ananya Reddy",
matrimonyId: "AR2847594",
age: 23,
height: "5.3",
religion: "Hindu / Reddy",
education: "B.Tech / Software Engineer",
location: "Hyderabad",
image:
"https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=600&h=800&fit=crop",
isPremium: false,
},
{
id: 3,
name: "Divya Patel",
matrimonyId: "DP2847595",
age: 25,
height: "5.5",
religion: "Hindu / Patel",
education: "CA / Chartered Accountant",
location: "Ahmedabad",
image:
"https://images.unsplash.com/photo-1534528741775-53994a69daeb?w=600&h=800&fit=crop",
isPremium: true,
},
],
sent: [
{
id: 4,
name: "Kavya Iyer",
matrimonyId: "KI2847596",
age: 22,
height: "5.2",
religion: "Hindu / Iyer",
education: "BCA / Data Analyst",
location: "Chennai",
image:
"https://images.unsplash.com/photo-1488426862026-3ee34a7d66df?w=600&h=800&fit=crop",
isPremium: true,
},
{
id: 5,
name: "Neha Singh",
matrimonyId: "NS2847597",
age: 26,
height: "5.6",
religion: "Hindu / Rajput",
education: "MD / Doctor",
location: "Delhi",
image:
"https://images.unsplash.com/photo-1524504388940-b1c1722653e1?w=600&h=800&fit=crop",
isPremium: false,
},
],
accepted: [
{
id: 6,
name: "Shreya Nair",
matrimonyId: "SN2847598",
age: 24,
height: "5.4",
religion: "Hindu / Nair",
education: "B.Sc / Nurse",
location: "Kochi",
image:
"https://images.unsplash.com/photo-1531123897727-8f129e1688ce?w=600&h=800&fit=crop",
isPremium: true,
},
{
id: 7,
name: "Meera Desai",
matrimonyId: "MD2847599",
age: 23,
height: "5.3",
religion: "Hindu / Desai",
education: "BBA / HR Manager",
location: "Pune",
image:
"https://images.unsplash.com/photo-1517841905240-472988babdf9?w=600&h=800&fit=crop",
isPremium: false,
},
{
id: 8,
name: "Riya Kumar",
matrimonyId: "RK2847600",
age: 25,
height: "5.5",
religion: "Hindu / Kumar",
education: "M.Tech / Project Manager",
location: "Bangalore",
image:
"https://images.unsplash.com/photo-1529626455594-4ff0802cfb7e?w=600&h=800&fit=crop",
isPremium: true,
},
],
rejected: [
{
id: 9,
name: "Sanya Joshi",
matrimonyId: "SJ2847601",
age: 27,
height: "5.7",
religion: "Hindu / Joshi",
education: "LLB / Lawyer",
location: "Nagpur",
image:
"https://images.unsplash.com/photo-1487412720507-e7ab37603c6f?w=600&h=800&fit=crop",
isPremium: false,
},
],
};
return (
<div className=" py-8 px-2">
<div className="max-w-7xl mx-auto">
{/* Header */}
<div className="text-center mb-8">
<h1 className="text-3xl md:text-4xl font-bold text-gray-800 mb-2">
Interest Management
</h1>
<p className="text-gray-600">
Manage your matrimony profile interests
</p>
</div>
{/* MUI Tabs */}
<Box sx={{ width: "100%", typography: "body1" }}>
<TabContext value={value}>
<Box
sx={{
borderBottom: 1,
borderColor: "divider",
width: "100%",
maxWidth: "800px",
margin: "0px auto",
}}
>
<TabList
onChange={handleChange}
aria-label="interest management tabs"
variant="scrollable"
// scrollButtons="auto"
scrollButtons="on"
allowScrollButtonsMobile
sx={{
"& .MuiTabs-scrollButtons": {
display: "flex !important", // force visible
alignItems: "center",
justifyContent: "center",
width: "36px",
height: "36px",
borderRadius: "50%",
backgroundColor: "#034E08",
color: "white",
margin: "0 6px",
boxShadow: "0 2px 5px rgba(0,0,0,0.2)",
},
"& .MuiTabs-scrollButtons:hover": {
backgroundColor: "#046b0b",
},
"& .MuiTabs-scrollButtons.Mui-disabled": {
opacity: 0.4,
backgroundColor: "#9bcf9d",
},
"& .MuiTab-root": {
fontSize: { xs: "14px", sm: "16px" },
fontWeight: 600,
textTransform: "none",
minWidth: { xs: 120, sm: 150 },
color: "#666",
},
"& .Mui-selected": {
color: "#034E08 !important",
},
"& .MuiTabs-indicator": {
backgroundColor: "#034E08",
height: 3,
},
}}
>
<Tab label="Received Requests" value="1" />
<Tab label="Sent Requests" value="2" />
<Tab label="Accepted" value="3" />
<Tab label="Rejected" value="4" />
</TabList>
</Box>
{/* Received Requests */}
<TabPanel value="1" sx={{ padding: "24px 0" }}>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 w-[100%] max-w-[1200px] mx-auto">
{profilesData.received.map((profile) => (
<ProfileCard key={profile.id} profile={profile} activeTab={value} />
))}
</div>
</TabPanel>
{/* Sent Requests */}
<TabPanel value="2" sx={{ padding: "24px 0" }}>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 w-[100%] max-w-[1200px] mx-auto">
{profilesData.sent.map((profile) => (
<ProfileCard key={profile.id} profile={profile} activeTab={value} />
))}
</div>
</TabPanel>
{/* Accepted */}
<TabPanel value="3" sx={{ padding: "24px 0" }}>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 w-[100%] max-w-[1200px] mx-auto">
{profilesData.accepted.map((profile) => (
<ProfileCard key={profile.id} profile={profile} activeTab={value} />
))}
</div>
</TabPanel>
{/* Rejected */}
<TabPanel value="4" sx={{ padding: "24px 0" }}>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 w-[100%] max-w-[1200px] mx-auto">
{profilesData.rejected.map((profile) => (
<ProfileCard key={profile.id} profile={profile} activeTab={value} />
))}
</div>
</TabPanel>
</TabContext>
</Box>
</div>
</div>
);
}
+15
View File
@@ -0,0 +1,15 @@
import MatchesInterface from "../components/matches/MatchesProfilesTab"
import SearchUI from "../components/matches/SearchUI"
const MatchesPage = () => {
return (
<>
<SearchUI/>
<MatchesInterface/>
</>
)
}
export default MatchesPage
+16
View File
@@ -0,0 +1,16 @@
import MatrimonyProfile from "../components/profiledetail/MatrimonyProfile"
import PartnerPreferences from "../components/profiledetail/PartnerPreferences"
const ProfileDetailPage = () => {
return (
<>
<div className="w-[100%] max-w-[1400px] mx-auto my-10">
<MatrimonyProfile/>
<PartnerPreferences/>
</div>
</>
)
}
export default ProfileDetailPage
+36 -115
View File
@@ -8,20 +8,33 @@ import DailyRecommendedCard from '../components/profiledashboard/DailyRecommende
import MatrimonyArticles from '../components/profiledashboard/MatrimonyArticles';
import MatchingList from '../components/profiledashboard/MatchingList';
import PaidMemberCard from '../components/profiledashboard/PaidMemberCard';
import LazyImage from '../components/common/LazyImage';
import weddingpromo1 from "../assets/images/weddingpromo1.jpg";
import weddingpromo2 from "../assets/images/weddingpromo2.jpg";
import weddingpromo3 from "../assets/images/weddingpromo3.jpg";
import weddingpromo4 from "../assets/images/weddingpromo4.jpg";
import ProfileCard from '../components/common/ProfileCard';
import NewJoinedProfile from '../components/profiledashboard/NewJoinedProfile';
import CustomerSupportCard from '../components/profiledashboard/CustomerSupportCard';
import VideoSwiperGallery from '../components/profiledashboard/VideoSwiperGallery';
const images = [
"https://images.unsplash.com/photo-1494790108377-be9c29b29330",
"https://images.unsplash.com/photo-1529626455594-4ff0802cfb7e",
"https://images.unsplash.com/photo-1494790108377-be9c29b29330",
"https://images.unsplash.com/photo-1529626455594-4ff0802cfb7e",
"https://images.unsplash.com/photo-1494790108377-be9c29b29330",
"https://images.unsplash.com/photo-1529626455594-4ff0802cfb7e",
"https://images.unsplash.com/photo-1494790108377-be9c29b29330",
"https://images.unsplash.com/photo-1529626455594-4ff0802cfb7e",
"https://images.unsplash.com/photo-1494790108377-be9c29b29330",
"https://images.unsplash.com/photo-1529626455594-4ff0802cfb7e",
];
weddingpromo1, // bride in saree
weddingpromo2, // traditional jewellery
weddingpromo3, // flower details
weddingpromo4, // couple hands
weddingpromo1, // bride close-up
weddingpromo3, // groom + bride portrait
weddingpromo2, // wedding decor
weddingpromo4, // bride in temple
weddingpromo1, // traditional ceremony
weddingpromo3 // couple full shot
];
const UserDashboardHome = () => {
return (
<>
@@ -62,6 +75,12 @@ const UserDashboardHome = () => {
alt={`Slide ${idx + 1}`}
className="w-full h-full object-cover"
/>
{/* <LazyImage
src={img}
alt={`Slide ${idx + 1}`}
className="w-full h-full object-cover"
/> */}
{/* <div className="absolute bottom-6 left-1/2 -translate-x-1/2 bg-black/50 backdrop-blur-sm px-6 py-2 rounded-full">
<span className="text-white font-semibold text-lg">Slide {idx + 1}</span>
</div> */}
@@ -71,109 +90,7 @@ const UserDashboardHome = () => {
</Swiper>
</div>
{/* <style>{`
.swiper {
width: 100%;
// padding: 60px 80px;
overflow: visible;
}
.swiper-slide {
width: 320px;
height: 320px;
transition: all 0.4s ease;
opacity: 1;
transform: scale(0.85);
}
.swiper-slide-active {
width: 630px !important;
height: 320px !important;
opacity: 1;
transform: scale(1);
z-index: 2;
}
@media only screen and (max-width: 768px) {
.swiper-slide {
width: 300px;
height: 150px; }
.swiper-slide-active {
width: 300px;
height: 150px ! important;
}
}
.swiper-slide > div {
width: 100%;
height: 100%;
}
.swiper-button-prev-custom,
.swiper-button-next-custom {
cursor: pointer;
}
@media (max-width: 1024px) {
.swiper {
padding: 50px 60px;
}
.swiper-slide {
width: 240px;
height: 340px;
}
.swiper-slide-active {
width: 380px !important;
height: 480px !important;
}
}
@media (max-width: 768px) {
.swiper {
padding: 40px 50px;
}
.swiper-slide {
width: 180px;
height: 280px;
}
.swiper-slide-active {
width: 300px !important;
height: 280px !important;
}
.swiper-button-prev-custom,
.swiper-button-next-custom {
width: 40px;
height: 40px;
}
}
@media (max-width: 480px) {
.swiper {
padding: 30px 40px;
}
.swiper-slide {
width: 140px;
height: 220px;
}
.swiper-slide-active {
width: 300px !important;
height: 220px !important;
}
.swiper-button-prev-custom,
.swiper-button-next-custom {
width: 36px;
height: 36px;
}
}
`}</style> */}
<style>{`
.custom-swiper-hero .swiper {
@@ -275,6 +192,10 @@ const UserDashboardHome = () => {
<MatrimonyArticles/>
<MatchingList/>
<PaidMemberCard/>
<NewJoinedProfile/>
<CustomerSupportCard/>
<VideoSwiperGallery/>
</>
)
}