useBoardService
Panoramica
useBoardService è la facade principale per la gestione di board generiche. Coordina internamente useBoardMetadata (board, stati, priorità, tag, campi) e useBoardElementi (CRUD schede + spostamento ottimistico), delegando tutta l'I/O al KanbanDataSource iniettato.
Senza opzioni, istanzia un PostgRESTDataSource di default — preserva il comportamento storico v1 senza configurazione aggiuntiva.
Firma
function useBoardService(
boardIdOrCode: number | string,
options?: UseBoardServiceOptions
): {
// State reattivo
board: Ref<Board | null>
stati: Ref<BoardStato[]>
priorita: Ref<BoardPriorita[]>
elementi: Ref<BoardElement[]>
tags: Ref<BoardTag[]>
origini: Ref<BoardOrigine[]>
visibilita: Ref<BoardVisibilita[]>
campi: Ref<BoardCampoRow[]>
loading: Ref<boolean>
error: Ref<string | null>
// Caricamento
initializeBoard: () => Promise<void>
loadBoardData: () => Promise<void>
loadStati: () => Promise<void>
loadElementi: () => Promise<void>
loadElement: (id: number) => Promise<BoardElement | undefined>
loadTags: () => Promise<void>
loadPriorita: () => Promise<void>
loadCampi: () => Promise<void>
// CRUD schede
createElement: (data: Partial<BoardElement>) => Promise<BoardElement | null>
updateElement: (id: number, data: Partial<BoardElement>) => Promise<BoardElement | null>
deleteElement: (id: number) => Promise<boolean | null>
moveElement: (elementId: number, targetFaseId: number, newOrder: number) => Promise<void>
updateElementTags: (elementId: number, newTagIds: number[]) => Promise<boolean>
}
interface UseBoardServiceOptions {
/**
* Sorgente dati iniettabile. Se omessa, viene istanziato `PostgRESTDataSource`
* con il client singleton di libreria — preserva il comportamento storico.
*/
dataSource?: KanbanDataSource<Board, BoardStato, BoardElement, BoardPriorita, BoardTag, BoardCampoRow>
}
boardIdOrCode è passato al composable, non a loadBoardData(). Il composable cattura l'ID al setup e tutte le chiamate successive lo riusano. Per cambiare board, monta un nuovo componente con un nuovo boardIdOrCode.Esempio: backend PostgREST default
import { useBoardService } from '@pzeta/vue-kanban'
import { onMounted } from 'vue'
const boardService = useBoardService('TICKET') // o ID numerico, es. 42
onMounted(() => boardService.loadBoardData())
async function onMoveItem(itemId: number, sourceId: number, targetId: number, newIndex: number) {
await boardService.moveElement(itemId, targetId, newIndex)
}
loadBoardData() carica in parallelo: initializeBoard + stati + priorità + elementi + campi + tag.
Esempio: backend custom
import { useBoardService, type KanbanDataSource } from '@pzeta/vue-kanban'
const myDataSource: KanbanDataSource = { /* ... vedi KanbanDataSource ... */ }
const service = useBoardService('PROJECT-X', { dataSource: myDataSource })
Tutti i composable interni useranno myDataSource invece del default PostgREST.
Stato reattivo
| Proprietà | Tipo | Descrizione |
|---|---|---|
board | Ref<Board | null> | Metadati board (caricata da initializeBoard) |
stati | Ref<BoardStato[]> | Stati / colonne |
elementi | Ref<BoardElement[]> | Schede attive |
priorita | Ref<BoardPriorita[]> | Priorità disponibili |
tags | Ref<BoardTag[]> | Tag disponibili |
campi | Ref<BoardCampoRow[]> | Campi dinamici (per dati_extra) |
origini / visibilita | refs | Lookup ausiliari (vuoti se non popolati) |
loading | Ref<boolean> | True durante operazioni async |
error | Ref<string | null> | Ultimo messaggio di errore |
CRUD schede
// Crea
const nuovo = await boardService.createElement({
titolo: 'Nuova scheda',
idfase: 1,
idpriorita: 2,
})
// Aggiorna
await boardService.updateElement(idscheda, {
titolo: 'Aggiornato',
idpriorita: 3,
})
// Elimina (soft o hard, dipende dal datasource)
await boardService.deleteElement(idscheda)
// Sostituzione completa dei tag (M2M)
await boardService.updateElementTags(idscheda, [1, 3, 5])
Spostamento ottimistico
await boardService.moveElement(elementId, targetFaseId, newOrder)
Il composable applica il move localmente prima di chiamare il datasource; in caso di errore esegue rollback automatico ripristinando lo stato precedente della scheda. La promise rilancia comunque l'errore così il consumer può gestirlo (toast, log, ecc.).
Quando usare cosa
| Scenario | Soluzione |
|---|---|
| Board generica con stati/colonne | useBoardService |
| Pipeline con WIP, stallo, metriche, team | useFasiService |
| Solo metadata (board + stati + priorità + tag + campi) | useBoardMetadata direttamente |
| Solo schede (CRUD + ottimismo) | useBoardElementi direttamente |