Introdução
Neste tutorial, construiremos um aplicativo de Gestão de Recursos Humanos com o Refine Framework e o implantaremos na Plataforma de Aplicativos DigitalOcean.
No final deste tutorial, teremos um aplicativo de gestão de RH que inclui:
- Página de login: Permite que os usuários façam login como gerentes ou empregados. Os gerentes têm acesso às páginas
Férias
eSolicitações
, enquanto os empregados têm acesso apenas à páginaFérias
. - Páginas de Férias: Permite que os empregados solicitem, visualizem e cancelem suas férias. Além disso, os gerentes podem atribuir novas férias.
- Página de Solicitações: Acessível apenas para gerentes de RH para aprovar ou rejeitar solicitações de férias.
Nota: Você pode obter o código fonte completo do aplicativo que construiremos neste tutorial a partir deste repositório GitHub
Enquanto fazemos isso, usaremos o:
- API REST: Para buscar e atualizar os dados. Refine tem pacotes de provedor de dados e APIs REST integrados, mas você também pode construir o seu próprio para atender às suas necessidades específicas. Neste guia, vamos usar NestJs CRUD como nosso serviço backend e o pacote @refinedev/nestjsx-crud como nosso provedor de dados.
- Material UI: Vamos utilizá-lo para componentes de interface e personalizá-lo totalmente de acordo com nosso próprio design. Refine possui suporte integrado para Material UI, mas você pode usar qualquer biblioteca de interface que preferir.
Assim que construirmos o aplicativo, vamos colocá-lo online usando Plataforma de Aplicativos da DigitalOcean, que facilita a configuração, lançamento e crescimento de aplicativos e sites estáticos. Você pode implantar o código simplesmente apontando para um repositório do GitHub e deixar a Plataforma de Aplicativos lidar com a infraestrutura, runtimes de aplicativos e dependências.
Pré-requisitos
- Um ambiente de desenvolvimento local para Node.js. Você pode seguir o Guia de Instalação do Node.js e Criação de um Ambiente de Desenvolvimento Local.
- Algum conhecimento preliminar de React e TypeScript. Você pode seguir a série Como Codificar em React.js e Usando TypeScript com React.
- Uma conta no GitHub
- Uma conta no DigitalOcean
O que é Refine?
Refine é um meta-framework React de código aberto para a construção de aplicações web complexas B2B, principalmente focadas em gerenciamento de dados, como ferramentas internas, painéis de administração e dashboards. Ele é projetado fornecendo um conjunto de hooks e componentes para melhorar o processo de desenvolvimento com um fluxo de trabalho melhor para o desenvolvedor.
Ele fornece recursos completos e prontos para produção para aplicativos de nível empresarial para simplificar tarefas pagas como gerenciamento de estado e dados, autenticação e controle de acesso. Isso permite que os desenvolvedores permaneçam focados no núcleo de sua aplicação de uma forma que está abstraída de muitos detalhes de implementação avassaladores.
Passo 1 — Configurando o Projeto
Usaremos o comando npm create refine-app
para inicializar o projeto de forma interativa.
Selecione as seguintes opções quando solicitado:
Uma vez que a configuração estiver completa, navegue até a pasta do projeto e inicie seu aplicativo com:
Abra http://localhost:5173
no seu navegador para ver o aplicativo.
Preparando o Projeto
Agora que temos nosso projeto configurado, vamos fazer algumas alterações na estrutura do projeto e remover os arquivos desnecessários.
Primeiro, instale as dependências de terceiros:
@mui/x-date-pickers
,@mui/x-date-pickers-pro
: Estes são componentes de seleção de data para o Material UI. Nós os usaremos para selecionar o intervalo de datas para os pedidos de folga.react-hot-toast
: Uma biblioteca minimalista de toast para React. Nós a usaremos para mostrar mensagens de sucesso e erro.react-infinite-scroll-component
: Um componente React para facilitar o scroll infinito. Nós o usaremos para carregar mais pedidos de folga à medida que o usuário rolar para baixo na página para visualizar mais pedidos.dayjs
: Uma biblioteca leve de datas para analisar, validar, manipular e formatar datas.vite-tsconfig-paths
: Um plugin Vite que permite usar aliases de caminho TypeScript em seu projeto Vite.
Após instalar as dependências, atualize vite.config.ts
e tsconfig.json
para usar o plugin vite-tsconfig-paths
. Isso habilita aliases de caminho TypeScript em projetos Vite, permitindo importações com o alias @
.
Em seguida, vamos remover os arquivos e pastas desnecessários:
src/contexts
: Esta pasta contém um único arquivo que éColorModeContext
. Ele gerencia o modo escuro/claro para o aplicativo. Não o utilizaremos neste tutorial.src/components
: Esta pasta contém o componente<Header />
. Usaremos um componente de cabeçalho personalizado neste tutorial.
Após remover os arquivos e pastas, App.tsx
apresenta um erro que resolveremos nos próximos passos.
Ao longo do tutorial, cobriremos o código das páginas e componentes principais. Portanto, obtenha os arquivos e pastas necessários do repositório GitHub. Com esses arquivos, teremos uma estrutura básica para nossa aplicação de Gestão de Recursos Humanos.
- ícones: Pasta de ícones contendo todos os ícones do aplicativo.
- tipos:
index.ts
: Tipos do aplicativo.
- utilidades:
constants.ts
: Constantes do aplicativo.axios.ts
: Instância Axios para requisições de API, lidando com tokens de acesso, tokens de atualização e erros.init-dayjs.ts
: Inicializa o Day.js com os plugins necessários.
- provedores:
controle-de-acesso
: Gerencia permissões de usuário usandoprovedorDeAcesso
; controla a visibilidade da página deSolicitações
com base no papel do usuário.provedor-de-autenticação
: Gerencia a autenticação comprovedorDeAutenticação
; garante que todas as páginas estejam protegidas e exijam login.provedor-de-notificações
: Exibe mensagens de sucesso e erro viareact-hot-toast
.cliente-de-consulta
: Cliente de consulta personalizado para controle e personalização total.provedor-de-tema
: Gerencia o tema do Material UI.
- componentes:
layout
: Componentes de layout.loading-overlay
: Exibe uma sobreposição de carregamento durante a busca de dados.input
: Renderiza campos de entrada de formulário.frame
: Componente personalizado que adiciona bordas, títulos e ícones às seções da página.modal
: Componente de diálogo modal personalizado.
Após copiar os arquivos e pastas, a estrutura de arquivos deve ficar assim:
└── 📁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
Em seguida, atualize o arquivo App.tsx
para incluir os provedores e componentes necessários.
Vamos detalhar as alterações importantes que fizemos no arquivo App.tsx
:
<Refine />
: O componente central do@refinedev/core
que envolve toda a aplicação para fornecer busca de dados, gerenciamento de estado e outros recursos.<DevtoolsProvider />
e<DevtoolsPanel />
: Usado para fins de depuração e desenvolvimento.<ThemeProvider />
: Aplica temas personalizados em todo o aplicativo.- Inicializando o Day.js: Para manipulação de datas e horários.
- recursos: Um array especificando as entidades de dados (
funcionário
egerente
) que o Refine irá buscar. Usamos recursos pai e filho para organizar dados e gerenciar permissões. Cada recurso tem umescopo
que define o papel do usuário, controlando o acesso a diferentes partes do aplicativo. - queryClient: Um cliente de consulta personalizado para controle total e personalização da busca de dados.
- syncWithLocation: Habilita a sincronização do estado do aplicativo (filtros, ordenações, paginação etc.) com a URL.
- warnWhenUnsavedChanges: Mostra um aviso quando o usuário tenta navegar para fora de uma página com alterações não salvas.
<Layout />
: Um componente de layout personalizado que envolve o conteúdo do aplicativo. Ele contém o cabeçalho, a barra lateral e a área principal de conteúdo. Vamos explicar este componente nos próximos passos.
Agora, estamos prontos para começar a construir a aplicação de Gestão de Recursos Humanos.
Passo 2— Personalização e estilo
Dê uma olhada mais de perto no theme-provider
. Personalizamos bastante o tema do Material UI para combinar com o design da aplicação de Gestão de Recursos Humanos, criando dois temas: um para gerentes e um para funcionários, para diferenciá-los com cores diferentes.
Além disso, adicionamos Inter como uma fonte personalizada para o aplicativo. Para instalar, você precisa adicionar a seguinte linha ao arquivo index.html
:
Inspecionando Personalizado <Layout />
Componente
No passo anterior, adicionamos um componente de layout personalizado ao aplicativo. Normalmente, poderíamos usar o layout padrão do framework de UI, mas queremos mostrar como você pode fazer personalizações.
O componente de layout contém o cabeçalho, barra lateral e área de conteúdo principal. Ele usa <ThemedLayoutV2 />
como base e o personalizou para combinar com o design do aplicativo de Gerenciamento de RH.
<Sider />
A barra lateral contém o logotipo do aplicativo e links de navegação. Em dispositivos móveis, é uma barra lateral colapsável que se abre quando o usuário clica no ícone do menu. Os links de navegação são preparados com o useMenu
hook do Refine e renderizados com base no papel do usuário, com a ajuda do <CanAccess />
componente.
<UserSelect />
Montado na barra lateral, mostra o avatar e o nome do usuário logado. Quando clicado, ele abre um popover com detalhes do usuário e um botão de logout. Os usuários podem alternar entre diferentes papéis selecionando no menu suspenso. Este componente permite testar alternando entre usuários com diferentes papéis.
<Header />
Não renderiza nada em dispositivos desktop. Em dispositivos móveis, mostra o logotipo do aplicativo e um ícone de menu para abrir a barra lateral. O cabeçalho é fixo e sempre visível no topo da página.
<PageHeader />
Ele mostra o título da página e os botões de navegação. O título da página é gerado automaticamente com o useResource
hook, que busca o nome do recurso do contexto do Refine. Isso nos permite compartilhar a mesma estilização e layout em todo o aplicativo.
Etapa 3 — Implementando a Autenticação & Autorização
Nesta etapa, implementaremos a lógica de autenticação e autorização para nosso aplicativo de Gestão de Recursos Humanos. Isso servirá como um ótimo exemplo de controle de acesso em aplicativos empresariais.
Quando os usuários fizerem login como gerentes, poderão ver as páginas Time Off
e Requests
. Se fizerem login como funcionários, verão apenas a página Time Off
. Os gerentes podem aprovar ou recusar solicitações de folga na página Requests
.
Os funcionários podem solicitar folgas e ver seu histórico na página Time Off
. Para implementar isso, utilizaremos os recursos authProvider
e accessControlProvider
do Refine.
Autenticação
No Refine, a autenticação é gerenciada pelo authProvider
. Ele permite que você defina a lógica de autenticação para seu aplicativo. Na etapa anterior, já copiamos o authProvider
do repositório do GitHub e o fornecemos ao componente <Refine />
como uma propriedade. Usaremos os seguintes hooks e componentes para controlar o comportamento do nosso aplicativo com base no fato de o usuário estar logado ou não.
useLogin
: Um hook que fornece uma funçãomutate
para logar o usuário.useLogout
: Um hook que fornece uma funçãomutate
para deslogar o usuário.useIsAuthenticated
: Um hook que retorna um booleano indicando se o usuário está autenticado.<Authenticated />
: Um componente que renderiza seus filhos apenas se o usuário estiver autenticado.
Authorization
No Refine, a autorização é gerenciada pelo accessControlProvider
. Ele permite definir papéis e permissões de usuário e controlar o acesso a diferentes partes do aplicativo com base no papel do usuário. Na etapa anterior, já copiamos o accessControlProvider
do repositório do GitHub e o passamos para o componente <Refine />
como uma prop. Vamos dar uma olhada mais de perto no accessControlProvider
para ver como funciona.
No nosso aplicativo, temos dois papéis: MANAGER
e EMPLOYEE
.
Os gerentes têm acesso à página Requests
, enquanto os funcionários têm acesso apenas à página Time Off
. O accessControlProvider
verifica a função do usuário e o escopo do recurso para determinar se o usuário pode acessar o recurso. Se a função do usuário corresponder ao escopo do recurso, ele pode acessar o recurso. Caso contrário, o acesso é negado. Vamos usar o hook useCan
e o componente <CanAccess />
para controlar o comportamento do nosso aplicativo com base na função do usuário.
Configurando a Página de Login
No passo anterior, adicionamos o authProvider
ao componente <Refine />
. O authProvider
é responsável por lidar com a autenticação.
Primeiro, precisamos obter imagens. Vamos usar essas imagens como imagens de fundo para a página de login. Crie uma nova pasta chamada images
na pasta public
e obtenha as imagens do repositório GitHub.
Após obter as imagens, vamos criar um novo arquivo chamado index.tsx
na pasta src/pages/login
e adicionar o seguinte código:
Para simplificar o processo de autenticação, criamos um objeto mockUsers
com dois arrays: managers
e employees
. Cada array contém objetos de usuário pré-definidos. Quando um usuário seleciona um e-mail na lista suspensa e clica no botão Sign in
, a função login
é chamada com o e-mail selecionado. A função login
é uma função de mutação fornecida pelo hook useLogin
do Refine. Ela chama authProvider.login
com o e-mail selecionado.
Em seguida, vamos importar o componente <PageLogin />
e atualizar o arquivo App.tsx
com as alterações destacadas.
No arquivo atualizado App.tsx
, adicionamos o componente <Authenticated />
do Refine. Este componente é usado para proteger rotas que requerem autenticação. Ele recebe uma propriedade key
para identificar o componente de forma única, uma propriedade fallback
para renderizar quando o usuário não está autenticado, e uma propriedade redirectOnFail
para redirecionar o usuário para a rota especificada quando a autenticação falha. Nos bastidores, ele chama o método authProvider.check
para verificar se o usuário está autenticado.
Vamos dar uma olhada mais de perto no que temos em key="auth-pages"
<Authenticated />
componente envolve a rota “/login” para verificar o status de autenticação do usuário.
fallback={<Outlet />}
: Se o usuário não estiver autenticado, renderize a rota aninhada (ou seja, mostre o componente<PageLogin />
).- Crianças (
<Navigate to="/" />
): Se o usuário estiver autenticado, redirecione-o para a página inicial (/
).
Vamos analisar mais de perto o que temos em key="catch-all"
<Authenticated />
componente envolve a rota path="*"
para verificar o status de autenticação do usuário. Esta rota é uma rota catch-all que renderiza o <ErrorComponent />
quando o usuário está autenticado. Ela nos permite mostrar uma página 404 quando o usuário tenta acessar uma rota inexistente.
Agora, quando você executar o aplicativo e navegar para http://localhost:5173/login
, você deverá ver a página de login com o dropdown para selecionar o usuário.
Neste momento, a página “/” não está fazendo nada. Nos próximos passos, implementaremos as páginas Time Off
e Requests
.
Passo 4 — Construindo uma Página de Tempo Livre
Página de Lista de Tempo de Folga
Neste passo, vamos construir a página de Tempo de Folga
. Os funcionários podem solicitar tempo de folga e ver seu histórico de folgas. Os gerentes também podem visualizar seu histórico, mas em vez de solicitar tempo de folga, eles podem atribuí-lo a si mesmos diretamente. Faremos isso funcionar usando o accessControlProvider
do Refine, o componente <CanAccess />
e o hook useCan
.

Antes de começarmos a construir a página de tempo de folga, precisamos criar alguns componentes para mostrar o histórico de folgas, os próximos pedidos de folga e as estatísticas de folgas usadas. No final deste passo, usaremos esses componentes para construir a página de tempo de folga.
Construindo o componente <TimeOffList />
para mostrar o histórico de folgas
Criar uma nova pasta chamada time-offs
na pasta src/components
. Dentro da pasta time-offs
, crie um novo arquivo chamado list.tsx
e adicione o seguinte código:
O arquivo list.tsx
é extenso, mas a maior parte dele trata de estilo e apresentação da interface.

Usaremos este <TimeOffList />
componente em três contextos diferentes:
A propriedade type
determina qual tipo de lista de folgas exibir:
inReview
: Mostra os pedidos de folga que estão pendentes de aprovação.upcoming
: Exibe as folgas futuras que foram aprovadas, mas ainda não ocorreram.history
: Lista as folgas que foram aprovadas e que já ocorreram.
Dentro do componente, criaremos filtros e classificadores com base na propriedade type
. Usaremos esses filtros e classificadores para buscar os dados de folga da API.
Vamos detalhar as partes principais do componente:
1. Obtendo o Usuário Atual
useGetIdentity<Employee>()
: Busca as informações do usuário atual.- Usamos o ID do funcionário para filtrar as folgas, para que cada usuário veja apenas seus pedidos.
2. Buscando Dados de Folga com Rolagem Infinita
-
useInfiniteList<TimeOff>()
: Recupera dados de folga com rolagem infinita.resource
: Especifica o endpoint da API.sorters
efilters
: Ajustados com base emtype
para recuperar os dados corretos.employeeId
filtro: Garante que apenas as folgas do usuário atual sejam recuperadas.queryOptions.enabled
: Executa a consulta apenas quando os dados do funcionário estão disponíveis.
-
<InfiniteScroll />
: Permite carregar mais dados à medida que o usuário rola para baixo.next
: Função para buscar a próxima página de dados.hasMore
: Indica se há mais dados disponíveis.
3. Cancelando uma Solicitação de Folga
useDelete
: Fornece a funçãotimeOffCancel
para excluir uma solicitação de folga.- Usado quando um usuário cancela sua folga.
- Mostra uma mensagem de sucesso ao concluir.
4. Exibindo Datas com <DateField />
<DateField />
: Formata e exibe datas de uma maneira amigável ao usuário.value
: A data a ser exibida.format
: Especifica o formato da data (por exemplo, “5 de janeiro”).
5. Criando Filtros e Ordenadores baseados em type
Filtros:
- Define critérios para buscar ausências com base em status e datas.
history
: Busca ausências aprovadas que já terminaram.upcoming
: Busca ausências aprovadas que estão por vir.
Ordenadores:
- Determina a ordem dos dados buscados.
history
: Ordena pela data de início em ordem decrescente.
Construindo o componente <TimeOffLeaveCards />
para exibir estatísticas de ausências utilizadas
Crie um novo arquivo chamado leave-cards.tsx
na pasta src/components/time-offs
e adicione o seguinte código:

O componente <TimeOffLeaveCards />
exibe estatísticas sobre as ausências de um funcionário. Ele mostra três cartões para Licença Anual, Licença Médica e Licença Casual, indicando quantos dias estão disponíveis ou utilizados.
Vamos detalhar as partes principais do componente:
1. Obtendo Dados
- Dados do Funcionário: Usa
useGetIdentity
para obter as informações do funcionário atual, como os dias de licença anual disponíveis. - Contagem de Ausências: Usa
useList
para buscar o número total de dias de licença médica e casual utilizados pelo funcionário. DefinepageSize
como 1 porque precisamos apenas da contagem total, não de todos os detalhes.
2. Exibindo os Cartões
- O componente renderiza três componentes de cartão, um para cada tipo de licença.
- Cada cartão mostra:
- O tipo de licença (por exemplo, Licença Anual).
- O número de dias disponíveis ou utilizados.
- Um ícone representando o tipo de licença.
3. Lidando com Estados de Carregamento
- Se os dados ainda estão sendo carregados, mostra um esqueleto em vez dos números reais.
- A propriedade
loading
é passada para os cartões para gerenciar este estado.
4. O Componente de Cartão
- Recebe as propriedades
type
,value
eloading
. - Usa um
variantMap
para obter os rótulos corretos, cores e ícones com base no tipo de licença. - Exibe as informações da licença com o estilo apropriado.
Construindo <PageEmployeeTimeOffsList />
Agora que temos os componentes para listar os períodos de folga e mostrar os cartões de licença, vamos criar o novo arquivo na pasta src/pages/employee/time-offs/
chamado list.tsx
e adicionar o seguinte código:
<PageEmployeeTimeOffsList />
é o componente principal da página de períodos de folga, vamos usar este componente para exibir as listas de períodos de folga e os cartões de licença quando os usuários navegarem para a rota /employee/time-offs
.

Vamos analisar as partes principais do componente:
1. Verificando Funções do Usuário
- Usa o gancho
useCan
para determinar se o usuário atual é um gerente. - Define
isManager
comotrue
se o usuário tiver permissões de gerente.
2. Aplicando Tema com Base na Função
- Envolve o conteúdo dentro de um
<ThemeProvider />
. - O tema muda com base se o usuário é um gerente ou um funcionário.
3. Cabeçalho da Página com Botão Condicional
- Renderiza um
<PageHeader />
com o título “Folga”. - Inclui um
<CreateButton />
que muda com base no papel do usuário:- Se o usuário for um gerente, o botão diz “Atribuir Folga”.
- Se o usuário não for um gerente, ele diz “Solicitar Folga”.
- Isto é tratado usando o componente
<CanAccess />
, que verifica permissões.
4. Exibindo Estatísticas de Licença
- Inclui o componente
<TimeOffLeaveCards />
para mostrar saldos e uso de licenças. - Isto fornece um resumo de licença anual, por doença e casual.
5. Listando Solicitações de Folga
- Usa um layout
<Grid />
para organizar o conteúdo. - No lado esquerdo (
md={6}
), ele exibe:TimeOffList
comtype="inReview"
: Mostra solicitações de folga pendentes.TimeOffList
comtype="upcoming"
: Mostra futuras folgas aprovadas.
- No lado direito (
md={6}
), ele exibe:TimeOffList
comtype="history"
: Mostra as folgas passadas que já ocorreram.
Adicionando a Rota “/employee/time-offs”
Estamos prontos para renderizar o componente <PageEmployeeTimeOffsList />
na rota /employee/time-offs
. Vamos atualizar o arquivo App.tsx
para incluir essa rota:
Vamos detalhar as partes principais do arquivo App.tsx
atualizado:
1. Definindo o Recurso de Folga
Adicionamos um novo recurso para folgas como um filho do recurso employee
recurso. Isso indica que as folgas estão relacionadas aos funcionários e são acessíveis pelos funcionários.
name: 'time-offs'
: Este é o identificador para o recurso, usado internamente pelo Refine.list: '/employee/time-offs'
: Especifica a rota que exibe a visualização da lista do recurso.meta
: Um objeto contendo metadados adicionais sobre o recurso.parent: 'employee'
: Agrupa este recurso sob o escopoemployee
, que pode ser usado para organizar recursos na interface do usuário (como em um menu lateral) ou para controle de acesso.scope: Role.EMPLOYEE
: Indica que este recurso é acessível a usuários com o papelEMPLOYEE
. Usamos isso noaccessControlProvider
para gerenciar permissões.label: 'Time Off'
: O nome de exibição para o recurso na interface do usuário.icon: <TimeOffIcon />
: Associa oTimeOffIcon
a este recurso para identificação visual.
2. Redirecionando para o recurso “time-offs” quando os usuários navegarem para a rota /
Usamos o <NavigateToResource />
componente para redirecionar os usuários para o recurso time-offs
quando eles navegam para a rota /
. Isso garante que os usuários vejam a lista de ausências por padrão.
3. Redirecionando para o recurso “time-offs” quando os usuários estão autenticados
Quando os usuários estão autenticados, nós os redirecionamos para o recurso time-offs
. Se não estiverem autenticados, eles veem a página de login.
4. Adicionando a Rota /employee/time-offs
Nós organizamos as páginas de funcionários usando rotas aninhadas. Primeiro, criamos uma rota principal com path='employee'
que envolve o conteúdo em um tema e layout específicos para funcionários. Dentro desta rota, adicionamos path='time-offs'
, que exibe o componente PageEmployeeTimeOffsList
. Essa estrutura agrupa todos os recursos dos funcionários sob um único caminho e mantém a estilização consistente.
Após adicionar essas alterações, você pode navegar até a rota /employee/time-offs
para ver a página da lista de ausências em ação.

Neste momento, a página da lista de ausências está funcional, mas falta a capacidade de criar novos pedidos de ausência. Vamos adicionar a capacidade de criar novos pedidos de ausência.
Construindo a Página de Criação de Ausências
Nós criaremos uma nova página para solicitar ou atribuir folgas. Esta página incluirá um formulário onde os usuários podem especificar o tipo de folga, datas de início e término, e quaisquer notas adicionais.
Antes de começarmos, precisamos criar novos componentes para usar no formulário:
Construindo o componente <TimeOffFormSummary />
Crie um novo arquivo chamado form-summary.tsx
na pasta src/components/time-offs/
e adicione o seguinte código:

O componente <TimeOffFormSummary />
exibe um resumo da solicitação de folga. Ele mostra os dias de folga anual disponíveis, o número de dias solicitados e os dias restantes. Usaremos este componente no formulário de folga para fornecer aos usuários uma visão clara de sua solicitação.
Construindo o componente <PageEmployeeTimeOffsCreate />
Crie um novo arquivo chamado create.tsx
na pasta src/pages/employee/time-offs/
e adicione o seguinte código:

O componente <PageEmployeeTimeOffsCreate />
exibe um formulário para criar novas solicitações de folga em um aplicativo de gerenciamento de RH. Tanto os funcionários quanto os gerentes podem usá-lo para solicitar ou atribuir folga. O formulário inclui opções para selecionar o tipo de folga, escolher as datas de início e término, adicionar notas e exibe um resumo da folga solicitada.
Vamos dividir as partes principais do componente:
1. Verificando o Papel do Usuário
Com o useCan
hook, verificamos se o usuário atual tem permissões de gerente. Isso determina se o usuário pode atribuir folgas ou apenas solicitá-las. Trataremos o envio do formulário de maneira diferente no onFinishHandler
com base no papel do usuário.
2. Estado do Formulário e Envio
useForm
inicializa o formulário com valores padrão e define notificações de sucesso com base no papel do usuário. A função onFinishHandler
processa os dados do formulário antes de enviá-los. Para gerentes, o status é definido como APPROVED
imediatamente, enquanto as solicitações dos funcionários são enviadas para revisão.
3. Estilização
Em nosso design, a cor primária muda com base no papel do usuário. Usamos o <ThemeProvider />
para aplicar o tema correto adequadamente. O texto e o ícone do botão de envio também mudam dependendo se o usuário é um gerente ou um funcionário.
4. Adicionando a Rota “/employee/time-offs/create”
Precisamos adicionar a nova rota para a página de criação de folgas. Vamos atualizar o arquivo App.tsx
para incluir essa rota:
Após adicionar essas alterações, você pode navegar até a rota /employee/time-offs/create
ou clicar no botão “Atribuir Folga” na página da lista de folgas para acessar o formulário de criação de folga.

Passo 5 — Construindo a Página de Gestão de Solicitações de Folga
Neste passo, vamos criar uma nova página para gerenciar as solicitações de folga. Esta página permitirá que os gerentes revisem e aprovem ou rejeitem as solicitações de folga enviadas pelos funcionários.

Construindo a Página de Lista de Solicitações de Folga
Vamos criar uma nova página para gerenciar as solicitações de folga. Esta página incluirá uma lista de solicitações de folga, mostrando detalhes como o nome do funcionário, o tipo de folga, as datas solicitadas e o status atual.
Antes de começarmos, precisamos criar novos componentes para usar na lista:
Construindo o Componente <RequestsList />
Crie um novo arquivo chamado list.tsx
na pasta src/components/requests/
e adicione o seguinte código:
O componente <RequestsList />
exibe uma lista de solicitações de folga com rolagem infinita. Ele inclui um indicador de carregamento, marcadores de esqueleto e uma mensagem quando não há dados. Este componente foi projetado para lidar com grandes conjuntos de dados de forma eficiente e proporcionar uma experiência de usuário suave.
Construindo o componente <RequestsListItem />
Crie um novo arquivo chamado list-item.tsx
na pasta src/components/requests/
e adicione o seguinte código:
O componente <RequestsListItem />
exibe uma única solicitação de folga na lista. Ele inclui o avatar do funcionário, nome, descrição e um botão para visualizar os detalhes da solicitação. Este componente é reutilizável e pode ser usado para renderizar cada item na lista de solicitações de folga.
Construindo o componente <PageManagerRequestsList />
Crie um novo arquivo chamado list.tsx
na pasta src/pages/manager/requests/
e adicione o seguinte código:
O componente <PageManagerRequestsList />
exibe as solicitações de folga pendentes que os gerentes precisam aprovar. Ele mostra detalhes como o nome do funcionário, tipo de licença, datas solicitadas e quanto tempo atrás a solicitação foi feita. Os gerentes podem clicar em uma solicitação para ver mais detalhes. Ele usa <RequestsList />
e <RequestsListItem />
para renderizar a lista.
Este componente também aceita children
como uma propriedade. Em seguida, implementaremos uma rota de modal usando <Outlet />
para exibir os detalhes da solicitação, renderizando a rota /manager/requests/:id
dentro do componente.
Adicionando a rota “/manager/requests”
Precisamos adicionar a nova rota para a página de gerenciamento de solicitações de folga. Vamos atualizar o App.tsx
para incluir essa rota:
Após adicionar essas alterações, você pode navegar até a rota /manager/requests
para ver a página de gerenciamento de solicitações de folga em ação

Construindo a Página de Detalhes da Solicitação de Folga
Nesta etapa, criaremos uma nova página para exibir os detalhes de uma solicitação de folga. Esta página mostrará o nome do funcionário, o tipo de folga, as datas solicitadas e o status atual. Os gerentes podem aprovar ou rejeitar a solicitação a partir desta página.
Construindo o Componente <TimeOffRequestModal />
Primeiro, crie um arquivo chamado use-get-employee-time-off-usage
na pasta src/hooks/
e adicione o seguinte código:
Usaremos o hook useGetEmployeeTimeOffUsage
para calcular o número total de dias que um funcionário tirou para cada tipo de folga. Essas informações serão exibidas na página de detalhes da solicitação de folga.
Depois disso, crie um novo arquivo chamado time-off-request-modal.tsx
na pasta src/components/requests/
e adicione o seguinte código:
Vamos detalhar o componente <TimeOffRequestModal />
:
1. Buscando o Uso de Folga do Funcionário
O useGetEmployeeTimeOffUsage
hook é usado para buscar o uso de folga do funcionário. Este hook calcula os dias de licença anual restantes e os dias de licença médica e casual já utilizados com base no histórico de folgas do funcionário.
2. Buscando Folgas Aprovadas em Sobreposição
O useList
hook com os filtros acima busca todas as folgas aprovadas que se sobrepõem ao pedido de folga atual. Esta lista é usada para exibir os funcionários que estão ausentes entre as datas solicitadas.
3. Tratando a Aprovação/Rejeição do Pedido de Folga
A função handleSubmit
é chamada quando o gerente aprova ou rejeita o pedido de folga.
Refine invalida automaticamente o cache de recursos após o recurso ser mutado (time-offs
neste caso). Como o uso de folga do funcionário é calculado com base no histórico de folgas, também invalidamos o cache de recursos employees
para atualizar o uso de folga do funcionário.
Adicionando a Rota “/manager/requests/:id”
Neste passo, vamos criar uma nova rota para exibir a página de detalhes do pedido de folga, onde os gerentes podem aprovar ou rejeitar os pedidos.
Vamos criar um novo arquivo chamado edit.tsx
na pasta src/pages/manager/requests/time-offs/
e adicionar o seguinte código:
Agora precisamos adicionar a nova rota para renderizar a página de detalhes do pedido de folga. Vamos atualizar o arquivo App.tsx
para incluir esta rota:
Vamos dar uma olhada mais de perto nas mudanças:
O código acima configura uma estrutura de rotas aninhadas onde um modal é exibido ao navegar para uma rota filho específica. O componente <PageManagerRequestsTimeOffsEdit />
é um modal e renderizado como um filho do componente <PageManagerRequestsList />
. Essa estrutura nos permite exibir o modal em cima da página da lista, enquanto mantém a página da lista visível ao fundo.
Quando você navega para a rota /manager/requests/:id/edit
ou clica em um pedido de folga na lista, a página de detalhes do pedido de folga será exibida como um modal em cima da página da lista.

Passo 6 — Implementando Autorização e Controle de Acesso
A autorização é um componente crítico em aplicações de nível empresarial, desempenhando um papel fundamental tanto na segurança quanto na eficiência operacional. Ela garante que apenas usuários autorizados possam acessar recursos específicos, protegendo dados sensíveis e funcionalidades. O sistema de autorização do Refine fornece a infraestrutura necessária para proteger seus recursos e garantir que os usuários interajam com sua aplicação de forma segura e controlada. Nesta etapa, vamos implementar a autorização e controle de acesso para o recurso de gerenciamento de solicitações de folga. Vamos restringir o acesso às rotas /manager/requests
e /manager/requests/:id/edit
apenas para gerentes com a ajuda do componente <CanAccess />
.
No momento, quando você faz login como um funcionário, você não consegue ver o link da página Solicitações
na barra lateral, mas ainda pode acessar a rota /manager/requests
digitando a URL no navegador. Vamos adicionar uma proteção para evitar acesso não autorizado a essas rotas.
Vamos atualizar o arquivo App.tsx
para incluir as verificações de autorização:
No código acima, adicionamos o componente <CanAccess />
à rota “/manager”. Este componente verifica se o usuário tem a função de “gerente” antes de renderizar as rotas filhas. Se o usuário não tiver a função de “gerente”, será redirecionado para a página de lista de folgas para funcionários.
Agora, quando você fizer login como funcionário e tentar acessar a rota /manager/requests
, você será redirecionado para a página de lista de folgas para funcionários.
Passo 7 — Implantação na plataforma de aplicativos DigitalOcean
Neste passo, vamos implantar a aplicação na Plataforma de Aplicativos DigitalOcean. Para fazer isso, vamos hospedar o código-fonte no GitHub e conectar o repositório do GitHub à Plataforma de Aplicativos.
Enviando o Código para o GitHub
Acesse sua conta do GitHub e crie um novo repositório chamado refine-hr
. Você pode tornar o repositório público ou privado:
Após criar o repositório, navegue até o diretório do projeto e execute o seguinte comando para inicializar um novo repositório Git:
Em seguida, adicione todos os arquivos ao repositório Git com este comando:
Depois, comite os arquivos com este comando:
Em seguida, adicione o repositório do GitHub como um repositório remoto com este comando:
Em seguida, especifique que deseja enviar seu código para o ramo main
com este comando:
Finalmente, envie o código para o repositório do GitHub com este comando:
Quando solicitado, insira suas credenciais do GitHub para enviar seu código.
Você receberá uma mensagem de sucesso após o código ser enviado para o repositório do GitHub.
Nesta seção, você enviou seu projeto para o GitHub para que possa acessá-lo usando o DigitalOcean Apps. O próximo passo é criar um novo aplicativo DigitalOcean usando seu projeto e configurar o deployment automático.
Implantando na Plataforma de Aplicativos DigitalOcean
Neste processo, você irá pegar um aplicativo React e prepará-lo para o deployment via Plataforma de Aplicativos da DigitalOcean. Você irá vincular seu repositório do GitHub ao DigitalOcean, configurar como o aplicativo será construído e, em seguida, criar um deployment inicial de um projeto. Após o projeto ser implantado, as alterações adicionais que você fizer serão automaticamente reconstruídas e atualizadas.
Até o final deste passo, você terá seu aplicativo implantado na DigitalOcean com entrega contínua atendida.
Acesse sua conta DigitalOcean e vá para a página de Apps. Clique no botão Criar App:
Se você não conectou sua conta do GitHub ao DigitalOcean, será solicitado que o faça. Clique no botão Conectar ao GitHub. Uma nova janela se abrirá, pedindo que você autorize o DigitalOcean a acessar sua conta do GitHub.
Depois de autorizar o DigitalOcean, você será redirecionado de volta para a página de Aplicativos do DigitalOcean. O próximo passo é selecionar seu repositório do GitHub. Após selecionar seu repositório, você será solicitado a selecionar um branch para implantar. Selecione o branch main
e clique no botão Próximo.
Depois disso, você verá as etapas de configuração para sua aplicação. Neste tutorial, você pode clicar no botão Próximo para pular as etapas de configuração. No entanto, você também pode configurar sua aplicação como desejar.
Aguarde a conclusão da compilação. Após a compilação ser concluída, clique em App ao Vivo para acessar seu projeto no navegador. Ele será o mesmo que o projeto testado localmente, mas estará ao vivo na web com uma URL segura. Além disso, você pode seguir este tutorial disponível no site da comunidade do DigitalOcean para aprender como implantar aplicações baseadas em React na Plataforma de Aplicativos.
Nota: Caso a compilação falhe ao ser implantada com sucesso, você pode configurar seu comando de compilação no DigitalOcean para usar npm install --production=false && npm run build && npm prune --production
em vez de npm run build
Conclusão
No tutorial de hoje, construímos uma aplicação de Gestão de Recursos Humanos usando o Refine do zero e nos familiarizamos com como criar um aplicativo CRUD totalmente funcional.
Além disso, demonstraremos como implantar sua aplicação na Plataforma de Aplicativos DigitalOcean.
Se você quiser aprender mais sobre o Refine, pode conferir a documentação e se tiver alguma dúvida ou feedback, pode se juntar ao Servidor Discord do Refine.