diff --git a/ipi-survey-platform/src/components/admin/AdminHeader.jsx b/ipi-survey-platform/src/components/admin/AdminHeader.jsx index 4b27f34..75a1204 100644 --- a/ipi-survey-platform/src/components/admin/AdminHeader.jsx +++ b/ipi-survey-platform/src/components/admin/AdminHeader.jsx @@ -78,7 +78,7 @@ const AdminHeader = () => { FCSC diff --git a/ipi-survey-platform/src/components/admin/StatCard.jsx b/ipi-survey-platform/src/components/admin/StatCard.jsx index 5fbfe3b..e5479db 100644 --- a/ipi-survey-platform/src/components/admin/StatCard.jsx +++ b/ipi-survey-platform/src/components/admin/StatCard.jsx @@ -1,16 +1,16 @@ import React from 'react'; -const StatCard = ({ icon = null, label, value, width = 200.4 }) => { +const StatCard = ({ icon = null, label, value, tooltipText, width = 200.4 }) => { const resolvedWidth = typeof width === 'number' ? `${width}px` : width; return (
-
+
{icon &&
{icon}
} - + {label}
@@ -18,6 +18,13 @@ const StatCard = ({ icon = null, label, value, width = 200.4 }) => { {value} + + {tooltipText && ( +
+ {tooltipText} +
+
+ )}
); }; diff --git a/ipi-survey-platform/src/components/admin/SubmissionTable.jsx b/ipi-survey-platform/src/components/admin/SubmissionTable.jsx index 49e3208..eccc512 100644 --- a/ipi-survey-platform/src/components/admin/SubmissionTable.jsx +++ b/ipi-survey-platform/src/components/admin/SubmissionTable.jsx @@ -1,125 +1,68 @@ -import React, { useState, useMemo } from 'react'; +import React, { useState, useEffect, useMemo } from 'react'; import Table from '@/components/common/Table'; +import apiClient from '../../services/api/apiClient.js'; +import { CheckCircle2, XCircle, Eye } from 'lucide-react'; -const searchIconSrc = '/assets/images/material-symbols_search-rounded.svg'; -const checkCircleSrc = '/assets/images/check-circle-fill 1.svg'; -const xCircleSrc = '/assets/images/warning-circle-fill 1.svg'; -const eyeIconSrc = '/assets/images/User-active.svg'; +const SubmissionTable = ({ selectedQuarter, selectedYear }) => { + const [data, setData] = useState([]); + const [loading, setLoading] = useState(true); + useEffect(() => { + const fetchDashboardData = async () => { + try { + setLoading(true); + const response = await apiClient.get('/admin_dashboard'); + const result = response?.data; + if (result?.status === 'success') { + setData(result.recent_submissions || []); + } else { + console.error('Error: Invalid response', result); + } + } catch (error) { + console.error('Error fetching recent submissions:', error); + } finally { + setLoading(false); + } + }; + fetchDashboardData(); + }, []); -const submissions = [ - { - establishment: 'CASCADE MARINE FOODS LLC', - emirate: 'Sharjah', - productCount: '5', - year: '2025', - quarter: 'Q4', - lastSubmission: '10/12/2024', - deadline: '20/12/2024', - }, - { - establishment: 'Khazan meat factory', - emirate: 'Sharjah', - productCount: '8', - year: '2025', - quarter: 'Q3', - lastSubmission: '15/11/2024', - deadline: '15/12/2024', - }, - { - establishment: 'SPINNEYS FRESH FOOD INDUSTRIES L.L.C', - emirate: 'Dubai', - productCount: '6', - year: '2025', - quarter: 'Q2', - lastSubmission: '12/12/2024', - deadline: '10/12/2024', - }, - { - establishment: 'FRESHLY FROZEN FOODS FACTORY L.L.C', - emirate: 'Dubai', - productCount: '8', - year: '2025', - quarter: 'Q1', - lastSubmission: '08/12/2024', - deadline: '18/12/2024', - }, - { - establishment: 'SAHAR FOOD INDUSTRY (L.L.C)', - emirate: 'Dubai', - productCount: '8', - year: '2025', - quarter: 'Q4', - lastSubmission: '08/12/2024', - deadline: '18/12/2024', - }, - { - establishment: 'CONTINENTAL FOOD PROCESSING LLC', - emirate: 'Ajman', - productCount: '8', - year: '2025', - quarter: 'Q3', - lastSubmission: '08/12/2024', - deadline: '18/12/2024', - }, - { - establishment: 'AL KHAZNA POULTRY FARM', - emirate: 'Abu Dhabi', - productCount: '8', - year: '2025', - quarter: 'Q2', - lastSubmission: '08/12/2024', - deadline: '18/12/2024', - }, - { - establishment: 'DIAMOND MEAT PROCESSING L.L.C', - emirate: 'Abu Dhabi', - productCount: '8', - year: '2025', - quarter: 'Q2', - lastSubmission: '08/12/2024', - deadline: '18/12/2024', - }, - { - establishment: 'ALLIANCE FOODS CO L.L.C', - emirate: 'Abu Dhabi', - productCount: '8', - year: '2025', - quarter: 'Q2', - lastSubmission: '08/12/2024', - deadline: '18/12/2024', - }, - { - establishment: 'KRUSTASIA FOODS L.L.C', - emirate: 'Dubai', - productCount: '4', - year: '2025', - quarter: 'Q1', - lastSubmission: '14/12/2024', - deadline: '21/12/2024', - }, -]; - -const SubmissionTable = () => { - const [search, setSearch] = useState(''); - const [selectedYear, setSelectedYear] = useState('2025'); - const [selectedQuarter, setSelectedQuarter] = useState('Q4'); - const [loading, setLoading] = useState(false); - - // Filter submissions by selected year and quarter - const filteredByQuarterYear = useMemo(() => { - return submissions.filter( - (item) => item.year === selectedYear && item.quarter === selectedQuarter - ); - }, [selectedYear, selectedQuarter]); - - // Apply search filter to the filteredByQuarterYear results const filtered = useMemo(() => { - if (!search.trim()) return filteredByQuarterYear; - const normalized = search.trim().toLowerCase(); - return filteredByQuarterYear.filter((item) => - Object.values(item).join(' ').toLowerCase().includes(normalized) - ); - }, [search, filteredByQuarterYear]); + let list = [...data]; + if (selectedQuarter !== 'None') { + list = list.filter((item) => item.quarter === selectedQuarter); + } + if (selectedYear !== 'None') { + list = list.filter((item) => String(item.year) === String(selectedYear)); + } + return list; + }, [data, selectedQuarter, selectedYear]); + + const titleText = useMemo(() => { + const count = filtered.length; + if (selectedQuarter !== 'None' && selectedYear !== 'None') { + return `Recent 10 Submissions for Selected Quarter ${selectedQuarter} ${selectedYear} (${count})`; + } else if (selectedQuarter !== 'None') { + return `Recent 10 Submissions for Selected Quarter ${selectedQuarter} (${count})`; + } else if (selectedYear !== 'None') { + return `Recent 10 Submissions for Selected Year ${selectedYear} (${count})`; + } else { + return `Recent 10 Submissions (${count})`; + } + }, [selectedQuarter, selectedYear, filtered]); + + const formatDate = (dateStr) => { + if (!dateStr) return '-'; + const date = new Date(dateStr); + const formatted = date.toLocaleString('en-GB', { + day: '2-digit', + month: '2-digit', + year: 'numeric', + hour: '2-digit', + minute: '2-digit', + hour12: true, + }); + return formatted.replace(/\s?(am|pm)$/i, (match) => match.toUpperCase()); + }; const headers = [ 'Establishment', @@ -139,25 +82,25 @@ const SubmissionTable = () => { const normalized = status?.toLowerCase(); if (normalized === 'approved') { return ( - + Approved ); } else if (normalized === 'rejected') { return ( - + Rejected ); } else if (normalized === 'pending') { return ( - + Pending ); } else { return ( - + {status || '-'} ); @@ -165,69 +108,53 @@ const SubmissionTable = () => { }; const tableRows = filtered.map((item) => [ - item.establishment, - item.emirate, - item.year, - item.quarter, - item.productCount, - item.submittedBy, - item.submissionDateTime, - renderStatusBadge(item.status), - item.reviewer, - item.reviewedOn, -
- Approve - Reject - View -
, + item?.establishment?.factory_name || '-', + item?.establishment?.establishment_emirate?.name || '-', + item?.year || '-', + item?.quarter || '-', + item?.product_count || '-', + item?.created_by || '-', + {formatDate(item?.created_at)}, + renderStatusBadge(item?.status), + item?.updated_by || '-', + {formatDate(item?.updated_at)}, +
+ + + +
, ]); const columnWidths = [240, 120, 100, 100, 130, 150, 180, 150, 150, 180, 120]; - const titleText = useMemo(() => { - const count = filtered.length; - if (selectedQuarter !== 'None' && selectedYear !== 'None') { - return `Recent 10 Submissions for Selected Quarter ${selectedQuarter} ${selectedYear} (${count})`; - } else if (selectedQuarter !== 'None') { - return `Recent 10 Submissions for Selected Quarter ${selectedQuarter} (${count})`; - } else if (selectedYear !== 'None') { - return `Recent 10 Submissions for Selected Year ${selectedYear} (${count})`; - } else { - return `Recent 10 Submissions (${count})`; - } - }, [selectedQuarter, selectedYear, filtered]); - - const toolbar = ( -
-
-

- {titleText} -

-
- Search - setSearch(event.target.value)} - placeholder="Search Establishment or Status" - className="h-10 w-full rounded-md border border-[#C3C6CB] pl-9 pr-3 text-sm focus:outline-none focus:ring-1 focus:ring-[#92722A]" - /> -
-
-
- ); - return (
- {toolbar} +
+

+ {titleText} +

+
+ {loading ? (
Loading submissions... @@ -245,10 +172,10 @@ const SubmissionTable = () => { )}
-
+
@@ -257,4 +184,4 @@ const SubmissionTable = () => { ); }; -export default SubmissionTable \ No newline at end of file +export default SubmissionTable; \ No newline at end of file diff --git a/ipi-survey-platform/src/pages/Admin/AdminDashboard.jsx b/ipi-survey-platform/src/pages/Admin/AdminDashboard.jsx index 18a1339..3e8c6df 100644 --- a/ipi-survey-platform/src/pages/Admin/AdminDashboard.jsx +++ b/ipi-survey-platform/src/pages/Admin/AdminDashboard.jsx @@ -98,36 +98,42 @@ const AdminDashboard = () => { value={loading ? '--' : summary.total_establishments} width={290} icon={Total Establishments} + tooltipText="Total establishments enrolled in the survey for selected quarter." /> } + tooltipText="Establishments that have submitted all products for this quarter." /> } + tooltipText="Submissions fully validated and approved." /> } + tooltipText="Submissions rejected and pending resubmission." /> } + tooltipText="Establishments past submission deadline." /> } + tooltipText="Establishments not yet submitted." />