Merge branch 'master' of https://bitbucket.org/jubilian/fcsc_ipi_frontend
This commit is contained in:
commit
3f2e7249f8
@ -24,16 +24,20 @@ const formatDateTime = (value) => {
|
||||
|
||||
const getStatusClass = (status) => {
|
||||
const normalized = String(status || '').toLowerCase();
|
||||
|
||||
if (normalized === 'approved') {
|
||||
return 'inline-flex items-center rounded-md bg-green-100 px-2 py-1 text-xs font-medium text-green-800';
|
||||
return 'inline-flex items-center rounded-md bg-[#F5FAF6] px-2 py-1 text-xs font-medium text-[#2F663C]';
|
||||
}
|
||||
|
||||
if (['pending', 'under review', 'in-progress'].includes(normalized)) {
|
||||
return 'inline-flex items-center rounded-md bg-yellow-100 px-2 py-1 text-xs font-medium text-yellow-800';
|
||||
return 'inline-flex items-center rounded-md bg-[#FFFDF3] px-2 py-1 text-xs font-medium text-[#7C5E24]';
|
||||
}
|
||||
|
||||
if (['rejected', 'returned'].includes(normalized)) {
|
||||
return 'inline-flex items-center rounded-md bg-red-100 px-2 py-1 text-xs font-medium text-red-800';
|
||||
return 'inline-flex items-center rounded-md bg-[#FEF6F6] px-2 py-1 text-xs font-medium text-[#B52520]';
|
||||
}
|
||||
return 'inline-flex items-center rounded-md bg-gray-100 px-2 py-1 text-xs font-medium text-gray-800';
|
||||
|
||||
return 'inline-flex items-center rounded-md bg-[#F8FAFC] px-2 py-1 text-xs font-medium text-[#374151]';
|
||||
};
|
||||
|
||||
const downloadCsv = (rows) => {
|
||||
@ -94,12 +98,27 @@ export const SubmissionHistory = ({ history = [], loading = false, error = '' })
|
||||
const rowsData = filteredRows.map((item) => {
|
||||
const productCount = Number(item.products) || 0;
|
||||
const productLabel = `${productCount} ${productCount === 1 ? 'product' : 'products'}`;
|
||||
|
||||
|
||||
return [
|
||||
item.survey_name,
|
||||
item.year,
|
||||
item.quarter,
|
||||
<span className={getStatusClass(item.status)}>{item.status}</span>,
|
||||
|
||||
(() => {
|
||||
const normalized = String(item.status || '').toLowerCase();
|
||||
let displayStatus = '—';
|
||||
|
||||
if (normalized === 'pending') displayStatus = 'Under Review';
|
||||
else if (normalized === 'rejected') displayStatus = 'Returned';
|
||||
else if (['submitted', 'approved'].includes(normalized)) displayStatus = 'Approved';
|
||||
|
||||
return (
|
||||
<span className={getStatusClass(displayStatus)}>
|
||||
{displayStatus}
|
||||
</span>
|
||||
);
|
||||
})(),
|
||||
|
||||
<span className="whitespace-nowrap">{item.submission_on}</span>,
|
||||
productLabel,
|
||||
<button
|
||||
@ -109,7 +128,7 @@ export const SubmissionHistory = ({ history = [], loading = false, error = '' })
|
||||
View Details
|
||||
</button>,
|
||||
];
|
||||
});
|
||||
});
|
||||
|
||||
const toolbar = (
|
||||
<div className="px-4 pt-6 pb-2 flex flex-col gap-3 md:flex-row md:items-center md:justify-between">
|
||||
@ -185,25 +204,50 @@ export const SubmissionHistory = ({ history = [], loading = false, error = '' })
|
||||
|
||||
return (
|
||||
<>
|
||||
<section className="max-w-[1280px] mx-auto px-0">
|
||||
<Table
|
||||
headers={[
|
||||
<section className="max-w-[1280px] mx-auto px-0">
|
||||
<div className="overflow-x-auto rounded-lg border border-[#D9D9DC] shadow-sm bg-white">
|
||||
<table className="min-w-full border-collapse text-sm text-[#232528]">
|
||||
<thead>
|
||||
<tr className="bg-[#F2ECCF] text-left text-[13px] font-semibold text-[#232528]">
|
||||
{[
|
||||
'Survey Name',
|
||||
'Year',
|
||||
'Quarter',
|
||||
'Status',
|
||||
'Submission On',
|
||||
'Submission on',
|
||||
'Products',
|
||||
'Actions',
|
||||
]}
|
||||
rows={rowsData}
|
||||
beforeHeader={toolbar}
|
||||
separated
|
||||
rowGapClass="border-spacing-y-2"
|
||||
columnWidths={[300, 100, 100, 120, 180, 120, 120]}
|
||||
/>
|
||||
</section>
|
||||
].map((header, index) => (
|
||||
<th
|
||||
key={index}
|
||||
className="px-4 py-3 border-b border-[#D9D9DC] whitespace-nowrap"
|
||||
>
|
||||
{header}
|
||||
</th>
|
||||
))}
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody className="divide-y divide-[#D9D9DC] text-[13px] leading-[20px]">
|
||||
{rowsData.map((row, rowIndex) => (
|
||||
<tr
|
||||
key={rowIndex}
|
||||
className="hover:bg-[#FAFAFA] transition-colors duration-150"
|
||||
>
|
||||
{row.map((cell, cellIndex) => (
|
||||
<td
|
||||
key={cellIndex}
|
||||
className="px-4 py-3 align-middle whitespace-nowrap border-b border-[#D9D9DC]"
|
||||
>
|
||||
{cell}
|
||||
</td>
|
||||
))}
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
<Footer />
|
||||
</>
|
||||
);
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { ChevronLeft, ChevronRight, Pause } from 'lucide-react';
|
||||
|
||||
import { CalendarDays, Clock3 } from 'lucide-react';
|
||||
const SurveyCarousel = ({
|
||||
surveys = [],
|
||||
autoRotate = true,
|
||||
@ -39,11 +39,25 @@ const SurveyCarousel = ({
|
||||
<p className="mt-1 text-[16px] leading-[24px] font-medium text-[#232528]">
|
||||
{current?.subtitle || ''}
|
||||
</p>
|
||||
<div className="mt-2 flex items-center gap-6 text-[12px] leading-[16px] font-medium text-[#232528]">
|
||||
<span>Due Date: {current?.dueDate || '—'}</span>
|
||||
<span>Est. time: {current?.estTime || '—'}</span>
|
||||
<span>Status: {current?.status || '—'}</span>
|
||||
</div>
|
||||
|
||||
<div className="mt-2 flex items-center gap-6 text-[12px] leading-[16px] font-medium text-[#232528]">
|
||||
<span className="flex items-center gap-1">
|
||||
<CalendarDays size={14} className="text-[#92722A]" />
|
||||
<span className="font-semibold">Due Date:</span>
|
||||
{current?.dueDate || '—'}
|
||||
</span>
|
||||
|
||||
<span className="flex items-center gap-1">
|
||||
<Clock3 size={14} className="text-[#92722A]" />
|
||||
<span className="font-semibold">Est. time:</span>
|
||||
{current?.estTime || '—'}
|
||||
</span>
|
||||
|
||||
<span>
|
||||
<span className="font-semibold">Status:</span>
|
||||
{current?.status || '—'}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button
|
||||
|
||||
@ -46,7 +46,7 @@ export const SurveyStatus = ({ data = null, loading = false, error = '' }) => {
|
||||
const surveys = [
|
||||
{
|
||||
title: `${formatQuarterYear(surveyData.previous_quarter, surveyData.previous_quarter_year)} Survey Ready`,
|
||||
subtitle: 'Complete your quarterly industrial production data submission',
|
||||
subtitle: 'Complete your quarterly Industrial Production Index (IPI) data submission',
|
||||
dueDate: formattedDueDate,
|
||||
relativeDue,
|
||||
estTime: '15–20 minutes',
|
||||
|
||||
@ -11,7 +11,6 @@ const formatDate = (value) => {
|
||||
export const WelcomeSection = ({ data = null, loading = false, error = '' }) => {
|
||||
const currentQuarter = data?.current_quarter;
|
||||
const currentYear = data?.current_quarter_year;
|
||||
const deadline = data?.next_deadline;
|
||||
|
||||
let description = 'Current reporting information unavailable.';
|
||||
if (loading) {
|
||||
@ -19,31 +18,35 @@ export const WelcomeSection = ({ data = null, loading = false, error = '' }) =>
|
||||
} else if (error) {
|
||||
description = error;
|
||||
} else if (currentQuarter && currentYear) {
|
||||
const formattedDeadline = formatDate(deadline);
|
||||
description = `Current reporting period: ${currentQuarter} ${currentYear}${formattedDeadline !== '—' ? ` (Due: ${formattedDeadline})` : ''}`;
|
||||
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="space-y-1">
|
||||
<h2 className="w-[360px] text-[18px] leading-[28px] font-medium text-[#232528]">
|
||||
Welcome{' '}
|
||||
{(() => {
|
||||
try {
|
||||
const userProfile = JSON.parse(sessionStorage.getItem('user_profile'));
|
||||
return userProfile?.name ? userProfile.name : '';
|
||||
} catch (error) {
|
||||
console.error('Error reading user_profile from sessionStorage:', error);
|
||||
return '';
|
||||
}
|
||||
})()} !
|
||||
</h2>
|
||||
<p className={`w-[360px] text-[14px] leading-[24px] font-normal ${error ? 'text-red-600' : 'text-[#5F646D]'}`}>{description}</p>
|
||||
<h2 className="w-[360px] text-[18px] leading-[28px] font-medium text-[#232528]">
|
||||
Welcome{' '}
|
||||
{(() => {
|
||||
try {
|
||||
const userProfile = JSON.parse(sessionStorage.getItem('user_profile'));
|
||||
return userProfile?.name ? userProfile.name : '';
|
||||
} catch (error) {
|
||||
console.error('Error reading user_profile from sessionStorage:', error);
|
||||
return '';
|
||||
}
|
||||
})()}!
|
||||
</h2>
|
||||
<p
|
||||
className={`w-[360px] text-[14px] leading-[24px] font-normal ${
|
||||
error ? 'text-red-600' : 'text-[#5F646D]'
|
||||
}`}
|
||||
>
|
||||
{description}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
};
|
||||
Loading…
Reference in New Issue
Block a user