Vue Ricerca

Libreria Vue 3 per toolbar di ricerca config-driven con generazione query PostgREST. Filtri, preset, rule builder, group-by e ricerche salvate.

Cos'è @pzeta/vue-ricerca

@pzeta/vue-ricerca è una libreria di componenti Vue 3 per costruire toolbar di ricerca config-driven sopra backend PostgREST. Definisci i filtri come array FieldConfig[] e la libreria genera UI + query parameters PostgREST coerenti.

Dichiari cosa filtrare (campi, tipi, operatori), non come renderizzarlo: il componente sceglie il widget giusto (InputText, Select, DatePicker, ...) e l'utility buildPostgrestQuery produce le condizioni PostgREST corrette.

Funzionalità principali

  • 7 tipi di campo: text, select, date, daterange, number, numberrange, boolean
  • Layer avanzati componibili (tutti opzionali, attivati solo se passi la prop relativa):
    • Preset: pill-bar di filtri preconfigurati con gruppi exclusive (radio) o multi-select
    • Rule Builder: AST visuale AND/OR con gruppi annidati, copre tutti gli operatori PostgREST
    • Group By: selettore di raggruppamenti multipli con ordine di priorità
    • Ricerche salvate: snapshot dello stato completo persistito tramite SavedSearchAdapter
  • Collapse: header inline (normal) o bottone-icona compatto con popover sospeso (popover)
  • Composable headless useSearchToolbar: stessa API senza il componente UI
  • Generazione query: buildPostgrestQuery (filtri base) o buildPostgrestQueryFromState (stato completo)

Architettura

@pzeta/vue-ricerca
├── components/
│   ├── SearchToolbar.vue              # componente principale
│   ├── SearchToolbarBody.vue          # corpo (riusato da normal/popover)
│   ├── fields/                        # field renderers per ciascun tipo
│   ├── presets/                       # PresetFilterBar
│   ├── rules/                         # RuleBuilder
│   ├── groupby/                       # GroupBySelector
│   ├── saved-search/                  # SavedSearchPanel
│   └── actions/                       # Apply/Reset buttons
├── composables/
│   ├── useSearchToolbar.ts            # composable completo (filters + layer avanzati)
│   ├── usePresets.ts · useRuleBuilder.ts · useSavedSearches.ts
│   └── useFilterValidation.ts · useGridConfig.ts · useSearchActions.ts
├── utils/
│   ├── postgrest.ts                   # buildPostgrestQuery + buildPostgrestQueryFromState
│   ├── rule-builder.ts                # buildRuleGroupQuery + buildRuleCondition
│   ├── defaults.ts · validation.ts
│   └── tailwind-grid.ts
├── plugins/                           # VueRicercaPlugin
└── types/                             # FieldConfig, SearchState, RuleGroup, ...

SearchState

L'evento apply (e il computed searchState del composable) emette sempre lo stato completo, anche quando i layer avanzati non sono configurati:

interface SearchState {
  filters: Record<string, unknown>  // valori dei FieldConfig
  activePresets: string[]           // ID preset attivi (vuoto se no preset configurati)
  rules: RuleGroup | null           // AST rule builder (null se nessuna regola)
  groupByFields: GroupByEntry[]     // raggruppamenti in ordine di priorità (vuoto se assenti)
}
Niente più applyV2/SearchStateV2/buildPostgrestQueryV2. La libreria attuale ha un singolo evento apply: SearchState. La generazione query è buildPostgrestQuery (solo filtri base) o buildPostgrestQueryFromState (stato completo coi 4 layer).

Sotto-pagine

Nessuna sotto-pagina disponibile.

Quick start

// main.ts
import { createApp } from 'vue'
import { VueRicercaPlugin } from '@pzeta/vue-ricerca'
import '@pzeta/vue-ricerca/style.css'

createApp(App).use(VueRicercaPlugin).mount('#app')
<script setup lang="ts">
import { ref } from 'vue'
import { buildPostgrestQuery } from '@pzeta/vue-ricerca'
import type { FieldConfig, SearchState } from '@pzeta/vue-ricerca'

const filtri = ref({})

const fields: FieldConfig[] = [
  { key: 'search', type: 'text', label: 'Cerca', showSearchIcon: true,
    postgrest: { column: ['nome', 'descrizione'] } },
  { key: 'stato', type: 'select', label: 'Stato',
    options: [{ label: 'Attivo', value: 'attivo' }, { label: 'Inattivo', value: 'inattivo' }],
    optionLabel: 'label', optionValue: 'value' },
]

function onApply(state: SearchState) {
  const query = buildPostgrestQuery(state.filters, fields)
  // fetch(`/api/items?${new URLSearchParams(query)}`)
}
</script>

<template>
  <SearchToolbar v-model="filtri" :fields="fields" @apply="onApply" />
</template>

Considerazioni di sicurezza

  • La libreria genera solo query parameters: il backend PostgREST deve applicare Row Level Security (RLS) e validazione lato server.
  • Sanifica/validazione lato server prima di eseguire la query: la libreria non applica escape sui valori (PostgREST stesso gestisce SQL injection tramite parametrizzazione).
  • CSP: style-src 'self' 'unsafe-inline' richiesto per gli inline styles di PrimeVue.