Polish: imperial, clear-bed, keyboard nudging, empty states (#18)
Build image / build-and-push (push) Successful in 4s
Build image / build-and-push (push) Successful in 4s
Co-authored-by: Steve Dudenhoeffer <[email protected]>
This commit was merged in pull request #37.
This commit is contained in:
@@ -263,6 +263,31 @@ export function useUpdatePlanting(gardenId: number) {
|
||||
})
|
||||
}
|
||||
|
||||
/** Clear a bed: soft-remove every active plop in an object (a loop of PATCHes;
|
||||
* a bulk ClearObject endpoint arrives with the agent seam, #19). Invalidates
|
||||
* once at the end. Pass the object's active plops (id + current version). */
|
||||
export function useClearObject(gardenId: number) {
|
||||
const qc = useQueryClient()
|
||||
return useMutation({
|
||||
mutationFn: async (plops: { id: number; version: number }[]) => {
|
||||
const today = new Date().toISOString().slice(0, 10)
|
||||
// allSettled, not all: a partial failure still soft-removed some rows
|
||||
// server-side, so we must reconcile the cache rather than roll everything
|
||||
// back. Report how many failed.
|
||||
const results = await Promise.allSettled(
|
||||
plops.map((p) => api.patch(`/plantings/${p.id}`, { removedAt: today, version: p.version })),
|
||||
)
|
||||
const failed = results.filter((r) => r.status === 'rejected').length
|
||||
if (failed > 0) {
|
||||
throw new Error(`${failed} of ${plops.length} plants couldn't be cleared — refresh and try again.`)
|
||||
}
|
||||
},
|
||||
// Reconcile on success OR partial failure, so the cache matches the server.
|
||||
onSettled: () => qc.invalidateQueries({ queryKey: fullKey(gardenId) }),
|
||||
onError: (err) => toast.error(err instanceof Error ? err.message : 'Could not clear the bed.'),
|
||||
})
|
||||
}
|
||||
|
||||
/** Soft-remove ("Remove"): PATCH removed_at to today; the row is kept but leaves
|
||||
* the active list. Distinct from a hard delete. */
|
||||
export function useRemovePlanting(gardenId: number) {
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
import { useEffect } from 'react'
|
||||
|
||||
/** Set the document title for the current route (suffixed with · pansy). No
|
||||
* restore-on-unmount: each route sets its own title, so restoring the previous
|
||||
* one would race and clobber the incoming route's title on a fast navigation. */
|
||||
export function usePageTitle(title: string): void {
|
||||
useEffect(() => {
|
||||
document.title = title ? `${title} · pansy` : 'pansy'
|
||||
}, [title])
|
||||
}
|
||||
Reference in New Issue
Block a user