├── backend ├── src │ ├── auth │ │ ├── entities │ │ │ └── auth.entity.ts │ │ ├── dto │ │ │ ├── create-auth.dto.ts │ │ │ └── update-auth.dto.ts │ │ ├── guards │ │ │ ├── jwt-auth.guard.ts │ │ │ └── local-auth.guard.ts │ │ ├── auth.controller.ts │ │ ├── strategies │ │ │ ├── local.strategy.ts │ │ │ └── jwt.strategy.ts │ │ ├── auth.module.ts │ │ └── auth.service.ts │ ├── types │ │ └── types.ts │ ├── app.service.ts │ ├── user │ │ ├── dto │ │ │ ├── update-user.dto.ts │ │ │ └── create-user.dto.ts │ │ ├── user.controller.ts │ │ ├── user.module.ts │ │ ├── entities │ │ │ └── user.entity.ts │ │ └── user.service.ts │ ├── category │ │ ├── dto │ │ │ ├── update-category.dto.ts │ │ │ └── create-category.dto.ts │ │ ├── category.module.ts │ │ ├── entities │ │ │ └── category.entity.ts │ │ ├── category.controller.ts │ │ └── category.service.ts │ ├── transaction │ │ ├── dto │ │ │ ├── update-transaction.dto.ts │ │ │ └── create-transaction.dto.ts │ │ ├── transaction.module.ts │ │ ├── entities │ │ │ └── transaction.entity.ts │ │ ├── transaction.controller.ts │ │ └── transaction.service.ts │ ├── app.controller.ts │ ├── exchangeRate │ │ ├── entities │ │ │ └── exchangeRate.entity.ts │ │ ├── exchangeRate.controller.ts │ │ ├── exchangeRate.module.ts │ │ └── exchangeRate.service.ts │ ├── main.ts │ ├── guard │ │ └── author.guard.ts │ └── app.module.ts ├── tsconfig.build.json ├── .prettierrc ├── Dockerfile ├── .dockerignore ├── nest-cli.json ├── .env.example ├── tsconfig.json ├── .eslintrc.js ├── .gitignore ├── package.json └── README.md ├── frontend ├── src │ ├── vite-env.d.ts │ ├── assets │ │ ├── protected-icon.png │ │ ├── page_not_found.png.png │ │ └── react.svg │ ├── helpers │ │ ├── currency.hepler.ts │ │ ├── date.helper.ts │ │ └── localStorage.helper.ts │ ├── hooks │ │ └── useAuth.ts │ ├── api │ │ └── axios.api.ts │ ├── store │ │ ├── hooks.ts │ │ ├── store.ts │ │ └── user │ │ │ └── userSlice.ts │ ├── pages │ │ ├── Layout.tsx │ │ ├── ErrorPage.tsx │ │ ├── Home.tsx │ │ ├── Auth.tsx │ │ ├── Transactions.tsx │ │ └── Categories.tsx │ ├── main.tsx │ ├── components │ │ ├── Notes.tsx │ │ ├── ProtectedRoute.tsx │ │ ├── Chart.tsx │ │ ├── CategoryModal.tsx │ │ ├── Header.tsx │ │ ├── TransactionForm.tsx │ │ ├── Calculator.tsx │ │ ├── TransactionTable.tsx │ │ └── ChartCambio.tsx │ ├── services │ │ └── auth.service.ts │ ├── App.tsx │ ├── types │ │ └── types.ts │ ├── index.css │ └── router │ │ └── router.tsx ├── .prettierrc ├── postcss.config.js ├── public │ ├── icons8-exchange-blue-ui-16.png │ ├── icons8-exchange-blue-ui-32.png │ └── icons8-exchange-blue-ui-96.png ├── .dockerignore ├── tsconfig.json ├── vite.config.ts ├── Dockerfile ├── .gitignore ├── tsconfig.node.json ├── tailwind.config.js ├── .eslintrc.cjs ├── tsconfig.app.json ├── index.html ├── README.md └── package.json ├── scripts ├── ecs │ ├── unix │ │ ├── deploy.sh │ │ ├── check-disponibilidade.sh │ │ └── build.sh │ └── windows │ │ ├── deploy.bat │ │ ├── check-disponibilidade.bat │ │ └── build.bat ├── start-session-bash.sh ├── criar_role_ssm.sh ├── user_data_ec2_zona_a.sh └── validar_recursos_zona_a.sh ├── docker-compose.yml └── README.md /backend/src/auth/entities/auth.entity.ts: -------------------------------------------------------------------------------- 1 | export class Auth {} 2 | -------------------------------------------------------------------------------- /frontend/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /backend/src/auth/dto/create-auth.dto.ts: -------------------------------------------------------------------------------- 1 | export class CreateAuthDto {} 2 | -------------------------------------------------------------------------------- /backend/src/types/types.ts: -------------------------------------------------------------------------------- 1 | export interface IUser { 2 | id: string; 3 | email: string; 4 | } -------------------------------------------------------------------------------- /frontend/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": false, 3 | "useTabs": true, 4 | "singleQuote": true 5 | } -------------------------------------------------------------------------------- /frontend/postcss.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /scripts/ecs/unix/deploy.sh: -------------------------------------------------------------------------------- 1 | ./build.sh 2 | aws ecs update-service --cluster [SEU_CLUSTER] --service [SEU_SERVICE] --force-new-deployment -------------------------------------------------------------------------------- /backend/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "exclude": ["node_modules", "test", "dist", "**/*spec.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /frontend/src/assets/protected-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hiag0liveira/ExpenseControlApp/HEAD/frontend/src/assets/protected-icon.png -------------------------------------------------------------------------------- /backend/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "trailingComma": "all", 4 | "semi": false, 5 | "useTabs": true, 6 | "tabWidth": 4 7 | } -------------------------------------------------------------------------------- /frontend/src/assets/page_not_found.png.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hiag0liveira/ExpenseControlApp/HEAD/frontend/src/assets/page_not_found.png.png -------------------------------------------------------------------------------- /frontend/public/icons8-exchange-blue-ui-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hiag0liveira/ExpenseControlApp/HEAD/frontend/public/icons8-exchange-blue-ui-16.png -------------------------------------------------------------------------------- /frontend/public/icons8-exchange-blue-ui-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hiag0liveira/ExpenseControlApp/HEAD/frontend/public/icons8-exchange-blue-ui-32.png -------------------------------------------------------------------------------- /frontend/public/icons8-exchange-blue-ui-96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hiag0liveira/ExpenseControlApp/HEAD/frontend/public/icons8-exchange-blue-ui-96.png -------------------------------------------------------------------------------- /frontend/src/helpers/currency.hepler.ts: -------------------------------------------------------------------------------- 1 | export const formatToUSD = new Intl.NumberFormat('en-US', { 2 | style: 'currency', 3 | currency: 'USD', 4 | }) -------------------------------------------------------------------------------- /scripts/ecs/windows/deploy.bat: -------------------------------------------------------------------------------- 1 | call build.bat 2 | aws ecs update-service --cluster [SEU_CLUSTER] --service [SEU_SERVICE] --force-new-deployment --profile [SEU_PROFILE] 3 | -------------------------------------------------------------------------------- /backend/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:latest 2 | 3 | WORKDIR /api 4 | 5 | COPY package*.json ./ 6 | 7 | RUN npm install 8 | 9 | COPY . . 10 | 11 | EXPOSE 3000 12 | 13 | CMD ["npm", "start"] 14 | -------------------------------------------------------------------------------- /backend/src/app.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@nestjs/common'; 2 | 3 | @Injectable() 4 | export class AppService { 5 | getHello(): string { 6 | return 'Hello World!'; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /backend/.dockerignore: -------------------------------------------------------------------------------- 1 | #dependencies 2 | /node_modules 3 | /.pnp 4 | .pnp.js 5 | 6 | 7 | # misc 8 | .DS_Store 9 | *.pem 10 | 11 | #debug 12 | npm-debug.log* 13 | yarn-debug.log* 14 | yarn-error.log* -------------------------------------------------------------------------------- /frontend/.dockerignore: -------------------------------------------------------------------------------- 1 | #dependencies 2 | /node_modules 3 | /.pnp 4 | .pnp.js 5 | 6 | 7 | # misc 8 | .DS_Store 9 | *.pem 10 | 11 | #debug 12 | npm-debug.log* 13 | yarn-debug.log* 14 | yarn-error.log* -------------------------------------------------------------------------------- /scripts/ecs/unix/check-disponibilidade.sh: -------------------------------------------------------------------------------- 1 | url="https://www.uol.com.br" 2 | docker build -t check_disponibilidade -f Dockerfile_checkdisponibilidade . 3 | docker run --rm -ti -e URL=$url check_disponibilidade 4 | -------------------------------------------------------------------------------- /frontend/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [], 3 | "references": [ 4 | { 5 | "path": "./tsconfig.app.json" 6 | }, 7 | { 8 | "path": "./tsconfig.node.json" 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /frontend/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import react from '@vitejs/plugin-react' 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [react()], 7 | }) 8 | -------------------------------------------------------------------------------- /scripts/start-session-bash.sh: -------------------------------------------------------------------------------- 1 | INSTANCE_ID=$1 2 | echo "Conectando na instancia $INSTANCE_ID" 3 | aws ssm start-session --target $INSTANCE_ID --document-name AWS-StartInteractiveCommand --parameters command="bash -l" -------------------------------------------------------------------------------- /backend/src/auth/guards/jwt-auth.guard.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@nestjs/common'; 2 | import { AuthGuard } from '@nestjs/passport'; 3 | 4 | @Injectable() 5 | export class JwtAuthGuard extends AuthGuard('jwt') { } 6 | -------------------------------------------------------------------------------- /backend/src/auth/guards/local-auth.guard.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@nestjs/common'; 2 | import { AuthGuard } from '@nestjs/passport'; 3 | 4 | @Injectable() 5 | export class LocalAuthGuard extends AuthGuard('local') { } -------------------------------------------------------------------------------- /frontend/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:latest 2 | 3 | WORKDIR /app 4 | 5 | COPY package*.json ./ 6 | 7 | RUN npm install 8 | 9 | COPY . . 10 | 11 | EXPOSE 5173 12 | 13 | CMD ["npm", "run", "dev", "--", "--host"] 14 | -------------------------------------------------------------------------------- /scripts/ecs/windows/check-disponibilidade.bat: -------------------------------------------------------------------------------- 1 | set url="https://www.uol.com.br" 2 | docker build -t check_disponibilidade -f Dockerfile_checkdisponibilidade . 3 | docker run --rm -ti -e URL=%url% check_disponibilidade 4 | -------------------------------------------------------------------------------- /backend/nest-cli.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/nest-cli", 3 | "collection": "@nestjs/schematics", 4 | "sourceRoot": "src", 5 | "compilerOptions": { 6 | "deleteOutDir": true 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /backend/src/auth/dto/update-auth.dto.ts: -------------------------------------------------------------------------------- 1 | import { PartialType } from '@nestjs/mapped-types'; 2 | import { CreateAuthDto } from './create-auth.dto'; 3 | 4 | export class UpdateAuthDto extends PartialType(CreateAuthDto) {} 5 | -------------------------------------------------------------------------------- /backend/src/user/dto/update-user.dto.ts: -------------------------------------------------------------------------------- 1 | import { PartialType } from '@nestjs/mapped-types'; 2 | import { CreateUserDto } from './create-user.dto'; 3 | 4 | export class UpdateUserDto extends PartialType(CreateUserDto) {} 5 | -------------------------------------------------------------------------------- /frontend/src/hooks/useAuth.ts: -------------------------------------------------------------------------------- 1 | import { useAppSelector } from "../store/hooks" 2 | 3 | export const useAuth = (): boolean => { 4 | const isAuth = useAppSelector((state) => state.user.isAuth) 5 | 6 | return isAuth 7 | } -------------------------------------------------------------------------------- /backend/src/category/dto/update-category.dto.ts: -------------------------------------------------------------------------------- 1 | import { PartialType } from '@nestjs/mapped-types'; 2 | import { CreateCategoryDto } from './create-category.dto'; 3 | 4 | export class UpdateCategoryDto extends PartialType(CreateCategoryDto) {} 5 | -------------------------------------------------------------------------------- /backend/src/transaction/dto/update-transaction.dto.ts: -------------------------------------------------------------------------------- 1 | import { PartialType } from '@nestjs/mapped-types'; 2 | import { CreateTransactionDto } from './create-transaction.dto'; 3 | 4 | export class UpdateTransactionDto extends PartialType(CreateTransactionDto) {} 5 | -------------------------------------------------------------------------------- /scripts/ecs/windows/build.bat: -------------------------------------------------------------------------------- 1 | aws ecr get-login-password --region us-east-1 --profile [SEU_PROFILE] | docker login --username AWS --password-stdin [SEU_ECR] 2 | docker build -t crud . 3 | docker tag crud:latest [SEU_ECR]/crud:latest 4 | docker push [SEU_ECR]/crud:latest -------------------------------------------------------------------------------- /scripts/ecs/unix/build.sh: -------------------------------------------------------------------------------- 1 | ECR_REGISTRY="SEU_REGISTRY" 2 | aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin $ECR_REGISTRY 3 | docker build -t crud . 4 | docker tag crud:latest $ECR_REGISTRY/crud:latest 5 | docker push $ECR_REGISTRY/crud:latest 6 | ß -------------------------------------------------------------------------------- /backend/src/user/dto/create-user.dto.ts: -------------------------------------------------------------------------------- 1 | import { IsEmail, MinLength } from "class-validator"; 2 | 3 | export class CreateUserDto { 4 | 5 | @IsEmail() 6 | email: string; 7 | 8 | @MinLength(6, { message: 'Password must ne more then 6 symbols' }) 9 | password: string; 10 | } 11 | -------------------------------------------------------------------------------- /backend/src/category/dto/create-category.dto.ts: -------------------------------------------------------------------------------- 1 | import { IsNotEmpty, IsOptional } from "class-validator"; 2 | import { User } from "src/user/entities/user.entity"; 3 | 4 | export class CreateCategoryDto { 5 | @IsNotEmpty() 6 | title: string; 7 | @IsOptional() 8 | user?: User 9 | } 10 | -------------------------------------------------------------------------------- /frontend/src/api/axios.api.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import { getTokenFromLocalStorage } from '../helpers/localStorage.helper'; 3 | 4 | export const instance = axios.create({ 5 | baseURL: 'http://localhost:3000/api', 6 | headers: { 7 | Authorization: `Bearer ` + getTokenFromLocalStorage() || '', 8 | }, 9 | }); 10 | -------------------------------------------------------------------------------- /frontend/src/store/hooks.ts: -------------------------------------------------------------------------------- 1 | import { useDispatch, useSelector } from "react-redux"; 2 | import type { TypedUseSelectorHook } from "react-redux"; 3 | import type { AppDispatch, RootState } from "./store"; 4 | 5 | export const useAppDispatch: () => AppDispatch = useDispatch 6 | export const useAppSelector: TypedUseSelectorHook = useSelector 7 | 8 | -------------------------------------------------------------------------------- /backend/src/app.controller.ts: -------------------------------------------------------------------------------- 1 | import { Controller, Get } from '@nestjs/common'; 2 | import { AppService } from './app.service'; 3 | 4 | @Controller() 5 | export class AppController { 6 | constructor(private readonly appService: AppService) {} 7 | 8 | @Get() 9 | getHello(): string { 10 | return this.appService.getHello(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /frontend/src/store/store.ts: -------------------------------------------------------------------------------- 1 | import { configureStore } from "@reduxjs/toolkit"; 2 | import userReducer from "./user/userSlice"; 3 | 4 | export const store = configureStore({ 5 | reducer: { 6 | user: userReducer, 7 | }, 8 | }); 9 | 10 | export type RootState = ReturnType; 11 | export type AppDispatch = typeof store.dispatch; -------------------------------------------------------------------------------- /frontend/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /frontend/src/helpers/date.helper.ts: -------------------------------------------------------------------------------- 1 | export const formatDate = (dateString: string): string => { 2 | const date = new Date(dateString); 3 | const options: Intl.DateTimeFormatOptions = { 4 | year: 'numeric', 5 | month: 'long', 6 | day: 'numeric' 7 | }; 8 | 9 | return date.toLocaleDateString('en-US', options); // Corrigido o código da localidade 10 | }; 11 | -------------------------------------------------------------------------------- /frontend/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", 5 | "skipLibCheck": true, 6 | "module": "ESNext", 7 | "moduleResolution": "bundler", 8 | "allowSyntheticDefaultImports": true, 9 | "strict": true, 10 | "noEmit": true 11 | }, 12 | "include": ["vite.config.ts"] 13 | } 14 | -------------------------------------------------------------------------------- /frontend/src/pages/Layout.tsx: -------------------------------------------------------------------------------- 1 | import { FC } from 'react' 2 | import { Outlet } from 'react-router-dom' 3 | import Header from '../components/Header' 4 | 5 | const Layout: FC = () => { 6 | return ( 7 |
8 |
9 |
10 | 11 |
12 |
13 | ) 14 | } 15 | 16 | export default Layout 17 | -------------------------------------------------------------------------------- /backend/src/exchangeRate/entities/exchangeRate.entity.ts: -------------------------------------------------------------------------------- 1 | import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm'; 2 | 3 | @Entity() 4 | export class ExchangeRate { 5 | @PrimaryGeneratedColumn() 6 | id: number; 7 | 8 | @Column({ type: 'date' }) 9 | date: string; 10 | 11 | @Column({ type: 'float' }) 12 | rate: number; 13 | 14 | @Column({ type: 'varchar', length: 3 }) 15 | currency: string; 16 | } 17 | -------------------------------------------------------------------------------- /backend/.env.example: -------------------------------------------------------------------------------- 1 | JWT_SECRET=c6f3503006d838777d4cd49f3eea2dfe 2 | 3 | POSTGRES_PORT=5432 4 | POSTGRES_HOST='aws_db' 5 | POSTGRES_USER='postgres' 6 | POSTGRES_PASSWORD='senhaForte10@' 7 | POSTGRES_DB='aws_db' 8 | 9 | PGADMIN_USER=email@gmail.com 10 | PGADMIN_PASSWORD='email10' 11 | 12 | 13 | POSTGRES_HOST_AWS='' 14 | POSTGRES_PORT_AWS=5432 15 | POSTGRES_USER_AWS='postgres' 16 | POSTGRES_PASSWORD_AWS='senhaForte10@' 17 | POSTGRES_DB_AWS='aws_db' 18 | 19 | -------------------------------------------------------------------------------- /frontend/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | export default { 3 | content: [ 4 | "./index.html", 5 | "./src/**/*.{js,ts,jsx,tsx}", 6 | ], theme: { 7 | container: { 8 | padding: '2rem', 9 | center: true, 10 | }, 11 | extend: { 12 | fontFamily: { 13 | roboto: ['Roboto', 'sans-serif'], 14 | }, 15 | }, 16 | }, 17 | plugins: [ 18 | require('@tailwindcss/forms') 19 | ], 20 | } 21 | 22 | -------------------------------------------------------------------------------- /frontend/src/helpers/localStorage.helper.ts: -------------------------------------------------------------------------------- 1 | export function getTokenFromLocalStorage(): string { 2 | const data = localStorage.getItem('token'); 3 | const token: string = data ? JSON.parse(data) : ""; 4 | return token; 5 | } 6 | 7 | export function setTokenToLocalStorage(key: string, token: string): void { 8 | localStorage.setItem(key, JSON.stringify(token)); 9 | } 10 | 11 | export function removeTokenFromLocalStorage(key: string): void { 12 | localStorage.removeItem(key); 13 | } 14 | -------------------------------------------------------------------------------- /backend/src/exchangeRate/exchangeRate.controller.ts: -------------------------------------------------------------------------------- 1 | import { Controller, Get, Query } from '@nestjs/common'; 2 | import { ExchangeRateService } from './exchangeRate.service'; 3 | 4 | @Controller('exchange-rate') 5 | export class ExchangeRateController { 6 | constructor(private readonly exchangeRateService: ExchangeRateService) { } 7 | 8 | @Get() 9 | async getExchangeRates(@Query('currency') currency: string) { 10 | return this.exchangeRateService.getExchangeRates(currency); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /frontend/src/main.tsx: -------------------------------------------------------------------------------- 1 | import ReactDOM from 'react-dom/client' 2 | import { Provider } from 'react-redux' 3 | import { ToastContainer } from 'react-toastify' 4 | import 'react-toastify/dist/ReactToastify.css' 5 | import App from './App.tsx' 6 | import './index.css' 7 | import { store } from './store/store.ts' 8 | 9 | ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( 10 | 11 | 12 | 13 | , 14 | ) 15 | -------------------------------------------------------------------------------- /frontend/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { browser: true, es2020: true }, 4 | extends: [ 5 | 'eslint:recommended', 6 | 'plugin:@typescript-eslint/recommended', 7 | 'plugin:react-hooks/recommended', 8 | ], 9 | ignorePatterns: ['dist', '.eslintrc.cjs'], 10 | parser: '@typescript-eslint/parser', 11 | plugins: ['react-refresh'], 12 | rules: { 13 | 'react-refresh/only-export-components': [ 14 | 'warn', 15 | { allowConstantExport: true }, 16 | ], 17 | }, 18 | } 19 | -------------------------------------------------------------------------------- /frontend/src/pages/ErrorPage.tsx: -------------------------------------------------------------------------------- 1 | import { FC } from 'react' 2 | import img from '../assets/page_not_found.png.png' 3 | import { Link } from 'react-router-dom' 4 | 5 | const ErrorPage: FC = () => { 6 | return ( 7 |
8 | img 9 | 13 | Back 14 | 15 |
16 | ) 17 | } 18 | 19 | export default ErrorPage 20 | -------------------------------------------------------------------------------- /backend/src/main.ts: -------------------------------------------------------------------------------- 1 | import { NestFactory } from '@nestjs/core'; 2 | import { AppModule } from './app.module'; 3 | import { ExchangeRateService } from './exchangeRate/exchangeRate.service'; 4 | 5 | async function bootstrap() { 6 | const app = await NestFactory.create(AppModule); 7 | 8 | app.setGlobalPrefix('api'); 9 | app.enableCors(); 10 | 11 | const exchangeRateService = app.get(ExchangeRateService); 12 | 13 | // Chame o método para fazer a coleta manual 14 | await exchangeRateService.triggerManualFetch(); 15 | 16 | await app.listen(3000); 17 | 18 | 19 | } 20 | bootstrap(); 21 | -------------------------------------------------------------------------------- /backend/src/exchangeRate/exchangeRate.module.ts: -------------------------------------------------------------------------------- 1 | import { Module } from '@nestjs/common'; 2 | import { TypeOrmModule } from '@nestjs/typeorm'; 3 | import { ExchangeRate } from './entities/exchangeRate.entity'; 4 | import { ExchangeRateService } from './exchangeRate.service'; 5 | import { ExchangeRateController } from './exchangeRate.controller'; 6 | 7 | 8 | @Module({ 9 | imports: [TypeOrmModule.forFeature([ExchangeRate])], 10 | providers: [ExchangeRateService], 11 | controllers: [ExchangeRateController], 12 | exports: [ExchangeRateService], 13 | }) 14 | export class ExchangeRateModule { } 15 | -------------------------------------------------------------------------------- /backend/src/user/user.controller.ts: -------------------------------------------------------------------------------- 1 | import { Controller, Get, Post, Body, Patch, Param, Delete, UsePipes, ValidationPipe } from '@nestjs/common'; 2 | import { UserService } from './user.service'; 3 | import { CreateUserDto } from './dto/create-user.dto'; 4 | import { UpdateUserDto } from './dto/update-user.dto'; 5 | 6 | @Controller('user') 7 | export class UserController { 8 | constructor(private readonly userService: UserService) { } 9 | 10 | @Post() 11 | @UsePipes(new ValidationPipe()) 12 | create(@Body() createUserDto: CreateUserDto) { 13 | return this.userService.create(createUserDto); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /backend/src/transaction/dto/create-transaction.dto.ts: -------------------------------------------------------------------------------- 1 | import { IsNotEmpty, IsNumber, IsOptional, IsString, MinLength } from "class-validator"; 2 | import { Category } from "src/category/entities/category.entity"; 3 | import { User } from "src/user/entities/user.entity"; 4 | 5 | export class CreateTransactionDto { 6 | 7 | @IsNotEmpty() 8 | title: string; 9 | 10 | @IsNotEmpty() 11 | @IsNumber() 12 | amount: number; 13 | 14 | @IsString() 15 | @MinLength(6) 16 | type: 'expense' | 'income'; 17 | 18 | @IsNotEmpty() 19 | category: Category; 20 | 21 | @IsOptional() 22 | user?: User; 23 | } 24 | -------------------------------------------------------------------------------- /frontend/src/components/Notes.tsx: -------------------------------------------------------------------------------- 1 | import { FC } from 'react' 2 | 3 | const Notes: FC = () => { 4 | return ( 5 |
14 |

Notes

15 |