monacousa-portal/src/routes/(app)/board/members/+page.server.ts

82 lines
2.7 KiB
TypeScript

import type { PageServerLoad } from './$types';
export const load: PageServerLoad = async ({ locals, url }) => {
const searchQuery = url.searchParams.get('search') || '';
const statusFilter = url.searchParams.get('status') || 'all';
const roleFilter = url.searchParams.get('role') || 'all';
// Get current member's role for privacy filtering
const { member } = await locals.safeGetSession();
const isPrivileged = member?.role === 'admin' || member?.role === 'board';
// Build the query - select only needed columns to avoid exposing sensitive fields
let query = locals.supabase
.from('members_with_dues')
.select('id, member_id, first_name, last_name, email, phone, role, status_name, type_name, avatar_url, created_at, nationality, address, directory_privacy')
.order('last_name', { ascending: true });
// Apply filters
if (statusFilter !== 'all') {
query = query.eq('status_name', statusFilter);
}
if (roleFilter !== 'all') {
query = query.eq('role', roleFilter);
}
const { data: members } = await query;
// Filter by search query in application (for name/email search)
let filteredMembers = members || [];
if (searchQuery) {
const lowerSearch = searchQuery.toLowerCase();
filteredMembers = filteredMembers.filter(
(m: any) =>
m.first_name?.toLowerCase().includes(lowerSearch) ||
m.last_name?.toLowerCase().includes(lowerSearch) ||
m.email?.toLowerCase().includes(lowerSearch) ||
m.member_id?.toLowerCase().includes(lowerSearch)
);
}
// Get membership statuses for filter dropdown
const { data: statuses } = await locals.supabase
.from('membership_statuses')
.select('*')
.order('sort_order', { ascending: true });
// Calculate stats
const stats = {
total: members?.length || 0,
active: members?.filter((m: any) => m.status_name === 'active').length || 0,
pending: members?.filter((m: any) => m.status_name === 'pending').length || 0,
inactive: members?.filter((m: any) => m.status_name === 'inactive').length || 0
};
// Apply directory privacy settings (admins/board see everything)
const privacyFilteredMembers = isPrivileged
? filteredMembers
: filteredMembers.map((m: any) => {
const privacy = m.directory_privacy || { show_email: true, show_phone: true, show_address: false, show_nationality: true };
return {
...m,
email: privacy.show_email ? m.email : null,
phone: privacy.show_phone ? m.phone : null,
address: privacy.show_address ? m.address : null,
nationality: privacy.show_nationality ? m.nationality : null,
directory_privacy: undefined
};
});
return {
members: privacyFilteredMembers,
statuses: statuses || [],
stats,
filters: {
search: searchQuery,
status: statusFilter,
role: roleFilter
}
};
};