Esta é uma aplicação full stack desenvolvida com Node.js, TypeScript, Express no backend e TypeScript, React e Vite no frontend. MongoDB como banco principal. Para execução, é necessário possuir o docker e o docker-compose em sua máquina.
Para iniciar a aplicação, siga estas etapas:
Abra um terminal com acesso ao git e:
Clone o projeto
git clone https://github.com/psnavega/device-task.git
Entre na pasta do projeto
cd device-task
Executa o projeto
docker-compose up
A aplicação backend estará disponível em http://localhost:3001 e a aplicação frontend em http://localhost:5173.
Para executar os testes unitários no backend, siga estas etapas:
docker ps
Encontre o ID do contêiner do backend na lista de contêineres em execução.
docker exec -it <ID_DO_CONTAINER> npm run test
Tomei a liberdade de criar um script de primeira carga para que o usuário que estiver executando a aplicação não precise inserir dispositivo por dispositivo
Como podem ver, temos uma tabela com 7 colunas, sendo elas:
- IMEI - identificado único do dispositivo
- Tag - a tag do status atual ou do último status emitido por aquele aparelho
- Valor - Detalhe emitido pelo aparelho
- Última atualização - Aponta para o momento em que recebemos o último ping do dispositivo
- Status de atraso - Caso o dispositivo não tenha realizado um report a partir dos 30 minutos, assumimos pode estar em falha e nesse caso
- Intervalo maior que 30 minutos e menor que 24h - Warning
- Intervalo maior que maior que 24h - Critical
- Existe erro - Foi reportado um erro pelo dispositivo?
- Detalhes do erro - Essa coluna só estará preenchida quando hasError for verdadeiro, nesse caso teremos um botão habilitado que abri'ra um modal com os detalhes do erro
O que acontece ao clicar em detalhes?
Abrimos um modal com os detalhes de todos os erros catalogados na aplicação, e suas soluções - caso já tenham sido solucionadas
Abaixo uma mensagem descrevendo qual o erro do usuário e solução a ser aplicada
Nessa versão MVP ainda não possuímos a possibilidade de registrar soluções de erro, contudo, em casos de error ser BAD_CONFIGURATION temos uma mensagem personalizada ao usuário informando para buscar uma assistência técnica.
Essa página nos dá um feedback visual sobre a relação de dispositivos ligados x desligados a partir de um gráfico de colunas/p>
Aqui estão alguns exemplos de uso das rotas do backend:
Endpoint: PATCH /api/v1/iot/:imei
Exemplo de uso:
curl -X PATCH -H "Content-Type: application/json" -d '{"tag":"poweron", "value":100}' http://localhost:3001/api/v1/iot/123456789
Retorno esperado
{
message: 'IOT updated'
}
Endpoint: POST /api/v1/iot
Exemplo de uso:
curl -X POST -H "Content-Type: application/json" -d '{"tag":"poweroff", "imei":"987654321", "value":200}' http://localhost:3001/api/v1/iot
Endpoint: GET /api/v1/iots?status=&imei=
Exemplo de uso:
curl http://localhost:3001/api/v1/iot?status=on-and-offs&imei=
- has-reports
- has-no-reports
- on-and-offs
- errors
Retorno esperado
{
"message": "success",
"data": [
{
"_id": "65d7af56584fab4573af05e3",
"tag": "poweron",
"imei": "12345",
"createdAt": "2024-02-22T20:32:22.201Z",
"updatedAt": "2024-02-22T20:32:22.201Z",
"__v": 0
},
...
{
"_id": "65d7afb086087c5b4072be55",
"tag": "poweron",
"imei": "12345",
"createdAt": "2024-02-22T20:33:52.083Z",
"updatedAt": "2024-02-22T20:33:52.083Z",
"__v": 0
},
]
}
{
tag: poweron
imei: string
value: 1
}
Retorno esperado
{
message: "success",
data: {
"_id": "65d7afb086087c5b4072be55",
"tag": "poweron",
"imei": "12345",
"createdAt": "2024-02-22T20:33:52.083Z",
"updatedAt": "2024-02-22T20:33:52.083Z",
"__v": 0
}
}
- poweron
- poweroff
- timebased
- errorCode
Essa rota cataloga todos os erros registrados nos dispositivos para que sejam renderizados em uma tabela no front-end e, caso queiramos, podemos ampliar a aplicação para que possa ser possível cadastrar sugestões de soluções para cada erro catalogável para que dessa maneira o usuário saiba o que fazer quando se deparar com um erro já conhecido e solucionado.
GET http://localhost:3001/api/v1/iot/errors
Retorno esperado
{
"message": "success",
"data": [
"MEMORY_FAILURE",
"BAD_CONFIGURATION"
]
}
Todas as rotas retornam um erro com formato padrão contendo a descrição do erro como detalhes e o status no header da requisição.
Retorno esperado
{
"error": true,
"message": "\"status\" must be one of [has-reports, has-no-reports, on-and-offs, errors]"
}
Note que nesse exemplo o status do retorno está como 422, ou seja entidade não processável. Ou seja, é esperado que a aplicação saiba lidar com erros e tratá-los
Pela natureza da aplicação optei por deixar a aplicação pública, não havendo necessidade de complefixicar o fluxo
Por se tratar de um MVP/Protótipo priorizei a funcionalidade e com isso não criei paginação para os registros também
Optei por não desenvolver a funcionalidade de permitir que o usuário possa associar uma sugestão a um erro por entender que isso seria uma nova feature
MIT
Patrick Navega