Getting Started

Quick Start

Esempi minimi per le 3 modalità d'uso — EnhancedKanbanBoard con dialog default, KanbanFasiBoard con metriche, KanbanBoard headless.

EnhancedKanbanBoard — caso più comune

Smart component che orchestra useBoardService + slot dialog. Caricamento dati, drag-and-drop, CRUD e validazione sono gestiti internamente.

<script setup lang="ts">
import { EnhancedKanbanBoard, getIdUtenteFromJwt } from '@pzeta/vue-kanban'
import {
  DefaultFormDialog,
  DefaultTagDialog,
  DefaultCommentDialog,
  DefaultAttachmentDialog,
  DefaultActivityDialog,
} from '@pzeta/vue-kanban/dialogs'

const getToken = () => sessionStorage.getItem('jwt')
const getCurrentUserId = () => getIdUtenteFromJwt()
</script>

<template>
  <EnhancedKanbanBoard
    board-id-or-code="TICKET"
    :get-token="getToken"
    :get-current-user-id="getCurrentUserId"
  >
    <template #dialog-form="p"><DefaultFormDialog v-bind="p" /></template>
    <template #dialog-attachment="p"><DefaultAttachmentDialog v-bind="p" /></template>
    <template #dialog-tag="p"><DefaultTagDialog v-bind="p" /></template>
    <template #dialog-activity="p"><DefaultActivityDialog v-bind="p" :get-token="getToken" /></template>
    <template #dialog-comment="p"><DefaultCommentDialog v-bind="p" /></template>
  </EnhancedKanbanBoard>
</template>

board-id-or-code accetta un numero (idboard) o una stringa (codboard). Senza slot dialog, i pulsanti azione sulle card non aprono nulla — utile per board read-only.

KanbanFasiBoard — pipeline con metriche

Variante per board con WIP limit, stallo, avanzamento e team per fase. Usa internamente useFasiService con tipi FasePipeline / SchedaKanban.

<script setup lang="ts">
import { KanbanFasiBoard } from '@pzeta/vue-kanban'

const userId = 42
const getToken = () => sessionStorage.getItem('jwt')
</script>

<template>
  <div class="h-screen p-4">
    <KanbanFasiBoard
      board-id="crm"
      :current-user-id="userId"
      :get-token="getToken"
      :show-toolbar="true"
      :show-search="true"
      :show-config="true"
      @schedaspostata="(idScheda, orig, dest) => console.log('spostata', idScheda)"
      @view="scheda => router.push(`/schede/${scheda.idscheda}`)"
    />
  </div>
</template>

Anche qui i dialog vanno passati come slot (gli stessi 5 di EnhancedKanbanBoard).

KanbanBoard — headless

Per controllo totale del rendering (board custom, no PostgREST):

Backend custom (no PostgREST)

Quando il backend è REST custom / GraphQL / mock, implementa l'interfaccia KanbanDataSource e iniettala:

import type { KanbanDataSource, MoveItemResult } from '@pzeta/vue-kanban'
import { useBoardService } from '@pzeta/vue-kanban'

const myDataSource: KanbanDataSource = {
  async loadBoard(id) { return fetch(`/api/boards/${id}`).then(r => r.json()) },
  async loadColumns(boardId) { /* ... */ },
  async loadItems(boardId) { /* ... */ },
  async loadItem(itemId) { /* ... */ },
  async createItem(boardId, data) { /* ... */ },
  async updateItem(itemId, data) { /* ... */ },
  async deleteItem(itemId) { return true },
  async moveItem(itemId, targetCol, order): Promise<MoveItemResult> {
    /* ... */
    return { success: true }
  },
}

const service = useBoardService('PROJECT-X', { dataSource: myDataSource })

Backend con shape diversa (ItemAdapter)

Per item raw che non corrispondono allo schema fasi (campi diversi, naming inglese, ecc.) usa un ItemAdapter:

import type { ItemAdapter } from '@pzeta/vue-kanban'

const myAdapter: ItemAdapter = (raw) => ({
  id: raw.uuid,
  columnId: raw.status,
  title: raw.headline,
  description: raw.summary,
  priority: raw.priority ? { name: raw.priority.label, color: raw.priority.hex } : undefined,
  tags: (raw.labels ?? []).map(l => ({ id: l.id, name: l.name, color: l.color })),
  assignee: raw.owner ? { id: raw.owner.id, name: raw.owner.fullName } : undefined,
  dueDate: raw.dueAt,
  number: raw.code,
  commentCount: raw.commentsCount ?? 0,
  activities: raw.activities ?? [],
  attachments: raw.files ?? [],
  raw,
})
<EnhancedKanbanBoard board-id-or-code="X" :item-adapter="myAdapter" />

L'adapter di default (defaultPostgRESTItemAdapter) gestisce automaticamente naming italiano (titolo, priorita, etichette), inglese (title, priority, tags) e flat RPC (priorita_nome, priorita_colore).

Quando usare quale componente

ScenarioComponente / API
Board CRM/ticket su PostgREST con dialog standardEnhancedKanbanBoard
Pipeline con WIP, stallo, metriche, teamKanbanFasiBoard
Layout completamente customKanbanBoard + composable manuale
Backend non-PostgRESTuseBoardService(id, { dataSource })
Backend con campi diversi:item-adapter="..." su Enhanced/FasiBoard
Solo logica, nessun componenteuseBoardService headless