diff --git a/ipi-survey-platform/src/pages/Admin/Validations.jsx b/ipi-survey-platform/src/pages/Admin/Validations.jsx index dadbfb6..4f4987d 100644 --- a/ipi-survey-platform/src/pages/Admin/Validations.jsx +++ b/ipi-survey-platform/src/pages/Admin/Validations.jsx @@ -4,180 +4,9 @@ import AdminHeader from '../../components/admin/AdminHeader'; import Table from '../../components/common/Table'; import SearchIcon from '../../assets/images/material-symbols_search-rounded.svg'; import DownloadIcon from '../../assets/images/DownloadSimple.svg'; -import ActionIcon from '../../assets/images/qlementine-icons_preview-16.svg'; import CaretUp from '../../assets/images/caret-up.svg'; -import { TextField, SelectField } from '../../components/common/FormControls'; - -const submissions = [ - { - id: 1, - establishment: 'CASCADE MARINE FOODS LLC', - emirate: 'Sharjah', - year: '2025', - quarter: 'Q4', - submittedAt: '18/10/2025, 10:40 AM', - products: 10, - submittedBy: 'Ahmed (Owner)', - status: 'Pending', - reviewer: 'Omar', - }, - { - id: 2, - establishment: 'Khazan meat factory', - emirate: 'Sharjah', - year: '2025', - quarter: 'Q3', - submittedAt: '18/10/2025, 10:40 AM', - products: 6, - submittedBy: 'Sara (Admin)', - status: 'Approved', - reviewer: 'Abdul', - }, - { - id: 3, - establishment: 'SPINNEYS FRESH FOOD INDUSTRIES L.L.C', - emirate: 'Dubai', - year: '2025', - quarter: 'Q2', - submittedAt: '18/10/2025, 10:40 AM', - products: 8, - submittedBy: 'Shaik (Admin)', - status: 'Approved', - reviewer: 'Abdul', - }, - { - id: 4, - establishment: 'FRESHLY FROZEN FOODS FACTORY L.L.C', - emirate: 'Dubai', - year: '2025', - quarter: 'Q1', - submittedAt: '18/10/2025, 10:40 AM', - products: 4, - submittedBy: 'Abdul (Manager)', - status: 'Rejected', - reviewer: 'Abdul', - }, - { - id: 5, - establishment: 'SAHAR FOOD INDUSTRY (L.L.C)', - emirate: 'Dubai', - year: '2025', - quarter: 'Q4', - submittedAt: '18/10/2025, 10:40 AM', - products: 8, - submittedBy: 'Ahmed (Owner)', - status: 'Approved', - reviewer: 'Abdul', - }, - { - id: 6, - establishment: 'CONTINENTAL FOOD PROCESSING LLC', - emirate: 'Ajman', - year: '2025', - quarter: 'Q3', - submittedAt: '18/10/2025, 10:40 AM', - products: 5, - submittedBy: 'Sara (Admin)', - status: 'Rejected', - reviewer: 'Abdul', - }, - { - id: 7, - establishment: 'AL KHAZNA POULTRY FARM', - emirate: 'Abu Dhabi', - year: '2025', - quarter: 'Q2', - submittedAt: '18/10/2025, 10:40 AM', - products: 7, - submittedBy: 'Sara (Admin)', - status: 'Approved', - reviewer: 'Abdul', - }, - { - id: 8, - establishment: 'DIAMOND MEAT PROCESSING L.L.C', - emirate: 'Abu Dhabi', - year: '2025', - quarter: 'Q2', - submittedAt: '18/10/2025, 10:40 AM', - products: 7, - submittedBy: 'Ahmed (Owner)', - status: 'Approved', - reviewer: 'Abdul', - }, - { - id: 9, - establishment: 'ALLIANCE FOODS CO L.L.C', - emirate: 'Abu Dhabi', - year: '2025', - quarter: 'Q2', - submittedAt: '18/10/2025, 10:40 AM', - products: 7, - submittedBy: 'Ahmed (Owner)', - status: 'Approved', - reviewer: 'Abdul', - }, - { - id: 10, - establishment: 'KRUSTASIA FOODS L.L.C', - emirate: 'Dubai', - year: '2025', - quarter: 'Q1', - submittedAt: '18/10/2025, 10:40 AM', - products: 8, - submittedBy: 'Sara (Admin)', - status: 'Pending', - reviewer: 'Fathima', - }, - { - id: 11, - establishment: 'AL TAMEER FOOD INDUSTRIES', - emirate: 'Abu Dhabi', - year: '2025', - quarter: 'Q3', - submittedAt: '19/10/2025, 8:15 AM', - products: 11, - submittedBy: 'Ahmed (Owner)', - status: 'Pending', - reviewer: 'Omar', - }, - { - id: 12, - establishment: 'AL RAWABI DAIRY COMPANY', - emirate: 'Dubai', - year: '2024', - quarter: 'Q4', - submittedAt: '12/09/2024, 4:10 PM', - products: 9, - submittedBy: 'Mariam (Admin)', - status: 'Approved', - reviewer: 'Abdul', - }, - { - id: 13, - establishment: 'EMIRATES FRESH POULTRY', - emirate: 'Ajman', - year: '2024', - quarter: 'Q4', - submittedAt: '05/09/2024, 11:05 AM', - products: 6, - submittedBy: 'Haroon (Manager)', - status: 'Rejected', - reviewer: 'Omar', - }, - { - id: 14, - establishment: 'GULF FISHERIES LLC', - emirate: 'Ras Al Khaimah', - year: '2024', - quarter: 'Q3', - submittedAt: '21/08/2024, 9:15 AM', - products: 12, - submittedBy: 'Owais (Owner)', - status: 'Approved', - reviewer: 'Fathima', - }, -]; +import { SelectField } from '../../components/common/FormControls'; +import { getSubmissions } from '../../services/admin/submission.js'; const STATUS_VARIANTS = { Approved: { background: '#F3FAF4', text: '#2F663C', border: '#F3FAF4' }, @@ -206,6 +35,10 @@ const Badge = ({ children, status }) => { const ManageSubmissions = () => { const navigate = useNavigate(); + const [submissions, setSubmissions] = React.useState([]); + const [loading, setLoading] = React.useState(true); + const [error, setError] = React.useState(null); + const [search, setSearch] = React.useState(''); const [year, setYear] = React.useState(''); const [quarter, setQuarter] = React.useState(''); @@ -214,37 +47,68 @@ const ManageSubmissions = () => { const [currentPage, setCurrentPage] = React.useState(1); const pageSize = 10; - const yearOptions = React.useMemo(() => ['All', ...new Set(submissions.map((item) => item.year))], []); - const quarterOptions = React.useMemo(() => ['All', ...new Set(submissions.map((item) => item.quarter))], []); - const emirateOptions = React.useMemo(() => ['All', ...new Set(submissions.map((item) => item.emirate))], []); - const statusOptions = React.useMemo(() => ['All', ...new Set(submissions.map((item) => item.status))], []); + // 🔹 Fetch data from backend + React.useEffect(() => { + const fetchSubmissions = async () => { + try { + const result = await getSubmissions(); + + // Handle success or direct data array + const data = result?.status === 'success' ? result.data : result; + + // Map API fields to table fields + const mapped = (data || []).map((item) => ({ + id: item.id, + establishment: '', // blank + emirate: '', // blank + year: String(item.year ?? ''), + quarter: item.quarter ?? '', + products: '', // blank + submittedBy: item.created_by ?? '', + submittedAt: item.created_at + ? new Date(item.created_at).toLocaleString() + : '', + status: item.status ?? '', + reviewer: '', // blank + })); + + setSubmissions(mapped); + } catch (err) { + console.error('Failed to load submissions', err); + setError('Unable to load submissions. Please try again later.'); + } finally { + setLoading(false); + } + }; + + fetchSubmissions(); + }, []); + + const yearOptions = React.useMemo(() => ['All', ...new Set(submissions.map((i) => i.year))], [submissions]); + const quarterOptions = React.useMemo(() => ['All', ...new Set(submissions.map((i) => i.quarter))], [submissions]); + const emirateOptions = React.useMemo(() => ['All', ...new Set(submissions.map((i) => i.emirate))], [submissions]); + const statusOptions = React.useMemo(() => ['All', ...new Set(submissions.map((i) => i.status))], [submissions]); const filtered = React.useMemo(() => { return submissions.filter((item) => { - const matchesSearch = search - ? item.establishment.toLowerCase().includes(search.toLowerCase()) || - item.submittedBy.toLowerCase().includes(search.toLowerCase()) + const matchSearch = search + ? item.establishment?.toLowerCase().includes(search.toLowerCase()) || + item.submittedBy?.toLowerCase().includes(search.toLowerCase()) : true; - const matchesYear = !year || year === 'All' || item.year === year; - const matchesQuarter = !quarter || quarter === 'All' || item.quarter === quarter; - const matchesEmirate = !emirate || emirate === 'All' || item.emirate === emirate; - const matchesStatus = !status || status === 'All' || item.status === status; - return matchesSearch && matchesYear && matchesQuarter && matchesEmirate && matchesStatus; + const matchYear = !year || year === 'All' || item.year === year; + const matchQuarter = !quarter || quarter === 'All' || item.quarter === quarter; + const matchEmirate = !emirate || emirate === 'All' || item.emirate === emirate; + const matchStatus = !status || status === 'All' || item.status === status; + return matchSearch && matchYear && matchQuarter && matchEmirate && matchStatus; }); - }, [search, year, quarter, emirate, status]); + }, [submissions, search, year, quarter, emirate, status]); - React.useEffect(() => { - setCurrentPage(1); - }, [search, year, quarter, emirate, status]); - - const summaryCounts = React.useMemo(() => { - return { - total: submissions.length, - approved: submissions.filter((item) => item.status === 'Approved').length, - pending: submissions.filter((item) => item.status === 'Pending').length, - rejected: submissions.filter((item) => item.status === 'Rejected').length, - }; - }, []); + const summaryCounts = React.useMemo(() => ({ + total: submissions.length, + approved: submissions.filter((i) => i.status === 'Approved').length, + pending: submissions.filter((i) => i.status === 'Pending').length, + rejected: submissions.filter((i) => i.status === 'Rejected').length, + }), [submissions]); const headers = [ 'Establishment', @@ -259,116 +123,61 @@ const ManageSubmissions = () => { 'Actions', ]; - const tableRows = React.useMemo( - () => - filtered.map((item) => [ - item.establishment, - item.emirate, - item.year, - item.quarter, - item.products, - item.submittedBy, - item.submittedAt, - item.status, - item.reviewer, - item.id, - ]), - [filtered] - ); + const tableRows = filtered.map((item) => [ + item.establishment, + item.emirate, + item.year, + item.quarter, + item.products, + item.submittedBy, + item.submittedAt, + item.status, + item.reviewer, + item.id, + ]); - const columnWidths = React.useMemo( - () => [ - 302, - 105, - 83, - 91, - 100, - 152, - 208, - 120, - 104, - 119, - ], - [] - ); + const columnWidths = [302, 105, 83, 91, 100, 152, 208, 120, 104, 119]; + + if (loading) { + return ( +