register1

This commit is contained in:
Meenadeveloper 2026-02-28 18:10:00 +05:30
parent 13b17037c9
commit fd0a327b13
2 changed files with 166 additions and 24 deletions

View File

@ -1,4 +1,6 @@
import React from "react"; import React from "react";
import ArrowLeftIcon from "@mui/icons-material/ArrowLeft";
import ArrowRightIcon from "@mui/icons-material/ArrowRight";
import { import {
Dropzone, Dropzone,
FileMosaic, FileMosaic,
@ -13,6 +15,7 @@ const AdvancedDropzone = ({ value, onChange }) => {
const [extFiles, setExtFiles] = React.useState(value || []); const [extFiles, setExtFiles] = React.useState(value || []);
const [imageSrc, setImageSrc] = React.useState(undefined); const [imageSrc, setImageSrc] = React.useState(undefined);
const [videoSrc, setVideoSrc] = React.useState(undefined); const [videoSrc, setVideoSrc] = React.useState(undefined);
const [hoveredId, setHoveredId] = React.useState(null);
const updateFiles = (incomingFiles) => { const updateFiles = (incomingFiles) => {
console.log("incoming files", incomingFiles); console.log("incoming files", incomingFiles);
@ -53,6 +56,17 @@ const AdvancedDropzone = ({ value, onChange }) => {
); );
}; };
const moveFile = (fromIndex, toIndex) => {
setExtFiles((prev) => {
if (toIndex < 0 || toIndex >= prev.length) return prev;
const updated = [...prev];
const [moved] = updated.splice(fromIndex, 1);
updated.splice(toIndex, 0, moved);
onChange && onChange(updated);
return updated;
});
};
return ( return (
<> <>
<Dropzone <Dropzone
@ -77,20 +91,115 @@ const AdvancedDropzone = ({ value, onChange }) => {
uploadButton: {}, uploadButton: {},
}} }}
> >
{extFiles.map((file) => ( {extFiles.map((file, index) => (
<FileMosaic <div
{...file}
key={file.id} key={file.id}
onDelete={onDelete} style={{
onSee={handleSee} position: "relative",
onWatch={handleWatch} display: "inline-block",
onAbort={handleAbort} marginBottom: 12,
onCancel={handleCancel} }}
resultOnTooltip onMouseEnter={() => setHoveredId(file.id)}
alwaysActive onMouseLeave={() => setHoveredId(null)}
preview >
info <FileMosaic
/> {...file}
onDelete={onDelete}
onSee={handleSee}
onWatch={handleWatch}
onAbort={handleAbort}
onCancel={handleCancel}
resultOnTooltip
alwaysActive
preview
info={false}
/>
{hoveredId === file.id && (
<div
style={{
position: "absolute",
left: 8,
right: 8,
bottom: 8,
display: "flex",
justifyContent: "space-between",
alignItems: "center",
padding: "6px 8px",
borderRadius: 8,
background: "rgba(0,0,0,0.5)",
pointerEvents: "auto",
zIndex: 5,
}}
>
<button
type="button"
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
moveFile(index, index - 1);
}}
disabled={index === 0}
style={{
width: 32,
height: 32,
borderRadius: "50%",
border: "1px solid rgba(255,255,255,0.6)",
background: index === 0 ? "rgba(255,255,255,0.4)" : "#fff",
cursor: index === 0 ? "not-allowed" : "pointer",
display: "flex",
alignItems: "center",
justifyContent: "center",
boxShadow: "0 2px 6px rgba(0,0,0,0.2)",
}}
aria-label="Move left"
>
<ArrowLeftIcon fontSize="small" />
</button>
<span
style={{
color: "#fff",
fontSize: 12,
opacity: 0.95,
maxWidth: 140,
overflow: "hidden",
textOverflow: "ellipsis",
whiteSpace: "nowrap",
}}
title={file.name}
>
{file.name}
</span>
<button
type="button"
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
moveFile(index, index + 1);
}}
disabled={index === extFiles.length - 1}
style={{
width: 32,
height: 32,
borderRadius: "50%",
border: "1px solid rgba(255,255,255,0.6)",
background:
index === extFiles.length - 1
? "rgba(255,255,255,0.4)"
: "#fff",
cursor:
index === extFiles.length - 1 ? "not-allowed" : "pointer",
display: "flex",
alignItems: "center",
justifyContent: "center",
boxShadow: "0 2px 6px rgba(0,0,0,0.2)",
}}
aria-label="Move right"
>
<ArrowRightIcon fontSize="small" />
</button>
</div>
)}
</div>
))} ))}
</Dropzone> </Dropzone>

View File

@ -13,8 +13,11 @@ import {
Typography, Typography,
Link, Link,
InputAdornment, InputAdornment,
IconButton,
} from "@mui/material"; } from "@mui/material";
import CheckCircleIcon from "@mui/icons-material/CheckCircle"; import CheckCircleIcon from "@mui/icons-material/CheckCircle";
import Visibility from "@mui/icons-material/Visibility";
import VisibilityOff from "@mui/icons-material/VisibilityOff";
import AdvancedDropzone from "./AdvancedDropzone"; import AdvancedDropzone from "./AdvancedDropzone";
import { DatePicker } from "@mui/x-date-pickers/DatePicker"; import { DatePicker } from "@mui/x-date-pickers/DatePicker";
import toast from "react-hot-toast"; import toast from "react-hot-toast";
@ -44,6 +47,8 @@ const PersonalDetailsForm = ({ onSubmitStep, errors }) => {
const [otpError, setOtpError] = useState(""); const [otpError, setOtpError] = useState("");
const [mobileOtpVerified, setMobileOtpVerified] = useState(false); const [mobileOtpVerified, setMobileOtpVerified] = useState(false);
const [mobileNumberError, setMobileNumberError] = useState(""); const [mobileNumberError, setMobileNumberError] = useState("");
const [showPassword, setShowPassword] = useState(false);
const [showConfirmPassword, setShowConfirmPassword] = useState(false);
const sendOtp = useSendOtp(); const sendOtp = useSendOtp();
const verifyOtp = useVerifyOtp(); const verifyOtp = useVerifyOtp();
@ -102,7 +107,7 @@ const PersonalDetailsForm = ({ onSubmitStep, errors }) => {
const raw = cityQuery.data; const raw = cityQuery.data;
if (!raw) return []; if (!raw) return [];
if (Array.isArray(raw)) return raw; if (Array.isArray(raw)) return raw;
return raw.city || raw.district || raw.data || []; return raw.subCaste || raw.district || raw.data || [];
}, [cityQuery.data]); }, [cityQuery.data]);
const starOptions = useMemo(() => { const starOptions = useMemo(() => {
@ -194,9 +199,10 @@ const PersonalDetailsForm = ({ onSubmitStep, errors }) => {
const res = await sendOtp.mutateAsync(data.mobileNumber); const res = await sendOtp.mutateAsync(data.mobileNumber);
const successMessage = const successMessage =
res?.message || res?.message ||
res?.otp ||
res?.status || res?.status ||
"OTP sent successfully"; "OTP sent successfully";
toast.success(successMessage); toast.success(successMessage, { position: "top-right" });
setShowOtp(true); setShowOtp(true);
resetOtp(); resetOtp();
setMobileOtpVerified(false); setMobileOtpVerified(false);
@ -207,7 +213,7 @@ const PersonalDetailsForm = ({ onSubmitStep, errors }) => {
error?.response?.data?.otp || error?.response?.data?.otp ||
error?.message || error?.message ||
"Failed to send OTP"; "Failed to send OTP";
toast.error(message); toast.error(message, { position: "top-right" });
} }
}; };
@ -251,20 +257,21 @@ const PersonalDetailsForm = ({ onSubmitStep, errors }) => {
}); });
const successMessage = const successMessage =
res?.message || res?.message ||
res?.otp ||
res?.status || res?.status ||
"OTP verified successfully"; "OTP verified successfully";
toast.success(successMessage); toast.success(successMessage, { position: "top-right" });
setMobileOtpVerified(true); setMobileOtpVerified(true);
setMobileNumberError(""); setMobileNumberError("");
setOtpError(""); setOtpError("");
} catch (error) { } catch (error) {
const message = const message =
error?.response?.data?.otp ||
error?.response?.data?.message || error?.response?.data?.message ||
error?.response?.data?.otp ||
error?.message || error?.message ||
"Invalid or expired OTP"; "Invalid or expired OTP";
setOtpError(message); setOtpError(message);
toast.error(message); toast.error(message, { position: "top-right" });
} }
}; };
@ -506,7 +513,7 @@ const PersonalDetailsForm = ({ onSubmitStep, errors }) => {
<Typography sx={{ ml: 2, minWidth: 56 }}> <Typography sx={{ ml: 2, minWidth: 56 }}>
{otpTimer > 0 ? ( {otpTimer > 0 ? (
formatTimer(otpTimer) ` ${formatTimer(otpTimer) } Seconds`
) : ( ) : (
<Link <Link
component="button" component="button"
@ -520,7 +527,7 @@ const PersonalDetailsForm = ({ onSubmitStep, errors }) => {
</Typography> </Typography>
{otpError && ( {otpError && (
<Typography color="error" variant="caption" sx={{ mt: 1 }}> <Typography color="error" variant="caption" sx={{ mt: "-10px", fontSize:"12px" }}>
{otpError} {otpError}
</Typography> </Typography>
)} )}
@ -925,13 +932,26 @@ const PersonalDetailsForm = ({ onSubmitStep, errors }) => {
</label> </label>
<TextField <TextField
fullWidth fullWidth
type="password" type={showPassword ? "text" : "password"}
name="password" name="password"
label="Enter Password" label="Enter Password"
value={data.password} value={data.password}
onChange={(e) => handleChange("password", e.target.value)} onChange={(e) => handleChange("password", e.target.value)}
error={Boolean(errors.password)} error={Boolean(errors.password)}
helperText={errors.password} helperText={errors.password}
InputProps={{
endAdornment: (
<InputAdornment position="end">
<IconButton
onClick={() => setShowPassword((prev) => !prev)}
edge="end"
aria-label="toggle password visibility"
>
{showPassword ? <VisibilityOff /> : <Visibility />}
</IconButton>
</InputAdornment>
),
}}
variant="outlined" variant="outlined"
/> />
</div> </div>
@ -943,13 +963,26 @@ const PersonalDetailsForm = ({ onSubmitStep, errors }) => {
</label> </label>
<TextField <TextField
fullWidth fullWidth
type="password" type={showConfirmPassword ? "text" : "password"}
name="confirmPassword" name="confirmPassword"
label="Confirm Password" label="Confirm Password"
value={data.confirmPassword} value={data.confirmPassword}
onChange={(e) => handleChange("confirmPassword", e.target.value)} onChange={(e) => handleChange("confirmPassword", e.target.value)}
error={Boolean(errors.confirmPassword)} error={Boolean(errors.confirmPassword)}
helperText={errors.confirmPassword} helperText={errors.confirmPassword}
InputProps={{
endAdornment: (
<InputAdornment position="end">
<IconButton
onClick={() => setShowConfirmPassword((prev) => !prev)}
edge="end"
aria-label="toggle confirm password visibility"
>
{showConfirmPassword ? <VisibilityOff /> : <Visibility />}
</IconButton>
</InputAdornment>
),
}}
variant="outlined" variant="outlined"
/> />
</div> </div>
@ -1022,7 +1055,7 @@ const PersonalDetailsForm = ({ onSubmitStep, errors }) => {
> >
{cityOptions.map((city) => ( {cityOptions.map((city) => (
<MenuItem key={city.id} value={city.id}> <MenuItem key={city.id} value={city.id}>
{getOptionLabel(city, "City")} {getOptionLabel(city.district_name, "City")}
</MenuItem> </MenuItem>
))} ))}
</Select> </Select>