feat(03-01): pagina SwipeFile UI + TanStack hooks + navigazione

- frontend/src/types.ts: aggiunge SwipeItem, SwipeItemCreate, SwipeItemUpdate, SwipeListResponse
- frontend/src/api/hooks.ts: aggiunge useSwipeItems, useAddSwipeItem, useUpdateSwipeItem, useDeleteSwipeItem
- frontend/src/pages/SwipeFile.tsx: pagina completa con form aggiunta, filtro nicchia, modifica inline, eliminazione con dialog conferma, data relativa
- frontend/src/components/Sidebar.tsx: aggiunge voce "Swipe File" con icona Lightbulb
- frontend/src/App.tsx: registra route /swipe-file
- TypeScript + build Vite: nessun errore
This commit is contained in:
Michele
2026-03-09 00:25:04 +01:00
parent d64c7f4524
commit d379789ec0
5 changed files with 580 additions and 2 deletions

View File

@@ -10,7 +10,7 @@
*/
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { apiDownload, apiGet, apiPost, apiPut, triggerDownload } from './client'
import { apiFetch, apiDownload, apiGet, apiPost, apiPut, triggerDownload } from './client'
import type {
CalendarRequest,
CalendarResponse,
@@ -23,6 +23,10 @@ import type {
PromptListResponse,
Settings,
SettingsStatus,
SwipeItem,
SwipeItemCreate,
SwipeItemUpdate,
SwipeListResponse,
} from '../types'
// ---------------------------------------------------------------------------
@@ -234,3 +238,49 @@ export function useResetPrompt() {
},
})
}
// ---------------------------------------------------------------------------
// Swipe File
// ---------------------------------------------------------------------------
/** Lista tutte le idee salvate nello Swipe File (ordine: piu' recenti prima). */
export function useSwipeItems() {
return useQuery<SwipeListResponse>({
queryKey: ['swipe'],
queryFn: () => apiGet<SwipeListResponse>('/swipe/'),
staleTime: 30_000,
})
}
/** Aggiunge una nuova idea allo Swipe File. */
export function useAddSwipeItem() {
const queryClient = useQueryClient()
return useMutation<SwipeItem, Error, SwipeItemCreate>({
mutationFn: (item) => apiPost<SwipeItem>('/swipe/', item),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['swipe'] })
},
})
}
/** Aggiorna una voce esistente dello Swipe File. */
export function useUpdateSwipeItem() {
const queryClient = useQueryClient()
return useMutation<SwipeItem, Error, { id: string; data: SwipeItemUpdate }>({
mutationFn: ({ id, data }) => apiPut<SwipeItem>(`/swipe/${id}`, data),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['swipe'] })
},
})
}
/** Elimina una voce dallo Swipe File. */
export function useDeleteSwipeItem() {
const queryClient = useQueryClient()
return useMutation<{ deleted: boolean }, Error, string>({
mutationFn: (id) => apiFetch<{ deleted: boolean }>(`/swipe/${id}`, { method: 'DELETE' }),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['swipe'] })
},
})
}