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 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 [newPassword, setNewPassword] = React.useState("");
@ -132,6 +137,7 @@ if (newPassword !== confirmPassword) {
otp: otp.trim(),
password: newPassword,
confirm_password: confirmPassword,
user_type: userType // Use the user_type from location state
};
const response = await apiClient.post("/forgot-password/verify-otp", payload);
@ -197,6 +203,21 @@ if (newPassword !== confirmPassword) {
/>
</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
label="Verification Code"
required

View File

@ -1,97 +1,172 @@
import React, { useState } from "react";
import { ChevronDown, ChevronUp } from "lucide-react"; // Up/Down icons
import React, { useState, useRef, useEffect } from "react";
import { ChevronDown, ChevronUp } from "lucide-react";
const Faq = () => {
const [openIndex, setOpenIndex] = useState(null);
const faqs = [
const [openIndexLeft, setOpenIndexLeft] = useState(null);
const [openIndexRight, setOpenIndexRight] = useState(null);
// FULL FAQ DATA
const leftFaqs = [
{
question: "Do I need an account to respond?",
answer:
"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?",
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?",
answer:
"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?",
answer:
"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?",
answer: "See Need help below.",
},
];
const toggleFaq = (index) => {
setOpenIndex(openIndex === index ? null : index);
// Auto height expand component
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 (
<section className="bg-[#fafafa] py-12 px-6 md:px-16 lg:px-24">
<h2 className="text-2xl font-semibold text-gray-900 mb-8">
Frequently asked questions
</h2>
<div className="grid md:grid-cols-2 gap-6">
{faqs.map((faq, index) => {
const isOpen = openIndex === index;
return (
<div
key={index}
className={`border rounded-xl p-5 shadow-sm transition-all duration-300 bg-white ${
isOpen ? "border-gray-200" : "border-gray-200"
}`}
>
<button
onClick={() => toggleFaq(index)}
className="w-full flex justify-between items-center text-left"
{/* TWO FULLY INDEPENDENT COLUMNS */}
<div className="grid md:grid-cols-2 gap-10">
{/* LEFT COLUMN */}
<div className="flex flex-col gap-6">
{leftFaqs.map((faq, index) => {
const isOpen = openIndexLeft === index;
return (
<div
key={index}
className="bg-white rounded-xl p-5 shadow-sm transition-all duration-300"
>
<span
className={`font-medium ${
isOpen ? "text-yellow-800" : "text-gray-900"
}`}
<button
onClick={() =>
setOpenIndexLeft(isOpen ? null : index)
}
className="w-full flex justify-between items-center text-left"
>
{faq.question}
</span>
{isOpen ? (
<ChevronUp size={22} className="text-yellow-700" /> // when open
) : (
<ChevronDown size={22} className="text-gray-600" /> // when closed
)}
</button>
{isOpen && (
<p className="mt-3 text-gray-700 text-sm leading-relaxed">
{faq.answer}
</p>
)}
</div>
);
})}
<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>
{/* 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>
</div>
</section>
);
};
export default Faq;
export default Faq;

View File

@ -8,6 +8,7 @@ const PublicContactForm = () => {
const navigate = useNavigate();
const [formData, setFormData] = useState({
userType: "establishment_user",
establishmentName: "",
establishmentId: "",
email: "",
@ -74,7 +75,13 @@ const PublicContactForm = () => {
const validate = (data = formData) => {
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.";
else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(data.email))
newErrors.email = "Enter a valid email address.";
@ -113,6 +120,7 @@ const PublicContactForm = () => {
setLoading(true);
try {
const payload = {
user_type: formData.userType,
establishment_name: formData.establishmentName.trim(),
establishment_code: formData.establishmentId.trim(),
registered_email: formData.email.trim(),
@ -124,7 +132,10 @@ const PublicContactForm = () => {
showToast('success', 'Verification Code sent to your registered email successfully!');
setTimeout(() => {
navigate("/change-password", {
state: { email: formData.email.trim() },
state: {
email: formData.email.trim(),
user_type: formData.userType
},
});
}, 1500);
} else {
@ -156,13 +167,19 @@ const PublicContactForm = () => {
const payload = {
registered_email: formData.email.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);
if (response?.data?.status === "success") {
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 {
const serverMsg = response?.data?.message?.toLowerCase() || "";
@ -240,27 +257,74 @@ const PublicContactForm = () => {
{errorMsg}
</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 && (
<div className="text-sm text-green-700 bg-green-50 border border-green-200 rounded px-3 py-2">
{success}
</div>
)}
<InputField
label="Establishment Name"
name="establishmentName"
required
value={formData.establishmentName}
onChange={handleChange}
error={errors.establishmentName}
/>
<InputField
label="Establishment ID"
name="establishmentId"
required
value={formData.establishmentId}
onChange={handleChange}
/>
{formData.userType === 'establishment_user' && (
<div className="space-y-4">
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Establishment Name <span className="text-red-500">*</span>
</label>
<input
type="text"
name="establishmentName"
value={formData.establishmentName}
onChange={handleChange}
className={`block w-full h-10 rounded-md border-2 ${
errors.establishmentName ? "border-red-500" : "border-[#92722A]"
} 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
label="Registered Email"
name="email"