Files
familienarchiv/frontend/src/routes/aktivitaeten/+page.server.ts
Marcel 567612761d refactor: move lib-root files to lib/shared/ and finalize domain structure
- Move api.server.ts, errors.ts, types.ts, utils.ts, relativeTime.ts to lib/shared/
- Move person relationship components to lib/person/relationship/
- Move Stammbaum components to lib/person/genealogy/
- Move HelpPopover to lib/shared/primitives/
- Update all import paths across routes, specs, and lib files
- Update vi.mock() paths in server-project test files
- Remove now-empty legacy directories (components/, hooks/, server/, etc.)
- Update vite.config.ts coverage include paths for new structure
- Update frontend/CLAUDE.md to reflect domain-based lib/ layout

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-05 14:53:31 +02:00

68 lines
2.2 KiB
TypeScript

import { createApiClient } from '$lib/shared/api.server';
import type { components, operations } from '$lib/generated/api';
type ActivityFeedItemDTO = components['schemas']['ActivityFeedItemDTO'];
type NotificationDTO = components['schemas']['NotificationDTO'];
type AuditKind = NonNullable<operations['getActivity']['parameters']['query']>['kinds'] extends
| (infer K)[]
| undefined
? K
: never;
export type FilterValue = 'alle' | 'fuer-dich' | 'hochgeladen' | 'transkription' | 'kommentare';
const VALID_FILTERS: FilterValue[] = [
'alle',
'fuer-dich',
'hochgeladen',
'transkription',
'kommentare'
];
// fuer-dich stays client-side: youMentioned || youParticipated cannot be expressed as a kinds filter
const KINDS_FOR_FILTER: Partial<Record<FilterValue, AuditKind[]>> = {
hochgeladen: ['FILE_UPLOADED'],
transkription: ['TEXT_SAVED', 'BLOCK_REVIEWED', 'ANNOTATION_CREATED'],
kommentare: ['COMMENT_ADDED', 'MENTION_CREATED']
};
function parseFilter(raw: string | null): FilterValue {
if (raw && (VALID_FILTERS as string[]).includes(raw)) return raw as FilterValue;
return 'alle';
}
export async function load({ fetch, url }) {
const api = createApiClient(fetch);
const filter = parseFilter(url.searchParams.get('filter'));
const limit = Math.min(Number(url.searchParams.get('limit')) || 40, 40);
const kinds = KINDS_FOR_FILTER[filter];
const [activityResult, unreadResult] = await Promise.allSettled([
api.GET('/api/dashboard/activity', { params: { query: { limit, ...(kinds && { kinds }) } } }),
api.GET('/api/notifications', {
params: { query: { read: false, page: 0, size: 20 } }
})
]);
let activityFeed: ActivityFeedItemDTO[] = [];
let unreadNotifications: NotificationDTO[] = [];
let loadError: string | null = null;
if (activityResult.status === 'fulfilled' && activityResult.value.response.ok) {
activityFeed = (activityResult.value.data as ActivityFeedItemDTO[]) ?? [];
} else if (activityResult.status === 'fulfilled') {
loadError = 'activity';
}
if (unreadResult.status === 'fulfilled' && unreadResult.value.response.ok) {
unreadNotifications = unreadResult.value.data?.content ?? [];
}
return {
filter,
activityFeed,
unreadNotifications,
loadError
};
}