-
-
- {bylaws.title}
-
-
- Version {bylaws.version}
- •
- Effective {formatDate(bylaws.effective_date)}
-
-
-
+ {showHistory && filteredHistory.filter(b => !b.is_current).length > 0 && (
+
+ {sortedYears.map(year => (
+
+
+
+ {year}
+
+
+ {groupedHistory[year].map(bylaws => (
+
+
+
+
+ {bylaws.title}
+
+
+ Version {bylaws.version}
+ •
+ Effective {formatDate(bylaws.effective_date)}
+
+
+
+
+
+ ))}
-
+
))}
)}
diff --git a/src/pages/members/Financials.js b/src/pages/members/Financials.js
index d4989d9..5953851 100644
--- a/src/pages/members/Financials.js
+++ b/src/pages/members/Financials.js
@@ -5,20 +5,36 @@ import MemberFooter from '../../components/MemberFooter';
import { Card } from '../../components/ui/card';
import { Button } from '../../components/ui/button';
import { Badge } from '../../components/ui/badge';
+import { Input } from '../../components/ui/input';
import { toast } from 'sonner';
-import { DollarSign, ExternalLink, TrendingUp } from 'lucide-react';
+import { DollarSign, ExternalLink, TrendingUp, Search, Calendar } from 'lucide-react';
export default function Financials() {
const [reports, setReports] = useState([]);
+ const [years, setYears] = useState([]);
+ const [selectedYear, setSelectedYear] = useState(null);
+ const [searchTerm, setSearchTerm] = useState('');
const [loading, setLoading] = useState(true);
useEffect(() => {
+ fetchYears();
fetchReports();
}, []);
- const fetchReports = async () => {
+ const fetchYears = async () => {
try {
- const response = await api.get('/financials');
+ const response = await api.get('/financials/years');
+ setYears(response.data);
+ } catch (error) {
+ console.error('Failed to load years');
+ }
+ };
+
+ const fetchReports = async (year = null) => {
+ try {
+ setLoading(true);
+ const url = year ? `/financials?year=${year}` : '/financials';
+ const response = await api.get(url);
setReports(response.data);
} catch (error) {
toast.error('Failed to load financial reports');
@@ -27,6 +43,36 @@ export default function Financials() {
}
};
+ const handleYearFilter = (year) => {
+ setSelectedYear(year);
+ fetchReports(year);
+ };
+
+ const clearFilter = () => {
+ setSelectedYear(null);
+ fetchReports();
+ };
+
+ const filteredReports = reports.filter(report =>
+ report.title.toLowerCase().includes(searchTerm.toLowerCase()) ||
+ report.year.toString().includes(searchTerm)
+ );
+
+ const groupByYear = (items) => {
+ const grouped = {};
+ items.forEach(item => {
+ const year = item.year;
+ if (!grouped[year]) {
+ grouped[year] = [];
+ }
+ grouped[year].push(item);
+ });
+ return grouped;
+ };
+
+ const groupedReports = groupByYear(filteredReports);
+ const sortedYears = Object.keys(groupedReports).sort((a, b) => b - a);
+
if (loading) {
return (
@@ -53,56 +99,104 @@ export default function Financials() {
Access annual financial reports and stay informed about LOAF's fiscal responsibility.
+
+ {/* Filters */}
+
+ {/* Search */}
+
+
+ setSearchTerm(e.target.value)}
+ className="pl-10 border-[var(--neutral-800)] focus:border-brand-purple "
+ />
+
+
+ {/* Year Filter */}
+
+
+ {years.map(year => (
+
+ ))}
+
+
{/* Reports List */}
- {reports.length === 0 ? (
+ {filteredReports.length === 0 ? (
- No financial reports available yet
+ No financial reports found
) : (
-
- {reports.map(report => (
-
-
- {/* Year Badge */}
-
-
-
- {report.year}
-
-
Fiscal Year
-
+
+ {sortedYears.map(year => (
+
+
+
+ {year}
+
+
+ {groupedReports[year].map(report => (
+
+
+ {/* Year Badge */}
+
+
+
+ {report.year}
+
+
Fiscal Year
+
- {/* Report Details */}
-
-
- {report.title}
-
-
-
- {report.document_type === 'google_drive' ? 'Google Drive' : report.document_type.toUpperCase()}
-
-
-
-
+ {/* Report Details */}
+
+
+ {report.title}
+
+
+
+ {report.document_type === 'google_drive' ? 'Google Drive' : report.document_type.toUpperCase()}
+
+
+
+
+
+
+ ))}
-
+
))}
)}
{/* Transparency Note */}
- {reports.length > 0 && (
+ {filteredReports.length > 0 && (