├── src ├── react-app-env.d.ts ├── assets │ └── img │ │ ├── bb-logo.jpg │ │ ├── itau-logo.webp │ │ ├── bradesco-logo.png │ │ ├── apiplaybook-logo.png │ │ ├── next-logo.svg │ │ ├── rate.svg │ │ ├── illustrations │ │ ├── account.svg │ │ ├── credit-card.svg │ │ └── loan.svg │ │ └── banco-pan-logo.svg ├── utils │ ├── fixTaxes.ts │ ├── omit.ts │ ├── omitBanks.ts │ ├── fixMoney.ts │ ├── toCamelCase.ts │ ├── getBanksOfApi.ts │ ├── brandMap.tsx │ ├── brandMapTest.tsx │ ├── returnBankLogo.ts │ ├── fixPayload.ts │ └── generateGridTemplate.ts ├── setupTests.ts ├── styles │ ├── App.ts │ ├── CallApiPage.styled.ts │ └── global.ts ├── components │ ├── Layout │ │ └── Layout.tsx │ ├── Header │ │ ├── Header.tsx │ │ └── Header.styled.ts │ ├── Modal │ │ ├── index.tsx │ │ └── modal.style.ts │ └── ComparisonMatrix │ │ ├── components │ │ ├── BrandMiniPayload │ │ │ ├── BrandMiniPayload.styled.ts │ │ │ └── index.tsx │ │ ├── MatrixCell │ │ │ └── MatrixCell.styled.ts │ │ └── MatrixHeader │ │ │ └── index.tsx │ │ ├── ComparisonMatrix.styled.ts │ │ └── index.tsx ├── index.tsx ├── reportWebVitals.ts ├── routes.ts ├── services │ ├── callApisOpenBanking.ts │ └── api.ts ├── hooks │ └── Modal.tsx ├── App.tsx ├── pages │ ├── Home │ │ ├── index.tsx │ │ ├── HomeData.ts │ │ └── Home.styled.ts │ ├── PersonalFinancings │ │ └── index.tsx │ ├── BusinessFinancing │ │ └── index.tsx │ ├── PersonalAccounts │ │ └── index.tsx │ ├── PersonalLoans │ │ └── index.tsx │ ├── BusinessLoans │ │ └── index.tsx │ ├── BusinessAccounts │ │ └── index.tsx │ ├── PersonalCreditCards │ │ └── index.tsx │ └── BusinessCreditCards │ │ └── index.tsx ├── constants │ ├── banks.ts │ └── apis.ts └── logo.svg ├── favicon.ico ├── logo192.png ├── logo512.png ├── robots.txt ├── public ├── robots.txt ├── favicon.ico ├── logo192.png ├── logo512.png ├── manifest.json └── index.html ├── static ├── media │ ├── itau-logo.96cc5dd0.webp │ ├── bradesco-logo.d69a0ae7.png │ ├── next-logo.d5228214.svg │ ├── account.228c857b.svg │ ├── banco-pan-logo.c0fd5379.svg │ ├── credit-card.11093fcb.svg │ └── loan.c6bc1e1a.svg └── js │ ├── 2.8b206ba6.chunk.js.LICENSE.txt │ ├── runtime-main.07745ca7.js │ ├── 3.f4a706e7.chunk.js │ ├── 3.f4a706e7.chunk.js.map │ └── runtime-main.07745ca7.js.map ├── .gitignore ├── manifest.json ├── tsconfig.json ├── LICENCE ├── package.json ├── asset-manifest.json ├── README.md └── index.html /src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apiplaybook/open-banking-brasil/HEAD/favicon.ico -------------------------------------------------------------------------------- /logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apiplaybook/open-banking-brasil/HEAD/logo192.png -------------------------------------------------------------------------------- /logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apiplaybook/open-banking-brasil/HEAD/logo512.png -------------------------------------------------------------------------------- /robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apiplaybook/open-banking-brasil/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apiplaybook/open-banking-brasil/HEAD/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apiplaybook/open-banking-brasil/HEAD/public/logo512.png -------------------------------------------------------------------------------- /src/assets/img/bb-logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apiplaybook/open-banking-brasil/HEAD/src/assets/img/bb-logo.jpg -------------------------------------------------------------------------------- /src/assets/img/itau-logo.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apiplaybook/open-banking-brasil/HEAD/src/assets/img/itau-logo.webp -------------------------------------------------------------------------------- /src/assets/img/bradesco-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apiplaybook/open-banking-brasil/HEAD/src/assets/img/bradesco-logo.png -------------------------------------------------------------------------------- /src/assets/img/apiplaybook-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apiplaybook/open-banking-brasil/HEAD/src/assets/img/apiplaybook-logo.png -------------------------------------------------------------------------------- /static/media/itau-logo.96cc5dd0.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apiplaybook/open-banking-brasil/HEAD/static/media/itau-logo.96cc5dd0.webp -------------------------------------------------------------------------------- /static/media/bradesco-logo.d69a0ae7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apiplaybook/open-banking-brasil/HEAD/static/media/bradesco-logo.d69a0ae7.png -------------------------------------------------------------------------------- /src/utils/fixTaxes.ts: -------------------------------------------------------------------------------- 1 | export const fixTaxes = (tax: string) => { 2 | return `${parseFloat(tax).toFixed(3).toString().replace(/[.\s]/g, ',')}%` 3 | } 4 | -------------------------------------------------------------------------------- /src/utils/omit.ts: -------------------------------------------------------------------------------- 1 | // Omite uma propriedade em um objeto 2 | export const omit = (key: string, obj: any) => { 3 | const { [key]: omitted, ...rest } = obj 4 | return rest 5 | } 6 | -------------------------------------------------------------------------------- /src/utils/omitBanks.ts: -------------------------------------------------------------------------------- 1 | import { banks } from '../constants/banks' 2 | 3 | export const omitBanks = (omitApis: string[]) => { 4 | return banks.filter((bank) => !omitApis.includes(bank.brandName)) 5 | } 6 | -------------------------------------------------------------------------------- /src/utils/fixMoney.ts: -------------------------------------------------------------------------------- 1 | export const fixMoney = (money: string) => { 2 | if (money === 'NA') { 3 | return 'N/A' 4 | } 5 | return `R$${parseFloat(money).toFixed(2).toString().replace(/[.\s]/g, ',')}` 6 | } 7 | -------------------------------------------------------------------------------- /src/utils/toCamelCase.ts: -------------------------------------------------------------------------------- 1 | export const toCamelCase = (str: string) => 2 | str 3 | .replace(/(?:^\w|[A-Z]|\b\w)/g, function (word, index) { 4 | return index === 0 ? word.toLowerCase() : word.toUpperCase() 5 | }) 6 | .replace(/\s+/g, '') 7 | -------------------------------------------------------------------------------- /src/setupTests.ts: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /src/styles/App.ts: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components' 2 | 3 | const AppStyled = styled.div` 4 | display: flex; 5 | flex-direction: column; 6 | background-image: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%); 7 | min-height: 100vh; 8 | ` 9 | 10 | export default AppStyled 11 | -------------------------------------------------------------------------------- /src/components/Layout/Layout.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import Header from '../Header/Header' 3 | 4 | const Layout = ({ title, children }: { title?: string; children: any }) => { 5 | return ( 6 | <> 7 |
8 | {children} 9 | 10 | ) 11 | } 12 | 13 | export default Layout 14 | -------------------------------------------------------------------------------- /.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 | 25 | .eslintcache 26 | -------------------------------------------------------------------------------- /src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom' 3 | import App from './App' 4 | import reportWebVitals from './reportWebVitals' 5 | import { GlobalStyles } from './styles/global' 6 | 7 | import { ModalProvider } from './hooks/Modal' 8 | 9 | ReactDOM.render( 10 | 11 | 12 | 13 | 14 | 15 | , 16 | document.getElementById('root') 17 | ) 18 | 19 | reportWebVitals() 20 | -------------------------------------------------------------------------------- /src/reportWebVitals.ts: -------------------------------------------------------------------------------- 1 | import { ReportHandler } from 'web-vitals'; 2 | 3 | const reportWebVitals = (onPerfEntry?: ReportHandler) => { 4 | if (onPerfEntry && onPerfEntry instanceof Function) { 5 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 6 | getCLS(onPerfEntry); 7 | getFID(onPerfEntry); 8 | getFCP(onPerfEntry); 9 | getLCP(onPerfEntry); 10 | getTTFB(onPerfEntry); 11 | }); 12 | } 13 | }; 14 | 15 | export default reportWebVitals; 16 | -------------------------------------------------------------------------------- /src/routes.ts: -------------------------------------------------------------------------------- 1 | export const HOME = '/' 2 | export const BUSINESS_LOANS = '/business-loans' 3 | export const PERSONAL_LOANS = '/personal-loans' 4 | export const PERSONAL_ACCOUNTS = '/personal-accounts' 5 | export const BUSINESS_ACCOUNTS = '/business-accounts' 6 | export const PERSONAL_FINANCINGS = '/personal-financings' 7 | export const BUSINESS_FINANCINGS = '/business-financings' 8 | export const PERSONAL_CREDIT_CARDS = '/personal-credit-cards' 9 | export const BUSINESS_CREDIT_CARDS = '/business-credit-cards' 10 | -------------------------------------------------------------------------------- /src/components/Header/Header.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Link } from 'react-router-dom' 3 | import { HOME } from '../../routes' 4 | import { HeaderStyled } from './Header.styled' 5 | 6 | import logo from '../../assets/img/apiplaybook-logo.png' 7 | 8 | const Header = ({ title }: { title?: string }) => { 9 | return ( 10 | 11 | 12 | API Playbook 13 | 14 | 15 | {title &&

{title}

} 16 |
17 | ) 18 | } 19 | 20 | export default Header 21 | -------------------------------------------------------------------------------- /src/components/Header/Header.styled.ts: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components' 2 | 3 | export const HeaderStyled = styled.header` 4 | display: flex; 5 | width: 100%; 6 | padding: 10px 35px; 7 | 8 | a { 9 | height: fit-content; 10 | width: fit-content; 11 | transform: scale(0.8); 12 | } 13 | 14 | h1 { 15 | font-family: 'Inter', sans-serif; 16 | margin: auto; 17 | transform: translateX(-70px); 18 | } 19 | @media only screen and (max-width: 1400px) { 20 | padding: 5px 15px; 21 | height: 100px; 22 | a { 23 | transform: scale(0.6); 24 | } 25 | } 26 | ` 27 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /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/utils/getBanksOfApi.ts: -------------------------------------------------------------------------------- 1 | import { apis } from './../constants/apis' 2 | import { banks } from './../constants/banks' 3 | 4 | export const getBanksOfApi = (apiEndpoint: string) => { 5 | const apiBanks = apis.filter((api) => api.endpoint === apiEndpoint)[0].banks 6 | const apiBanksCompanies = apiBanks.flatMap((bank) => bank.companies) 7 | const apiBanksName = apiBanks.flatMap((bank) => bank.brand) 8 | 9 | return banks 10 | .filter(({ brandName }) => apiBanksName.includes(brandName)) 11 | .map((bank) => { 12 | return { 13 | ...bank, 14 | companies: bank.companies.filter((company) => apiBanksCompanies.includes(company)), 15 | } 16 | }) 17 | } 18 | -------------------------------------------------------------------------------- /src/utils/brandMap.tsx: -------------------------------------------------------------------------------- 1 | //@ts-nocheck 2 | import { fixTaxes } from './fixTaxes' 3 | import { omit } from './omit' 4 | 5 | export const brandMap = (interestRates: any, brand: string) => { 6 | return ( 7 | interestRates.brand === brand && 8 | Object.values(omit('brand', interestRates)).map((interestRates) => ( 9 |
10 |
11 | {interestRates.referentialRateIndexer.replace(/[_\s]/g, ' ')} 12 |
13 |
{fixTaxes(interestRates.minimumRate)}%
14 |
{fixTaxes(interestRates.maximumRate)}%
15 |
16 | )) 17 | ) 18 | } 19 | -------------------------------------------------------------------------------- /src/utils/brandMapTest.tsx: -------------------------------------------------------------------------------- 1 | interface IPayload { 2 | name: string 3 | minimum: string 4 | maximum: string 5 | brand: string 6 | } 7 | 8 | export const brandMap = (payload: IPayload, requiredBrand: string, fixFunction?: any) => { 9 | return ( 10 | payload.brand === requiredBrand && ( 11 |
12 |
13 | {payload.name.replace(/[_\s]/g, ' ')} 14 |
15 | 16 |
17 | {fixFunction ? fixFunction(payload.minimum) : payload.minimum} 18 |
19 |
20 | {fixFunction ? fixFunction(payload.maximum) : payload.maximum} 21 |
22 |
23 | ) 24 | ) 25 | } 26 | -------------------------------------------------------------------------------- /src/utils/returnBankLogo.ts: -------------------------------------------------------------------------------- 1 | import bbLogo from '../assets/img/bb-logo.jpg' 2 | import bancoPanLogo from '../assets/img/banco-pan-logo.svg' 3 | import bradescoLogo from '../assets/img/bradesco-logo.png' 4 | import itauLogo from '../assets/img/itau-logo.webp' 5 | import nextLogo from '../assets/img/next-logo.svg' 6 | 7 | export const returnBankLogo = (brandName: string) => { 8 | switch (brandName) { 9 | case 'Banco do Brasil S/A': 10 | return bbLogo 11 | 12 | case 'Grupo Pan': 13 | return bancoPanLogo 14 | 15 | case 'Banco Bradesco': 16 | return bradescoLogo 17 | 18 | case 'Banco Digital Next': 19 | return nextLogo 20 | 21 | case 'Itaú': 22 | case 'ITAU': 23 | case 'Itau Unibanco S.A.': 24 | return itauLogo 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/services/callApisOpenBanking.ts: -------------------------------------------------------------------------------- 1 | import { getBanksOfApi } from './../utils/getBanksOfApi' 2 | import { callOpenBanking } from './api' 3 | 4 | export const callApisOpenBanking = async (endpoint: string, omit?: string[]) => { 5 | // Realiza as consultas às APIs 6 | try { 7 | const banks = getBanksOfApi(endpoint) 8 | const urls = omit 9 | ? banks.map((bank) => !omit.includes(bank.brandName) && bank.apiUrl) 10 | : banks.map((bank) => bank.apiUrl) 11 | 12 | const apiResponses = await Promise.all( 13 | urls.filter(Boolean).map(async (url) => { 14 | // @ts-ignore 15 | const response = await callOpenBanking(url, endpoint) 16 | return response 17 | }) 18 | ) 19 | return apiResponses 20 | } catch (error) { 21 | console.log('Error to call api:', error) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/services/api.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios' 2 | import { toCamelCase } from '../utils/toCamelCase' 3 | import { banks } from './../constants/banks' 4 | 5 | export const callOpenBanking = async (baseURL: string, endpoint: string) => { 6 | const api = axios.create({ 7 | baseURL: `${baseURL}/open-banking/products-services/v1`, 8 | }) 9 | 10 | const currentBank = banks.filter((bank) => bank.apiUrl === baseURL)[0] 11 | 12 | const payloadName = toCamelCase( 13 | endpoint.substr(1, endpoint.length - 1).replace(/[-\s]/g, ' ') 14 | ) 15 | 16 | return await api 17 | .get(endpoint) 18 | .then((response) => response.data.data.brand) 19 | .catch(() => { 20 | return { 21 | name: currentBank.brandName, 22 | companies: [ 23 | { 24 | name: 'INDISPONÍVEL', 25 | cnpjNumber: '00000000000000', 26 | urlComplementaryList: null, 27 | [payloadName]: [], 28 | }, 29 | ], 30 | } 31 | }) 32 | } 33 | -------------------------------------------------------------------------------- /src/components/Modal/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { useModal } from '../../hooks/Modal' 3 | 4 | import { LightBox, ModalWrapper, CloseButtonModal } from './modal.style' 5 | 6 | export const Modal: React.FC = () => { 7 | const { moreInfo, removeMoreInfo } = useModal() 8 | return ( 9 | <> 10 | {moreInfo && ( 11 | 12 | 13 | 14 |
15 |

{moreInfo.name.replace(/[_\s]/g, ' ')}

16 |

{moreInfo.chargingTriggerInfo}

17 |
18 |
19 |

Termos e Condições

20 |

{moreInfo.termsConditions?.additionalInfo}

21 |

{moreInfo.termsConditions?.elegibilityCriteriaInfo}

22 |

Informações de Processo de Cancelamento

23 |

{moreInfo.termsConditions?.closingProcessInfo}

24 |
25 |
26 |
27 | )} 28 | 29 | ) 30 | } 31 | -------------------------------------------------------------------------------- /src/components/ComparisonMatrix/components/BrandMiniPayload/BrandMiniPayload.styled.ts: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components' 2 | 3 | export const BrandMiniPayloadStyled = styled.div` 4 | display: grid; 5 | text-align: center; 6 | height: 100%; 7 | max-height: 200px; 8 | div { 9 | display: flex; 10 | justify-content: space-around; 11 | align-items: center; 12 | padding: 5px 0; 13 | } 14 | .index { 15 | grid-area: index; 16 | background-color: #e5ebf3; 17 | border-bottom: 1px solid #c6c6c650; 18 | font-weight: 600; 19 | font-size: 10pt; 20 | word-break: break-all; 21 | } 22 | .max { 23 | border-left: 1px solid #c6c6c650; 24 | border-bottom: 1px solid #c6c6c650; 25 | grid-area: max; 26 | height: 100%; 27 | } 28 | .min { 29 | border-bottom: 1px solid #c6c6c650; 30 | grid-area: min; 31 | height: 100%; 32 | } 33 | .miniFont { 34 | font-size: 9pt; 35 | min-height: 30px; 36 | padding: 2px; 37 | 38 | &.title { 39 | font-size: 8pt; 40 | } 41 | } 42 | grid-template-areas: 43 | 'index index' 44 | 'min max'; 45 | ` 46 | -------------------------------------------------------------------------------- /src/styles/CallApiPage.styled.ts: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components' 2 | 3 | export const MatrixPageStyled = styled.div` 4 | display: flex; 5 | flex-direction: column; 6 | align-items: center; 7 | justify-content: center; 8 | height: 100%; 9 | width: 100%; 10 | h3 { 11 | max-width: 500px; 12 | font-weight: 600; 13 | text-align: center; 14 | margin-bottom: 30px; 15 | font-family: 'Inter', sans-serif; 16 | } 17 | ` 18 | 19 | export const CompanyStyled = styled.div` 20 | display: flex; 21 | flex-direction: column; 22 | width: fit-content; 23 | div:first-child { 24 | background-color: #f0f4f7; 25 | width: 100%; 26 | margin-bottom: 20px; 27 | padding: 10px; 28 | font-size: 14pt; 29 | justify-content: space-between; 30 | } 31 | ` 32 | 33 | export const TableStyled = styled.table` 34 | border-collapse: collapse; 35 | width: 900px; 36 | margin-bottom: 40px; 37 | th, 38 | td { 39 | background-color: #f0f4f7; 40 | padding: 10px 20px; 41 | border-bottom: 1px solid #aaa; 42 | font-weight: 600; 43 | } 44 | th { 45 | font-weight: 700; 46 | } 47 | ` 48 | -------------------------------------------------------------------------------- /src/utils/fixPayload.ts: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | export const fixPayload = (payload) => { 3 | let types = [] 4 | let lastBrand = false 5 | let fixedBrand = [] 6 | let fixedType = [] 7 | Object.keys(types).forEach((typeIndex) => { 8 | types[typeIndex].forEach((brand, brandIndex) => { 9 | if (lastBrand === false) { 10 | lastBrand = brand 11 | if (types[typeIndex].length === brandIndex + 1) { 12 | types[typeIndex] = [brand] 13 | lastBrand = false 14 | } 15 | } else { 16 | if (brand.brand === lastBrand.brand && brand.company === lastBrand.company) { 17 | fixedBrand.push(omit('company', omit('brand', lastBrand))[0]) 18 | lastBrand = brand 19 | } else { 20 | if (fixedBrand.length > 0) { 21 | fixedBrand = { 22 | ...fixedBrand, 23 | brand: lastBrand.brand, 24 | company: lastBrand.company, 25 | } 26 | 27 | fixedType.push(fixedBrand) 28 | } 29 | fixedType.push(brand) 30 | } 31 | } 32 | if (types[typeIndex].length === brandIndex + 1) { 33 | types[typeIndex] = fixedType 34 | fixedType = [] 35 | lastBrand = false 36 | } 37 | }) 38 | }) 39 | return types 40 | } 41 | -------------------------------------------------------------------------------- /src/hooks/Modal.tsx: -------------------------------------------------------------------------------- 1 | import React, { createContext, useState, useContext } from 'react' 2 | import { Modal } from '../components/Modal' 3 | 4 | interface IModalContextData { 5 | addMoreInfo(data: IModalProps): void 6 | removeMoreInfo(): void 7 | moreInfo: IModalProps | null 8 | } 9 | 10 | export interface IModalProps { 11 | name: string 12 | chargingTriggerInfo: string 13 | termsConditions: { 14 | additionalInfo?: string 15 | elegibilityCriteriaInfo?: string 16 | closingProcessInfo?: string 17 | } 18 | } 19 | 20 | const ModalContext = createContext({} as IModalContextData) 21 | 22 | export const ModalProvider: React.FC = ({ children }) => { 23 | const [moreInfo, setMoreInfo] = useState(null) 24 | 25 | const addMoreInfo = (data: IModalProps) => { 26 | setMoreInfo(data) 27 | } 28 | 29 | const removeMoreInfo = () => { 30 | setMoreInfo(null) 31 | } 32 | 33 | return ( 34 | 35 | 36 | {children} 37 | 38 | ) 39 | } 40 | 41 | export function useModal() { 42 | const context = useContext(ModalContext) 43 | 44 | return context 45 | } 46 | -------------------------------------------------------------------------------- /src/components/ComparisonMatrix/components/BrandMiniPayload/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { BrandMiniPayloadStyled } from './BrandMiniPayload.styled' 3 | 4 | interface IPayload { 5 | name: string 6 | minimum: string 7 | maximum: string 8 | brand: string 9 | } 10 | 11 | interface Props { 12 | props: { 13 | payload: IPayload 14 | requiredBrand: string 15 | fixFunction?: any 16 | } 17 | } 18 | 19 | const BrandMiniPayload = ({ props }: Props) => { 20 | const { payload, requiredBrand, fixFunction } = props 21 | return ( 22 | payload.brand === requiredBrand && ( 23 | 24 |
30 && 'miniFont'}`}> 25 | {payload.name.replace(/[_\s]/g, ' ')} 26 |
27 |
5 && 'miniFont'}`}> 28 | {fixFunction ? fixFunction(payload.minimum) : payload.minimum} 29 |
30 |
5 && 'miniFont'}`}> 31 | {fixFunction ? fixFunction(payload.maximum) : payload.maximum} 32 |
33 |
34 | ) 35 | ) 36 | } 37 | 38 | export default BrandMiniPayload 39 | -------------------------------------------------------------------------------- /LICENCE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2021 API Connect (CHEZI PRESTACAO DE SERVICOS DE MARKETING E EVENTOS EIRELI) 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 13 | all 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 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/utils/generateGridTemplate.ts: -------------------------------------------------------------------------------- 1 | import { IBankProps } from './../constants/banks' 2 | 3 | export const generateGridTemplate = (banks: IBankProps[]) => { 4 | let template = '200px' 5 | banks.forEach((bank) => { 6 | template += ` ${bank.companies.length === 0 ? 130 : 130 * bank.companies.length}px` 7 | }) 8 | 9 | return template 10 | } 11 | export const generateGridTemplateByLength = (length: number) => { 12 | let template = '' 13 | 14 | for (let i = 0; i < length; i++) { 15 | template += i === 0 ? '130px' : ' 130px' 16 | } 17 | 18 | return template 19 | } 20 | 21 | export const generateCellGridConfig = (companiesLength: number) => { 22 | let areas = '' 23 | let templateAreas = '' 24 | for (let i = 0; i < companiesLength; i++) { 25 | areas += ` div.cellCompanyColumn${i} { grid-area: cellCompanyColumn${i}; }` 26 | templateAreas += ` cellCompanyColumn${i}` 27 | } 28 | areas = areas.trim() 29 | templateAreas = templateAreas.trim() 30 | 31 | return `max-width: ${ 32 | companiesLength === 0 ? 130 : 130 * companiesLength 33 | }px; ${areas} grid-template-columns: ${generateGridTemplateByLength( 34 | companiesLength === 0 ? 1 : companiesLength 35 | )}; grid-template-areas: '${templateAreas}' !important;` 36 | } 37 | -------------------------------------------------------------------------------- /src/components/Modal/modal.style.ts: -------------------------------------------------------------------------------- 1 | import styled, { keyframes } from 'styled-components' 2 | import { MdClose } from 'react-icons/md' 3 | 4 | const appearFromMiddle = keyframes` 5 | from { 6 | opacity: 0; 7 | transform:translateY(-100%) 8 | } to { 9 | opacity: 1; 10 | transform: translateY(0%) 11 | } 12 | ` 13 | 14 | export const LightBox = styled.div` 15 | display: block; 16 | position: fixed; 17 | width: 100%; 18 | height: 100vh; 19 | background-color: rgba(0, 0, 0, 0.3); 20 | z-index: 1; 21 | overflow-x: auto; 22 | padding: 60px 20px; 23 | ` 24 | 25 | export const ModalWrapper = styled.div` 26 | position: relative; 27 | background-color: #ffff; 28 | color: #888888; 29 | width: 600px; 30 | margin: 0 auto; 31 | padding-top: 60px; 32 | padding: 50px; 33 | box-shadow: 0 5px 16px rgba(0, 0, 0, 0.4); 34 | overflow-y: auto; 35 | animation: ${appearFromMiddle} 0.2s; 36 | 37 | div { 38 | h1 { 39 | font-size: 21px; 40 | margin-top: 20px; 41 | margin-bottom: 10px; 42 | color: #666666; 43 | } 44 | } 45 | ` 46 | 47 | export const CloseButtonModal = styled(MdClose)` 48 | position: absolute; 49 | top: 20px; 50 | right: 20px; 51 | font-weight: 800; 52 | 53 | &:hover { 54 | color: #111111; 55 | cursor: pointer; 56 | } 57 | ` 58 | -------------------------------------------------------------------------------- /src/components/ComparisonMatrix/components/MatrixCell/MatrixCell.styled.ts: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components' 2 | 3 | interface MatrixCellProps { 4 | gridConfig: string 5 | } 6 | 7 | export const MatrixCellStyled = styled.div` 8 | display: grid !important; 9 | padding: 0 !important; 10 | ${({ gridConfig }) => gridConfig} 11 | max-height: fit-content; 12 | div.cellCompanyColumn { 13 | width: 100%; 14 | display: flex; 15 | flex-direction: column; 16 | border-right: 1px solid #c6c6c650; 17 | border-left: 1px solid #c6c6c650; 18 | } 19 | div.minMax { 20 | display: grid; 21 | text-align: center; 22 | height: 100%; 23 | width: 100%; 24 | div { 25 | display: flex; 26 | justify-content: space-around; 27 | align-items: center; 28 | } 29 | 30 | .max { 31 | border-left: 1px solid #c6c6c650; 32 | grid-area: max; 33 | height: 100%; 34 | } 35 | .min { 36 | grid-area: min; 37 | height: 100%; 38 | } 39 | .miniHeader { 40 | border-bottom: 1px solid #c6c6c650; 41 | grid-area: miniHeader; 42 | height: 100%; 43 | font-size: 10pt; 44 | } 45 | grid-template-rows: 60px 40px; 46 | grid-template-areas: 47 | 'miniHeader miniHeader' 48 | 'min max'; 49 | } 50 | 51 | /* ${({ gridConfig }) => gridConfig} */ 52 | ` 53 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "homepage": "http://apiplaybook.github.io/open-banking-brasil", 3 | "name": "open-banking-brasil", 4 | "version": "0.1.0", 5 | "private": true, 6 | "dependencies": { 7 | "@testing-library/jest-dom": "^5.11.4", 8 | "@testing-library/react": "^11.1.0", 9 | "@testing-library/user-event": "^12.1.10", 10 | "@types/jest": "^26.0.15", 11 | "@types/node": "^12.0.0", 12 | "@types/react": "^16.9.53", 13 | "@types/react-dom": "^16.9.8", 14 | "@types/react-router-dom": "^5.1.7", 15 | "axios": "^0.21.1", 16 | "react": "^17.0.1", 17 | "react-dom": "^17.0.1", 18 | "react-github-btn": "^1.2.0", 19 | "react-icons": "^4.2.0", 20 | "react-router-dom": "^5.2.0", 21 | "react-scripts": "4.0.1", 22 | "react-spinners-css": "^1.2.2", 23 | "styled-components": "^5.2.1", 24 | "typescript": "^4.0.3", 25 | "web-vitals": "^0.2.4" 26 | }, 27 | "scripts": { 28 | "predeploy": "yarn build", 29 | "deploy": "gh-pages -d build", 30 | "start": "react-scripts start", 31 | "build": "react-scripts build", 32 | "test": "react-scripts test", 33 | "eject": "react-scripts eject" 34 | }, 35 | "eslintConfig": { 36 | "extends": [ 37 | "react-app", 38 | "react-app/jest" 39 | ] 40 | }, 41 | "browserslist": { 42 | "production": [ 43 | ">0.2%", 44 | "not dead", 45 | "not op_mini all" 46 | ], 47 | "development": [ 48 | "last 1 chrome version", 49 | "last 1 firefox version", 50 | "last 1 safari version" 51 | ] 52 | }, 53 | "devDependencies": { 54 | "@types/react-icons": "^3.0.0", 55 | "@types/styled-components": "^5.1.7", 56 | "gh-pages": "^3.1.0" 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /static/js/2.8b206ba6.chunk.js.LICENSE.txt: -------------------------------------------------------------------------------- 1 | /* 2 | object-assign 3 | (c) Sindre Sorhus 4 | @license MIT 5 | */ 6 | 7 | /*! 8 | Copyright (c) 2017 Jed Watson. 9 | Licensed under the MIT License (MIT), see 10 | http://jedwatson.github.io/classnames 11 | */ 12 | 13 | /*! 14 | * github-buttons v2.14.2 15 | * (c) 2021 なつき 16 | * @license BSD-2-Clause 17 | */ 18 | 19 | /** @license React v0.20.1 20 | * scheduler.production.min.js 21 | * 22 | * Copyright (c) Facebook, Inc. and its affiliates. 23 | * 24 | * This source code is licensed under the MIT license found in the 25 | * LICENSE file in the root directory of this source tree. 26 | */ 27 | 28 | /** @license React v16.13.1 29 | * react-is.production.min.js 30 | * 31 | * Copyright (c) Facebook, Inc. and its affiliates. 32 | * 33 | * This source code is licensed under the MIT license found in the 34 | * LICENSE file in the root directory of this source tree. 35 | */ 36 | 37 | /** @license React v17.0.1 38 | * react-dom.production.min.js 39 | * 40 | * Copyright (c) Facebook, Inc. and its affiliates. 41 | * 42 | * This source code is licensed under the MIT license found in the 43 | * LICENSE file in the root directory of this source tree. 44 | */ 45 | 46 | /** @license React v17.0.1 47 | * react-jsx-runtime.production.min.js 48 | * 49 | * Copyright (c) Facebook, Inc. and its affiliates. 50 | * 51 | * This source code is licensed under the MIT license found in the 52 | * LICENSE file in the root directory of this source tree. 53 | */ 54 | 55 | /** @license React v17.0.1 56 | * react.production.min.js 57 | * 58 | * Copyright (c) Facebook, Inc. and its affiliates. 59 | * 60 | * This source code is licensed under the MIT license found in the 61 | * LICENSE file in the root directory of this source tree. 62 | */ 63 | -------------------------------------------------------------------------------- /src/App.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { HashRouter as Router, Switch, Route } from 'react-router-dom' 3 | 4 | import HomePage from './pages/Home' 5 | import BusinessLoansPage from './pages/BusinessLoans' 6 | import PersonalLoansPage from './pages/PersonalLoans' 7 | import PersonalAccountsPage from './pages/PersonalAccounts' 8 | import BusinessAccountsPage from './pages/BusinessAccounts' 9 | import PersonalFinancingsPage from './pages/PersonalFinancings' 10 | import BusinessFinancingsPage from './pages/BusinessFinancing' 11 | import PersonalCreditCardsPage from './pages/PersonalCreditCards' 12 | import BusinessCreditCardsPage from './pages/BusinessCreditCards' 13 | 14 | import { 15 | HOME, 16 | PERSONAL_LOANS, 17 | BUSINESS_LOANS, 18 | PERSONAL_ACCOUNTS, 19 | BUSINESS_ACCOUNTS, 20 | PERSONAL_FINANCINGS, 21 | BUSINESS_FINANCINGS, 22 | BUSINESS_CREDIT_CARDS, 23 | PERSONAL_CREDIT_CARDS, 24 | } from './routes' 25 | import AppStyled from './styles/App' 26 | 27 | function App() { 28 | return ( 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | ) 45 | } 46 | 47 | export default App 48 | -------------------------------------------------------------------------------- /src/components/ComparisonMatrix/ComparisonMatrix.styled.ts: -------------------------------------------------------------------------------- 1 | //@ts-nocheck 2 | import styled from 'styled-components' 3 | 4 | interface ComparisonMatrixProps { 5 | gridTemplateColumns: string 6 | } 7 | 8 | export const ComparisonMatrixStyled = styled.div` 9 | width: fit-content; 10 | display: grid; 11 | grid-template-columns: ${({ gridTemplateColumns }) => gridTemplateColumns}; 12 | grid-template-rows: auto; 13 | .mainIndex { 14 | background-color: #3e446c; 15 | color: #f0f4f7; 16 | } 17 | & > div { 18 | display: flex; 19 | background-color: #f0f4f7; 20 | padding: 50px; 21 | justify-content: space-around; 22 | border: 1px solid #c6c6c650; 23 | } 24 | .header { 25 | grid-area: header; 26 | } 27 | div.mini { 28 | display: flex; 29 | flex-direction: row; 30 | justify-content: flex-start; 31 | padding: 0; 32 | max-height: fit-content; 33 | div.miniHeaders { 34 | display: flex; 35 | flex-direction: row; 36 | width: 100%; 37 | } 38 | div.miniCompanyColumn { 39 | width: 100%; 40 | display: flex; 41 | flex-direction: column; 42 | &:last-child { 43 | border-left: 1px solid #c6c6c650; 44 | } 45 | } 46 | div.minMax { 47 | display: grid; 48 | text-align: center; 49 | height: 100%; 50 | width: 100%; 51 | div { 52 | display: flex; 53 | justify-content: space-around; 54 | align-items: center; 55 | } 56 | 57 | .max { 58 | border-left: 1px solid #c6c6c650; 59 | grid-area: max; 60 | height: 100%; 61 | } 62 | .min { 63 | grid-area: min; 64 | height: 100%; 65 | } 66 | .miniHeader { 67 | border-bottom: 1px solid #c6c6c650; 68 | grid-area: miniHeader; 69 | height: 100%; 70 | font-size: 10pt; 71 | } 72 | grid-template-rows: 60px 40px; 73 | grid-template-areas: 74 | 'miniHeader miniHeader' 75 | 'min max'; 76 | } 77 | } 78 | ` 79 | -------------------------------------------------------------------------------- /src/styles/global.ts: -------------------------------------------------------------------------------- 1 | import { createGlobalStyle } from 'styled-components' 2 | 3 | export const GlobalStyles = createGlobalStyle` 4 | html { 5 | box-sizing: border-box; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | scroll-behavior: smooth; 9 | } 10 | 11 | *, 12 | *::before, 13 | *::after { 14 | box-sizing: inherit; 15 | } 16 | * { 17 | margin: 0; 18 | padding: 0; 19 | } 20 | a { 21 | text-decoration: none; 22 | color: #000; 23 | } 24 | 25 | button.blue, a.blue { 26 | color: #2e93db; 27 | background: none; 28 | font-weight: bold; 29 | 30 | &:hover { 31 | cursor: pointer; 32 | opacity: 0.5; 33 | } 34 | } 35 | 36 | strong, 37 | b { 38 | font-weight: 700; 39 | } 40 | 41 | body { 42 | color: rgba(0, 0, 0, 0.87); 43 | font-size: 0.875rem; 44 | font-family: 'Open Sans', 'Helvetica', 'Arial', sans-serif; 45 | font-weight: 400; 46 | line-height: 1.43; 47 | letter-spacing: 0.01071em; 48 | background-color: #f5f5f5; 49 | overflow-x: hidden; 50 | &.dark { 51 | background-color: #1b1b1b; 52 | color: #fff; 53 | input:-webkit-autofill, 54 | input:-webkit-autofill:hover, 55 | input:-webkit-autofill:focus, 56 | input:-webkit-autofill:active { 57 | -webkit-box-shadow: 0 0 0 30px rgba(255, 255, 255, 0.1) inset !important; 58 | box-shadow: 0 0 0 30px rgba(255, 255, 255, 0.1) inset !important; 59 | } 60 | input:-internal-autofill-selected { 61 | background-color: transparent !important; 62 | } 63 | } 64 | } 65 | 66 | input, button { 67 | outline: 0; 68 | border: 0 none; 69 | } 70 | @media print { 71 | body { 72 | background-color: #fff; 73 | &.dark { 74 | background-color: #1b1b1b; 75 | } 76 | } 77 | } 78 | ` 79 | -------------------------------------------------------------------------------- /src/components/ComparisonMatrix/components/MatrixHeader/index.tsx: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | import React from 'react' 3 | import { IBankProps } from '../../../../constants/banks' 4 | import { returnBankLogo } from '../../../../utils/returnBankLogo' 5 | 6 | interface Props { 7 | banks: IBankProps[] 8 | } 9 | 10 | const MatrixHeader = ({ banks }: Props) => { 11 | return ( 12 | <> 13 | 14 | {banks.map((bank) => ( 15 |
16 | {bank.brandName} 21 |
22 | ))} 23 | 24 | {banks.map((bank, index) => ( 25 |
26 |
31 | {bank.companies.length === 0 ? ( 32 |
33 |
34 | INDISPONÍVEL 35 |
36 |
37 | ) : ( 38 | bank.companies.map((company, i) => ( 39 |
0 ? { borderLeft: '2px solid #c6c6c650' } : {}} 43 | > 44 |
45 | {company} 46 |
47 |
48 | MÍN. 49 |
50 |
51 | MÁX. 52 |
53 |
54 | )) 55 | )} 56 |
57 |
58 | ))} 59 | 60 | ) 61 | } 62 | 63 | export default MatrixHeader 64 | -------------------------------------------------------------------------------- /src/pages/Home/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Link } from 'react-router-dom' 3 | import Layout from '../../components/Layout/Layout' 4 | 5 | import { 6 | HomeStyled, 7 | LeftSideStyled, 8 | CardStyled, 9 | HomeButtonStyled, 10 | ApiCardStyled, 11 | HomeButtonRedirect, 12 | HomeMainContent, 13 | ButtonContainer, 14 | GitHubButtonContainer, 15 | } from './Home.styled' 16 | import home from '../../assets/img/home.svg' 17 | import GitHubButton from 'react-github-btn' 18 | 19 | import { HomeData } from './HomeData' 20 | 21 | const HomePage = () => { 22 | return ( 23 | 24 | 25 | 26 | 34 | Star 35 | 36 | 37 | 38 | 39 |

Seja bem-vindo ao Open Banking Brasil!

40 |

41 | Por meio de um sistema financeiro aberto, regulamentado pelo Banco Central do 42 | Brasil, os dados do cliente podem ser compartilhados de forma segura, mediante 43 | autorização. 44 |

45 | 46 | 47 | 48 | Veja todos os comparativos 49 | 50 | 51 |
52 | 53 |
54 | 55 | 56 | {HomeData.map((item) => ( 57 | 58 | 59 | 60 |

{item.title}

61 | {item.img.alt} 62 |

{item.description}

63 |
64 | 65 |
66 | ))} 67 |
68 |
69 |
70 | ) 71 | } 72 | 73 | export default HomePage 74 | -------------------------------------------------------------------------------- /src/constants/banks.ts: -------------------------------------------------------------------------------- 1 | export interface IBankProps { 2 | brandName: string 3 | apiUrl: string 4 | style: any 5 | logoWidth: string 6 | companies: string[] 7 | } 8 | export const banks: IBankProps[] = [ 9 | { 10 | brandName: 'Banco do Brasil S/A', 11 | companies: ['Banco do Brasil S/A'], 12 | apiUrl: 'https://bb-api.concore.io', 13 | style: { 14 | backgroundColor: '#FBAB7E', 15 | backgroundImage: 'linear-gradient(62deg, #FBAB7E 0%, #F7CE68 100%)', 16 | }, 17 | logoWidth: '40px', 18 | }, 19 | { 20 | brandName: 'Grupo Pan', 21 | companies: ['Banco Pan'], 22 | apiUrl: 'https://bancopan-api.concore.io', 23 | style: { 24 | backgroundImage: 25 | 'radial-gradient( circle 732px at -23.9% -25.1%, #0043ff 6.1%, #00C5FF 100.2% )', 26 | }, 27 | logoWidth: '40px', 28 | }, 29 | { 30 | brandName: 'Banco Bradesco', 31 | companies: ['Banco Bradesco S.A.'], 32 | apiUrl: 'https://api.bradesco.com/bradesco', 33 | style: { background: 'linear-gradient(180deg, #cc092f 0%, #b2207b 100%)' }, 34 | logoWidth: '50px', 35 | }, 36 | { 37 | brandName: 'Itaú', 38 | companies: ['BANCO ITAU CONSIGNADO S.A.', 'BANCO ITAU UNIBANCO S.A.'], 39 | apiUrl: 'https://itau-api.concore.io', 40 | style: { 41 | background: 'linear-gradient( 0deg, #ff9d00 11.2%, rgba(255,0,0,1) 100.2% )', 42 | }, 43 | logoWidth: '50px', 44 | }, 45 | { 46 | brandName: 'Itau Unibanco S.A.', 47 | companies: ['Itau Unibanco S.A.', 'Banco Itaucard S.A.'], 48 | apiUrl: 'https://itau-api.concore.io', 49 | style: { 50 | background: 'linear-gradient( 0deg, #ff9d00 11.2%, rgba(255,0,0,1) 100.2% )', 51 | }, 52 | logoWidth: '50px', 53 | }, 54 | { 55 | brandName: 'ITAU', 56 | companies: [ 57 | 'INVESTCRED', 58 | 'LUIZACRED CFI', 59 | 'FIC FINANCEIRA', 60 | 'HIPERCARD BM', 61 | 'BANCO ITAUCARD', 62 | ], 63 | apiUrl: 'https://itau-api.concore.io', 64 | style: { 65 | background: 'linear-gradient( 0deg, #ff9d00 11.2%, rgba(255,0,0,1) 100.2% )', 66 | }, 67 | logoWidth: '50px', 68 | }, 69 | { 70 | brandName: 'Banco Digital Next', 71 | companies: ['Banco Bradesco S.A.'], 72 | apiUrl: 'https://api.bradesco.com/next', 73 | style: { 74 | background: 'linear-gradient( 110deg, #1D3B3B 11.2%, #3cc974 100.2% )', 75 | }, 76 | logoWidth: '35px', 77 | }, 78 | ] 79 | -------------------------------------------------------------------------------- /asset-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": { 3 | "main.js": "/open-banking-brasil/static/js/main.2f04f596.chunk.js", 4 | "main.js.map": "/open-banking-brasil/static/js/main.2f04f596.chunk.js.map", 5 | "runtime-main.js": "/open-banking-brasil/static/js/runtime-main.07745ca7.js", 6 | "runtime-main.js.map": "/open-banking-brasil/static/js/runtime-main.07745ca7.js.map", 7 | "static/css/2.adb2dfaf.chunk.css": "/open-banking-brasil/static/css/2.adb2dfaf.chunk.css", 8 | "static/js/2.8b206ba6.chunk.js": "/open-banking-brasil/static/js/2.8b206ba6.chunk.js", 9 | "static/js/2.8b206ba6.chunk.js.map": "/open-banking-brasil/static/js/2.8b206ba6.chunk.js.map", 10 | "static/js/3.f4a706e7.chunk.js": "/open-banking-brasil/static/js/3.f4a706e7.chunk.js", 11 | "static/js/3.f4a706e7.chunk.js.map": "/open-banking-brasil/static/js/3.f4a706e7.chunk.js.map", 12 | "index.html": "/open-banking-brasil/index.html", 13 | "static/css/2.adb2dfaf.chunk.css.map": "/open-banking-brasil/static/css/2.adb2dfaf.chunk.css.map", 14 | "static/js/2.8b206ba6.chunk.js.LICENSE.txt": "/open-banking-brasil/static/js/2.8b206ba6.chunk.js.LICENSE.txt", 15 | "static/media/account.228c857b.svg": "/open-banking-brasil/static/media/account.228c857b.svg", 16 | "static/media/banco-pan-logo.c0fd5379.svg": "/open-banking-brasil/static/media/banco-pan-logo.c0fd5379.svg", 17 | "static/media/bradesco-logo.d69a0ae7.png": "/open-banking-brasil/static/media/bradesco-logo.d69a0ae7.png", 18 | "static/media/credit-card.11093fcb.svg": "/open-banking-brasil/static/media/credit-card.11093fcb.svg", 19 | "static/media/financings.868a4c70.svg": "/open-banking-brasil/static/media/financings.868a4c70.svg", 20 | "static/media/home.5c01ce36.svg": "/open-banking-brasil/static/media/home.5c01ce36.svg", 21 | "static/media/itau-logo.96cc5dd0.webp": "/open-banking-brasil/static/media/itau-logo.96cc5dd0.webp", 22 | "static/media/loan.c6bc1e1a.svg": "/open-banking-brasil/static/media/loan.c6bc1e1a.svg", 23 | "static/media/next-logo.d5228214.svg": "/open-banking-brasil/static/media/next-logo.d5228214.svg" 24 | }, 25 | "entrypoints": [ 26 | "static/js/runtime-main.07745ca7.js", 27 | "static/css/2.adb2dfaf.chunk.css", 28 | "static/js/2.8b206ba6.chunk.js", 29 | "static/js/main.2f04f596.chunk.js" 30 | ] 31 | } -------------------------------------------------------------------------------- /src/pages/Home/HomeData.ts: -------------------------------------------------------------------------------- 1 | import loan from '../../assets/img/illustrations/loan.svg' 2 | import account from '../../assets/img/illustrations/account.svg' 3 | import creditcard from '../../assets/img/illustrations/credit-card.svg' 4 | import financings from '../../assets/img/illustrations/financings.svg' 5 | 6 | import { 7 | PERSONAL_LOANS, 8 | PERSONAL_ACCOUNTS, 9 | PERSONAL_CREDIT_CARDS, 10 | PERSONAL_FINANCINGS, 11 | BUSINESS_LOANS, 12 | BUSINESS_ACCOUNTS, 13 | BUSINESS_CREDIT_CARDS, 14 | BUSINESS_FINANCINGS, 15 | } from '../../routes' 16 | 17 | export const HomeData = [ 18 | { 19 | path: PERSONAL_LOANS, 20 | title: 'Juros - Empréstimos PF', 21 | img: { 22 | src: loan, 23 | alt: 'Api de Empréstimos pessoa física', 24 | }, 25 | description: 'Api de Empréstimos PJ', 26 | }, 27 | { 28 | path: BUSINESS_LOANS, 29 | title: 'Juros - Empréstimos PJ', 30 | img: { 31 | src: loan, 32 | alt: 'Api de Empréstimos pessoa jurídica', 33 | }, 34 | description: 'Api de Empréstimos PJ', 35 | }, 36 | { 37 | path: PERSONAL_ACCOUNTS, 38 | title: 'Tarifas - Conta PF', 39 | img: { 40 | src: account, 41 | alt: 'Tarifas Conta Pessoal', 42 | }, 43 | description: 'Api de Conta pessoa física', 44 | }, 45 | { 46 | path: BUSINESS_ACCOUNTS, 47 | title: 'Tarifas - Conta PJ', 48 | img: { 49 | src: account, 50 | alt: 'Tarifas - Conta Jurídica', 51 | }, 52 | description: 'Api de Conta pessoa jurídica', 53 | }, 54 | { 55 | path: PERSONAL_CREDIT_CARDS, 56 | title: 'Tarifas - Cartão PF', 57 | img: { 58 | src: creditcard, 59 | alt: 'Tarifas - Cartão PF', 60 | }, 61 | description: 'Api de Cartão de Crédito PF', 62 | }, 63 | { 64 | path: BUSINESS_CREDIT_CARDS, 65 | title: 'Tarifas - Cartão PJ', 66 | img: { 67 | src: creditcard, 68 | alt: 'Tarifas - Cartão PJ', 69 | }, 70 | description: 'Api de Cartão de Crédito PJ', 71 | }, 72 | { 73 | path: PERSONAL_FINANCINGS, 74 | title: 'Tarifas - Financiamento PF', 75 | img: { 76 | src: financings, 77 | alt: 'Tarifas - Financiamento PF', 78 | }, 79 | description: 'Api de Financiamento PF', 80 | }, 81 | { 82 | path: BUSINESS_FINANCINGS, 83 | title: 'Tarifas - Financiamento PJ', 84 | img: { 85 | src: financings, 86 | alt: 'Tarifas - Financiamento PJ', 87 | }, 88 | description: 'Api de Financiamento PJ', 89 | }, 90 | ] 91 | -------------------------------------------------------------------------------- /static/js/runtime-main.07745ca7.js: -------------------------------------------------------------------------------- 1 | !function(e){function r(r){for(var n,i,u=r[0],c=r[1],l=r[2],s=0,p=[];s -------------------------------------------------------------------------------- /src/assets/img/next-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /static/media/next-logo.d5228214.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Feito com ♥ pelo time de Developer Experience da API Playbook! [Fale conosco](https://www.apiplaybook.com/) ;D. 2 | 3 | Licença MIT. 4 | 5 | # Open Banking Brasil 6 | 7 | No dia 1º de fevereiro de 2021, foi implementado o Open Banking no Brasil. Ele promete revolucionar o mercado financeiro, pois com ele será possível o compartilhamento de informações bancárias entre diferentes instituições. 8 | 9 | A primeira fase do Open Banking Brasil disponibiliza informações sobre as instituições financeiras, como taxas e tarifas cobradas por serviços prestados pelos bancos. Neste primeiro momento, isso permite que o cliente possa comparar as instituições e que escolha a melhor opção para o seu caso, incentivando a competição por serviços e crédito mais barato e de melhor qualidade. 10 | 11 | Essas informações públicas são disponibilizadas através de _RESTful APIs_. Para mais informações sobre as APIs, consulte esta [documentação](https://openbanking-brasil.github.io/areadesenvolvedor/). 12 | 13 | ## Como realizar as consultas às APIs 14 | 15 | As APIs disponíveis, na primeira fase, possuem um funcionamento muito simples. Basta realizar uma requisição `GET` ao _URI_ da API desejada e será retornada a resposta em um `JSON` 16 | 17 | Os URIs das APIs de diferentes bancos seguem o mesmo princípio: 18 | 19 | https://**url-base-disponibilizado-pelo-banco**/open-banking/products-services/v1/**api** 20 | 21 | O URL base fica disponível no portal dev da instituição financeira e **normalmente** seguem o padrão: 22 | 23 | https://api.**banco**.com 24 | 25 | Algumas APIs podem sofrer com um problema de acesso bloqueado pelo `CORS` (_Cross-origin resource sharing_). Se isso ocorrer, será necessário o uso de um _proxy_ para intermediar a requisição à API que está sofrendo com este problema. 26 | 27 | Para mais informações sobre as APIs do **Open Banking Brasil**, consulte esta [documentação](https://openbanking-brasil.github.io/areadesenvolvedor/). 28 | 29 | ## `Contas pessoa física` 30 | 31 | A API de contas pessoa física leva o nome de **`personal-accounts`** e retorna as formas de movimentações e suas tarifas, termos e condições de contrato, entre outras coisas. 32 | 33 | `GET` https://**url-base-disponibilizado-pelo-banco**/open-banking/products-services/v1/**personal-accounts** 34 | 35 | ## `Empréstimo pessoa física` 36 | 37 | A API de empréstimo pessoa física leva o nome de **`personal-loans`** e retorna as taxas cobradas para os diferentes tipos de empréstimo, termos e condições de contrato e outras informações sobre empréstimo para pessoa física. 38 | 39 | `GET` https://**url-base-disponibilizado-pelo-banco**/open-banking/products-services/v1/**personal-loans** 40 | 41 | ## `Empréstimo pessoa jurídica` 42 | 43 | A API de empréstimo pessoa jurpidica leva o nome de **`business-loans`** e retorna as taxas cobradas para os diferentes tipos de empréstimo, termos e condições de contrato e outras informações sobre empréstimo para pessoa jurídica. 44 | 45 | `GET` https://**url-base-disponibilizado-pelo-banco**/open-banking/products-services/v1/**business-loans** 46 | -------------------------------------------------------------------------------- /src/constants/apis.ts: -------------------------------------------------------------------------------- 1 | interface IBank { 2 | brand: string 3 | companies: string[] 4 | } 5 | export interface IApis { 6 | endpoint: string 7 | banks: IBank[] 8 | } 9 | 10 | export const apis: IApis[] = [ 11 | { 12 | endpoint: '/personal-accounts', 13 | banks: [ 14 | { brand: 'Banco do Brasil S/A', companies: ['Banco do Brasil S/A'] }, 15 | { brand: 'Grupo Pan', companies: ['Banco Pan'] }, 16 | { brand: 'Banco Bradesco', companies: ['Banco Bradesco S.A.'] }, 17 | { 18 | brand: 'Itau Unibanco S.A.', 19 | companies: ['Itau Unibanco S.A.'], 20 | }, 21 | { brand: 'Banco Digital Next', companies: ['Banco Bradesco S.A.'] }, 22 | ], 23 | }, 24 | { 25 | endpoint: '/business-accounts', 26 | banks: [ 27 | { brand: 'Banco do Brasil S/A', companies: ['Banco do Brasil S/A'] }, 28 | { brand: 'Banco Bradesco', companies: ['Banco Bradesco S.A.'] }, 29 | { 30 | brand: 'Itau Unibanco S.A.', 31 | companies: ['Itau Unibanco S.A.'], 32 | }, 33 | ], 34 | }, 35 | { 36 | endpoint: '/personal-loans', 37 | banks: [ 38 | { brand: 'Banco do Brasil S/A', companies: ['Banco do Brasil S/A'] }, 39 | { brand: 'Grupo Pan', companies: ['Banco Pan'] }, 40 | { brand: 'Banco Bradesco', companies: ['Banco Bradesco S.A.'] }, 41 | { 42 | brand: 'Itaú', 43 | companies: ['BANCO ITAU CONSIGNADO S.A.', 'BANCO ITAU UNIBANCO S.A.'], 44 | }, 45 | { brand: 'Banco Digital Next', companies: ['Banco Bradesco S.A.'] }, 46 | ], 47 | }, 48 | { 49 | endpoint: '/business-loans', 50 | banks: [ 51 | { brand: 'Banco do Brasil S/A', companies: ['Banco do Brasil S/A'] }, 52 | { brand: 'Banco Bradesco', companies: ['Banco Bradesco S.A.'] }, 53 | { 54 | brand: 'Itaú', 55 | companies: ['BANCO ITAU UNIBANCO S.A.'], 56 | }, 57 | ], 58 | }, 59 | { 60 | endpoint: '/personal-financings', 61 | banks: [ 62 | { brand: 'Banco do Brasil S/A', companies: ['Banco do Brasil S/A'] }, 63 | { brand: 'Banco Bradesco', companies: ['Banco Bradesco S.A.'] }, 64 | { 65 | brand: 'Itaú', 66 | companies: ['BANCO ITAU UNIBANCO S.A.'], 67 | }, 68 | ], 69 | }, 70 | { 71 | endpoint: '/business-financings', 72 | banks: [ 73 | { brand: 'Banco do Brasil S/A', companies: ['Banco do Brasil S/A'] }, 74 | { brand: 'Banco Bradesco', companies: ['Banco Bradesco S.A.'] }, 75 | { 76 | brand: 'Itaú', 77 | companies: ['BANCO ITAU UNIBANCO S.A.', 'BANCO ITAUCARD'], 78 | }, 79 | ], 80 | }, 81 | 82 | { 83 | endpoint: '/personal-credit-cards', 84 | banks: [ 85 | { brand: 'Banco do Brasil S/A', companies: ['Banco do Brasil S/A'] }, 86 | { brand: 'Banco Bradesco', companies: ['Banco Bradesco S.A.'] }, 87 | { 88 | brand: 'ITAU', 89 | companies: [ 90 | 'INVESTCRED', 91 | 'LUIZACRED CFI', 92 | 'FIC FINANCEIRA', 93 | 'HIPERCARD BM', 94 | 'BANCO ITAUCARD', 95 | ], 96 | }, 97 | ], 98 | }, 99 | 100 | { 101 | endpoint: '/business-credit-cards', 102 | banks: [ 103 | { brand: 'Banco do Brasil S/A', companies: ['Banco do Brasil S/A'] }, 104 | { brand: 'Banco Bradesco', companies: ['Banco Bradesco S.A.'] }, 105 | { 106 | brand: 'ITAU', 107 | companies: ['BANCO ITAUCARD'], 108 | }, 109 | ], 110 | }, 111 | ] 112 | -------------------------------------------------------------------------------- /static/js/3.f4a706e7.chunk.js: -------------------------------------------------------------------------------- 1 | (this["webpackJsonpopen-banking-brasil"]=this["webpackJsonpopen-banking-brasil"]||[]).push([[3],{113:function(t,n,e){"use strict";e.r(n),e.d(n,"getCLS",(function(){return v})),e.d(n,"getFCP",(function(){return g})),e.d(n,"getFID",(function(){return h})),e.d(n,"getLCP",(function(){return y})),e.d(n,"getTTFB",(function(){return F}));var i,a,r=function(){return"".concat(Date.now(),"-").concat(Math.floor(8999999999999*Math.random())+1e12)},o=function(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:-1;return{name:t,value:n,delta:0,entries:[],id:r(),isFinal:!1}},u=function(t,n){try{if(PerformanceObserver.supportedEntryTypes.includes(t)){var e=new PerformanceObserver((function(t){return t.getEntries().map(n)}));return e.observe({type:t,buffered:!0}),e}}catch(t){}},s=!1,c=!1,p=function(t){s=!t.persisted},d=function(){addEventListener("pagehide",p),addEventListener("beforeunload",(function(){}))},f=function(t){var n=arguments.length>1&&void 0!==arguments[1]&&arguments[1];c||(d(),c=!0),addEventListener("visibilitychange",(function(n){var e=n.timeStamp;"hidden"===document.visibilityState&&t({timeStamp:e,isUnloading:s})}),{capture:!0,once:n})},l=function(t,n,e,i){var a;return function(){e&&n.isFinal&&e.disconnect(),n.value>=0&&(i||n.isFinal||"hidden"===document.visibilityState)&&(n.delta=n.value-(a||0),(n.delta||n.isFinal||void 0===a)&&(t(n),a=n.value))}},v=function(t){var n,e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],i=o("CLS",0),a=function(t){t.hadRecentInput||(i.value+=t.value,i.entries.push(t),n())},r=u("layout-shift",a);r&&(n=l(t,i,r,e),f((function(t){var e=t.isUnloading;r.takeRecords().map(a),e&&(i.isFinal=!0),n()})))},m=function(){return void 0===i&&(i="hidden"===document.visibilityState?0:1/0,f((function(t){var n=t.timeStamp;return i=n}),!0)),{get timeStamp(){return i}}},g=function(t){var n,e=o("FCP"),i=m(),a=u("paint",(function(t){"first-contentful-paint"===t.name&&t.startTime1&&void 0!==arguments[1]&&arguments[1],i=o("LCP"),a=m(),r=function(t){var e=t.startTime;e { 24 | let pageCompanies: any = ['INDISPONÍVEL'] 25 | stateCompanies.forEach((array: string[][]) => 26 | array.forEach((companyName) => pageCompanies.push(companyName)) 27 | ) 28 | let fixedBanks = banks 29 | banks.forEach((banks: any, index: number) => { 30 | if (fixedBanks[index].companies.length === 0) { 31 | fixedBanks[index].companies = ['INDISPONÍVEL'] 32 | } else { 33 | fixedBanks[index].companies = fixedBanks[ 34 | index 35 | ].companies.filter((companyName: string) => pageCompanies.includes(companyName)) 36 | } 37 | }) 38 | return ( 39 | 40 | 41 | {Object.keys(typesState).map((index) => ( 42 | 43 |
44 | {index.replace(/[_\s]/g, ' ')} 45 |
46 | {banks 47 | .map((bank) => bank.brandName) 48 | .map((requiredBrand) => ( 49 | brandName === requiredBrand)[0].companies 52 | .length 53 | )} 54 | key={`matrixCell${requiredBrand}_${index}${Math.random()}`} 55 | id="matrixCell" 56 | > 57 | {typesState[index].map((brand) => { 58 | return banks 59 | .filter(({ brandName }) => brandName === requiredBrand)[0] 60 | .companies.map((companyName, cIndex) => { 61 | return ( 62 | omit('brand', brand).company === companyName && 63 | brand.brand === requiredBrand && ( 64 |
69 | {Object.values(omit('company', omit('brand', brand))).map( 70 | ({ name, minimum, maximum }) => { 71 | return ( 72 | 88 | ) 89 | } 90 | )} 91 |
92 | ) 93 | ) 94 | }) 95 | })} 96 |
97 | ))} 98 |
99 | ))} 100 |
101 | ) 102 | } 103 | 104 | export default ComparisonMatrix 105 | -------------------------------------------------------------------------------- /src/pages/Home/Home.styled.ts: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components' 2 | 3 | export const HomeStyled = styled.div` 4 | display: flex; 5 | flex-direction: column; 6 | max-width: 1120px; 7 | margin: 0 auto; 8 | ` 9 | export const LeftSideStyled = styled.div` 10 | img { 11 | width: 600px; 12 | } 13 | display: grid; 14 | grid-template-columns: 0.9fr 1.1fr; 15 | & > img { 16 | max-width: 50vw; 17 | } 18 | @media only screen and (max-width: 1600px) { 19 | grid-template-columns: 1.2fr 0.8fr; 20 | & > img { 21 | max-width: 43vw; 22 | } 23 | h1 { 24 | font-size: 30pt !important; 25 | } 26 | p { 27 | font-size: 12pt !important; 28 | } 29 | & > div { 30 | padding: 0 0 0 50px; 31 | } 32 | } 33 | @media only screen and (max-width: 1100px) { 34 | grid-template-columns: 1.5fr 0.5fr; 35 | & > img { 36 | max-width: 40vw; 37 | } 38 | h1 { 39 | font-size: 26pt !important; 40 | } 41 | 42 | & > div { 43 | padding: 0 40px; 44 | } 45 | } 46 | @media only screen and (max-width: 800px) { 47 | display: flex; 48 | flex-direction: column; 49 | & > img { 50 | align-self: center; 51 | max-width: 80vw; 52 | } 53 | } 54 | ` 55 | export const CardStyled = styled.div` 56 | margin-top: 20px; 57 | 58 | h1 { 59 | font-family: 'Inter', sans-serif; 60 | margin-top: 35px; 61 | margin-bottom: 15px; 62 | font-size: 40px; 63 | } 64 | 65 | p { 66 | margin-top: 30px; 67 | text-align: justify; 68 | font-size: 16px; 69 | font-weight: 500; 70 | } 71 | ` 72 | export const HomeButtonStyled = styled.div` 73 | display: flex; 74 | justify-content: center; 75 | align-items: center; 76 | ` 77 | export const ApiCardStyled = styled.div` 78 | width: 400px; 79 | position: relative; 80 | top: -35px; 81 | display: flex; 82 | flex-direction: column; 83 | align-content: center; 84 | justify-content: center; 85 | height: fit-content; 86 | width: fit-content; 87 | max-width: 600px; 88 | background: #f0f4f7; 89 | padding: 30px; 90 | border-radius: 5px; 91 | box-shadow: 0px 0px 24px rgb(0 0 0 / 14%); 92 | margin-bottom: 50px; 93 | cursor: pointer; 94 | transition: all 0.2s ease-in-out; 95 | &:hover { 96 | transform: scale(1.1); 97 | background: linear-gradient(180deg, #46236f 0%, #7b2987 100%); 98 | color: #fff; 99 | z-index: 1; 100 | } 101 | h3 { 102 | margin-bottom: 15px; 103 | text-align: center; 104 | } 105 | h3::before { 106 | content: ''; 107 | width: 50px; 108 | height: 4px; 109 | display: block; 110 | background: #3e446c; 111 | position: absolute; 112 | left: 50%; 113 | bottom: 0; 114 | -ms-transform: translateX(-50%); 115 | transform: translateX(-50%); 116 | } 117 | img { 118 | height: 150px; 119 | margin: auto; 120 | margin-bottom: 15px; 121 | } 122 | p { 123 | text-align: center; 124 | font-size: 11pt; 125 | } 126 | ` 127 | 128 | export const HomeButtonRedirect = styled.button` 129 | background-color: #6c63ff; 130 | height: 40px; 131 | font-weight: bold; 132 | padding: 0 30px; 133 | color: #ffff; 134 | cursor: pointer; 135 | transition: all 0.2s ease-in-out; 136 | &:hover { 137 | opacity: 0.5; 138 | } 139 | ` 140 | 141 | export const HomeMainContent = styled.div` 142 | padding-top: 150px; 143 | max-width: 1120px; 144 | width: 100%; 145 | display: flex; 146 | align-items: center; 147 | justify-content: space-evenly; 148 | flex-wrap: wrap; 149 | margin-top: 150px; 150 | margin-bottom: 80px; 151 | margin: 0 auto; 152 | ` 153 | 154 | export const ButtonContainer = styled.div` 155 | margin-top: 25px; 156 | width: 100%; 157 | display: flex; 158 | align-items: center; 159 | 160 | a { 161 | flex: 1; 162 | } 163 | ` 164 | 165 | export const GitHubButtonContainer = styled.div` 166 | width: 100%; 167 | display: flex; 168 | flex-direction: row-reverse; 169 | padding-right: 59px; 170 | @media only screen and (max-width: 1600px) { 171 | padding-right: 40px; 172 | } 173 | @media only screen and (max-width: 1100px) { 174 | padding-right: 30px; 175 | } 176 | @media only screen and (max-width: 1100px) { 177 | padding-right: 25px; 178 | } 179 | ` 180 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 11 | 12 | 16 | 17 | 18 | 19 | 28 | API Playbook - Comparador de Taxas 29 | 40 | 73 | 74 | 75 | 76 | 77 |
78 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | API Playbook - Comparador de Taxas
-------------------------------------------------------------------------------- /src/assets/img/rate.svg: -------------------------------------------------------------------------------- 1 | #119_analyzing process_twocolour -------------------------------------------------------------------------------- /static/media/account.228c857b.svg: -------------------------------------------------------------------------------- 1 | #95_profile analysis_twocolour -------------------------------------------------------------------------------- /src/assets/img/illustrations/account.svg: -------------------------------------------------------------------------------- 1 | #95_profile analysis_twocolour -------------------------------------------------------------------------------- /src/assets/img/banco-pan-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Banco PAN - 616161 e azul 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /static/media/banco-pan-logo.c0fd5379.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Banco PAN - 616161 e azul 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/pages/PersonalFinancings/index.tsx: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | 3 | import React, { useState, useEffect, useMemo } from 'react' 4 | import { Ellipsis } from 'react-spinners-css' 5 | 6 | import { callApisOpenBanking } from '../../services/callApisOpenBanking' 7 | import { getBanksOfApi } from '../../utils/getBanksOfApi' 8 | import { fixMoney } from '../../utils/fixMoney' 9 | 10 | import ComparisonMatrix from '../../components/ComparisonMatrix' 11 | import Layout from '../../components/Layout/Layout' 12 | import { 13 | CompanyStyled, 14 | MatrixPageStyled, 15 | TableStyled, 16 | } from '../../styles/CallApiPage.styled' 17 | 18 | const PersonalFinancingsPage = () => { 19 | const [state, setState] = useState([]) 20 | 21 | const endpoint = '/personal-financings' 22 | const banks = getBanksOfApi(endpoint) 23 | 24 | // Realiza as consultas às APIs 25 | useEffect(() => { 26 | ;(async () => { 27 | const apiResponses = await callApisOpenBanking('/personal-financings') 28 | 29 | setState(apiResponses) 30 | })() 31 | }, []) 32 | 33 | // Organiza as informações para serem lidas pela matriz 34 | const typesState = useMemo(() => { 35 | let types = [] 36 | state.forEach((brand) => 37 | brand.companies.forEach((company) => { 38 | company.personalFinancings.forEach((financing) => { 39 | const services = financing.fees.services.map(({ name, minimum, maximum }) => { 40 | return { 41 | name: name, 42 | minimum: minimum.value, 43 | maximum: maximum.value, 44 | } 45 | }) 46 | 47 | if (types[financing.type]) { 48 | types[financing.type] = [ 49 | ...types[financing.type], 50 | { 51 | ...services, 52 | brand: brand.name, 53 | company: company.name, 54 | }, 55 | ] 56 | } else { 57 | types[financing.type] = [ 58 | { 59 | ...services, 60 | brand: brand.name, 61 | company: company.name, 62 | }, 63 | ] 64 | } 65 | }) 66 | }) 67 | ) 68 | 69 | return types 70 | }, [state]) 71 | 72 | return ( 73 | 74 | 75 |

76 | Estas são todas as tarifas dos serviços de financiamento para pessoa física dos 77 | bancos:  78 | {banks.map((bank, index) => 79 | index === 0 ? `${bank.brandName}` : `, ${bank.brandName}` 80 | )} 81 | . 82 |

83 | {state.length > 0 && ( 84 | bank.brandName) 88 | .map( 89 | (requiredBrand) => state.filter((brand) => brand.name === requiredBrand)[0] 90 | ) 91 | .map(({ companies }) => 92 | companies.map(({ name }) => { 93 | return name 94 | }) 95 | ) 96 | .map((array) => Object.values(array))} 97 | typesState={typesState} 98 | fixFunction={fixMoney} 99 | /> 100 | )} 101 | {Object.keys(typesState).length === 0 && } 102 |

103 | Tabelas completas com as tarifas dos serviços de financiamento para pessoa física: 104 |

105 | {state && 106 | state.map((brand, index) => 107 | brand.companies.map((company) => ( 108 | 109 |
110 | {brand.name}{' '} 111 | 117 | {brand.companies[0].name} 118 | {' '} 119 | CNPJ: {brand.companies[0].cnpjNumber} 120 |
121 | 122 | 123 | 124 | Tipo de financiamento 125 | Serviço 126 | Tarifa Mín. 127 | Tarifa Máx. 128 | Termos 129 | 130 | 131 | 132 | {company.personalFinancings && 133 | company.personalFinancings.map(({ type, fees, termsConditions }) => 134 | fees.services.map(({ name, minimum, maximum }, index) => ( 135 | 136 | {type.replace(/[_\s]/g, ' ')} 137 | {name.replace(/[_\s]/g, ' ')} 138 | {fixMoney(minimum.value)} 139 | {fixMoney(maximum.value)} 140 | 141 | {!termsConditions ? ( 142 |

NA

143 | ) : ( 144 | 150 | Termos 151 | 152 | )} 153 | 154 | 155 | )) 156 | )} 157 | 158 |
159 |
160 | )) 161 | )} 162 |
163 |
164 | ) 165 | } 166 | 167 | export default PersonalFinancingsPage 168 | -------------------------------------------------------------------------------- /src/pages/BusinessFinancing/index.tsx: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | 3 | import React, { useState, useEffect, useMemo } from 'react' 4 | import { Ellipsis } from 'react-spinners-css' 5 | 6 | import { callApisOpenBanking } from '../../services/callApisOpenBanking' 7 | import { getBanksOfApi } from '../../utils/getBanksOfApi' 8 | import { fixMoney } from '../../utils/fixMoney' 9 | 10 | import ComparisonMatrix from '../../components/ComparisonMatrix' 11 | import Layout from '../../components/Layout/Layout' 12 | import { 13 | CompanyStyled, 14 | MatrixPageStyled, 15 | TableStyled, 16 | } from '../../styles/CallApiPage.styled' 17 | const BusinessFinancingsPage = () => { 18 | const [state, setState] = useState([]) 19 | 20 | const endpoint = '/business-financings' 21 | const banks = getBanksOfApi(endpoint) 22 | 23 | // Realiza as consultas às APIs 24 | useEffect(() => { 25 | ;(async () => { 26 | const apiResponses = await callApisOpenBanking('/business-financings') 27 | 28 | setState(apiResponses) 29 | })() 30 | }, []) 31 | 32 | // Organiza as informações para serem lidas pela matriz 33 | const typesState = useMemo(() => { 34 | let types = [] 35 | state.forEach((brand) => 36 | brand.companies.forEach((company) => { 37 | company.businessFinancings.forEach((financing) => { 38 | const rates = financing.interestRates.map((rate) => { 39 | return { 40 | name: rate.referentialRateIndexer, 41 | minimum: rate.minimumRate, 42 | maximum: rate.maximumRate, 43 | } 44 | }) 45 | if (types[financing.type]) { 46 | types[financing.type] = [ 47 | ...types[financing.type], 48 | { 49 | ...rates, 50 | brand: brand.name, 51 | company: company.name, 52 | }, 53 | ] 54 | } else { 55 | types[financing.type] = [ 56 | { 57 | ...rates, 58 | brand: brand.name, 59 | company: company.name, 60 | }, 61 | ] 62 | } 63 | }) 64 | }) 65 | ) 66 | 67 | return types 68 | }, [state]) 69 | 70 | return ( 71 | 72 | 73 |

74 | Estas são todas as tarifas dos serviços de financiamento para pessoa juridica dos 75 | bancos:  76 | {banks.map((bank, index) => 77 | index === 0 ? `${bank.brandName}` : `, ${bank.brandName}` 78 | )} 79 | . 80 |

81 | {state.length > 0 && ( 82 | bank.brandName) 86 | .map( 87 | (requiredBrand) => state.filter((brand) => brand.name === requiredBrand)[0] 88 | ) 89 | .map(({ companies }) => 90 | companies.map(({ name }) => { 91 | return name 92 | }) 93 | ) 94 | .map((array) => Object.values(array))} 95 | typesState={typesState} 96 | fixFunction={fixMoney} 97 | /> 98 | )} 99 | {Object.keys(typesState).length === 0 && } 100 |

101 | Tabelas completas com as tarifas dos serviços de financiamento para pessoa 102 | juridica: 103 |

104 | {state && 105 | state.map((brand, index) => 106 | brand.companies.map((company) => ( 107 | 108 |
109 | {brand.name}{' '} 110 | 116 | {brand.companies[0].name} 117 | {' '} 118 | CNPJ: {brand.companies[0].cnpjNumber} 119 |
120 | 121 | 122 | 123 | Tipo de financiamento 124 | Serviço 125 | Tarifa Mín. 126 | Tarifa Máx. 127 | Termos 128 | 129 | 130 | 131 | {company.businessFinancings && 132 | company.businessFinancings.map(({ type, fees, termsConditions }) => 133 | fees.services.map( 134 | ({ name, chargingTriggerInfo, minimum, maximum }, index) => ( 135 | 136 | {type.replace(/[_\s]/g, ' ')} 137 | {name.replace(/[_\s]/g, ' ')} 138 | {fixMoney(minimum.value)} 139 | {fixMoney(maximum.value)} 140 | 141 | 142 | {termsConditions === 'NA' ? ( 143 |

NA

144 | ) : ( 145 | 151 | Termos 152 | 153 | )} 154 | 155 | 156 | ) 157 | ) 158 | )} 159 | 160 |
161 |
162 | )) 163 | )} 164 |
165 |
166 | ) 167 | } 168 | 169 | export default BusinessFinancingsPage 170 | -------------------------------------------------------------------------------- /src/pages/PersonalAccounts/index.tsx: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-extra-semi */ 2 | // @ts-nocheck 3 | import React, { useState, useEffect, useMemo } from 'react' 4 | import { Ellipsis } from 'react-spinners-css' 5 | 6 | import Layout from '../../components/Layout/Layout' 7 | import { 8 | CompanyStyled, 9 | MatrixPageStyled, 10 | TableStyled, 11 | } from '../../styles/CallApiPage.styled' 12 | import { fixMoney } from '../../utils/fixMoney' 13 | import { useModal } from '../../hooks/Modal' 14 | 15 | import { callApisOpenBanking } from '../../services/callApisOpenBanking' 16 | import ComparisonMatrix from '../../components/ComparisonMatrix' 17 | 18 | import { getBanksOfApi } from '../../utils/getBanksOfApi' 19 | 20 | const PersonalLoansPage = () => { 21 | const [state, setState] = useState([]) 22 | const { addMoreInfo } = useModal() 23 | 24 | const endpoint = '/personal-accounts' 25 | const banks = getBanksOfApi(endpoint) 26 | 27 | // Realiza as consultas às APIs 28 | useEffect(() => { 29 | ;(async () => { 30 | const apiResponses = await callApisOpenBanking(endpoint) 31 | setState(apiResponses) 32 | })() 33 | }, []) 34 | 35 | // Organiza as informações para serem lidas pela matriz 36 | const typesState = useMemo(() => { 37 | let services = [] 38 | let servicesList = [] 39 | let companies = [] 40 | state && 41 | state.forEach((brand) => { 42 | brand.companies.forEach((company) => { 43 | company.personalAccounts.forEach((account) => { 44 | account.fees.priorityServices.forEach(({ code, minimum, maximum }) => { 45 | const fare = { 46 | code, 47 | name: account.type, 48 | minimum: minimum.value, 49 | maximum: maximum.value, 50 | } 51 | 52 | companies[company.name] 53 | ? companies[company.name].push(fare) 54 | : (companies[company.name] = [fare]) 55 | 56 | !servicesList.includes(code) && servicesList.push(code) 57 | }) 58 | }) 59 | servicesList.forEach((serviceCode) => { 60 | const servicePayload = company.name !== 'INDISPONÍVEL' && { 61 | ...companies[company.name] 62 | .filter((fare) => fare.code === serviceCode) 63 | .map((fare) => { 64 | return { 65 | name: fare.name, 66 | minimum: fare.minimum, 67 | maximum: fare.maximum, 68 | } 69 | }), 70 | brand: brand.name, 71 | company: company.name, 72 | } 73 | services[serviceCode] 74 | ? services[serviceCode].push(servicePayload) 75 | : (services[serviceCode] = [servicePayload]) 76 | }) 77 | }) 78 | }) 79 | 80 | return services 81 | }, [state]) 82 | 83 | return ( 84 | 85 | 86 |

87 | Estas são todas as taxas dos produtos e serviços para contas de pessoa fisica dos 88 | bancos:  89 | {banks.map((bank, index) => 90 | index === 0 ? `${bank.brandName}` : `, ${bank.brandName}` 91 | )} 92 | . 93 |

94 | {state.length > 0 && ( 95 | bank.brandName) 99 | .map( 100 | (requiredBrand) => state.filter((brand) => brand.name === requiredBrand)[0] 101 | ) 102 | .map(({ companies }) => 103 | companies.map(({ name }) => { 104 | return name 105 | }) 106 | ) 107 | .map((array) => Object.values(array))} 108 | typesState={typesState} 109 | fixFunction={fixMoney} 110 | /> 111 | )} 112 | 113 | {Object.keys(typesState).length === 0 && } 114 |

115 | Tabelas completas com as tarifas de contas para pessoas físicas. 116 |

117 | {state && 118 | state.map((brand, index) => 119 | brand.companies.map((company) => ( 120 | 121 |
122 | {brand.name}{' '} 123 | 129 | {brand.companies[0].name} 130 | 131 | CNPJ: {brand.companies[0].cnpjNumber} 132 |
133 | 134 | 135 | 136 | Taxas de juros 137 | Tipo de conta 138 | Mín 139 | Máx 140 | Informações 141 | 142 | 143 | 144 | {company.personalAccounts && 145 | company.personalAccounts.map(({ type, fees, termsConditions }) => 146 | fees.priorityServices.map( 147 | ( 148 | { name, chargingTriggerInfo, code, minimum, maximum }, 149 | index 150 | ) => ( 151 | 152 | {code.replace(/[_\s]/g, ' ')} 153 | {type.replace(/[_\s]/g, ' ')} 154 | {fixMoney(minimum.value)} 155 | {fixMoney(maximum.value)} 156 | 157 | 169 | 170 | 171 | ) 172 | ) 173 | )} 174 | 175 | 176 |
177 | )) 178 | )} 179 |
180 |
181 | ) 182 | } 183 | 184 | export default PersonalLoansPage 185 | -------------------------------------------------------------------------------- /src/pages/PersonalLoans/index.tsx: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | import React, { useState, useEffect, useMemo } from 'react' 3 | import { Ellipsis } from 'react-spinners-css' 4 | 5 | import { callApisOpenBanking } from '../../services/callApisOpenBanking' 6 | import { fixTaxes } from '../../utils/fixTaxes' 7 | import { getBanksOfApi } from '../../utils/getBanksOfApi' 8 | 9 | import Layout from '../../components/Layout/Layout' 10 | import ComparisonMatrix from '../../components/ComparisonMatrix' 11 | import { 12 | CompanyStyled, 13 | MatrixPageStyled, 14 | TableStyled, 15 | } from '../../styles/CallApiPage.styled' 16 | 17 | const PersonalLoansPage = () => { 18 | const [state, setState] = useState([]) 19 | 20 | const endpoint = '/personal-loans' 21 | const banks = getBanksOfApi(endpoint) 22 | 23 | // Realiza as consultas às APIs 24 | useEffect(() => { 25 | ;(async () => { 26 | const apiResponses = await callApisOpenBanking('/personal-loans') 27 | setState(apiResponses) 28 | })() 29 | }, []) 30 | 31 | // Organiza as informações para serem lidas pela matriz 32 | const typesState = useMemo(() => { 33 | let types = [] 34 | state.forEach((brand) => 35 | brand.companies.forEach((company) => { 36 | company.personalLoans.forEach((loan) => { 37 | const rates = loan.interestRates.map( 38 | ({ referentialRateIndexer, minimumRate, maximumRate }) => { 39 | return { 40 | name: referentialRateIndexer, 41 | minimum: minimumRate, 42 | maximum: maximumRate, 43 | } 44 | } 45 | ) 46 | if (types[loan.type]) { 47 | types[loan.type] = [ 48 | ...types[loan.type], 49 | { 50 | ...rates, 51 | brand: brand.name, 52 | company: company.name, 53 | }, 54 | ] 55 | } else { 56 | types[loan.type] = [ 57 | { 58 | ...rates, 59 | brand: brand.name, 60 | company: company.name, 61 | }, 62 | ] 63 | } 64 | }) 65 | }) 66 | ) 67 | return types 68 | }, [state]) 69 | 70 | return ( 71 | 72 | 73 |

74 | Este é um comparativo das taxas de empréstimos para pessoas físicas dos 75 | bancos:  76 | {banks.map((bank, index) => 77 | index === 0 ? `${bank.brandName}` : `, ${bank.brandName}` 78 | )} 79 | . 80 |

81 | 82 | {state.length > 0 && ( 83 | bank.brandName) 87 | .map( 88 | (requiredBrand) => state.filter((brand) => brand.name === requiredBrand)[0] 89 | ) 90 | .map(({ companies }) => 91 | companies.map(({ name }) => { 92 | return name 93 | }) 94 | ) 95 | .map((array) => Object.values(array))} 96 | typesState={typesState} 97 | fixFunction={fixTaxes} 98 | /> 99 | )} 100 | {Object.keys(typesState).length === 0 && } 101 |

102 | Tabelas completas com as taxas de empréstimos para pessoas físicas. 103 |

104 | {state && 105 | state.map((brand, index) => 106 | brand.companies.map((company) => ( 107 | 108 |
109 | 115 | {brand.name} 116 | {' '} 117 | {company.name} CNPJ: {company.cnpjNumber} 118 |
119 | 120 | 121 | 122 | Tipo 123 | Taxas de juros 124 | Mín 125 | Máx 126 | Garantias Requeridas 127 | Termos 128 | 129 | 130 | 131 | {company.personalLoans && 132 | company.personalLoans.map( 133 | ({ type, interestRates, requiredWarranties, termsConditions }) => ( 134 | 135 | {type.replace(/[_\s]/g, ' ')} 136 | 137 | {interestRates.map( 138 | ( 139 | { referentialRateIndexer, minimumRate, maximumRate }, 140 | index 141 | ) => ( 142 |

143 | {referentialRateIndexer.replace(/[_\s]/g, ' ')} 144 |

145 | ) 146 | )} 147 | 148 | 149 | {interestRates.map(({ minimumRate }, index) => ( 150 |

151 | {fixTaxes(minimumRate)} 152 |

153 | ))} 154 | 155 | 156 | {interestRates.map(({ maximumRate }, index) => ( 157 |

158 | {fixTaxes(maximumRate)} 159 |

160 | ))} 161 | 162 | {requiredWarranties[0].replace(/[_\s]/g, ' ')} 163 | 164 | {termsConditions === 'NA' ? ( 165 |

NA

166 | ) : ( 167 | 173 | Termos 174 | 175 | )} 176 | 177 | 178 | ) 179 | )} 180 | 181 |
182 |
183 | )) 184 | )} 185 |
186 |
187 | ) 188 | } 189 | 190 | export default PersonalLoansPage 191 | -------------------------------------------------------------------------------- /src/pages/BusinessLoans/index.tsx: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-extra-semi */ 2 | // @ts-nocheck 3 | import React, { useState, useEffect, useMemo } from 'react' 4 | import { Ellipsis } from 'react-spinners-css' 5 | 6 | import { fixTaxes } from '../../utils/fixTaxes' 7 | import { callApisOpenBanking } from '../../services/callApisOpenBanking' 8 | import { getBanksOfApi } from '../../utils/getBanksOfApi' 9 | 10 | import Layout from '../../components/Layout/Layout' 11 | import ComparisonMatrix from '../../components/ComparisonMatrix' 12 | import { 13 | CompanyStyled, 14 | MatrixPageStyled, 15 | TableStyled, 16 | } from '../../styles/CallApiPage.styled' 17 | 18 | const BusinessLoansPage = () => { 19 | const [state, setState] = useState([]) 20 | 21 | const endpoint = '/business-loans' 22 | const banks = getBanksOfApi(endpoint) 23 | 24 | // Realiza as consultas às APIs 25 | useEffect(() => { 26 | ;(async () => { 27 | const apiResponses = await callApisOpenBanking(endpoint) 28 | setState(apiResponses) 29 | })() 30 | }, []) 31 | 32 | // Organiza as informações para serem lidas pela matriz 33 | const typesState = useMemo(() => { 34 | let types = [] 35 | state && 36 | state.forEach((brand) => { 37 | brand.companies.forEach((company) => { 38 | // No retorno do banco orignal ele retorna como personalLoans 39 | const businessLoans = company.personalLoans 40 | ? company.personalLoans 41 | : company.businessLoans 42 | businessLoans.forEach((loan) => { 43 | const rates = loan.interestRates.map( 44 | ({ referentialRateIndexer, minimumRate, maximumRate }) => { 45 | return { 46 | name: referentialRateIndexer, 47 | minimum: minimumRate, 48 | maximum: maximumRate, 49 | } 50 | } 51 | ) 52 | if (types[loan.type]) { 53 | types[loan.type] = [ 54 | ...types[loan.type], 55 | { 56 | ...rates, 57 | brand: brand.name, 58 | company: company.name, 59 | }, 60 | ] 61 | } else { 62 | types[loan.type] = [ 63 | { 64 | ...rates, 65 | brand: brand.name, 66 | company: company.name, 67 | }, 68 | ] 69 | } 70 | }) 71 | }) 72 | }) 73 | 74 | return types 75 | }, [state]) 76 | 77 | return ( 78 | 79 | 80 |

81 | Este é um comparativo das taxas de empréstimos para pessoas jurídicas dos 82 | bancos:  83 | {banks.map((bank, index) => 84 | index === 0 ? `${bank.brandName}` : `, ${bank.brandName}` 85 | )} 86 |

87 | 88 | {state.length > 0 && ( 89 | bank.brandName) 93 | .map( 94 | (requiredBrand) => state.filter((brand) => brand.name === requiredBrand)[0] 95 | ) 96 | .map(({ companies }) => 97 | companies.map(({ name }) => { 98 | return name 99 | }) 100 | ) 101 | .map((array) => Object.values(array))} 102 | typesState={typesState} 103 | fixFunction={fixTaxes} 104 | /> 105 | )} 106 | {Object.keys(typesState).length === 0 && } 107 |

108 | Tabelas completas com as taxas de empréstimos para pessoas jurídica. 109 |

110 | {state && 111 | state.map((brand, index) => 112 | brand.companies.map((company) => ( 113 | 114 |
115 | 121 | {brand.name} 122 | {' '} 123 | {company.name} CNPJ: {company.cnpjNumber} 124 |
125 | 126 | 127 | 128 | Tipo 129 | Taxas de juros 130 | Mín 131 | Máx 132 | Garantias Requeridas 133 | Termos 134 | 135 | 136 | 137 | {company.businessLoans && 138 | company.businessLoans.map( 139 | ( 140 | { type, interestRates, requiredWarranties, termsConditions }, 141 | i 142 | ) => ( 143 | 144 | {type.replace(/[_\s]/g, ' ')} 145 | 146 | {interestRates.map( 147 | ( 148 | { referentialRateIndexer, minimumRate, maximumRate }, 149 | index 150 | ) => ( 151 |

152 | {referentialRateIndexer.replace(/[_\s]/g, ' ')} 153 |

154 | ) 155 | )} 156 | 157 | 158 | {interestRates.map(({ minimumRate }, index) => ( 159 |

160 | {fixTaxes(minimumRate)} 161 |

162 | ))} 163 | 164 | 165 | {interestRates.map(({ maximumRate }, index) => ( 166 |

167 | {fixTaxes(maximumRate)} 168 |

169 | ))} 170 | 171 | {requiredWarranties[0].replace(/[_\s]/g, ' ')} 172 | 173 | {termsConditions === 'NA' ? ( 174 |

NA

175 | ) : ( 176 | 182 | Termos 183 | 184 | )} 185 | 186 | 187 | ) 188 | )} 189 | 190 |
191 |
192 | )) 193 | )} 194 |
195 |
196 | ) 197 | } 198 | 199 | export default BusinessLoansPage 200 | -------------------------------------------------------------------------------- /src/pages/BusinessAccounts/index.tsx: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-extra-semi */ 2 | // @ts-nocheck 3 | import React, { useState, useEffect, useMemo } from 'react' 4 | import { Ellipsis } from 'react-spinners-css' 5 | 6 | import Layout from '../../components/Layout/Layout' 7 | import { 8 | CompanyStyled, 9 | MatrixPageStyled, 10 | TableStyled, 11 | } from '../../styles/CallApiPage.styled' 12 | import { fixMoney } from '../../utils/fixMoney' 13 | 14 | import { callApisOpenBanking } from '../../services/callApisOpenBanking' 15 | import ComparisonMatrix from '../../components/ComparisonMatrix' 16 | import { useModal } from '../../hooks/Modal' 17 | 18 | import { getBanksOfApi } from '../../utils/getBanksOfApi' 19 | 20 | interface IResponsePersonalAccounts { 21 | name: string 22 | companies: ICompanies[] 23 | } 24 | 25 | interface ICompanies { 26 | name: string 27 | cnpjNumber: string 28 | urlComplementaryList: string 29 | businessAccounts: IBusinessAccounts[] 30 | } 31 | 32 | interface IBusinessAccounts { 33 | type: string 34 | fees: { 35 | services: IService[] 36 | } 37 | serviceBundles: IServiceBundles[] 38 | openingClosingChannels: [] 39 | additionalInfo: [] 40 | transactionMethods: [] 41 | termsConditions: {} 42 | incomeRate: {} 43 | } 44 | 45 | interface IService { 46 | name: string 47 | code: string 48 | chargingTriggerInfo: string 49 | prices: IPrice[] 50 | minimum: { 51 | value: string 52 | currency: string 53 | } 54 | maximum: { 55 | value: string 56 | currency: string 57 | } 58 | } 59 | 60 | interface IPrice { 61 | interval: string 62 | value: string 63 | currency: string 64 | customers: { 65 | rate: number 66 | } 67 | } 68 | 69 | const PersonalLoansPage = () => { 70 | const [state, setState] = useState([]) 71 | const { addMoreInfo } = useModal() 72 | 73 | const endpoint = '/business-accounts' 74 | const banks = getBanksOfApi(endpoint) 75 | 76 | // Realiza as consultas às APIs 77 | useEffect(() => { 78 | ;(async () => { 79 | const apiResponses = await callApisOpenBanking(endpoint) 80 | setState(apiResponses) 81 | })() 82 | }, []) 83 | 84 | // Organiza as informações para serem lidas pela matriz 85 | const typesState = useMemo(() => { 86 | let services = [] 87 | let servicesList = [] 88 | let companies = [] 89 | state && 90 | state.forEach((brand) => { 91 | brand.companies.forEach((company) => { 92 | company.businessAccounts.forEach((account) => { 93 | account.fees.services.forEach(({ code, minimum, maximum }) => { 94 | const fare = { 95 | code, 96 | name: account.type, 97 | minimum: minimum.value, 98 | maximum: maximum.value, 99 | } 100 | 101 | companies[company.name] 102 | ? companies[company.name].push(fare) 103 | : (companies[company.name] = [fare]) 104 | 105 | !servicesList.includes(code) && servicesList.push(code) 106 | }) 107 | }) 108 | servicesList.forEach((serviceCode) => { 109 | const servicePayload = company.name !== 'INDISPONÍVEL' && { 110 | ...companies[company.name] 111 | .filter((fare) => fare.code === serviceCode) 112 | .map((fare) => { 113 | return { 114 | name: fare.name, 115 | minimum: fare.minimum, 116 | maximum: fare.maximum, 117 | } 118 | }), 119 | brand: brand.name, 120 | company: company.name, 121 | } 122 | services[serviceCode] 123 | ? services[serviceCode].push(servicePayload) 124 | : (services[serviceCode] = [servicePayload]) 125 | }) 126 | }) 127 | }) 128 | 129 | return services 130 | }, [state]) 131 | 132 | return ( 133 | 134 | 135 |

136 | Estas são todas as tarifas dos serviços prestados para contas de pessoa jurídica 137 | dos bancos:  138 | {banks.map((bank, index) => 139 | index === 0 ? `${bank.brandName}` : `, ${bank.brandName}` 140 | )} 141 | . 142 |

143 | {state.length > 0 && ( 144 | bank.brandName) 148 | .map( 149 | (requiredBrand) => state.filter((brand) => brand.name === requiredBrand)[0] 150 | ) 151 | .map(({ companies }) => 152 | companies.map(({ name }) => { 153 | return name 154 | }) 155 | ) 156 | .map((array) => Object.values(array))} 157 | typesState={typesState} 158 | fixFunction={fixMoney} 159 | /> 160 | )} 161 | 162 | {Object.keys(typesState).length === 0 && } 163 |

164 | Tabelas completas com as tarifas de contas para pessoas físicas. 165 |

166 | {state && 167 | state.map((brand, index) => 168 | brand.companies.map((company) => ( 169 | 170 |
171 | {brand.name}{' '} 172 | 178 | {brand.companies[0].name} 179 | {' '} 180 | CNPJ: {brand.companies[0].cnpjNumber} 181 |
182 | 183 | 184 | 185 | Taxas de juros 186 | Tipo de conta 187 | Mín 188 | Máx 189 | Informações 190 | 191 | 192 | 193 | {company.businessAccounts && 194 | company.businessAccounts.map(({ type, fees, termsConditions }) => 195 | fees.services.map( 196 | ( 197 | { name, chargingTriggerInfo, code, minimum, maximum }, 198 | index 199 | ) => ( 200 | 201 | {code.replace(/[_\s]/g, ' ')} 202 | {type.replace(/[_\s]/g, ' ')} 203 | {fixMoney(minimum.value)} 204 | {fixMoney(maximum.value)} 205 | 206 | 218 | 219 | 220 | ) 221 | ) 222 | )} 223 | 224 | 225 |
226 | )) 227 | )} 228 |
229 |
230 | ) 231 | } 232 | 233 | export default PersonalLoansPage 234 | -------------------------------------------------------------------------------- /static/js/3.f4a706e7.chunk.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["../node_modules/web-vitals/dist/web-vitals.es5.min.js"],"names":["v","t","n","e","concat","Date","now","Math","floor","random","i","arguments","length","name","value","delta","entries","id","isFinal","a","PerformanceObserver","supportedEntryTypes","includes","getEntries","map","observe","type","buffered","r","o","s","persisted","u","addEventListener","c","timeStamp","document","visibilityState","isUnloading","capture","once","l","disconnect","p","hadRecentInput","push","takeRecords","d","startTime","f","processingStart","window","perfMetrics","onFirstInputDelay","entryType","target","cancelable","m","Promise","passive","g","then","h","performance","getEntriesByType","timing","max","navigationStart","responseStart","readyState","setTimeout"],"mappings":"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","file":"static/js/3.f4a706e7.chunk.js","sourcesContent":["var t,n,e=function(){return\"\".concat(Date.now(),\"-\").concat(Math.floor(8999999999999*Math.random())+1e12)},i=function(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:-1;return{name:t,value:n,delta:0,entries:[],id:e(),isFinal:!1}},a=function(t,n){try{if(PerformanceObserver.supportedEntryTypes.includes(t)){var e=new PerformanceObserver((function(t){return t.getEntries().map(n)}));return e.observe({type:t,buffered:!0}),e}}catch(t){}},r=!1,o=!1,s=function(t){r=!t.persisted},u=function(){addEventListener(\"pagehide\",s),addEventListener(\"beforeunload\",(function(){}))},c=function(t){var n=arguments.length>1&&void 0!==arguments[1]&&arguments[1];o||(u(),o=!0),addEventListener(\"visibilitychange\",(function(n){var e=n.timeStamp;\"hidden\"===document.visibilityState&&t({timeStamp:e,isUnloading:r})}),{capture:!0,once:n})},l=function(t,n,e,i){var a;return function(){e&&n.isFinal&&e.disconnect(),n.value>=0&&(i||n.isFinal||\"hidden\"===document.visibilityState)&&(n.delta=n.value-(a||0),(n.delta||n.isFinal||void 0===a)&&(t(n),a=n.value))}},p=function(t){var n,e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],r=i(\"CLS\",0),o=function(t){t.hadRecentInput||(r.value+=t.value,r.entries.push(t),n())},s=a(\"layout-shift\",o);s&&(n=l(t,r,s,e),c((function(t){var e=t.isUnloading;s.takeRecords().map(o),e&&(r.isFinal=!0),n()})))},d=function(){return void 0===t&&(t=\"hidden\"===document.visibilityState?0:1/0,c((function(n){var e=n.timeStamp;return t=e}),!0)),{get timeStamp(){return t}}},v=function(t){var n,e=i(\"FCP\"),r=d(),o=a(\"paint\",(function(t){\"first-contentful-paint\"===t.name&&t.startTime1&&void 0!==arguments[1]&&arguments[1],r=i(\"LCP\"),o=d(),s=function(t){var e=t.startTime;e { 84 | const [state, setState] = useState([]) 85 | const { addMoreInfo } = useModal() 86 | 87 | const endpoint = '/personal-credit-cards' 88 | const banks = getBanksOfApi(endpoint) 89 | 90 | // Realiza as consultas às APIs 91 | useEffect(() => { 92 | ;(async () => { 93 | const apiResponses = await callApisOpenBanking('/personal-credit-cards') 94 | 95 | setState(apiResponses) 96 | })() 97 | }, []) 98 | 99 | // Organiza as informações para serem lidas pela matriz 100 | const typesState = useMemo(() => { 101 | let services = [] 102 | let servicesList = [] 103 | let companies = [] 104 | state.forEach((brand) => 105 | brand.companies.forEach((company) => { 106 | company.personalCreditCards.forEach((creditcard) => { 107 | creditcard.fees.services.forEach(({ code, minimum, maximum }) => { 108 | const fare = { 109 | code, 110 | name: creditcard.name, 111 | minimum: minimum.value, 112 | maximum: maximum.value, 113 | } 114 | 115 | companies[company.name] 116 | ? companies[company.name].push(fare) 117 | : (companies[company.name] = [fare]) 118 | 119 | !servicesList.includes(code) && servicesList.push(code) 120 | }) 121 | }) 122 | servicesList.forEach((serviceCode) => { 123 | const servicePayload = company.name !== 'INDISPONÍVEL' && { 124 | ...companies[company.name] 125 | .filter((fare) => fare.code === serviceCode) 126 | .map((fare) => { 127 | return { 128 | name: fare.name, 129 | minimum: fare.minimum, 130 | maximum: fare.maximum, 131 | } 132 | }), 133 | brand: brand.name, 134 | company: company.name, 135 | } 136 | services[serviceCode] 137 | ? services[serviceCode].push(servicePayload) 138 | : (services[serviceCode] = [servicePayload]) 139 | }) 140 | }) 141 | ) 142 | 143 | return services 144 | }, [state]) 145 | 146 | return ( 147 | 148 | 149 |

150 | Estas são todas as tarifas dos serviços de cartão de crédito para pessoa física 151 | dos bancos:  152 | {banks.map((bank, index) => 153 | index === 0 ? `${bank.brandName}` : `, ${bank.brandName}` 154 | )} 155 | . 156 |

157 | {state.length > 0 && ( 158 | bank.brandName) 162 | .map( 163 | (requiredBrand) => state.filter((brand) => brand.name === requiredBrand)[0] 164 | ) 165 | .map(({ companies }) => 166 | companies.map(({ name }) => { 167 | return name 168 | }) 169 | ) 170 | .map((array) => Object.values(array))} 171 | typesState={typesState} 172 | fixFunction={fixMoney} 173 | /> 174 | )} 175 | {Object.keys(typesState).length === 0 && } 176 |

177 | Tabelas completas com as taxas de cartão de crédito para pessoa física. 178 |

179 | {state && 180 | state.map((brand, index) => 181 | brand.companies.map((company) => ( 182 | 183 |
184 | {brand.name}{' '} 185 | 191 | {brand.companies[0].name} 192 | {' '} 193 | CNPJ: {brand.companies[0].cnpjNumber} 194 |
195 | 196 | 197 | 198 | Serviço 199 | Cartão 200 | Emissor 201 | Mín 202 | Máx 203 | Informações 204 | 205 | 206 | 207 | {company.personalCreditCards && 208 | company.personalCreditCards.map( 209 | ({ identification, fees, termsConditions }) => 210 | fees.services.map( 211 | ( 212 | { name, code, chargingTriggerInfo, minimum, maximum }, 213 | index 214 | ) => ( 215 | 216 | {code.replace(/[_\s]/g, ' ')} 217 | 218 | {identification.product.type.replace(/[_\s]/g, ' ')} 219 | 220 | 221 | {identification.creditCard.network.replace(/[_\s]/g, ' ')} 222 | 223 | {fixMoney(minimum.value)} 224 | {fixMoney(maximum.value)} 225 | 226 | 238 | 239 | 240 | ) 241 | ) 242 | )} 243 | 244 | 245 |
246 | )) 247 | )} 248 |
249 |
250 | ) 251 | } 252 | 253 | export default PersonalCreditCardsPage 254 | -------------------------------------------------------------------------------- /static/media/credit-card.11093fcb.svg: -------------------------------------------------------------------------------- 1 | credit card 2CREDIT CARDCREDIT CARD -------------------------------------------------------------------------------- /src/assets/img/illustrations/credit-card.svg: -------------------------------------------------------------------------------- 1 | credit card 2CREDIT CARDCREDIT CARD -------------------------------------------------------------------------------- /src/pages/BusinessCreditCards/index.tsx: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | 3 | import React, { useState, useEffect, useMemo } from 'react' 4 | 5 | import { callApisOpenBanking } from '../../services/callApisOpenBanking' 6 | import { getBanksOfApi } from '../../utils/getBanksOfApi' 7 | import { fixMoney } from '../../utils/fixMoney' 8 | import { useModal } from '../../hooks/Modal' 9 | 10 | import ComparisonMatrix from '../../components/ComparisonMatrix' 11 | import Layout from '../../components/Layout/Layout' 12 | import { 13 | MatrixPageStyled, 14 | CompanyStyled, 15 | TableStyled, 16 | } from '../../styles/CallApiPage.styled' 17 | 18 | interface IResponseBusinessCreditCard { 19 | name: string 20 | companies: ICompanies[] 21 | } 22 | 23 | interface ICompanies { 24 | name: string 25 | cnpjNumber: string 26 | urlComplementaryList: string 27 | businessCreditCards: IBusinessCreditCards[] 28 | } 29 | 30 | interface IBusinessCreditCards { 31 | name: string 32 | identification: { 33 | product: { 34 | type: string 35 | additionalInfo: string 36 | } 37 | creditCard: { 38 | network: string 39 | additionalInfo: string 40 | } 41 | } 42 | rewardsProgram: { 43 | hasRewardProgram: boolean 44 | rewardProgramInfo: string 45 | } 46 | fees: { 47 | services: IService[] 48 | } 49 | interest: IInterest[] 50 | termsConditions: { 51 | minimumFeeRate: string 52 | additionalInfo: string | null 53 | elegibilityCriteriaInfo: string 54 | closingProcessInfo: string 55 | } 56 | } 57 | 58 | interface IService { 59 | name: string 60 | code: string 61 | chargingTriggerInfo: string 62 | prices: IPrice[] 63 | minimum: { 64 | value: string 65 | currency: string 66 | } 67 | maximum: { 68 | value: string 69 | currency: string 70 | } 71 | } 72 | 73 | interface IPrice { 74 | interval: string 75 | value: string 76 | currency: string 77 | customers: { 78 | rate: number 79 | } 80 | } 81 | 82 | interface IInterest { 83 | rates: IRates[] 84 | instalmentRates: IInstalmentRates[] 85 | otherCredits: IOtherCredits[] 86 | } 87 | 88 | const BusinessCreditCardsPage = () => { 89 | const [state, setState] = useState([]) 90 | const { addMoreInfo } = useModal() 91 | 92 | const endpoint = '/business-credit-cards' 93 | const banks = getBanksOfApi(endpoint) 94 | 95 | // Realiza as consultas às APIs 96 | useEffect(() => { 97 | ;(async () => { 98 | const apiResponses = await callApisOpenBanking('/business-credit-cards') 99 | 100 | setState(apiResponses) 101 | })() 102 | }, []) 103 | 104 | // Organiza as informações para serem lidas pela matriz 105 | const typesState = useMemo(() => { 106 | let services = [] 107 | let servicesList = [] 108 | let companies = [] 109 | state.forEach((brand) => 110 | brand.companies.forEach((company) => { 111 | company.businessCreditCards.forEach((creditCard) => { 112 | creditCard.fees.services.forEach(({ code, minimum, maximum }) => { 113 | const fare = { 114 | code, 115 | name: creditCard.name, 116 | minimum: minimum.value, 117 | maximum: maximum.value, 118 | } 119 | if (fare.minimum !== 'NA' || fare.maximum !== 'NA') { 120 | companies[company.name] 121 | ? companies[company.name].push(fare) 122 | : (companies[company.name] = [fare]) 123 | !servicesList.includes(code) && servicesList.push(code) 124 | } 125 | }) 126 | }) 127 | servicesList.forEach((serviceCode) => { 128 | const servicePayload = company.name !== 'INDISPONÍVEL' && { 129 | ...companies[company.name] 130 | .filter((fare) => fare.code === serviceCode) 131 | .map((fare) => { 132 | return { 133 | name: fare.name, 134 | minimum: fare.minimum, 135 | maximum: fare.maximum, 136 | } 137 | }), 138 | brand: brand.name, 139 | company: company.name, 140 | } 141 | services[serviceCode] 142 | ? services[serviceCode].push(servicePayload) 143 | : (services[serviceCode] = [servicePayload]) 144 | }) 145 | }) 146 | ) 147 | 148 | return services 149 | }, [state]) 150 | 151 | return ( 152 | <> 153 | 154 | 155 |

156 | Estas são todas as tarifas dos serviços de cartões de crédito para pessoa 157 | jurídica dos bancos:  158 | {banks.map((bank, index) => 159 | index === 0 ? `${bank.brandName}` : `, ${bank.brandName}` 160 | )} 161 | . 162 |

163 | {state.length > 0 && ( 164 | bank.brandName) 168 | .map( 169 | (requiredBrand) => 170 | state.filter((brand) => brand.name === requiredBrand)[0] 171 | ) 172 | .map(({ companies }) => 173 | companies.map(({ name }) => { 174 | return name 175 | }) 176 | ) 177 | .map((array) => Object.values(array))} 178 | typesState={typesState} 179 | fixFunction={fixMoney} 180 | /> 181 | )} 182 |

183 | Tabelas completas com as taxas de cartão de crédito para pessoa Jurídica. 184 |

185 | {state && 186 | state.map((brand, index) => 187 | brand.companies.map((company) => ( 188 | 189 |
190 | {brand.name}{' '} 191 | 197 | {brand.companies[0].name} 198 | 199 | CNPJ: {brand.companies[0].cnpjNumber} 200 |
201 | 202 | 203 | 204 | Serviço 205 | Cartão 206 | Emissor 207 | Mín 208 | Máx 209 | Informações 210 | 211 | 212 | 213 | {company.businessCreditCards && 214 | company.businessCreditCards.map( 215 | ({ identification, fees, termsConditions }) => 216 | fees.services.map( 217 | ( 218 | { code, name, chargingTriggerInfo, maximum, minimum }, 219 | index 220 | ) => ( 221 | 222 | {code.replace(/[_\s]/g, ' ')} 223 | 224 | {identification.product.type.replace(/[_\s]/g, ' ')} 225 | 226 | 227 | {identification.creditCard.network.replace( 228 | /[_\s]/g, 229 | ' ' 230 | )} 231 | 232 | {fixMoney(minimum.value)} 233 | {fixMoney(maximum.value)} 234 | 235 | 247 | 248 | 249 | ) 250 | ) 251 | )} 252 | 253 | 254 |
255 | )) 256 | )} 257 |
258 |
259 | 260 | ) 261 | } 262 | 263 | export default BusinessCreditCardsPage 264 | -------------------------------------------------------------------------------- /static/media/loan.c6bc1e1a.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/assets/img/illustrations/loan.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /static/js/runtime-main.07745ca7.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["../webpack/bootstrap"],"names":["webpackJsonpCallback","data","moduleId","chunkId","chunkIds","moreModules","executeModules","i","resolves","length","Object","prototype","hasOwnProperty","call","installedChunks","push","modules","parentJsonpFunction","shift","deferredModules","apply","checkDeferredModules","result","deferredModule","fulfilled","j","depId","splice","__webpack_require__","s","installedModules","1","exports","module","l","e","promises","installedChunkData","promise","Promise","resolve","reject","onScriptComplete","script","document","createElement","charset","timeout","nc","setAttribute","src","p","jsonpScriptSrc","error","Error","event","onerror","onload","clearTimeout","chunk","errorType","type","realSrc","target","message","name","request","undefined","setTimeout","head","appendChild","all","m","c","d","getter","o","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","oe","err","console","jsonpArray","this","oldJsonpFunction","slice"],"mappings":"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","file":"static/js/runtime-main.07745ca7.js","sourcesContent":[" \t// install a JSONP callback for chunk loading\n \tfunction webpackJsonpCallback(data) {\n \t\tvar chunkIds = data[0];\n \t\tvar moreModules = data[1];\n \t\tvar executeModules = data[2];\n\n \t\t// add \"moreModules\" to the modules object,\n \t\t// then flag all \"chunkIds\" as loaded and fire callback\n \t\tvar moduleId, chunkId, i = 0, resolves = [];\n \t\tfor(;i < chunkIds.length; i++) {\n \t\t\tchunkId = chunkIds[i];\n \t\t\tif(Object.prototype.hasOwnProperty.call(installedChunks, chunkId) && installedChunks[chunkId]) {\n \t\t\t\tresolves.push(installedChunks[chunkId][0]);\n \t\t\t}\n \t\t\tinstalledChunks[chunkId] = 0;\n \t\t}\n \t\tfor(moduleId in moreModules) {\n \t\t\tif(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {\n \t\t\t\tmodules[moduleId] = moreModules[moduleId];\n \t\t\t}\n \t\t}\n \t\tif(parentJsonpFunction) parentJsonpFunction(data);\n\n \t\twhile(resolves.length) {\n \t\t\tresolves.shift()();\n \t\t}\n\n \t\t// add entry modules from loaded chunk to deferred list\n \t\tdeferredModules.push.apply(deferredModules, executeModules || []);\n\n \t\t// run deferred modules when all chunks ready\n \t\treturn checkDeferredModules();\n \t};\n \tfunction checkDeferredModules() {\n \t\tvar result;\n \t\tfor(var i = 0; i < deferredModules.length; i++) {\n \t\t\tvar deferredModule = deferredModules[i];\n \t\t\tvar fulfilled = true;\n \t\t\tfor(var j = 1; j < deferredModule.length; j++) {\n \t\t\t\tvar depId = deferredModule[j];\n \t\t\t\tif(installedChunks[depId] !== 0) fulfilled = false;\n \t\t\t}\n \t\t\tif(fulfilled) {\n \t\t\t\tdeferredModules.splice(i--, 1);\n \t\t\t\tresult = __webpack_require__(__webpack_require__.s = deferredModule[0]);\n \t\t\t}\n \t\t}\n\n \t\treturn result;\n \t}\n\n \t// The module cache\n \tvar installedModules = {};\n\n \t// object to store loaded and loading chunks\n \t// undefined = chunk not loaded, null = chunk preloaded/prefetched\n \t// Promise = chunk loading, 0 = chunk loaded\n \tvar installedChunks = {\n \t\t1: 0\n \t};\n\n \tvar deferredModules = [];\n\n \t// script path function\n \tfunction jsonpScriptSrc(chunkId) {\n \t\treturn __webpack_require__.p + \"static/js/\" + ({}[chunkId]||chunkId) + \".\" + {\"3\":\"f4a706e7\"}[chunkId] + \".chunk.js\"\n \t}\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n \t// This file contains only the entry chunk.\n \t// The chunk loading function for additional chunks\n \t__webpack_require__.e = function requireEnsure(chunkId) {\n \t\tvar promises = [];\n\n\n \t\t// JSONP chunk loading for javascript\n\n \t\tvar installedChunkData = installedChunks[chunkId];\n \t\tif(installedChunkData !== 0) { // 0 means \"already installed\".\n\n \t\t\t// a Promise means \"currently loading\".\n \t\t\tif(installedChunkData) {\n \t\t\t\tpromises.push(installedChunkData[2]);\n \t\t\t} else {\n \t\t\t\t// setup Promise in chunk cache\n \t\t\t\tvar promise = new Promise(function(resolve, reject) {\n \t\t\t\t\tinstalledChunkData = installedChunks[chunkId] = [resolve, reject];\n \t\t\t\t});\n \t\t\t\tpromises.push(installedChunkData[2] = promise);\n\n \t\t\t\t// start chunk loading\n \t\t\t\tvar script = document.createElement('script');\n \t\t\t\tvar onScriptComplete;\n\n \t\t\t\tscript.charset = 'utf-8';\n \t\t\t\tscript.timeout = 120;\n \t\t\t\tif (__webpack_require__.nc) {\n \t\t\t\t\tscript.setAttribute(\"nonce\", __webpack_require__.nc);\n \t\t\t\t}\n \t\t\t\tscript.src = jsonpScriptSrc(chunkId);\n\n \t\t\t\t// create error before stack unwound to get useful stacktrace later\n \t\t\t\tvar error = new Error();\n \t\t\t\tonScriptComplete = function (event) {\n \t\t\t\t\t// avoid mem leaks in IE.\n \t\t\t\t\tscript.onerror = script.onload = null;\n \t\t\t\t\tclearTimeout(timeout);\n \t\t\t\t\tvar chunk = installedChunks[chunkId];\n \t\t\t\t\tif(chunk !== 0) {\n \t\t\t\t\t\tif(chunk) {\n \t\t\t\t\t\t\tvar errorType = event && (event.type === 'load' ? 'missing' : event.type);\n \t\t\t\t\t\t\tvar realSrc = event && event.target && event.target.src;\n \t\t\t\t\t\t\terror.message = 'Loading chunk ' + chunkId + ' failed.\\n(' + errorType + ': ' + realSrc + ')';\n \t\t\t\t\t\t\terror.name = 'ChunkLoadError';\n \t\t\t\t\t\t\terror.type = errorType;\n \t\t\t\t\t\t\terror.request = realSrc;\n \t\t\t\t\t\t\tchunk[1](error);\n \t\t\t\t\t\t}\n \t\t\t\t\t\tinstalledChunks[chunkId] = undefined;\n \t\t\t\t\t}\n \t\t\t\t};\n \t\t\t\tvar timeout = setTimeout(function(){\n \t\t\t\t\tonScriptComplete({ type: 'timeout', target: script });\n \t\t\t\t}, 120000);\n \t\t\t\tscript.onerror = script.onload = onScriptComplete;\n \t\t\t\tdocument.head.appendChild(script);\n \t\t\t}\n \t\t}\n \t\treturn Promise.all(promises);\n \t};\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"/open-banking-brasil/\";\n\n \t// on error function for async loading\n \t__webpack_require__.oe = function(err) { console.error(err); throw err; };\n\n \tvar jsonpArray = this[\"webpackJsonpopen-banking-brasil\"] = this[\"webpackJsonpopen-banking-brasil\"] || [];\n \tvar oldJsonpFunction = jsonpArray.push.bind(jsonpArray);\n \tjsonpArray.push = webpackJsonpCallback;\n \tjsonpArray = jsonpArray.slice();\n \tfor(var i = 0; i < jsonpArray.length; i++) webpackJsonpCallback(jsonpArray[i]);\n \tvar parentJsonpFunction = oldJsonpFunction;\n\n\n \t// run deferred modules from other chunks\n \tcheckDeferredModules();\n"],"sourceRoot":""} --------------------------------------------------------------------------------