Bug fixed in quaterly windows

This commit is contained in:
Malini 2025-11-06 09:47:15 +05:30
parent 00491af737
commit 07e1c56da8
5 changed files with 66 additions and 151 deletions

View File

@ -570,6 +570,7 @@ export const DateField = ({
rightIcon = calendarIconSrc,
onBlur,
onFocus,
required=false,
...rest
}) => {
const inputRef = React.useRef(null);
@ -647,6 +648,7 @@ export const DateField = ({
{label && (
<label htmlFor={id || name} className="block text-[14px] leading-[20px] font-medium text-[#232528] mb-1">
{label}
{required && <span className="text-[#B91C1C] ml-1">*</span>}
</label>
)}
<div className="relative">
@ -662,6 +664,7 @@ export const DateField = ({
style={inputStyle}
onFocus={handleFocus}
onBlur={handleBlur}
required={required}
{...rest}
/>
{rightIcon && (

View File

@ -35,7 +35,6 @@ export const SurveyStatus = ({ data = null, loading = false, error = '' }) => {
const navigate = useNavigate();
const handleStartSurvey = (survey) => {
console.log('Starting survey:', survey.title);
};
const surveyData = data || {};

View File

@ -67,11 +67,7 @@ export const DetailedOverview = ({ submission, onBack }) => {
try {
setIsLoading(true);
setError(null);
console.log('Fetching submission details for ID:', submission.id);
const response = await fetchSubmissionDetail(submission.id);
console.log('API Response:', response);
const response = await fetchSubmissionDetail(submission.id);
if (response && response.data) {
console.log('Setting submission data:', response.data);
setSubmissionData(response.data);

View File

@ -2,16 +2,13 @@ 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, deleteQuarterlyWindow } from '@/services/configuration/quarterlyWindows';
import { createQuarterlyWindow, updateQuarterlyWindow, getQuarterlyWindows } from '@/services/configuration/quarterlyWindows';
import CustomToast from '@/components/common/CustomToast';
const downloadIconSrc = '/assets/images/DownloadSimple.svg';
const addIconSrc = '/assets/images/ic_baseline-plus.svg';
const pencilActiveSrc = '/assets/images/PencilSimple.svg';
const pencilInactiveSrc = '/assets/images/pencilsimple-inactive.svg';
const trashActiveSrc = '/assets/images/Trash - active.svg';
const trashInactiveSrc = '/assets/images/Trash - Inactive.svg';
const deleteIconSrc = '/assets/images/delete.svg';
const caretDownActiveSrc = '/assets/images/caretdown-active.svg';
const searchIconSrc = '/assets/images/material-symbols_search-rounded.svg';
const caretDownSrc = '/assets/images/CaretDown-black.svg';
@ -31,15 +28,12 @@ const createEmptyQuarterForm = () => ({
const QuarterlyWindows = () => {
const [quarterData, setQuarterData] = React.useState([]);
const [editingRow, setEditingRow] = React.useState(null);
const [deletingRow, setDeletingRow] = React.useState(null);
const [modalMode, setModalMode] = React.useState(null);
const [form, setForm] = React.useState(createEmptyQuarterForm());
const [originalForm, setOriginalForm] = React.useState(null);
const [showDeleteConfirm, setShowDeleteConfirm] = React.useState(false);
const [searchTerm, setSearchTerm] = React.useState('');
const [statusFilter, setStatusFilter] = React.useState('all');
const [hoveredEdit, setHoveredEdit] = React.useState(null);
const [hoveredDelete, setHoveredDelete] = React.useState(null);
const [currentPage, setCurrentPage] = React.useState(1);
const pageSize = 10;
const [isLoading, setIsLoading] = React.useState(false);
@ -76,7 +70,7 @@ const QuarterlyWindows = () => {
startDate: item.start_date || '',
endDate: item.end_date || '',
gracePeriod: item.grace_periods_days ? `${item.grace_periods_days} days` : '0 days',
submissionCount: '0',
submissionCount: item.submission_count?.toString() || '-',
status: item.is_active ? 'Active' : 'Inactive'
}));
setQuarterData(formattedData);
@ -95,13 +89,6 @@ const QuarterlyWindows = () => {
fetchQuarterlyWindows();
}, []);
const deletingQuarter = React.useMemo(() => {
if (deletingRow === null || deletingRow < 0 || deletingRow >= quarterData.length) {
return null;
}
return quarterData[deletingRow];
}, [deletingRow, quarterData]);
const headers = ['Survey Name', 'Year', 'Quarter', 'Start Date', 'End Date', 'Grace Period', 'Submission Count', 'Status', 'Actions'];
const columnwidth = [300, 100, 100, 100, 100, 100, 100, 100, 100];
const filteredRows = React.useMemo(() => {
@ -198,19 +185,9 @@ const QuarterlyWindows = () => {
const openDeleteConfirm = (index) => {
setDeletingRow(index);
setShowDeleteConfirm(true);
};
const closeDeleteConfirm = () => {
setShowDeleteConfirm(false);
setDeletingRow(null);
};
const showToast = (message, type = 'success') => {
setToast({ show: true, message, type });
setTimeout(() => setToast({ ...toast, show: false }), 4000);
setTimeout(() => setToast(prev => ({ ...prev, show: false })), 4000);
};
const handleSave = async () => {
@ -219,6 +196,14 @@ const QuarterlyWindows = () => {
showToast('Please fill in all required fields', 'error');
return;
}
const startDate = new Date(form.startDate);
const endDate = new Date(form.endDate);
if (endDate <= startDate) {
showToast('Close Date must be after Open Date', 'error');
return;
}
const formatDateForAPI = (dateString) => {
if (!dateString) return '';
// If already in YYYY-MM-DD format
@ -234,12 +219,13 @@ const QuarterlyWindows = () => {
return new Date(dateString).toISOString().split('T')[0];
};
const formattedData = {
survey_name: form.survey_name || '',
year: form.year ? parseInt(form.year, 10) : 0,
quarter: form.quarter || '',
start_date: form.startDate ? formatDateForAPI(form.startDate) : '',
end_date: form.endDate ? formatDateForAPI(form.endDate) : '',
start_date: startDate.toISOString().split('T')[0],
end_date: endDate.toISOString().split('T')[0],
grace_periods_days: form.gracePeriod ? parseInt(form.gracePeriod.split(' ')[0], 10) || 0 : 0,
is_active: form.status === 'Active',
establishment: form.establishment || '-',
@ -296,36 +282,6 @@ const QuarterlyWindows = () => {
}
};
const handleDelete = async () => {
if (deletingRow === null) return;
try {
// First, get the item to ensure we have the latest data
const itemToDelete = quarterData[deletingRow];
if (!itemToDelete?.id) {
showToast('Error: Could not find the item to delete', 'error');
closeDeleteConfirm();
return;
}
// Call the delete API with the ID
const response = await deleteQuarterlyWindow(itemToDelete.id);
if (response.status === 'success') {
// Update the UI by removing the deleted item
setQuarterData(prev => prev.filter(item => item.id !== itemToDelete.id));
showToast('Quarterly window deleted successfully!');
} else {
showToast(response.message || 'Failed to delete quarterly window', 'error');
}
} catch (error) {
console.error('Error deleting quarterly window:', error);
showToast('An error occurred while deleting. Please try again.', 'error');
} finally {
closeDeleteConfirm();
}
};
return (
<>
{toast.show && (
@ -434,21 +390,6 @@ const QuarterlyWindows = () => {
className="h-5 w-5"
/>
</button>
<button
type="button"
className="h-8 w-8 grid place-items-center rounded hover:bg-gray-50 cursor-pointer"
title="Delete"
aria-label="Delete quarter"
onClick={() => openDeleteConfirm(rowIndex)}
onMouseEnter={() => setHoveredDelete(rowIndex)}
onMouseLeave={() => setHoveredDelete(null)}
>
<img
src={hoveredDelete === rowIndex || deletingRow === rowIndex ? trashActiveSrc : trashInactiveSrc}
alt="Delete"
className="h-5 w-5"
/>
</button>
</div>
);
}
@ -474,6 +415,28 @@ const QuarterlyWindows = () => {
border: '1px solid #E5E7EB',
}}
>
{/* Toast Notification */}
{toast.show && (
<div className="flex items-center gap-2 bg-[#FEF2F2] border-l-4 border-[#DC2626] p-3 w-[calc(100%-32px)] mx-auto mt-4 rounded">
<svg
className="flex-shrink-0 w-4 h-4 text-[#DC2626]"
fill="currentColor"
viewBox="0 0 20 20"
>
<path
fillRule="evenodd"
d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z"
clipRule="evenodd"
/>
</svg>
<span className="text-sm font-medium text-[#DC2626] leading-tight">
{toast.message}
</span>
</div>
)}
<div className="flex items-center justify-between px-6 py-4 border-b border-[#F1F2F4]">
<h3 className="text-[18px] font-medium text-[#232528]">
{modalMode === 'edit' ? 'Edit Quarter' : 'Create Quarterly Survey'}
@ -512,6 +475,7 @@ const QuarterlyWindows = () => {
<TextField
label="Survey Name"
value={form.survey_name}
required
onChange={(e) => setForm({ ...form, survey_name: e.target.value })}
placeholder="Enter survey name"
/>
@ -520,6 +484,7 @@ const QuarterlyWindows = () => {
<SelectField
label="Quarter"
value={form.quarter}
required
onChange={(e) => setForm({ ...form, quarter: e.target.value })}
options={['Q1', 'Q2', 'Q3', 'Q4'].map((q) => ({ label: q, value: q }))}
placeholder="Select Quarter"
@ -532,17 +497,20 @@ const QuarterlyWindows = () => {
const yr = 2023 + idx;
return { label: String(yr), value: String(yr) };
})}
required
placeholder="Select Year"
/>
<DateField
label="Opens On"
value={form.startDate}
required
onChange={(e) => setForm({ ...form, startDate: e.target.value })}
placeholder="Select Date"
/>
<DateField
label="Closes On"
value={form.endDate}
required
onChange={(e) => setForm({ ...form, endDate: e.target.value })}
placeholder="Select Date"
/>
@ -559,6 +527,7 @@ const QuarterlyWindows = () => {
<SelectField
label="Status"
value={form.status}
required
onChange={(e) => setForm({ ...form, status: e.target.value })}
options={[
{ label: 'Active', value: 'Active' },
@ -589,66 +558,6 @@ const QuarterlyWindows = () => {
</div>
)}
{showDeleteConfirm && (
<div className="fixed inset-0 z-50">
<div
className="absolute inset-0 bg-black/40"
onClick={() => {
setShowDeleteConfirm(false);
setDeletingRow(null);
}}
/>
<div
className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 rounded-lg bg-white border"
style={{
width: '480px',
borderColor: '#CBD5E1',
boxShadow: '0 20px 45px rgba(0,0,0,0.12)',
}}
>
<div className="px-8 py-6 space-y-6">
<div className="flex items-start gap-3">
<img src={deleteIconSrc} alt="Delete" className="h-6 w-6 mt-1" />
<div className="flex-1">
<h3 className="text-[18px] font-semibold text-[#232528]">
Delete Product
</h3>
<p className="mt-1 text-sm text-[#4B5563]">
Are you sure you want to delete{' '}
<span className="font-semibold text-[#232528]">
{rowsData[deletingRow]?.product || 'this product'}?
</span>
</p>
<p className="mt-2 text-sm text-[#4B5563]">
This action will permanently delete the data and cannot be undone.
</p>
</div>
</div>
<div className="flex justify-end gap-4">
<button
type="button"
className="h-10 px-6 rounded-md border border-[#92722A] text-sm font-medium text-[#92722A] bg-white"
onClick={() => {
setShowDeleteConfirm(false);
setDeletingRow(null);
}}
>
Cancel
</button>
<button
type="button"
className="h-10 px-6 rounded-md bg-[#92722A] text-white text-sm font-semibold"
onClick={handleConfirmDelete}
disabled={isLoading}
>
{isLoading ? 'Deleting...' : 'Delete'}
</button>
</div>
</div>
</div>
</div>
)}
</div>
</>
);

View File

@ -57,17 +57,23 @@ const fetchUnits = async () => {
try {
setLoading(true);
const response = await getUnits();
console.log("resposne",response)
console.log("API Response:", response); // Log the full response
const unitsData = response.data || [];
console.log("Units Data:", unitsData); // Log the units data
// Process units to ensure mapped_products_count is included
const processedUnits = unitsData.map(unit => ({
...unit,
// Use existing mapped_products_count or calculate from productsMapped array
mapped_products_count: unit.mapped_products_count ||
(Array.isArray(unit.productsMapped) ? unit.productsMapped.length : 0)
}));
console.log("processedUnits",processedUnits)
const processedUnits = unitsData.map(unit => {
console.log("Processing unit:", unit); // Log each unit being processed
return {
...unit,
mapped_products_count: unit.mapped_products_count !== undefined
? unit.mapped_products_count
: (Array.isArray(unit.productsMapped) ? unit.productsMapped.length : 0)
};
});
console.log("Processed Units:", processedUnits); // Log the processed units
// Sort by latest created_at date (newest first)
const sortedUnits = [...processedUnits].sort(
@ -113,18 +119,20 @@ const fetchUnits = async () => {
: '-';
const currentUserName = currentUser?.name || '';
console.log("Rendering row with item:", item); // Log the item being rendered
return [
item.uom || item.unitName, // Unit Name
item.uom_short_name || item.description, // Description
Array.isArray(item.productsMapped) ? item.productsMapped.length : 0, // Mapped Products
item.mapped_products_count !== undefined ? item.mapped_products_count : '-', // Mapped Products Count
item.created_by_name || currentUserName || '-', // Created By
createdDate, // Created On
updatedDate, // Last Update (moved here)
updatedDate, // Last Update
<StatusBadge
status={item.is_active ? 'Active' : 'Inactive'}
tone={item.is_active ? 'green' : 'gray'}
/>, // Status
'actions', // Actions
/>, // Status
'actions', // Actions
];
});
}, [units, currentUser]);