[
  {
    "path": ".gitignore",
    "content": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pnp\n.pnp.js\n\n# testing\n/coverage\n\n# production\n/build\n\n# misc\n.DS_Store\n.env.local\n.env.development.local\n.env.test.local\n.env.production.local\n\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n"
  },
  {
    "path": "README.md",
    "content": "<div align=\"center\" >\n  <img src=\"./docs/assets/logo.png\" width=\"200\">\n</div>\n\n\nDashboard desenvolvido em **ReactJs** com **TypeScript** inteiramente componentizado com **componentes puros**.\n\n<div align=\"center\" >\n  <img src=\"./docs/assets/minhacarteirapreview.gif\">\n</div>\n\n\n\n\nNão há banco de dados. Os dados são carregados de 2 arquivos que contém arrays simulando os repositórios de dados.\n\n\n### Layout & Componentes Responsivos\n\n<div align=\"center\" >\n  <img src=\"./docs/assets/resposiveview.png\">\n</div>\n\n- [x] Link do prototipo desenvolvido no [**Figma**](https://www.figma.com/file/nOGmUkhcINJt6nd57R4ENu/Untitled?node-id=0%3A1).\n\n### Layout & Componentes Responsivos\n\n- [x] Para os gráficos, foi utilizada a bibliteca [**Recharts**](http://recharts.org/en-US) que é opensource.\n- [x] Para efeito de número crescendo eu utilizei o [**React CountUp**](https://www.npmjs.com/package/react-countup).\n\n\n<div align=\"center\">\n  <small>Rodrigo Gonçalves Santana - 2020</small>\n</div>"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"minha-carteira\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"dependencies\": {\n    \"@testing-library/jest-dom\": \"^4.2.4\",\n    \"@testing-library/react\": \"^9.3.2\",\n    \"@testing-library/user-event\": \"^7.1.2\",\n    \"@types/jest\": \"^24.0.0\",\n    \"@types/node\": \"^12.0.0\",\n    \"@types/react\": \"^16.9.0\",\n    \"@types/react-dom\": \"^16.9.0\",\n    \"@types/recharts\": \"^1.8.14\",\n    \"react\": \"^16.13.1\",\n    \"react-countup\": \"^4.3.3\",\n    \"react-dom\": \"^16.13.1\",\n    \"react-icons\": \"^3.10.0\",\n    \"react-router-dom\": \"^5.2.0\",\n    \"react-scripts\": \"3.4.1\",\n    \"react-switch\": \"^5.0.1\",\n    \"recharts\": \"^1.8.5\",\n    \"styled-components\": \"^5.1.1\",\n    \"typescript\": \"~3.7.2\",\n    \"uuidv4\": \"^6.2.0\"\n  },\n  \"scripts\": {\n    \"start\": \"react-scripts start\",\n    \"build\": \"react-scripts build\",\n    \"test\": \"react-scripts test\",\n    \"eject\": \"react-scripts eject\"\n  },\n  \"eslintConfig\": {\n    \"extends\": \"react-app\"\n  },\n  \"browserslist\": {\n    \"production\": [\n      \">0.2%\",\n      \"not dead\",\n      \"not op_mini all\"\n    ],\n    \"development\": [\n      \"last 1 chrome version\",\n      \"last 1 firefox version\",\n      \"last 1 safari version\"\n    ]\n  },\n  \"devDependencies\": {\n    \"@types/react-router-dom\": \"^5.1.5\",\n    \"@types/styled-components\": \"^5.1.1\"\n  }\n}\n"
  },
  {
    "path": "public/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <link rel=\"icon\" href=\"./assets/logo.svg\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n    \n    <link href=\"https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap\" rel=\"stylesheet\">\n    \n    <title>Minha Carteira</title>\n  </head>\n  <body>\n    <noscript>You need to enable JavaScript to run this app.</noscript>\n    <div id=\"root\"></div>\n  </body>\n</html>\n"
  },
  {
    "path": "src/App.tsx",
    "content": "import React from 'react';\nimport { ThemeProvider } from 'styled-components';\nimport GlobalStyles from './styles/GlobalStyles';\n\nimport { useTheme } from './hooks/theme';\n\nimport Routes from './routes';\n\n\nconst App: React.FC = () => {\n    const {theme} = useTheme();\n    \n    return (\n        <ThemeProvider theme={theme}>\n            <GlobalStyles />\n            <Routes/>\n        </ThemeProvider>\n    );\n}\n\nexport default App;"
  },
  {
    "path": "src/components/Aside/index.tsx",
    "content": "import React, {useState} from 'react';\nimport Toggle from '../Toggle';\n\nimport {\n    MdDashboard,\n    MdArrowDownward,\n    MdArrowUpward,\n    MdExitToApp,\n    MdClose,\n    MdMenu, \n} from 'react-icons/md';\n\nimport logoImg from '../../assets/logo.svg';\n\nimport { useAuth } from '../../hooks/auth';\nimport { useTheme } from '../../hooks/theme';\n\nimport { \n    Container,\n    Header,\n    LogImg,\n    Title,\n    MenuContainer,\n    MenuItemLink,\n    MenuItemButton,\n    ToggleMenu,\n    ThemeToggleFooter,\n}  from './styles';\n\nconst Aside: React.FC = () => {\n    const { signOut } = useAuth();\n    const { toggleTheme, theme } = useTheme();\n\n    const [toggleMenuIsOpened, setToggleMenuIsOpened ] = useState(false);\n    const [darkTheme, setDarkTheme] = useState(() => theme.title === 'dark' ? true : false);\n\n\n    const handleToggleMenu = () => {\n        setToggleMenuIsOpened(!toggleMenuIsOpened);\n    }\n\n\n    const handleChangeTheme = () => {\n        setDarkTheme(!darkTheme);\n        toggleTheme();\n    }\n\n\n    return (\n        <Container menuIsOpen={toggleMenuIsOpened}>\n            <Header>\n                <ToggleMenu onClick={handleToggleMenu}>\n                { toggleMenuIsOpened ? <MdClose /> : <MdMenu /> }\n                </ToggleMenu>\n\n                <LogImg src={logoImg} alt=\"Logo Minha Carteira\" />\n                <Title>Minha Carteira</Title>\n            </Header>\n\n            <MenuContainer>\n                <MenuItemLink href=\"/\">\n                    <MdDashboard />\n                    Dashboard\n                </MenuItemLink>\n\n                <MenuItemLink href=\"/list/entry-balance\">\n                    <MdArrowUpward />\n                    Entradas\n                </MenuItemLink>\n\n                <MenuItemLink href=\"/list/exit-balance\">\n                    <MdArrowDownward />\n                    Saídas\n                </MenuItemLink>\n\n                <MenuItemButton onClick={signOut}>\n                    <MdExitToApp />\n                    Sair\n                </MenuItemButton>\n            </MenuContainer>\n\n            <ThemeToggleFooter menuIsOpen={toggleMenuIsOpened}>\n                <Toggle\n                    labelLeft=\"Light\"\n                    labelRight=\"Dark\"\n                    checked={darkTheme}\n                    onChange={handleChangeTheme}\n                />\n            </ThemeToggleFooter>\n        </Container>\n    );\n}\n\nexport default Aside;"
  },
  {
    "path": "src/components/Aside/styles.ts",
    "content": "import styled, { css } from 'styled-components';\n\n\ninterface IContainerProps {\n    menuIsOpen: boolean;\n}\n\n\ninterface IThemeToggleFooterProps {\n    menuIsOpen: boolean;\n}\n\n\nexport const Container = styled.div<IContainerProps>`\n    grid-area: AS;\n    \n    background-color: ${props => props.theme.colors.secondary};\n    padding-left: 20px;\n\n    border-right: 1px solid ${props => props.theme.colors.gray};\n\n    position: relative;\n\n    @media(max-width: 600px){\n        padding-left: 20px;\n        position: fixed;\n        z-index: 2;\n\n        width: 170px;\n\n        height: ${props => props.menuIsOpen ? '100vh' : '70px'};\n        overflow: hidden;\n\n        ${props => !props.menuIsOpen && css`\n            border: none;\n            border-bottom: 1px solid ${props => props.theme.colors.gray};\n        `};\n    }\n`;\n\nexport const Header = styled.header`\n    height: 70px;\n    display: flex;\n    align-items: center;\n\n`;\n\nexport const LogImg = styled.img`\n    height: 40px;\n    width: 40px;\n\n    @media(max-width: 600px){        \n        display: none;\n    }\n`;\n\nexport const Title = styled.h3`\n    color: ${props => props.theme.colors.white};\n    margin-left: 10px;\n\n    @media(max-width: 600px){\n        display: none;\n    }\n`;\n\n\nexport const MenuContainer = styled.nav`\n    display: flex;\n    flex-direction: column;\n\n\n    margin-top: 50px;\n`;\n\nexport const MenuItemLink = styled.a`\n    color: ${props => props.theme.colors.info};\n    text-decoration: none;\n\n    margin: 7px 0;\n    display: flex;\n    align-items: center;\n\n    transition: opacity .3s;\n\n    &:hover {\n        opacity: .7;\n    }\n\n    > svg {\n        font-size: 18px;\n        margin-right: 5px;\n    }\n`;\n\n\n\nexport const MenuItemButton = styled.button`\n    font-size: 16px;\n    color: ${props => props.theme.colors.info};\n    \n    border: none;\n    background: none;\n\n    margin: 7px 0;\n    display: flex;\n    align-items: center;\n\n    transition: opacity .3s;\n\n    &:hover {\n        opacity: .7;\n    }\n\n    > svg {\n        font-size: 18px;\n        margin-right: 5px;\n    }\n`;\n\nexport const ToggleMenu = styled.button`\n    width: 40px;\n    height: 40px;\n\n    border-radius: 5px;\n    font-size: 22px;\n    \n    background-color: ${props => props.theme.colors.warning};\n    color: ${props => props.theme.colors.white};\n\n    transition: opacity .3s;\n\n    &:hover{\n        opacity: 0.7;\n    }\n\n    display: none;\n\n    @media(max-width: 600px){\n        display: flex;\n        justify-content: center;\n        align-items: center;\n    }\n`;\n\nexport const ThemeToggleFooter = styled.footer<IThemeToggleFooterProps>`\n    display: none;\n    position: absolute;\n    bottom: 30px;\n    \n    @media(max-width: 470px){\n        display: ${props => props.menuIsOpen ? 'flex' : 'none'};\n    }\n\n`;"
  },
  {
    "path": "src/components/BarChartBox/index.tsx",
    "content": "import React from 'react';\nimport {\n    ResponsiveContainer,\n    BarChart,\n    Bar,\n    Cell,\n    Tooltip,\n} from 'recharts';\n\nimport formatCurrency from '../../utils/formatCurrency';\n\nimport { \n    Container,\n    SideLeft,\n    SideRight,\n    LegendContainer,\n    Legend,\n}  from './styles';\n\ninterface IBarChartProps {\n    title: string;\n    data: {\n        name: string;\n        amount: number;\n        percent: number;\n        color: string\n    }[],\n}\n\nconst BarChartBox: React.FC<IBarChartProps> = ({ title, data }) => (\n        <Container>\n            <SideLeft>\n                <h2>{title}</h2>\n\n                <LegendContainer>\n                    {\n                        data.map((indicator) => (\n                            <Legend key={indicator.name} color={indicator.color}>\n                            <div>{indicator.percent}%</div>\n                            <span>{indicator.name}</span>\n                            </Legend>  \n                        ))              \n                    }\n                </LegendContainer>\n            </SideLeft>\n            \n\n            <SideRight>\n                <ResponsiveContainer>\n                    <BarChart data={data}>                    \n                        <Bar dataKey=\"amount\" name=\"Valor\">\n                            {\n                                data.map((indicator) => (\n                                    <Cell \n                                        key={indicator.name}\n                                        fill={indicator.color}\n                                        cursor=\"pointer\"    \n                                    />\n                                ))\n                            }\n                        </Bar>   \n                        <Tooltip \n                            cursor={{fill: 'none'}}\n                            formatter={(value) => formatCurrency(Number(value))} \n                        />\n                    </BarChart>\n                </ResponsiveContainer>\n            </SideRight>       \n        </Container>\n    );\n\nexport default BarChartBox;"
  },
  {
    "path": "src/components/BarChartBox/styles.ts",
    "content": "import styled, { keyframes } from 'styled-components';\n\ninterface ILegendProps {\n    color: string;\n}\n\nconst animate = keyframes`\n    0% {\n        transform: translateX(100px);\n        opacity: 0;\n    }\n    50%{\n        opacity: .3;\n    }\n    100%{\n        transform: translateX(0px);\n        opacity: 1;\n    }\n`;\n\nexport const Container = styled.div`\n    width: 48%;\n    min-height: 260px;\n\n    margin: 10px 0;\n\n    background-color: ${props => props.theme.colors.tertiary};\n    color: ${props => props.theme.colors.white};\n    \n    border-radius: 7px;\n\n    display: flex;\n\n    animation: ${animate} .5s;\n\n    @media(max-width: 1200px){\n        display: flex;\n        flex-direction: column;\n\n        width: 100%;\n        height: auto;\n    }\n`;\n\nexport const SideLeft = styled.aside`    \n    flex: 1;\n    padding: 30px 20px;\n\n    > h2 {\n        padding-left: 16px;\n        margin-bottom: 10px;\n    }\n`;\n\n\nexport const LegendContainer = styled.ul`\n    list-style: none;\n    \n    height: 175px; \n    padding-right: 15px;\n    overflow-y: scroll;\n\n    ::-webkit-scrollbar {\n        width: 10px;\n    }\n\n    ::-webkit-scrollbar-thumb {\n        background-color: ${props => props.theme.colors.secondary};\n        border-radius: 10px;\n    }\n\n    ::-webkit-scrollbar-track {\n        background-color: ${props => props.theme.colors.tertiary};\n    }\n\n    \n    @media(max-width: 1200px){\n        display: flex;\n\n        height: auto; \n    }\n`;\n\nexport const Legend = styled.li<ILegendProps>`\n    display: flex;\n    align-items: center;\n\n    margin-bottom: 7px;  \n\n    padding-left: 16px;  \n\n    > div {\n        background-color: ${props => props.color};\n\n        width: 40px;\n        height: 40px;\n        border-radius: 5px;\n        \n        font-size: 14px;        \n        line-height: 40px;\n        text-align: center;\n    }\n\n    > span {\n        margin-left: 5px;\n    }\n\n    @media(max-width: 1200px){\n        > div {\n            width: 30px;\n            height: 30px;\n            \n            font-size: 10px;        \n            line-height: 30px;\n        }\n\n    }\n`;\n\n\nexport const SideRight = styled.main`\n   flex: 1;\n   min-height: 150px;\n\n   display: flex;\n   justify-content: center;\n\n   padding-top: 35px;\n     \n`;"
  },
  {
    "path": "src/components/Button/index.tsx",
    "content": "import React, { ButtonHTMLAttributes } from 'react';\n\nimport { Container }  from './styles'\n\ntype IButtonProps = ButtonHTMLAttributes<HTMLButtonElement>;\n\nconst Button: React.FC<IButtonProps> = ({children, ...rest }) => (\n    <Container {...rest}>\n        {children}\n    </Container>\n);\n\nexport default Button;"
  },
  {
    "path": "src/components/Button/styles.ts",
    "content": "import styled from 'styled-components';\n\nexport const Container = styled.button`\n    width: 100%;\n\n    margin: 7px 0;\n    padding: 10px;\n\n    border-radius: 5px;\n\n    font-weight: bold;\n    color: ${props => props.theme.colors.white};\n    background-color: ${props => props.theme.colors.warning};\n\n    transition: opacity .3s;\n\n    &:hover{\n        opacity: .7;\n    }\n`;"
  },
  {
    "path": "src/components/Content/index.tsx",
    "content": "import React from 'react';\n\nimport { Container }  from './styles';\n\nconst Content: React.FC = ({ children }) => (\n    <Container>\n        {children}\n    </Container>\n);\n\nexport default Content;"
  },
  {
    "path": "src/components/Content/styles.ts",
    "content": "import styled from 'styled-components';\n\nexport const Container = styled.div`\n    grid-area: CT;\n    color: ${props => props.theme.colors.white};\n    background-color: ${props => props.theme.colors.primary};\n\n    padding: 25px;  \n\n    height: calc(100vh - 70px); \n    overflow-y: scroll;\n\n    ::-webkit-scrollbar {\n        width: 10px;\n    }\n\n    ::-webkit-scrollbar-thumb {\n        background-color: ${props => props.theme.colors.secondary};\n        border-radius: 10px;\n    }\n\n    ::-webkit-scrollbar-track {\n        background-color: ${props => props.theme.colors.tertiary};\n    }\n`;\n"
  },
  {
    "path": "src/components/ContentHeader/index.tsx",
    "content": "import React from 'react';\n\nimport { \n    Container,\n    TitleContainer,\n    Controllers \n}  from './styles';\n\ninterface IContentHeaderProps {\n    title: string;\n    lineColor: string;\n    children: React.ReactNode;\n}\n\nconst ContentHeader: React.FC<IContentHeaderProps> = ({\n    title, lineColor, children\n}) => (\n    <Container>\n        <TitleContainer lineColor={lineColor}>\n            <h1>{title}</h1>                \n        </TitleContainer>\n        <Controllers>\n            {children}\n        </Controllers>\n    </Container>\n);\n\n\nexport default ContentHeader;"
  },
  {
    "path": "src/components/ContentHeader/styles.ts",
    "content": "import styled from 'styled-components';\n\ninterface ITitleContainerProps {\n    lineColor: string;\n}\n\nexport const Container = styled.div`\n    width: 100%;\n\n    display: flex;\n    justify-content: space-between;\n\n    margin-bottom: 25px;    \n\n\n    @media(max-width: 320px){\n        flex-direction: column;\n       \n    }\n`;\n\nexport const TitleContainer = styled.div<ITitleContainerProps>`\n\n    > h1 {\n        color: ${props => props.theme.colors.white};\n\n        &::after {\n            content: '';\n            display: block;\n            width: 55px;\n            border-bottom: 10px solid ${props => props.lineColor};\n        }\n    }\n\n    @media(max-width: 420px){\n        > h1 {\n                font-size: 22px;\n\n                &::after {\n                content: '';\n                display: block;\n                width: 55px;\n                border-bottom: 5px solid ${props => props.lineColor};\n            }\n        }\n    }\n`;\n\nexport const Controllers = styled.div`\n    display: flex;\n\n    @media(max-width: 320px){\n        width: 100%;\n\n        justify-content: space-around;\n        \n        margin-top: 20px;       \n    }\n`;"
  },
  {
    "path": "src/components/HistoryBox/index.tsx",
    "content": "import React from 'react';\nimport {\n    ResponsiveContainer,\n    LineChart,\n    Line,\n    XAxis,\n    CartesianGrid,\n    Tooltip,\n} from 'recharts';\n\nimport formatCurrency from '../../utils/formatCurrency';\n\nimport { \n    Container, \n    ChartContainer,\n    Header,\n    LegendContainer,\n    Legend,\n}  from './styles';\n\n\ninterface IHistoryBoxProps {\n    data: {\n        month: string;\n        amountEntry: number;\n        amountOutput: number;\n    }[],\n    lineColorAmountEntry: string;\n    lineColorAmountOutput: string;\n}\n\nconst HistoryBox: React.FC<IHistoryBoxProps> = ({\n    data, lineColorAmountEntry, lineColorAmountOutput\n}) => (\n    <Container>\n        <Header>\n            <h2>Histórico de saldo</h2>\n\n            <LegendContainer>\n                <Legend color={lineColorAmountEntry}>\n                    <div></div>\n                    <span>Entradas</span>\n                </Legend>\n           \n                <Legend color={lineColorAmountOutput}>\n                    <div></div>\n                    <span>Saídas</span>\n                </Legend>\n            </LegendContainer>\n        </Header>\n\n        <ChartContainer>\n            <ResponsiveContainer>\n                <LineChart data={data} margin={{ top: 5, right: 20, left: 20, bottom: 5 }}>\n                    <CartesianGrid strokeDasharray=\"3 3\" stroke=\"#cecece\" />\n                    <XAxis dataKey=\"month\" stroke=\"#cecece\" />\n                    <Tooltip formatter={(value) => formatCurrency(Number(value))} />\n                    <Line \n                        type=\"monotone\"                \n                        dataKey=\"amountEntry\"\n                        name=\"Entradas\"\n                        stroke={lineColorAmountEntry}\n                        strokeWidth={5}\n                        dot={{ r: 5}}\n                        activeDot={{ r: 8}}\n                    />\n                    <Line \n                        type=\"monotone\"                \n                        dataKey=\"amountOutput\"\n                        name=\"Saídas\"\n                        stroke={lineColorAmountOutput}\n                        strokeWidth={5}\n                        dot={{ r: 5}}\n                        activeDot={{ r: 8}}\n                    />\n                </LineChart>\n            </ResponsiveContainer>\n        </ChartContainer>\n    </Container>\n)\n\nexport default HistoryBox;"
  },
  {
    "path": "src/components/HistoryBox/styles.ts",
    "content": "import styled, {keyframes} from 'styled-components';\n\ninterface ILegendProps {\n    color: string;\n}\n\nconst animate = keyframes`\n    0% {\n        transform: translateX(-100px);\n        opacity: 0;\n    }\n    50%{\n        opacity: .3;\n    }\n    100%{\n        transform: translateX(0px);\n        opacity: 1;\n    }\n`;\n\nexport const Container = styled.div`\n    width: 100%;\n\n    display: flex;\n    flex-direction: column;\n\n    background-color: ${props => props.theme.colors.tertiary};\n    color: ${props => props.theme.colors.white};\n\n    margin: 10px 0;\n    padding: 30px 20px;\n\n    border-radius: 7px;\n\n    animation: ${animate} .5s;\n`;\n\nexport const ChartContainer = styled.div`\n     flex: 1;\n     height: 260px;    \n`;\n\nexport const Header = styled.header`\n    width: 100%;\n   \n    display: flex;\n    justify-content: space-between;\n\n    > h2 {\n        margin-bottom: 20px;\n        padding-left: 16px;\n    }\n\n\n    @media(max-width: 1200px){\n        flex-direction: column;\n    }\n`;\n\nexport const LegendContainer = styled.ul`\n    list-style: none;\n    \n    display: flex;\n    padding-right: 16px;\n`;\n\nexport const Legend = styled.li<ILegendProps>`\n    display: flex;\n    align-items: center;    \n\n    margin-bottom: 7px;    \n    margin-left: 16px;    \n\n    > div {\n        background-color: ${props => props.color};\n\n        width: 40px;\n        height: 40px;\n        border-radius: 5px;\n        \n        font-size: 14px;        \n        line-height: 40px;\n        text-align: center;\n    }\n\n    > span {\n        margin-left: 5px;\n    }\n\n\n    \n    @media(max-width: 1280px){\n        > div {\n            width: 30px;\n            height: 30px;\n        }\n    }\n`;"
  },
  {
    "path": "src/components/HistoryFinanceCard/index.tsx",
    "content": "import React from 'react';\n\nimport { Container, Tag }  from './styles';\n\ninterface IHistoryFinanceCardProps {\n    tagColor: string;\n    title: string;\n    subtitle: string;\n    amount: string;\n}\n\nconst HistoryFinanceCard: React.FC<IHistoryFinanceCardProps> = ({\n    tagColor,\n    title,\n    subtitle,\n    amount\n}) => (\n    <Container>\n        <Tag color={tagColor} />\n        <div>\n            <span>{title}</span>\n            <small>{subtitle}</small>\n        </div>        \n        <h3>{amount}</h3>\n    </Container>\n);\n\n\nexport default HistoryFinanceCard;"
  },
  {
    "path": "src/components/HistoryFinanceCard/styles.ts",
    "content": "import styled, { keyframes } from 'styled-components';\n\ninterface ITagProps {\n  color: string;\n}\n\nconst animate = keyframes`\n    0% {\n        transform: translateX(-100px);\n        opacity: 0;\n    }\n    50%{\n        opacity: .3;\n    }\n    100%{\n        transform: translateX(0px);\n        opacity: 1;\n    }\n`;\n\nexport const Container = styled.li`\n    background-color: ${props => props.theme.colors.tertiary};\n\n    list-style: none;\n    border-radius: 10px;\n\n    margin: 10px 0;\n    padding: 12px 10px;\n\n    display: flex;\n    justify-content: space-between;\n    align-items: center;\n\n    cursor: pointer;\n    transition: all .3s;\n\n    position: relative;\n\n    animation: ${animate} .5s ease;\n\n    &:hover {\n        opacity: .7;\n        transform: translateX(10px);\n    }\n\n\n    > div {\n        display: flex;\n        flex-direction: column;\n        justify-content: space-between;    \n\n        padding-left: 10px;    \n    }\n\n    > div span {\n        font-size: 22px;\n        font-weight: 500;\n    }\n\n    \n\n    \n`;\n\nexport const Tag = styled.div<ITagProps>`\n    width: 13px;\n    height: 60%;\n\n    background-color: ${props => props.color};\n\n    position: absolute;\n    left: 0;\n`;"
  },
  {
    "path": "src/components/Input/index.tsx",
    "content": "import React, { InputHTMLAttributes } from 'react';\n\nimport { Container }  from './styles'\n\ntype IInputProps = InputHTMLAttributes<HTMLInputElement>;\n\nconst Input: React.FC<IInputProps> = ({ ...rest }) => (\n    <Container {...rest} />\n);\n\nexport default Input;"
  },
  {
    "path": "src/components/Input/styles.ts",
    "content": "import styled from 'styled-components';\n\nexport const Container = styled.input`\n    width: 100%;\n\n    margin: 7px 0;\n    padding: 10px;\n\n    border-radius: 5px;\n`;"
  },
  {
    "path": "src/components/Layout/index.tsx",
    "content": "import React from 'react';\n\nimport { Grid } from './styles';\n\nimport MainHeader from '../MainHeader';\nimport Aside from '../Aside';\nimport Content from '../Content';\n\nconst Layout: React.FC = ({ children }) => (\n    <Grid>\n        <MainHeader />\n        <Aside />\n        <Content>\n            { children }\n        </Content>\n    </Grid>\n);\n\n\nexport default Layout;"
  },
  {
    "path": "src/components/Layout/styles.ts",
    "content": "import styled from 'styled-components';\n\n/**\n* Layout\n* MH = Main Header\n* AS = Aside\n* CT = Content    \n*/\n\nexport const Grid = styled.div`\n    display: grid;\n    grid-template-columns: 250px auto;\n    grid-template-rows: 70px auto;\n\n    grid-template-areas:\n    'AS MH'\n    'AS CT';\n\n    height: 100vh;\n    min-width: 315px;\n\n    @media(max-width: 600px){\n        grid-template-columns: 100%;\n        grid-template-rows: 70px auto;\n\n        grid-template-areas:\n        'MH'\n        'CT';\n    }\n`;\n"
  },
  {
    "path": "src/components/MainHeader/index.tsx",
    "content": "import React, { useMemo, useState } from 'react';\nimport Toggle from '../Toggle';\n\nimport emojis from '../../utils/emojis';\n\nimport { useTheme } from '../../hooks/theme';\n\nimport { \n    Container, \n    Profile, \n    Welcome, \n    UserName, \n}  from './styles';\n\n\nconst MainHeader: React.FC = () => {\n    const { toggleTheme, theme } = useTheme();\n\n    const [darkTheme, setDarkTheme] = useState(() => theme.title === 'dark' ? true : false);\n\n    const handleChangeTheme = () => {\n        setDarkTheme(!darkTheme);\n        toggleTheme();\n    }\n\n    const emoji = useMemo(() => {\n        const indice = Math.floor(Math.random() * emojis.length);\n        return emojis[indice];\n    },[]);\n\n    return (\n        <Container>\n            <Toggle\n                labelLeft=\"Light\"\n                labelRight=\"Dark\"\n                checked={darkTheme}\n                onChange={handleChangeTheme}\n            />\n\n            <Profile>\n                <Welcome>Olá, {emoji}</Welcome>\n                <UserName>Rodrigo Gonçalves</UserName>\n            </Profile>\n        </Container>\n    );\n}\n\nexport default MainHeader;"
  },
  {
    "path": "src/components/MainHeader/styles.ts",
    "content": "import styled from 'styled-components';\n\nexport const Container = styled.div`\n    grid-area: MH;\n    \n    background-color: ${props => props.theme.colors.secondary};\n    \n    display: flex;\n    justify-content: space-between;\n    align-items: center;\n\n    padding: 0 10px;\n\n    border-bottom: 1px solid ${props => props.theme.colors.gray};\n`;\n\nexport const Profile = styled.div`\n    color: ${props => props.theme.colors.white};\n`;\n\nexport const Welcome = styled.h3``;\n\nexport const UserName = styled.span``;"
  },
  {
    "path": "src/components/MessageBox/index.tsx",
    "content": "import React from 'react';\n\nimport { Container }  from './styles';\n\ninterface IMessageBoxProps {\n    title: string;\n    description: string;\n    footerText: string;\n    icon: string;\n}\n\nconst MessageBox: React.FC<IMessageBoxProps> = ({\n    title,\n    description,\n    footerText,\n    icon,\n}) => (\n      <Container>\n        <header>\n          <h1>\n              {title}\n              <img src={icon} alt={title}/> \n          </h1>\n          <p>{description}</p>\n        </header>\n\n        <footer>\n          <span>{footerText}</span>\n        </footer>\n      </Container>\n  );\n\n\nexport default MessageBox;"
  },
  {
    "path": "src/components/MessageBox/styles.ts",
    "content": "import styled, {keyframes} from 'styled-components';\n\nconst animate = keyframes`\n    0% {\n        transform: translateX(-100px);\n        opacity: 0;\n    }\n    50%{\n        opacity: .3;\n    }\n    100%{\n        transform: translateX(0px);\n        opacity: 1;\n    }\n`;\n\nexport const Container = styled.div`\n    width: 48%;\n    height: 260px;\n\n    background-color: ${props => props.theme.colors.tertiary};\n    color: ${props => props.theme.colors.white};\n\n    border-radius: 7px;\n\n    margin: 10px 0;\n    padding: 30px 20px;\n\n    display: flex;\n    flex-direction: column;\n    justify-content: space-between;\n\n    animation: ${animate} .5s;\n\n    > header img {\n        width: 35px;\n        margin-left: 7px;\n    }\n\n    > header p {\n        font-size: 18px;\n    }\n\n    @media(max-width: 770px){\n        width: 100%;\n        \n        > header h1 {\n            font-size: 24px;\n\n            img {\n                height: 20px;\n                width: 20px;\n            }\n        }\n\n        > header p, > footer span {\n            font-size: 14px;\n        }\n    }\n\n    @media(max-width: 420px){\n        width: 100%;\n        height: auto;\n\n        > header p {\n            margin-bottom: 15px;\n        }\n    }\n`;"
  },
  {
    "path": "src/components/PieChartBox/index.tsx",
    "content": "import React from 'react';\nimport {\n    PieChart,\n    Pie,\n    Cell,\n    ResponsiveContainer\n} from 'recharts';\n\nimport { \n    Container,\n    SideLeft,\n    LegendContainer,\n    Legend,\n    SideRight,\n }  from './styles';\n\n\n interface IPieChartProps {\n     data: {\n        name: string;\n        value: number;\n        percent: number;\n        color: string;\n     }[];\n }\n\nconst PieChartBox: React.FC<IPieChartProps> = ({ data }) => (\n    <Container>\n        <SideLeft>\n            <h2>Relação</h2>\n            <LegendContainer>\n                {\n                    data.map((indicator) => (\n                        <Legend key={indicator.name} color={indicator.color}>\n                        <div>{indicator.percent}%</div>\n                        <span>{indicator.name}</span>\n                        </Legend>  \n                    ))              \n                }\n            </LegendContainer>\n        </SideLeft>\n\n        <SideRight>\n            <ResponsiveContainer>\n                <PieChart>\n                    <Pie data={data} dataKey=\"percent\">\n                        {\n                            data.map((indicator) => (\n                                <Cell key={indicator.name} fill={indicator.color} />\n                            ))\n                        }\n                    </Pie>\n                </PieChart>\n            </ResponsiveContainer>\n        </SideRight>\n    </Container>\n);\n\nexport default PieChartBox;"
  },
  {
    "path": "src/components/PieChartBox/styles.ts",
    "content": "import styled, { keyframes } from 'styled-components';\n\ninterface ILegendProps {\n    color: string;\n}\n\n\nconst animate = keyframes`\n    0% {\n        transform: translateX(100px);\n        opacity: 0;\n    }\n    50%{\n        opacity: .3;\n    }\n    100%{\n        transform: translateX(0px);\n        opacity: 1;\n    }\n`;\n\n\nexport const Container = styled.div`\n    width: 48%;\n    height: 260px;\n\n    margin: 10px 0;\n\n    background-color: ${props => props.theme.colors.tertiary};\n    color: ${props => props.theme.colors.white};\n\n    border-radius: 7px;\n\n    display: flex;\n\n    animation: ${animate} .5s;\n\n    @media(max-width: 770px){\n        display: flex;\n        width: 100%;\n\n    }\n`;\n\nexport const SideLeft = styled.aside`\n    padding: 30px 20px;\n\n    > h2 {\n        margin-bottom: 20px;\n    }\n\n    @media(max-width: 1345px){\n        padding: 0 15px 5px;\n        margin-bottom: 7px;\n\n        > h2 {\n            margin-top: 15px;\n            margin-bottom: 7px;\n        }\n    }\n\n    @media(max-width: 420px){\n        padding: 15px;\n        margin-bottom: 7px;\n    }\n`;\n\nexport const LegendContainer = styled.ul`\n    list-style: none;\n    \n    height: 175px; \n    padding-right: 15px;\n    overflow-y: scroll;\n\n    ::-webkit-scrollbar {\n        width: 10px;\n    }\n\n    ::-webkit-scrollbar-thumb {\n        background-color: ${props => props.theme.colors.secondary};\n        border-radius: 10px;\n    }\n\n    ::-webkit-scrollbar-track {\n        background-color: ${props => props.theme.colors.tertiary};\n    }\n\n\n    @media(max-width: 1345px){\n        display: flex;\n        flex-direction: column;\n    }\n`;\n\nexport const Legend = styled.li<ILegendProps>`\n    display: flex;\n    align-items: center;\n\n    margin-bottom: 7px;    \n\n    > div {\n        background-color: ${props => props.color};\n\n        width: 40px;\n        height: 40px;\n        border-radius: 5px;\n        \n        font-size: 14px;        \n        line-height: 40px;\n        text-align: center;\n    }\n\n    > span {\n        margin-left: 5px;\n    }\n\n    @media(max-width: 145px){\n        font-size: 14px;\n        margin: 3px 0;\n\n        > div {\n            height: 35px;\n            width: 35px;\n            line-height: 35px;\n        }\n\n        > span {\n            margin-left: 7px;\n        }\n    }\n`;\n\nexport const SideRight = styled.main`\n    display: flex;\n    flex: 1;\n    justify-content: center;\n\n    @media(max-width: 1345px){\n        height: 100%;\n    }\n`;"
  },
  {
    "path": "src/components/SelectInput/index.tsx",
    "content": "import React from 'react';\n\nimport { Container }  from './styles';\n\ninterface ISelectInputProps {\n    options: {\n        value: string | number;\n        label: string | number;\n    }[],    \n    onChange(event: React.ChangeEvent<HTMLSelectElement>): void | undefined;\n    defaultValue?: string | number;\n}\n\nconst SelectInput: React.FC<ISelectInputProps> = ({ \n  options, \n  onChange, \n  defaultValue \n}) => (\n    <Container>\n      <select onChange={onChange} defaultValue={defaultValue}>\n        {\n          options.map(option => (\n            <option \n            key={option.value}\n            value={option.value}\n            >\n              {option.label}\n            </option>\n          ))              \n        }\n      </select>\n    </Container>\n);\n\n\nexport default SelectInput;"
  },
  {
    "path": "src/components/SelectInput/styles.ts",
    "content": "import styled from 'styled-components';\n\nexport const Container = styled.div`\n\n    > select {\n        padding: 7px 10px;\n        border-radius: 5px;\n\n        margin-left: 7px;\n    }\n`;"
  },
  {
    "path": "src/components/Toggle/index.tsx",
    "content": "import React from 'react';\n\nimport {\n    Container,\n    ToggleLabel,\n    ToggleSelector\n} from './styles';\n\n\ninterface IToggleProps {\n    labelLeft: string;\n    labelRight: string;\n    checked: boolean;\n    onChange(): void;\n}\n\nconst Toggle: React.FC<IToggleProps> = ({\n    labelLeft,\n    labelRight,\n    checked,\n    onChange\n}) => (\n    <Container>\n        <ToggleLabel>{labelLeft}</ToggleLabel>\n        <ToggleSelector                    \n            checked={checked}\n            uncheckedIcon={false}\n            checkedIcon={false}\n            onChange={onChange}\n        />\n        <ToggleLabel>{labelRight}</ToggleLabel>\n    </Container>\n)\n\nexport default Toggle;"
  },
  {
    "path": "src/components/Toggle/styles.ts",
    "content": "import styled from 'styled-components';\nimport Switch, { ReactSwitchProps } from 'react-switch';\n\nexport const Container = styled.div`\n    display: flex;\n    align-items: center;\n`;\n\nexport const ToggleLabel = styled.span`\n    color: ${props => props.theme.colors.white};\n`;\n\nexport const ToggleSelector = styled(Switch).attrs<ReactSwitchProps>(\n    ({ theme }) => ({\n        onColor: theme.colors.info,\n        offColor: theme.colors.warning\n    }))<ReactSwitchProps>`\n    margin: 0 7px;\n`;\n"
  },
  {
    "path": "src/components/WalletBox/index.tsx",
    "content": "import React, { useMemo } from 'react';\nimport CountUp from 'react-countup';\n\nimport dolarImg from '../../assets/dolar.svg';\nimport arrowUpImg from '../../assets/arrow-up.svg';\nimport arrowDownImg from '../../assets/arrow-down.svg';\n\n\nimport { Container }  from './styles';\n\ninterface IWalletBoxProps {\n    title: string;\n    amount: number;\n    footerlabel: string;\n    icon: 'dolar' | 'arrowUp' | 'arrowDown';\n    color: string;\n}\n\nconst WalletBox: React.FC<IWalletBoxProps> = ({\n    title,\n    amount,\n    footerlabel,\n    icon,\n    color\n}) => {\n\n    const iconSelected = useMemo(() => {\n        switch (icon) {\n            case 'dolar':\n                return dolarImg;\n            case 'arrowUp': \n                return arrowUpImg;\n            case 'arrowDown':\n                return arrowDownImg;\n            default:\n              return undefined;\n        }\n    },[icon]);\n\n    return (\n        <Container color={color}>\n            <span>{title}</span>\n            <h1>\n                <strong>R$ </strong>\n                <CountUp \n                    end={amount}\n                    separator=\".\"\n                    decimal=\",\"\n                    decimals={2}                                    \n                />\n            </h1>\n            <small>{footerlabel}</small>\n            <img src={iconSelected} alt={title} />\n        </Container>\n    );\n}\n\nexport default WalletBox;"
  },
  {
    "path": "src/components/WalletBox/styles.ts",
    "content": "import styled, {keyframes} from 'styled-components';\n\ninterface IContainerProps {\n    color: string;\n}\n\nconst animate = keyframes`\n    0%{\n        transform: translateX(100px);\n        opacity: 0;\n    }\n    50%{     \n        opacity: .3;\n    }\n    100%{\n        transform: translateX(0px);\n        opacity: 1;\n    }\n`;\n\nexport const Container = styled.div<IContainerProps>`\n    width: 32%;\n    height: 150px;\n\n    margin: 10px 0;\n    \n    background-color: ${props => props.color};\n    color: ${props => props.theme.colors.white};\n\n    border-radius: 7px;\n    padding: 10px 20px;\n\n    position: relative;\n    overflow: hidden;\n\n    animation: ${animate} .5s;\n\n    > img {\n        height: 110%;\n        \n        position: absolute;\n        top: -10px;\n        right: -30px;\n\n        opacity: .3;\n    }\n\n    > span {\n        font-size: 18px;\n        font-weight: 500;\n    }\n\n    > small {\n        font-size: 12px;\n        position: absolute;\n        bottom: 10px;\n    }\n\n\n\n    @media(max-width: 770px){\n        > span {\n            font-size: 14px;\n        }\n\n        > h1 {\n            word-wrap: break-word;\n            font-size: 22px;\n\n            strong {\n                display: inline-block;\n                width: 100%;\n                font-size: 16px;\n            }\n        }\n    }\n\n    @media(max-width: 420px){\n        width: 100%;\n\n        > h1 {\n            display: flex;\n            \n            strong {\n                position: initial;        \n                width: auto;\n                font-size: 22px;\n            }\n\n            strong:after {\n                display: inline-block;\n                content: '';\n                width: 1px;                \n            }\n        }\n    }\n`;"
  },
  {
    "path": "src/hooks/auth.tsx",
    "content": "import React, { createContext, useState, useContext } from 'react';\n\ninterface IAuthContext {\n    logged: boolean;\n    signIn(email: string, password: string): void;\n    signOut(): void;\n}\n\nconst AuthContext = createContext<IAuthContext>({} as IAuthContext);\n\nconst AuthProvider: React.FC = ({ children }) => {\n    const [logged, setLogged] = useState<boolean>(() => {\n        const isLogged = localStorage.getItem('@minha-carteira:logged');\n\n        return !!isLogged;\n    });\n\n    const signIn = (email: string, password: string) => {\n        if(email === 'rodrigo@email.com' && password === '123'){\n            localStorage.setItem('@minha-carteira:logged', 'true');\n            setLogged(true);\n        }else{\n            alert('Senha ou usuário inválidos!');\n        }\n    }\n\n    const signOut = () => {\n        localStorage.removeItem('@minha-carteira:logged');\n        setLogged(false);\n    }\n\n    return (\n        <AuthContext.Provider value={{logged, signIn, signOut}}>\n            {children}\n        </AuthContext.Provider>\n    );\n}\n\nfunction useAuth(): IAuthContext {\n    const context = useContext(AuthContext);\n\n    return context;\n}\n\nexport { AuthProvider, useAuth };"
  },
  {
    "path": "src/hooks/theme.tsx",
    "content": "import React, { createContext, useState, useContext } from 'react';\n\nimport dark from '../styles/themes/dark';\nimport light from '../styles/themes/light';\n\ninterface IThemeContext {\n    toggleTheme(): void;\n    theme: ITheme;\n}\n\ninterface ITheme {\n    title: string;\n\n    colors: {\n        primary: string;\n        secondary: string;\n        tertiary: string;\n\n        white: string;\n        black: string;\n        gray: string;\n\n        success: string;\n        info: string;\n        warning: string;\n    }\n}\n\nconst ThemeContext = createContext<IThemeContext>({} as IThemeContext);\n\nconst ThemeProvider: React.FC = ({ children }) => {\n    const [theme, setTheme] = useState<ITheme>(() => {\n        const themeSaved = localStorage.getItem('@minha-carteira:theme');\n\n        if(themeSaved) {\n            return JSON.parse(themeSaved);\n        }else{\n            return dark;\n        }\n    });\n\n    const toggleTheme = () => {\n        if(theme.title === 'dark'){\n            setTheme(light);\n            localStorage.setItem('@minha-carteira:theme', JSON.stringify(light));\n        }else{\n            setTheme(dark);\n            localStorage.setItem('@minha-carteira:theme', JSON.stringify(dark));\n        }\n    };\n\n    return (\n        <ThemeContext.Provider value={{ toggleTheme, theme }}>\n            {children}\n        </ThemeContext.Provider>\n    )\n}\n\nfunction useTheme(): IThemeContext {\n    const context = useContext(ThemeContext);\n\n    return context;\n}\n\n\nexport { ThemeProvider, useTheme };\n"
  },
  {
    "path": "src/index.tsx",
    "content": "import React from 'react';\nimport ReactDOM from 'react-dom';\n\nimport { ThemeProvider } from './hooks/theme';\nimport { AuthProvider } from './hooks/auth';\n\nimport App from './App';\n\nReactDOM.render(\n  <React.StrictMode>    \n    <ThemeProvider>\n      <AuthProvider>\n        <App />\n      </AuthProvider>\n    </ThemeProvider>\n  </React.StrictMode>,\n  document.getElementById('root')\n);"
  },
  {
    "path": "src/pages/Dashboard/index.tsx",
    "content": "import React, { useState, useMemo, useCallback } from 'react';\n\n\nimport ContentHeader from '../../components/ContentHeader';\nimport SelectInput from '../../components/SelectInput';\nimport WalletBox from '../../components/WalletBox';\nimport MessageBox from '../../components/MessageBox';\nimport PieChartBox from '../../components/PieChartBox';\nimport HistoryBox from '../../components/HistoryBox';\nimport BarChartBox from '../../components/BarChartBox'\n\nimport expenses from '../../repositories/expenses';\nimport gains from '../../repositories/gains';\nimport listOfMonths from '../../utils/months';\n\nimport happyImg from '../../assets/happy.svg';\nimport sadImg from '../../assets/sad.svg';\nimport grinningImg from '../../assets/grinning.svg';\nimport opsImg from '../../assets/ops.svg';\n\n\nimport { \n    Container,\n    Content, \n} from './styles';\n\n\nconst Dashboard: React.FC = () => {\n    const [monthSelected, setMonthSelected] = useState<number>(new Date().getMonth() + 1);\n    const [yearSelected, setYearSelected] = useState<number>(new Date().getFullYear());\n\n\n    const years = useMemo(() => {\n        let uniqueYears: number[] = [];\n\n        [...expenses, ...gains].forEach(item => {\n            const date = new Date(item.date);\n            const year = date.getFullYear();\n\n            if(!uniqueYears.includes(year)){\n                uniqueYears.push(year)\n           }\n        });\n\n        return uniqueYears.map(year => {\n            return {\n                value: year,\n                label: year,\n            }\n        });\n    },[]);\n\n\n    const months = useMemo(() => {\n        return listOfMonths.map((month, index) => {\n            return {\n                value: index + 1,\n                label: month,\n            }\n        });\n    },[]);\n    \n    \n    const totalExpenses = useMemo(() => {\n        let total: number = 0;\n\n        expenses.forEach(item => {\n            const date = new Date(item.date);\n            const year = date.getFullYear();\n            const month = date.getMonth() + 1;\n\n            if(month === monthSelected && year === yearSelected){\n                try{\n                    total += Number(item.amount)\n                }catch{\n                    throw new Error('Invalid amount! Amount must be number.')\n                }\n            }\n        });\n\n        return total;\n    },[monthSelected, yearSelected]);\n\n\n    const totalGains = useMemo(() => {\n        let total: number = 0;\n\n        gains.forEach(item => {\n            const date = new Date(item.date);\n            const year = date.getFullYear();\n            const month = date.getMonth() + 1;\n\n            if(month === monthSelected && year === yearSelected){\n                try{\n                    total += Number(item.amount)\n                }catch{\n                    throw new Error('Invalid amount! Amount must be number.')\n                }\n            }\n        });\n\n        return total;\n    },[monthSelected, yearSelected]);\n\n    const totalBalance = useMemo(() => {\n        return totalGains - totalExpenses;\n    },[totalGains, totalExpenses]);\n\n    const message = useMemo(() => {\n        if(totalBalance < 0){\n            return {\n                title: \"Que triste!\",\n                description: \"Neste mês, você gastou mais do que deveria.\",\n                footerText: \"Verifique seus gastos e tente cortar algumas coisas desnecessárias.\",\n                icon: sadImg\n            }\n        }      \n        else if(totalGains === 0 && totalExpenses === 0){\n            return {\n                title: \"Op's!\",\n                description: \"Neste mês, não há registros de entradas ou saídas.\",\n                footerText: \"Parece que você não fez nenhum registro no mês e ano selecionado.\",\n                icon: opsImg\n            }\n        }\n        else if(totalBalance === 0){\n            return {\n                title: \"Ufaa!\",\n                description: \"Neste mês, você gastou exatamente o que ganhou.\",\n                footerText: \"Tenha cuidado. No próximo tente poupar o seu dinheiro.\",\n                icon: grinningImg\n            }\n        }\n        else{\n            return {\n                title: \"Muito bem!\",\n                description: \"Sua carteira está positiva!\",\n                footerText: \"Continue assim. Considere investir o seu saldo.\",\n                icon: happyImg\n            }\n        }\n\n    },[totalBalance, totalGains, totalExpenses]);\n\n    const relationExpensesVersusGains = useMemo(() => {\n        const total = totalGains + totalExpenses;\n\n        const percentGains = Number(((totalGains / total) * 100).toFixed(1));\n        const percentExpenses = Number(((totalExpenses / total) * 100).toFixed(1));\n\n        const data = [\n            {\n                name: \"Entradas\",\n                value: totalGains,\n                percent: percentGains ? percentGains : 0, \n                color: '#E44C4E'\n            },\n            {\n                name: \"Saídas\",\n                value: totalExpenses,\n                percent: percentExpenses ? percentExpenses : 0, \n                color: '#F7931B'\n            },\n        ];\n\n        return data;\n    },[totalGains, totalExpenses]);\n\n    const historyData = useMemo(() => {\n        return listOfMonths\n        .map((_, month) => {\n            \n            let amountEntry = 0;\n            gains.forEach(gain => {\n                const date = new Date(gain.date);\n                const gainMonth = date.getMonth();\n                const gainYear = date.getFullYear();\n\n                if(gainMonth === month && gainYear === yearSelected){\n                    try{\n                        amountEntry += Number(gain.amount);\n                    }catch{\n                        throw new Error('amountEntry is invalid. amountEntry must be valid number.')\n                    }\n                }\n            });\n\n            let amountOutput = 0;\n            expenses.forEach(expense => {\n                const date = new Date(expense.date);\n                const expenseMonth = date.getMonth();\n                const expenseYear = date.getFullYear();\n\n                if(expenseMonth === month && expenseYear === yearSelected){\n                    try{\n                        amountOutput += Number(expense.amount);\n                    }catch{\n                        throw new Error('amountOutput is invalid. amountOutput must be valid number.')\n                    }\n                }\n            });\n\n\n            return {\n                monthNumber: month,\n                month: listOfMonths[month].substr(0, 3),\n                amountEntry,\n                amountOutput\n            }\n        })\n        .filter(item => {\n            const currentMonth = new Date().getMonth();\n            const currentYear = new Date().getFullYear();\n            return (yearSelected === currentYear && item.monthNumber <= currentMonth) || (yearSelected < currentYear)\n        });\n    },[yearSelected]);\n\n    const relationExpensevesRecurrentVersusEventual = useMemo(() => {\n        let amountRecurrent = 0;\n        let amountEventual = 0;\n\n        expenses\n        .filter((expense) => {\n            const date = new Date(expense.date);\n            const year = date.getFullYear();\n            const month = date.getMonth() + 1;\n\n            return month === monthSelected && year === yearSelected;\n        })\n        .forEach((expense) => {\n            if(expense.frequency === 'recorrente'){\n                return amountRecurrent += Number(expense.amount);\n            }\n\n            if(expense.frequency === 'eventual'){\n                return amountEventual += Number(expense.amount);\n            }\n        });\n\n        const total = amountRecurrent + amountEventual;\n\n        const percentRecurrent = Number(((amountRecurrent / total) * 100).toFixed(1));\n        const percentEventual = Number(((amountEventual / total) * 100).toFixed(1));\n\n        return [\n            {\n                name: 'Recorrentes',\n                amount: amountRecurrent,\n                percent: percentRecurrent ? percentRecurrent : 0, \n                color: \"#F7931B\"\n            },\n            {\n                name: 'Eventuais',\n                amount: amountEventual,\n                percent: percentEventual ? percentEventual : 0,\n                color: \"#E44C4E\"\n            }\n        ];\n    },[monthSelected, yearSelected]);\n\n\n    const relationGainsRecurrentVersusEventual = useMemo(() => {\n        let amountRecurrent = 0;\n        let amountEventual = 0;\n\n        gains\n        .filter((gain) => {\n            const date = new Date(gain.date);\n            const year = date.getFullYear();\n            const month = date.getMonth() + 1;\n\n            return month === monthSelected && year === yearSelected;\n        })\n        .forEach((gain) => {\n            if(gain.frequency === 'recorrente'){\n                return amountRecurrent += Number(gain.amount);\n            }\n\n            if(gain.frequency === 'eventual'){\n                return amountEventual += Number(gain.amount);\n            }\n        });\n\n        const total = amountRecurrent + amountEventual;\n\n        const percentRecurrent = Number(((amountRecurrent / total) * 100).toFixed(1));\n        const percentEventual = Number(((amountEventual / total) * 100).toFixed(1));\n\n        return [\n            {\n                name: 'Recorrentes',\n                amount: amountRecurrent,\n                percent: percentRecurrent ? percentRecurrent : 0,\n                color: \"#F7931B\"\n            },\n            {\n                name: 'Eventuais',\n                amount: amountEventual,\n                percent: percentEventual ? percentEventual : 0,\n                color: \"#E44C4E\"\n            }\n        ];\n    },[monthSelected, yearSelected]);\n\n    const handleMonthSelected = useCallback((month: string) => {\n        try {\n            const parseMonth = Number(month);\n            setMonthSelected(parseMonth);\n        }\n        catch{\n            throw new Error('invalid month value. Is accept 0 - 24.')\n        }\n    },[]);\n\n\n    const handleYearSelected = useCallback((year: string) => {\n        try {\n            const parseYear = Number(year);\n            setYearSelected(parseYear);\n        }\n        catch{\n            throw new Error('invalid year value. Is accept integer numbers.')\n        }\n    },[]);\n\n\n    return (\n        <Container>\n            <ContentHeader title=\"Dashboard\" lineColor=\"#F7931B\">\n                <SelectInput \n                    options={months}\n                    onChange={(e) => handleMonthSelected(e.target.value)} \n                    defaultValue={monthSelected}\n                />\n                <SelectInput \n                    options={years} \n                    onChange={(e) => handleYearSelected(e.target.value)} \n                    defaultValue={yearSelected}\n                />\n            </ContentHeader>\n\n            <Content>\n                <WalletBox \n                    title=\"saldo\"\n                    color=\"#4E41F0\"\n                    amount={totalBalance}\n                    footerlabel=\"atualizado com base nas entradas e saídas\"\n                    icon=\"dolar\"\n                />\n\n                <WalletBox \n                    title=\"entradas\"\n                    color=\"#F7931B\"\n                    amount={totalGains}\n                    footerlabel=\"atualizado com base nas entradas e saídas\"\n                    icon=\"arrowUp\"\n                />\n\n                <WalletBox \n                    title=\"saídas\"\n                    color=\"#E44C4E\"\n                    amount={totalExpenses}\n                    footerlabel=\"atualizado com base nas entradas e saídas\"\n                    icon=\"arrowDown\"\n                />\n\n                <MessageBox\n                    title={message.title}\n                    description={message.description}\n                    footerText={message.footerText}\n                    icon={message.icon}\n                />\n\n                <PieChartBox data={relationExpensesVersusGains} />\n\n                <HistoryBox \n                    data={historyData} \n                    lineColorAmountEntry=\"#F7931B\"\n                    lineColorAmountOutput=\"#E44C4E\"\n                />\n\n                <BarChartBox \n                    title=\"Saídas\"\n                    data={relationExpensevesRecurrentVersusEventual} \n                />\n                \n                <BarChartBox \n                    title=\"Entradas\"\n                    data={relationGainsRecurrentVersusEventual} \n                />\n                \n            </Content>\n        </Container>\n    );\n}\n\nexport default Dashboard;"
  },
  {
    "path": "src/pages/Dashboard/styles.ts",
    "content": "import styled from 'styled-components';\n\nexport const Container = styled.div``;\n\nexport const Content = styled.div`\n    display: flex;\n    justify-content: space-between;\n    flex-wrap: wrap;\n`;\n"
  },
  {
    "path": "src/pages/List/index.tsx",
    "content": "import React, { useMemo, useState, useEffect } from 'react';\nimport { uuid } from 'uuidv4';\n \nimport ContentHeader from '../../components/ContentHeader';\nimport SelectInput from '../../components/SelectInput';\nimport HistoryFinanceCard from '../../components/HistoryFinanceCard';\n\nimport gains from '../../repositories/gains';\nimport expenses from '../../repositories/expenses';\nimport formatCurrency from '../../utils/formatCurrency';\nimport formatDate from '../../utils/formatDate';\nimport listOfMonths from '../../utils/months';\n\nimport { \n    Container, \n    Content, \n    Filters \n} from './styles';\n\ninterface IRouteParams {\n    match: {\n        params: {\n            type: string;\n        }\n    }\n}\n\ninterface IData {\n    id: string;\n    description: string;\n    amountFormatted: string;\n    frequency: string;\n    dateFormatted: string;\n    tagColor: string;\n}\n\nconst List: React.FC<IRouteParams> = ({ match }) => {\n    const [data, setData] = useState<IData[]>([]);\n    const [monthSelected, setMonthSelected] = useState<number>(new Date().getMonth() + 1);\n    const [yearSelected, setYearSelected] = useState<number>(new Date().getFullYear());\n    const [frequencyFilterSelected, setFrequencyFilterSelected] = useState(['recorrente', 'eventual']);\n    \n    const movimentType = match.params.type;\n\n\n    const pageData = useMemo(() => {\n        return movimentType === 'entry-balance' ?\n            {\n                title: 'Entradas',\n                lineColor: '#4E41F0',\n                data: gains\n            }\n            :       \n            {\n                title: 'Saídas',\n                lineColor: '#E44C4E',\n                data: expenses\n            }       \n    },[movimentType]);\n     \n\n    const years = useMemo(() => {\n        let uniqueYears: number[] = [];\n\n        const { data } = pageData;\n\n        data.forEach(item => {\n            const date = new Date(item.date);\n            const year = date.getFullYear();\n\n            if(!uniqueYears.includes(year)){\n                uniqueYears.push(year)\n           }\n        });\n\n        return uniqueYears.map(year => {\n            return {\n                value: year,\n                label: year,\n            }\n        });\n    },[pageData]);\n\n\n    const months = useMemo(() => {\n        return listOfMonths.map((month, index) => {\n            return {\n                value: index + 1,\n                label: month,\n            }\n        });\n    },[]);\n\n\n    const handleFrequencyClick = (frequency: string) => {\n        const alreadySelected = frequencyFilterSelected.findIndex(item => item === frequency);\n\n        if(alreadySelected >= 0){\n            const filtered = frequencyFilterSelected.filter(item => item !== frequency);\n            setFrequencyFilterSelected(filtered);\n        }else{            \n            setFrequencyFilterSelected((prev) => [...prev, frequency]); \n        }\n    }\n\n    const handleMonthSelected = (month: string) => {\n        try {\n            const parseMonth = Number(month);\n            setMonthSelected(parseMonth);\n        }\n        catch{\n            throw new Error('invalid month value. Is accept 0 - 24.')\n        }\n    }\n\n    const handleYearSelected = (year: string) => {\n        try {\n            const parseYear = Number(year);\n            setYearSelected(parseYear);\n        }\n        catch{\n            throw new Error('invalid year value. Is accept integer numbers.')\n        }\n    }\n\n\n    useEffect(() => {        \n        const { data } = pageData;\n\n        const filteredData = data.filter(item => {\n            const date = new Date(item.date);\n            const month = date.getMonth() + 1;\n            const year = date.getFullYear();\n\n            return month === monthSelected && year === yearSelected && frequencyFilterSelected.includes(item.frequency);\n        });\n\n        const formattedData = filteredData.map(item => {\n            return {\n                id: uuid(),\n                description: item.description,\n                amountFormatted: formatCurrency(Number(item.amount)),\n                frequency: item.frequency,\n                dateFormatted: formatDate(item.date),\n                tagColor: item.frequency === 'recorrente' ? '#4E41F0' : '#E44C4E',\n            }\n        });\n        \n        setData(formattedData);\n    },[pageData, monthSelected, yearSelected, data.length, frequencyFilterSelected]); \n\n\n    return (\n        <Container>\n            <ContentHeader title={pageData.title} lineColor={pageData.lineColor}>\n                <SelectInput \n                    options={months}\n                    onChange={(e) => handleMonthSelected(e.target.value)} \n                    defaultValue={monthSelected}\n                />\n                <SelectInput \n                    options={years} \n                    onChange={(e) => handleYearSelected(e.target.value)} \n                    defaultValue={yearSelected}\n                />\n            </ContentHeader>\n\n            <Filters>\n                <button \n                    type=\"button\"\n                    className={`\n                    tag-filter \n                    tag-filter-recurrent\n                    ${frequencyFilterSelected.includes('recorrente') && 'tag-actived'}`}\n                    onClick={() => handleFrequencyClick('recorrente')}\n                >\n                    Recorrentes\n                </button>\n\n                <button \n                    type=\"button\"\n                    className={`\n                    tag-filter \n                    tag-filter-eventual\n                    ${frequencyFilterSelected.includes('eventual') && 'tag-actived'}`}\n                    onClick={() => handleFrequencyClick('eventual')}\n                >\n                    Eventuais\n                </button>\n            </Filters>\n\n            <Content>\n                {\n                    data.map(item => (\n                        <HistoryFinanceCard \n                            key={item.id}\n                            tagColor={item.tagColor}\n                            title={item.description}\n                            subtitle={item.dateFormatted}\n                            amount={item.amountFormatted}\n                        />\n                    ))\n                }     \n            </Content>            \n        </Container>\n    );\n}\n\nexport default List;"
  },
  {
    "path": "src/pages/List/styles.ts",
    "content": "import styled from 'styled-components';\n\nexport const Container = styled.div``;\n\nexport const Content = styled.main``;\n\nexport const Filters = styled.div`\n    width: 100%;\n    \n    display: flex;\n    justify-content: center;\n    \n    margin-bottom: 30px;\n\n    .tag-filter {\n        font-size: 18px;\n        font-weight: 500;\n\n        background: none;\n        color: ${props => props.theme.colors.white};\n\n        margin: 0 10px;\n        \n        opacity: .4;\n        transition: opacity .3s;\n\n        &:hover {\n            opacity: .7;\n        }\n    }\n\n    .tag-filter-recurrent::after {\n        content: '';\n        display: block;\n        width: 55px;\n        margin: 0 auto;\n        border-bottom: 10px solid ${props => props.theme.colors.success};    \n    }\n\n    .tag-filter-eventual::after {\n        content: '';\n        display: block;\n        width: 55px;\n        margin: 0 auto;\n        border-bottom: 10px solid ${props => props.theme.colors.warning};    \n    }\n    \n    .tag-actived {\n       opacity: 1;\n    }\n`;"
  },
  {
    "path": "src/pages/SignIn/index.tsx",
    "content": "import React, {useState} from 'react';\n\nimport logoImg from '../../assets/logo.svg';\n\nimport Input from '../../components/Input';\nimport Button from '../../components/Button';\n\nimport { useAuth } from '../../hooks/auth';\n\nimport {\n    Container,\n    Logo,\n    Form,\n    FormTitle,\n} from './styles';\n\nconst SignIn: React.FC = () => {\n    const [email, setEmail] = useState<string>('');\n    const [password, setPassword] = useState<string>('');    \n\n    const { signIn } = useAuth();\n\n    return (\n        <Container>\n            <Logo>\n                <img src={logoImg} alt=\"Minha Carteira\" />\n                <h2>Minha Carteira</h2>\n            </Logo>\n\n            <Form onSubmit={() => signIn(email, password)}>\n                <FormTitle>Entrar</FormTitle>\n\n                <Input \n                    type=\"email\"\n                    placeholder=\"e-mail\"\n                    required\n                    onChange={(e) => setEmail(e.target.value)}\n                />\n                <Input \n                    type=\"password\"\n                    placeholder=\"senha\"\n                    required\n                    onChange={(e) => setPassword(e.target.value)}\n                />\n\n               <Button type=\"submit\">Acessar</Button>\n            </Form>\n        </Container>\n    );\n}\n\nexport default SignIn;"
  },
  {
    "path": "src/pages/SignIn/styles.ts",
    "content": "import styled from 'styled-components';\n\nexport const Container = styled.div`\n    height: 100vh;\n    \n    display: flex;\n    flex: 1;\n    flex-direction: column;\n    justify-content: center;\n    align-items: center;\n\n    background-color: ${props => props.theme.colors.primary};\n`;\n\nexport const Logo = styled.div`\n    display: flex;\n    align-items: center;\n\n    margin-bottom: 30px;\n\n    > h2 {\n        color: ${props => props.theme.colors.white}; \n        margin-left: 7px;\n    }\n\n    > img {\n        width: 40px;\n        height: 40px;\n    }\n`;\n\nexport const Form = styled.form`\n    width: 300px;\n    height: 300px;\n\n    padding: 30px;\n\n    border-radius: 10px;\n\n    background-color: ${props => props.theme.colors.tertiary};\n`;\n\nexport const FormTitle = styled.h1`\n    margin-bottom: 40px;\n\n    color: ${props => props.theme.colors.white}; \n\n    &:after {\n        content: '';\n        display: block;\n        width: 55px;\n        border-bottom: 10px solid ${props => props.theme.colors.warning};  \n    }\n`;\n\n"
  },
  {
    "path": "src/react-app-env.d.ts",
    "content": "/// <reference types=\"react-scripts\" />\n"
  },
  {
    "path": "src/repositories/expenses.ts",
    "content": "export default [\n  {\"description\":\"Energia elétrica\",      \"amount\":\"150.55\",\"type\":\"saída\",\"frequency\":\"recorrente\",\"date\":\"2020-01-10\"},\n  {\"description\":\"Água\",                  \"amount\":\"75.55\", \"type\":\"saída\",\"frequency\":\"recorrente\",\"date\":\"2020-01-15\"},\n  {\"description\": \"Telefone\",             \"amount\":\"99.99\", \"type\":\"saída\",\"frequency\":\"recorrente\",\"date\":\"2020-01-23\"},\n  {\"description\":\"Plano de Saúde\",        \"amount\":\"300.00\",\"type\":\"saída\",\"frequency\":\"recorrente\",\"date\":\"2020-01-23\"},\n  {\"description\":\"Compras do mês\",        \"amount\":\"625.78\",\"type\":\"saída\",\"frequency\":\"recorrente\",\"date\":\"2020-01-23\"},\n  {\"description\":\"Lanche\",                \"amount\":\"45.70\", \"type\":\"saída\",\"frequency\":\"eventual\",  \"date\":\"2020-01-23\"},\n  {\"description\":\"Blusa\",                 \"amount\":\"95.70\", \"type\":\"saída\",\"frequency\":\"eventual\",  \"date\":\"2020-01-23\"},\n  {\"description\":\"Energia elétrica\",      \"amount\":\"125.55\",\"type\":\"saída\",\"frequency\":\"recorrente\",\"date\":\"2020-02-10\"},\n  {\"description\":\"Água\",                  \"amount\":\"90.15\", \"type\":\"saída\",\"frequency\":\"recorrente\",\"date\":\"2020-02-15\"},\n  {\"description\":\"Telefone\",              \"amount\":\"99.99\", \"type\":\"saída\",\"frequency\":\"recorrente\",\"date\":\"2020-02-23\"},\n  {\"description\":\"Plano de Saúde\",        \"amount\":\"300.00\",\"type\":\"saída\",\"frequency\":\"recorrente\",\"date\":\"2020-02-23\"},\n  {\"description\":\"Compras do mês\",        \"amount\":\"540.00\",\"type\":\"saída\",\"frequency\":\"recorrente\",\"date\":\"2020-02-25\"},\n  {\"description\":\"Parcela do Celular 1/5\",\"amount\":\"150.99\",\"type\":\"saída\",\"frequency\":\"eventual\",  \"date\":\"2020-02-26\"},\n  {\"description\":\"Cinema\",                \"amount\":\"45.00\", \"type\":\"saída\",\"frequency\":\"eventual\",  \"date\":\"2020-02-23\"},\n  {\"description\":\"Energia elétrica\",      \"amount\":\"97.00\", \"type\":\"saída\",\"frequency\":\"recorrente\",\"date\":\"2020-03-10\"},\n  {\"description\":\"Água\",                  \"amount\":\"100.10\",\"type\":\"saída\",\"frequency\":\"recorrente\",\"date\":\"2020-03-15\"},\n  {\"description\":\"Telefone\",              \"amount\":\"99.99\", \"type\":\"saída\",\"frequency\":\"recorrente\",\"date\":\"2020-03-23\"},\n  {\"description\":\"Plano de Saúde\",        \"amount\":\"300.00\",\"type\":\"saída\",\"frequency\":\"recorrente\",\"date\":\"2020-03-23\"},\n  {\"description\":\"Compras do mês\",        \"amount\":\"800.50\",\"type\":\"saída\",\"frequency\":\"recorrente\",\"date\":\"2020-03-17\"},\n  {\"description\":\"Parcela do Celular 2/5\",\"amount\":\"150.99\",\"type\":\"saída\",\"frequency\":\"eventual\",  \"date\":\"2020-03-18\"},\n  {\"description\":\"Troca de Oléo do carro\",\"amount\":\"90.00\", \"type\":\"saída\",\"frequency\":\"eventual\",  \"date\":\"2020-03-23\"},\n  {\"description\":\"Energia elétrica\",      \"amount\":\"75.99\", \"type\":\"saída\",\"frequency\":\"recorrente\",\"date\":\"2020-04-10\"},\n  {\"description\":\"Água\",                  \"amount\":\"80.33\", \"type\":\"saída\",\"frequency\":\"recorrente\",\"date\":\"2020-04-15\"},\n  {\"description\":\"Telefone\",              \"amount\":\"99.99\", \"type\":\"saída\",\"frequency\":\"recorrente\",\"date\":\"2020-04-23\"},\n  {\"description\":\"Plano de Saúde\",        \"amount\":\"300.00\",\"type\":\"saída\",\"frequency\":\"recorrente\",\"date\":\"2020-04-23\"},\n  {\"description\":\"Compras do mês\",        \"amount\":\"600.00\",\"type\":\"saída\",\"frequency\":\"recorrente\",\"date\":\"2020-04-25\"},\n  {\"description\":\"Parcela do Celular 3/5\",\"amount\":\"150.99\",\"type\":\"saída\",\"frequency\":\"eventual\",  \"date\":\"2020-04-26\"},\n  {\"description\":\"Ebook de React Js\",     \"amount\":\"85.95\", \"type\":\"saída\",\"frequency\":\"eventual\",  \"date\":\"2020-04-13\"},\n  {\"description\":\"Energia elétrica\",      \"amount\":\"125.55\",\"type\":\"saída\",\"frequency\":\"recorrente\",\"date\":\"2020-05-10\"},\n  {\"description\":\"Água\",                  \"amount\":\"90.15\", \"type\":\"saída\",\"frequency\":\"recorrente\",\"date\":\"2020-05-15\"},\n  {\"description\":\"Telefone\",              \"amount\":\"99.99\", \"type\":\"saída\",\"frequency\":\"recorrente\",\"date\":\"2020-05-23\"},\n  {\"description\":\"Plano de Saúde\",        \"amount\":\"300.00\",\"type\":\"saída\",\"frequency\":\"recorrente\",\"date\":\"2020-05-23\"},\n  {\"description\":\"Compras do mês\",        \"amount\":\"540.00\",\"type\":\"saída\",\"frequency\":\"recorrente\",\"date\":\"2020-05-25\"},\n  {\"description\":\"Parcela do Celular 4/5\",\"amount\":\"150.99\",\"type\":\"saída\",\"frequency\":\"eventual\",  \"date\":\"2020-05-26\"},\n  {\"description\":\"Blusa Iron Man\",        \"amount\":\"150.00\",\"type\":\"saída\",\"frequency\":\"eventual\",  \"date\":\"2020-01-23\"},\n  {\"description\":\"Energia elétrica\",      \"amount\":\"200.00\",\"type\":\"saída\",\"frequency\":\"recorrente\",\"date\":\"2020-06-10\"},\n  {\"description\":\"Água\",                  \"amount\":\"150.00\",\"type\":\"saída\",\"frequency\":\"recorrente\",\"date\":\"2020-06-15\"},\n  {\"description\":\"Telefone\",              \"amount\":\"99.99\", \"type\":\"saída\",\"frequency\":\"recorrente\",\"date\":\"2020-06-23\"},\n  {\"description\":\"Plano de Saúde\",        \"amount\":\"300.00\",\"type\":\"saída\",\"frequency\":\"recorrente\",\"date\":\"2020-06-23\"},\n  {\"description\":\"Compras do mês\",        \"amount\":\"559.15\",\"type\":\"saída\",\"frequency\":\"recorrente\",\"date\":\"2020-06-25\"},\n  {\"description\":\"Parcela do Celular 5/5\",\"amount\":\"150.99\",\"type\":\"saída\",\"frequency\":\"eventual\",  \"date\":\"2020-06-26\"},\n  {\"description\":\"Perfume\",               \"amount\":\"250.00\",\"type\":\"saída\",\"frequency\":\"eventual\",  \"date\":\"2020-06-21\"},\n  {\"description\":\"Energia elétrica\",      \"amount\":\"250.00\",\"type\":\"saída\",\"frequency\":\"recorrente\",\"date\":\"2020-07-10\"},\n  {\"description\":\"Água\",                  \"amount\":\"90.00\", \"type\":\"saída\",\"frequency\":\"recorrente\",\"date\":\"2020-07-15\"},\n  {\"description\":\"Telefone\",              \"amount\":\"99.99\", \"type\":\"saída\",\"frequency\":\"recorrente\",\"date\":\"2020-07-23\"},\n  {\"description\":\"Plano de Saúde\",        \"amount\":\"300.00\",\"type\":\"saída\",\"frequency\":\"recorrente\",\"date\":\"2020-07-23\"},\n  {\"description\":\"Compras do mês\",        \"amount\":\"700.00\",\"type\":\"saída\",\"frequency\":\"recorrente\",\"date\":\"2020-07-25\"},\n  {\"description\":\"Cafeteira\",             \"amount\":\"250.00\",\"type\":\"saída\",\"frequency\":\"eventual\",  \"date\":\"2020-07-26\"},\n  {\"description\":\"Pizza\",                 \"amount\":\"60.00\", \"type\":\"saída\",\"frequency\":\"eventual\",  \"date\":\"2020-07-19\"},\n  {\"description\":\"Pizza\",                 \"amount\":\"750.01\", \"type\":\"saída\",\"frequency\":\"eventual\",  \"date\":\"2020-07-19\"}\n]"
  },
  {
    "path": "src/repositories/gains.ts",
    "content": "export default [\n  { \"description\": \"Salário\",     \"amount\": \"1300.52\", \"type\": \"entrada\", \"frequency\": \"recorrente\", \"date\": \"2020-01-10\" }, \n  { \"description\": \"Freela\",      \"amount\": \"150.13\",  \"type\": \"entrada\", \"frequency\": \"eventual\",   \"date\": \"2020-01-17\" }, \n  { \"description\": \"Salário\",     \"amount\": \"2500.23\", \"type\": \"entrada\", \"frequency\": \"recorrente\", \"date\": \"2020-02-10\" }, \n  { \"description\": \"Freela site\", \"amount\": \"900.23\",  \"type\": \"entrada\", \"frequency\": \"eventual\",   \"date\": \"2020-02-21\" }, \n  { \"description\": \"Freela app\",  \"amount\": \"950.92\",  \"type\": \"entrada\", \"frequency\": \"eventual\",   \"date\": \"2020-02-23\" }, \n  { \"description\": \"Salário\",     \"amount\": \"2500.25\", \"type\": \"entrada\", \"frequency\": \"recorrente\", \"date\": \"2020-03-10\" }, \n  { \"description\": \"Salário\",     \"amount\": \"2500.18\", \"type\": \"entrada\", \"frequency\": \"recorrente\", \"date\": \"2020-04-10\" }, \n  { \"description\": \"Salário\",     \"amount\": \"2500.15\", \"type\": \"entrada\", \"frequency\": \"recorrente\", \"date\": \"2020-05-10\" }, \n  { \"description\": \"Salário\",     \"amount\": \"2500.12\", \"type\": \"entrada\", \"frequency\": \"recorrente\", \"date\": \"2020-06-10\" }, \n  { \"description\": \"Salário\",     \"amount\": \"2500.00\", \"type\": \"entrada\", \"frequency\": \"recorrente\", \"date\": \"2020-07-10\" },\n  ]\n  "
  },
  {
    "path": "src/routes/app.routes.tsx",
    "content": "import React from 'react';\nimport { Switch, Route } from 'react-router-dom';\n\nimport Layout from '../components/Layout';\nimport Dashboard from '../pages/Dashboard';\nimport List from '../pages/List';\n\nconst AppRoutes: React.FC = () => (\n    <Layout>\n        <Switch>\n            <Route path=\"/\" exact component={Dashboard} />\n            <Route path=\"/list/:type\" exact component={List} />\n        </Switch>\n    </Layout>\n);\n\nexport default AppRoutes;"
  },
  {
    "path": "src/routes/auth.routes.tsx",
    "content": "import React from 'react';\nimport { Switch, Route } from 'react-router-dom'; \n\nimport SignIn from '../pages/SignIn';\n\nconst AuthRoutes: React.FC = () => (\n    <Switch>\n        <Route path=\"/\" component={SignIn} />\n    </Switch>\n);\n\nexport default AuthRoutes;"
  },
  {
    "path": "src/routes/index.tsx",
    "content": "import React from 'react';\nimport { BrowserRouter } from 'react-router-dom';\n\nimport { useAuth } from '../hooks/auth';\n\nimport App from './app.routes';\nimport Auth from './auth.routes';\n\nconst Routes: React.FC = () => {\n    const { logged } = useAuth();\n    \n    return (\n        <BrowserRouter>\n            { logged ? <App/> : <Auth /> }\n        </BrowserRouter>\n    );\n}\n\nexport default Routes;"
  },
  {
    "path": "src/styles/GlobalStyles.ts",
    "content": "import { createGlobalStyle } from 'styled-components';\n\nexport default createGlobalStyle`\n    * {\n        margin: 0;\n        padding: 0;\n        box-sizing: border-box;\n    }\n\n    html, body, #root {\n        height: 100%;\n    }\n\n    *, button, input {\n        border: 0;\n        outline: 0;\n        font-family: 'Roboto', sans-serif;\n    }\n\n    button {\n        cursor: pointer;\n    }\n`;"
  },
  {
    "path": "src/styles/styled.d.ts",
    "content": "import 'styled-components';\n\ndeclare module 'styled-components' {\n    export interface DefaultTheme {\n        title: string;\n    \n        colors: {\n            primary: string;\n            secondary: string;\n            tertiary: string;\n    \n            white: string;\n            black: string;\n            gray: string;\n    \n            success: string;\n            info: string;\n            warning: string;\n        },\n    };\n}"
  },
  {
    "path": "src/styles/themes/dark.ts",
    "content": "export default {\n    title: 'dark',\n\n    colors: {\n        primary: '#1B1F38',\n        secondary: '#252A48',\n        tertiary: '#313862',\n\n        white: '#FFF',\n        black: '#000',\n        gray: '#BFBFBF',\n\n        success: '#4E41F0',\n        info: '#F7931B',\n        warning: '#E44C4E',\n    },\n};"
  },
  {
    "path": "src/styles/themes/light.ts",
    "content": "export default {\n    title: 'light',\n\n    colors: {\n        primary: '#DCDCDC',\n        secondary: '#FFFFFF',\n        tertiary: '#F5F5F5',\n\n        white: '#000',\n        black: '#FFF',\n        gray: '#BFBFBF',\n\n        success: '#03BB85',\n        info: '#3B5998',\n        warning: '#FF6961',\n    },\n};"
  },
  {
    "path": "src/utils/emojis.ts",
    "content": "export default ['🤑', '🤩', '😍', '😎', '🤑', '😃', '😄'];"
  },
  {
    "path": "src/utils/formatCurrency.ts",
    "content": "const formatCurrency = (current: number): string => {\n    return current.toLocaleString( \n        'pt-br', \n        {\n            style: 'currency', \n            currency: 'BRL'\n        });\n};\n\nexport default formatCurrency;"
  },
  {
    "path": "src/utils/formatDate.ts",
    "content": "const formatDate = (date: string): string => {\n   const dateFormatted = new Date(date);\n   const year = dateFormatted.getFullYear();\n   \n   const day = dateFormatted.getDate() > 9 \n   ? dateFormatted.getDate() : `0${dateFormatted.getDate()}`;\n   \n   const month = dateFormatted.getMonth() + 1 > 9\n   ? dateFormatted.getMonth() + 1 : `0${dateFormatted.getMonth() + 1}`; \n\n   return `${day}/${month}/${year}`;\n};\n\nexport default formatDate;"
  },
  {
    "path": "src/utils/months.ts",
    "content": "export default [\n    'Janeiro',\n    'Fevereiro',\n    'Março',\n    'Abril',\n    'Maio',\n    'Junho',\n    'Julho',\n    'Agosto',\n    'Setembro',\n    'Outubro',\n    'Novembro',\n    'Dezembro'\n];"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"es5\",\n    \"lib\": [\n      \"dom\",\n      \"dom.iterable\",\n      \"esnext\"\n    ],\n    \"allowJs\": true,\n    \"skipLibCheck\": true,\n    \"esModuleInterop\": true,\n    \"allowSyntheticDefaultImports\": true,\n    \"strict\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"module\": \"esnext\",\n    \"moduleResolution\": \"node\",\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"noEmit\": true,\n    \"jsx\": \"react\"\n  },\n  \"include\": [\n    \"src\"\n  ]\n}\n"
  }
]