changed quarter

This commit is contained in:
Malini 2025-11-08 18:58:07 +05:30
parent 31883f8689
commit 776f1391d2
11 changed files with 222 additions and 144 deletions

View File

@ -57,13 +57,13 @@ const SubmissionTable = ({ selectedQuarter, selectedYear }) => {
const titleText = useMemo(() => {
const count = filtered.length;
if (selectedQuarter !== 'All' && selectedYear !== 'All') {
return `Recent 10 Submissions for Selected Quarter ${selectedQuarter} ${selectedYear} (${count})`;
return ` Recent Submissions for Selected Quarter ${selectedQuarter} ${selectedYear} (${count})`;
} else if (selectedQuarter !== 'All') {
return `Recent 10 Submissions for Selected Quarter ${selectedQuarter} (${count})`;
return `Recent Submissions for Selected Quarter ${selectedQuarter} (${count})`;
} else if (selectedYear !== 'All') {
return `Recent 10 Submissions for Selected Year ${selectedYear} (${count})`;
return `Recent Submissions for Selected Year ${selectedYear} (${count})`;
} else {
return `Recent 10 Submissions (${count})`;
return `Recent Submissions (${count})`;
}
}, [selectedQuarter, selectedYear, filtered]);

View File

@ -115,15 +115,22 @@ export const SubmissionHistory = ({ history = [], loading = false, error = '' })
const normalizedHistory = React.useMemo(() => {
if (!Array.isArray(history)) return [];
return history.map((entry, index) => ({
id: entry?.id ?? index,
survey_name: 'Industrial Production Survey',
year: entry?.year || '—',
quarter: entry?.quarter || '—',
status: entry?.status || 'Pending',
submission_on: formatDateTime(entry?.created_at || entry?.submitted_on),
products: entry?.product_count ?? 0,
}));
return history.map((entry, index) => {
const quarter = entry?.quarter || '';
const year = entry?.year || '';
const surveyName = `IPI ${quarter} ${year} Survey`;
return {
id: entry?.id ?? index,
survey_name: surveyName,
year: year || '—',
quarter: quarter || '—',
status: entry?.status || 'Pending',
submission_on: formatDateTime(entry?.created_at || entry?.submitted_on),
products: entry?.product_count ?? 0,
originalData: entry // Keep original data for reference
};
});
}, [history]);
const filtered = normalizedHistory.filter((entry) => {
@ -165,88 +172,90 @@ export const SubmissionHistory = ({ history = [], loading = false, error = '' })
return (
<>
<div className="max-w-[1280px] mx-auto bg-white border border-[#E5E7EB] shadow-[0_16px_32px_rgba(15,23,42,0.06)] rounded-[8px] mt-8 w-full overflow-hidden">
<div className="flex items-center justify-between px-6 pt-6 pb-4">
<h2 className="text-[18px] leading-[28px] font-medium text-[#232528]">
Submission History
</h2>
<div className="min-h-[4rem] mt-[-70px]">
<div className="max-w-[1280px] mx-auto mb-5 bg-white border border-[#E5E7EB] shadow-[0_16px_32px_rgba(15,23,42,0.06)] rounded-[8px] mt-8 w-full overflow-hidden">
<div className="flex items-center justify-between px-6 pt-6 pb-4">
<h2 className="text-[18px] leading-[28px] font-medium text-[#232528]">
Submission History
</h2>
<div className="flex items-center gap-3">
<div className="relative w-56">
<input
type="text"
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
placeholder="Search Establishment"
className="w-full h-10 rounded-md border border-[#E5E7EB] pl-10 pr-3 text-sm focus:outline-none focus:ring-1 focus:ring-[#92722A]"
/>
<img
src={searchIconSrc}
alt="Search"
className="pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 h-5 w-5"
/>
</div>
<button
type="button"
onClick={() => downloadCsv(filtered)}
disabled={!filtered.length}
className={`inline-flex h-10 items-center gap-2 rounded-md border px-4 text-sm font-medium ${
filtered.length
? 'border-[#92722A] text-[#92722A] hover:bg-[#F2ECCF]'
: 'border-gray-200 text-gray-400 cursor-not-allowed'
}`}
>
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-4 w-4"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M4 16v2a2 2 0 002 2h12a2 2 0 002-2v-2M7 10l5 5m0 0l5-5m-5 5V4"
<div className="flex items-center gap-3">
<div className="relative w-56">
<input
type="text"
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
placeholder="Search Establishment"
className="w-full h-10 rounded-md border border-[#E5E7EB] pl-10 pr-3 text-sm focus:outline-none focus:ring-1 focus:ring-[#92722A]"
/>
</svg>
<span>Export CSV</span>
</button>
</div>
</div>
<div className="overflow-x-auto">
{loading ? (
<div className="flex items-center justify-center h-[500px] text-gray-500">
Loading submissions...
</div>
) : filtered.length === 0 ? (
<div className="flex items-center justify-center py-20 text-[#7B5C1F] font-semibold text-[15px]">
No Submission Found
</div>
) : (
<div className="overflow-x-auto">
<div className="min-w-[1200px]">
<Table
headers={tableHeaders}
rows={tableRows}
separated
rowGapClass="border-spacing-y-1"
pagination={{
currentPage,
onPageChange: setCurrentPage,
pageSize,
totalItems: filtered.length,
}}
columnWidths={[250, 100, 100, 160, 180, 150, 120]}
<img
src={searchIconSrc}
alt="Search"
className="pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 h-5 w-5"
/>
</div>
<button
type="button"
onClick={() => downloadCsv(filtered)}
disabled={!filtered.length}
className={`inline-flex h-10 items-center gap-2 rounded-md border px-4 text-sm font-medium ${filtered.length
? 'border-[#92722A] text-[#92722A] hover:bg-[#F2ECCF]'
: 'border-gray-200 text-gray-400 cursor-not-allowed'
}`}
>
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-4 w-4"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M4 16v2a2 2 0 002 2h12a2 2 0 002-2v-2M7 10l5 5m0 0l5-5m-5 5V4"
/>
</svg>
<span>Export CSV</span>
</button>
</div>
)}
</div>
<div className="overflow-x-auto">
{loading ? (
<div className="flex items-center justify-center h-[500px] text-gray-500">
Loading submissions...
</div>
) : filtered.length === 0 ? (
<div className="flex items-center justify-center py-20 text-[#7B5C1F] font-semibold text-[15px]">
No Submission Found
</div>
) : (
<div className="overflow-x-auto">
<div className="min-w-[1200px] ">
<Table
headers={tableHeaders}
rows={tableRows}
separated
rowGapClass="border-spacing-y-1"
pagination={{
currentPage,
onPageChange: setCurrentPage,
pageSize,
totalItems: filtered.length,
}}
columnWidths={[250, 100, 100, 160, 180, 150, 120]}
/>
</div>
</div>
)}
</div>
</div>
</div>
<Footer />
</>
);

View File

@ -31,7 +31,7 @@ const SurveyCarousel = ({
return (
<div className="bg-black rounded-lg shadow-sm ring-1 w-[1275px] ring-gray-200 h-[148px] mb-8 ml-2 ">
<div className="rounded-none bg-[#F2ECCF] px-8 py-8 min-h-[148px] flex items-center justify-between transition-all duration-500">
<div className="rounded-none bg-[#F2ECCF] px-8 py-10 min-h-[148px] flex items-center justify-between transition-all duration-500">
<div className="flex-1">
<h3 className="text-[18px] leading-[28px] font-medium text-[#232528]">
{current?.title || '—'}

View File

@ -83,20 +83,19 @@ export const SurveyStatus = () => {
fetchData();
}, []);
const handleStartSurvey = (survey) => {
// The survey object contains all the data from survey_ready
console.log('Survey data being passed to survey screen:', {
quarter: survey.quarter,
year: survey.year,
startDate: survey.startDate,
endDate: survey.endDate,
title: survey.title
});
// You can add any additional processing here before navigation
// For example, you might want to store the selected survey in state
// or make an API call to initialize the survey
};
const handleStartSurvey = (survey) => {
// Store the survey data in localStorage
localStorage.setItem('currentSurvey', JSON.stringify({
quarter: survey.quarter,
year: survey.year,
startDate: survey.startDate,
endDate: survey.endDate,
title: survey.title
}));
// Navigate to the survey page
navigate('/survey');
};
const nextDeadline = dashboardData?.next_deadline;
const formattedDueDate = formatDate(nextDeadline);
@ -133,7 +132,7 @@ export const SurveyStatus = () => {
: 'Complete your quarterly industrial production data submission';
return (
<section className="max-w-[1340px] mx-auto px-0">
<section className="max-w-[1340px] mx-auto px-0 pb-15">
<div className="p-6">
{loading ? (
<div className="text-center text-gray-500 text-sm py-10">

View File

@ -1,38 +1,38 @@
import React from 'react';
import HeaderBar from '@/components/layout/HeaderBar';
const getCurrentQuarterAndYear = () => {
const now = new Date();
const month = now.getMonth() + 1;
const year = now.getFullYear();
let quarter = '';
// const getCurrentQuarterAndYear = () => {
// const now = new Date();
// const month = now.getMonth() + 1;
// const year = now.getFullYear();
// let quarter = '';
if (month >= 1 && month <= 3) quarter = 'Q1';
else if (month >= 4 && month <= 6) quarter = 'Q2';
else if (month >= 7 && month <= 9) quarter = 'Q3';
else quarter = 'Q4';
// if (month >= 1 && month <= 3) quarter = 'Q1';
// else if (month >= 4 && month <= 6) quarter = 'Q2';
// else if (month >= 7 && month <= 9) quarter = 'Q3';
// else quarter = 'Q4';
return { quarter, year };
};
// return { quarter, year };
// };
export const WelcomeSection = ({ data = null, loading = false, error = '' }) => {
const { quarter: currentQuarter, year: currentYear } = getCurrentQuarterAndYear();
// const { quarter: currentQuarter, year: currentYear } = getCurrentQuarterAndYear();
let description = 'Current reporting information unavailable.';
if (loading) {
description = 'Loading dashboard information…';
} else if (error) {
description = error;
} else if (currentQuarter && currentYear) {
description = `Current reporting period: ${currentQuarter} ${currentYear}`;
}
// let description = 'Current reporting information unavailable.';
// if (loading) {
// description = 'Loading dashboard information';
// } else if (error) {
// description = error;
// } else if (currentQuarter && currentYear) {
// description = `Current reporting period: ${currentQuarter} ${currentYear}`;
// }
return (
<div className="min-h-[4rem] bg-gray-50">
<HeaderBar />
<div className="max-w-[1280px] mx-auto px-4 pt-4 pb-2">
<div className="max-w-[1280px] mx-auto px-4 pt-4 ">
<div className="space-y-1">
<h2 className="w-[360px] text-[18px] leading-[28px] font-medium text-[#232528]">
<h2 className="w-[360px] text-[18px] pt-4 leading-[28px] font-medium text-[#232528]">
Welcome{' '}
{(() => {
try {
@ -44,13 +44,13 @@ export const WelcomeSection = ({ data = null, loading = false, error = '' }) =>
}
})()}!
</h2>
<p
{/* <p
className={`w-[360px] text-[14px] leading-[24px] font-normal ${
error ? 'text-red-600' : 'text-[#5F646D]'
}`}
>
{description}
</p>
</p> */}
</div>
</div>
</div>

View File

@ -81,11 +81,26 @@ const HeaderBar = () => {
</NavLink>
<NavLink
to="/survey"
className={({ isActive }) => `inline-flex items-center gap-2 pb-1 border-b-2 ${isActive ? 'text-[#92722A] font-medium border-[#92722A]' : 'text-[#232528] hover:text-gray-900 border-transparent'}`}
className={({ isActive, isPending }) => `inline-flex items-center gap-2 pb-1 border-b-2 ${
isActive
? 'text-[#92722A] font-medium border-[#92722A]'
: window.location.pathname === '/dashboard'
? 'text-gray-400 cursor-not-allowed'
: 'text-[#232528] hover:text-gray-900 border-transparent'
}`}
onClick={(e) => {
if (window.location.pathname === '/dashboard') {
e.preventDefault();
}
}}
>
{({ isActive }) => (
<>
<img src={isActive ? surveyIconActiveSrc : surveyIconInactiveSrc} alt="Survey" className="h-[18px] w-[18px]" />
<img
src={isActive ? surveyIconActiveSrc : surveyIconInactiveSrc}
alt="Survey"
className={`h-[18px] w-[18px] ${window.location.pathname === '/dashboard' ? 'opacity-50' : ''}`}
/>
<span>Survey</span>
</>
)}
@ -163,8 +178,28 @@ const HeaderBar = () => {
<img src={dashboardIconInactiveSrc} alt="Dashboard" className="h-[18px] w-[18px]" />
<span>Dashboard</span>
</NavLink>
<NavLink to="/survey" onClick={() => setOpen(false)} className={({ isActive }) => `inline-flex items-center gap-2 px-2 py-2 rounded border-b-2 ${isActive ? 'text-[#92722A] bg-[#F2ECCF] border-[#92722A]' : 'text-[#232528] hover:bg-gray-100 border-transparent'}`}>
<img src={surveyIconInactiveSrc} alt="Survey" className="h-[18px] w-[18px]" />
<NavLink
to="/survey"
onClick={(e) => {
if (window.location.pathname === '/dashboard') {
e.preventDefault();
} else {
setOpen(false);
}
}}
className={({ isActive }) => `inline-flex items-center gap-2 px-2 py-2 rounded border-b-2 ${
isActive
? 'text-[#92722A] bg-[#F2ECCF] border-[#92722A]'
: window.location.pathname === '/dashboard'
? 'text-gray-400 cursor-not-allowed bg-gray-100'
: 'text-[#232528] hover:bg-gray-100 border-transparent'
}`}
>
<img
src={surveyIconInactiveSrc}
alt="Survey"
className={`h-[18px] w-[18px] ${window.location.pathname === '/dashboard' ? 'opacity-50' : ''}`}
/>
<span>Survey</span>
</NavLink>
<NavLink to="/overview" onClick={() => setOpen(false)} className={({ isActive }) => `inline-flex items-center gap-2 px-2 py-2 rounded border-b-2 ${isActive ? 'text-[#92722A] bg-[#F2ECCF] border-[#92722A]' : 'text-[#232528] hover:bg-gray-100 border-transparent'}`}>

View File

@ -105,6 +105,7 @@ const createEmptyProfile = () => ({
permanentFactoryCode: '',
uniqueLicenseNumber: '',
industryCodeBusiness: '',
industryCodeProduction: '',
industryCodeCurrent: '',
industryDescription: '',
// Establishment contact details
@ -2026,7 +2027,7 @@ const requiredFields = [
factory_name: form.establishmentName || form.contactName || '',
permanent_factory_code: form.permanentFactoryCode || '',
industry_code: form.industryCodeBusiness || form.industryCodeCurrent || '',
industry_code_production: form.industryCodeBusiness || form.industryCodeCurrent || '',
industry_code_production: form.industryCodeProduction || '',
license_number: form.uniqueLicenseNumber || '',
isic_code: form.isicCode || form.industryCodeBusiness || '',
description: form.industryDescription || '',

View File

@ -250,7 +250,7 @@ const UnitMaster = () => {
const handleSave = async () => {
const selectedProducts = Array.isArray(form.productsMapped) ? form.productsMapped : [];
console.log(selectedProducts,"selectedProducts");
// Validation checks
if (!form.unitName) {
setToastData({
@ -292,8 +292,9 @@ const UnitMaster = () => {
uom: form.unitName,
uom_short_name: form.description,
is_active: form.status === 'Active',
productsMapped: selectedProducts,
productsMapped: selectedProducts.length,
};
console.log("unitData",unitData)
try {
setLoading(true);

View File

@ -884,8 +884,9 @@ const tableRows = auditHistory.map((entry, index) => {
{ width: 80, style: { whiteSpace: 'normal', wordWrap: 'break-word' } }, // Quarter
{ width: 120, style: { whiteSpace: 'normal', wordWrap: 'break-word' } }, // HS Code
{ width: 200, style: { whiteSpace: 'normal', wordWrap: 'break-word' } }, // Product
{ width: 130, align: 'center', style: { whiteSpace: 'normal', wordWrap: 'break-word' } }, // Status
{ width: 150, style: { whiteSpace: 'normal', wordWrap: 'break-word' } }, // Actors
{ width: 150, align: 'center', style: { whiteSpace: 'normal', wordWrap: 'break-word' } }, // Status
{ width: 100, style: { padding: 10, margin: 0 } }, // Gap between Status and Actors
{ width: 200, style: { whiteSpace: 'normal', wordWrap: 'break-word' } }, // Actors
{ width: 270, style: { whiteSpace: 'normal', wordWrap: 'break-word' } } // Details
]}
pagination={{

View File

@ -157,8 +157,8 @@ const Overview = () => {
const toolbar = (
<div className="px-6 pt-6 pb-4 flex flex-col gap-4 md:flex-row md:items-center md:justify-between">
<div>
<h2 className="text-[18px] font-medium text-[#232528]">Quarter Overview</h2>
<div className="flex items-center gap-2">
<h2 className="text-[18px] font-medium text-[#232528]">Quarter Overview ({filteredRows.length})</h2>
</div>
<div className="flex flex-col md:flex-row md:items-center gap-3">
<div className="relative w-full md:w-72">
@ -228,7 +228,7 @@ const Overview = () => {
<div className="min-h-screen bg-[#F8FAFC]">
<HeaderBar />
<main className="max-w-[1280px] mx-auto px-4 py-6">
<button
{/* <button
onClick={() => setSelectedSubmission(null)}
className="mb-4 flex items-center text-[#9E792B] hover:text-[#7b5f22] font-medium"
>
@ -236,7 +236,7 @@ const Overview = () => {
<path fillRule="evenodd" d="M9.707 16.707a1 1 0 01-1.414 0l-6-6a1 1 0 010-1.414l6-6a1 1 0 011.414 1.414L5.414 9H17a1 1 0 110 2H5.414l4.293 4.293a1 1 0 010 1.414z" clipRule="evenodd" />
</svg>
Back to Submissions
</button>
</button> */}
<DetailedOverview submission={selectedSubmission} onBack={() => setSelectedSubmission(null)} />
</main>
</div>

View File

@ -1,4 +1,4 @@
import React from 'react';
import React, { useEffect } from 'react';
import { useLocation, useNavigate } from 'react-router-dom';
import { submitSurvey, fetchSubmissionDetail, resubmitSurvey } from '@/services/submissions/submissionService';
import { fetchEstablishmentDetail, fetchEstablishmentDashboard } from '@/services/establishments/establishmentService';
@ -70,6 +70,7 @@ const Survey = () => {
const [viewError, setViewError] = React.useState('');
const [establishmentLoading, setEstablishmentLoading] = React.useState(false);
const [establishmentError, setEstablishmentError] = React.useState('');
const [surveyData, setSurveyData] = React.useState(null);
const isViewMode = React.useMemo(() => Boolean(locationState.submission), [locationState.submission]);
const isResubmit = React.useMemo(() => locationState?.isResubmit === true, [locationState?.isResubmit]);
const submissionId = React.useMemo(() => locationState?.submissionId || locationState?.submission?.id, [locationState]);
@ -79,6 +80,20 @@ const Survey = () => {
setStep(initialStepFromState);
}, [initialStepFromState]);
useEffect(() => {
const savedSurvey = localStorage.getItem('currentSurvey');
if (savedSurvey) {
const surveyData = JSON.parse(savedSurvey);
setSurveyData(surveyData);
// Update the establishmentData with the saved survey data
setEstablishmentData(prev => ({
...prev,
quarter: surveyData.quarter || '',
year: surveyData.year || ''
}));
}
}, []);
// Function to fetch current quarter and year from dashboard
const fetchCurrentQuarterAndYear = async () => {
try {
@ -373,9 +388,14 @@ const Survey = () => {
const buildSubmissionPayload = React.useCallback((isResubmitFlow = false) => {
const info = establishmentData?.employeeInfo ?? {};
// Get quarter and year from surveyData if available, otherwise from establishmentData
const quarter = surveyData?.quarter || '';
const year = surveyData?.year || '';
return {
quarter: establishmentData?.quarter ?? '',
year: parseNumber(establishmentData?.year),
quarter: quarter,
year: year,
status: 'Submitted',
emirati_male: parseNumber(info.emiratiMale),
emirati_female: parseNumber(info.emiratiFemale),
@ -511,6 +531,8 @@ const Survey = () => {
showToast('success', response?.message || 'You have successfully submitted the survey.');
setShowSuccessPopup(true);
setHasSubmitted(true);
// Clear the stored survey data after successful submission
localStorage.removeItem('currentSurvey');
} catch (error) {
console.error('Failed to submit survey', error);
const message = error?.response?.data?.message || error?.message || 'Failed to submit survey.';
@ -537,6 +559,9 @@ const Survey = () => {
setShowSuccessPopup(true);
setHasSubmitted(true);
showToast('success', 'Survey resubmitted successfully!');
localStorage.removeItem('surveyRemarks');
// Clear the stored survey data after successful resubmission
localStorage.removeItem('currentSurvey');
} catch (error) {
console.error('Resubmission failed:', error);
const message = error?.response?.data?.message || error?.message || 'Failed to resubmit survey. Please try again.';
@ -558,12 +583,17 @@ const Survey = () => {
try {
const payload = buildSubmissionPayload();
console.log('Submission Payload:', JSON.stringify(payload, null, 2));
await submitSurvey(payload);
setShowSuccessPopup(true);
setHasSubmitted(true);
showToast('success', 'Survey submitted successfully!');
localStorage.removeItem('surveyRemarks');
// Clear the stored survey data after successful submission
localStorage.removeItem('currentSurvey');
} catch (error) {
const message = error?.response?.data?.message || error?.message || 'Failed to submit survey. Please try again.';
console.error('Submission Error:', error);
setError(message);
showToast('error', message);
} finally {
@ -819,7 +849,9 @@ const Survey = () => {
{/* Message */}
<p className="text-sm text-gray-700">
Thank you. Your IP Quarterly Survey for <span className="font-semibold text-gray-900">{establishmentData?.quarter} {establishmentData?.year}</span> has been {isResubmit ? 'resubmitted' : 'submitted'}.
Thank you. Your IP Quarterly Survey for <span className="font-semibold text-gray-900">
{surveyData?.quarter} {surveyData?.year}
</span> has been {isResubmit ? 'resubmitted' : 'submitted'}.
</p>
{/* Button */}