Essa é uma aplicação frontend que reimagina o conceito tradicional de "Memory Board" em um ambiente digital. Originalmente, um Memory Board é uma ferramenta física usada para organizar e exibir memórias visuais, como fotos, cartões postais e lembranças. Ele serve como um lembrete tangível de momentos especiais, experiências significativas ou mesmo personalidades importantes na vida de alguém.
Seu objetivo principal é fornecer aos usuários uma plataforma digital onde eles possam:
-
Capturar Memórias: Os usuários podem realizar o upload de suas memórias, ou seja, arquivos de imagens.
-
Organizá-las: A aplicação permite que os usuários organizem suas imagens de forma personalizada, semelhante à disposição física tradicional.
-
Persisti-las: Através do uso do LocalStorage, o Memory Board garante que as memórias permaneçam acessíveis e intocadas entre sessões de uso.
Este projeto é desenvolvido como parte de um esforço para aprimorar minhas habilidades de desenvolvimento frontend e serve como um exemplo prático das tecnologias e técnicas que domino. É também uma expressão do meu apreço pela nostalgia e pelo poder da memória e portanto da história em nossa vida cotidiana.
- Visão Geral
- Sumário
- Produção
- Tecnologias Utilizadas
- Principais Features
- Instalação e Execução em Ambiente de Desenvolvimento
- Arquitetura do Software
- Créditos e Direitos Autorais
Essa aplicação está disponível em ambiente de produção, pela Vercel, através do link abaixo:
memoryboardio.vercel.appA principal feature dessa aplicação é sem dúvidas a capacidade do usuário realizar o envio de suas memórias, ou seja, seus arquivos de imagem.
Ele pode fazê-lo de duas maneiras, arrastando as imagens para o menu de importação, ou simplesmente clicando no mesmo menu.
Isso tudo é possível graças ao framework React Dropzone, que facilita a implementação do <input />
responsável por realizar o upload dos arquivos.
Essa implementação em código fica assim:
Bloco de código jsx que desestrutura alguns dos objetos retornados pelo custom hook useDropzone, que serão utilizados no jsx e em outras funções.
Bloco de código jsx utilizando os objetos retornados pelo método getRootProps() e getInputProps() do custom hook useDropzone.
Após as imagens serem importadas, é necessário lidar com elas, para que possam ser acessadas por outros componentes.
Para tal, fora utilizado o framework Zustand, criando algumas Stores, dentre as quais, a polaroidStore
, que trata os dados de importação.
Zustand store responsável pelos arquivos importados.
Importação do custom hook no componente Dropzone.
Assim, utilizando uma Handler Function, os arquivos importados, salvos no array acceptedFiles
são salvos "globalmente", ao utilizar o método addPolarids
:
Isso faz com que o anterior array de Files
(acceptedFiles
), retornado pelo hook useDropzone
, seja mapeado como um novo array do tipo PolaroidObject
, apresentado no bloco de código da polaroidStore
agora com novas informações.
Dentre as informações salvas no tipo PolaroidObject
, encontrasse a chave file
. Inicialmente, esse valor guardava o proprio objeto File
, padrão do JavaScript para lidar com arquivos enviados. No entanto isso faria com que a aplicação começasse a perder performance considerávelmente. Primeiro porque o próprio tipo File, apesar de ser um objeto é um classe dificil de se lidar, por exemplo, não é possível enviá-la ao LocalStorage como json e recuperá-la, esse valor acaba se "corrompendo" no meio do processo. E também para que a mesma seja renderizada, teria de ser convertida em em uma Uri.
Além disso, o tamanho das imagens não estão sob o controle da aplicação, ou seja, em teoria o usuário pode enviar uma imagem de qualquer tamanho, e quanto maior a mesma fosse, mais performance a aplicação perderia.
Por isso, na função handleUploads
previamente exposta, cada File
dentro do arrayacceptedFiles
, não é somente salvo no novo objeto PolaroidObject
, como também é antes comprimido e convertido numa string base64
.
Depois que as imagens são importadas, e seus valores mapeados como componentes Polaroid
, podem ser facilmente movidas com o atributo drag
do framework Framer Motion. Mas não basta apenas movê-las pela tela, é necessário melhor organizá-las, e para isso, funcionalidades como: trazer para frente, enviar para trás e apagar, são imprescindíveis.
Assim fora desenvolvido um Context Menu personalizado. Ao clicar com o botão direito em uma imagem, ela é salva na PolaroidStore como targetedPolaroid
, e assim seus dados são usados para manipular o array polaroids
.
Com os dados das imagens, facilmente manipuláveis, agora como uma string base64
. É muito simples persistir esses dados em sessões de LocalStorage.
Para isso, foi desenvolvido um custom hook, chamado useLocalStorage
, que salva não somente as imagens na chave file
de cada PolaroidObject
, mas também todas suas outras chaves como também sua position
. Bastando um clique no botão de salvar.
Custom hook useLocalStorage.
Action responsável por persistir os dados.
UI do componente Notification, demonstrando que a persistência dos dados foi realizada com sucesso.
Para aqueles que queiram executar a aplicação localmente, é possível fazê-lo em simples passos:
- Clone o projeto em sua máquina:
git clone git@github.com:fnandesrafael/memoryboard.git
- Acesse o diretório raiz do projeto:
cd memoryboard
- Instale as dependências, utilizando seu gerenciador de pacotes Node.js, como
npm
,yarn
,pnpm
etc.
npm install
ou mesmo a versão encurtada,
npm i
- Execute o comando node para iniciar a aplicação no servidor LocalHost.
npm run dev
Após executá-lo, basta acessar o endereço
https://localhost:3000
em seu navegador.
É importante perceber que para que todos esses comandos sejam possíveis, a sua máquina deve possuir as dependências necessárias, nesse caso o Git, para a clonagem do repositório remoto em sua máquina local, além do Node.js e do Npm(ou outro gerenciador de pacotes node), para sua instalação e execução dos comandos.
src/
├── assets/
│ └── images/
│ ├── (arquivos de imagens aqui)
│
├── components/
│ ├── (componentes React aqui)
│
├── constants/
│ ├── animations/
│ │ ├── (arquivos de animações aqui)
│
├── hooks/
│ ├── (hooks personalizados aqui)
│
├── store/
│ ├── (gerenciamento de estado global aqui)
│
└── utils/
├── (funções utilitárias aqui)
Fora do diretório src
, encontram-se apenas arquivos de configuração, módulos, documentações etc.
Todos os códigos desse projeto foram por mim desenvolvidos, os quais possuo direito de propriedade intelectual. No entanto, alguns assets como: fontes, imagens, texturas e bibliotecas, foram utilizados de terceiros, e a estes pertencem. Sendo esse apenas um projeto de cunho educacional, sem fins lucrativos, apenas tendo o fim o aperfeiçoamento do meu currículo e das minhas habilidades práticas de desenvolvimento frontend.
© Rafael Fernandes de Lima - All rights reserved.