Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 14 additions & 38 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,47 +2,23 @@

<img src="https://accurate.com.br/wp-content/uploads/2020/06/logo-accurate-300.svg" alt="drawing" width="200"/>

Seja bem-vindo a [Accurate Software](https://accurate.com.br).

Temos diversas vagas para desenvolvedores: Frontend, Backend e Fullstack!

> Para conhecer melhor os candidatos, preparamos um desafio técnico. Não se preocupe em cumprir todos os requisitos propostos no desafio, este teste visa avaliar a sua capacidade de resolução de problemas. Abaixo serão apresentados dois desafios direcionados aos perfis frontend e backend, caso o seu perfil for voltado para fullstack fique a vontade em nos enviar uma solução completa abordando tanto frontend quanto backend!

## Instruções

1. Para começar o desafio, realize um fork no repositório: https://github.com/accurate-software/accurate-software.github.io

2. O desafio deverá set commitado no fork.

3. Após a finalização do desafio, solicite um pull request do fork no nosso repositório ;)

### Desafio Frontend

O seu desafio é realizar um desenvolvimento de uma aplicação frontend que compra os requisitos:

+ Consumo de API REST
+ CRUD ou listagem de algum recurso da API
+ Utilizar alguma API pública, podendo ser alguma do site: https://public-apis.xyz/

Vamos avaliar a sua capacidade como desenvolvedor frontend, observando os critérios:

+ Uso semântico do HTML
+ Estruturação do layout e tags CSS
+ Layout acessível e responsivo
+ Utilização de frameworks da atualizade, como: React, Vue, Angular ou algum outro de sua preferência.
+ Lembre-se de documentar a solução com um README.MD :)

### Desafio Backend

O seu desafio é realizar um desenvolvimento de uma API Rest para um site de achados e perfidos. Sua API deve conter as seguintes funcionalidades:
Desenvolvimento de uma API/REST para "Achados/Perdidos"

+ Cadastro de um "Achado"/"Perdido"
+ Atualização de histórico de um "Achado"/"Perdido"
+ Busca com opção de filtros, como por exemplo: Categoria
+ Relatório de cruzamento de informações "Achados"/"Perdidos", dado um categoria e um raio.
### Utilizei nesse projeto:
- TypeScript
- Node.JS
- Express
- express-fileupload
- PDFKit
- TypeOrm
- Mysql

### Nesse projeto há a criação de um item perdido com seu nome, localização, categoria e foto e a geração de um relatório com todos os itens

Fique a vontade para usar a linguagem e framework de sua preferência, como: Java, C# e Node! Porém se atente aos seguintes pontos:
### Para utiliza-lo dê um git clone no repositorio e um yarn para baixar todas as dependências. Estou utilizando o mysql mas você pode mudar a o Banco, se desejar, mudando suas configurações dentro do arquivo ormconfig.json e adicionar o drive do seu banco ao projeto.

+ Tratamento de erros e exceções
+ Clareza e clean code no desenvolvimento da solução
+ Documentação da solução - README.MD :)
### Aqui uma demonstração
https://youtu.be/x1f-NVtJysY
17 changes: 17 additions & 0 deletions ormconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"type": "mysql",
"host": "localhost",
"port": 3306,
"username": "vitu",
"password": "root",
"database": "projetos",
"migrations": [
"./src/database/migrations/*.ts"
],
"cli": {
"migrationsDir": "./src/database/migrations"
},
"entities": [
"./src/models/*.ts"
]
}
25 changes: 25 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"name": "users",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"build": "tsc",
"dev:server": "ts-node-dev --transpile-only --ignore-watch node_modules ./src/server.ts",
"typeorm": "ts-node-dev ./node_modules/typeorm/cli.js"
},
"dependencies": {
"express": "^4.17.1",
"express-fileupload": "^1.2.0",
"mysql": "^2.18.1",
"pdfkit": "^0.11.0",
"reflect-metadata": "^0.1.13",
"typeorm": "^0.2.29"
},
"devDependencies": {
"@types/express": "^4.17.9",
"@types/express-fileupload": "^1.1.5",
"@types/pdfkit": "^0.10.6",
"ts-node-dev": "^1.0.0",
"typescript": "^4.1.2"
}
}
3 changes: 3 additions & 0 deletions src/database/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import {createConnection} from 'typeorm';

createConnection();
63 changes: 63 additions & 0 deletions src/database/migrations/1606497498300-items.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { MigrationInterface, QueryRunner, Table } from "typeorm";

export class items1606497498300 implements MigrationInterface {

public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.createTable(
new Table({
name: "items",
columns: [
{
name: 'id',
type: 'serial',
isPrimary: true,
generationStrategy: 'increment',

},
{
name: 'name',
type: 'varchar',
isNullable: false,
},
{
name: 'category',
type: 'varchar',
isNullable: false,
},
{
name: "situation",
type: "integer",
default: 0
},
{
name: 'localization',
type: 'varchar',
isNullable: false,
},
{
name: 'photo',
type: 'varchar',
isNullable: false,
},
{
name: 'created_at',
type: 'timestamp',
default: 'now()',
},
{
name: 'updated_at',
isNullable: true,
type: 'timestamp',
default: 'null',
onUpdate: 'now()'
}
]
})
)
}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.dropTable('items');
}

}
39 changes: 39 additions & 0 deletions src/functions/generateRelatory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import ItemModel from "../models/itemModel";
import fs from 'fs';
import pdfkit from 'pdfkit';


const doc = new pdfkit();

export default (items: Array<ItemModel>): void => {
doc.fontSize(30);
doc.text("Relátorio de Items", 190);
doc.moveDown(1);
doc.fontSize(20);
doc.text("Encontrados", 210);
doc.moveDown(1);
items.forEach(item => {
if (item.situation === 1) {
const date = new Date(item.updated_at).toLocaleDateString('pt-BR', {
day: 'numeric',
month: 'short',
year: 'numeric'
})
doc.fontSize(12);
doc.text(`O item ${item.name} ainda já foi encontrado no dia ${date}`, 10);
doc.moveDown(2);
}
})
doc.fontSize(20);
doc.text("Não Encontrados", 210);
doc.moveDown(1);

items.forEach(item => {
doc.fontSize(12);
doc.text(`O item ${item.name} ainda não foi encontrado`, 10);
doc.moveDown(2);
})
doc.pipe(fs.createWriteStream('./uploads/relatory.pdf'));

doc.end()
}
11 changes: 11 additions & 0 deletions src/functions/mimetypeVerify.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export default (type: string) => {
const allowedFormats = [
"image/jpeg",
"image/jpg",
"image/png"
];

if (!allowedFormats.includes(type)) {
throw new Error("Invalid Format");
}
}
8 changes: 8 additions & 0 deletions src/functions/verifyFileSize.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export default (sizeFile: number) => {
const maxSize = 1 * 1000 * 1000;


if (sizeFile >= maxSize) {
throw new Error("File Too Large");
}
}
31 changes: 31 additions & 0 deletions src/models/itemModel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { Entity, Column, PrimaryGeneratedColumn, CreateDateColumn, UpdateDateColumn } from 'typeorm'


@Entity('items')
class ItemModel {
@PrimaryGeneratedColumn('increment')
id: number;

@Column()
name: string;

@Column()
category: string;

@Column()
localization: string;

@Column('int')
situation: number;

@Column()
photo: string;

@CreateDateColumn()
created_at: Date;

@UpdateDateColumn()
updated_at: Date;
}

export default ItemModel;
40 changes: 40 additions & 0 deletions src/repositories/ItemRepository.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { EntityRepository, Repository } from 'typeorm';;
import ItemModel from '../models/itemModel';

@EntityRepository(ItemModel)
class ItemRepository extends Repository<ItemModel>{

public async findByCategorie(categorie: string): Promise<ItemModel[] | null> {
const foundItem = await this.find({
where: [
{ category: categorie }
]
});


if (foundItem.length == 0) {
throw new Error("Category doesn't not found");

}

return foundItem;
}

public async showAllFounded() {
const foundItem = await this.find({
where: [
{ situation: 1 }
]
});


if (foundItem.length == 0) {
throw new Error("Categoria não encontrada");

}

return foundItem;
}
}

export default ItemRepository;
7 changes: 7 additions & 0 deletions src/routes/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { Request, Response, Router } from 'express';


const router = Router();


export default router
Loading