449 lines
16 KiB
JavaScript
449 lines
16 KiB
JavaScript
import React from "react";
|
|
import { useSelector } from 'react-redux';
|
|
import { Swiper, SwiperSlide } from "swiper/react";
|
|
import { Navigation, Pagination } from "swiper/modules";
|
|
import "swiper/css";
|
|
import "swiper/css/navigation";
|
|
import "swiper/css/pagination";
|
|
import { Edit2,Info } from 'lucide-react';
|
|
import {
|
|
Card,
|
|
CardContent,
|
|
CardHeader,
|
|
Typography,
|
|
Box,
|
|
Divider,
|
|
IconButton,
|
|
Button,
|
|
Grid,
|
|
Tooltip,
|
|
} from '@mui/material';
|
|
import { usePreviewDetails } from "../hooks/usePreview";
|
|
import { isAuthenticated } from "../utills/auth";
|
|
|
|
const PreviewScreen = ({ onEdit, onSubmit }) => {
|
|
const formData = useSelector((state) => state.registerform);
|
|
const isAuth = isAuthenticated();
|
|
const { data: previewData, isLoading: apiLoading, isError: apiError } = usePreviewDetails(isAuth);
|
|
const isLoading = isAuth && apiLoading;
|
|
const isError = isAuth && apiError;
|
|
|
|
const sections = previewData?.personal_details
|
|
? [
|
|
{
|
|
title: "Personal Details",
|
|
step: 1,
|
|
data: previewData.personal_details,
|
|
},
|
|
{
|
|
title: "Educational & Professional Details",
|
|
step: 2,
|
|
data: previewData.educational_details,
|
|
},
|
|
{
|
|
title: "Family Details",
|
|
step: 3,
|
|
data: previewData.family_details,
|
|
},
|
|
{
|
|
title: "Lifestyle & Habits",
|
|
step: 4,
|
|
data: previewData.lifestyle_details,
|
|
},
|
|
{
|
|
title: "Partner Preferences",
|
|
step: 5,
|
|
data: previewData.partner_preferences,
|
|
},
|
|
]
|
|
: [
|
|
{
|
|
title: 'Personal Details',
|
|
step: 1,
|
|
data: formData.personalDetails,
|
|
},
|
|
{
|
|
title: 'Educational & Professional Details',
|
|
step: 2,
|
|
data: formData.educationalDetails,
|
|
},
|
|
{
|
|
title: 'Family Details',
|
|
step: 3,
|
|
data: formData.familyDetails,
|
|
},
|
|
{
|
|
title: 'Lifestyle & Habits',
|
|
step: 4,
|
|
data: formData.lifestyleDetails,
|
|
},
|
|
{
|
|
title: 'Partner Preferences',
|
|
step: 5,
|
|
data: formData.partnerPreferences,
|
|
},
|
|
];
|
|
|
|
const renderValue = (key, value) => {
|
|
if (key === "profiles" || key === "profile" || key === "profile_images" || key === "images") {
|
|
const list = Array.isArray(value) ? value : (value ? [value] : []);
|
|
return (
|
|
<Box display="flex" gap={1} flexWrap="wrap">
|
|
{list.length > 0 ? (
|
|
list.map((imgObj, index) => {
|
|
const src =
|
|
typeof imgObj === "string"
|
|
? imgObj
|
|
: imgObj?.preview ||
|
|
imgObj?.url ||
|
|
(imgObj?.file ? URL.createObjectURL(imgObj.file) : null);
|
|
if (!src) return null;
|
|
return (
|
|
<img
|
|
key={index}
|
|
src={src}
|
|
alt="Profile"
|
|
style={{
|
|
width: "90px",
|
|
height: "90px",
|
|
objectFit: "cover",
|
|
borderRadius: "50%",
|
|
border: "1px solid #ccc",
|
|
// marginLeft: "-20px",
|
|
}}
|
|
/>
|
|
);
|
|
})
|
|
) : (
|
|
<Box display="flex" alignItems="center" gap={1} sx={{ color: "#888" }}>
|
|
<Info size={16} />
|
|
<Typography>No photos uploaded</Typography>
|
|
</Box>
|
|
)}
|
|
</Box>
|
|
);
|
|
}
|
|
|
|
if (Array.isArray(value)) {
|
|
if (value.length === 0) return "-";
|
|
if (typeof value[0] === "object") {
|
|
return value.map((item, idx) => (
|
|
<div key={idx}>{JSON.stringify(item)}</div>
|
|
));
|
|
}
|
|
return value.join(", ");
|
|
}
|
|
|
|
if (value && typeof value === "object") {
|
|
return "-";
|
|
}
|
|
|
|
return value || "-";
|
|
};
|
|
|
|
const renderChartGrid = (getDataForCell, title) => {
|
|
const renderCell = (i) => {
|
|
const items = getDataForCell(i);
|
|
const label = Array.isArray(items) ? items.join(', ') : '';
|
|
|
|
return (
|
|
<Tooltip key={i} title={label} arrow placement="top" disableHoverListener={!items || items.length === 0}>
|
|
<Box
|
|
sx={{
|
|
border: '1px solid #ccc',
|
|
bgcolor: '#fff',
|
|
height: '60px',
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
textAlign: 'center',
|
|
fontSize: '0.65rem',
|
|
fontWeight: 'bold',
|
|
overflow: 'hidden',
|
|
p: 0.5,
|
|
wordBreak: 'break-word',
|
|
lineHeight: 1.1,
|
|
cursor: items && items.length > 0 ? 'help' : 'default'
|
|
}}
|
|
>
|
|
{items && items.length > 2 ? (
|
|
<Box>
|
|
{items.slice(0, 2).join(', ')}
|
|
<Box component="span" sx={{ color: 'primary.main', display: 'block', fontSize:'0.6rem' }}>+{items.length - 2}</Box>
|
|
</Box>
|
|
) : label}
|
|
</Box>
|
|
</Tooltip>
|
|
);
|
|
};
|
|
|
|
return (
|
|
<Box>
|
|
<Typography variant="subtitle2" align="center" gutterBottom sx={{ fontWeight: 600 }}>{title}</Typography>
|
|
<Box sx={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 0.5, maxWidth: '300px', mx: 'auto', p: 1, bgcolor: '#fff3e0', borderRadius: 2 }}>
|
|
{renderCell(1)} {renderCell(2)} {renderCell(3)} {renderCell(4)}
|
|
{renderCell(5)}
|
|
<Box sx={{ gridColumn: 'span 2', gridRow: 'span 2', bgcolor: '#fff', border: '1px solid #eee', display:'flex', alignItems:'center', justifyContent:'center', fontSize:'0.7rem', fontWeight:'bold', color:'#aaa' }}>
|
|
{title.toUpperCase()}
|
|
</Box>
|
|
{renderCell(6)}
|
|
{renderCell(7)} {renderCell(8)}
|
|
{renderCell(9)} {renderCell(10)} {renderCell(11)} {renderCell(12)}
|
|
</Box>
|
|
</Box>
|
|
);
|
|
};
|
|
|
|
return (
|
|
<Box p={3} sx={{maxWidth:"1400px", width:"100%"}} mx="auto" >
|
|
|
|
<div className='grid grid-cols-1 md:grid-cols-2 gap-4 my-10'>
|
|
|
|
{isLoading && (
|
|
<Box
|
|
py={4}
|
|
display="flex"
|
|
justifyContent="center"
|
|
sx={{ color: "#666" }}
|
|
>
|
|
Loading preview...
|
|
</Box>
|
|
)}
|
|
|
|
{isError && (
|
|
<Box
|
|
py={4}
|
|
display="flex"
|
|
justifyContent="center"
|
|
sx={{ color: "#d32f2f" }}
|
|
>
|
|
Failed to load preview.
|
|
</Box>
|
|
)}
|
|
|
|
{!isLoading &&
|
|
sections.map((section) => (
|
|
|
|
<Card key={section.title} variant="outlined" sx={{ borderRadius: 2, background:"#fff5ed" }}>
|
|
<CardHeader
|
|
title={
|
|
<Typography variant="h6" fontWeight="bold">
|
|
{section.title}
|
|
</Typography>
|
|
}
|
|
action={
|
|
<IconButton
|
|
aria-label="edit"
|
|
color="primary"
|
|
onClick={() => onEdit(section.step)}
|
|
size="large"
|
|
>
|
|
<Edit2 size={20} />
|
|
</IconButton>
|
|
}
|
|
sx={{padding:"15px 15px", background:"#f5fbff" }}
|
|
/>
|
|
<Divider />
|
|
<CardContent sx={{ pt: 1, }}>
|
|
{Object.entries(section.data || {}).map(([key, value]) => {
|
|
// Filter out ID fields
|
|
if (key === 'id' || key.endsWith('_id') || key.endsWith('Id') || key.endsWith('_ids') || key.endsWith('Ids') || key === 'created_at' || key === 'updated_at') {
|
|
return null;
|
|
}
|
|
|
|
// Handle Horoscope Chart (Server Data)
|
|
if (key === 'horoscope' && value && typeof value === 'object') {
|
|
return (
|
|
<Box key={key} sx={{ width: '100%', mt: 2, mb: 2, borderTop: '1px solid #e0e0e0', pt: 2, gridColumn: '1 / -1' }}>
|
|
<Typography variant="subtitle1" fontWeight="bold" gutterBottom>Horoscope Details</Typography>
|
|
<Grid container spacing={4} justifyContent="center">
|
|
<Grid item xs={12} md={6}>
|
|
{renderChartGrid((i) => {
|
|
const val = value[`graha_${i}`];
|
|
return val ? val.split(',') : [];
|
|
}, 'Rasi')}
|
|
</Grid>
|
|
<Grid item xs={12} md={6}>
|
|
{renderChartGrid((i) => {
|
|
const val = value[`amsam_${i}`];
|
|
return val ? val.split(',') : [];
|
|
}, 'Navamsam')}
|
|
</Grid>
|
|
</Grid>
|
|
</Box>
|
|
);
|
|
}
|
|
|
|
// Handle Horoscope Chart (Redux Data)
|
|
if (key === 'graha' && value) {
|
|
return (
|
|
<Box key={key} sx={{ width: '100%', mt: 2, mb: 2, gridColumn: '1 / -1' }}>
|
|
{renderChartGrid((i) => value[i] || [], 'Rasi')}
|
|
</Box>
|
|
);
|
|
}
|
|
if (key === 'amsam' && value) {
|
|
return (
|
|
<Box key={key} sx={{ width: '100%', mt: 2, mb: 2, gridColumn: '1 / -1' }}>
|
|
{renderChartGrid((i) => value[i] || [], 'Navamsam')}
|
|
</Box>
|
|
);
|
|
}
|
|
|
|
// Handle brothers and sisters arrays specifically
|
|
if ((key === 'brothers' || key === 'sisters') && Array.isArray(value) && value.length > 0) {
|
|
return (
|
|
<Box key={key} sx={{ py: 2, borderBottom: "1px solid #e0e0e0" }}>
|
|
<Typography color="text.secondary" sx={{ fontWeight: 600, mb: 1 }}>
|
|
{key === 'brothers' ? 'Brothers Details' : 'Sisters Details'}
|
|
</Typography>
|
|
<style>
|
|
{`
|
|
.custom-swiper-${key} .swiper-button-next,
|
|
.custom-swiper-${key} .swiper-button-prev {
|
|
color: #d32f2f;
|
|
width: 25px;
|
|
height: 25px;
|
|
background: rgba(255, 255, 255, 0.9);
|
|
border-radius: 50%;
|
|
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
}
|
|
.custom-swiper-${key} .swiper-button-next::after,
|
|
.custom-swiper-${key} .swiper-button-prev::after {
|
|
font-size: 12px;
|
|
font-weight: bold;
|
|
}
|
|
.custom-swiper-${key} .swiper-pagination-bullet-active {
|
|
background-color: #d32f2f;
|
|
}
|
|
`}
|
|
</style>
|
|
<Swiper
|
|
className={`custom-swiper-${key}`}
|
|
modules={[Navigation, Pagination]}
|
|
spaceBetween={15}
|
|
slidesPerView={1}
|
|
navigation
|
|
pagination={{ clickable: true }}
|
|
style={{ padding: "4px 4px 30px 4px" }}
|
|
>
|
|
{value.map((sibling, idx) => (
|
|
<SwiperSlide key={idx}>
|
|
<Card variant="outlined" sx={{ bgcolor: '#fff', height: '100%' }}>
|
|
<CardContent sx={{ p: 2, '&:last-child': { pb: 2 } }}>
|
|
{Object.entries(sibling).map(([sKey, sVal]) => {
|
|
if (sKey === 'id' || sKey.endsWith('_id') || sKey.endsWith('Id') || sKey === 'created_at' || sKey === 'updated_at') return null;
|
|
let displayValue = sVal;
|
|
if (sKey === 'haveChildrens' || sKey === 'have_childrens') {
|
|
if (sVal === true || sVal === 1 || sVal === '1') {
|
|
displayValue = 'Yes';
|
|
} else if (sVal === false || sVal === 0 || sVal === '0') {
|
|
displayValue = 'No';
|
|
}
|
|
}
|
|
return (
|
|
<Box key={sKey} display="grid" gridTemplateColumns="45% 55%" gap={1} mb={0.8} alignItems="start">
|
|
<Typography variant="caption" color="text.secondary" sx={{ fontWeight: 500 }}>
|
|
{sKey
|
|
.replace(/([A-Z])/g, ' $1')
|
|
.replace(/_/g, ' ')
|
|
.replace(/\b\w/g, (l) => l.toUpperCase())
|
|
.trim()}
|
|
</Typography>
|
|
<Typography variant="body2" fontWeight={600} sx={{ wordBreak: 'break-word' }}>
|
|
{displayValue ?? '-'}
|
|
</Typography>
|
|
</Box>
|
|
)})}
|
|
</CardContent>
|
|
</Card>
|
|
</SwiperSlide>
|
|
))}
|
|
</Swiper>
|
|
</Box>
|
|
);
|
|
}
|
|
// Convert camelCase or camel_Snake_case to readable words
|
|
const formattedKey = key
|
|
.replace(/([A-Z])/g, ' $1')
|
|
.replace(/_/g, ' ')
|
|
.replace(/\b\w/g, (l) => l.toUpperCase())
|
|
.trim();
|
|
const content = renderValue(key, value);
|
|
return (
|
|
|
|
<Box
|
|
key={key}
|
|
py={0.7}
|
|
borderBottom="1px solid #e0e0e0"
|
|
sx={{
|
|
display: "grid",
|
|
gridTemplateColumns: {
|
|
xs: "1fr",
|
|
sm: "1fr 1fr",
|
|
},
|
|
gap: "10px",
|
|
alignItems: "center",
|
|
}}
|
|
>
|
|
<Typography color="text.secondary" sx={{ fontWeight: 500 }}>
|
|
{formattedKey}:
|
|
</Typography>
|
|
|
|
{/* Special Case: Profiles Image Preview */}
|
|
{key === "profiles" || key === "profile" || key === "profile_images" || key === "images" ? (
|
|
content
|
|
) : value ? (
|
|
<Typography
|
|
sx={{
|
|
fontWeight: 600,
|
|
wordBreak: "break-word",
|
|
textAlign: "left",
|
|
}}
|
|
>
|
|
{content}
|
|
</Typography>
|
|
) : (
|
|
<Box
|
|
display="flex"
|
|
alignItems="center"
|
|
gap={1}
|
|
sx={{ color: "#888", fontStyle: "italic" }}
|
|
>
|
|
<Info size={16} />
|
|
<Typography>No data available</Typography>
|
|
</Box>
|
|
)}
|
|
</Box>
|
|
|
|
|
|
);
|
|
|
|
|
|
})}
|
|
</CardContent>
|
|
</Card>
|
|
|
|
))}
|
|
|
|
</div>
|
|
|
|
<Grid item xs={12} sx={{display:"flex", justifyContent:"center"}}>
|
|
<Button
|
|
variant="contained"
|
|
color="success"
|
|
|
|
size="large"
|
|
onClick={onSubmit}
|
|
sx={{ borderRadius: 2 }}
|
|
>
|
|
Submit full Completed Data
|
|
</Button>
|
|
</Grid>
|
|
|
|
</Box>
|
|
);
|
|
};
|
|
|
|
export default PreviewScreen;
|