128 lines
3.8 KiB
TypeScript
128 lines
3.8 KiB
TypeScript
import {
|
|
useQuery,
|
|
useMutation,
|
|
useQueryClient,
|
|
type UseQueryResult,
|
|
type UseMutationResult,
|
|
} from '@tanstack/react-query';
|
|
import { apiClient } from '@/lib/api';
|
|
import type {
|
|
ReminderStatus,
|
|
ReminderTargetType,
|
|
ReminderTriggerType,
|
|
NotificationChannel,
|
|
} from '@life-platform/shared';
|
|
|
|
export interface Reminder {
|
|
id: string;
|
|
targetType: ReminderTargetType;
|
|
targetId: string | null;
|
|
title: string;
|
|
message: string | null;
|
|
triggerType: ReminderTriggerType;
|
|
triggerConfig: Record<string, unknown>;
|
|
channels: NotificationChannel[];
|
|
status: ReminderStatus;
|
|
firedAt: string | null;
|
|
nextFireAt: string | null;
|
|
createdAt: string;
|
|
updatedAt: string;
|
|
deletedAt: string | null;
|
|
}
|
|
|
|
export interface PaginatedReminders {
|
|
data: Reminder[];
|
|
total: number;
|
|
page: number;
|
|
limit: number;
|
|
}
|
|
|
|
export interface ReminderListParams {
|
|
status?: ReminderStatus;
|
|
targetType?: ReminderTargetType;
|
|
targetId?: string;
|
|
page?: number;
|
|
limit?: number;
|
|
}
|
|
|
|
export interface CreateReminderInput {
|
|
targetType: ReminderTargetType;
|
|
targetId?: string;
|
|
title: string;
|
|
message?: string;
|
|
triggerType: ReminderTriggerType;
|
|
triggerConfig: Record<string, unknown>;
|
|
channels: NotificationChannel[];
|
|
}
|
|
|
|
export type UpdateReminderInput = Partial<CreateReminderInput>;
|
|
|
|
const KEYS = {
|
|
all: ['notifications'] as const,
|
|
list: (params?: ReminderListParams): readonly ['notifications', 'list', ReminderListParams | undefined] =>
|
|
[...KEYS.all, 'list', params] as const,
|
|
upcoming: (minutes?: number): readonly ['notifications', 'upcoming', number | undefined] =>
|
|
[...KEYS.all, 'upcoming', minutes] as const,
|
|
detail: (id: string): readonly ['notifications', 'detail', string] =>
|
|
[...KEYS.all, 'detail', id] as const,
|
|
};
|
|
|
|
export function useReminders(params?: ReminderListParams): UseQueryResult<PaginatedReminders> {
|
|
return useQuery({
|
|
queryKey: KEYS.list(params),
|
|
queryFn: (): Promise<PaginatedReminders> =>
|
|
apiClient.get<PaginatedReminders>('/notifications', { params }).then((r) => r.data),
|
|
});
|
|
}
|
|
|
|
export function useUpcomingReminders(minutes?: number): UseQueryResult<Reminder[]> {
|
|
return useQuery({
|
|
queryKey: KEYS.upcoming(minutes),
|
|
queryFn: (): Promise<Reminder[]> =>
|
|
apiClient
|
|
.get<Reminder[]>('/notifications/upcoming', { params: minutes ? { minutes } : undefined })
|
|
.then((r) => r.data),
|
|
refetchInterval: 60_000,
|
|
});
|
|
}
|
|
|
|
export function useReminder(id: string): UseQueryResult<Reminder> {
|
|
return useQuery({
|
|
queryKey: KEYS.detail(id),
|
|
queryFn: (): Promise<Reminder> =>
|
|
apiClient.get<Reminder>(`/notifications/${id}`).then((r) => r.data),
|
|
enabled: !!id,
|
|
});
|
|
}
|
|
|
|
export function useCreateReminder(): UseMutationResult<Reminder, Error, CreateReminderInput> {
|
|
const qc = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: (data: CreateReminderInput): Promise<Reminder> =>
|
|
apiClient.post<Reminder>('/notifications', data).then((r) => r.data),
|
|
onSuccess: (): void => {
|
|
qc.invalidateQueries({ queryKey: KEYS.all });
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useUpdateReminder(): UseMutationResult<Reminder, Error, { id: string; data: UpdateReminderInput }> {
|
|
const qc = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: ({ id, data }: { id: string; data: UpdateReminderInput }): Promise<Reminder> =>
|
|
apiClient.patch<Reminder>(`/notifications/${id}`, data).then((r) => r.data),
|
|
onSuccess: (): void => {
|
|
qc.invalidateQueries({ queryKey: KEYS.all });
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useDismissReminder(): UseMutationResult<void, Error, string> {
|
|
const qc = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: (id: string): Promise<void> => apiClient.delete(`/notifications/${id}`).then(() => undefined),
|
|
onSuccess: (): void => {
|
|
qc.invalidateQueries({ queryKey: KEYS.all });
|
|
},
|
|
});
|
|
}
|