62 lines
2.2 KiB
TypeScript
62 lines
2.2 KiB
TypeScript
import { useQuery } from '@tanstack/react-query';
|
|
import {
|
|
checkInZone,
|
|
clearTodayZoneCheckin,
|
|
getTodayZoneCheckin,
|
|
listZoneCheckinHistory,
|
|
} from '@/shared/api/zoneCheckins';
|
|
import { getApiListRows } from '@/shared/business/apiListRows';
|
|
import { useInvalidatingMutation } from '@/shared/business/queryMutations';
|
|
import type { ZoneColor } from '@/shared/types/app';
|
|
|
|
export const ZONE_CHECKIN_QUERY_KEYS = {
|
|
today: ['zoneCheckin', 'today'],
|
|
history: ['zoneCheckin', 'history'],
|
|
} as const;
|
|
|
|
/**
|
|
* Today's Zone check-in for the caller. "Today" is resolved server-side in the
|
|
* campus timezone, so this hook never computes a date. `retry: false` so a
|
|
* caller without `ZONE_CHECKIN` (a non-campus role) silently gets no data
|
|
* instead of retrying a 403 — the nudge is role-gated anyway.
|
|
*/
|
|
export function useTodayZoneCheckIn() {
|
|
const todayQuery = useQuery({
|
|
queryKey: ZONE_CHECKIN_QUERY_KEYS.today,
|
|
queryFn: getTodayZoneCheckin,
|
|
retry: false,
|
|
});
|
|
|
|
const saveMutation = useInvalidatingMutation({
|
|
mutationFn: (zone: ZoneColor) => checkInZone(zone),
|
|
invalidateQueryKey: ZONE_CHECKIN_QUERY_KEYS.today,
|
|
});
|
|
|
|
const clearMutation = useInvalidatingMutation({
|
|
mutationFn: () => clearTodayZoneCheckin(),
|
|
invalidateQueryKey: ZONE_CHECKIN_QUERY_KEYS.today,
|
|
});
|
|
|
|
return {
|
|
todayZone: todayQuery.data?.zone ?? null,
|
|
isCheckedInToday: todayQuery.data?.isCheckedInToday ?? false,
|
|
isLoading: todayQuery.isLoading,
|
|
isSaving: saveMutation.isPending || clearMutation.isPending,
|
|
// Only surface actionable mutation (save/clear) errors. The today-load query
|
|
// can 403 for a non-eligible role or before seeding; that is non-actionable
|
|
// for the user and must not render as a scary "Forbidden" in the widget.
|
|
error: saveMutation.error || clearMutation.error,
|
|
setZone: (zone: ZoneColor) => saveMutation.mutateAsync(zone),
|
|
clearToday: () => clearMutation.mutateAsync(),
|
|
};
|
|
}
|
|
|
|
/** The caller's daily check-in history (most-recent first). */
|
|
export function useZoneCheckInHistory() {
|
|
return useQuery({
|
|
queryKey: ZONE_CHECKIN_QUERY_KEYS.history,
|
|
queryFn: () => getApiListRows(listZoneCheckinHistory()),
|
|
retry: false,
|
|
});
|
|
}
|