diff --git a/apps/frontend/src/app/accounts/page.tsx b/apps/frontend/src/app/accounts/page.tsx
index 5bd1f7a5..06fd6119 100644
--- a/apps/frontend/src/app/accounts/page.tsx
+++ b/apps/frontend/src/app/accounts/page.tsx
@@ -1,14 +1,16 @@
-'use client';
+"use client";
import React, { useState } from 'react';
+import { useUsers } from '@/hooks/useUsers';
import StaffCard from '../components/StaffCard';
import AddUserModal from '../components/AddUserModal';
import { Button } from '@chakra-ui/react';
-import { facilitationTeam, teamMembers } from './mockUsers';
export default function AccountsPage() {
+ const { users, loading, error } = useUsers();
+ const shownFacilitation = users.filter(u => u.is_admin);
+ const shownTeam = users.filter(u => !u.is_admin);
const [isModalOpen, setIsModalOpen] = useState(false);
-
return (
@@ -23,13 +25,15 @@ export default function AccountsPage() {
Core BRANCH Facilitation Team
- {facilitationTeam.map(user => (
+ {loading &&
Loading users...
}
+ {error &&
{error}
}
+ {!loading && !error && shownFacilitation.map(user => (
))}
BRANCH Team Members
- {teamMembers.map(user => (
+ {!loading && !error && shownTeam.map(user => (
))}
diff --git a/apps/frontend/src/app/donations/page.tsx b/apps/frontend/src/app/donations/page.tsx
index 31014556..30137830 100644
--- a/apps/frontend/src/app/donations/page.tsx
+++ b/apps/frontend/src/app/donations/page.tsx
@@ -1,44 +1,34 @@
'use client'
-import React, { useState } from 'react';
+import React, { useEffect, useState } from 'react';
import NavBar from "../components/Navbar";
import { HStack, Input, Button, Dialog, Portal, CloseButton, Stack } from "@chakra-ui/react";
import TextInputField from '../components/TextInputField';
import { CiFilter } from "react-icons/ci";
import { LuArrowDownUp } from "react-icons/lu";
-import { FaPlus } from "react-icons/fa";
+import { FaPlus, FaAngleLeft, FaAngleRight } from "react-icons/fa";
import DropdownSelector from '../components/DropdownSelector';
import DataTable, { type DataTableColumn } from '../components/DataTable';
-import Pagination from '../components/Pagination';
type Donation = {
donor_id: number;
- date: string | null;
+ donated_at: string | null;
+ project_id: number;
project_name: string;
- amount: number;
+ amount: number | string;
};
+import { useApi } from '@/hooks/useApi';
+
+type ApiDonation = Omit
;
+type ApiDonor = { donor_id: number; organization: string };
+type ApiProject = { project_id: number; name: string };
-const mockDonors = ['Green Future Foundation', 'Horizon Trust', 'Bright Path Nonprofit', 'Unity Giving Circle', 'Sunrise Community Fund'];
-const mockProjects = ['Clean Water Initiative', 'Youth Mentorship Program', 'Food Security Drive', 'Urban Garden Project', 'STEM Education Fund'];
-
-const mockDonations: Donation[] = [
- { donor_id: 1, date: '03/12/2024', project_name: 'Clean Water Initiative', amount: 5000 },
- { donor_id: 2, date: '01/05/2024', project_name: 'Youth Mentorship Program', amount: 12000 },
- { donor_id: 3, date: '02/28/2024', project_name: 'Food Security Drive', amount: 750 },
- { donor_id: 4, date: '03/30/2024', project_name: 'Urban Garden Project', amount: 3200 },
- { donor_id: 5, date: '04/01/2024', project_name: 'STEM Education Fund', amount: 8500 },
- { donor_id: 6, date: '02/14/2024', project_name: 'Shelter Renovation', amount: 1500 },
- { donor_id: 7, date: '01/20/2024', project_name: 'Mental Health Outreach', amount: 20000 },
- { donor_id: 8, date: '03/05/2024', project_name: 'Digital Literacy Program', amount: 9750 },
- { donor_id: 9, date: '04/10/2024', project_name: 'Community Health Fair', amount: 4300 },
- { donor_id: 10, date: '03/22/2024', project_name: 'After-School Arts', amount: 600 },
-];
const donationColumns: DataTableColumn[] = [
{
- key: 'date',
+ key: 'donated_at',
header: 'Date',
width: '15%',
- cell: (donation) => donation.date ?? '—',
+ cell: (donation) => donation.donated_at ?? '—',
skeleton: { width: '70%' },
},
{
@@ -53,7 +43,7 @@ const donationColumns: DataTableColumn[] = [
key: 'amount',
header: 'Amount',
width: '15%',
- cell: (donation) => `$${donation.amount.toLocaleString()}`,
+ cell: (donation) => `$${Number(donation.amount).toLocaleString()}`,
skeleton: { width: '55%' },
},
];
@@ -62,12 +52,59 @@ export default function DonationsPage() {
const [currentPage, setCurrentPage] = useState(1);
const rowsPerPage = 10;
- const totalPages = Math.ceil(mockDonations.length / rowsPerPage);
- const currentDonations = mockDonations.slice(
+ const api = useApi();
+ const [donations, setDonations] = useState([]);
+ const [donorNames, setDonorNames] = useState([]);
+ const [projectNames, setProjectNames] = useState([]);
+ const [loading, setLoading] = useState(true);
+ const [error, setError] = useState(null);
+
+ useEffect(() => {
+ async function loadAll() {
+ try {
+ const [donationsJson, donorsJson, projectsJson] = await Promise.all([
+ api.get('/donors/donations'),
+ api.get('/donors'),
+ api.get('/projects'),
+ ]);
+
+ const donations = Array.isArray(donationsJson) ? donationsJson : donationsJson.data;
+ const donors = Array.isArray(donorsJson) ? donorsJson : donorsJson.data;
+ const projects = projectsJson;
+ const projectNamesById = new Map(projects.map((project) => [project.project_id, project.name]));
+
+ setDonations(donations.map((donation) => ({
+ ...donation,
+ project_name: projectNamesById.get(donation.project_id) ?? `Project #${donation.project_id}`,
+ })));
+ setDonorNames(donors.map((donor) => donor.organization));
+ setProjectNames(projects.map((project) => project.name));
+ } catch (err) {
+ setError(err instanceof Error ? err.message : 'Failed to load donations data');
+ setDonations([]);
+ setDonorNames([]);
+ setProjectNames([]);
+ } finally {
+ setLoading(false);
+ }
+ }
+ loadAll();
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, []);
+
+ const totalPages = Math.max(1, Math.ceil(donations.length / rowsPerPage));
+ const currentDonations = donations.slice(
(currentPage - 1) * rowsPerPage,
currentPage * rowsPerPage
);
+ const getPageNumbers = (): Array => {
+ if (totalPages <= 5) return Array.from({ length: totalPages }, (_, index) => index + 1);
+ if (currentPage <= 3) return [1, 2, 3, '...', totalPages];
+ if (currentPage >= totalPages - 2) return [1, '...', totalPages - 2, totalPages - 1, totalPages];
+ return [1, '...', currentPage - 1, currentPage, currentPage + 1, '...', totalPages];
+ };
+
const [showFilter, setShowFilter] = useState(false);
const [selectedDonor, setSelectedDonor] = useState('');
const [showSort, setShowSort] = useState(false);
@@ -124,7 +161,7 @@ export default function DonationsPage() {
{showFilter && (
{showSort && (
- setSelectedSort(val as string)}
- />
+ setSelectedSort(val as string)}
+ />
)}
@@ -194,7 +231,7 @@ export default function DonationsPage() {
{dateError && Enter a valid date}