177 lines
5.4 KiB
JavaScript
177 lines
5.4 KiB
JavaScript
import { useState } from "react";
|
||
import { changePassword, requestPasswordChangeCode } from "../authApi";
|
||
|
||
export default function ChangePassword({ token, onClose, onSuccess }) {
|
||
const [step, setStep] = useState(1); // 1: request code, 2: enter code & passwords
|
||
const [verificationCode, setVerificationCode] = useState("");
|
||
const [currentPassword, setCurrentPassword] = useState("");
|
||
const [newPassword, setNewPassword] = useState("");
|
||
const [confirmPassword, setConfirmPassword] = useState("");
|
||
const [error, setError] = useState("");
|
||
const [loading, setLoading] = useState(false);
|
||
const [codeSent, setCodeSent] = useState(false);
|
||
|
||
const handleRequestCode = async () => {
|
||
setError("");
|
||
setLoading(true);
|
||
|
||
try {
|
||
await requestPasswordChangeCode(token);
|
||
setCodeSent(true);
|
||
setStep(2);
|
||
} catch (err) {
|
||
setError(err.message);
|
||
} finally {
|
||
setLoading(false);
|
||
}
|
||
};
|
||
|
||
const handleSubmit = async (e) => {
|
||
e.preventDefault();
|
||
setError("");
|
||
|
||
// Validation
|
||
if (!verificationCode || !currentPassword || !newPassword || !confirmPassword) {
|
||
setError("נא למלא את כל השדות");
|
||
return;
|
||
}
|
||
|
||
if (verificationCode.length !== 6) {
|
||
setError("קוד האימות חייב להכיל 6 ספרות");
|
||
return;
|
||
}
|
||
|
||
if (newPassword !== confirmPassword) {
|
||
setError("הסיסמאות החדשות אינן תואמות");
|
||
return;
|
||
}
|
||
|
||
if (newPassword.length < 6) {
|
||
setError("הסיסמה חייבת להכיל לפחות 6 תווים");
|
||
return;
|
||
}
|
||
|
||
setLoading(true);
|
||
|
||
try {
|
||
await changePassword(verificationCode, currentPassword, newPassword, token);
|
||
onSuccess?.();
|
||
onClose();
|
||
} catch (err) {
|
||
setError(err.message);
|
||
} finally {
|
||
setLoading(false);
|
||
}
|
||
};
|
||
|
||
return (
|
||
<div className="modal-overlay" onClick={onClose}>
|
||
<div className="modal-content" onClick={(e) => e.stopPropagation()}>
|
||
<div className="modal-header">
|
||
<h2>שינוי סיסמה</h2>
|
||
<button className="close-btn" onClick={onClose}>
|
||
×
|
||
</button>
|
||
</div>
|
||
|
||
<div className="modal-body">
|
||
{error && <div className="error-message">{error}</div>}
|
||
|
||
{step === 1 && (
|
||
<div>
|
||
<p style={{ marginBottom: "1rem", color: "var(--text-muted)" }}>
|
||
קוד אימות יישלח לכתובת המייל שלך. הקוד תקף ל-10 דקות.
|
||
</p>
|
||
<button
|
||
className="btn btn-primary full"
|
||
onClick={handleRequestCode}
|
||
disabled={loading}
|
||
>
|
||
{loading ? "שולח..." : "שלח קוד אימות"}
|
||
</button>
|
||
</div>
|
||
)}
|
||
|
||
{step === 2 && (
|
||
<form onSubmit={handleSubmit}>
|
||
{codeSent && (
|
||
<div style={{
|
||
padding: "0.75rem",
|
||
background: "rgba(34, 197, 94, 0.1)",
|
||
borderRadius: "8px",
|
||
marginBottom: "1rem",
|
||
color: "var(--accent)"
|
||
}}>
|
||
✓ קוד אימות נשלח לכתובת המייל שלך
|
||
</div>
|
||
)}
|
||
|
||
<div className="field">
|
||
<label>קוד אימות (6 ספרות)</label>
|
||
<input
|
||
type="text"
|
||
value={verificationCode}
|
||
onChange={(e) => setVerificationCode(e.target.value.replace(/\D/g, '').slice(0, 6))}
|
||
disabled={loading}
|
||
autoFocus
|
||
placeholder="123456"
|
||
maxLength={6}
|
||
style={{ fontSize: "1.2rem", letterSpacing: "0.3rem", textAlign: "center" }}
|
||
/>
|
||
</div>
|
||
|
||
<div className="field">
|
||
<label>סיסמה נוכחית</label>
|
||
<input
|
||
type="password"
|
||
value={currentPassword}
|
||
onChange={(e) => setCurrentPassword(e.target.value)}
|
||
disabled={loading}
|
||
/>
|
||
</div>
|
||
|
||
<div className="field">
|
||
<label>סיסמה חדשה</label>
|
||
<input
|
||
type="password"
|
||
value={newPassword}
|
||
onChange={(e) => setNewPassword(e.target.value)}
|
||
disabled={loading}
|
||
/>
|
||
</div>
|
||
|
||
<div className="field">
|
||
<label>אימות סיסמה חדשה</label>
|
||
<input
|
||
type="password"
|
||
value={confirmPassword}
|
||
onChange={(e) => setConfirmPassword(e.target.value)}
|
||
disabled={loading}
|
||
/>
|
||
</div>
|
||
|
||
<div className="modal-footer">
|
||
<button
|
||
type="button"
|
||
className="btn btn-secondary"
|
||
onClick={onClose}
|
||
disabled={loading}
|
||
>
|
||
ביטול
|
||
</button>
|
||
<button
|
||
type="submit"
|
||
className="btn btn-primary"
|
||
disabled={loading}
|
||
>
|
||
{loading ? "משנה..." : "שמור סיסמה"}
|
||
</button>
|
||
</div>
|
||
</form>
|
||
)}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|