diff --git a/modulo6/case4-doghero/.gitignore b/modulo6/case4-doghero/.gitignore
new file mode 100644
index 0000000..8ece3ba
--- /dev/null
+++ b/modulo6/case4-doghero/.gitignore
@@ -0,0 +1,4 @@
+node_modules
+package-lock.json
+build
+.env
\ No newline at end of file
diff --git a/modulo6/case4-doghero/README.md b/modulo6/case4-doghero/README.md
new file mode 100644
index 0000000..5c9b73d
--- /dev/null
+++ b/modulo6/case4-doghero/README.md
@@ -0,0 +1,35 @@
+# DOG HERO
+## Documentação
+[Postman](https://documenter.getpostman.com/view/19296393/UzBqq65M)
+
+[Heroku](https://doghero-vsux.herokuapp.com)
+## Descrição
+
+O dog Hero é um case de projeto back-end para conclusão do bootcamp Labenu, onde é feita uma API para passeios de cachorros. Nessa API pode-se cadastrar passeios, iniciar um passeio, finalizar o passeio, mostrar quais passeios estão acontecendo no momento e retornar todos os passeios
+
+
+## Instalação
+
+
+
+```bash
+NPM install
+```
+
+
+## Desenvolvedor
+
+
+
diff --git a/modulo6/case4-doghero/package.json b/modulo6/case4-doghero/package.json
new file mode 100644
index 0000000..2fde628
--- /dev/null
+++ b/modulo6/case4-doghero/package.json
@@ -0,0 +1,37 @@
+{
+ "name": "case4-doghero",
+ "version": "1.0.0",
+ "main": "index.js",
+ "scripts": {
+ "start:dev": "ts-node-dev ./src/index.ts",
+ "start": "tsc && node ./build/index.js",
+ "build": "tsc",
+ "dev": "ts-node-dev ./src/index.ts",
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "keywords": [],
+ "author": "",
+ "license": "ISC",
+ "devDependencies": {
+ "@types/cors": "^2.8.12",
+ "@types/express": "^4.17.13",
+ "@types/knex": "^0.16.1",
+ "dotenv": "^16.0.1",
+ "knex": "^2.1.0",
+ "mysql": "^2.18.1",
+ "ts-node-dev": "^2.0.0",
+ "typescript": "^4.7.3"
+ },
+ "dependencies": {
+ "@types/bcryptjs": "^2.4.2",
+ "@types/express-serve-static-core": "^4.17.28",
+ "@types/jsonwebtoken": "^8.5.8",
+ "@types/uuid": "^8.3.4",
+ "bcryptjs": "^2.4.3",
+ "cors": "^2.8.5",
+ "express": "^4.18.1",
+ "jsonwebtoken": "^8.5.1",
+ "uuid": "^8.3.2"
+ },
+ "description": ""
+}
diff --git a/modulo6/case4-doghero/src/Business/DogWalkingBusiness.ts b/modulo6/case4-doghero/src/Business/DogWalkingBusiness.ts
new file mode 100644
index 0000000..9df87e3
--- /dev/null
+++ b/modulo6/case4-doghero/src/Business/DogWalkingBusiness.ts
@@ -0,0 +1,203 @@
+import { CalculatePrice } from './../Services/CalculatePrice';
+import { IdGenerator } from './../Services/IdGeneretor';
+import { CreateWalkInputDTO, Duration, FinishWalkInputDTO, StartWalkInputDTO, STATUS, Walk } from "../Model/Walk";
+import { FormataHoras } from "../Services/formatHours";
+import { dogWalkingRepository } from "./DogWalkingRepository";
+
+export default class DogWalkingBusiness {
+ private idGenerator: IdGenerator;
+ private dogWalkingData: dogWalkingRepository
+ private calculatePrice: CalculatePrice
+ private formatHours: FormataHoras
+
+ constructor(
+ dogWalkingDataImplementation: dogWalkingRepository
+ ) {
+ this.dogWalkingData = dogWalkingDataImplementation
+ this.idGenerator = new IdGenerator()
+ this.calculatePrice = new CalculatePrice()
+ this.formatHours = new FormataHoras()
+ }
+
+ create = async (input: CreateWalkInputDTO) => {
+ const {
+ date_schedule,
+ duration,
+ latitude,
+ longitude,
+ pets,
+ date_start,
+ date_end
+ } = input
+
+ if (!date_schedule || !duration || !latitude || !longitude || !pets || !date_start || !date_end) {
+ throw new Error("Insira todos os campos!")
+ }
+
+ if (duration !== Duration.HORA && duration !== Duration.MEIAHORA) {
+ throw new Error("Tempo de duração é inválido!")
+ }
+
+ if (date_start === date_end) {
+ throw new Error("O horário de início não pode ser igual ao de término")
+ }
+
+ const horaInicio = this.formatHours.FormataStringHora(date_start)
+ const horaTermino = this.formatHours.FormataStringHora(date_end)
+
+ if (horaInicio > horaTermino) {
+ throw new Error("O horário de início não pode ser maior que o horário de término")
+ }
+
+ if (date_end.length !== 8 || date_start.length !== 8) {
+ throw new Error("Insira um horário válido")
+ }
+
+ const id: string = this.idGenerator.generate()
+ const status = STATUS.INICIO
+ const preco = this.calculatePrice.calculatePrice(pets, duration)
+
+ const walk = new Walk(
+ id,
+ status,
+ date_schedule,
+ preco as number,
+ duration,
+ latitude,
+ longitude,
+ pets,
+ date_start,
+ date_end
+ )
+
+ await this.dogWalkingData.insert(walk)
+ }
+
+ startWalk = async (input: StartWalkInputDTO) => {
+ const { id, date_start } = input
+
+ if (!id || !date_start) {
+ throw new Error("Insira todos os campos!")
+ }
+
+ if (date_start.length !== 8) {
+ throw new Error("Insira um horário válido")
+ }
+
+ const walkId = await this.dogWalkingData.getWalkById(id)
+ const status = walkId.status
+
+ if (status !== STATUS.INICIO) {
+ throw new Error("Esse passeio já foi iniciado ou já foi finalizado")
+ }
+
+ if (!walkId) {
+ throw new Error("Esse passeio não existe!")
+ }
+
+ if (walkId) {
+ await this.dogWalkingData.start_walk(date_start, id)
+ }
+ }
+
+ finishWalk = async (input: FinishWalkInputDTO) => {
+ const { id, date_end } = input
+
+ if (!id || !date_end) {
+ throw new Error("Insira todos os campos!")
+ }
+
+ if (date_end.length !== 8) {
+ throw new Error("Insira um horário válido")
+ }
+
+ const walkId = await this.dogWalkingData.getWalkById(id)
+ const status = walkId.status
+ const duration = Number(walkId.duration)
+ const horarioInicio = walkId.date_start
+
+ const horarioInicioFormatado = this.formatHours.FormataStringHora(horarioInicio)
+ const horarioTerminoFormatado = this.formatHours.FormataStringHora(date_end)
+
+ if (status !== STATUS.ANDAMENTO) {
+ throw new Error("Esse passeio ainda não foi iniciado!")
+ }
+
+ if (duration === 30 && (horarioTerminoFormatado - horarioInicioFormatado) < (30 * 60)) {
+ throw new Error("Esse passeio não teve a duração mínima!")
+ }
+
+ if (duration === 60 && (horarioTerminoFormatado - horarioInicioFormatado) < (60 * 60)) {
+ throw new Error("Esse passeio não teve a duração mínima!")
+ }
+
+ if (horarioTerminoFormatado < horarioInicioFormatado) {
+ throw new Error("Não há como finalizar a corrida antes do horário de início!")
+ }
+
+ if (!walkId) {
+ throw new Error("Esse passeio não existe!")
+ }
+
+ if (walkId) {
+ await this.dogWalkingData.finish_walk(date_end, id)
+ }
+ }
+
+ show = async (input: string) => {
+ const walkId = input
+
+ if (!walkId) {
+ throw new Error("Insira todos os campos!")
+ }
+
+ const verifyWalkId = await this.dogWalkingData.getWalkById(walkId)
+
+ if (!verifyWalkId) {
+ throw new Error("Esse passeio não existe!")
+ }
+
+ const status = verifyWalkId.status
+
+ if (status !== STATUS.FINALIZADO) {
+ throw new Error("Esse passeio ainda não foi encerrado!")
+ }
+
+ const tempoInicio = verifyWalkId.date_start
+ const tempoTermino = verifyWalkId.date_end
+
+ const tempoInicioFormatado = this.formatHours.FormataStringHora(tempoInicio)
+ const tempoTerminoFormatado = this.formatHours.FormataStringHora(tempoTermino)
+
+ const diferenca = this.formatHours.diferenca(tempoTerminoFormatado, tempoInicioFormatado)
+ const diferencaFormatada = this.formatHours.segundosParaHora(diferenca)
+
+ return diferencaFormatada
+
+ }
+
+ index = async (page: number | any, walksPerPage: number | any) => {
+ const pageInput = page
+ const walksPerPageInput = walksPerPage
+
+ if (pageInput === 0) {
+ throw new Error("A página não pode ser igual a 0")
+ }
+
+ if ((pageInput || pageInput === "") && !walksPerPageInput) {
+ throw new Error("Insira todos os campos")
+ }
+
+ if (!pageInput && (walksPerPageInput || walksPerPageInput === "")) {
+ throw new Error("Insira todos os campos")
+ }
+
+ if (pageInput && walksPerPageInput) {
+ const result = await this.dogWalkingData.getAllWalksPaged(pageInput, walksPerPageInput)
+ return result
+ } else {
+ const result = await this.dogWalkingData.getAllWalks()
+ return result
+ }
+ }
+}
\ No newline at end of file
diff --git a/modulo6/case4-doghero/src/Business/DogWalkingRepository.ts b/modulo6/case4-doghero/src/Business/DogWalkingRepository.ts
new file mode 100644
index 0000000..12d33c5
--- /dev/null
+++ b/modulo6/case4-doghero/src/Business/DogWalkingRepository.ts
@@ -0,0 +1,10 @@
+import { Walk } from "../Model/Walk";
+
+export interface dogWalkingRepository {
+ insert(walk: Walk): Promise
+ start_walk(start_walk: string, id: string): Promise
+ finish_walk(finish_walk: string, id: string): Promise
+ getWalkById(id: string): Promise
+ getAllWalks(): Promise
+ getAllWalksPaged(page: number, walksPerPage: number): Promise
+}
\ No newline at end of file
diff --git a/modulo6/case4-doghero/src/Controller/DogWalkingController.ts b/modulo6/case4-doghero/src/Controller/DogWalkingController.ts
new file mode 100644
index 0000000..b5cc4dc
--- /dev/null
+++ b/modulo6/case4-doghero/src/Controller/DogWalkingController.ts
@@ -0,0 +1,107 @@
+import { Request, Response } from "express"
+import DogWalkingBusiness from "../Business/DogWalkingBusiness";
+import DogWalkingData from "../data/DogWalkingData";
+
+import { CreateWalkInputDTO, FinishWalkInputDTO, StartWalkInputDTO } from "../Model/Walk";
+
+export default class DogWalkingController {
+ private dogWalkingBusiness: DogWalkingBusiness
+ constructor(
+
+ ) {
+ this.dogWalkingBusiness = new DogWalkingBusiness(new DogWalkingData())
+ }
+
+ create = async (req: Request, res: Response) => {
+ const {
+ date_schedule,
+ duration,
+ latitude,
+ longitude,
+ pets,
+ date_start,
+ date_end
+ } = req.body
+
+ const input: CreateWalkInputDTO = {
+ date_schedule,
+ duration,
+ latitude,
+ longitude,
+ pets,
+ date_start,
+ date_end
+ }
+
+ try {
+ const walk = await this.dogWalkingBusiness.create(input)
+ res.send({ message: "Caminhada registrada com sucesso!", walk })
+ } catch (error: any) {
+ res.statusCode = 400
+ let message = error.sqlMessage || error.message
+ res.send({ message })
+ }
+ }
+
+ start = async (req: Request, res: Response) => {
+ const { id, date_start } = req.body
+
+ const input: StartWalkInputDTO = {
+ id,
+ date_start
+ }
+
+ try {
+ const walk = await this.dogWalkingBusiness.startWalk(input)
+ res.send({ message: "Caminhada iniciada!", walk })
+ } catch (error: any) {
+ res.statusCode = 400
+ let message = error.sqlMessage || error.message
+ res.send({ message })
+ }
+ }
+
+ finish = async (req: Request, res: Response) => {
+ const { id, date_end } = req.body
+
+ const input: FinishWalkInputDTO = {
+ id,
+ date_end
+ }
+
+ try {
+ const walk = await this.dogWalkingBusiness.finishWalk(input)
+ res.send({ message: "Caminhada Finalizada!", walk })
+ } catch (error: any) {
+ res.statusCode = 400
+ let message = error.sqlMessage || error.message
+ res.send({ message })
+ }
+ }
+
+ show = async (req: Request, res: Response) => {
+ const { id } = req.body
+
+ try {
+ const walkTime = await this.dogWalkingBusiness.show(id)
+ res.send({ walk: walkTime })
+ } catch (error: any) {
+ res.statusCode = 400
+ let message = error.sqlMessage || error.message
+ res.send({ message })
+ }
+ }
+
+ getWalks = async (req: Request, res: Response) => {
+ const { page, walksPerPage } = req.body
+
+ try {
+ const walks = await this.dogWalkingBusiness.index(page, walksPerPage)
+ res.send({ walks: walks })
+ } catch (error: any) {
+ res.statusCode = 400
+ let message = error.sqlMessage || error.message
+ res.send({ message })
+ }
+ }
+}
\ No newline at end of file
diff --git a/modulo6/case4-doghero/src/Error/BaseError.ts b/modulo6/case4-doghero/src/Error/BaseError.ts
new file mode 100644
index 0000000..ff52a46
--- /dev/null
+++ b/modulo6/case4-doghero/src/Error/BaseError.ts
@@ -0,0 +1,6 @@
+export abstract class BaseError extends Error {
+
+ constructor(public code: number, message: string) {
+ super(message)
+ }
+}
\ No newline at end of file
diff --git a/modulo6/case4-doghero/src/Error/CustomError.ts b/modulo6/case4-doghero/src/Error/CustomError.ts
new file mode 100644
index 0000000..fef32b8
--- /dev/null
+++ b/modulo6/case4-doghero/src/Error/CustomError.ts
@@ -0,0 +1,9 @@
+
+import { BaseError } from "./BaseError"
+
+export class CustomError extends BaseError {
+
+ constructor(public code: number, message: string) {
+ super(code, message)
+ }
+}
\ No newline at end of file
diff --git a/modulo6/case4-doghero/src/Model/Walk.ts b/modulo6/case4-doghero/src/Model/Walk.ts
new file mode 100644
index 0000000..1a86b63
--- /dev/null
+++ b/modulo6/case4-doghero/src/Model/Walk.ts
@@ -0,0 +1,109 @@
+export enum Duration {
+ MEIAHORA = "30",
+ HORA = "60",
+}
+
+export enum STATUS {
+ INICIO = "NÃO REALIZADO",
+ ANDAMENTO = "EM ANDAMENTO",
+ FINALIZADO = "FINALIZADO"
+}
+
+export type CreateWalkInputDTO = {
+ date_schedule: string,
+ duration: Duration,
+ latitude: number,
+ longitude: number,
+ pets: number,
+ date_start: string,
+ date_end: string
+}
+
+export type StartWalkInputDTO = {
+ id: string,
+ date_start: string
+}
+
+export type FinishWalkInputDTO = {
+ id: string,
+ date_end: string
+}
+
+export class Walk {
+
+ constructor(
+ private id: string,
+ private status: STATUS,
+ private date_schedule: string,
+ private price: number,
+ private duration: string,
+ private latitude: number,
+ private longitude: number,
+ private pets: number,
+ private date_start: string,
+ private date_end: string
+ ) {
+ this.id = id,
+ this.status = status,
+ this.date_schedule = date_schedule,
+ this.price = price,
+ this.duration = duration,
+ this.latitude = latitude,
+ this.longitude = longitude,
+ this.pets = pets,
+ this.date_start = date_start,
+ this.date_end = date_end
+ }
+ public getId() {
+ return this.id
+ }
+
+ public getStatus() {
+ return this.status
+ }
+
+ public getDataDeAgendamento() {
+ return this.date_schedule
+ }
+
+ public getprice() {
+ return this.price
+ }
+
+ public getduration() {
+ return this.duration
+ }
+
+ public getLatitude() {
+ return this.latitude
+ }
+
+ public getLongitude() {
+ return this.longitude
+ }
+
+ public getPets() {
+ return this.pets
+ }
+
+ public getHorarioInicio() {
+ return this.date_start
+ }
+
+ public getHorarioTermino() {
+ return this.date_end
+ }
+
+ static toWalkModel(data: any): Walk {
+ return new Walk(
+ data.id,
+ data.status,
+ data.date_schedule,
+ data.price, data.duration,
+ data.latitude,
+ data.longitude,
+ data.pets,
+ data.date_start,
+ data.date_end)
+ }
+}
\ No newline at end of file
diff --git a/modulo6/case4-doghero/src/Routes/dogWalkerRouter.ts b/modulo6/case4-doghero/src/Routes/dogWalkerRouter.ts
new file mode 100644
index 0000000..0ef3424
--- /dev/null
+++ b/modulo6/case4-doghero/src/Routes/dogWalkerRouter.ts
@@ -0,0 +1,14 @@
+
+import express from "express";
+import DogWalkingController from "../Controller/DogWalkingController";
+
+
+export const dogWalkingRouter = express.Router();
+
+const dogWalkingController = new DogWalkingController();
+
+dogWalkingRouter.post("/create", dogWalkingController.create);
+dogWalkingRouter.post("/start", dogWalkingController.start)
+dogWalkingRouter.post("/finish", dogWalkingController.finish)
+dogWalkingRouter.get("/show", dogWalkingController.show)
+dogWalkingRouter.get("/walks", dogWalkingController.getWalks)
\ No newline at end of file
diff --git a/modulo6/case4-doghero/src/Services/Authenticator.ts b/modulo6/case4-doghero/src/Services/Authenticator.ts
new file mode 100644
index 0000000..4a859a0
--- /dev/null
+++ b/modulo6/case4-doghero/src/Services/Authenticator.ts
@@ -0,0 +1,32 @@
+import * as jwt from "jsonwebtoken";
+
+export class Authenticator {
+ public generateToken(input: AuthenticationData,
+ expiresIn: string = process.env.ACCESS_TOKEN_EXPIRES_IN!): string {
+ const token = jwt.sign(
+ {
+ id: input.id,
+ role: input.role
+ },
+ process.env.JWT_KEY as string,
+ {
+ expiresIn,
+ }
+ );
+ return token;
+ }
+
+ public getData(token: string): AuthenticationData {
+ const payload = jwt.verify(token, process.env.JWT_KEY as string) as any;
+ const result = {
+ id: payload.id,
+ role: payload.role
+ };
+ return result;
+ }
+}
+
+export interface AuthenticationData {
+ id: string;
+ role?: string;
+}
\ No newline at end of file
diff --git a/modulo6/case4-doghero/src/Services/CalculatePrice.ts b/modulo6/case4-doghero/src/Services/CalculatePrice.ts
new file mode 100644
index 0000000..279fef7
--- /dev/null
+++ b/modulo6/case4-doghero/src/Services/CalculatePrice.ts
@@ -0,0 +1,17 @@
+export class CalculatePrice {
+ public calculatePrice(pets: number, duration: string) {
+ if (pets === 1 && duration === "30") {
+ const preco = 25
+ return preco
+ } else if (pets > 1 && duration === "30") {
+ const preco = 25 + (pets - 1) * 15
+ return preco
+ } else if (pets === 1 && duration === "60") {
+ const preco = 35
+ return preco
+ } else if (pets > 1 && duration === "60") {
+ const preco = 35 + (pets - 1) * 20
+ return preco
+ }
+ }
+}
\ No newline at end of file
diff --git a/modulo6/case4-doghero/src/Services/HashManager.ts b/modulo6/case4-doghero/src/Services/HashManager.ts
new file mode 100644
index 0000000..aa34c41
--- /dev/null
+++ b/modulo6/case4-doghero/src/Services/HashManager.ts
@@ -0,0 +1,17 @@
+import * as bcrypt from "bcryptjs";
+
+
+export class HashManager {
+
+ public async hash(text: string): Promise {
+ const rounds = 12;
+ const salt = await bcrypt.genSalt(rounds);
+ const result = await bcrypt.hash(text, salt);
+ return result;
+ }
+
+ public async compare(text: string, hash: string): Promise {
+ return await bcrypt.compare(text, hash);
+ }
+
+}
\ No newline at end of file
diff --git a/modulo6/case4-doghero/src/Services/IdGeneretor.ts b/modulo6/case4-doghero/src/Services/IdGeneretor.ts
new file mode 100644
index 0000000..077e67c
--- /dev/null
+++ b/modulo6/case4-doghero/src/Services/IdGeneretor.ts
@@ -0,0 +1,7 @@
+import { v4 } from "uuid";
+
+export class IdGenerator {
+ public generate(): string {
+ return v4()
+ }
+}
\ No newline at end of file
diff --git a/modulo6/case4-doghero/src/Services/TokenGenerator.ts b/modulo6/case4-doghero/src/Services/TokenGenerator.ts
new file mode 100644
index 0000000..1e212ba
--- /dev/null
+++ b/modulo6/case4-doghero/src/Services/TokenGenerator.ts
@@ -0,0 +1,34 @@
+import * as jwt from "jsonwebtoken";
+import dotenv from "dotenv";
+
+dotenv.config();
+
+export class TokenGenerator {
+ private static expiresIn: number = 1200;
+
+ public generate = (input: AuthenticationData): string => {
+ const newToken = jwt.sign(
+ {
+ id: input.id,
+ role: input.role,
+ },
+ process.env.JWT_KEY as string,
+ {
+ expiresIn: TokenGenerator.expiresIn,
+ }
+ );
+ return newToken;
+ };
+
+ public verify(token: string) {
+ const payload = jwt.verify(token, process.env.JWT_KEY as string) as any;
+ const result = { id: payload.id, role: payload.role };
+ return result;
+ }
+}
+
+export interface AuthenticationData {
+ id: string;
+ role: string;
+}
+
diff --git a/modulo6/case4-doghero/src/Services/formatData.ts b/modulo6/case4-doghero/src/Services/formatData.ts
new file mode 100644
index 0000000..e1852db
--- /dev/null
+++ b/modulo6/case4-doghero/src/Services/formatData.ts
@@ -0,0 +1,10 @@
+
+export class FormataData {
+ public FormataStringData(data: string) {
+ var dia = data.split("/")[0];
+ var mes = data.split("/")[1];
+ var ano = data.split("/")[2];
+
+ return ano + '-' + ("0" + mes).slice(-2) + '-' + ("0" + dia).slice(-2);
+ }
+}
\ No newline at end of file
diff --git a/modulo6/case4-doghero/src/Services/formatHours.ts b/modulo6/case4-doghero/src/Services/formatHours.ts
new file mode 100644
index 0000000..1bb8e1f
--- /dev/null
+++ b/modulo6/case4-doghero/src/Services/formatHours.ts
@@ -0,0 +1,50 @@
+export class FormataHoras {
+ public FormataStringHora(hora: string) {
+ var h = hora.split(":")[0];
+ var m = hora.split(":")[1];
+ var s = hora.split(":")[2];
+
+ const hr = Number(h)
+ const min = Number(m)
+ const seg = Number(s)
+
+ const formatada = (hr * 3600) + (min * 60) + (seg);
+
+ return formatada
+ }
+
+ public segundosParaHora(seg: number) {
+ var hora = Math.floor((seg / 3600))
+ var horaString = hora.toString()
+
+ var minuto = Math.floor((seg % 3600 / 60))
+ var minutoString = minuto.toString()
+
+ var segundo = ((seg % 3600) % 60)
+ var segundoString = segundo.toString()
+
+ function duasCasas(numero: string) {
+ if (Number(numero) <= 9) {
+ var numero = "0" + numero
+ }
+ if (Number(numero) === 0) {
+ var numero = "00"
+ }
+ return numero;
+ }
+
+ var horas = duasCasas(horaString) + ":" + duasCasas(minutoString) + ":" + duasCasas(segundoString)
+ return horas;
+ }
+
+ public diferenca(h1: number, h2: number) {
+ return h1 - h2
+ }
+
+ public data_format(s: number) {
+ const h = Math.floor(s / 3600);
+ const min = Math.floor((s - (h * 3600)) / 60);
+ s = s - (Math.floor(s / 60) * 60);
+ return h + "h " + min + "min " + s + "s";
+ }
+}
\ No newline at end of file
diff --git a/modulo6/case4-doghero/src/data/BaseDatabase.ts b/modulo6/case4-doghero/src/data/BaseDatabase.ts
new file mode 100644
index 0000000..cd30038
--- /dev/null
+++ b/modulo6/case4-doghero/src/data/BaseDatabase.ts
@@ -0,0 +1,21 @@
+import knex from 'knex'
+import dotenv from 'dotenv'
+
+dotenv.config()
+
+export abstract class BaseDatabase {
+ protected static connection = knex({
+ client: 'mysql',
+ connection: {
+ host: process.env.DB_HOST,
+ user: process.env.DB_USER,
+ password: process.env.DB_PASSWORD,
+ database: process.env.DB_SCHEMA,
+ port: 3303,
+ multipleStatements: true
+ }
+ })
+ public static async destroyConnection(): Promise {
+ await BaseDatabase.connection.destroy();
+ }
+}
\ No newline at end of file
diff --git a/modulo6/case4-doghero/src/data/DogWalkingData.ts b/modulo6/case4-doghero/src/data/DogWalkingData.ts
new file mode 100644
index 0000000..029f3f9
--- /dev/null
+++ b/modulo6/case4-doghero/src/data/DogWalkingData.ts
@@ -0,0 +1,83 @@
+import { Walk } from './../Model/Walk';
+import { BaseDatabase } from "./BaseDatabase"
+
+
+export default class DogWalkingData extends BaseDatabase {
+ protected TABLE_NAME = "Dog_Walking"
+
+ insert = async (walk: Walk) => {
+ try {
+ await BaseDatabase
+ .connection(this.TABLE_NAME)
+ .insert(walk)
+
+ return walk
+ } catch (error: any) {
+ throw new Error(error.message)
+ }
+ }
+
+ start_walk = async (start_walk: string, id: string): Promise => {
+ try {
+ const result = await BaseDatabase.connection.raw(`
+ UPDATE ${this.TABLE_NAME} SET horario_inicio = '${start_walk}', status = "EM ANDAMENTO" WHERE id = '${id}'
+ `
+ );
+
+ return result[0]
+ } catch (error: any) {
+ throw new Error(error.sqlMessage || error.message)
+ }
+ }
+
+ finish_walk = async (finish_walk: string, id: string): Promise => {
+ try {
+ const result = await BaseDatabase.connection.raw(`
+ UPDATE ${this.TABLE_NAME} SET horario_termino = '${finish_walk}', status = "FINALIZADO" WHERE id = '${id}'
+ `
+ );
+ return result[0]
+ } catch (error: any) {
+ throw new Error(error.sqlMessage || error.message)
+ }
+ }
+
+ getWalkById = async (id: string): Promise => {
+ try {
+
+ const queryResult = await BaseDatabase.connection(this.TABLE_NAME)
+ .select()
+ .where('id', id)
+
+ return queryResult[0]
+ } catch (error: any) {
+ throw new Error(error.sqlMessage || error.message)
+ }
+ }
+
+ getAllWalks = async (): Promise => {
+ try {
+ const result = await BaseDatabase.connection.raw(`
+ SELECT * FROM ${this.TABLE_NAME} ORDER BY status ASC
+ `
+ );
+
+ return result[0]
+ } catch (error: any) {
+ throw new Error(error.sqlMessage || error.message)
+ }
+ }
+
+ getAllWalksPaged = async (page: number, walksPerPage: number): Promise => {
+ try {
+ const result = await BaseDatabase.connection.raw(`
+ SELECT * FROM ${this.TABLE_NAME} ORDER BY status ASC LIMIT ${page - 1}, ${walksPerPage}
+ `
+ );
+
+ return result[0]
+ } catch (error: any) {
+ throw new Error(error.sqlMessage || error.message)
+ }
+ }
+}
\ No newline at end of file
diff --git a/modulo6/case4-doghero/src/data/app.ts b/modulo6/case4-doghero/src/data/app.ts
new file mode 100644
index 0000000..0d9aecf
--- /dev/null
+++ b/modulo6/case4-doghero/src/data/app.ts
@@ -0,0 +1,20 @@
+import express from 'express';
+import dotenv from 'dotenv';
+
+import { AddressInfo } from "net";
+
+
+dotenv.config();
+
+export const app = express();
+
+app.use(express.json());
+
+export const server = app.listen(process.env.PORT || 3003, () => {
+ if (server) {
+ const address = server.address() as AddressInfo;
+ console.log(`Server is running in http://localhost:${address.port}`);
+ } else {
+ console.error(`Failure upon starting server.`);
+ }
+});
\ No newline at end of file
diff --git a/modulo6/case4-doghero/src/index.ts b/modulo6/case4-doghero/src/index.ts
new file mode 100644
index 0000000..6e04629
--- /dev/null
+++ b/modulo6/case4-doghero/src/index.ts
@@ -0,0 +1,4 @@
+import { app } from "./data/app";
+import { dogWalkingRouter } from "./Routes/dogWalkerRouter";
+
+app.use("/doghero", dogWalkingRouter);
\ No newline at end of file
diff --git a/modulo6/case4-doghero/tsconfig.json b/modulo6/case4-doghero/tsconfig.json
new file mode 100644
index 0000000..38600d2
--- /dev/null
+++ b/modulo6/case4-doghero/tsconfig.json
@@ -0,0 +1,11 @@
+{
+ "compilerOptions": {
+ "target": "es6" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */,
+ "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */,
+ "outDir": "./build" /* Redirect output structure to the directory. */,
+ "rootDir": "./src" /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */,
+ "strict": true /* Enable all strict type-checking options. */,
+ "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
+ "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
+ }
+ }
\ No newline at end of file