Raccolta di componenti e funzionalità utilizzati da progetti PDND Interoperabilità.
npm install @pagopa/interop-fe-commons
⚠️ Accertarsi di avere installato tutte lepeerDependencies
richieste.
npm install @pagopa/mui-italia @mui/material @mui/lab @mui/icons-material @emotion/react @emotion/styled date-fns @mui/x-date-pickers react-router-dom
I filtri vengono gestiti attraverso un hook, useFilters
, e un componente Filters
.
useFilters
mantiene lo stato dei filtri in sync con i parametri url. Ritorna l'oggetto contenente i dati da passare alla query e ciò che serve al componente Filters
per renderizzare i campi, i filtri attivi e gestire le interazioni con l'utente.
L'hook accetta un array di oggetti che descrivono i filtri disponibili. Ogni oggetto deve essere costituito dai seguenti campi obbligatori:
label
: Etichetta del filtroname
: Nome del filtro, usato internamente per identificare il filtro e per costruire i parametri url.type
: Tipo del filto. Può esserefreetext
numeric
autocomplete-multiple
autocomplete-single
datepicker
I filtri di tipo autocomplete-multiple
e autocomplete-single
, oltre ai campi obbligatori, accettano anche i seguenti campi:
options
: Richiesto. Deve contenere un array di oggetti con i seguenti campi:value
: valore dell'opzionelabel
: etichetta dell'opzione
onTextInputChange
: opzionale. Callback che viene chiamata quando l'utente modifica il testo inserito nel campo di testo. Può essere usata per aggiornare l'array di opzioni passato al filtro.
I filtri di tipo numeric
, oltre ai campi obbligatori, accettano opzionalmente, i seguenti campi:
min
: valore minimo accettatomax
: valore massimo accettato
Esempio di utilizzo:
import React from "react";
import { useFilters, Filters } from "@pagopa/interop-fe-commons";
const FiltersExample: React.FC = () => {
const { filtersParams, ...handlers } = useFilters<EServiceListQueryFilters>([
{ name: "q", type: "freetext", label: "Find by name" },
{
name: "version",
type: "numeric",
label: "Find by version number",
min: 10,
max: 20,
},
{
name: "consumerId",
type: "autocomplete-multiple",
label: "Find by consumer",
options: [
{ value: "option-1", label: "PagoPA S.p.A." },
{ value: "option-2", label: "Agenzia delle Entrate" },
],
onTextInputChange: (value) => console.log(value),
},
{
name: "state",
type: "autocomplete-single",
label: "Find by State",
options: [
{ value: "option-1", label: "PagoPA S.p.A." },
{ value: "option-2", label: "Agenzia delle Entrate" },
],
onTextInputChange: (value) => console.log(value),
},
{
name: "createdAt",
type: "datepicker",
label: "Find by creation date",
},
]);
return <Filters {...handlers} />
}
La paginazione viene gestita attraverso un hook, usePagination
, e un componente Pagination
.
usePagination
è un hook che mantiene lo stato della paginazione in sync con i parametri url. Accetta in input un oggetto con una proprietà limit
che indica il numero di elementi desiderati per pagina e ritorna un oggetto contente:
paginationParams
: oggetto contenente i parametri da passare alla query.paginatinoProps
: le props da passare al componentePagination
.getTotalPageCount
: funzione che prende in input il numero totale di elementi e ritorna il numero totale di pagine.
Il componente Pagination
è di default allineato a destra e non viene renderizzato se il numero di pagine è inferiore a 2.
Esso accetta tutte le props di un componente Stack
di MUI
nel caso si voglia personalizzare il layout.
Esempio di utilizzo:
import React from "react";
import { usePagination, Pagination } from "@pagopa/interop-fe-commons";
import { useQuery } from '@tanstack/react-query'
const PaginationExample: React.FC = () => {
const {
paginationParams,
paginationProps,
getTotalPageCount
} = usePagination({ limit: 10 });
const { data } = useQuery(
["Records", paginationParams],
/* ... */
)
const totalPages = getTotalPageCount(data.totalCount);
return (
<Pagination
totalPages={totalPages}
{...paginationProps}
/>
);
}
Table
accetta come props:
headLabels
: array di stringhe che vanno a comporre l'intestazione della tabella. Il numero di elementi sarà uguale al numero di colonne.isEmpty
: booleano opzionale che indica se la tabella è vuota. Se ètrue
, viene renderizzato una alert diMUI
con messaggio di avviso.noDataLabel
: stringa opzionale che indica il messaggio da mostrare nel renderizzato nel casoisEmpty
siatrue
. Di default è 'La ricerca corrente non ha prodotto risultati' che viene tradotto in base alla lingua impostata (italiano o inglese).
TableRow
, vanno inserite come children
del componente Table
. Accetta come props:
cellData
: array di stringhe o elementi JSX che vanno a comporre una riga della tabella. Attenzione: nel caso di elementi JSX, è necessario passare unkey
univoco per ogni elemento.children
: opzionale, se viene passato, viene renderizzato come ultima colonna della tabella, allineata a destra. Può essere usato per renderizzare un azione (es. un bottone) per ogni riga.
Esempio di utilizzo:
import React from "react";
import { Table, TableRow } from "@pagopa/interop-fe-commons";
import { Button, Chip } from "@mui/material";
const tableData = [
{ name: "e-service 1", state: "ACTIVE" },
{ name: "e-service 2", state: "SUSPENDED" },
{ name: "e-service 3", state: "ARCHIVED" },
];
export const TableExample: React.FC = () => {
const headLabels = ["Nome", "Stato", ""];
const isEmpty = tableData.length === 0;
return (
<Table isEmpty={isEmpty} headLabels={headLabels}>
{tableData.map((data) => (
<TableRow
key={data.name}
cellData={[data.name, <Chip key={data.name} label={data.state} />]}
>
<Button size="small" variant="outlined">
Ispeziona
</Button>
</TableRow>
))}
</Table>
);
};
Componente che viene generalmente utilizzato per mostrare un informazione costituita da una label ed un contenuto. Accetta come props:
label
: stringa che indica il titolo da mostrare.labelDescription
: stringa opzionale che indica una descrizione del titolo.content
: stringa o elemento JSX che indica il contenuto da mostrare.copyToClipboard
: opzionale, prende un oggetto con le props del componenteCopyToClipboard
di@pagopa/mui-italia
che vengono passate al componente stesso. Se non viene passato, il componente non viene renderizzato.
Esempio di utilizzo:
import React from "react";
import { InformationContainer } from "@pagopa/interop-fe-commons";
const InformationContainerExample: React.FC = () => {
return (
<InformationContainer
label="E-Service"
labelDescription="This is the e-service name"
content="Service"
/>
)
}
Accetta come props:
code
: stringa che indica il codice da mostrare. Se viene passato un oggetto, viene serializzato tramiteJSON.stringify
.hideCopyButton
: booleano opzionale che indica se il bottone per copiare il codice deve essere nascosto. Di default viene mostrato.
Accetta come props:
label
: opzionale, stringa che indica il testo da mostrare vicino lo spinner.direction
: opzionale, stringa che indica la direzione dello spinner in base al testo. Accetta:row
column
(default)row-reverse
column-reverse
sx
: opzionale, oggetto che indica le propssx
diMUI
da passare allo spinner.
Hook che gestisce il caso in cui ci sia bisogno di effettuare query per filtrare le opzioni di un Autocomplete di MUI
.
Per il filtraggio dinamico delle opzioni utilizziamo la seguente logica:
- se il valore del campo di testo contiene meno di 3 caratteri, dal backend ci tornano tutte le opzioni (max 50) ed il filtraggio delle opzioni avviene client-side (svolto in automatico dall'Autocomplete di
MUI
). - se il valore del campo di testo contiene almeno 3 caratteri, il filtraggio delle opzioni avviene tramite query al backend.
L'hook si comporta analogamente a useState
di React, l'unica differenza è la funzione di setState
che implementa il comportamento descritto sopra, applicando un debounce di 300ms al cambio di stato.
Esempio di utilizzo:
import React from "react";
import { useAutocompleteTextInput } from "@pagopa/interop-fe-commons";
import { Autocomplete } from "@mui/material";
import { useQuery } from "@tanstack/react-query";
const AutocompleteExample: React.FC = () => {
const [optionsSearchQuery, setInputTextValue] = useAutocompleteTextInput();
const { data: options } = useQuery(
["Options", { q: optionsSearchQuery }],
/* ... */
)
return (
<Autocomplete
value={value}
options={options}
onInputChange={setInputTextValue}
{/** ... */}
/>
);
};