Aplicação front-end desenvolvida como parte do desafio técnico da Top Solutions, implementando um sistema completo de cadastro de usuários com autenticação e operações de CRUD.
- Vue.js 3 com Composition API
- Vue Router 4
- TypeScript
- Vite
- PrimeVue 4 + PrimeIcons
- Tailwind CSS 4
- ViaCEP API
- LocalStorage + JWT (simulado para front-end) (persistência de dados e autenticação)
- Login com email e senha (bônus do desafio)
- Token JWT simulado gerado e armazenado no
localStorage, com verificação de assinatura e expiração (TTL configurável viaVITE_AUTH_TOKEN_TTL_MSno.env) - Proteção de rotas via
beforeEachno Vue Router — acesso direto por URL sem autenticação redireciona para/login - Logout invalida o token e redireciona para a tela de login
- Criar usuário com formulário validado
- Listar usuários ordenados do mais recente ao mais antigo
- Editar usuário com formulário pré-preenchido
- Excluir usuário com modal de confirmação — o card some imediatamente sem reload
- Preenchimento automático de Rua, Bairro, Cidade e Estado ao informar o CEP
- Tratamento de CEP inválido ou não encontrado com mensagem de erro
- Todos os campos são obrigatórios
- Nome: limite de 100 caracteres
- Data de nascimento: máscara
DD/MM/AAAAcom validação de data real - CEP: validado via ViaCEP API
- Função: dropdown com opções pré-definidas
- Email no login: validação do email digitado
- Senha no login: validação do tamanho mínimo da senha inserida
- Campos inválidos destacados em vermelho com mensagens de erro
- Idade calculada automaticamente a partir da data de nascimento
- Avatar do usuário definido pelo gênero informado (masculino / feminino)
- Endereços preenchidos automaticamente pelo CEP são somente leitura
- Layout adaptado para mobile e desktop
- Cards da listagem colapsam para
flex-colem telas pequenas com rótulos inline e exibe os dados emgridem telas maiores que 1024px (64rem)
- Node.js v18 ou superior
- Gerenciador de pacotes:
npm,yarn,pnpmoubun(o arquivo.locknão está versionado — use o de sua preferência)
As credenciais e configurações sensíveis são lidas de um arquivo .env na raiz do projeto. Esse arquivo não é versionado — copie o exemplo e preencha com os valores desejados:
cp .env.example .envO .env.example já está disponível no repositório com as chaves necessárias:
VITE_AUTH_EMAIL=
VITE_AUTH_PASSWORD=
VITE_AUTH_SECRET=
VITE_AUTH_TOKEN_KEY=
VITE_AUTH_TOKEN_TTL_MS=| Variável | Descrição | Exemplo Sugerido |
|---|---|---|
| VITE_AUTH_EMAIL | E-mail predefinido para realizar o login no sistema. | seu@email.com |
| VITE_AUTH_PASSWORD | Senha correspondente ao e-mail de administração. | SenhaQualquer@1234 |
| VITE_AUTH_SECRET | Chave secreta utilizada pelo algoritmo XOR para "assinar" o token JWT simulado. | sua-chave-secreta-2026 |
| VITE_AUTH_TOKEN_KEY | Nome da chave que será utilizada para salvar o token no localStorage. | auth_token |
| VITE_AUTH_TOKEN_TTL_MS | Tempo de vida do token em milissegundos (Tempo de expiração). | 1500000 (25 minutos) |
Atenção: o Vite só expõe variáveis prefixadas com
VITE_para o código do cliente. Variáveis sem esse prefixo ficam invisíveis no bundle final.
# 1. Clone o repositório
git clone https://github.com/seu-usuario/toprecruta-front-end.git
cd toprecruta-front-end
# 2. Configure as variáveis de ambiente
cp .env.example .env
# Edite o .env com as credenciais desejadas
# 3. Instale as dependências (use o gerenciador de sua preferência)
npm install
# ou
yarn install
# ou
pnpm install
# ou
bun install
# 4. Inicie o servidor de desenvolvimento
npm run dev
# ou
yarn run dev
# ou
pnpm run dev
# ou
bun run dev
# 5. Acesse no navegador
http://localhost:5173npm run build
# ou
yarn run build
# ou
pnpm run build
# ou
bun run buildO output será gerado na pasta dist/.
| Campo | Valor |
|---|---|
VITE_AUTH_EMAIL |
|
| Senha | VITE_AUTH_PASSWORD |
- Acesse
http://localhost:5173— você será redirecionado para/login - Tente acessar
/diretamente sem autenticar — confirme o redirecionamento para/login - Faça login com as credenciais acima
- Cadastre um novo usuário preenchendo todos os campos; informe um CEP válido e veja o endereço ser preenchido automaticamente
- Confirme que o novo usuário aparece no topo da lista em
/ - Edite o usuário clicando no ícone de lápis — os campos devem estar pré-preenchidos, incluindo a data de nascimento
- Exclua um usuário clicando no ícone de lixeira, confirme o modal e veja o card ser removido imediatamente
- Clique em Sair no cabeçalho — confirme o redirecionamento para
/logine que o acesso às rotas protegidas foi bloqueado - Recarregue a página durante uma sessão ativa — a sessão deve ser mantida (token ainda válido)
src/
├── assets/ # Avatares e imagens estáticas
├── components/ # Header e Footer
├── router/ # Configuração de rotas e guards
├── services/ # authService, userService, viaCepService
├── types/ # Tipagens TypeScript (User, ViaCepAddress)
└── views/ # Login, Dashboard, UserForm
JWT simulado sem backend
O desafio é 100% front-end. O authService gera um token no formato header.payload.signature em base64url com assinatura XOR determinística, o que impede adulteração manual do token no localStorage. Em produção, a assinatura seria feita por um backend com HMAC-SHA256 real.
Máscara de data sem dependências externas
O DatePicker do PrimeVue não insere barras ao digitar. A solução adotada foi um InputText com função de máscara reativa (DD/MM/AAAA), convertida para ISO (YYYY-MM-DD) apenas no momento do submit.
Parsing de data sem new Date(isoString)
new Date("2000-01-15") interpreta a string como UTC midnight, causando deslocamento de fuso horário no navegador. A conversão é feita manualmente via regex para evitar o problema.
Variáveis de ambiente com .env
Credenciais de autenticação (email, senha, secret de assinatura do JWT) e configurações do token (TOKEN_KEY, TOKEN_TTL_MS) são lidas via import.meta.env do Vite. O arquivo .env não é versionado — o repositório inclui apenas o .env.example com as chaves sem valores, para que cada ambiente configure os seus próprios segredos sem risco de exposição.
Grid de listagem com CSS nativo
O layout dos cards usa grid-template-columns com minmax e larguras fixas em vez de grid-cols-12, garantindo alinhamento preciso entre o cabeçalho de colunas e os valores dos cards independente do conteúdo.