client side bug fixed

This commit is contained in:
Malini 2025-11-19 16:06:18 +05:30
parent 9b015fe922
commit 2aa572ad1f
3 changed files with 239 additions and 79 deletions

View File

@ -59,7 +59,12 @@ const ChangePassword = () => {
const navigate = useNavigate(); const navigate = useNavigate();
const location = useLocation(); const location = useLocation();
const registeredEmail = location.state?.email || ""; const { email: registeredEmail, user_type: userType } = location.state || {};
// Ensure user_type is set in the form data
const [formData, setFormData] = React.useState({
user_type: userType
});
const [otp, setOtp] = React.useState(""); const [otp, setOtp] = React.useState("");
const [newPassword, setNewPassword] = React.useState(""); const [newPassword, setNewPassword] = React.useState("");
@ -132,6 +137,7 @@ if (newPassword !== confirmPassword) {
otp: otp.trim(), otp: otp.trim(),
password: newPassword, password: newPassword,
confirm_password: confirmPassword, confirm_password: confirmPassword,
user_type: userType // Use the user_type from location state
}; };
const response = await apiClient.post("/forgot-password/verify-otp", payload); const response = await apiClient.post("/forgot-password/verify-otp", payload);
@ -197,6 +203,21 @@ if (newPassword !== confirmPassword) {
/> />
</div> </div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
User Type
</label>
<div className="relative">
<input
type="text"
disabled
value={userType === 'admin_user' ? 'Admin' : 'Establishment'}
className="block w-full h-10 rounded-md border-2 border-gray-300 px-4 text-sm bg-gray-50 cursor-not-allowed"
/>
<input type="hidden" name="user_type" value={userType} />
</div>
</div>
<ToggleableInput <ToggleableInput
label="Verification Code" label="Verification Code"
required required

View File

@ -1,50 +1,76 @@
import React, { useState } from "react"; import React, { useState, useRef, useEffect } from "react";
import { ChevronDown, ChevronUp } from "lucide-react"; // Up/Down icons import { ChevronDown, ChevronUp } from "lucide-react";
const Faq = () => { const Faq = () => {
const [openIndex, setOpenIndex] = useState(null); const [openIndexLeft, setOpenIndexLeft] = useState(null);
const [openIndexRight, setOpenIndexRight] = useState(null);
const faqs = [ // FULL FAQ DATA
const leftFaqs = [
{ {
question: "Do I need an account to respond?", question: "Do I need an account to respond?",
answer: answer:
"Yes. FCSC provisions accounts to selected establishments. Use Login to access the survey.", "Yes. FCSC provisions accounts to selected establishments. Use Login to access the survey.",
}, },
{
question: "Can I register myself?",
answer:
"No. There is no self-registration. If you were contacted but cant access your account, use Forgot password or Contact support.",
},
{ {
question: "Is my data public?", question: "Is my data public?",
answer: "No. Results are published only in aggregate form.", answer: "No. Results are published only in aggregate form.",
}, },
{
question: "What if production was zero in a month?",
answer: "Enter 0 for the month and provide a reason when prompted.",
},
{ {
question: "Can I update after submission?", question: "Can I update after submission?",
answer: answer:
"Yes, if a revision window is open or if FCSC requests a correction.", "Yes, if a revision window is open or if FCSC requests a correction.",
}, },
{
question: "Which browser is supported?",
answer: "Latest Chrome, Edge, Safari.",
},
{ {
question: "How long does it take?", question: "How long does it take?",
answer: answer:
"Most respondents complete within minutes each quarter, depending on product lines.", "Most respondents complete within minutes each quarter, depending on product lines.",
}, },
];
const rightFaqs = [
{
question: "Can I register myself?",
answer:
"No. There is no self-registration. If you were contacted but cant access your account, use Forgot password or Contact support.",
},
{
question: "What if production was zero in a month?",
answer: "Enter 0 for the month and provide a reason when prompted.",
},
{
question: "Which browser is supported?",
answer: "Latest Chrome, Edge, Safari.",
},
{ {
question: "Who can I contact?", question: "Who can I contact?",
answer: "See Need help below.", answer: "See Need help below.",
}, },
]; ];
const toggleFaq = (index) => { // Auto height expand component
setOpenIndex(openIndex === index ? null : index); const Expandable = ({ isOpen, children }) => {
const ref = useRef(null);
useEffect(() => {
if (isOpen) {
ref.current.style.maxHeight = ref.current.scrollHeight + "px";
} else {
ref.current.style.maxHeight = "0px";
}
}, [isOpen]);
return (
<div
ref={ref}
className={`overflow-hidden transition-[max-height] duration-300 ${
isOpen ? "mt-3" : ""
}`}
style={{ maxHeight: "0px" }}
>
{children}
</div>
);
}; };
return ( return (
@ -53,42 +79,91 @@ const Faq = () => {
Frequently asked questions Frequently asked questions
</h2> </h2>
<div className="grid md:grid-cols-2 gap-6"> {/* TWO FULLY INDEPENDENT COLUMNS */}
{faqs.map((faq, index) => { <div className="grid md:grid-cols-2 gap-10">
const isOpen = openIndex === index;
return ( {/* LEFT COLUMN */}
<div <div className="flex flex-col gap-6">
key={index} {leftFaqs.map((faq, index) => {
className={`border rounded-xl p-5 shadow-sm transition-all duration-300 bg-white ${ const isOpen = openIndexLeft === index;
isOpen ? "border-gray-200" : "border-gray-200"
}`} return (
> <div
<button key={index}
onClick={() => toggleFaq(index)} className="bg-white rounded-xl p-5 shadow-sm transition-all duration-300"
className="w-full flex justify-between items-center text-left" >
> <button
<span onClick={() =>
className={`font-medium ${ setOpenIndexLeft(isOpen ? null : index)
isOpen ? "text-yellow-800" : "text-gray-900" }
}`} className="w-full flex justify-between items-center text-left"
> >
{faq.question} <span
</span> className={`font-medium ${
{isOpen ? ( isOpen ? "text-yellow-800" : "text-gray-900"
<ChevronUp size={22} className="text-yellow-700" /> // when open }`}
) : ( >
<ChevronDown size={22} className="text-gray-600" /> // when closed {faq.question}
)} </span>
</button>
{isOpen ? (
<ChevronUp size={22} className="text-yellow-700" />
) : (
<ChevronDown size={22} className="text-gray-600" />
)}
</button>
<Expandable isOpen={isOpen}>
<p className="text-gray-700 text-sm leading-relaxed">
{faq.answer}
</p>
</Expandable>
</div>
);
})}
</div>
{/* RIGHT COLUMN */}
<div className="flex flex-col gap-6">
{rightFaqs.map((faq, index) => {
const isOpen = openIndexRight === index;
return (
<div
key={index}
className="bg-white rounded-xl p-5 shadow-sm transition-all duration-300"
>
<button
onClick={() =>
setOpenIndexRight(isOpen ? null : index)
}
className="w-full flex justify-between items-center text-left"
>
<span
className={`font-medium ${
isOpen ? "text-yellow-800" : "text-gray-900"
}`}
>
{faq.question}
</span>
{isOpen ? (
<ChevronUp size={22} className="text-yellow-700" />
) : (
<ChevronDown size={22} className="text-gray-600" />
)}
</button>
<Expandable isOpen={isOpen}>
<p className="text-gray-700 text-sm leading-relaxed">
{faq.answer}
</p>
</Expandable>
</div>
);
})}
</div>
{isOpen && (
<p className="mt-3 text-gray-700 text-sm leading-relaxed">
{faq.answer}
</p>
)}
</div>
);
})}
</div> </div>
</section> </section>
); );

View File

@ -8,6 +8,7 @@ const PublicContactForm = () => {
const navigate = useNavigate(); const navigate = useNavigate();
const [formData, setFormData] = useState({ const [formData, setFormData] = useState({
userType: "establishment_user",
establishmentName: "", establishmentName: "",
establishmentId: "", establishmentId: "",
email: "", email: "",
@ -74,7 +75,13 @@ const PublicContactForm = () => {
const validate = (data = formData) => { const validate = (data = formData) => {
const newErrors = {}; const newErrors = {};
if (!data.establishmentName.trim()) newErrors.establishmentName = "Required."; if (!data.userType) {
newErrors.userType = "Please select user type";
} else if (data.userType === 'establishment_user') {
if (!data.establishmentName.trim()) newErrors.establishmentName = "Required.";
if (!data.establishmentId.trim()) newErrors.establishmentId = "Required.";
}
if (!data.email.trim()) newErrors.email = "Required."; if (!data.email.trim()) newErrors.email = "Required.";
else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(data.email)) else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(data.email))
newErrors.email = "Enter a valid email address."; newErrors.email = "Enter a valid email address.";
@ -113,6 +120,7 @@ const PublicContactForm = () => {
setLoading(true); setLoading(true);
try { try {
const payload = { const payload = {
user_type: formData.userType,
establishment_name: formData.establishmentName.trim(), establishment_name: formData.establishmentName.trim(),
establishment_code: formData.establishmentId.trim(), establishment_code: formData.establishmentId.trim(),
registered_email: formData.email.trim(), registered_email: formData.email.trim(),
@ -124,7 +132,10 @@ const PublicContactForm = () => {
showToast('success', 'Verification Code sent to your registered email successfully!'); showToast('success', 'Verification Code sent to your registered email successfully!');
setTimeout(() => { setTimeout(() => {
navigate("/change-password", { navigate("/change-password", {
state: { email: formData.email.trim() }, state: {
email: formData.email.trim(),
user_type: formData.userType
},
}); });
}, 1500); }, 1500);
} else { } else {
@ -156,13 +167,19 @@ const PublicContactForm = () => {
const payload = { const payload = {
registered_email: formData.email.trim(), registered_email: formData.email.trim(),
otp: otp.trim(), otp: otp.trim(),
user_type: formData.userType // Add user_type to the verification request
}; };
const response = await apiClient.post("/forgot-password/verify-otp", payload); const response = await apiClient.post("/forgot-password/verify-otp", payload);
if (response?.data?.status === "success") { if (response?.data?.status === "success") {
setSuccess("Verification Code verified successfully. Redirecting to change password..."); setSuccess("Verification Code verified successfully. Redirecting to change password...");
setTimeout(() => navigate("/change-password"), 1500); setTimeout(() => navigate("/change-password", {
state: {
email: formData.email.trim(),
user_type: formData.userType // Ensure user_type is passed
}
}), 1500);
} else { } else {
const serverMsg = response?.data?.message?.toLowerCase() || ""; const serverMsg = response?.data?.message?.toLowerCase() || "";
@ -240,27 +257,74 @@ const PublicContactForm = () => {
{errorMsg} {errorMsg}
</div> </div>
)} )}
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
User Type <span className="text-red-500">*</span>
</label>
<select
name="userType"
value={formData.userType}
onChange={handleChange}
className={`w-full px-3 py-2 border ${
errors.userType ? 'border-red-300' : 'border-gray-300'
} rounded-md shadow-sm focus:outline-none focus:ring-1 focus:ring-[#92722A] focus:border-[#92722A]`}
>
<option value="establishment_user">Establishment</option>
<option value="admin_user">Admin</option>
</select>
{errors.userType && (
<p className="mt-1 text-sm text-red-600">{errors.userType}</p>
)}
</div>
{success && ( {success && (
<div className="text-sm text-green-700 bg-green-50 border border-green-200 rounded px-3 py-2"> <div className="text-sm text-green-700 bg-green-50 border border-green-200 rounded px-3 py-2">
{success} {success}
</div> </div>
)} )}
<InputField {formData.userType === 'establishment_user' && (
label="Establishment Name" <div className="space-y-4">
name="establishmentName" <div>
required <label className="block text-sm font-medium text-gray-700 mb-1">
value={formData.establishmentName} Establishment Name <span className="text-red-500">*</span>
onChange={handleChange} </label>
error={errors.establishmentName} <input
/> type="text"
<InputField name="establishmentName"
label="Establishment ID" value={formData.establishmentName}
name="establishmentId" onChange={handleChange}
required className={`block w-full h-10 rounded-md border-2 ${
value={formData.establishmentId} errors.establishmentName ? "border-red-500" : "border-[#92722A]"
onChange={handleChange} } focus:border-[#92722A] focus:ring-0 px-4 text-sm`}
/> placeholder="Enter establishment name"
/>
{errors.establishmentName && (
<p className="text-xs text-red-600 mt-1">{errors.establishmentName}</p>
)}
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Establishment ID <span className="text-red-500">*</span>
</label>
<input
type="text"
name="establishmentId"
value={formData.establishmentId}
onChange={handleChange}
className={`block w-full h-10 rounded-md border-2 ${
errors.establishmentId ? "border-red-500" : "border-[#92722A]"
} focus:border-[#92722A] focus:ring-0 px-4 text-sm`}
placeholder="Enter establishment ID"
/>
{errors.establishmentId && (
<p className="text-xs text-red-600 mt-1">{errors.establishmentId}</p>
)}
</div>
</div>
)}
<InputField <InputField
label="Registered Email" label="Registered Email"
name="email" name="email"