86 lines
2.5 KiB
TypeScript
86 lines
2.5 KiB
TypeScript
import { redirect } from '@sveltejs/kit';
|
|
import type { PageServerLoad } from './$types';
|
|
import type { OrgLayoutData } from '$lib/types/layout';
|
|
import { createLogger } from '$lib/utils/logger';
|
|
import { getServiceAccountEmail } from '$lib/api/google-calendar-push';
|
|
import { env } from '$env/dynamic/private';
|
|
|
|
const log = createLogger('page.settings');
|
|
|
|
export const load: PageServerLoad = async ({ parent, locals }) => {
|
|
const { org, userRole } = await parent() as OrgLayoutData;
|
|
|
|
// Only admins and owners can access settings
|
|
if (userRole !== 'owner' && userRole !== 'admin') {
|
|
redirect(303, `/${org.slug}`);
|
|
}
|
|
|
|
const orgId = org.id;
|
|
|
|
// Fetch all settings data in parallel
|
|
const [membersResult, rolesResult, invitesResult, calendarResult] = await Promise.all([
|
|
// Get org members (without embedded profile join — FK points to auth.users, not profiles)
|
|
locals.supabase
|
|
.from('org_members')
|
|
.select('id, user_id, role, role_id, invited_at')
|
|
.eq('org_id', orgId),
|
|
// Get org roles
|
|
locals.supabase
|
|
.from('org_roles')
|
|
.select('*')
|
|
.eq('org_id', orgId)
|
|
.order('position'),
|
|
// Get pending invites
|
|
locals.supabase
|
|
.from('org_invites')
|
|
.select('*')
|
|
.eq('org_id', orgId)
|
|
.is('accepted_at', null)
|
|
.gt('expires_at', new Date().toISOString()),
|
|
// Get org Google Calendar connection
|
|
locals.supabase
|
|
.from('org_google_calendars')
|
|
.select('*')
|
|
.eq('org_id', orgId)
|
|
.single()
|
|
]);
|
|
|
|
if (membersResult.error) {
|
|
log.error('Failed to fetch members', { error: membersResult.error, data: { orgId } });
|
|
}
|
|
|
|
// Fetch profiles separately since org_members.user_id FK points to auth.users, not profiles
|
|
const rawMembers = membersResult.data ?? [];
|
|
const userIds = rawMembers.map(m => m.user_id).filter((id): id is string => id !== null);
|
|
let profilesMap: Record<string, { id: string; email: string; full_name: string | null; avatar_url: string | null }> = {};
|
|
|
|
if (userIds.length > 0) {
|
|
const { data: profiles } = await locals.supabase
|
|
.from('profiles')
|
|
.select('id, email, full_name, avatar_url')
|
|
.in('id', userIds);
|
|
|
|
if (profiles) {
|
|
profilesMap = Object.fromEntries(profiles.map(p => [p.id, p]));
|
|
}
|
|
}
|
|
|
|
const members = rawMembers.map(m => ({
|
|
...m,
|
|
profiles: (m.user_id ? profilesMap[m.user_id] : null) ?? null
|
|
}));
|
|
|
|
const serviceAccountEmail = env.GOOGLE_SERVICE_ACCOUNT_KEY
|
|
? getServiceAccountEmail(env.GOOGLE_SERVICE_ACCOUNT_KEY)
|
|
: null;
|
|
|
|
return {
|
|
members,
|
|
roles: rolesResult.data ?? [],
|
|
invites: invitesResult.data ?? [],
|
|
orgCalendar: calendarResult.data,
|
|
serviceAccountEmail,
|
|
userRole
|
|
};
|
|
};
|