changes in inline styles
This commit is contained in:
parent
fce67c8e02
commit
1796b3aea4
@ -1,16 +1,13 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
const StatCard = ({ icon = null, label, value, tooltipText, width = 200.4 }) => {
|
const StatCard = ({ icon = null, label, value, tooltipText, width = 200.4 }) => {
|
||||||
const resolvedWidth = typeof width === 'number' ? `${width}px` : width;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="relative group flex flex-col items-center justify-center rounded-[8px] border border-[#E3E5E8] bg-white px-5 py-5 shadow-[0_8px_20px_rgba(42,47,66,0.06)]"
|
className={`relative group flex flex-col items-center justify-center rounded-lg border border-gray-200 bg-white px-5 py-5 shadow-sm ${typeof width === 'number' ? `w-[${width}px]` : `w-${width}`} min-h-[120px]`}
|
||||||
style={{ width: resolvedWidth, minHeight: '120px' }}
|
|
||||||
>
|
>
|
||||||
<div className="flex items-center justify-center gap-2 whitespace-nowrap">
|
<div className="flex items-center justify-center gap-2 whitespace-nowrap">
|
||||||
{icon && <div className="flex items-center justify-center w-5 h-5">{icon}</div>}
|
{icon && <div className="flex items-center justify-center w-5 h-5">{icon}</div>}
|
||||||
<span className="text-[15px] font-medium text-[#5F646D] leading-[22px] text-center truncate">
|
<span className="text-sm font-medium text-gray-600 leading-5 text-center truncate">
|
||||||
{label}
|
{label}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -324,10 +324,9 @@ const tableRows = filtered.map((item) => [
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="border border-[#E5E7EB] bg-white shadow-[0_8px_16px_rgba(15,23,42,0.05)] rounded-[6px] w-full overflow-hidden py-2"
|
className={`border border-gray-200 bg-white shadow-sm rounded-md w-full overflow-hidden py-2 ${
|
||||||
style={{
|
filtered.length === 0 || loading ? 'min-h-auto' : 'min-h-[200px]'
|
||||||
minHeight: filtered.length === 0 || loading ? 'auto' : '200px',
|
}`}
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<div className="flex justify-between items-center px-4 pr-6 py-2 mt-3">
|
<div className="flex justify-between items-center px-4 pr-6 py-2 mt-3">
|
||||||
<h2 className="text-[18px] leading-[28px] font-medium text-[#232528]">
|
<h2 className="text-[18px] leading-[28px] font-medium text-[#232528]">
|
||||||
|
|||||||
@ -13,19 +13,10 @@ const CustomToast = ({ message, type = 'success', onClose, duration = 4000 }) =>
|
|||||||
: 'bg-red-50 border border-red-500 text-red-700';
|
: 'bg-red-50 border border-red-500 text-red-700';
|
||||||
const Icon = isSuccess ? CheckCircle : XCircle;
|
const Icon = isSuccess ? CheckCircle : XCircle;
|
||||||
|
|
||||||
// In CustomToast.jsx
|
return (
|
||||||
// return (
|
<div
|
||||||
// In CustomToast.jsx
|
className={`fixed top-4 left-1/2 -translate-x-1/2 flex items-start gap-3 p-4 rounded-lg shadow-md ${bgColor} z-[10000] min-w-[320px] max-w-[90%] animate-[fadeIn_0.3s_ease-out]`}
|
||||||
return (
|
>
|
||||||
<div
|
|
||||||
className={`fixed top-4 left-1/2 -translate-x-1/2 flex items-start gap-3 p-4 rounded-lg shadow-md ${bgColor} animate-fade-in`}
|
|
||||||
style={{
|
|
||||||
zIndex: 10000,
|
|
||||||
minWidth: '320px',
|
|
||||||
maxWidth: '90%',
|
|
||||||
animation: 'fadeIn 0.3s ease-out',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Icon className="w-5 h-5 mt-0.5 flex-shrink-0" />
|
<Icon className="w-5 h-5 mt-0.5 flex-shrink-0" />
|
||||||
<div className="flex-1 text-sm font-medium">{message}</div>
|
<div className="flex-1 text-sm font-medium">{message}</div>
|
||||||
<button
|
<button
|
||||||
|
|||||||
@ -363,14 +363,14 @@ export const SelectField = ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<div style={wrapperStyle} className="w-full">
|
<div className={`w-full ${wrapperStyle ? '' : ''}`} style={wrapperStyle || {}}>
|
||||||
{label && (
|
{label && (
|
||||||
<label htmlFor={id || name} className="block text-[14px] leading-[20px] font-medium text-[#232528] mb-1">
|
<label htmlFor={id || name} className="block text-sm font-medium text-gray-900 mb-1">
|
||||||
{label}
|
{label}
|
||||||
{required && <span className="text-[#B91C1C] ml-1">*</span>}
|
{required && <span className="text-red-700 ml-1">*</span>}
|
||||||
</label>
|
</label>
|
||||||
)}
|
)}
|
||||||
<div className="relative" style={{ width: '100%' }}>
|
<div className="relative w-full">
|
||||||
<select
|
<select
|
||||||
id={id || name}
|
id={id || name}
|
||||||
name={name}
|
name={name}
|
||||||
|
|||||||
@ -139,8 +139,12 @@ const Table = ({
|
|||||||
<div className={`overflow-hidden rounded-lg bg-white ${className}`}>
|
<div className={`overflow-hidden rounded-lg bg-white ${className}`}>
|
||||||
{beforeHeader}
|
{beforeHeader}
|
||||||
<div
|
<div
|
||||||
className={`${disableHorizontalScroll ? 'overflow-x-hidden' : 'overflow-x-auto'} px-6 pt-2 pb-6`}
|
className={`
|
||||||
style={disableHorizontalScroll ? undefined : { scrollbarWidth: 'thin' }}
|
${disableHorizontalScroll
|
||||||
|
? 'overflow-x-hidden'
|
||||||
|
: 'overflow-x-auto scrollbar-thin'}
|
||||||
|
px-6 pt-2 pb-6
|
||||||
|
`}
|
||||||
>
|
>
|
||||||
<table
|
<table
|
||||||
className={`min-w-[720px] w-full table-fixed rounded-2xl px-4 py-4${
|
className={`min-w-[720px] w-full table-fixed rounded-2xl px-4 py-4${
|
||||||
@ -190,13 +194,9 @@ const Table = ({
|
|||||||
return (
|
return (
|
||||||
<td
|
<td
|
||||||
key={ci}
|
key={ci}
|
||||||
className={`px-6 py-2 text-sm text-[#232528] border-b border-[#C3C6CB] align-top ${getCellClass ? getCellClass(ri, ci) : ''}`}
|
className={`px-6 py-2 text-sm text-gray-900 border-b border-gray-300 align-top whitespace-normal break-words ${getCellClass ? getCellClass(ri, ci) : ''} ${
|
||||||
style={{
|
widthValue ? `w-[${typeof widthValue === 'number' ? `${widthValue}px` : widthValue}] min-w-[${typeof widthValue === 'number' ? `${widthValue}px` : widthValue}]` : 'max-w-[200px]'
|
||||||
...widthStyle,
|
}`}
|
||||||
whiteSpace: 'normal',
|
|
||||||
wordWrap: 'break-word',
|
|
||||||
maxWidth: widthValue || '200px'
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
{renderCell ? renderCell(cell, ri, ci) : cell}
|
{renderCell ? renderCell(cell, ri, ci) : cell}
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
@ -329,14 +329,11 @@ const Card = ({ children }) => (
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
const SectionBox = ({ title, children, badgeBg = '#ffffff', badgeText = '#374151' }) => (
|
const SectionBox = ({ title, children, badgeBg = 'bg-white', badgeText = 'text-gray-700' }) => (
|
||||||
<div className="rounded-md ring-1 ring-gray-200 bg-white">
|
<div className="rounded-md ring-1 ring-gray-200 bg-white">
|
||||||
<div className="p-5">
|
<div className="p-5">
|
||||||
<div className="font-medium mb-2">
|
<div className="font-medium mb-2">
|
||||||
<span
|
<span className={`inline-flex items-center rounded text-sm font-medium px-2 py-1 ${badgeBg} ${badgeText}`}>
|
||||||
className="inline-flex items-center rounded text-sm font-medium px-2 py-1"
|
|
||||||
style={{ backgroundColor: badgeBg, color: badgeText }}
|
|
||||||
>
|
|
||||||
{title}
|
{title}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@ -1501,7 +1498,7 @@ const location = useLocation();
|
|||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||||
{quarterPeriods?.previous_month?.previous_period_one } Qty
|
{quarterPeriods?.previous_month?.previous_period_one } Qty
|
||||||
</label>
|
</label>
|
||||||
<div className="flex items-center h-10 px-3 py-2 text-sm text-gray-700 rounded-md w-24" style={{ border: '1px solid #E6D7A2' }}>
|
<div className="flex items-center h-10 px-3 py-2 text-sm text-gray-700 rounded-md w-24 border border-amber-200">
|
||||||
{p.octQuantity || '0'}
|
{p.octQuantity || '0'}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -1509,7 +1506,7 @@ const location = useLocation();
|
|||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||||
{quarterPeriods?.previous_month?.previous_period_two } Qty
|
{quarterPeriods?.previous_month?.previous_period_two } Qty
|
||||||
</label>
|
</label>
|
||||||
<div className="flex items-center h-10 px-3 py-2 text-sm text-gray-700 rounded-md w-24" style={{ border: '1px solid #E6D7A2' }}>
|
<div className="flex items-center h-10 px-3 py-2 text-sm text-gray-700 rounded-md w-24 border border-amber-200">
|
||||||
{p.novQuantity || '0'}
|
{p.novQuantity || '0'}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -1517,7 +1514,7 @@ const location = useLocation();
|
|||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||||
{quarterPeriods?.previous_month?.previous_period_three} Qty
|
{quarterPeriods?.previous_month?.previous_period_three} Qty
|
||||||
</label>
|
</label>
|
||||||
<div className="flex items-center h-10 px-3 py-2 text-sm text-gray-700 rounded-md w-24" style={{ border: '1px solid #E6D7A2' }}>
|
<div className="flex items-center h-10 px-3 py-2 text-sm text-gray-700 rounded-md w-24 border border-amber-200">
|
||||||
{p.decQuantity || '0'}
|
{p.decQuantity || '0'}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -1527,7 +1524,7 @@ const location = useLocation();
|
|||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||||
{quarterPeriods?.previous_month?.previous_period_one } Cost (<img src={uae_currency} alt="AED" className="inline-block w-5 h-5 -mt-0.5 -mb-2.4 opacity-100 -mr-1 -ml-1" />)
|
{quarterPeriods?.previous_month?.previous_period_one } Cost (<img src={uae_currency} alt="AED" className="inline-block w-5 h-5 -mt-0.5 -mb-2.4 opacity-100 -mr-1 -ml-1" />)
|
||||||
</label>
|
</label>
|
||||||
<div className="flex items-center h-10 px-3 py-2 text-sm text-gray-700 rounded-md w-24" style={{ border: '1px solid #E6D7A2' }}>
|
<div className="flex items-center h-10 px-3 py-2 text-sm text-gray-700 rounded-md w-24 border border-amber-200">
|
||||||
{p.octCost || '0'}
|
{p.octCost || '0'}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -1535,7 +1532,7 @@ const location = useLocation();
|
|||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||||
{quarterPeriods?.previous_month?.previous_period_two } Cost (<img src={uae_currency} alt="AED" className="inline-block w-5 h-5 -mt-0.5 -mb-2.4 opacity-100 -mr-1 -ml-1" />)
|
{quarterPeriods?.previous_month?.previous_period_two } Cost (<img src={uae_currency} alt="AED" className="inline-block w-5 h-5 -mt-0.5 -mb-2.4 opacity-100 -mr-1 -ml-1" />)
|
||||||
</label>
|
</label>
|
||||||
<div className="flex items-center h-10 px-3 py-2 text-sm text-gray-700 rounded-md w-24" style={{ border: '1px solid #E6D7A2' }}>
|
<div className="flex items-center h-10 px-3 py-2 text-sm text-gray-700 rounded-md w-24 border border-amber-200">
|
||||||
{p.novCost || '0'}
|
{p.novCost || '0'}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -1543,7 +1540,7 @@ const location = useLocation();
|
|||||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||||
{quarterPeriods?.previous_month?.previous_period_three } Cost (<img src={uae_currency} alt="AED" className="inline-block w-5 h-5 -mt-0.5 -mb-2.4 opacity-100 -mr-1 -ml-1" />)
|
{quarterPeriods?.previous_month?.previous_period_three } Cost (<img src={uae_currency} alt="AED" className="inline-block w-5 h-5 -mt-0.5 -mb-2.4 opacity-100 -mr-1 -ml-1" />)
|
||||||
</label>
|
</label>
|
||||||
<div className="flex items-center h-10 px-3 py-2 text-sm text-gray-700 rounded-md w-24" style={{ border: '1px solid #E6D7A2' }}>
|
<div className="flex items-center h-10 px-3 py-2 text-sm text-gray-700 rounded-md w-24 border border-amber-200">
|
||||||
{p.decCost || '0'}
|
{p.decCost || '0'}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -147,35 +147,40 @@ const AdminDashboard = () => {
|
|||||||
<StatCard
|
<StatCard
|
||||||
label="Total Establishments"
|
label="Total Establishments"
|
||||||
value={loading ? '--' : summary.total_establishments}
|
value={loading ? '--' : summary.total_establishments}
|
||||||
width={290}
|
width={200}
|
||||||
|
className="flex-1 min-w-0"
|
||||||
icon={<img src={surveyIconSrc} alt="Total Establishments" className="h-5 w-5" />}
|
icon={<img src={surveyIconSrc} alt="Total Establishments" className="h-5 w-5" />}
|
||||||
tooltipText="Total establishments enrolled in the survey for selected quarter."
|
tooltipText="Total establishments enrolled in the survey for selected quarter."
|
||||||
/>
|
/>
|
||||||
<StatCard
|
<StatCard
|
||||||
label="Submitted"
|
label="Submitted"
|
||||||
value={loading ? '--' : summary.submitted}
|
value={loading ? '--' : summary.submitted}
|
||||||
width={190}
|
width={200}
|
||||||
|
className="flex-1 min-w-0"
|
||||||
icon={<img src={submittedIconSrc} alt="Submitted" className="h-5 w-5" />}
|
icon={<img src={submittedIconSrc} alt="Submitted" className="h-5 w-5" />}
|
||||||
tooltipText="Establishments that have submitted all products for this quarter."
|
tooltipText="Establishments that have submitted all products for this quarter."
|
||||||
/>
|
/>
|
||||||
<StatCard
|
<StatCard
|
||||||
label="Approved"
|
label="Approved"
|
||||||
value={loading ? '--' : summary.approved}
|
value={loading ? '--' : summary.approved}
|
||||||
width={190}
|
width={200}
|
||||||
|
className="flex-1 min-w-0"
|
||||||
icon={<img src={approvedIconSrc} alt="Approved" className="h-5 w-5" />}
|
icon={<img src={approvedIconSrc} alt="Approved" className="h-5 w-5" />}
|
||||||
tooltipText="Submissions fully validated and approved."
|
tooltipText="Submissions fully validated and approved."
|
||||||
/>
|
/>
|
||||||
<StatCard
|
<StatCard
|
||||||
label="Rejected"
|
label="Rejected"
|
||||||
value={loading ? '--' : summary.rejected}
|
value={loading ? '--' : summary.rejected}
|
||||||
width={190}
|
width={200}
|
||||||
|
className="flex-1 min-w-0"
|
||||||
icon={<img src={rejectedIconSrc} alt="Rejected" className="h-5 w-5" />}
|
icon={<img src={rejectedIconSrc} alt="Rejected" className="h-5 w-5" />}
|
||||||
tooltipText="Submissions rejected and pending resubmission."
|
tooltipText="Submissions rejected and pending resubmission."
|
||||||
/>
|
/>
|
||||||
<StatCard
|
<StatCard
|
||||||
label="Not Started"
|
label="Not Started"
|
||||||
value={loading ? '--' : summary.not_started}
|
value={loading ? '--' : summary.not_started}
|
||||||
width={190}
|
width={200}
|
||||||
|
className="flex-1 min-w-0"
|
||||||
icon={<img src={overdueIconSrc} alt="Not Started" className="h-5 w-5" />}
|
icon={<img src={overdueIconSrc} alt="Not Started" className="h-5 w-5" />}
|
||||||
tooltipText="Establishments past submission deadline."
|
tooltipText="Establishments past submission deadline."
|
||||||
/>
|
/>
|
||||||
@ -186,7 +191,8 @@ const AdminDashboard = () => {
|
|||||||
(selectedQuarter === 'All' || selectedYear === 'All') ? 'NA' :
|
(selectedQuarter === 'All' || selectedYear === 'All') ? 'NA' :
|
||||||
(quarterlyWindows.end_date ? new Date(quarterlyWindows.end_date).toLocaleDateString('en-GB') : '--')}
|
(quarterlyWindows.end_date ? new Date(quarterlyWindows.end_date).toLocaleDateString('en-GB') : '--')}
|
||||||
valueClassName="text-sm"
|
valueClassName="text-sm"
|
||||||
width={190}
|
width={200}
|
||||||
|
className="flex-1 min-w-0"
|
||||||
icon={<img src={dueDateIconSrc} alt="Due Date" className="h-5 w-5" />}
|
icon={<img src={dueDateIconSrc} alt="Due Date" className="h-5 w-5" />}
|
||||||
tooltipText={selectedQuarter === 'All' || selectedYear === 'All' ?
|
tooltipText={selectedQuarter === 'All' || selectedYear === 'All' ?
|
||||||
"Due date is not applicable when viewing all quarters or years" :
|
"Due date is not applicable when viewing all quarters or years" :
|
||||||
|
|||||||
@ -11,6 +11,15 @@ const caretUpSrc = '/assets/images/caret-up.svg';
|
|||||||
import apiClient from '@/services/api/apiClient';
|
import apiClient from '@/services/api/apiClient';
|
||||||
import { putRequest } from '@/services/api/CommonService';
|
import { putRequest } from '@/services/api/CommonService';
|
||||||
|
|
||||||
|
const STATUS_CLASSES = {
|
||||||
|
Approved: 'bg-green-50 text-green-800 border-green-50',
|
||||||
|
Pending: 'bg-blue-50 text-blue-600 border-blue-50',
|
||||||
|
Rejected: 'bg-red-50 text-red-700 border-red-50',
|
||||||
|
Resubmitted: 'bg-amber-50 text-amber-800 border-amber-200',
|
||||||
|
Submitted: 'bg-blue-50 text-blue-600 border-blue-50',
|
||||||
|
default: 'bg-gray-50 text-gray-600 border-gray-200'
|
||||||
|
};
|
||||||
|
|
||||||
const STATUS_VARIANTS = {
|
const STATUS_VARIANTS = {
|
||||||
Approved: { background: '#F3FAF4', text: '#2F663C', border: '#F3FAF4' },
|
Approved: { background: '#F3FAF4', text: '#2F663C', border: '#F3FAF4' },
|
||||||
Pending: { background: '#E7F5FF', text: '#286CFF', border: '#E7F5FF' },
|
Pending: { background: '#E7F5FF', text: '#286CFF', border: '#E7F5FF' },
|
||||||
@ -45,15 +54,11 @@ const formatDateTime = (value) => {
|
|||||||
});
|
});
|
||||||
return formatted;
|
return formatted;
|
||||||
};
|
};
|
||||||
const Badge = ({ children, status }) => {
|
|
||||||
const variant = STATUS_VARIANTS[status] || { background: '#F2F4F7', text: '#475467', border: '#EAECF0' };
|
|
||||||
return (
|
|
||||||
<span
|
|
||||||
// className={`inline-flex h-6 min-w-[67px] items-center justify-center rounded px-2 text-xs font-medium border ${variant.background} ${variant.text} ${variant.border}`}
|
|
||||||
className="inline-flex h-6 min-w-[67px] items-center justify-center rounded px-2 text-xs font-medium"
|
|
||||||
style={{ background: variant.background, color: variant.text, border: `1px solid ${variant.border}` }}
|
|
||||||
|
|
||||||
>
|
const Badge = ({ children, status }) => {
|
||||||
|
const variantClass = STATUS_CLASSES[status] || STATUS_CLASSES.default;
|
||||||
|
return (
|
||||||
|
<span className={`inline-flex h-6 min-w-[67px] items-center justify-center rounded px-2 text-xs font-medium border ${variantClass}`}>
|
||||||
{children}
|
{children}
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -35,8 +35,7 @@ const SummaryCard = ({ label, count, icon, iconBg = '#FDF7EB' }) => (
|
|||||||
<div className="flex min-h-[96px] min-w-[220px] flex-1 items-center justify-between rounded-[16px] border border-[#E6EAF5] bg-white px-6 py-5 shadow-[0_12px_24px_rgba(15,23,42,0.06)]">
|
<div className="flex min-h-[96px] min-w-[220px] flex-1 items-center justify-between rounded-[16px] border border-[#E6EAF5] bg-white px-6 py-5 shadow-[0_12px_24px_rgba(15,23,42,0.06)]">
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4">
|
||||||
<span
|
<span
|
||||||
className="flex h-12 w-12 items-center justify-center rounded-full"
|
className={`flex h-12 w-12 items-center justify-center rounded-full ${iconBg ? `bg-[${iconBg}]` : 'bg-[#FDF7EB]'}`}
|
||||||
style={{ backgroundColor: iconBg }}
|
|
||||||
>
|
>
|
||||||
{icon && <img src={icon} alt={label} className="h-6 w-6" />}
|
{icon && <img src={icon} alt={label} className="h-6 w-6" />}
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@ -989,10 +989,7 @@ const CompanyProfile = () => {
|
|||||||
<h4 className="text-[16px] font-semibold text-[#232528]">Details</h4>
|
<h4 className="text-[16px] font-semibold text-[#232528]">Details</h4>
|
||||||
|
|
||||||
{/* Responsive grid */}
|
{/* Responsive grid */}
|
||||||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-2 w-full overflow-x-hidden" style={{
|
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-2 w-full overflow-x-hidden [&::-webkit-scrollbar]:hidden [-ms-overflow-style:none] [scrollbar-width:none]">
|
||||||
msOverflowStyle: 'none', /* IE and Edge */
|
|
||||||
scrollbarWidth: 'none', /* Firefox */
|
|
||||||
}}>
|
|
||||||
<div>
|
<div>
|
||||||
<TextField
|
<TextField
|
||||||
label="Permanent Factory Code"
|
label="Permanent Factory Code"
|
||||||
@ -1043,7 +1040,7 @@ const CompanyProfile = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mt-4 w-full" style={{ width: 'calc(100% - 1px)' }}>
|
<div className="mt-4 w-[calc(100%-1px)]">
|
||||||
<TextField
|
<TextField
|
||||||
label="Description"
|
label="Description"
|
||||||
value={form.industryDescription}
|
value={form.industryDescription}
|
||||||
@ -1055,7 +1052,7 @@ const CompanyProfile = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{form.industryCodeProduction && form.industryCodeBusiness != null && form.industryCodeBusiness !== form.industryCodeProduction && (
|
{form.industryCodeProduction && form.industryCodeBusiness != null && form.industryCodeBusiness !== form.industryCodeProduction && (
|
||||||
<div className="mt-4 w-full" style={{ width: 'calc(100% - 1px)' }}>
|
<div className="mt-4 w-[calc(100%-1px)]">
|
||||||
<TextField
|
<TextField
|
||||||
label="Remarks"
|
label="Remarks"
|
||||||
value={form.industryCodeMismatchRemarks}
|
value={form.industryCodeMismatchRemarks}
|
||||||
@ -3376,17 +3373,7 @@ const handleImport = async () => {
|
|||||||
<div className="fixed inset-0 z-50">
|
<div className="fixed inset-0 z-50">
|
||||||
<div className="absolute inset-0 bg-black/40" onClick={closeModal} />
|
<div className="absolute inset-0 bg-black/40" onClick={closeModal} />
|
||||||
<div
|
<div
|
||||||
className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 rounded-[8px] bg-white"
|
className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 rounded-lg bg-white w-[1300px] max-w-[calc(100vw-32px)] max-h-[94vh] shadow-xl border border-slate-200 overflow-hidden flex flex-col"
|
||||||
style={{
|
|
||||||
width: '1300px',
|
|
||||||
maxWidth: 'calc(100vw - 32px)',
|
|
||||||
maxHeight: '94vh',
|
|
||||||
boxShadow: '0 24px 40px rgba(27, 29, 33, 0.16)',
|
|
||||||
border: '1px solid #CBD5E1',
|
|
||||||
overflow: 'hidden',
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<div className="flex items-center justify-between px-6 py-4 border-b border-[#F1F2F4]">
|
<div className="flex items-center justify-between px-6 py-4 border-b border-[#F1F2F4]">
|
||||||
<h3 className="text-[18px] font-medium text-[#232528]">
|
<h3 className="text-[18px] font-medium text-[#232528]">
|
||||||
@ -3406,7 +3393,7 @@ const handleImport = async () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-1 overflow-hidden">
|
<div className="flex flex-1 overflow-hidden">
|
||||||
<aside className="w-64 bg-[#F9FAFB] border-r border-[#E5E7EB] overflow-y-auto" style={{ maxHeight: 'calc(94vh - 120px)' }}>
|
<aside className="w-64 bg-[#F9FAFB] border-r border-[#E5E7EB] overflow-y-auto max-h-[calc(94vh-120px)]">
|
||||||
<ol className="py-6 px-4 space-y-2">
|
<ol className="py-6 px-4 space-y-2">
|
||||||
{formSteps.map((step, index) => {
|
{formSteps.map((step, index) => {
|
||||||
const isActive = index === activeStep;
|
const isActive = index === activeStep;
|
||||||
@ -3447,7 +3434,7 @@ const handleImport = async () => {
|
|||||||
})}
|
})}
|
||||||
</ol>
|
</ol>
|
||||||
</aside>
|
</aside>
|
||||||
<div className="flex-1 overflow-y-auto" style={{ maxHeight: 'calc(94vh - 120px)' }}>
|
<div className="flex-1 overflow-y-auto max-h-[calc(94vh-120px)]">
|
||||||
<div className="px-6 py-6">
|
<div className="px-6 py-6">
|
||||||
{renderStepContent()}
|
{renderStepContent()}
|
||||||
</div>
|
</div>
|
||||||
@ -3548,20 +3535,11 @@ const handleImport = async () => {
|
|||||||
onClick={isDeletingApi ? undefined : closeDeleteConfirm}
|
onClick={isDeletingApi ? undefined : closeDeleteConfirm}
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 rounded-lg bg-white border"
|
className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 rounded-lg bg-white border border-[#CBD5E1] w-[480px] max-w-[92vw] shadow-lg"
|
||||||
style={{
|
|
||||||
width: '480px',
|
|
||||||
maxWidth: '92vw',
|
|
||||||
borderColor: '#CBD5E1',
|
|
||||||
boxShadow: '0 20px 45px rgba(0,0,0,0.12)',
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<div className="px-8 py-6 space-y-6">
|
<div className="px-8 py-6 space-y-6">
|
||||||
<div className="flex items-start gap-3">
|
<div className="flex items-start gap-3">
|
||||||
<span
|
<span className="flex items-center justify-center w-8 h-9">
|
||||||
className="flex items-center justify-center"
|
|
||||||
style={{ width: '32px', height: '36px' }}
|
|
||||||
>
|
|
||||||
<img src={deleteIconSrc} alt="Delete" className="h-6 w-6" />
|
<img src={deleteIconSrc} alt="Delete" className="h-6 w-6" />
|
||||||
</span>
|
</span>
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
|
|||||||
@ -67,13 +67,7 @@ const EmailTemplates = () => {
|
|||||||
value={form.body}
|
value={form.body}
|
||||||
onChange={handleChange('body')}
|
onChange={handleChange('body')}
|
||||||
rows={10}
|
rows={10}
|
||||||
className="w-full text-sm focus:outline-none"
|
className="w-full text-sm focus:outline-none border-2 border-[#CBA344] rounded p-3"
|
||||||
style={{
|
|
||||||
width: '100%',
|
|
||||||
border: '2px solid #CBA344',
|
|
||||||
borderRadius: '4px',
|
|
||||||
padding: '12px 16px',
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -81,8 +75,7 @@ const EmailTemplates = () => {
|
|||||||
<div className="px-6 pb-6 flex items-center justify-end gap-3">
|
<div className="px-6 pb-6 flex items-center justify-end gap-3">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="h-9 px-5 rounded-md border text-[#92722A] bg-white cursor-pointer"
|
className="h-9 px-5 rounded-md border border-[#92722A] text-[#92722A] bg-white cursor-pointer"
|
||||||
style={{ borderColor: '#92722A' }}
|
|
||||||
onClick={handleCancel}
|
onClick={handleCancel}
|
||||||
>
|
>
|
||||||
Cancel
|
Cancel
|
||||||
|
|||||||
@ -307,8 +307,7 @@ const Establishment = () => {
|
|||||||
<div className="px-6 py-4 border-t border-[#E5E7EB] flex items-center justify-end gap-3">
|
<div className="px-6 py-4 border-t border-[#E5E7EB] flex items-center justify-end gap-3">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="h-9 px-5 rounded-md border text-[#92722A] bg-white cursor-pointer"
|
className="h-9 px-5 rounded-md border border-[#92722A] text-[#92722A] bg-white cursor-pointer"
|
||||||
style={{ borderColor: '#92722A' }}
|
|
||||||
onClick={closeModal}
|
onClick={closeModal}
|
||||||
>
|
>
|
||||||
Cancel
|
Cancel
|
||||||
|
|||||||
@ -1613,9 +1613,8 @@ const handleExportCSV = () => {
|
|||||||
onChange={handleFormChange("description")}
|
onChange={handleFormChange("description")}
|
||||||
disabled={modalMode === "view"}
|
disabled={modalMode === "view"}
|
||||||
rows={1}
|
rows={1}
|
||||||
className="w-full px-3 py-2 text-sm border border-[#CBA344] rounded-md focus:outline-none focus:ring-1 focus:ring-[#92722A] focus:border-[#92722A] min-h-[38px]"
|
className="w-full px-3 py-2 text-sm border border-[#CBA344] rounded-md focus:outline-none focus:ring-1 focus:ring-[#92722A] focus:border-[#92722A] min-h-[38px] resize-y"
|
||||||
placeholder="Enter product description"
|
placeholder="Enter product description"
|
||||||
style={{ resize: 'vertical' }}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{/* <div>
|
{/* <div>
|
||||||
@ -1671,12 +1670,7 @@ const handleExportCSV = () => {
|
|||||||
<div className="fixed inset-0 z-50">
|
<div className="fixed inset-0 z-50">
|
||||||
<div className="absolute inset-0 bg-black/40" onClick={closeDeleteConfirm} />
|
<div className="absolute inset-0 bg-black/40" onClick={closeDeleteConfirm} />
|
||||||
<div
|
<div
|
||||||
className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 rounded-lg bg-white border"
|
className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 rounded-lg bg-white border border-[#CBD5E1] w-[480px] shadow-lg"
|
||||||
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="px-8 py-6 space-y-6">
|
||||||
<div className="flex items-start gap-3">
|
<div className="flex items-start gap-3">
|
||||||
|
|||||||
@ -90,25 +90,25 @@ const QuarterlyWindows = () => {
|
|||||||
const [isLoading, setIsLoading] = React.useState(false);
|
const [isLoading, setIsLoading] = React.useState(false);
|
||||||
const [validationErrors, setValidationErrors] = React.useState({});
|
const [validationErrors, setValidationErrors] = React.useState({});
|
||||||
const [toastData, setToastData] = React.useState(null);
|
const [toastData, setToastData] = React.useState(null);
|
||||||
const [isSaving, setIsSaving] = React.useState(false); // Add this line
|
const [isSaving, setIsSaving] = React.useState(false); // Add this line
|
||||||
|
|
||||||
const [sortConfig, setSortConfig] = React.useState({
|
const [sortConfig, setSortConfig] = React.useState({
|
||||||
key: null,
|
key: null,
|
||||||
direction: 'asc'
|
direction: 'asc'
|
||||||
});
|
});
|
||||||
const extractText = (node) => {
|
const extractText = (node) => {
|
||||||
if (typeof node === "string") return node;
|
if (typeof node === "string") return node;
|
||||||
if (typeof node === "number") return String(node);
|
if (typeof node === "number") return String(node);
|
||||||
|
|
||||||
if (node?.props?.children) {
|
if (node?.props?.children) {
|
||||||
if (Array.isArray(node.props.children)) {
|
if (Array.isArray(node.props.children)) {
|
||||||
return node.props.children.map(extractText).join(" ");
|
return node.props.children.map(extractText).join(" ");
|
||||||
|
}
|
||||||
|
return extractText(node.props.children);
|
||||||
}
|
}
|
||||||
return extractText(node.props.children);
|
|
||||||
}
|
return "";
|
||||||
|
};
|
||||||
return "";
|
|
||||||
};
|
|
||||||
|
|
||||||
// Format date to yyyy-MM-dd for input fields
|
// Format date to yyyy-MM-dd for input fields
|
||||||
const formatDateForInput = (dateString) => {
|
const formatDateForInput = (dateString) => {
|
||||||
@ -172,29 +172,29 @@ const QuarterlyWindows = () => {
|
|||||||
|
|
||||||
const getSortedData = (data) => {
|
const getSortedData = (data) => {
|
||||||
if (!sortConfig.key) return data;
|
if (!sortConfig.key) return data;
|
||||||
|
|
||||||
return [...data].sort((a, b) => {
|
return [...data].sort((a, b) => {
|
||||||
let aValue = a[sortConfig.key];
|
let aValue = a[sortConfig.key];
|
||||||
let bValue = b[sortConfig.key];
|
let bValue = b[sortConfig.key];
|
||||||
|
|
||||||
// Handle numeric comparisons
|
// Handle numeric comparisons
|
||||||
if (['year', 'assigned', 'responded', 'not_responded', 'submissionCount'].includes(sortConfig.key)) {
|
if (['year', 'assigned', 'responded', 'not_responded', 'submissionCount'].includes(sortConfig.key)) {
|
||||||
aValue = Number(aValue) || 0;
|
aValue = Number(aValue) || 0;
|
||||||
bValue = Number(bValue) || 0;
|
bValue = Number(bValue) || 0;
|
||||||
return sortConfig.direction === 'asc' ? aValue - bValue : bValue - aValue;
|
return sortConfig.direction === 'asc' ? aValue - bValue : bValue - aValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle date comparisons
|
// Handle date comparisons
|
||||||
if (['startDate', 'endDate'].includes(sortConfig.key)) {
|
if (['startDate', 'endDate'].includes(sortConfig.key)) {
|
||||||
aValue = aValue ? new Date(aValue).getTime() : 0;
|
aValue = aValue ? new Date(aValue).getTime() : 0;
|
||||||
bValue = bValue ? new Date(bValue).getTime() : 0;
|
bValue = bValue ? new Date(bValue).getTime() : 0;
|
||||||
return sortConfig.direction === 'asc' ? aValue - bValue : bValue - aValue;
|
return sortConfig.direction === 'asc' ? aValue - bValue : bValue - aValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default string comparison
|
// Default string comparison
|
||||||
aValue = String(aValue || '').toLowerCase();
|
aValue = String(aValue || '').toLowerCase();
|
||||||
bValue = String(bValue || '').toLowerCase();
|
bValue = String(bValue || '').toLowerCase();
|
||||||
|
|
||||||
if (aValue < bValue) {
|
if (aValue < bValue) {
|
||||||
return sortConfig.direction === 'asc' ? -1 : 1;
|
return sortConfig.direction === 'asc' ? -1 : 1;
|
||||||
}
|
}
|
||||||
@ -206,88 +206,88 @@ const QuarterlyWindows = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const headers = [
|
const headers = [
|
||||||
{
|
{
|
||||||
name: 'Survey Name',
|
name: 'Survey Name',
|
||||||
key: 'survey_name',
|
key: 'survey_name',
|
||||||
sortable: true,
|
sortable: true,
|
||||||
className: 'whitespace-nowrap text-left'
|
className: 'whitespace-nowrap text-left'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Year',
|
name: 'Year',
|
||||||
key: 'year',
|
key: 'year',
|
||||||
sortable: true,
|
sortable: true,
|
||||||
className: 'whitespace-nowrap text-left'
|
className: 'whitespace-nowrap text-left'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Quarter',
|
name: 'Quarter',
|
||||||
key: 'quarter',
|
key: 'quarter',
|
||||||
sortable: true,
|
sortable: true,
|
||||||
className: 'whitespace-nowrap text-left'
|
className: 'whitespace-nowrap text-left'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Start Date',
|
name: 'Start Date',
|
||||||
key: 'startDate',
|
key: 'startDate',
|
||||||
sortable: true,
|
sortable: true,
|
||||||
className: 'whitespace-nowrap text-left'
|
className: 'whitespace-nowrap text-left'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'End Date',
|
name: 'End Date',
|
||||||
key: 'endDate',
|
key: 'endDate',
|
||||||
sortable: true,
|
sortable: true,
|
||||||
className: 'whitespace-nowrap text-left'
|
className: 'whitespace-nowrap text-left'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Grace Period',
|
name: 'Grace Period',
|
||||||
key: 'gracePeriod',
|
key: 'gracePeriod',
|
||||||
sortable: false,
|
sortable: false,
|
||||||
className: 'whitespace-nowrap text-left'
|
className: 'whitespace-nowrap text-left'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Assigned',
|
name: 'Assigned',
|
||||||
key: 'assigned',
|
key: 'assigned',
|
||||||
sortable: false,
|
sortable: false,
|
||||||
className: 'whitespace-nowrap text-left'
|
className: 'whitespace-nowrap text-left'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Responded',
|
name: 'Responded',
|
||||||
key: 'responded',
|
key: 'responded',
|
||||||
sortable: false,
|
sortable: false,
|
||||||
className: 'whitespace-nowrap text-left'
|
className: 'whitespace-nowrap text-left'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Not Responded',
|
name: 'Not Responded',
|
||||||
key: 'not_responded',
|
key: 'not_responded',
|
||||||
sortable: false,
|
sortable: false,
|
||||||
className: 'whitespace-nowrap text-left'
|
className: 'whitespace-nowrap text-left'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Submission Count',
|
name: 'Submission Count',
|
||||||
key: 'submissionCount',
|
key: 'submissionCount',
|
||||||
sortable: false,
|
sortable: false,
|
||||||
className: 'whitespace-nowrap text-left'
|
className: 'whitespace-nowrap text-left'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Status',
|
name: 'Status',
|
||||||
key: 'status',
|
key: 'status',
|
||||||
sortable: false,
|
sortable: false,
|
||||||
className: 'whitespace-nowrap text-left'
|
className: 'whitespace-nowrap text-left'
|
||||||
},
|
},
|
||||||
].map(header => {
|
].map(header => {
|
||||||
if (!header.sortable) return { name: header.name, className: header.className };
|
if (!header.sortable) return { name: header.name, className: header.className };
|
||||||
|
|
||||||
const isActive = sortConfig.key === header.key;
|
const isActive = sortConfig.key === header.key;
|
||||||
const isAsc = sortConfig.direction === 'asc';
|
const isAsc = sortConfig.direction === 'asc';
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: (
|
name: (
|
||||||
<div
|
<div
|
||||||
className="flex items-center cursor-pointer gap-1"
|
className="flex items-center cursor-pointer gap-1"
|
||||||
onClick={() => handleSort(header.key)}
|
onClick={() => handleSort(header.key)}
|
||||||
>
|
>
|
||||||
<span>{header.name}</span>
|
<span>{header.name}</span>
|
||||||
<img
|
<img
|
||||||
src={isActive ? "/assets/images/active-sort.svg" : "/assets/images/inactive-sort.svg"}
|
src={isActive ? "/assets/images/active-sort.svg" : "/assets/images/inactive-sort.svg"}
|
||||||
alt="Sort"
|
alt="Sort"
|
||||||
className={`w-3 h-3 transition-transform ${isActive && isAsc ? 'transform rotate-180' : ''}`}
|
className={`w-3 h-3 transition-transform ${isActive && isAsc ? 'transform rotate-180' : ''}`}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -295,7 +295,7 @@ const QuarterlyWindows = () => {
|
|||||||
className: header.className
|
className: header.className
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const columnwidth = [
|
const columnwidth = [
|
||||||
220, // Survey Name
|
220, // Survey Name
|
||||||
100, // Year
|
100, // Year
|
||||||
@ -309,16 +309,16 @@ const QuarterlyWindows = () => {
|
|||||||
140, // Submission Count
|
140, // Submission Count
|
||||||
120 // Actions
|
120 // Actions
|
||||||
];
|
];
|
||||||
|
|
||||||
const filteredRows = React.useMemo(() => {
|
const filteredRows = React.useMemo(() => {
|
||||||
const term = searchTerm.trim().toLowerCase();
|
const term = searchTerm.trim().toLowerCase();
|
||||||
return quarterData.filter((item) => {
|
return quarterData.filter((item) => {
|
||||||
// Apply year filter
|
// Apply year filter
|
||||||
if (yearFilter !== 'all' && item.year !== yearFilter) return false;
|
if (yearFilter !== 'all' && item.year !== yearFilter) return false;
|
||||||
|
|
||||||
// Apply quarter filter
|
// Apply quarter filter
|
||||||
if (quarterFilter !== 'all' && item.quarter !== quarterFilter) return false;
|
if (quarterFilter !== 'all' && item.quarter !== quarterFilter) return false;
|
||||||
|
|
||||||
// Apply search term
|
// Apply search term
|
||||||
if (!term) return true;
|
if (!term) return true;
|
||||||
const haystack = [
|
const haystack = [
|
||||||
@ -345,18 +345,17 @@ const QuarterlyWindows = () => {
|
|||||||
<div className="flex items-center gap-1 group relative">
|
<div className="flex items-center gap-1 group relative">
|
||||||
<span>{children}</span>
|
<span>{children}</span>
|
||||||
<div className="relative group cursor-pointer" title={text}>
|
<div className="relative group cursor-pointer" title={text}>
|
||||||
<img
|
<img
|
||||||
src="/assets/images/tooltip.svg"
|
src="/assets/images/tooltip.svg"
|
||||||
alt="info"
|
alt="info"
|
||||||
className="w-4 h-4"
|
className="w-4 h-4 grayscale opacity-70"
|
||||||
style={{ filter: 'invert(45%) sepia(6%) saturate(323%) hue-rotate(175deg) brightness(93%) contrast(82%)' }}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
const sortedRows = getSortedData(filteredRows);
|
const sortedRows = getSortedData(filteredRows);
|
||||||
|
|
||||||
const rows = sortedRows.map((item) => [
|
const rows = sortedRows.map((item) => [
|
||||||
item.survey_name || '-',
|
item.survey_name || '-',
|
||||||
item.year,
|
item.year,
|
||||||
@ -364,13 +363,13 @@ const QuarterlyWindows = () => {
|
|||||||
item.startDate ? formatDateForDisplay(item.startDate) : '-',
|
item.startDate ? formatDateForDisplay(item.startDate) : '-',
|
||||||
item.endDate ? formatDateForDisplay(item.endDate) : '-',
|
item.endDate ? formatDateForDisplay(item.endDate) : '-',
|
||||||
item.gracePeriod,
|
item.gracePeriod,
|
||||||
<Tooltip text="Number of establishments assigned this survey">
|
<Tooltip key="assigned" text="Number of establishments assigned this survey">
|
||||||
{item.assigned || '0'}
|
{item.assigned || '0'}
|
||||||
</Tooltip>,
|
</Tooltip>,
|
||||||
<Tooltip text="Number of establishments that have responded">
|
<Tooltip key="responded" text="Number of establishments that have responded">
|
||||||
{item.responded || '0'}
|
{item.responded || '0'}
|
||||||
</Tooltip>,
|
</Tooltip>,
|
||||||
<Tooltip text="Number of establishments yet to respond">
|
<Tooltip key="not-responded" text="Number of establishments yet to respond">
|
||||||
{item.not_responded || '0'}
|
{item.not_responded || '0'}
|
||||||
</Tooltip>,
|
</Tooltip>,
|
||||||
item.submissionCount,
|
item.submissionCount,
|
||||||
@ -381,19 +380,19 @@ const QuarterlyWindows = () => {
|
|||||||
const yearOptions = React.useMemo(() => {
|
const yearOptions = React.useMemo(() => {
|
||||||
const currentYear = new Date().getFullYear();
|
const currentYear = new Date().getFullYear();
|
||||||
const years = new Set(['all']);
|
const years = new Set(['all']);
|
||||||
|
|
||||||
// Add years from 2022 to current year
|
// Add years from 2022 to current year
|
||||||
for (let y = 2022; y <= currentYear; y++) {
|
for (let y = 2022; y <= currentYear; y++) {
|
||||||
years.add(y.toString());
|
years.add(y.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add any additional years that might be in the data
|
// Add any additional years that might be in the data
|
||||||
quarterData.forEach(item => {
|
quarterData.forEach(item => {
|
||||||
if (item.year && !years.has(item.year)) {
|
if (item.year && !years.has(item.year)) {
|
||||||
years.add(item.year);
|
years.add(item.year);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Sort years in descending order (newest first)
|
// Sort years in descending order (newest first)
|
||||||
return Array.from(years).sort((a, b) => {
|
return Array.from(years).sort((a, b) => {
|
||||||
if (a === 'all') return -1;
|
if (a === 'all') return -1;
|
||||||
@ -401,7 +400,7 @@ const QuarterlyWindows = () => {
|
|||||||
return parseInt(b) - parseInt(a);
|
return parseInt(b) - parseInt(a);
|
||||||
});
|
});
|
||||||
}, [quarterData]);
|
}, [quarterData]);
|
||||||
|
|
||||||
const quarterOptions = ['all', 'Q1', 'Q2', 'Q3', 'Q4'];
|
const quarterOptions = ['all', 'Q1', 'Q2', 'Q3', 'Q4'];
|
||||||
|
|
||||||
const openAddModal = () => {
|
const openAddModal = () => {
|
||||||
@ -420,18 +419,18 @@ const QuarterlyWindows = () => {
|
|||||||
const openEditModal = async (index) => {
|
const openEditModal = async (index) => {
|
||||||
try {
|
try {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
|
|
||||||
// Calculate the actual index in the filtered data based on pagination
|
// Calculate the actual index in the filtered data based on pagination
|
||||||
const actualIndex = (currentPage - 1) * pageSize + index;
|
const actualIndex = (currentPage - 1) * pageSize + index;
|
||||||
const selected = filteredRows[actualIndex];
|
const selected = filteredRows[actualIndex];
|
||||||
|
|
||||||
if (!selected || !selected.id) {
|
if (!selected || !selected.id) {
|
||||||
throw new Error('Invalid quarterly window selected');
|
throw new Error('Invalid quarterly window selected');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch the latest data for this quarter
|
// Fetch the latest data for this quarter
|
||||||
const response = await getQuarterlyWindowById(selected.id);
|
const response = await getQuarterlyWindowById(selected.id);
|
||||||
|
|
||||||
if (response && response.data) {
|
if (response && response.data) {
|
||||||
const quarterData = response.data;
|
const quarterData = response.data;
|
||||||
const formData = {
|
const formData = {
|
||||||
@ -449,7 +448,7 @@ const QuarterlyWindows = () => {
|
|||||||
not_responded: quarterData.not_responded?.toString() || '0',
|
not_responded: quarterData.not_responded?.toString() || '0',
|
||||||
status: quarterData.is_active ? 'Active' : 'Inactive'
|
status: quarterData.is_active ? 'Active' : 'Inactive'
|
||||||
};
|
};
|
||||||
|
|
||||||
setEditingRow(actualIndex);
|
setEditingRow(actualIndex);
|
||||||
setForm(formData);
|
setForm(formData);
|
||||||
setOriginalForm(formData);
|
setOriginalForm(formData);
|
||||||
@ -525,7 +524,7 @@ const QuarterlyWindows = () => {
|
|||||||
|
|
||||||
const handleFormChange = (field) => (value) => {
|
const handleFormChange = (field) => (value) => {
|
||||||
setForm(prev => ({ ...prev, [field]: value }));
|
setForm(prev => ({ ...prev, [field]: value }));
|
||||||
|
|
||||||
// Clear validation error when user starts typing
|
// Clear validation error when user starts typing
|
||||||
if (validationErrors[field]) {
|
if (validationErrors[field]) {
|
||||||
setValidationErrors(prev => ({
|
setValidationErrors(prev => ({
|
||||||
@ -535,125 +534,125 @@ const QuarterlyWindows = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSave = async () => {
|
const handleSave = async () => {
|
||||||
try {
|
try {
|
||||||
if (!validateForm()) {
|
if (!validateForm()) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setIsSaving(true);
|
|
||||||
|
|
||||||
const startDate = new Date(form.startDate);
|
|
||||||
const endDate = new Date(form.endDate);
|
|
||||||
|
|
||||||
const formattedData = {
|
|
||||||
survey_name: form.survey_name || '',
|
|
||||||
year: form.year ? parseInt(form.year, 10) : 0,
|
|
||||||
quarter: form.quarter || '',
|
|
||||||
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,
|
|
||||||
assigned: form.assigned || 0,
|
|
||||||
responded: form.responded || 0,
|
|
||||||
not_responded: form.not_responded || 0,
|
|
||||||
is_active: form.status === 'Active',
|
|
||||||
establishment: form.establishment || '-',
|
|
||||||
};
|
|
||||||
|
|
||||||
if (modalMode === 'add') {
|
|
||||||
const response = await createQuarterlyWindow(formattedData);
|
|
||||||
if (response.status === 'success') {
|
|
||||||
// Fetch the latest data from the server
|
|
||||||
const latestData = await getQuarterlyWindows();
|
|
||||||
if (latestData.status === 'success' && Array.isArray(latestData.data)) {
|
|
||||||
const formattedData = latestData.data.map(item => ({
|
|
||||||
id: item.id,
|
|
||||||
survey_name: item.survey_name || '',
|
|
||||||
establishment: item.establishment || '-',
|
|
||||||
year: item.year?.toString() || '',
|
|
||||||
quarter: item.quarter || '',
|
|
||||||
startDate: item.start_date || '',
|
|
||||||
endDate: item.end_date || '',
|
|
||||||
gracePeriod: item.grace_periods_days ? `${item.grace_periods_days} days` : '0 days',
|
|
||||||
submissionCount: item.submission_count?.toString() || '-',
|
|
||||||
assigned: item.assigned?.toString() || '0',
|
|
||||||
responded: item.responded?.toString() || '0',
|
|
||||||
not_responded: item.not_responded?.toString() || '0',
|
|
||||||
status: item.is_active ? 'Active' : 'Inactive'
|
|
||||||
}));
|
|
||||||
setQuarterData(formattedData);
|
|
||||||
}
|
|
||||||
|
|
||||||
setToastData({
|
|
||||||
message: 'Quarterly survey created successfully!',
|
|
||||||
type: 'success'
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
const errorMessage = response.message || 'Failed to add quarterly window';
|
|
||||||
setToastData({
|
|
||||||
message: errorMessage,
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
console.error('Failed to add quarterly window:', errorMessage);
|
|
||||||
}
|
|
||||||
} else if (modalMode === 'edit' && editingRow !== null) {
|
|
||||||
const itemId = quarterData[editingRow]?.id;
|
|
||||||
if (!itemId) {
|
|
||||||
setToastData({
|
|
||||||
message: 'Error: Could not find the item to update',
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
console.error('Error: Could not find the item to update');
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const response = await updateQuarterlyWindow(itemId, formattedData);
|
|
||||||
if (response.status === 'success') {
|
setIsSaving(true);
|
||||||
// Fetch the latest data from the server
|
|
||||||
const latestData = await getQuarterlyWindows();
|
const startDate = new Date(form.startDate);
|
||||||
if (latestData.status === 'success' && Array.isArray(latestData.data)) {
|
const endDate = new Date(form.endDate);
|
||||||
const formattedData = latestData.data.map(item => ({
|
|
||||||
id: item.id,
|
const formattedData = {
|
||||||
survey_name: item.survey_name || '',
|
survey_name: form.survey_name || '',
|
||||||
establishment: item.establishment || '-',
|
year: form.year ? parseInt(form.year, 10) : 0,
|
||||||
year: item.year?.toString() || '',
|
quarter: form.quarter || '',
|
||||||
quarter: item.quarter || '',
|
start_date: startDate.toISOString().split('T')[0],
|
||||||
startDate: item.start_date || '',
|
end_date: endDate.toISOString().split('T')[0],
|
||||||
endDate: item.end_date || '',
|
grace_periods_days: form.gracePeriod ? parseInt(form.gracePeriod.split(' ')[0], 10) || 0 : 0,
|
||||||
gracePeriod: item.grace_periods_days ? `${item.grace_periods_days} days` : '0 days',
|
assigned: form.assigned || 0,
|
||||||
submissionCount: item.submission_count?.toString() || '-',
|
responded: form.responded || 0,
|
||||||
assigned: item.assigned?.toString() || '0',
|
not_responded: form.not_responded || 0,
|
||||||
responded: item.responded?.toString() || '0',
|
is_active: form.status === 'Active',
|
||||||
not_responded: item.not_responded?.toString() || '0',
|
establishment: form.establishment || '-',
|
||||||
status: item.is_active ? 'Active' : 'Inactive'
|
};
|
||||||
}));
|
|
||||||
setQuarterData(formattedData);
|
if (modalMode === 'add') {
|
||||||
|
const response = await createQuarterlyWindow(formattedData);
|
||||||
|
if (response.status === 'success') {
|
||||||
|
// Fetch the latest data from the server
|
||||||
|
const latestData = await getQuarterlyWindows();
|
||||||
|
if (latestData.status === 'success' && Array.isArray(latestData.data)) {
|
||||||
|
const formattedData = latestData.data.map(item => ({
|
||||||
|
id: item.id,
|
||||||
|
survey_name: item.survey_name || '',
|
||||||
|
establishment: item.establishment || '-',
|
||||||
|
year: item.year?.toString() || '',
|
||||||
|
quarter: item.quarter || '',
|
||||||
|
startDate: item.start_date || '',
|
||||||
|
endDate: item.end_date || '',
|
||||||
|
gracePeriod: item.grace_periods_days ? `${item.grace_periods_days} days` : '0 days',
|
||||||
|
submissionCount: item.submission_count?.toString() || '-',
|
||||||
|
assigned: item.assigned?.toString() || '0',
|
||||||
|
responded: item.responded?.toString() || '0',
|
||||||
|
not_responded: item.not_responded?.toString() || '0',
|
||||||
|
status: item.is_active ? 'Active' : 'Inactive'
|
||||||
|
}));
|
||||||
|
setQuarterData(formattedData);
|
||||||
|
}
|
||||||
|
|
||||||
|
setToastData({
|
||||||
|
message: 'Quarterly survey created successfully!',
|
||||||
|
type: 'success'
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const errorMessage = response.message || 'Failed to add quarterly window';
|
||||||
|
setToastData({
|
||||||
|
message: errorMessage,
|
||||||
|
type: 'error'
|
||||||
|
});
|
||||||
|
console.error('Failed to add quarterly window:', errorMessage);
|
||||||
|
}
|
||||||
|
} else if (modalMode === 'edit' && editingRow !== null) {
|
||||||
|
const itemId = quarterData[editingRow]?.id;
|
||||||
|
if (!itemId) {
|
||||||
|
setToastData({
|
||||||
|
message: 'Error: Could not find the item to update',
|
||||||
|
type: 'error'
|
||||||
|
});
|
||||||
|
console.error('Error: Could not find the item to update');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const response = await updateQuarterlyWindow(itemId, formattedData);
|
||||||
|
if (response.status === 'success') {
|
||||||
|
// Fetch the latest data from the server
|
||||||
|
const latestData = await getQuarterlyWindows();
|
||||||
|
if (latestData.status === 'success' && Array.isArray(latestData.data)) {
|
||||||
|
const formattedData = latestData.data.map(item => ({
|
||||||
|
id: item.id,
|
||||||
|
survey_name: item.survey_name || '',
|
||||||
|
establishment: item.establishment || '-',
|
||||||
|
year: item.year?.toString() || '',
|
||||||
|
quarter: item.quarter || '',
|
||||||
|
startDate: item.start_date || '',
|
||||||
|
endDate: item.end_date || '',
|
||||||
|
gracePeriod: item.grace_periods_days ? `${item.grace_periods_days} days` : '0 days',
|
||||||
|
submissionCount: item.submission_count?.toString() || '-',
|
||||||
|
assigned: item.assigned?.toString() || '0',
|
||||||
|
responded: item.responded?.toString() || '0',
|
||||||
|
not_responded: item.not_responded?.toString() || '0',
|
||||||
|
status: item.is_active ? 'Active' : 'Inactive'
|
||||||
|
}));
|
||||||
|
setQuarterData(formattedData);
|
||||||
|
}
|
||||||
|
|
||||||
|
setToastData({
|
||||||
|
message: 'Quarterly survey updated successfully!',
|
||||||
|
type: 'success'
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const errorMessage = response.message || 'Failed to update quarterly window';
|
||||||
|
setToastData({
|
||||||
|
message: errorMessage,
|
||||||
|
type: 'error'
|
||||||
|
});
|
||||||
|
console.error('Failed to update quarterly window:', errorMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
setToastData({
|
|
||||||
message: 'Quarterly survey updated successfully!',
|
|
||||||
type: 'success'
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
const errorMessage = response.message || 'Failed to update quarterly window';
|
|
||||||
setToastData({
|
|
||||||
message: errorMessage,
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
console.error('Failed to update quarterly window:', errorMessage);
|
|
||||||
}
|
}
|
||||||
|
handleCloseModal();
|
||||||
|
} catch (error) {
|
||||||
|
const errorMessage = error.response?.data?.message || error.message || 'An error occurred while saving';
|
||||||
|
setToastData({
|
||||||
|
message: errorMessage,
|
||||||
|
type: 'error'
|
||||||
|
});
|
||||||
|
console.error('Error saving quarterly window:', error);
|
||||||
|
} finally {
|
||||||
|
setIsSaving(false);
|
||||||
}
|
}
|
||||||
handleCloseModal();
|
};
|
||||||
} catch (error) {
|
|
||||||
const errorMessage = error.response?.data?.message || error.message || 'An error occurred while saving';
|
|
||||||
setToastData({
|
|
||||||
message: errorMessage,
|
|
||||||
type: 'error'
|
|
||||||
});
|
|
||||||
console.error('Error saving quarterly window:', error);
|
|
||||||
} finally {
|
|
||||||
setIsSaving(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-full max-w-[1280px] rounded-lg border border-[#C3C6CB] bg-white min-h-[348px] pb-6">
|
<div className="w-full max-w-[1280px] rounded-lg border border-[#C3C6CB] bg-white min-h-[348px] pb-6">
|
||||||
@ -669,7 +668,7 @@ const handleSave = async () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="px-6 py-4">
|
<div className="px-6 py-4">
|
||||||
<div className="flex flex-col gap-3 md:h-12 md:flex-row md:items-center md:justify-between">
|
<div className="flex flex-col gap-3 md:h-12 md:flex-row md:items-center md:justify-between">
|
||||||
<h3 className="text-[18px] leading-[28px] font-medium text-[#232528]">Manage Surveys ({filteredRows.length})</h3>
|
<h3 className="text-[18px] leading-[28px] font-medium text-[#232528]">Manage Surveys ({filteredRows.length})</h3>
|
||||||
@ -727,9 +726,9 @@ const handleSave = async () => {
|
|||||||
// .map((h) => `"${h.name}"`)
|
// .map((h) => `"${h.name}"`)
|
||||||
// .join(',');
|
// .join(',');
|
||||||
const csvHeader = headers
|
const csvHeader = headers
|
||||||
.filter((h) => extractText(h.name) !== "") // remove Actions
|
.filter((h) => extractText(h.name) !== "") // remove Actions
|
||||||
.map((h) => `"${extractText(h.name)}"` ) // extract plain text
|
.map((h) => `"${extractText(h.name)}"`) // extract plain text
|
||||||
.join(',');
|
.join(',');
|
||||||
const csvRows = filteredRows.map((item) => {
|
const csvRows = filteredRows.map((item) => {
|
||||||
const rowData = [
|
const rowData = [
|
||||||
item.survey_name || '',
|
item.survey_name || '',
|
||||||
@ -758,21 +757,21 @@ const handleSave = async () => {
|
|||||||
document.body.removeChild(link);
|
document.body.removeChild(link);
|
||||||
URL.revokeObjectURL(url);
|
URL.revokeObjectURL(url);
|
||||||
}}
|
}}
|
||||||
className={`h-10 px-5 rounded-[6px] border text-sm inline-flex items-center gap-3 ${
|
className={`h-10 min-w-[143px] px-5 rounded-[6px] border text-sm inline-flex items-center gap-3
|
||||||
filteredRows.length
|
${filteredRows.length
|
||||||
? 'bg-[#F7F7F7] border-[#C3C6CB] text-[#232528]'
|
? 'bg-[#F7F7F7] border-[#C3C6CB] text-[#232528]'
|
||||||
: 'bg-[#F3F4F6] border-[#E5E7EB] text-[#9CA3AF] cursor-not-allowed'
|
: 'bg-[#F3F4F6] border-[#E5E7EB] text-[#9CA3AF] cursor-not-allowed'
|
||||||
}`}
|
}
|
||||||
|
`}
|
||||||
disabled={!filteredRows.length}
|
disabled={!filteredRows.length}
|
||||||
style={{ minWidth: '143px' }}
|
|
||||||
>
|
>
|
||||||
<img src={downloadIconSrc} alt="Export" className="h-5 w-5" />
|
<img src={downloadIconSrc} alt="Export" className="h-5 w-5" />
|
||||||
<span className="font-medium">Export CSV</span>
|
<span className="font-medium">Export CSV</span>
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={openAddModal}
|
onClick={openAddModal}
|
||||||
className="h-10 px-5 rounded-[6px] bg-[#92722A] text-white text-sm inline-flex items-center gap-3 cursor-pointer"
|
className="h-10 px-5 rounded-[6px] bg-[#92722A] text-white text-sm inline-flex items-center gap-3 cursor-pointer md:min-w-[148px]"
|
||||||
style={{ minWidth: '148px' }}
|
|
||||||
>
|
>
|
||||||
<img src={addIconSrc} alt="Add" className="h-5 w-5" />
|
<img src={addIconSrc} alt="Add" className="h-5 w-5" />
|
||||||
<span className="font-medium">Create Survey</span>
|
<span className="font-medium">Create Survey</span>
|
||||||
@ -833,13 +832,7 @@ const handleSave = async () => {
|
|||||||
<div className="fixed inset-0 z-50">
|
<div className="fixed inset-0 z-50">
|
||||||
<div className="absolute inset-0 bg-black/40" onClick={handleCloseModal} />
|
<div className="absolute inset-0 bg-black/40" onClick={handleCloseModal} />
|
||||||
<div
|
<div
|
||||||
className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 rounded-[16px] bg-white"
|
className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 rounded-[16px] bg-white w-[628px] max-w-[92vw] shadow-[0_24px_40px_rgba(27,29,33,0.16)] border border-[#E5E7EB]"
|
||||||
style={{
|
|
||||||
width: '628px',
|
|
||||||
maxWidth: '92vw',
|
|
||||||
boxShadow: '0 24px 40px rgba(27, 29, 33, 0.16)',
|
|
||||||
border: '1px solid #E5E7EB',
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<div className="flex items-center justify-between px-6 py-4 border-b border-[#F1F2F4]">
|
<div className="flex items-center justify-between px-6 py-4 border-b border-[#F1F2F4]">
|
||||||
<h3 className="text-[18px] font-medium text-[#232528]">
|
<h3 className="text-[18px] font-medium text-[#232528]">
|
||||||
@ -893,7 +886,7 @@ const handleSave = async () => {
|
|||||||
<p className="mt-1 text-sm text-red-600"></p>
|
<p className="mt-1 text-sm text-red-600"></p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
<div>
|
<div>
|
||||||
<SelectField
|
<SelectField
|
||||||
@ -914,7 +907,7 @@ const handleSave = async () => {
|
|||||||
<p className="mt-1 text-sm text-red-600"></p>
|
<p className="mt-1 text-sm text-red-600"></p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<SelectField
|
<SelectField
|
||||||
label={
|
label={
|
||||||
@ -937,7 +930,7 @@ const handleSave = async () => {
|
|||||||
<p className="mt-1 text-sm text-red-600"></p>
|
<p className="mt-1 text-sm text-red-600"></p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<DateField
|
<DateField
|
||||||
label={
|
label={
|
||||||
@ -957,7 +950,7 @@ const handleSave = async () => {
|
|||||||
<p className="mt-1 text-sm text-red-500">{validationErrors.startDate}</p>
|
<p className="mt-1 text-sm text-red-500">{validationErrors.startDate}</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<DateField
|
<DateField
|
||||||
label={
|
label={
|
||||||
@ -978,7 +971,7 @@ const handleSave = async () => {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<SelectField
|
<SelectField
|
||||||
label="Grace Period (Days)"
|
label="Grace Period (Days)"
|
||||||
|
|||||||
@ -62,8 +62,7 @@ const SubmissionDeadlines = () => {
|
|||||||
<div className="px-6 pb-6 flex items-center justify-end gap-3">
|
<div className="px-6 pb-6 flex items-center justify-end gap-3">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="h-9 px-5 rounded-md border text-[#92722A] bg-white cursor-pointer"
|
className="h-9 px-5 rounded-md border border-[#92722A] text-[#92722A] bg-white cursor-pointer"
|
||||||
style={{ borderColor: '#92722A' }}
|
|
||||||
onClick={handleCancel}
|
onClick={handleCancel}
|
||||||
>
|
>
|
||||||
Cancel
|
Cancel
|
||||||
|
|||||||
@ -964,14 +964,8 @@ const downloadSampleCSV = async () => {
|
|||||||
<div className="fixed inset-0 z-50">
|
<div className="fixed inset-0 z-50">
|
||||||
<div className="absolute inset-0 bg-black/40" onClick={closeModal} />
|
<div className="absolute inset-0 bg-black/40" onClick={closeModal} />
|
||||||
<div
|
<div
|
||||||
className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 rounded-[16px] bg-white"
|
className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 rounded-[16px] bg-white w-[628px] max-w-[92vw] shadow-[0_24px_40px_rgba(27,29,33,0.16)] border border-[#E5E7EB]"
|
||||||
style={{
|
>
|
||||||
width: '628px',
|
|
||||||
maxWidth: '92vw',
|
|
||||||
boxShadow: '0 24px 40px rgba(27, 29, 33, 0.16)',
|
|
||||||
border: '1px solid #E5E7EB',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div className="flex items-center justify-between px-6 py-4 border-b border-[#F1F2F4]">
|
<div className="flex items-center justify-between px-6 py-4 border-b border-[#F1F2F4]">
|
||||||
<h3 className="text-[18px] font-medium text-[#232528]">
|
<h3 className="text-[18px] font-medium text-[#232528]">
|
||||||
View Unit Master
|
View Unit Master
|
||||||
@ -1028,14 +1022,8 @@ const downloadSampleCSV = async () => {
|
|||||||
<div className="fixed inset-0 z-50">
|
<div className="fixed inset-0 z-50">
|
||||||
<div className="absolute inset-0 bg-black/40" onClick={closeModal} />
|
<div className="absolute inset-0 bg-black/40" onClick={closeModal} />
|
||||||
<div
|
<div
|
||||||
className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 rounded-xl bg-white"
|
className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 rounded-xl bg-white w-[628px] max-w-[92vw] shadow-[0_24px_40px_rgba(27,29,33,0.16)] border border-[#E5E7EB]"
|
||||||
style={{
|
>
|
||||||
width: '628px',
|
|
||||||
maxWidth: '92vw',
|
|
||||||
boxShadow: '0 24px 40px rgba(27, 29, 33, 0.16)',
|
|
||||||
border: '1px solid #E5E7EB',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div className="flex items-center justify-between px-6 py-4 border-b border-[#F1F2F4]">
|
<div className="flex items-center justify-between px-6 py-4 border-b border-[#F1F2F4]">
|
||||||
<h3 className="text-[18px] font-medium text-[#232528]">
|
<h3 className="text-[18px] font-medium text-[#232528]">
|
||||||
{modalMode === 'edit' ? 'Edit Unit Master' : 'Add Unit Master'}
|
{modalMode === 'edit' ? 'Edit Unit Master' : 'Add Unit Master'}
|
||||||
@ -1108,20 +1096,11 @@ const downloadSampleCSV = async () => {
|
|||||||
<div className="fixed inset-0 z-50">
|
<div className="fixed inset-0 z-50">
|
||||||
<div className="absolute inset-0 bg-black/40" onClick={closeDeleteConfirm} />
|
<div className="absolute inset-0 bg-black/40" onClick={closeDeleteConfirm} />
|
||||||
<div
|
<div
|
||||||
className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 rounded-lg bg-white border"
|
className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 rounded-lg bg-white border border-[#CBD5E1] w-[480px] max-w-[92vw] shadow-[0_20px_45px_rgba(0,0,0,0.12)]"
|
||||||
style={{
|
|
||||||
width: '480px',
|
|
||||||
maxWidth: '92vw',
|
|
||||||
borderColor: '#CBD5E1',
|
|
||||||
boxShadow: '0 20px 45px rgba(0,0,0,0.12)',
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<div className="px-8 py-6 space-y-6">
|
<div className="px-8 py-6 space-y-6">
|
||||||
<div className="flex items-start gap-3">
|
<div className="flex items-start gap-3">
|
||||||
<span
|
<span className="flex items-center justify-center w-8 h-9">
|
||||||
className="flex items-center justify-center"
|
|
||||||
style={{ width: '32px', height: '36px' }}
|
|
||||||
>
|
|
||||||
<img src={deleteIconSrc} alt="Delete" className="h-6 w-6" />
|
<img src={deleteIconSrc} alt="Delete" className="h-6 w-6" />
|
||||||
</span>
|
</span>
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
|
|||||||
@ -56,17 +56,17 @@ const Faq = () => {
|
|||||||
if (isOpen) {
|
if (isOpen) {
|
||||||
ref.current.style.maxHeight = ref.current.scrollHeight + "px";
|
ref.current.style.maxHeight = ref.current.scrollHeight + "px";
|
||||||
} else {
|
} else {
|
||||||
ref.current.style.maxHeight = "0px";
|
ref.current.classList.remove('max-h-md');
|
||||||
|
ref.current.classList.add('max-h-0');
|
||||||
}
|
}
|
||||||
}, [isOpen]);
|
}, [isOpen]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={`overflow-hidden transition-[max-height] duration-300 ${
|
className={`overflow-hidden transition-[max-height] duration-300 max-h-0 ${
|
||||||
isOpen ? "mt-3" : ""
|
isOpen ? "mt-3" : ""
|
||||||
}`}
|
}`}
|
||||||
style={{ maxHeight: "0px" }}
|
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -516,7 +516,7 @@ const ManufacturingIndex = () => {
|
|||||||
Next scheduled run: {nextScheduledRun}
|
Next scheduled run: {nextScheduledRun}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex text-sm text-gray-600">
|
<div className="flex text-sm text-gray-600">
|
||||||
<InfoOutlinedIcon className="text-gray-400 mr-1 mt-0.5 flex-shrink-0" style={{ fontSize: '1rem' }} />
|
<InfoOutlinedIcon className="text-gray-400 text-base mr-1 mt-0.5 flex-shrink-0" />
|
||||||
<span className="whitespace-nowrap">Formula: Manufacturing index<sub>t</sub> = Σ (sector weight<sub>i</sub> × group index<sub>i,t</sub>)</span>
|
<span className="whitespace-nowrap">Formula: Manufacturing index<sub>t</sub> = Σ (sector weight<sub>i</sub> × group index<sub>i,t</sub>)</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user