Introduzione
In questo tutorial, costruiremo un’applicazione di gestione HR con il Refine Framework e la deployeremo sulla DigitalOcean App Platform.
Alla fine di questo tutorial, avremo un’applicazione di gestione HR che include:
- Pagina di accesso: Consente agli utenti di accedere come manager o dipendente. I manager hanno accesso alle pagine
Time Off
eRequests
, mentre i dipendenti hanno accesso solo alla paginaTime Off
. - Pagine Time Off: Permette ai dipendenti di richiedere, visualizzare e annullare il loro tempo libero. Inoltre, i manager possono assegnare nuovi permessi di assenza.
- Pagina delle richieste: Accessibile solo ai manager HR per approvare o rifiutare le richieste di assenza.
Nota: Puoi ottenere il codice sorgente completo dell’app che costruiremo in questo tutorial da questo repository GitHub
Durante queste operazioni, utilizzeremo:
- API REST: Per recuperare e aggiornare i dati. Refine ha pacchetti provider di dati e API REST integrati, ma è anche possibile crearne uno proprio per soddisfare requisiti specifici. In questa guida, utilizzeremo NestJs CRUD come servizio backend e il pacchetto @refinedev/nestjsx-crud come provider di dati.
- Material UI: Lo utilizzeremo per i componenti dell’interfaccia utente e lo personalizzeremo completamente secondo il nostro design. Refine supporta nativamente Material UI, ma è possibile utilizzare qualsiasi libreria UI preferita.
Una volta completata l’applicazione, la metteremo online utilizzando App Platform di DigitalOcean, che semplifica la configurazione, il lancio e la crescita di app e siti web statici. È possibile distribuire il codice semplicemente puntando a un repository GitHub e lasciando che App Platform si occupi della gestione dell’infrastruttura, degli ambienti di esecuzione dell’app e delle dipendenze.
Prerequisiti
- Un ambiente di sviluppo locale per Node.js. È possibile seguire la guida su Come Installare Node.js e Creare un Ambiente di Sviluppo Locale.
- Alcune conoscenze preliminari di React e TypeScript. Puoi seguire la serie Come programmare in React.js e Utilizzare TypeScript con React.
- Un account GitHub
- Un account DigitalOcean
Cos’è Refine?
Refine è un meta-framework React open source per costruire complesse applicazioni web B2B, principalmente casi d’uso focalizzati sulla gestione dei dati come strumenti interni, pannelli di amministrazione e dashboard. È progettato fornendo un insieme di hook e componenti per migliorare il processo di sviluppo con un flusso di lavoro migliore per lo sviluppatore.
Fornisce funzionalità complete e pronte per la produzione per applicazioni a livello enterprise per semplificare compiti a pagamento come la gestione dello stato e dei dati, l’autenticazione e il controllo degli accessi. Questo consente agli sviluppatori di rimanere concentrati sul nucleo della loro applicazione in un modo che è astratto da molti dettagli di implementazione opprimenti.
Passo 1 — Impostare il progetto
Utilizzeremo il comando npm create refine-app
per inizializzare interattivamente il progetto.
Seleziona le seguenti opzioni quando richiesto:
Una volta completata la configurazione, naviga nella cartella del progetto e avvia la tua app con:
Apri http://localhost:5173
nel tuo browser per vedere l’app.
Preparazione del Progetto
Ora che abbiamo impostato il nostro progetto, apportiamo alcune modifiche alla struttura del progetto e rimuoviamo i file non necessari.
Per prima cosa, installa le dipendenze di terze parti:
@mui/x-date-pickers
,@mui/x-date-pickers-pro
: Questi sono componenti per la selezione delle date per Material UI. Li useremo per selezionare l’intervallo di date per le richieste di tempo libero.react-hot-toast
: Una libreria di toast minimalista per React. La useremo per mostrare messaggi di successo e di errore.react-infinite-scroll-component
: Un componente React per rendere facile lo scroll infinito. Lo useremo per caricare ulteriori richieste di tempo libero mentre l’utente scorre verso il basso per visualizzare più richieste.dayjs
: Una libreria di date leggera per analizzare, convalidare, manipolare e formattare le date.vite-tsconfig-paths
: Un plugin Vite che ti consente di utilizzare alias di percorso TypeScript nel tuo progetto Vite.
Dopo aver installato le dipendenze, aggiorna vite.config.ts
e tsconfig.json
per utilizzare il plugin vite-tsconfig-paths
. Questo abilita gli alias di percorso TypeScript nei progetti Vite, consentendo importazioni con l’alias @
.
Successivamente, rimuoviamo i file e le cartelle non necessari:
src/contexts
: Questa cartella contiene un singolo file che èColorModeContext
. Gestisce la modalità scura/chiara per l’app. Non lo utilizzeremo in questo tutorial.src/components
: Questa cartella contiene il componente<Header />
. Utilizzeremo un componente intestazione personalizzato in questo tutorial.
Dopo aver rimosso i file e le cartelle, App.tsx
genera un errore che risolveremo nei prossimi passaggi.
Durante il tutorial, copriremo la codifica delle pagine e dei componenti principali. Quindi, ottieni i file e le cartelle necessari dal repository GitHub. Con questi file, avremo una struttura di base per la nostra applicazione di gestione HR.
- icone: Cartella icone contenente tutte le icone dell’app.
- tipi:
index.ts
: Tipi dell’app.
- utilità:
constants.ts
: Costanti dell’app.axios.ts
: Istanza di Axios per richieste API, gestione dei token di accesso, token di aggiornamento e degli errori.init-dayjs.ts
: Inizializza Day.js con i plugin necessari.
- fornitori:
access-control
: Gestisce i permessi degli utenti utilizzandoaccessControlProvider
; controlla la visibilità della paginaRequests
in base al ruolo dell’utente.auth-provider
: Gestisce l’autenticazione conauthProvider
; garantisce che tutte le pagine siano protette e richiedano il login.notification-provider
: Visualizza messaggi di successo e di errore tramitereact-hot-toast
.query-client
: Client per query personalizzato per un controllo e una personalizzazione completi.theme-provider
: Gestisce il tema di Material UI.
- componenti:
layout
: Componenti di layout.loading-overlay
: Mostra un overlay di caricamento durante il recupero dei dati.input
: Rende i campi di input del modulo.frame
: Componente personalizzato che aggiunge bordi, titoli e icone alle sezioni della pagina.modal
: Componente di dialogo modale personalizzato.
Dopo aver copiato i file e le cartelle, la struttura dei file dovrebbe apparire così:
└── 📁src
└── 📁components
└── 📁frame
└── 📁input
└── 📁layout
└── 📁header
└── 📁page-header
└── 📁sider
└── 📁loading-overlay
└── 📁modal
└── 📁icons
└── 📁providers
└── 📁access-control
└── 📁auth-provider
└── 📁notification-provider
└── 📁query-client
└── 📁theme-provider
└── 📁types
└── 📁utilities
└── App.tsx
└── index.tsx
└── vite-env.d.ts
Successivamente, aggiorna il file App.tsx
per includere i provider e i componenti necessari.
Analizziamo le modifiche importanti che abbiamo apportato al file App.tsx
:
<Refine />
: Il componente principale di@refinedev/core
che avvolge l’intera applicazione per fornire recupero dati, gestione dello stato e altre funzionalità.<DevtoolsProvider />
e<DevtoolsPanel />
: Utilizzati per scopi di debug e sviluppo.<ThemeProvider />
: Applica un tema personalizzato all’intera app.- Inizializzazione di Day.js: Per la manipolazione di date e orari.
- risorse: Un array che specifica le entità dati (
employee
emanager
) che Refine recupererà. Utilizziamo risorse padre e figlio per organizzare i dati e gestire i permessi. Ogni risorsa ha unscope
che definisce il ruolo dell’utente, il quale controlla l’accesso a diverse parti dell’app. - queryClient: Un client di query personalizzato per il pieno controllo e la personalizzazione del recupero dei dati.
- syncWithLocation: Abilita la sincronizzazione dello stato dell’app (filtri, ordinamenti, paginazione, ecc.) con l’URL.
- warnWhenUnsavedChanges: Mostra un avviso quando l’utente tenta di navigare lontano da una pagina con modifiche non salvate.
<Layout />
: Un componente di layout personalizzato che avvolge il contenuto dell’app. Contiene l’intestazione, la barra laterale e l’area principale del contenuto. Spiegheremo questo componente nei prossimi passaggi.
Ora siamo pronti per iniziare a costruire l’applicazione di gestione HR.
Passo 2— Personalizzazione e stile
Guarda più da vicino il theme-provider
. Abbiamo personalizzato ampiamente il tema di Material UI per adattarlo al design dell’app di gestione HR, creando due temi, uno per i manager e uno per i dipendenti, per differenziarli con colori diversi.
Inoltre, abbiamo aggiunto Inter come font personalizzato per l’app. Per installarlo, devi aggiungere la seguente riga al file index.html
:
Ispezionare il componente personalizzato <Layout />
Componente
Nel passaggio precedente abbiamo aggiunto un componente di layout personalizzato all’app. Normalmente, potremmo utilizzare il layout predefinito del framework UI, ma vogliamo mostrare come puoi effettuare delle personalizzazioni.
Il componente di layout contiene l’intestazione, la barra laterale e l’area dei contenuti principali. Utilizza <ThemedLayoutV2 />
come base e lo ha personalizzato per adattarsi al design dell’app di gestione HR.
<Sider />
La barra laterale contiene il logo dell’app e i link di navigazione. Su dispositivi mobili è una barra laterale collapsibile che si apre quando l’utente clicca sull’icona del menu. I link di navigazione sono preparati con il useMenu
hook di Refine e vengono resi in base al ruolo dell’utente con l’aiuto del <CanAccess />
componente.
<UserSelect />
Montato sulla barra laterale, mostra l’avatar e il nome dell’utente connesso. Quando cliccato, apre un popover con i dettagli dell’utente e un pulsante di disconnessione. Gli utenti possono passare tra diversi ruoli selezionando dal menu a discesa. Questo componente consente di testare passando tra utenti con ruoli diversi.
<Header />
Non rende nulla sui dispositivi desktop. Su dispositivi mobili, mostra il logo dell’app e un’icona di menu per aprire la barra laterale. L’intestazione è fissa e sempre visibile nella parte superiore della pagina.
<PageHeader />
Mostra il titolo della pagina e i pulsanti di navigazione. Il titolo della pagina viene generato automaticamente con il hook useResource
, che recupera il nome della risorsa dal contesto di Refine. Ci consente di condividere lo stesso stile e layout in tutta l’applicazione.
Passaggio 3 — Implementazione dell’Autenticazione e Autorizzazione
In questo passaggio, implementeremo la logica di autenticazione e autorizzazione per la nostra applicazione di Gestione delle Risorse Umane. Questo servirà come ottimo esempio di controllo degli accessi nelle applicazioni enterprise.
Quando gli utenti effettuano l’accesso come manager, potranno vedere le pagine Time Off
e Requests
. Se accedono come dipendenti, vedranno solo la pagina Time Off
. I manager possono approvare o rifiutare le richieste di permesso sulla pagina Requests
.
I dipendenti possono richiedere del tempo libero e visualizzare la loro cronologia sulla pagina Time Off
. Per implementare ciò, utilizzeremo le funzionalità authProvider
e accessControlProvider
di Refine.
Authentication
In Refine, l’autenticazione è gestita dal authProvider
. Questo ti consente di definire la logica di autenticazione per la tua app. Nel passaggio precedente, abbiamo già copiato il authProvider
dal repository GitHub e lo abbiamo dato al componente <Refine />
come prop. Utilizzeremo i seguenti hooks e componenti per controllare il comportamento della nostra app in base se l’utente ha effettuato il login o meno.
useLogin
: Un hook che fornisce una funzionemutate
per effettuare il login dell’utente.useLogout
: Un hook che fornisce una funzionemutate
per effettuare il logout dell’utente.useIsAuthenticated
: Un hook che restituisce un booleano che indica se l’utente è autenticato.<Authenticated />
: Un componente che rende i suoi figli solo se l’utente è autenticato.
Authorization
In Refine, l’autorizzazione è gestita dal accessControlProvider
. Permette di definire ruoli e permessi degli utenti e controllare l’accesso a diverse parti dell’app in base al ruolo dell’utente. Nel passaggio precedente, abbiamo già copiato il accessControlProvider
dal repository di GitHub e lo abbiamo fornito al componente <Refine />
come prop. Diamo un’occhiata più da vicino al accessControlProvider
per vedere come funziona.
Nel nostro app, abbiamo due ruoli: MANAGER
e EMPLOYEE
.
I manager hanno accesso alla pagina Richieste
, mentre i dipendenti hanno accesso solo alla pagina Permesso
. Il accessControlProvider
controlla il ruolo dell’utente e lo scope della risorsa per determinare se l’utente può accedere alla risorsa. Se il ruolo dell’utente corrisponde allo scope della risorsa, allora possono accedere alla risorsa. Altrimenti, viene loro negato l’accesso. Utilizzeremo il hook useCan
e il componente <CanAccess />
per controllare il comportamento della nostra app basato sul ruolo dell’utente.
Configurazione della Pagina di Accesso
Nel passaggio precedente, abbiamo aggiunto il authProvider
al componente <Refine />
. Il authProvider
è responsabile della gestione dell’autenticazione.
Prima di tutto, dobbiamo ottenere delle immagini. Utilizzeremo queste immagini come sfondi per la pagina di accesso. Crea una nuova cartella chiamata images
nella cartella public
e ottieni le immagini dal repository di GitHub.
Dopo aver ottenuto le immagini, creiamo un nuovo file chiamato index.tsx
nella cartella src/pages/login
e aggiungiamo il seguente codice:
Per semplificare il processo di autenticazione, abbiamo creato un oggetto mockUsers
con due array: managers
e employees
. Ogni array contiene oggetti utente predefiniti. Quando un utente seleziona un’email dal menu a discesa e clicca sul pulsante Accedi
, la funzione login
viene chiamata con l’email selezionata. La funzione login
è una funzione di mutazione fornita dal hook useLogin
di Refine. Essa chiama authProvider.login
con l’email selezionata.
Successivamente, importiamo il componente <PageLogin />
e aggiornare il file App.tsx
con le modifiche evidenziate.
Nell’aggiornato file App.tsx
, abbiamo aggiunto il <Authenticated />
componente di Refine. Questo componente viene utilizzato per proteggere le rotte che richiedono autenticazione. Prende una prop key
per identificare univocamente il componente, una prop fallback
da rendere quando l’utente non è autenticato, e una prop redirectOnFail
per reindirizzare l’utente alla rotta specificata quando l’autenticazione fallisce. Sotto il cofano chiama il metodo authProvider.check
per verificare se l’utente è autenticato.
Esaminiamo più da vicino cosa abbiamo su key="auth-pages"
<Authenticated />
componente avvolge la rotta “/login” per controllare lo stato di autenticazione dell’utente.
fallback={<Outlet />}
: Se l’utente è non autenticato, renderizza la rotta nidificata (ossia, mostra il componente<PageLogin />
).- Figli (
<Navigate to="/" />
): Se l’utente è autenticato, reindirizzalo alla home page (/
).
Esaminiamo più da vicino cosa abbiamo su key="catch-all"
<Authenticated />
componente avvolge la rotta path="*"
per controllare lo stato di autenticazione dell’utente. Questa rotta è una rotta catch-all che renderizza il <ErrorComponent />
quando l’utente è autenticato. Ci permette di mostrare una pagina 404 quando l’utente tenta di accedere a una rotta inesistente.
Ora, quando esegui l’app e navighi a http://localhost:5173/login
, dovresti vedere la pagina di accesso con il menu a discesa per selezionare l’utente.
Al momento, la pagina “/” non sta facendo nulla. Nei prossimi passi implementeremo le pagine Time Off
e Requests
.
Passo 4 — Creazione di una pagina Time Off
Costruzione della pagina Elenco Permessi
In questo passaggio, costruiremo la pagina Permessi
. I dipendenti possono richiedere permessi e vedere la loro cronologia dei permessi. I manager possono anche visualizzare la loro cronologia, ma invece di richiedere permessi, possono assegnarli direttamente a se stessi. Faremo funzionare questo utilizzando accessControlProvider
di Refine, il componente <CanAccess />
e l’hook useCan
.

Prima di iniziare a costruire la pagina dei permessi, dobbiamo creare un paio di componenti per mostrare la cronologia dei permessi, le richieste di permesso imminenti e le statistiche dei permessi utilizzati. Alla fine di questo passaggio, utilizzeremo questi componenti per costruire la pagina dei permessi.
Costruzione del componente <TimeOffList />
per mostrare la cronologia dei permessi
Crea una nuova cartella chiamata time-offs
nella cartella src/components
. All’interno della cartella time-offs
, crea un nuovo file chiamato list.tsx
e aggiungi il seguente codice:
Il file list.tsx
è lungo, ma la maggior parte riguarda lo styling e la presentazione dell’interfaccia utente.

Utilizzeremo questo <TimeOffList />
componente in tre contesti diversi:
Il prop type
determina che tipo di lista di assenze mostrare:
inReview
: Mostra le richieste di assenza in attesa di approvazione.upcoming
: Visualizza le assenze future che sono state approvate ma non ancora verificatesi.history
: Elenca le assenze che sono state approvate e che si sono già verificate.
All’interno del componente, creeremo filtri e ordinamenti basati sul prop type
. Useremo questi filtri e ordinamenti per recuperare i dati sulle assenze dall’API.
Analizziamo le parti chiave del componente:
1. Ottenere l’Utente Corrente
useGetIdentity<Employee>()
: Recupera le informazioni dell’utente corrente.- Utilizziamo l’ID del dipendente per filtrare le assenze in modo che ogni utente veda solo le proprie richieste.
2. Recuperare Dati sulle Assenze con Scorrimento Infinito
-
useInfiniteList<TimeOff>()
: Recupera i dati delle ferie con scrolling infinito.resource
: Specifica il punto di accesso API.sorters
efilters
: Regolati in base altype
per recuperare i dati corretti.employeeId
filtro: Assicura che vengano recuperate solo le ferie dell’utente attuale.queryOptions.enabled
: Esegue la query solo quando i dati dell’utente sono disponibili.
-
<InfiniteScroll />
: Consente di caricare più dati man mano che l’utente scorre verso il basso.next
: Funzione per recuperare la pagina successiva di dati.hasMore
: Indica se sono disponibili ulteriori dati.
3. Annullamento di una Richiesta di Ferie
useDelete
: Fornisce la funzionetimeOffCancel
per eliminare una richiesta di ferie.- Utilizzato quando un utente annulla le proprie ferie.
- Mostra un messaggio di successo al termine.
4. Visualizzazione delle Date con <DateField />
<DateField />
: Formatta e visualizza le date in modo user-friendly.value
: La data da visualizzare.format
: Specifica il formato della data (ad es., “5 Gennaio”).
5. Creazione di Filtri e Ordinatori basati su type
Filtri:
- Definisce i criteri per recuperare le assenze in base allo stato e alle date.
history
: Recupera le assenze approvate che sono già terminate.upcoming
: Recupera le assenze approvate che sono in arrivo.
Ordinatori:
- Determina l’ordine dei dati recuperati.
history
: Ordina per data di inizio in ordine decrescente.
Creazione del componente <TimeOffLeaveCards />
per visualizzare le statistiche delle assenze utilizzate.
Crea un nuovo file chiamato leave-cards.tsx
nella cartella src/components/time-offs
e aggiungi il seguente codice:

Il componente <TimeOffLeaveCards />
visualizza statistiche sul tempo libero di un dipendente. Mostra tre schede per il Permesso Annuale, il Permesso di Malattia e il Permesso Personale, indicando quanti giorni sono disponibili o utilizzati.
Analizziamo le parti chiave del componente:
1. Recupero dei Dati
- Dati del Dipendente: Utilizza
useGetIdentity
per ottenere le informazioni dell’attuale dipendente, come i giorni di permesso annuale disponibili. - Conteggi del Tempo Libero: Utilizza
useList
per recuperare il numero totale di giorni di malattia e di permesso personale utilizzati dal dipendente. ImpostapageSize
a 1 perché abbiamo bisogno solo del conteggio totale, non di tutti i dettagli.
2. Visualizzazione delle Schede
- Il componente rende tre componenti scheda, uno per ciascun tipo di permesso.
- Ogni scheda mostra:
- Il tipo di permesso (ad es. Permesso Annuale).
- Il numero di giorni disponibili o utilizzati.
- Un’icona che rappresenta il tipo di permesso.
3. Gestione degli Stati di Caricamento
- Se i dati sono ancora in fase di caricamento, viene visualizzato un segnaposto scheletro invece dei numeri effettivi.
- La prop
loading
viene passata alle card per gestire questo stato.
4. Il Componente Card
- Riceve
type
,value
eloading
come prop. - Utilizza un
variantMap
per ottenere le etichette corrette, i colori e le icone in base al tipo di permesso. - Visualizza le informazioni sul permesso con uno stile appropriato.
Costruzione di <PageEmployeeTimeOffsList />
Ora che abbiamo i componenti per l’elenco dei permessi e la visualizzazione delle card dei permessi, creiamo il nuovo file nella cartella src/pages/employee/time-offs/
chiamato list.tsx
e aggiungiamo il seguente codice:
<PageEmployeeTimeOffsList />
è il componente principale per la pagina dei permessi, useremo questo componente per visualizzare gli elenchi dei permessi e le card dei permessi quando gli utenti navigano sulla rotta /employee/time-offs
.

Suddividiamo le parti chiave del componente:
1. Verifica dei Ruoli Utente
- Utilizza il hook
useCan
per determinare se l’utente attuale è un manager. - Imposta
isManager
sutrue
se l’utente ha le autorizzazioni di manager.
2. Applicazione del Tema in Base al Ruolo
- Avvolge il contenuto all’interno di un
<ThemeProvider />
. - Il tema cambia in base a se l’utente è un manager o un dipendente.
3. Intestazione Pagina con Pulsante Condizionale
- Visualizza un
<PageHeader />
con il titolo “Richiesta di Permesso”. - Includi un
<CreateButton />
che cambia in base al ruolo dell’utente:- Se l’utente è un manager, il pulsante dice “Assegna Permesso”.
- Se l’utente non è un manager, dice “Richiedi Permesso”.
- Questo è gestito utilizzando il componente
<CanAccess />
, che controlla i permessi.
4. Visualizzazione delle Statistiche dei Permessi
- Includi il componente
<TimeOffLeaveCards />
per mostrare i saldi e l’utilizzo dei permessi. - Questo fornisce un riepilogo dei permessi annuali, malattia e casuali.
5. Elenco delle Richieste di Permesso
- Utilizza un layout
<Grid />
per organizzare il contenuto. - Nella parte sinistra (
md={6}
), visualizza:TimeOffList
contype="inReview"
: Mostra le richieste di permesso in sospeso.TimeOffList
contype="upcoming"
: Mostra i permessi approvati imminenti.
- Sul lato destro (
md={6}
), viene visualizzato:TimeOffList
contype="history"
: Mostra i permessi passati che si sono già verificati.
Aggiungendo il percorso “/employee/time-offs”
Siamo pronti a visualizzare il componente <PageEmployeeTimeOffsList />
nel percorso /employee/time-offs
. Aggiorniamo il file App.tsx
per includere questo percorso:
Analizziamo le parti chiave del file App.tsx
aggiornato:
1. Definizione della Risorsa Tempo Libero
Abbiamo aggiunto una nuova risorsa per i permessi come figlio della risorsa employee
risorsa. Questo indica che i permessi sono correlati agli impiegati e sono accessibili dagli impiegati.
name: 'time-offs'
: Questo è l’identificatore per la risorsa, utilizzato internamente da Refine.list: '/employee/time-offs'
: Specifica il percorso che visualizza la vista elenco della risorsa.meta
: Un oggetto che contiene metadati aggiuntivi sulla risorsa.parent: 'employee'
: Raggruppa questa risorsa nell’ambito diemployee
, che può essere utilizzato per organizzare le risorse nell’interfaccia utente (come in un menu a barra laterale) o per il controllo degli accessi.scope: Role.EMPLOYEE
: Indica che questa risorsa è accessibile agli utenti con il ruoloEMPLOYEE
. Utilizziamo questo nell’accessControlProvider
per gestire le autorizzazioni.label: 'Time Off'
: Il nome visualizzato per la risorsa nell’interfaccia utente.icon: <TimeOffIcon />
: Associa l’iconaTimeOffIcon
a questa risorsa per l’identificazione visiva.
2. Reindirizzamento alla risorsa “time-offs” quando gli utenti navigano nella route /
Utilizziamo il <NavigateToResource />
componente per reindirizzare gli utenti alla risorsa time-offs
quando navigano alla rotta /
. Questo assicura che gli utenti vedano l’elenco delle assenze per default.
3. Reindirizzamento alla risorsa “time-offs” quando gli utenti sono autenticati
Quando gli utenti sono autenticati, li reindirizziamo alla risorsa time-offs
. Se non sono autenticati, vedono la pagina di accesso.
4. Aggiunta della rotta /employee/time-offs
Organizziamo le pagine degli impiegati utilizzando rotte annidate. Prima, creiamo una rotta principale con path='employee'
che racchiude il contenuto in un tema e layout specifici per gli impiegati. All’interno di questa rotta, aggiungiamo path='time-offs'
, che visualizza il componente PageEmployeeTimeOffsList
. Questa struttura raggruppa tutte le funzionalità degli impiegati sotto un’unica rotta e mantiene lo stile coerente.
Dopo aver apportato queste modifiche, puoi navigare alla rotta /employee/time-offs
per vedere la pagina dell’elenco delle assenze in azione.

Al momento, la pagina dell’elenco delle assenze è funzionale, ma manca la possibilità di creare nuove richieste di assenza. Aggiungiamo la possibilità di creare nuove richieste di assenza.
Creazione della pagina per le richieste di assenza
Creeremo una nuova pagina per richiedere o assegnare giorni di assenza. Questa pagina includerà un modulo in cui gli utenti possono specificare il tipo di assenza, le date di inizio e fine e eventuali note aggiuntive.
Prima di iniziare, dobbiamo creare nuovi componenti da utilizzare nel modulo:
Creazione del componente <TimeOffFormSummary />
Crea un nuovo file chiamato form-summary.tsx
nella cartella src/components/time-offs/
e aggiungi il seguente codice:

Il componente <TimeOffFormSummary />
visualizza un riepilogo della richiesta di assenza. Mostra i giorni di ferie annuali disponibili, il numero di giorni richiesti e i giorni rimanenti. Utilizzeremo questo componente nel modulo di assenza per fornire agli utenti una chiara panoramica della loro richiesta.
Creazione del componente <PageEmployeeTimeOffsCreate />
Crea un nuovo file chiamato create.tsx
nella cartella src/pages/employee/time-offs/
e aggiungi il seguente codice:

Il componente <PageEmployeeTimeOffsCreate />
visualizza un modulo per creare nuove richieste di assenza in un’app di gestione HR. Sia i dipendenti che i manager possono utilizzarlo per richiedere o assegnare assenze. Il modulo include opzioni per selezionare il tipo di assenza, scegliere le date di inizio e fine, aggiungere note e mostra un riepilogo dell’assenza richiesta.
Analizziamo le parti chiave del componente:
1. Controllo del ruolo utente
Con l’useCan
hook, controlliamo se l’utente attuale ha i permessi di manager. Questo determina se l’utente può assegnare un permesso o solo richiederlo. Gestiremo l’invio del modulo in modo diverso in onFinishHandler
in base al ruolo dell’utente.
2. Stato del Modulo e Invio
useForm
inizializza il modulo con valori predefiniti e imposta le notifiche di successo in base al ruolo dell’utente. La funzione onFinishHandler
elabora i dati del modulo prima di inviarli. Per i manager, lo stato viene impostato su APPROVED
immediatamente, mentre le richieste dei dipendenti vengono inviate per revisione.
3. Stile
Nel nostro design, il colore principale cambia in base al ruolo dell’utente. Utilizziamo il <ThemeProvider />
per applicare il tema corretto di conseguenza. Il testo e l’icona del pulsante di invio cambiano anche a seconda che l’utente sia un manager o un dipendente.
4. Aggiunta della Route “/employee/time-offs/create”
Dobbiamo aggiungere la nuova route per la pagina di creazione del permesso. Aggiorniamo il file App.tsx
per includere questa route:
Dopo aver aggiunto queste modifiche, puoi navigare alla route /employee/time-offs/create
o fare clic sul pulsante “Assegna Permesso” nella pagina dell’elenco dei permessi per accedere al modulo di creazione del permesso.

Passo 5 — Costruzione Pagina di Gestione delle Richieste di Permesso
In questo passo, creeremo una nuova pagina per gestire le richieste di permesso. Questa pagina permetterà ai manager di esaminare e approvare o respingere le richieste di permesso inviate dagli dipendenti.

Costruzione Pagina Elenco Richieste di Permesso
Ci occuperemo di creare una nuova pagina per la gestione delle richieste di permesso. Questa pagina includerà un elenco delle richieste di permesso, mostrando dettagli come il nome del dipendente, il tipo di permesso richiesto, le date richieste e lo stato attuale.
Prima di iniziare, dobbiamo creare nuovi componenti da utilizzare nell’elenco:
Costruzione <RequestsList />
Componente
Crea un nuovo file chiamato list.tsx
nella cartella src/components/requests/
e aggiungi il seguente codice:
Il componente <RequestsList />
visualizza un elenco di richieste di permesso con scorrimento infinito. Include un indicatore di caricamento, segnaposto scheletro e un messaggio quando non ci sono dati. Questo componente è progettato per gestire grandi set di dati in modo efficiente e offrire un’esperienza utente fluida.
Costruzione del componente <RequestsListItem />
Crea un nuovo file chiamato list-item.tsx
nella cartella src/components/requests/
e aggiungi il seguente codice:
Il componente <RequestsListItem />
visualizza una singola richiesta di permesso nella lista. Include l’avatar dell’impiegato, il nome, la descrizione e un pulsante per visualizzare i dettagli della richiesta. Questo componente è riutilizzabile e può essere utilizzato per rendere ogni elemento nell’elenco delle richieste di permesso.
Costruzione del componente <PageManagerRequestsList />
Crea un nuovo file chiamato list.tsx
nella cartella src/pages/manager/requests/
e aggiungi il seguente codice:
Il componente <PageManagerRequestsList />
visualizza le richieste di permesso in sospeso che i manager devono approvare. Mostra dettagli come il nome dell’impiegato, il tipo di permesso, le date richieste e da quanto tempo è stata fatta la richiesta. I manager possono fare clic su una richiesta per vedere ulteriori dettagli. Utilizza <RequestsList />
e <RequestsListItem />
per rendere l’elenco.
Questo componente accetta anche children
come prop. Successivamente, implementeremo un percorso modale utilizzando <Outlet />
per visualizzare i dettagli della richiesta, rendendo il percorso /manager/requests/:id
all’interno del componente.
Aggiunta del percorso “/manager/requests”
Dobbiamo aggiungere la nuova route per la pagina di gestione delle richieste di permesso. Aggiorniamo il file App.tsx
per includere questa route:
Dopo aver apportato queste modifiche, è possibile navigare alla route /manager/requests
per visualizzare la pagina di gestione delle richieste di permesso in azione

Costruzione della Pagina dei Dettagli della Richiesta di Permesso
In questo passaggio, creeremo una nuova pagina per visualizzare i dettagli di una richiesta di permesso. Questa pagina mostrerà il nome dell’impiegato, il tipo di permesso richiesto, le date richieste e lo stato attuale. I manager possono approvare o rifiutare la richiesta da questa pagina.
Costruzione del Componente <TimeOffRequestModal />
Per prima cosa, crea un file chiamato use-get-employee-time-off-usage
nella cartella src/hooks/
e aggiungi il seguente codice:
Useremo il hook useGetEmployeeTimeOffUsage
per calcolare il numero totale di giorni che un impiegato ha preso per ogni tipo di permesso. Queste informazioni verranno mostrate nella pagina dei dettagli della richiesta di permesso.
Dopo di che, crea un nuovo file chiamato time-off-request-modal.tsx
nella cartella src/components/requests/
e aggiungi il seguente codice:
Suddividiamo il componente <TimeOffRequestModal />
:
1. Recupero dell’Utilizzo del Permesso dell’Impiegato
Il useGetEmployeeTimeOffUsage
hook viene utilizzato per recuperare l’uso dei giorni di ferie da parte dell’impiegato. Questo hook calcola i giorni di ferie annuali rimanenti e i giorni di malattia e di ferie non retribuite precedentemente utilizzati in base alla storia delle assenze dell’impiegato.
2. Recupero delle Assenze Approvate Sovrapposte
Il useList
hook con i filtri sopra indicati recupera tutte le assenze approvate che si sovrappongono con la richiesta di assenza attuale. Questa lista viene utilizzata per visualizzare gli impiegati che sono assenti tra le date richieste.
3. Gestione dell’Approvazione/Rifiuto della Richiesta di Assenza
La funzione handleSubmit
viene chiamata quando il manager approva o rifiuta la richiesta di assenza.
Refine invalida automaticamente la cache delle risorse dopo che la risorsa è stata mutata (time-offs
in questo caso). Poiché l’uso delle assenze da parte dell’impiegato viene calcolato in base alla storia delle assenze, invalidiamo anche la cache delle risorse employees
per aggiornare l’uso delle assenze dell’impiegato.
Aggiunta della Route “/manager/requests/:id”
In questo passaggio, creeremo una nuova route per visualizzare la pagina dei dettagli della richiesta di assenza, dove i manager possono approvare o rifiutare le richieste.
Creiamo un nuovo file chiamato edit.tsx
nella cartella src/pages/manager/requests/time-offs/
e aggiungiamo il seguente codice:
Ora dobbiamo aggiungere la nuova route per visualizzare la pagina dei dettagli della richiesta di assenza. Aggiorniamo il file App.tsx
per includere questa route:
Esaminiamo più da vicino le modifiche:
Il codice sopra imposta una struttura di route annidate in cui viene visualizzato un modulo quando si naviga verso una specifica route figlia. Il componente <PageManagerRequestsTimeOffsEdit />
è un modulo e viene renderizzato come un figlio del componente <PageManagerRequestsList />
. Questa struttura ci consente di visualizzare il modulo sopra la pagina dell’elenco mantenendo la pagina dell’elenco visibile sullo sfondo.
Quando si naviga verso la route /manager/requests/:id/edit
o si fa clic su una richiesta di tempo libero nell’elenco, la pagina dei dettagli della richiesta di tempo libero verrà visualizzata come un modulo sopra la pagina dell’elenco.

Passo 6 — Implementazione dell’Autorizzazione e del Controllo degli Accessi
L’autorizzazione è un componente critico nelle applicazioni a livello aziendale, giocando un ruolo chiave sia nella sicurezza che nell’efficienza operativa. Garantisce che solo gli utenti autorizzati possano accedere a risorse specifiche, proteggendo dati e funzionalità sensibili. Il sistema di autorizzazione di Refine fornisce l’infrastruttura necessaria per proteggere le tue risorse e garantire che gli utenti interagiscano con la tua applicazione in modo sicuro e controllato. In questo passaggio, implementeremo l’autorizzazione e il controllo degli accessi per la gestione delle richieste di permesso. Restrigiamo l’accesso alle rotte /manager/requests
e /manager/requests/:id/edit
solo ai manager con l’aiuto del componente <CanAccess />
.
Al momento, quando accedi come dipendente, non puoi vedere il link alla pagina Richieste
nella barra laterale, ma puoi comunque accedere alla rotta /manager/requests
digitando l’URL nel browser. Aggiungeremo una protezione per prevenire l’accesso non autorizzato a queste rotte.
Aggiorniamo il file App.tsx
per includere i controlli di autorizzazione:
Nel codice sopra, abbiamo aggiunto il componente <CanAccess />
alla rotta “/manager”. Questo componente controlla se l’utente ha il ruolo di “manager” prima di eseguire il rendering delle rotte figlie. Se l’utente non ha il ruolo di “manager”, verrà reindirizzato alla pagina dell’elenco dei permessi per i dipendenti.
Ora, quando accedi come dipendente e cerchi di accedere al percorso /manager/requests
, verrai reindirizzato alla pagina dell’elenco delle assenze per i dipendenti.
Passo 7 — Distribuzione sulla piattaforma App di DigitalOcean
In questo passo, distribuiamo l’applicazione sulla piattaforma App di DigitalOcean. Per farlo, ospiteremo il codice sorgente su GitHub e collegheremo il repository GitHub alla piattaforma App.
Invio del codice su GitHub
Accedi al tuo account GitHub e crea un nuovo repository chiamato refine-hr
. Puoi rendere il repository pubblico o privato:
Dopo aver creato il repository, naviga nella directory del progetto ed esegui il seguente comando per inizializzare un nuovo repository Git:
Successivamente, aggiungi tutti i file al repository Git con questo comando:
Poi, esegui il commit dei file con questo comando:
Successivamente, aggiungi il repository GitHub come repository remoto con questo comando:
Infine, specifica che desideri inviare il tuo codice al ramo main
con questo comando:
Infine, spingi il codice nel repository di GitHub con questo comando:
Quando richiesto, inserisci le tue credenziali GitHub per spingere il tuo codice.
Riceverai un messaggio di successo dopo che il codice è stato inviato al repository di GitHub.
In questa sezione, hai caricato il tuo progetto su GitHub in modo da poterlo accedere utilizzando le App di DigitalOcean. Il passo successivo è creare una nuova App di DigitalOcean utilizzando il tuo progetto e impostare il deployment automatico.
Distribuzione sulla DigitalOcean App Platform
Durante questo processo, prenderai un’applicazione React e la preparerai per la distribuzione tramite la App Platform di DigitalOcean. Collegherai il tuo repository GitHub a DigitalOcean, configurerai come l’app verrà costruita e poi creerai un’iniziale distribuzione di un progetto. Dopo che il progetto è stato distribuito, le ulteriori modifiche che apporti verranno ricostruite e aggiornate automaticamente.
Entro la fine di questo passaggio, avrai la tua applicazione distribuita su DigitalOcean con consegna continua predisposta.
Accedi al tuo account DigitalOcean e vai alla pagina Apps. Clicca sul pulsante Crea App:
Se non hai collegato il tuo account GitHub a DigitalOcean, ti verrà chiesto di farlo. Clicca sul pulsante Collegati a GitHub. Si aprirà una nuova finestra che ti chiederà di autorizzare DigitalOcean ad accedere al tuo account GitHub.
Dopo aver autorizzato DigitalOcean, verrai reindirizzato alla pagina delle App di DigitalOcean. Il passo successivo è selezionare il tuo repository GitHub. Dopo aver selezionato il tuo repository, ti verrà chiesto di selezionare un branch da distribuire. Seleziona il branch main
e clicca sul pulsante Avanti.
Dopo di ciò, vedrai i passaggi di configurazione per la tua applicazione. In questo tutorial, puoi cliccare sul pulsante Avanti per saltare i passaggi di configurazione. Tuttavia, puoi anche configurare la tua applicazione come desideri.
Aspetta che la build sia completata. Dopo che la build è completata, premi App Live per accedere al tuo progetto nel browser. Sarà lo stesso del progetto che hai testato localmente, ma questo sarà attivo sul web con un URL sicuro. Inoltre, puoi seguire questo tutorial disponibile sul sito della community di DigitalOcean per imparare a distribuire applicazioni basate su React su App Platform.
Nota: Nel caso in cui la tua build non riesca a essere distribuita con successo, puoi configurare il tuo comando di build su DigitalOcean per utilizzare npm install --production=false && npm run build && npm prune --production
invece di npm run build
Conclusione
In questo tutorial, abbiamo costruito un’applicazione di gestione HR utilizzando Refine da zero e ci siamo familiarizzati con come costruire un’app CRUD completamente funzionale.
Inoltre, dimostreremo come distribuire la tua applicazione sulla Piattaforma App di DigitalOcean.
Se desideri saperne di più su Refine, puoi consultare la documentazione e se hai domande o feedback, puoi unirti al Server Discord di Refine.