Introdução
Neste tutorial, construiremos uma aplicação de Gestão de Recursos Humanos com o Refine Framework e a implantaremos na Plataforma de Aplicativos da DigitalOcean.
No final deste tutorial, teremos uma aplicação de gestão de RH que inclui:
- Página de Login: Permite que usuários façam login como gerente ou empregado. Os gerentes têm acesso às páginas de
Férias
ePedidos
, enquanto os empregados têm acesso apenas à página deFé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 Pedidos: 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 da aplicação que construiremos neste tutorial neste repositório do GitHub
Enquanto fazemos isso, usaremos o:
- API Rest: Para buscar e atualizar os dados. O Refine possui pacotes de provedores de dados e APIs REST integrados, mas você também pode criar o seu próprio para atender às suas necessidades específicas. Neste guia, usaremos NestJs CRUD como nosso serviço backend e o pacote @refinedev/nestjsx-crud como nosso provedor de dados.
- Material UI: Vamos usá-lo para componentes de UI e personalizá-lo totalmente de acordo com nosso próprio design. O Refine tem suporte integrado para Material UI, mas você pode usar qualquer biblioteca de UI que desejar.
Uma vez que tenhamos construído o aplicativo, o colocaremos online usando A 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 fazer o trabalho pesado de gerenciar a infraestrutura, tempos de execução do aplicativo e dependências.
Pré-requisitos
- Um ambiente de desenvolvimento local para Node.js. Você pode seguir o Como Instalar o Node.js e Criar 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 construir aplicações web B2B complexas, principalmente focadas em gerenciamento de dados, como ferramentas internas, painéis administrativos e dashboards. Ele é projetado para fornecer um conjunto de hooks e componentes para melhorar o processo de desenvolvimento com um fluxo de trabalho melhor para o desenvolvedor.
Ele oferece recursos completos e prontos para produção para aplicativos de nível empresarial, simplificando 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 maneira que é abstraída de muitos detalhes de implementação sobrecarregantes.
Passo 1 — Configurando o Projeto
Usaremos o comando npm create refine-app
para inicializar interativamente o projeto.
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
em seu navegador para ver o aplicativo.
Preparando o Projeto
Agora que temos nosso projeto configurado, vamos fazer algumas mudanças 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
: Esses são componentes de seleção de data para o Material UI. Vamos usá-los para selecionar o intervalo de datas para os pedidos de folga.react-hot-toast
: Uma biblioteca minimalista de toast para React. Vamos usá-la para mostrar mensagens de sucesso e erro.react-infinite-scroll-component
: Um componente React para facilitar o scroll infinito. Vamos usá-lo para carregar mais pedidos de folga à medida que o usuário rola 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 do 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 os aliases de caminho do 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 iremos utilizá-lo 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
gera um erro que corrigiremos nos próximos passos. Durante o tutorial, cobriremos a codificação das páginas e componentes principais. Então, obtenha os arquivos e pastas necessários do repositório do 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 do Axios para solicitações de API, lidando com tokens de acesso, tokens de atualização e erros.init-dayjs.ts
: Inicializa o Day.js com plugins necessários.
- provedores:
controle-de-acesso
: Gerencia as permissões dos usuários usandoaccessControlProvider
; controla a visibilidade da páginaRequests
com base no papel do usuário.provedor-de-autenticacao
: Gerencia a autenticação comauthProvider
; garante que todas as páginas estejam protegidas e exijam login.provedor-de-notificacao
: 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
: Mostra uma sobreposição de carregamento durante buscas 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 mudanças 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 outras funcionalidades.<DevtoolsProvider />
e<DevtoolsPanel />
: Usados para fins de depuração e desenvolvimento.<ThemeProvider />
: Aplica temas personalizados em todo o aplicativo.- Inicializando o Day.js: Para manipulação de data e hora.
- recursos: Um array que especifica 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 possui umescopo
que define o papel do usuário, que controla 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 longe 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 de conteúdo principal. Explicaremos este componente nos próximos passos.
Agora, estamos prontos para começar a construir o aplicativo 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 do aplicativo de Gestão de Recursos Humanos, criando dois temas, um para gerentes e um para funcionários, para diferenciá-los com cores distintas.
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 Componente <Layout />
Personalizado
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, a barra lateral e a área de conteúdo principal. Ele usa <ThemedLayoutV2 />
como base e foi personalizado para corresponder ao design do aplicativo de Gestão 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 useMenu
hook do Refine e renderizados com base no papel do usuário com a ajuda do componente <CanAccess />
.
<UserSelect />
Montado na barra lateral, exibe o avatar e o nome do usuário logado. Ao clicar, abre um popover com os detalhes do usuário e um botão de logout. Os usuários podem alternar entre diferentes papéis selecionando no dropdown. Este componente permite testar alternando entre usuários com diferentes papéis.
<Header />
Não renderiza nada em dispositivos desktop. Em dispositivos móveis, exibe 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 exibe 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 no contexto do Refine. Isso nos permite compartilhar o mesmo estilo e layout em todo o aplicativo.
Etapa 3 — Implementando a Autenticação e 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 aplicações 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 pedidos de licença na página Requests
.
Os funcionários podem solicitar folgas e visualizar seu histórico na página Folgas
. 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. No passo 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 em o usuário estar logado ou não.
useLogin
: Um hook que fornece uma funçãomutate
para fazer o login do usuário.useLogout
: Um hook que fornece uma funçãomutate
para fazer o logout do 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.
Autorização
No Refine, a autorização é tratada pelo accessControlProvider
. Isso permite que você defina funções e permissões de usuário, e controle o acesso a diferentes partes do aplicativo com base na função do usuário. Na etapa anterior, nós já copiamos o accessControlProvider
do repositório do GitHub e o fornecemos para o componente <Refine />
como uma propriedade. Vamos dar uma olhada mais de perto no accessControlProvider
para ver como funciona.
Em nosso aplicativo, temos duas funções: GERENTE
e FUNCIONÁRIO
.
Os gerentes têm acesso à página Requests
, enquanto os funcionários têm acesso apenas à página Time Off
. O accessControlProvider
verifica o papel do usuário e o escopo do recurso para determinar se o usuário pode acessar o recurso. Se o papel do usuário corresponder ao escopo do recurso, ele pode acessá-lo. Caso contrário, o acesso é negado. Usaremos o useCan
hook e o <CanAccess />
componente para controlar o comportamento do nosso aplicativo com base no papel 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. Usaremos 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 no dropdown 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 App.tsx
atualizado, adicionamos o componente <Authenticated />
do Refine. Este componente é utilizado para proteger rotas que exigem autenticação. Ele aceita uma prop key
para identificar exclusivamente o componente, uma prop fallback
para renderizar quando o usuário não está autenticado, e uma prop 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"
O componente <Autenticado />
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 />
).- Children (
<Navegar para="/" />
): Se o usuário estiver autenticado, redirecione-os para a página inicial (/
).
Vamos dar uma olhada mais de perto no que temos em key="catch-all"
O componente <Autenticado />
envolve a rota path="*"
para verificar o status de autenticação do usuário. Esta rota é uma rota de captura que renderiza o <ComponenteDeErro />
quando o usuário está autenticado. Isso nos permite mostrar uma página 404 quando o usuário tenta acessar uma rota inexistente.
Agora, ao executar o aplicativo e navegar para http://localhost:5173/login
, você deverá ver a página de login com o menu suspenso para selecionar o usuário.
No momento, a página “/” não está fazendo nada. Nos próximos passos, implementaremos as páginas Afastamento
e Solicitações
.
Passo 4 — Construindo uma Página de Afastamento
Página de Lista de Férias
Neste passo, vamos construir a página Férias
. Os funcionários podem solicitar férias e ver seu histórico de férias. Os gerentes também podem visualizar seu histórico, mas, em vez de solicitar férias, eles podem atribuí-las a si mesmos diretamente. Vamos fazer isso funcionar usando o accessControlProvider
do Refine, o componente <CanAccess />
e o hook useCan
.

Antes de começarmos a construir a página de férias, precisamos criar alguns componentes para mostrar o histórico de férias, as solicitações de férias futuras e as estatísticas de férias utilizadas. No final deste passo, usaremos esses componentes para construir a página de férias.
Criando o componente <TimeOffList />
para mostrar o histórico de férias
Crie 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 lida com estilos e apresentação da interface do usuário.

Vamos usar este componente <TimeOffList />
em três contextos diferentes:
A propriedade type
determina qual tipo de lista de folgas deve ser exibida:
inReview
: Mostra solicitações de folgas pendentes de aprovação.upcoming
: Exibe as próximas folgas 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 folgas na API.
Vamos analisar as partes principais do componente:
1. Obtendo o Usuário Atual
useGetIdentity<Employee>()
: Busca as informações do usuário atual.- Nós usamos o ID do funcionário para filtrar as folgas para que cada usuário veja apenas suas solicitações.
2. Buscando Dados de Folgas com Rolagem Infinita
-
useInfiniteList<TimeOff>()
: Busca dados de folgas com rolagem infinita.resource
: Especifica o endpoint da API.sorters
efilters
: Ajustados com base emtype
para buscar os dados corretos.employeeId
filtro: Garante que apenas as folgas do usuário atual sejam buscadas.queryOptions.enabled
: Executa a consulta somente 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 mais dados estão disponíveis.
3. Cancelando um Pedido de Folga
useDelete
: Fornece a funçãotimeOffCancel
para deletar um pedido de folga.- Usado quando um usuário cancela sua folga.
- Exibe uma mensagem de sucesso após a conclusão.
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 com base 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 por 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 o tempo de folga 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 usados.
Vamos detalhar as partes principais do componente:
1. Buscando 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 Licenças: Usa
useList
para buscar o número total de dias de licença médica e casual usados pelo funcionário. DefinepageSize
como 1 porque só precisamos 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 usados.
- Um ícone representando o tipo de licença.
3. Gerenciando Estados de Carregamento
- Se os dados ainda estiverem carregando, é exibido um espaço reservado em esqueleto em vez dos números reais.
- O prop
loading
é passado para os cartões para gerenciar este estado.
4. O Componente Card
- Recebe
type
,value
eloading
como props. - Usa um
variantMap
para obter os rótulos, cores e ícones corretos com base no tipo de licença. - Exibe as informações da licença com estilo apropriado.
Construindo <PageEmployeeTimeOffsList />
Agora que temos os componentes para listar ausências e mostrar 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 para a página de ausências, usaremos este componente para exibir as listas de ausências e cartões de licença quando os usuários navegarem para a rota /employee/time-offs
.

Vamos detalhar as partes principais do componente:
1. Verificando Papéis do Usuário
- Usa o hook
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 no Papel
- Envolve o conteúdo dentro de um
<ThemeProvider />
. - O tema muda com base em 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 “Férias”. - Inclui um
<CreateButton />
que muda com base no papel do usuário:- Se o usuário for um gerente, o botão diz “Atribuir Férias”.
- Se o usuário não for um gerente, diz “Solicitar Férias”.
- Isso é tratado usando o componente
<CanAccess />
, que verifica as permissões.
4. Exibindo Estatísticas de Férias
- Inclui o componente
<TimeOffLeaveCards />
para mostrar os saldos e o uso de férias. - Isso fornece um resumo de férias anuais, por doença e ocasionais.
5. Listando Solicitações de Férias
- Usa um layout
<Grid />
para organizar o conteúdo. - No lado esquerdo (
md={6}
), exibe:TimeOffList
comtype="inReview"
: Mostra solicitações de férias pendentes.TimeOffList
comtype="upcoming"
: Mostra as férias aprovadas que se aproximam.
- Do lado direito (
md={6}
), é exibido: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 esta rota:
Vamos analisar as partes principais do arquivo App.tsx
atualizado:
1. Definindo o Recurso de Folga
Adicionamos um novo recurso para folgas como um filho do 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 do recurso, usado internamente pelo Refine.list: '/employee/time-offs'
: Especifica a rota que exibe a visão em 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 exibido 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 navegam para a /
rota
Utilizamos 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 dos funcionários usando rotas aninhadas. Primeiro, criamos uma rota principal com path='employee'
que envolve o conteúdo em um tema e layout específico para funcionários. Dentro dessa 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 o estilo consistente.
Após adicionar essas mudanças, você pode navegar para 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ência
Vamos criar uma nova página para solicitar ou atribuir folga. Esta página incluirá um formulário onde os usuários podem especificar o tipo de folga, datas de início e fim, e quaisquer notas adicionais.
Antes de começarmos, precisamos criar novos componentes para usar no formulário:
Construindo o componente <TimeOffFormSummary />
Criar um novo arquivo chamado form-summary.tsx
na pasta src/components/time-offs/
e adicionar o seguinte código:

O componente <TimeOffFormSummary />
exibe um resumo da solicitação de folga. Ele mostra os dias de licença 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 />
Criar um novo arquivo chamado create.tsx
na pasta src/pages/employee/time-offs/
e adicionar 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 datas de início e fim, adicionar notas e mostra um resumo da folga solicitada.
Vamos detalhar 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 conceder folgas ou apenas solicitá-las. Iremos tratar a submissão do formulário de maneira diferente no onFinishHandler
com base no papel do usuário.
2. Estado do Formulário e Submissão
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 submetê-los. Para gerentes, o status é definido como APPROVED
imediatamente, enquanto as solicitações dos funcionários são submetidas para revisão.
3. Estilização
No nosso design, a cor primária muda com base no papel do usuário. Usamos o <ThemeProvider />
para aplicar o tema correto de acordo. O texto e o ícone do botão de submissão 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 Gerenciamento de Solicitações de Licença
Neste passo, criaremos uma nova página para gerenciar as solicitações de licença. Esta página permitirá que os gerentes revisem e aprovem ou rejeitem as solicitações de licença enviadas pelos funcionários.

Construindo a Página de Lista de Solicitações de Licença
Vamos criar uma nova página para gerenciar as solicitações de licença. Esta página incluirá uma lista de solicitações de licença, mostrando detalhes como o nome do funcionário, o tipo de licença, 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 licença com rolagem infinita. Ele inclui um indicador de carregamento, espaços reservados em forma de esqueleto e uma mensagem quando não há dados. Este componente é 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 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 modal usando <Outlet />
para exibir 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 mudanças, você pode navegar para 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
Neste passo, 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 total de dias que um funcionário tirou para cada tipo de folga. Essa informação será exibida 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 licença do funcionário. Este hook calcula os dias restantes de licença anual e os dias de licença médica e casual já utilizados com base no histórico de licenças do funcionário.
2. Buscando Licenças Aprovadas que se Sobrepõem
O useList
hook com os filtros acima busca todas as licenças aprovadas que se sobrepõem ao pedido de licença atual. Esta lista é usada para exibir os funcionários que estão ausentes entre as datas solicitadas.
3. Tratando Aprovação/Rejeição de Pedidos de Licença
A função handleSubmit
é chamada quando o gerente aprova ou rejeita o pedido de licença.
Refine invalida automaticamente o cache de recursos após o recurso ser mutado (time-offs
neste caso). Como o uso de licença do funcionário é calculado com base no histórico de licenças, também invalidamos o cache de recursos employees
para atualizar o uso de licença do funcionário.
Adicionando a Rota “/manager/requests/:id”
Nesta etapa, criaremos uma nova rota para exibir a página de detalhes do pedido de licença, 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 licença. 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 específica de filho. O componente <PageManagerRequestsTimeOffsEdit />
é um modal e renderizado como um filho do componente <PageManagerRequestsList />
. Essa estrutura nos permite exibir o modal sobre a página da lista enquanto mantém a página da lista visível em segundo plano.
Quando você navega para a rota /manager/requests/:id/edit
ou clica em um pedido de licença na lista, a página de detalhes do pedido de licença será exibida como um modal sobre a 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 e funcionalidades sensíveis. O sistema de autorização da 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. Neste passo, implementaremos a autorização e o 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 />
.
Agora, quando você faz login como um funcionário, não consegue ver o link da página Requests
na barra lateral, mas ainda pode acessar a rota /manager/requests
digitando a URL no navegador. Vamos adicionar uma proteção para evitar o 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 possui o papel de “gerente” antes de renderizar as rotas filhas. Se o usuário não tiver o papel de “gerente”, ele será redirecionado para a página de lista de folgas para funcionários.
Agora, quando você fizer login como um funcionário e tentar acessar a rota /manager/requests
, você será redirecionado para a página de lista de folgas dos funcionários.
Passo 7 — Implantando na plataforma de aplicativos DigitalOcean
Neste passo, vamos implantar a aplicação na Plataforma de Aplicativos DigitalOcean. Para 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
Faça login na 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, faça o commit dos arquivos com este comando:
Em seguida, adicione o repositório do GitHub como um repositório remoto com este comando:
Por fim, especifique que você deseja enviar seu código para a branch 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 deploy automático.
Implantando na Plataforma de Apps da DigitalOcean
Neste processo, você pegaria uma aplicação React e a prepararia para implantação pela Plataforma de Apps da DigitalOcean. Você vincularia seu repositório do GitHub à DigitalOcean, configuraria como o aplicativo será construído e, em seguida, criaria uma implantação inicial de um projeto. Após a implantação do projeto, as alterações adicionais que você fizer serão reconstruídas e atualizadas automaticamente.
No final desta etapa, você terá sua aplicação implantada na DigitalOcean com entrega contínua configurada.
Faça login na sua conta DigitalOcean e navegue até a página Apps. Clique no botão Criar App:
Se você ainda não conectou sua conta do GitHub ao DigitalOcean, você será solicitado a fazê-lo. Clique no botão Conectar ao GitHub. Uma nova janela será aberta, pedindo para você autorizar o DigitalOcean a acessar sua conta do GitHub.
Após autorizar o DigitalOcean, você será redirecionado de volta para a página de Apps do DigitalOcean. O próximo passo é selecionar o seu repositório do GitHub. Depois de selecionar o 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 a 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 a sua aplicação como desejar.
Aguarde a conclusão da compilação. Após a compilação ser concluída, pressione Aplicativo ao Vivo para acessar o seu projeto no navegador. Será o mesmo projeto que você testou 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 no App Platform.
Observação: Caso a implantação do seu build falhe, você pode configurar o comando de build no DigitalOcean para usar npm install --production=false && npm run build && npm prune --production
em vez de npm run build
Conclusão
Neste tutorial, construímos uma aplicação de Gestão de Recursos Humanos usando o Refine do zero e nos familiarizamos com como construir um aplicativo CRUD totalmente funcional.
Além disso, iremos demonstrar 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.