├── src ├── react-app-env.d.ts ├── services │ └── api.ts ├── components │ ├── Dashboard │ │ ├── styles.ts │ │ └── index.tsx │ ├── Header │ │ ├── index.tsx │ │ └── styles.ts │ ├── TransactionsTable │ │ ├── styles.ts │ │ └── index.tsx │ ├── Summary │ │ ├── styles.ts │ │ └── index.tsx │ └── NewTransactionModal │ │ ├── styles.ts │ │ └── index.tsx ├── assets │ ├── close.svg │ ├── income.svg │ ├── outcome.svg │ ├── total.svg │ └── logo.svg ├── App.tsx ├── index.tsx ├── hooks │ └── TransactionsContext.tsx └── styles │ └── global.ts ├── .github └── cover.png ├── public ├── favicon.png └── index.html ├── .gitignore ├── tsconfig.json ├── LICENSE ├── package.json └── README.md /src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /.github/cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/martins-rafael/dtmoney/HEAD/.github/cover.png -------------------------------------------------------------------------------- /public/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/martins-rafael/dtmoney/HEAD/public/favicon.png -------------------------------------------------------------------------------- /src/services/api.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | export const api = axios.create({ 4 | baseURL: 'http://localhost:3000/api' 5 | }); -------------------------------------------------------------------------------- /src/components/Dashboard/styles.ts: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const Container = styled.main` 4 | margin: 0 auto; 5 | padding: 2.5rem 1rem; 6 | max-width: 1120px; 7 | `; -------------------------------------------------------------------------------- /src/assets/close.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/components/Dashboard/index.tsx: -------------------------------------------------------------------------------- 1 | import { Summary } from '../Summary'; 2 | import { TransactionsTable } from '../TransactionsTable'; 3 | import { Container } from './styles'; 4 | 5 | export const Dashboard = () => ( 6 | 7 | 8 | 9 | 10 | ); -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /src/components/Header/index.tsx: -------------------------------------------------------------------------------- 1 | import logoImg from '../../assets/logo.svg'; 2 | 3 | import { Container, Content } from './styles'; 4 | 5 | interface HeaderProps { 6 | onOpenNewTransactionModal: () => void; 7 | } 8 | 9 | export const Header = ({ onOpenNewTransactionModal }: HeaderProps) => ( 10 | 11 | 12 | dt money 13 | 16 | 17 | 18 | ); -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | dtmoney 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | -------------------------------------------------------------------------------- /src/assets/income.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/assets/outcome.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "module": "esnext", 17 | "moduleResolution": "node", 18 | "resolveJsonModule": true, 19 | "isolatedModules": true, 20 | "noEmit": true, 21 | "jsx": "react-jsx" 22 | }, 23 | "include": [ 24 | "src" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /src/assets/total.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/components/Header/styles.ts: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const Container = styled.header` 4 | background-color: var(--gray-dark); 5 | `; 6 | 7 | export const Content = styled.div` 8 | display: flex; 9 | align-items: center; 10 | justify-content: space-between; 11 | margin: 0 auto; 12 | padding: 2rem 1rem 12rem; 13 | max-width: 1120px; 14 | 15 | button { 16 | padding: 0 2rem; 17 | height: 3rem; 18 | font-size: 1rem; 19 | color: #ffffff; 20 | background: var(--gray-light); 21 | border: 0; 22 | border-radius: 0.25rem; 23 | transition: filter 0.2s ease-in-out; 24 | 25 | &:hover { 26 | filter: brightness(0.9); 27 | } 28 | } 29 | `; -------------------------------------------------------------------------------- /src/components/TransactionsTable/styles.ts: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const Container = styled.div` 4 | margin-top: 4rem; 5 | 6 | table { 7 | width: 100%; 8 | border-spacing: 0 0.5rem; 9 | 10 | th { 11 | padding: 1rem 2rem; 12 | font-weight: 400; 13 | line-height: 1.5rem; 14 | text-align: left; 15 | color: var(--text-body); 16 | } 17 | 18 | td { 19 | padding: 1rem 2rem; 20 | color: var(--text-body); 21 | background: var(--shape); 22 | border: 0; 23 | border-radius: 0.25rem; 24 | 25 | &:first-child { 26 | color: var(--text-title); 27 | } 28 | 29 | &.deposit { 30 | color: var(--green); 31 | } 32 | 33 | &.withdraw { 34 | color: var(--red); 35 | } 36 | } 37 | } 38 | `; -------------------------------------------------------------------------------- /src/components/Summary/styles.ts: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | 3 | export const Container = styled.div` 4 | display: grid; 5 | grid-template-columns: repeat(3, 1fr); 6 | gap: 2rem; 7 | margin-top: -10rem; 8 | 9 | div { 10 | padding: 1.5rem 2rem; 11 | color: var(--text-title); 12 | background: var(--shape); 13 | border-radius: 0.25rem; 14 | box-shadow: 0px 1.5rem 4rem rgba(0, 0, 0, 0.06); 15 | 16 | header { 17 | display: flex; 18 | align-items: center; 19 | justify-content: space-between; 20 | } 21 | 22 | strong { 23 | display: block; 24 | margin-top: 1rem; 25 | font-size: 2rem; 26 | font-weight: 500; 27 | line-height: 3rem; 28 | } 29 | 30 | &.highlight-background { 31 | color: #ffffff; 32 | background: linear-gradient( 33 | to right, 34 | var(--orange) 0%, 35 | var(--orange-light) 51%, 36 | var(--orange) 100% 37 | ); 38 | } 39 | } 40 | `; -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Rafael Martins 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/App.tsx: -------------------------------------------------------------------------------- 1 | import { useState } from 'react'; 2 | import Modal from 'react-modal'; 3 | 4 | import { TransactionProvider } from './hooks/TransactionsContext'; 5 | 6 | import { Dashboard } from "./components/Dashboard"; 7 | import { Header } from "./components/Header"; 8 | import { NewTransactionModal } from './components/NewTransactionModal'; 9 | 10 | import { GlobalStyle } from "./styles/global"; 11 | 12 | Modal.setAppElement('#root'); 13 | 14 | export const App = () => { 15 | const [ 16 | isNewTransactionModalOpen, 17 | setIsNewTransactionModalOpen 18 | ] = useState(false); 19 | 20 | function handleOpenNewTransactionModal() { 21 | setIsNewTransactionModalOpen(true); 22 | } 23 | 24 | function handleCloseNewTransactionModal() { 25 | setIsNewTransactionModalOpen(false); 26 | } 27 | 28 | return ( 29 | 30 | 31 | 32 |
33 | 34 | 35 | 36 | 40 | 41 | ); 42 | } 43 | -------------------------------------------------------------------------------- /src/components/TransactionsTable/index.tsx: -------------------------------------------------------------------------------- 1 | import { useTransactions } from '../../hooks/TransactionsContext'; 2 | import { Container } from './styles'; 3 | 4 | export const TransactionsTable = () => { 5 | const { transactions } = useTransactions(); 6 | 7 | return ( 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | {transactions.map(transaction => ( 21 | 22 | 23 | 29 | 30 | 35 | 36 | ))} 37 | 38 |
TítuloValorCategoriaData
{transaction.title} 24 | {new Intl.NumberFormat('pt-BR', { 25 | style: 'currency', 26 | currency: 'BRL' 27 | }).format(transaction.amount)} 28 | {transaction.category} 31 | {new Intl.DateTimeFormat('pt-BR').format( 32 | new Date(transaction.createdAt) 33 | )} 34 |
39 |
40 | ); 41 | } -------------------------------------------------------------------------------- /src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import { createServer, Model } from 'miragejs'; 4 | import { App } from './App'; 5 | 6 | createServer({ 7 | models: { 8 | transaction: Model, 9 | }, 10 | seeds(server) { 11 | server.db.loadData({ 12 | transactions: [ 13 | { 14 | id: 1, 15 | title: 'Freela webpage', 16 | type: 'deposit', 17 | category: 'Dev', 18 | amount: 4500, 19 | createdAt: new Date('2021-03-15 08:00:00') 20 | }, 21 | 22 | { 23 | id: 2, 24 | title: 'Supermercado', 25 | type: 'withdraw', 26 | category: 'Compras', 27 | amount: 1200, 28 | createdAt: new Date('2021-03-15 13:00:00') 29 | } 30 | ] 31 | }); 32 | }, 33 | routes() { 34 | this.namespace = 'api'; 35 | 36 | this.get('/transactions', () => { 37 | return this.schema.all('transaction') 38 | }); 39 | 40 | this.post('/transactions', (schema, request) => { 41 | const data = JSON.parse(request.requestBody); 42 | return schema.create('transaction', data); 43 | }); 44 | } 45 | }); 46 | 47 | ReactDOM.render( 48 | 49 | 50 | , 51 | document.getElementById('root') 52 | ); 53 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dtmoney", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "axios": "^0.21.1", 7 | "miragejs": "^0.1.41", 8 | "polished": "^4.1.1", 9 | "react": "^17.0.1", 10 | "react-dom": "^17.0.1", 11 | "react-modal": "^3.12.1", 12 | "react-scripts": "4.0.3", 13 | "styled-components": "^5.2.1", 14 | "web-vitals": "^1.0.1" 15 | }, 16 | "devDependencies": { 17 | "@testing-library/jest-dom": "^5.11.4", 18 | "@testing-library/react": "^11.1.0", 19 | "@testing-library/user-event": "^12.1.10", 20 | "@types/jest": "^26.0.15", 21 | "@types/node": "^12.0.0", 22 | "@types/react": "^17.0.0", 23 | "@types/react-dom": "^17.0.0", 24 | "@types/react-modal": "^3.12.0", 25 | "@types/styled-components": "^5.1.9", 26 | "typescript": "^4.1.2" 27 | }, 28 | "scripts": { 29 | "start": "react-scripts start", 30 | "build": "react-scripts build", 31 | "test": "react-scripts test", 32 | "eject": "react-scripts eject" 33 | }, 34 | "eslintConfig": { 35 | "extends": [ 36 | "react-app", 37 | "react-app/jest" 38 | ] 39 | }, 40 | "browserslist": { 41 | "production": [ 42 | ">0.2%", 43 | "not dead", 44 | "not op_mini all" 45 | ], 46 | "development": [ 47 | "last 1 chrome version", 48 | "last 1 firefox version", 49 | "last 1 safari version" 50 | ] 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/hooks/TransactionsContext.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | createContext, 3 | ReactNode, 4 | useContext, 5 | useEffect, 6 | useState 7 | } from "react"; 8 | import { api } from "../services/api"; 9 | 10 | interface Transactions { 11 | id: number; 12 | title: string; 13 | type: string 14 | category: string 15 | amount: number; 16 | createdAt: string; 17 | } 18 | 19 | type TransactionInput = Omit 20 | 21 | interface TransactionsProviderProps { 22 | children: ReactNode; 23 | } 24 | 25 | interface TransactionContextData { 26 | transactions: Transactions[]; 27 | createTransaction: (transaction: TransactionInput) => void; 28 | } 29 | 30 | const TransactionContext = createContext( 31 | {} as TransactionContextData 32 | ); 33 | 34 | export const TransactionProvider = ({ children }: TransactionsProviderProps) => { 35 | const [transactions, setTransactions] = useState([]); 36 | 37 | useEffect(() => { 38 | api.get('transactions') 39 | .then(response => setTransactions(response.data.transactions)); 40 | }, []); 41 | 42 | async function createTransaction(transactionInput: TransactionInput) { 43 | const response = await api.post('/transactions', { 44 | ...transactionInput, 45 | createdAt: new Date() 46 | }); 47 | const { transaction } = response.data; 48 | setTransactions([...transactions, transaction]); 49 | } 50 | 51 | return ( 52 | 53 | {children} 54 | 55 | ); 56 | }; 57 | 58 | export const useTransactions = () => { 59 | const contex = useContext(TransactionContext); 60 | return contex; 61 | } -------------------------------------------------------------------------------- /src/styles/global.ts: -------------------------------------------------------------------------------- 1 | import { createGlobalStyle } from 'styled-components'; 2 | 3 | export const GlobalStyle = createGlobalStyle` 4 | :root { 5 | --background: #f0f2f5; 6 | --red: #e52e4d; 7 | --green: #33cc95; 8 | --blue: #5429cc; 9 | --blue-light: #6933ff; 10 | --orange: #ff512f; 11 | --orange-light: #f09819; 12 | --gray-dark: #121214; 13 | --gray-light: #202024; 14 | --text-title: #363f5f; 15 | --text-body: #969cb3; 16 | --shape: #ffffff; 17 | } 18 | 19 | * { 20 | margin: 0; 21 | padding: 0; 22 | box-sizing: border-box; 23 | } 24 | 25 | html { 26 | @media (max-width: 1080px) { 27 | font-size: 93.75%; 28 | } 29 | 30 | @media (max-width: 720px) { 31 | font-size: 87.5%; 32 | } 33 | } 34 | 35 | body { 36 | background-color: var(--background); 37 | -webkit-font-smoothing: antialiased; 38 | } 39 | 40 | body, input, textarea, button { 41 | font-family: 'Poppins', sans-serif; 42 | font-weight: 400; 43 | } 44 | 45 | h1, h2, h3, h4, h5, h6, strong { 46 | font-weight: 600; 47 | } 48 | 49 | button { 50 | cursor: pointer; 51 | } 52 | 53 | [disabled] { 54 | opacity: 0.6; 55 | cursor: not-allowed; 56 | } 57 | 58 | .react-modal-overlay { 59 | position: fixed; 60 | top: 0; 61 | left: 0; 62 | right: 0; 63 | bottom: 0; 64 | display: flex; 65 | align-items: center; 66 | justify-content: center; 67 | background: rgba(0, 0, 0, 0.5); 68 | } 69 | 70 | .react-modal-content { 71 | position: relative; 72 | padding: 3rem; 73 | width: 100%; 74 | max-width: 576px; 75 | background: var(--background); 76 | border-radius: 0.25rem; 77 | } 78 | 79 | .react-modal-close { 80 | position: absolute; 81 | top: 1.5rem; 82 | right: 1.5rem; 83 | background: transparent; 84 | border: 0; 85 | transition: filter 0.2s ease-in-out; 86 | 87 | &:hover { 88 | filter: brightness(0.8); 89 | } 90 | } 91 | `; -------------------------------------------------------------------------------- /src/components/Summary/index.tsx: -------------------------------------------------------------------------------- 1 | import { useTransactions } from '../../hooks/TransactionsContext'; 2 | 3 | import { Container } from "./styles"; 4 | 5 | import incomeImg from '../../assets/income.svg'; 6 | import outcomeImg from '../../assets/outcome.svg'; 7 | import totalImg from '../../assets/total.svg'; 8 | 9 | export const Summary = () => { 10 | const { transactions } = useTransactions(); 11 | 12 | const summary = transactions.reduce((acc, transaction) => { 13 | if (transaction.type === 'deposit') { 14 | acc.deposits += transaction.amount; 15 | acc.total += transaction.amount; 16 | } else { 17 | acc.withdraws += transaction.amount; 18 | acc.total -= transaction.amount; 19 | } 20 | 21 | return acc; 22 | }, { 23 | deposits: 0, 24 | withdraws: 0, 25 | total: 0 26 | }); 27 | 28 | return ( 29 | 30 |
31 |
32 |

Entradas

33 | Entradas 34 |
35 | 36 | {new Intl.NumberFormat('pt-BR', { 37 | style: 'currency', 38 | currency: 'BRL' 39 | }).format(summary.deposits)} 40 | 41 |
42 | 43 |
44 |
45 |

Saídas

46 | Saídas 47 |
48 | 49 | {new Intl.NumberFormat('pt-BR', { 50 | style: 'currency', 51 | currency: 'BRL' 52 | }).format(summary.withdraws)} 53 | 54 |
55 | 56 |
57 |
58 |

Total

59 | Total 60 |
61 | 62 | {new Intl.NumberFormat('pt-BR', { 63 | style: 'currency', 64 | currency: 'BRL' 65 | }).format(summary.total)} 66 | 67 |
68 |
69 | ); 70 | } -------------------------------------------------------------------------------- /src/components/NewTransactionModal/styles.ts: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components'; 2 | import { darken, transparentize } from 'polished'; 3 | 4 | interface RadioBoxProps { 5 | isActive: boolean; 6 | activeColor: 'green' | 'red'; 7 | } 8 | 9 | const colors = { 10 | green: '#33cc95', 11 | red: '#e52e4d' 12 | } 13 | 14 | export const Container = styled.form` 15 | h2 { 16 | margin-bottom: 2rem; 17 | font-size: 1.5rem; 18 | color: var(--text-title); 19 | } 20 | 21 | input { 22 | padding: 0 1.5rem; 23 | width: 100%; 24 | height: 4rem; 25 | font-size: 1rem; 26 | font-weight: 400; 27 | background: #e7e9ee; 28 | border: 1px solid #d7d7d7; 29 | border-radius: 0.25rem; 30 | 31 | &::placeholder { 32 | color: var(--text-body); 33 | } 34 | 35 | & + input { 36 | margin-top: 1rem; 37 | } 38 | } 39 | 40 | button[type="submit"] { 41 | margin-top: 1.5rem; 42 | padding: 0 1.5rem; 43 | width: 100%; 44 | height: 4rem; 45 | font-size: 1rem; 46 | font-weight: 600; 47 | color: #ffffff; 48 | background: var(--orange); 49 | border: 0; 50 | border-radius: 0.25rem; 51 | transition: filter 0.2s ease-in-out; 52 | 53 | &:hover { 54 | filter: brightness(0.9); 55 | } 56 | } 57 | `; 58 | 59 | export const TransactionTypeContainer = styled.div` 60 | display: grid; 61 | grid-template-columns: 1fr 1fr; 62 | gap: 0.5rem; 63 | margin: 1rem 0; 64 | `; 65 | 66 | export const RadioBox = styled.button` 67 | display: flex; 68 | align-items: center; 69 | justify-content: center; 70 | height: 4rem; 71 | background: ${({ isActive, activeColor }) => isActive 72 | ? transparentize(0.9, colors[activeColor]) 73 | : 'transparent'}; 74 | border: 1px solid #d7d7d7; 75 | border-radius: 0.25rem; 76 | transition: border-color 0.2s ease-in-out; 77 | 78 | &:hover { 79 | border-color: ${darken(0.1, '#d7d7d7')}; 80 | } 81 | 82 | img { 83 | width: 20px; 84 | height: 20px; 85 | } 86 | 87 | span { 88 | display: block; 89 | margin-left: 1rem; 90 | font-size: 1rem; 91 | color: var(--text-title); 92 | } 93 | `; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # dt money 2 | 3 |

4 | 5 | GitHub language count 6 | GitHub Top Language 7 | 8 | License 9 | 10 | 11 |

12 | 13 | dt money 14 | 15 | ## Tópicos 16 | 17 | [Sobre o dt money](#sobre-o-dt-money) 18 | 19 | [Tecnologias](#tecnologias) 20 | 21 | [Instalação e uso](#instalação-e-uso) 22 | 23 | [Licença](#licença) 24 | 25 |
26 | 27 | ## Sobre o dt money 28 | 29 | O dt money é uma alternativa simples e eficaz para gerenciar suas finanças, permitindo o cadastro de entradas, saídas e a organização das mesmas em categorias. 30 | 31 |
32 | 33 |

34 | Página inicial 35 |

36 | 37 | ## Tecnologias 38 | 39 | Tecnologias e ferramentas utilizadas no desenvolvimento do projeto: 40 | 41 | - [React](https://reactjs.org/) 42 | - [TypeScript](https://www.typescriptlang.org/) 43 | - [Styled Components](https://styled-components.com/) 44 | - [MirageJS](https://miragejs.com/) 45 | - [Axios](https://github.com/axios/axios) 46 | - [Polished](https://polished.js.org/) 47 | 48 |
49 | 50 | ## Instalação e uso 51 | 52 | ```bash 53 | # Abra um terminal e copie este repositório com o comando 54 | git clone https://github.com/martins-rafael/dtmoney.git 55 | # ou use a opção de download. 56 | 57 | # Entre na pasta web com 58 | cd dtmoney 59 | 60 | # Instale as dependências 61 | yarn install 62 | 63 | # Rode a aplicação 64 | yarn start 65 | ``` 66 | 67 |
68 | 69 | 70 | ## Licença 71 | 72 | License 73 | 74 | 75 |
76 | 77 | Esse projeto está sob a licença MIT. Veja o arquivo [LICENSE](/LICENSE) para mais detalhes. 78 | 79 | --- 80 | 81 | Feito com :orange_heart: by [Rafael Martins](https://github.com/martins-rafael) 82 | 83 | [![Linkedin Badge](https://img.shields.io/badge/-Rafael%20Martins-ff512f?style=flat-square&logo=Linkedin&logoColor=white&link=https://www.linkedin.com/in/rafaeldcmartins/)](https://www.linkedin.com/in/rafaeldcmartins/) 84 | [![Gmail Badge](https://img.shields.io/badge/-rafaeldcmartins@gmail.com-ff512f?style=flat-square&logo=Gmail&logoColor=white&link=mailto:rafaeldcmartins@gmail.com)](mailto:rafaeldcmartins@gmail.com) 85 | -------------------------------------------------------------------------------- /src/components/NewTransactionModal/index.tsx: -------------------------------------------------------------------------------- 1 | import { FormEvent, useState } from 'react'; 2 | import Modal from 'react-modal'; 3 | 4 | import { useTransactions } from '../../hooks/TransactionsContext'; 5 | 6 | import closeImg from '../../assets/close.svg'; 7 | import incomeImg from '../../assets/income.svg'; 8 | import outcomeImg from '../../assets/outcome.svg'; 9 | 10 | import { Container, TransactionTypeContainer, RadioBox } from './styles'; 11 | 12 | interface NewTransactionModalProps { 13 | isOpen: boolean; 14 | onRequestClose: () => void; 15 | } 16 | 17 | export const NewTransactionModal = ({ 18 | isOpen, 19 | onRequestClose 20 | }: NewTransactionModalProps) => { 21 | const { createTransaction } = useTransactions(); 22 | 23 | const [type, setType] = useState('deposit'); 24 | const [title, setTitle] = useState(''); 25 | const [amount, setAmout] = useState(0); 26 | const [category, setCategory] = useState(''); 27 | 28 | async function handleCreateNewTransaction(event: FormEvent) { 29 | event.preventDefault(); 30 | 31 | await createTransaction({ type, title, amount, category }); 32 | 33 | setType('deposit'); 34 | setTitle(''); 35 | setAmout(0); 36 | setCategory(''); 37 | onRequestClose(); 38 | } 39 | 40 | return ( 41 | 47 | 54 | 55 | 56 |

Cadastrar Transação

57 | 58 | setTitle(target.value)} 63 | /> 64 | 65 | setAmout(Number(target.value))} 70 | /> 71 | 72 | 73 | setType('deposit')} 76 | isActive={type === 'deposit'} 77 | activeColor="green" 78 | > 79 | Entrada 80 | Entrada 81 | 82 | 83 | setType('withdraw')} 86 | isActive={type === 'withdraw'} 87 | activeColor="red" 88 | > 89 | Saída 90 | Saída 91 | 92 | 93 | 94 | setCategory(target.value)} 99 | /> 100 | 101 | 102 |
103 |
104 | ); 105 | } -------------------------------------------------------------------------------- /src/assets/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | --------------------------------------------------------------------------------