{"id":23810404,"url":"https://github.com/zingarelli/casa-verde","last_synced_at":"2026-05-07T09:31:15.703Z","repository":{"id":161124518,"uuid":"635888189","full_name":"zingarelli/casa-verde","owner":"zingarelli","description":"Landing page to practice React, TypeScript, hooks, API requests and styled-components. Part of the \"7 Days of Code\" challenge.","archived":false,"fork":false,"pushed_at":"2023-05-04T19:34:30.000Z","size":1079,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-11-11T09:32:33.629Z","etag":null,"topics":["7daysofcode","react","styled-components","typescript"],"latest_commit_sha":null,"homepage":"https://casa-verde-gold.vercel.app","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zingarelli.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-05-03T17:08:08.000Z","updated_at":"2023-05-03T18:59:31.000Z","dependencies_parsed_at":null,"dependency_job_id":"b310f81c-cccb-41a2-ad24-aeb0e2e4f73b","html_url":"https://github.com/zingarelli/casa-verde","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/zingarelli/casa-verde","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zingarelli%2Fcasa-verde","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zingarelli%2Fcasa-verde/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zingarelli%2Fcasa-verde/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zingarelli%2Fcasa-verde/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zingarelli","download_url":"https://codeload.github.com/zingarelli/casa-verde/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zingarelli%2Fcasa-verde/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32731192,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-07T02:14:30.463Z","status":"ssl_error","status_checked_at":"2026-05-07T02:14:29.405Z","response_time":62,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["7daysofcode","react","styled-components","typescript"],"created_at":"2025-01-02T00:14:23.619Z","updated_at":"2026-05-07T09:31:15.681Z","avatar_url":"https://github.com/zingarelli.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Casa Verde 🪴\n\nEste projeto é o resultado da minha participação no [7 Days of Code](https://7daysofcode.io) da Alura, [edição React](https://7daysofcode.io/matricula/react). O \"7 Days of Code\" é uma oportunidade de praticar alguma tecnologia, por meio de desafios diários e incrementais que são enviados por e-mail. \n\nNesse desafio de React, o objetivo foi desenvolver a [página inicial](https://casa-verde-gold.vercel.app/) do e-commerce da empresa fictícia **\"Casa Verde\"**, que vende plantas decorativas. O objetivo foi explorar diferentes tecnologias e bibliotecas com o React, criando componentes, utilizando styled-components para estilização, gerenciando estados com hooks e atuando nas interações do usuário com filtros e ordenadores. Os detalhes sobre cada dia podem ser vistos na [seção Desenvolvimento](#desenvolvimento)\n\n## Instalação e execução\n\nO site foi hospedado na Vercel e pode ser visto online neste link: https://casa-verde-gold.vercel.app/. Infelizmente, ele **não** está responsivo, então é melhor visualizado em telas com uma largura de pelo menos 1024px.\n\nSe desejar rodá-lo localmente e modificá-lo, siga as instruções abaixo: \n\nApós clonar/baixar o projeto, abra um terminal, navegue até a pasta do projeto e rode o seguinte comando para instalar todas as dependências necessárias\n\n    npm install\n\nApós isso, você pode rodar a aplicação em modo de desenvolvimento com o seguinte comando:\n\n    npm start\n\nA aplicação irá rodar no endereço http://localhost:3000.\n\n## Desenvolvimento\n\nO projeto foi desenvolvido em **React** com **TypeScript**, e foi criado com o Create React App, utilizando Node.js (versão v16.15.1) e npm (versão 8.11.0). \n\n## Dia 01\n\nNo primeiro dia, a tarefa foi estudar o [Figma do projeto](https://www.figma.com/file/0yOQR6fGtbdrmqeStiO0jf/7Days-React?type=design\u0026node-id=0-1\u0026t=bZkMTooGMFICXZf6-0) e **criar os componentes** necessários para as **seções de \"Menu\" e \"Newsletter\"**. A seção de \"Newsletter\" inclui um formulário simples para se digitar o e-mail e clicar em um botão de assinatura da newsletter.\n\nCriei dois componentens principais: `\u003cMenu /\u003e` e `\u003cAssinaturaNewsletter /\u003e` e mais alguns componentes que fiz, tendo em vista seu reúso em outras seções do site: \n\n- `\u003cLink /\u003e`: esse componente renderiza um link e um separador (opcional) e foi criado para se chegar ao mesmo efeito do menu de links do Figma;\n\n- `\u003cHeading /\u003e`: muitas seções do site são formadas por um título principal e um sub-título posicionado acima dele, cada com um fonte e estilos diferentes, como pode ser visto na imagem abaixo. Criei esse componente `\u003cHeading /\u003e` para poder aplicá-lo nessas diferentes seções. O título e o subtítulo são enviados via props, além de uma prop `size` (opcional), utilizada para aumentar ou diminuir o tamanho do título principal;\n\n    ![imagem exemplificando um título em negrito e fonte grande e um sub-título em cinza e fonte pequena, posicionado acima do título principal](https://user-images.githubusercontent.com/19349339/236294315-8048f0c5-2d9c-427d-993b-beea88402df4.png)\n\n# Dia 02\n\nO desafio foi **utilizar a biblioteca [styled-components](https://styled-components.com)** para aplicar uma solução \"CSS-in-JS\" na estilização do projeto.\n\nA instalação da biblioteca pode ser feita por meio do comando:\n\n    npm install styled-components\n\nÉ necessário também instalar o pacote para a tipagem de styled-components:\n\n    npm install --save-dev @types/styled-components\n\nApliquei o styled-components aos componentes por meio da criação de um arquivo `styled.tsx` na pasta de cada componente. Decidi por essa abordagem para deixar mais separada a estrutura do componente em si de sua estilização. Seguirei dessa forma na criação dos próximos componentes. \n\n# Dia 03 \n\nEste dia foi dedicado a utilizar o hook `useState` para **melhorar a experiência do usuário** com o formulário de assinatura da Newsletter. Foi proposto que o botão de assinatura fique desabilitado caso o campo de e-mail esteja em branco ou não tenha um e-mail válido.\n\nPara isso, criei dois estados: `active`, para lidar com a validação do campo, e `email`, para armazenar o valor do e-mail. A validação é feita pelo próprio HTML, que disponibiliza um objeto `ValidityState` com uma propriedade `valid` informando se o input está ou não válido. Essa propriedade é utilizada pelo estado `active` para habilitar/desabilitar o botão. \n\nAqui foi possível ver a **vantagem do uso de styled-components**, em que pude passar o estado `active` como uma prop ao botão e assim alterar seu estilo dinamicamente. \n\nO gif abaixo mostra como fica a interação com o campo e input e o botão:\n\n![gif mostrando o botão desabilitado e com uma cor cinza enquanto o campo de input não é preenchido com um e-mail válido. Após preenchido, o botão fica habilitado e com a cor laranja](https://user-images.githubusercontent.com/19349339/236299918-0561d574-1262-4731-bf02-fb9b27248d79.gif)\n\n# Dia 04\n\nEste **não foi um bom dia**...\n\nO desafio proposto foi enviar de fato uma mensagem de boas-vindas ao e-mail da pessoa. Como sugestão, foi recomendada a **utilização da API do [SendGrid](https://docs.sendgrid.com/pt-br/for-developers/sending-email)**. Esta API requer uma key de autenticação para seu uso. Para tratar essa key como uma **variável de ambiente**, sem manter essa informação sigilosa no código, foi utilizado o **pacote [dotenv](https://www.npmjs.com/package/dotenv)**.\n\nO dotenv já vem instalado pelo Create React App. Para utilizar variáveis de ambiente, basta criar um arquivo `.env` e colocar suas variáveis neste arquivo. No entanto, para funcionar, as variáveis devem começar com `REACT_APP_`. Exemplo: \n\n    REACT_APP_SENDGRID_API_KEY='sua_chave_secreta_aqui'\n\nO motivo de este não ter sido um bom dia foi que não consegui utilizar o SendGrid. Recebi diversos erros de problema com o pacote e na configuracão ao utilizá-lo no React. \n\nO provável motivo dos erros foi por estar tentando utilizar a API em um projeto de front-end, sendo que a **recomendação** é que o envio de e-mails seja feito no **lado do servidor** (back-end). Os códigos de exemplo da [documentação](https://github.com/sendgrid/sendgrid-nodejs), inclusive, são feitos em Node.js, para serem usados em um projeto de back-end. \n\nPor conta disso, e por eu ainda não ter conhecimentos em back-end, **pulei a atividade do dia 4**. Mesmo assim, valeu a pena por obter conhecimento nestas duas tecnologias, especialmente no dotenv, que pode ser muito útil em futuros projetos.\n\n# Dia 05\n\nEvoluindo a aplicação, o desafio do dia 05 foi se **comunicar com uma API** para preencher a **seção de ofertas** do site. Esta seção deve mostrar diversos produtos do site como se fosse uma galeria, sendo que produtos com estoque zerado não devem ser exibidos.\n\nPar simular uma API, foi disponibilizado um [arquivo Gist](https://gist.githubusercontent.com/bugan/41d60ffa23fa0c4044cc138bf670780d/raw) com um JSON. Esse Gist, no entanto, estava ruim e incompleto: ele possuía somente 3 produtos e nenhuma informação sobre estoque. Por esse motivo, criei [outro GIST](https://gist.githubusercontent.com/zingarelli/8953e40f635f51675736a4fe45481b17/raw/d17f9d208ada3a4c6714540e9926bb7d534fabd6/casa-verde.json) com mais itens, dados de estoque e imagens.\n\nA comunicação com a API foi feita utilizando a Fetch API. Deixei o código separado em outro arquivo (`utils/api.ts`), para separar as responsabilidades de cada código. \n\nCriei os componentes `\u003cOfertas /\u003e` e `\u003cCard /\u003e`, para montar a seção de ofertas, bem como uma interface `interfaces/Product.ts` para tipar os dados retornados pela API (um array de objetos).\n\n# Dia 06\n\nContinuando na seção de ofertas, foram solicitadas algumas alterações: ela agora deveria mostrar todos os produtos da loja e oferecer **opções para filtrar produtos** a partir de uma faixa de preço, bem como poder **ordená-los por nome ou preço**. \n\nA ordenação é feita em um elemento de select e o filtro por meio de um formulário contendo um input (tipo `number`) e um botão, como pode ser visto na imagem abaixo:\n\n![screenshot do site exibindo o título \"Conheça nossas plantas\" e os campos para seleção de ordenação e filtro por valor](https://user-images.githubusercontent.com/19349339/236305325-e1e708ca-12b9-459f-9efb-405dd2d00ba8.png)\n\nOs dois campos, ordenação e filtro, são controlados por variáveis de estados, que eu utilizo como sendo as dependências de um hook `useEffect`. Dessa forma, quando um desses campos é alterado, eu aplico o filtro e a ordenação para que a galeria de produtos seja renderizada de acordo. \n\nPara evitar ter que fazer uma nova chamada à API quando o filtro é removido, repliquei a lista retornada pela API em uma segunda variável de estado. Assim, o tratamento de filtro e ordenação é feito em uma lista, que recebe os dados originais da outra lista quando o filtro é limpo. Não sinto que seja a solução ideal e acho que isso poderia ser melhorado...\n\n# Dia 07\n\nPara o último dia, o desafio foi **colocar a aplicação no ar** e compartilhá-la com o mundo. Fiz o deploy do projeto na Vercel, e o site está disponível online no link: https://casa-verde-gold.vercel.app/. Deixo mais abaixo uma screenshot com o resultado final.\n\nTambém dediquei o dia a preencher este Readme. \n\nAté o próximo desafio! 🚀\n\n![screenshot mostrando a página inicial finalizada para o site Casa Verde](https://user-images.githubusercontent.com/19349339/236310607-5f9790b6-9ffb-473d-94a0-8280a4140cbd.png)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzingarelli%2Fcasa-verde","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzingarelli%2Fcasa-verde","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzingarelli%2Fcasa-verde/lists"}