├── 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 |
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 |
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 |
6 |
--------------------------------------------------------------------------------
/src/assets/outcome.svg:
--------------------------------------------------------------------------------
1 |
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 |
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 | | Título |
13 | Valor |
14 | Categoria |
15 | Data |
16 |
17 |
18 |
19 |
20 | {transactions.map(transaction => (
21 |
22 | | {transaction.title} |
23 |
24 | {new Intl.NumberFormat('pt-BR', {
25 | style: 'currency',
26 | currency: 'BRL'
27 | }).format(transaction.amount)}
28 | |
29 | {transaction.category} |
30 |
31 | {new Intl.DateTimeFormat('pt-BR').format(
32 | new Date(transaction.createdAt)
33 | )}
34 | |
35 |
36 | ))}
37 |
38 |
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 |
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 |
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 |
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 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
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 |
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 |
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 | [](https://www.linkedin.com/in/rafaeldcmartins/)
84 | [](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 |
80 | Entrada
81 |
82 |
83 | setType('withdraw')}
86 | isActive={type === 'withdraw'}
87 | activeColor="red"
88 | >
89 |
90 | Saída
91 |
92 |
93 |
94 | setCategory(target.value)}
99 | />
100 |
101 |
102 |
103 |
104 | );
105 | }
--------------------------------------------------------------------------------
/src/assets/logo.svg:
--------------------------------------------------------------------------------
1 |
20 |
--------------------------------------------------------------------------------