71 lines
2.5 KiB
TypeScript
71 lines
2.5 KiB
TypeScript
"use client"
|
|
|
|
import useSWR from "swr"
|
|
import * as api from "./api"
|
|
import type { CalendarEvent, SignupStatus } from "./types"
|
|
|
|
export function useRooms() {
|
|
const { data, error, isLoading, mutate } = useSWR("rooms", () => api.getRooms())
|
|
return { rooms: data ?? [], error, isLoading, mutate }
|
|
}
|
|
|
|
// activeRoomId === null => all rooms combined via /events
|
|
export function useEvents(activeRoomId: number | null, from?: string, to?: string) {
|
|
const key = activeRoomId === null ? ["events", from, to] : ["room-events", activeRoomId, from, to]
|
|
const { data, error, isLoading, mutate } = useSWR(
|
|
key,
|
|
() =>
|
|
activeRoomId === null
|
|
? api.getUserEvents(from, to)
|
|
: api.getRoomEvents(activeRoomId, from, to),
|
|
// Keep showing the previous week/room's events while the new key loads,
|
|
// instead of flashing an empty/loading state on every switch.
|
|
{ keepPreviousData: true },
|
|
)
|
|
return { events: data ?? [], error, isLoading, mutate }
|
|
}
|
|
|
|
export function useRoomMembers(roomId: number | null) {
|
|
const { data, error, isLoading, mutate } = useSWR(
|
|
roomId === null ? null : ["room-members", roomId],
|
|
() => api.getRoomMembers(roomId as number),
|
|
)
|
|
return { members: data ?? [], error, isLoading, mutate }
|
|
}
|
|
|
|
export function useRoomPermissions(roomId: number | null) {
|
|
const { data, error, isLoading, mutate } = useSWR(
|
|
roomId === null ? null : ["room-whoami", roomId],
|
|
() => api.roomWhoami(roomId as number),
|
|
)
|
|
return { permissions: data, error, isLoading, mutate }
|
|
}
|
|
|
|
// Bulk-fetch the current user's own RSVP status for every visible proposal
|
|
// event, so the week view can color-code events the user has declined.
|
|
// Only proposal-type events carry RSVPs, so we skip busy/private blocks.
|
|
export function useMyResponses(events: CalendarEvent[], currentUserId: number | null) {
|
|
const proposalIds = events
|
|
.filter((e) => e.type === "proposal")
|
|
.map((e) => e.id)
|
|
.sort((a, b) => a - b)
|
|
|
|
const key =
|
|
currentUserId !== null && proposalIds.length > 0
|
|
? ["my-responses", currentUserId, proposalIds.join(",")]
|
|
: null
|
|
|
|
const { data, isLoading } = useSWR(key, async () => {
|
|
const entries = await Promise.all(
|
|
proposalIds.map(async (id) => {
|
|
const responses = await api.getEventResponses(id)
|
|
const mine = responses.find((r) => r.user_id === currentUserId)?.status
|
|
return [id, mine] as [number, SignupStatus | undefined]
|
|
}),
|
|
)
|
|
return Object.fromEntries(entries) as Record<number, SignupStatus | undefined>
|
|
})
|
|
|
|
return { myResponses: data ?? {}, isLoading }
|
|
}
|