diff --git a/README.md b/README.md index 95586ca..01acaa3 100755 --- a/README.md +++ b/README.md @@ -1,8 +1,10 @@ # Gerador -* Gerador de CPF, CNPJ e RG válidos para testes de desenovimento. +- Gerador de CPF, CNPJ e RG válidos para testes de desenvolvimento. -* JSON Pretty para facilitar a leitura de JSONs. +- JSON Pretty para facilitar a leitura de JSONs. + +- Gerador de Cartão de Créditos válidos para testes de desenvolvimento. ### _Acesse: [gerador.dev.br](https://gerador.dev.br)_ @@ -10,27 +12,32 @@ Como todo bom densenvolvedor brasileiro, quem nunca precisou gerar um CPF, CNPJ ou RG válidos para aquele teste faceiro. -Pois bem, temos muitos geradores famosos por aí, porém recentemente eu e meus colegas, passamos por experiências ruins e demoradas. Então, porque não como um bom desenvolvedor, criar o seu próprio hehe. +Pois bem, temos muitos geradores famosos por aí, porém recentemente eu e meus colegas, passamos por experiências ruins e demoradas. Então, porque não como um bom desenvolvedor, criar o seu próprio hehe. Algo que fosse leve, prático e rápido. Sem milhões de publicidade pulando na sua frente e fazendo você esperar para que daí sim possa gerar o documento necessário. Pois bem, assim nasceu o querido Gerador. -![Gerador CPF,CNPJ e RG](https://user-images.githubusercontent.com/5226773/182047125-bf829b64-f478-4ef7-903d-f990da27bf8f.png) +![Gerador - CPF, CNPJ e RG](https://user-images.githubusercontent.com/5226773/194178532-350fba85-7d38-4d51-9da4-9dd2f8f76fa2.png) + +![Gerador - JSON Pretty](https://user-images.githubusercontent.com/5226773/194178376-3387aedb-6cc8-416b-a6ba-ccc5a0f295b5.png) -![Gerador - JSON Pretty](https://user-images.githubusercontent.com/5226773/182047153-f1ca5cc3-720a-4f07-88b3-c7e53bd54c6b.png) +![Gerador - Cartão de Crédito](https://user-images.githubusercontent.com/5226773/194178445-ff157c43-d5e7-4688-bec5-5ab64289fb6a.png) ## Features + - [x] Gerador de CPF válido - [x] Gerador de CNPJ válido - [x] Gerador de RG válido - [x] JSON Pretty +- [x] Gerador de Cartão de Crédito válido ## Colabore Colabore criando Issues de sugestões, bugs e o que mais precisar. ;) ## Importante + O gerador tem como intenção ajudar estudantes, programadores, analistas e testadores a gerar documentos válidos, normalmente necessários para testar seus softwares em desenvolvimento. A má utilização dos dados gerados é de total responsabilidade do usuário. Os números são gerados de forma aleatória, respeitando as regras de criação de cada diff --git a/public/brands/mastercard.svg b/public/brands/mastercard.svg new file mode 100644 index 0000000..545ac33 --- /dev/null +++ b/public/brands/mastercard.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/brands/visa.svg b/public/brands/visa.svg new file mode 100644 index 0000000..c729f35 --- /dev/null +++ b/public/brands/visa.svg @@ -0,0 +1,76 @@ + + + +image/svg+xml + + + + + + + + + + \ No newline at end of file diff --git a/src/components/credit-card.tsx b/src/components/credit-card.tsx new file mode 100644 index 0000000..e895479 --- /dev/null +++ b/src/components/credit-card.tsx @@ -0,0 +1,35 @@ +import { Box, Image, useColorModeValue } from '@chakra-ui/react' + +interface CreditCardComponentProps { + children: React.ReactNode + brand: string +} + +const CreditCardComponent = ({ children, brand }: CreditCardComponentProps) => { + const bgCard = useColorModeValue('gray.50', 'gray.700') + + return ( + + {children} + + + Mastercard + + + ) +} + +export default CreditCardComponent diff --git a/src/components/footer.tsx b/src/components/footer.tsx index c1c94c8..f043686 100644 --- a/src/components/footer.tsx +++ b/src/components/footer.tsx @@ -4,7 +4,7 @@ const Footer = () => { return ( - © {new Date().getFullYear()} Marcelo Pecin. All Rights Reserved. + © {new Date().getFullYear()} Marcelo Pecin ) diff --git a/src/components/menu-mobile.tsx b/src/components/menu-mobile.tsx index c5947e1..5bbbee8 100644 --- a/src/components/menu-mobile.tsx +++ b/src/components/menu-mobile.tsx @@ -44,6 +44,17 @@ const MobileMenu = () => { Documentos + + + Cartão de Crédito + + { Documentos + Cartão de Crédito JSON Pretty diff --git a/src/enums.ts b/src/enums.ts index e1ce086..03b78d1 100644 --- a/src/enums.ts +++ b/src/enums.ts @@ -3,3 +3,8 @@ export enum DocumentType { CNPJ = 'CNPJ', RG = 'RG', } + +export enum CreditCardBrand { + MASTERCARD = 'mastercard', + VISA = 'visa', +} diff --git a/src/interfaces.ts b/src/interfaces.ts new file mode 100644 index 0000000..0eee25c --- /dev/null +++ b/src/interfaces.ts @@ -0,0 +1,6 @@ +export interface ICreditCard { + number: string + expirity: string + cvv: string + brand: string +} diff --git a/src/pages/credit-card.tsx b/src/pages/credit-card.tsx new file mode 100644 index 0000000..eadc468 --- /dev/null +++ b/src/pages/credit-card.tsx @@ -0,0 +1,81 @@ +import React from 'react' +import { Button, Heading, HStack, VStack } from '@chakra-ui/react' +import Head from 'next/head' + +import { onGenerateCreditCard } from '@/utils' +import { CreditCardBrand } from '@/enums' +import { ICreditCard } from '@/interfaces' + +import CopyButton from '@/components/copy-button' +import CreditCardComponent from '@/components/credit-card' + +const CreditCard = () => { + const [creditCard, setCreditCard] = React.useState({ + number: '**** **** **** ****', + expirity: '**/****', + cvv: '***', + brand: CreditCardBrand.MASTERCARD, + }) + + React.useEffect(() => { + onGenerate(CreditCardBrand.MASTERCARD) + }, []) + + const onGenerate = (brand: CreditCardBrand) => { + const card = onGenerateCreditCard(brand) + + setCreditCard(card) + } + + return ( + <> + + Gerador | Cartão de Crédito + + + + + + + + + + + + + + {creditCard.number} + + + + + + + {creditCard.expirity} + + + + + + + {creditCard.cvv} + + + + + + + + ) +} + +export default CreditCard diff --git a/src/utils.ts b/src/utils.ts index d64f5c5..2985062 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,4 +1,5 @@ -import { DocumentType } from './enums' +import { CreditCardBrand, DocumentType } from './enums' +import { ICreditCard } from './interfaces' const initialArray = (total: number, number: number) => { return Array.from(Array(total), () => numberRandom(number)) @@ -134,3 +135,113 @@ export const onSetMask = (value: string, type: DocumentType): string => { return value } } + +/** + * CREDIT CARD FUNCTIONS + **/ +export const onGenerateCreditCard = (brand: CreditCardBrand): ICreditCard => { + let number = generateCardNumber(brand) + + while (!luhnCheck(number)) { + number = generateCardNumber(brand) + } + + return { + number, + expirity: getRamdomDateInBetween(), + cvv: String(Math.floor(Math.random() * (999 - 100)) + 100), + brand, + } +} + +const generateCardNumber = (brand: CreditCardBrand) => { + let bin: string + + switch (brand) { + case CreditCardBrand.MASTERCARD: + bin = ['51', '55'].sort(() => 0.5 - Math.random())[0] + break + + case CreditCardBrand.VISA: + bin = '4' + break + + default: + bin = '55' + } + + let cardNumber = bin, + randomNumberLength = 16 - (bin.length + 1) + + for (let i = 0; i < randomNumberLength; i++) { + let digit = Math.floor(Math.random() * 9 + 0) + cardNumber += digit + } + + let checkDigit = getCheckDigit(cardNumber) + + cardNumber += String(checkDigit) + + return cardNumber +} + +const getCheckDigit = (number: string) => { + let sum = 0, + module, + checkDigit + + for (let i = 0; i < number.length; i++) { + let digit = parseInt(number.substring(i, i + 1)) + + if (i % 2 == 0) { + digit = digit * 2 + if (digit > 9) { + digit = digit / 10 + (digit % 10) + } + } + + sum += digit + } + + module = parseInt(String(sum)) % 10 + checkDigit = module === 0 ? 0 : 10 - module + + return checkDigit +} + +const luhnCheck = (num: string): boolean => { + let arr = (num + '') + .split('') + .reverse() + .map((x) => parseInt(x)) + + let lastDigit = arr.splice(0, 1)[0] + + let sum = arr.reduce( + (acc, val, i) => (i % 2 !== 0 ? acc + val : acc + ((val * 2) % 9) || 9), + 0 + ) + + sum += lastDigit + + return sum % 10 === 0 +} + +const getRamdomDateInBetween = (): string => { + const start = new Date() + const end = new Date( + start.getFullYear() + 5, + start.getMonth(), + start.getDate() + ) + + const randomDate = new Date( + Math.floor( + Math.random() * (end.getTime() - start.getTime() + 1) + start.getTime() + ) + ) + + return `${('0' + (randomDate.getMonth() + 1)).slice( + -2 + )}/${randomDate.getFullYear()}` +}