Files
SimpleFinanceDash/src/hooks/useQuickAdd.ts
2026-04-02 14:29:36 +02:00

138 lines
4.2 KiB
TypeScript

import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"
import { supabase } from "@/lib/supabase"
import type { QuickAddItem } from "@/lib/types"
// ---------------------------------------------------------------------------
// Query key
// ---------------------------------------------------------------------------
const QUICK_ADD_KEY = ["quick-add"] as const
// ---------------------------------------------------------------------------
// Hook
// ---------------------------------------------------------------------------
/**
* TanStack Query hook for managing the user's quick-add item library.
*
* Provides:
* - `items` — ordered list of QuickAddItem rows
* - `loading` — true while the initial fetch is in-flight
* - `create` — mutation to add a new item (name, optional icon)
* - `update` — mutation to rename / change the icon of an existing item
* - `remove` — mutation to delete an item by id
*/
export function useQuickAdd() {
const queryClient = useQueryClient()
// ------------------------------------------------------------------
// Query: list all quick-add items for the current user, by sort_order
// ------------------------------------------------------------------
const query = useQuery({
queryKey: QUICK_ADD_KEY,
queryFn: async () => {
const { data, error } = await supabase
.from("quick_add_items")
.select("*")
.order("sort_order")
if (error) throw error
return data as QuickAddItem[]
},
})
// ------------------------------------------------------------------
// Mutation: create a new quick-add item
// ------------------------------------------------------------------
const create = useMutation({
mutationFn: async ({
name,
icon,
}: {
name: string
icon?: string | null
}) => {
const {
data: { user },
} = await supabase.auth.getUser()
if (!user) throw new Error("Not authenticated")
// Determine next sort_order as max + 1 (or 0 for the first item)
const currentItems = queryClient.getQueryData<QuickAddItem[]>(QUICK_ADD_KEY) ?? []
const nextOrder =
currentItems.length > 0
? Math.max(...currentItems.map((i) => i.sort_order)) + 1
: 0
const { data, error } = await supabase
.from("quick_add_items")
.insert({
user_id: user.id,
name,
icon: icon ?? null,
sort_order: nextOrder,
})
.select()
.single()
if (error) throw error
return data as QuickAddItem
},
onSuccess: () => queryClient.invalidateQueries({ queryKey: QUICK_ADD_KEY }),
})
// ------------------------------------------------------------------
// Mutation: update name and/or icon of an existing item
// ------------------------------------------------------------------
const update = useMutation({
mutationFn: async ({
id,
name,
icon,
}: {
id: string
name: string
icon: string | null
}) => {
const { data, error } = await supabase
.from("quick_add_items")
.update({ name, icon })
.eq("id", id)
.select()
.single()
if (error) throw error
return data as QuickAddItem
},
onSuccess: () => queryClient.invalidateQueries({ queryKey: QUICK_ADD_KEY }),
})
// ------------------------------------------------------------------
// Mutation: delete a quick-add item by id
// ------------------------------------------------------------------
const remove = useMutation({
mutationFn: async (id: string) => {
const { error } = await supabase
.from("quick_add_items")
.delete()
.eq("id", id)
if (error) throw error
},
onSuccess: () => queryClient.invalidateQueries({ queryKey: QUICK_ADD_KEY }),
})
// ------------------------------------------------------------------
// Exposed API
// ------------------------------------------------------------------
return {
/** All quick-add items for the current user, ordered by sort_order. */
items: query.data ?? [],
loading: query.isLoading,
create,
update,
remove,
}
}