bug fixed
This commit is contained in:
parent
142bd4f21f
commit
9d5ca6874f
@ -2,7 +2,7 @@ import React from 'react';
|
||||
import Table from '@/components/common/Table';
|
||||
import { TextField, SelectField, DateField } from '@/components/common/FormControls';
|
||||
import StatusBadge from '@/components/common/StatusBadge';
|
||||
import { createQuarterlyWindow, updateQuarterlyWindow, getQuarterlyWindows } from '@/services/configuration/quarterlyWindows';
|
||||
import { createQuarterlyWindow, updateQuarterlyWindow, getQuarterlyWindows, getQuarterlyWindowById } from '@/services/configuration/quarterlyWindows';
|
||||
|
||||
const downloadIconSrc = '/assets/images/DownloadSimple.svg';
|
||||
const addIconSrc = '/assets/images/ic_baseline-plus.svg';
|
||||
@ -275,19 +275,56 @@ const QuarterlyWindows = () => {
|
||||
setCurrentPage((prev) => Math.min(prev, maxPage));
|
||||
}, [filteredRows.length, pageSize]);
|
||||
|
||||
const openEditModal = (index) => {
|
||||
const selected = quarterData[index];
|
||||
// Ensure dates are in the correct format for the form inputs
|
||||
const formData = {
|
||||
...selected,
|
||||
startDate: selected.startDate ? formatDateForInput(selected.startDate) : '',
|
||||
endDate: selected.endDate ? formatDateForInput(selected.endDate) : ''
|
||||
};
|
||||
setEditingRow(index);
|
||||
setForm(formData);
|
||||
setOriginalForm(formData);
|
||||
setModalMode('edit');
|
||||
setValidationErrors({});
|
||||
const openEditModal = async (index) => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
|
||||
// Calculate the actual index in the filtered data based on pagination
|
||||
const actualIndex = (currentPage - 1) * pageSize + index;
|
||||
const selected = filteredRows[actualIndex];
|
||||
|
||||
if (!selected || !selected.id) {
|
||||
throw new Error('Invalid quarterly window selected');
|
||||
}
|
||||
|
||||
// Fetch the latest data for this quarter
|
||||
const response = await getQuarterlyWindowById(selected.id);
|
||||
|
||||
if (response && response.data) {
|
||||
const quarterData = response.data;
|
||||
const formData = {
|
||||
id: quarterData.id,
|
||||
survey_name: quarterData.survey_name || '',
|
||||
establishment: quarterData.establishment || '-',
|
||||
year: quarterData.year?.toString() || '',
|
||||
quarter: quarterData.quarter || '',
|
||||
startDate: quarterData.start_date ? formatDateForInput(quarterData.start_date) : '',
|
||||
endDate: quarterData.end_date ? formatDateForInput(quarterData.end_date) : '',
|
||||
gracePeriod: quarterData.grace_periods_days ? `${quarterData.grace_periods_days} days` : '0 days',
|
||||
submissionCount: quarterData.submission_count?.toString() || '-',
|
||||
assigned: quarterData.assigned?.toString() || '0',
|
||||
responded: quarterData.responded?.toString() || '0',
|
||||
not_responded: quarterData.not_responded?.toString() || '0',
|
||||
status: quarterData.is_active ? 'Active' : 'Inactive'
|
||||
};
|
||||
|
||||
setEditingRow(actualIndex);
|
||||
setForm(formData);
|
||||
setOriginalForm(formData);
|
||||
setModalMode('edit');
|
||||
setValidationErrors({});
|
||||
} else {
|
||||
throw new Error('No data returned from server');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error in openEditModal:', error);
|
||||
setToastData({
|
||||
message: 'Failed to load quarterly window details. Please try again.',
|
||||
type: 'error'
|
||||
});
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleCloseModal = () => {
|
||||
|
||||
@ -33,10 +33,17 @@ const Banner = () => {
|
||||
</a>
|
||||
<button
|
||||
onClick={() => {
|
||||
// Scroll to How it works section
|
||||
// Scroll to How it works section with offset for fixed header
|
||||
const howItWorksSection = document.getElementById('how-it-works');
|
||||
if (howItWorksSection) {
|
||||
howItWorksSection.scrollIntoView({ behavior: 'smooth' });
|
||||
const headerOffset = 80; // Same as in Navbar.jsx
|
||||
const elementPosition = howItWorksSection.getBoundingClientRect().top;
|
||||
const offsetPosition = elementPosition + window.pageYOffset - headerOffset;
|
||||
|
||||
window.scrollTo({
|
||||
top: offsetPosition,
|
||||
behavior: 'smooth'
|
||||
});
|
||||
}
|
||||
}}
|
||||
className="border-2 border-[#92722A] text-[#92722A] text-md px-5 py-2 rounded-md hover:bg-[#f9f6ec] transition-all shadow-sm"
|
||||
|
||||
@ -49,13 +49,20 @@ const Navbar = () => {
|
||||
: "text-gray-800 hover:text-[#b9933b]"
|
||||
}`;
|
||||
|
||||
// Scroll and highlight on click
|
||||
// Scroll and highlight on click with offset for fixed header
|
||||
const handleClick = (id) => {
|
||||
setActiveSection(id);
|
||||
closeMenu();
|
||||
const section = document.getElementById(id);
|
||||
if (section) {
|
||||
section.scrollIntoView({ behavior: "smooth", block: "start" });
|
||||
const headerOffset = 80; // Height of your fixed header
|
||||
const elementPosition = section.getBoundingClientRect().top;
|
||||
const offsetPosition = elementPosition + window.pageYOffset - headerOffset;
|
||||
|
||||
window.scrollTo({
|
||||
top: offsetPosition,
|
||||
behavior: "smooth"
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@ -124,8 +131,9 @@ const Navbar = () => {
|
||||
)}
|
||||
</header>
|
||||
|
||||
{/* Sections */}
|
||||
<div className="pt-20 scroll-smooth">
|
||||
{/* Sections with proper spacing */}
|
||||
<div className="scroll-smooth">
|
||||
<div className="pt-24">
|
||||
<Banner />
|
||||
<section id="about-ipi"><Industrial /></section>
|
||||
<section id="how-it-works"><Cards /></section>
|
||||
@ -138,6 +146,7 @@ const Navbar = () => {
|
||||
<section id="faqs"><Faq /></section>
|
||||
<Cta/>
|
||||
<Footer />
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
@ -109,19 +109,26 @@ const Login = () => {
|
||||
React.useEffect(() => {
|
||||
generateCaptcha();
|
||||
|
||||
const lockUntil = localStorage.getItem('lock_until');
|
||||
const attempts = parseInt(localStorage.getItem('failed_attempts') || '0', 10);
|
||||
// Get the stored attempts and lock status for the current email
|
||||
const storedAttempts = JSON.parse(localStorage.getItem('login_attempts') || '{}');
|
||||
const emailAttempts = storedAttempts[email] || { attempts: 0, lockUntil: null };
|
||||
|
||||
setFailedAttempts(emailAttempts.attempts);
|
||||
|
||||
if (lockUntil && Date.now() < parseInt(lockUntil, 10)) {
|
||||
if (emailAttempts.lockUntil && Date.now() < emailAttempts.lockUntil) {
|
||||
setIsLocked(true);
|
||||
setLockExpiry(lockUntil);
|
||||
startCountdown(lockUntil);
|
||||
setLockExpiry(emailAttempts.lockUntil);
|
||||
startCountdown(emailAttempts.lockUntil);
|
||||
} else if (emailAttempts.lockUntil) {
|
||||
// Clear expired lock
|
||||
const updatedAttempts = { ...storedAttempts };
|
||||
delete updatedAttempts[email];
|
||||
localStorage.setItem('login_attempts', JSON.stringify(updatedAttempts));
|
||||
setIsLocked(false);
|
||||
} else {
|
||||
localStorage.removeItem('lock_until');
|
||||
setIsLocked(false);
|
||||
}
|
||||
setFailedAttempts(attempts);
|
||||
}, [generateCaptcha, startCountdown]);
|
||||
}, [generateCaptcha, startCountdown, email]);
|
||||
|
||||
React.useEffect(
|
||||
() => () => {
|
||||
@ -225,8 +232,13 @@ const Login = () => {
|
||||
String(role || '').toLowerCase() === 'admin' || payload?.is_admin === true;
|
||||
const successMessage = response?.message || 'Login successful.';
|
||||
|
||||
localStorage.removeItem('failed_attempts');
|
||||
localStorage.removeItem('lock_until');
|
||||
// Clear login attempts for this email
|
||||
const storedAttempts = JSON.parse(localStorage.getItem('login_attempts') || '{}');
|
||||
if (storedAttempts[email]) {
|
||||
delete storedAttempts[email];
|
||||
localStorage.setItem('login_attempts', JSON.stringify(storedAttempts));
|
||||
}
|
||||
|
||||
setFailedAttempts(0);
|
||||
setIsLocked(false);
|
||||
setRemainingTime(0);
|
||||
@ -262,15 +274,27 @@ const Login = () => {
|
||||
} catch (err) {
|
||||
console.error('Login failed', err);
|
||||
|
||||
const attempts = failedAttempts + 1;
|
||||
localStorage.setItem('failed_attempts', attempts);
|
||||
const storedAttempts = JSON.parse(localStorage.getItem('login_attempts') || '{}');
|
||||
const attempts = (storedAttempts[email]?.attempts || 0) + 1;
|
||||
|
||||
// Update attempts for this email
|
||||
const updatedAttempts = {
|
||||
...storedAttempts,
|
||||
[email]: {
|
||||
attempts,
|
||||
lockUntil: attempts >= MAX_FAILED_ATTEMPTS
|
||||
? Date.now() + LOCK_DURATION_MINUTES * 60 * 1000
|
||||
: null
|
||||
}
|
||||
};
|
||||
|
||||
localStorage.setItem('login_attempts', JSON.stringify(updatedAttempts));
|
||||
setFailedAttempts(attempts);
|
||||
|
||||
refreshCaptcha();
|
||||
|
||||
if (attempts >= MAX_FAILED_ATTEMPTS) {
|
||||
const lockUntil = Date.now() + LOCK_DURATION_MINUTES * 60 * 1000;
|
||||
localStorage.setItem('lock_until', lockUntil);
|
||||
setIsLocked(true);
|
||||
setLockExpiry(lockUntil);
|
||||
startCountdown(lockUntil);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user