CarboAny / src /lib /notificationStore.ts
Esketch's picture
deploy: [P4] Strangler Pattern API Adapter Release (Orphan Clean Build v2)
daaf9d7
Raw
History Blame Contribute Delete
2.68 kB
// Notification store (Supabase-backed)
import { supabase } from './supabase';
export type NotificationType = 'approval_result' | 'new_request' | 'status_change' | 'system';
export interface Notification {
id: string;
userId: string;
type: NotificationType;
title: string;
body: string;
linkTo?: string;
relatedApprovalId?: string;
read: boolean;
createdAt: string;
}
// --- Mapping helpers ---
function dbToNotif(row: Record<string, unknown>): Notification {
return {
id: row.id as string,
userId: row.user_id as string,
type: row.type as NotificationType,
title: row.title as string,
body: row.body as string,
linkTo: (row.link_to as string) ?? undefined,
relatedApprovalId: (row.related_approval_id as string) ?? undefined,
read: row.read as boolean,
createdAt: row.created_at as string,
};
}
// --- CRUD ---
export async function getNotifications(userId: string): Promise<Notification[]> {
const { data, error } = await supabase
.from('notifications')
.select('*')
.eq('user_id', userId)
.order('created_at', { ascending: false })
.limit(50);
if (error) {
console.error('getNotifications error:', error);
return [];
}
return (data ?? []).map(dbToNotif);
}
export async function getUnreadCount(userId: string): Promise<number> {
const { count, error } = await supabase
.from('notifications')
.select('*', { count: 'exact', head: true })
.eq('user_id', userId)
.eq('read', false);
if (error) {
console.error('getUnreadCount error:', error);
return 0;
}
return count ?? 0;
}
export async function createNotification(
n: Omit<Notification, 'id' | 'createdAt' | 'read'>,
): Promise<Notification | null> {
const row = {
user_id: n.userId,
type: n.type,
title: n.title,
body: n.body,
link_to: n.linkTo ?? null,
related_approval_id: n.relatedApprovalId ?? null,
read: false,
};
const { data, error } = await supabase
.from('notifications')
.insert(row)
.select()
.single();
if (error) {
console.error('createNotification error:', error);
return null;
}
return dbToNotif(data);
}
export async function markAsRead(id: string): Promise<void> {
const { error } = await supabase
.from('notifications')
.update({ read: true })
.eq('id', id);
if (error) console.error('markAsRead error:', error);
}
export async function markAllAsRead(userId: string): Promise<void> {
const { error } = await supabase
.from('notifications')
.update({ read: true })
.eq('user_id', userId)
.eq('read', false);
if (error) console.error('markAllAsRead error:', error);
}