Files
my_closet/relatorio_pap.tex
2026-07-01 10:11:59 +01:00

579 lines
43 KiB
TeX

\documentclass[11pt,a4paper]{report}
\usepackage[utf8]{inputenc}
\usepackage[portuguese]{babel}
\usepackage{amsmath}
\usepackage{graphicx}
\usepackage[hidelinks]{hyperref}
\usepackage{enumitem}
\usepackage{geometry}
\geometry{margin=3cm}
\usepackage{titling}
\usepackage{setspace}
\usepackage{indentfirst}
\usepackage{fancyhdr}
\usepackage{etoolbox}
\usepackage{titlesec}
% Garante que a primeira página do capítulo usa o estilo fancy
\titleformat{\chapter}[display]
{\normalfont\Huge\bfseries}
{\thechapter}{20pt}{\huge}
[\thispagestyle{fancy}] % <-- aplica estilo fancy ao fim do título do capítulo
\newcommand{\projecttitle}{\textbf{MyCloset -- Guarda-Roupa Inteligente}}
% Cabeçalho e rodapé configurado com linhas
\pagestyle{fancy}
\fancyhf{} % limpa tudo
\rhead{\projecttitle} % canto superior direito
\cfoot{\thepage} % centro do rodapé
\cfoot{} % limpa o centro do rodapé (caso esteja definido)
\rfoot{\thepage} % coloca o número da página no canto inferior direito
\renewcommand{\headrulewidth}{0.4pt} % linha superior
\renewcommand{\footrulewidth}{0.4pt} % linha inferior
\usepackage[scaled]{helvet}
\renewcommand{\familydefault}{\sfdefault}
\doublespacing
\begin{document}
\pagenumbering{roman}
\renewcommand{\chaptername}{}
\makeatletter
\def\@makechapterhead#1{%
\thispagestyle{fancy} % <- força o estilo fancy aqui
\vspace*{50pt}%
{\parindent \z@ \raggedright \normalfont
\Huge\bfseries \thechapter\ #1\par\nobreak
\vskip 40pt
}}
\makeatother
\begin{titlepage}
% Logótipo no canto superior direito absoluto
\vspace*{-2cm}
\noindent
\hspace*{\fill}
\includegraphics[width=0.22\textwidth]{imagens/logo.png}
\vspace*{1cm}
\begin{center}
{\Huge \textbf{Prova de Aptidão Profissional}}\\[0.5cm]
\vspace*{1cm}
{\large Curso Profissional de Técnico/a de Informática de Gestão}\\
\vspace*{1cm}
{\large Ciclo de formação 2023 / 2026}\\[2.5cm]
{\LARGE \textbf{MyCloset -- Guarda-Roupa Inteligente Virtual}}\\[5.5cm]
{\large \textbf{«Seu Nome Completo»}}\\[0.5cm]
{\large n.º 230419}
\vfill
\noindent
\hfill
\vspace*{-6cm}
\begin{minipage}{0.5\textwidth}
\begin{flushright}
{\large Orientador: João Miranda}
\end{flushright}
\end{minipage}
\end{center}
% Rodapé com a barra de apoios
\vfill
\begin{center}
\includegraphics[width=\textwidth]{imagens/barra_apoios.png}
\end{center}
\vspace*{-2cm}
\end{titlepage}
\chapter*{Agradecimentos}
Neste capítulo, expresso o meu sincero agradecimento a todas as pessoas e instituições que contribuíram de forma direta ou indireta para a realização e sucesso do meu projeto de Prova de Aptidão Profissional (PAP) e do meu percurso formativo:
Agradeço ao meu orientador de projeto, o formador \textbf{João Miranda}, por todo o acompanhamento técnico, paciência, orientação e partilha de conhecimentos transmitidos ao longo do planeamento e desenvolvimento do \textbf{MyCloset}.
Agradeço à direção pedagógica e a todo o corpo docente da \textbf{Escola Profissional de Vila do Conde} pela oportunidade de aprendizagem e pelo ambiente de apoio fornecido durante este ciclo de formação.
Agradeço à minha família e amigos, cujo incentivo moral constante e apoio emocional foram pilares fundamentais nas fases mais exigentes do projeto, motivando-me a concluir esta etapa com sucesso.
Por fim, agradeço aos meus colegas de curso pela entreajuda constante e troca de ideias no laboratório informático, essenciais para a resolução de desafios técnicos ao longo destes três anos de formação.
\chapter*{Glossário}
\begin{description}[align=left,labelwidth=3cm]
\item[Vite:] Ferramenta de build rápida para projetos web modernos, responsável por compilar e otimizar o código React com alto desempenho em tempo de desenvolvimento.
\item[React:] Biblioteca JavaScript baseada em componentes reutilizáveis, desenvolvida pela Meta, utilizada para criar interfaces de utilizador dinâmicas, fluidas e reativas.
\item[Firebase:] Plataforma de backend em nuvem fornecida pela Google, que providencia autenticação, base de dados em tempo real, notificações push e outros serviços serverless.
\item[NoSQL:] Sistema de gestão de bases de dados não-relacional, ideal para aplicações com estruturas de dados flexíveis e dinâmicas que não utilizam tabelas relacionais clássicas.
\item[Cloud Firestore:] Base de dados documental NoSQL pertencente ao Firebase, que armazena dados sob o formato de documentos JSON e suporta sincronização automática em tempo real.
\item[Firebase Authentication:] Serviço de gestão e segurança de utilizadores, permitindo login e registo seguros através de e-mail e palavra-passe na plataforma.
\item[Tailwind CSS:] Framework CSS utilitário para design web moderno, que permite estruturar layouts altamente responsivos e personalizados através de classes utilitárias no próprio código.
\item[FCM (Firebase Cloud Messaging):] Serviço de transporte de mensagens em nuvem para o envio fiável de notificações push e lembretes aos dispositivos dos utilizadores.
\item[JSON (JavaScript Object Notation):] Formato de texto simples para intercâmbio de dados legível por humanos e máquinas, utilizado para exportar informações de utilizador no projeto.
\item[SPA (Single Page Application):] Aplicação web que carrega uma única página HTML e reescreve dinamicamente o seu conteúdo à medida que o utilizador interage, evitando recarregamentos completos da página.
\item[API (Application Programming Interface):] Relação de regras e métodos que possibilita a comunicação e partilha de dados entre softwares distintos (como a integração de dados meteorológicos).
\end{description}
\tableofcontents
\newpage
\chapter{Introdução}
\pagenumbering{arabic}
A Prova de Aptidão Profissional (PAP) representa o culminar do percurso escolar no Curso Profissional de Técnico de Informática de Gestão. O projeto desenvolvido, intitulado \textbf{MyCloset}, consiste numa aplicação web inovadora voltada para a gestão digital inteligente e partilhada de um guarda-roupa pessoal.
A motivação para o desenvolvimento do \textbf{MyCloset} advém das necessidades crescentes de organização diária da população moderna. A proliferação do consumo de moda rápida (fast fashion) leva à acumulação excessiva de peças de roupa nos guarda-roupas, muitas das quais acabam esquecidas. Este problema provoca não só desperdício financeiro (através da compra duplicada de peças semelhantes), mas também frustração diária no momento de escolher uma combinação visual adequada (a conhecida paralisia de decisão matinal). Além disso, a preocupação em vestir peças limpas e adequadas às variações meteorológicas é uma rotina constante que exige planeamento manual.
O \textbf{MyCloset} surge para solucionar estes problemas através de um sistema totalmente acessível em qualquer dispositivo (computador, tablet ou telemóvel), permitindo ao utilizador:
\begin{enumerate}
\item Registar digitalmente cada peça do seu armário, organizando-as por nome, categoria, cor e secções personalizadas;
\item Controlar quais as peças prontas a usar e quais as que se encontram no cesto da roupa suja (\textit{Lavandaria});
\item Criar e guardar conjuntos completos de roupa (\textit{Outfits}), partilhando-os com amigos através de links públicos únicos;
\item Planear a sua semana ou mês através de um calendário dinâmico (\textit{Planeamento});
\item Receber conselhos de vestuário integrados com dados e previsões climatéricas simuladas ou reais;
\item Pesquisar perfis de outros utilizadores na rede social da plataforma, facilitando a partilha de inspirações e permitindo clonar looks de terceiros.
\end{enumerate}
Para a implementação do \textbf{MyCloset}, recorreu-se a um conjunto de tecnologias modernas adequadas ao perfil do Técnico de Informática de Gestão. O front-end foi estruturado em \textbf{React} com build do \textbf{Vite}, estilizado com \textbf{Tailwind CSS} para uma experiência de utilizador rica, moderna, responsiva e otimizada com efeitos visuais premium. O back-end e armazenamento de dados utilizam a plataforma serverless \textbf{Firebase} da Google, recorrendo especificamente ao \textbf{Cloud Firestore} para base de dados NoSQL em tempo real, ao \textbf{Firebase Authentication} para controlo de acessos, e ao \textbf{Firebase Cloud Messaging} para a gestão de lembretes e notificações push.
\section{Planeamento do Projeto}
O planeamento temporal do projeto foi definido com base nos prazos estipulados para a PAP, dividindo-se nas seguintes fases sequenciais descritas na Tabela \ref{tab:cronograma}.
\begin{table}[h!]
\centering
\begin{tabular}{|l|p{7.5cm}|c|l|}
\hline
\textbf{Fase} & \textbf{Descrição das Tarefas} & \textbf{Duração} & \textbf{Estado} \\ \hline
Fase 1 & Levantamento de requisitos e desenho de mockups da interface. & 2 Semanas & Concluído \\ \hline
Fase 2 & Configuração do ambiente (Vite, React, Tailwind CSS) e Firebase. & 1 Semana & Concluído \\ \hline
Fase 3 & Desenvolvimento do sistema de Autenticação e Perfil de utilizador. & 2 Semanas & Concluído \\ \hline
Fase 4 & Implementação do módulo do Armário, Carrinho e Lavandaria. & 3 Semanas & Concluído \\ \hline
Fase 5 & Desenvolvimento do módulo de Criação de Outfits e Planeamento. & 3 Semanas & Concluído \\ \hline
Fase 6 & Integração do sistema de clima e funcionalidades da Comunidade. & 2 Semanas & Concluído \\ \hline
Fase 7 & Otimização do design premium, atalhos, testes e correções de bugs. & 2 Semanas & Concluído \\ \hline
Fase 8 & Escrita do relatório de PAP e preparação da defesa final. & 3 Semanas & Concluído \\ \hline
\end{tabular}
\caption{Cronograma e Sequência de Tarefas da PAP}
\label{tab:cronograma}
\end{table}
\section{Apresentação da Empresa}
Por se tratar de um projeto de Prova de Aptidão Profissional de cariz puramente académico e de desenvolvimento autónomo, a sua conceção e produção decorreram integralmente nos laboratórios tecnológicos da \textbf{Escola Profissional de Vila do Conde} sob a orientação direta dos formadores do curso. Não obstante, o desenvolvimento do \textbf{MyCloset} replicou fielmente a metodologia e as boas práticas adotadas no mercado de trabalho das empresas de desenvolvimento de software, seguindo ciclos de desenvolvimento ágeis e testes de usabilidade regulares.
\chapter{Contexto}
O desenvolvimento da aplicação \textbf{MyCloset} enquadra-se no setor de \textit{Fashion Technology} (tecnologia aplicada à moda), uma área em forte crescimento que promove a sustentabilidade, o consumo consciente e a eficiência pessoal através de soluções digitais. No mercado de trabalho contemporâneo, a capacidade de automatizar tarefas diárias e gerir recursos através da internet constitui uma competência chave para qualquer organização ou indivíduo.
O projeto apresenta impactos positivos esperados em várias frentes:
\begin{itemize}
\item \textbf{Impacto Ambiental e Social:} Promove a consciencialização do vestuário disponível, incentivando a reutilização de peças que de outra forma seriam esquecidas, combatendo o consumo impulsivo.
\item \textbf{Impacto na Produtividade Pessoal:} Reduz consideravelmente o tempo gasto diariamente a escolher o vestuário adequado, permitindo automatizar esta tarefa com base no clima ou no planeamento prévio feito no fim de semana.
\item \textbf{Impacto Tecnológico:} Demonstra a viabilidade da utilização de arquiteturas serverless em nuvem para aplicações de consumo em tempo real, aliando segurança e escalabilidade rápida a custos reduzidos de infraestrutura.
\end{itemize}
\section{Perfil de Desempenho do Técnico de Informática de Gestão}
O/A Técnico/a de Informática de Gestão é o profissional qualificado que desenvolve competências no âmbito da moderna gestão das organizações, nomeadamente na construção de modelos de gestão de negócios/projetos, criando matrizes com recurso a aplicações informáticas para as micro, pequenas e médias empresas, com vista à eficácia de resultados. Está apto para apoiar a coordenação de departamentos de informática e proceder ao desenvolvimento, instalação e utilização de aplicações informáticas em qualquer área funcional de uma organização/empresa.
As atividades fundamentais a desempenhar por este técnico são:
\begin{itemize}
\item Instalar, configurar e efetuar a manutenção de diferentes sistemas operativos e software de aplicação;
\item Instalar, configurar, desenvolver e efetuar a manutenção de Bases de Dados;
\item Avaliar, participar na escolha de utilitários e participar nas políticas de segurança em sistemas informáticos;
\item Desenvolver aplicações na área de gestão;
\item Avaliar e participar na escolha de ferramentas de gestão;
\item Parametrizar e adequar a necessidades específicas, ferramentas de gestão existentes;
\item Analisar convenientemente problemas existentes e propor soluções adequadas aos meios existentes na empresa;
\item Desenvolver módulos que complementem as aplicações de gestão à medida das necessidades da empresa;
\item Desenvolver, distribuir, instalar e efetuar a manutenção de aplicações informáticas, utilizando ambientes e linguagens de programação orientadas a objetos, procedimentos e visuais;
\item Desenvolver, instalar e manter servidores, páginas e sistemas de informação nas tecnologias web;
\item Colaborar na gestão de recursos humanos, materiais e financeiros;
\item Participar na execução da contabilidade geral da empresa;
\item Apoiar no processamento de salários;
\item Utilizar aplicações de faturação, stocks, contas correntes, imobilizados, contabilidade e salários;
\item Participar na organização dos processos e procedimentos das obrigações fiscais;
\item Participar nos processos e procedimentos referentes aos diversos regimes de proteção social;
\item Apoiar o expediente e arquivo;
\item Participar na elaboração de relatórios e mapas de gestão.
\end{itemize}
O desenvolvimento do \textbf{MyCloset} permitiu pôr em prática competências cruciais deste perfil, tais como: desenho e implementação de bases de dados não-relacionais, implementação de políticas de segurança na nuvem, desenvolvimento e manutenção de sistemas de informação baseados em tecnologias web modernas, parametrização de utilitários e estruturação de interfaces intuitivas para utilizadores finais.
\section{Objetivos da Formação em Contexto de Trabalho}
A Formação em Contexto de Trabalho (FCT) visa a aquisição e o desenvolvimento de competências técnicas, relacionais e organizacionais relevantes para a qualificação profissional de Técnico/a de Informática de Gestão.
A modalidade adotada pela Escola Profissional de Vila do Conde para a Formação em Contexto de Trabalho é o estágio curricular.
Em conformidade com o Plano de Formação previsto para o curso profissional de Técnico/a de Informática de Gestão, todos os formandos realizam os seus estágios em instituições e empresas da Área de Formação do curso, de forma a garantir uma boa contextualização da formação e um bom desenvolvimento do perfil de competências técnicas tecnológicas e práticas.
\section{Funções Exercidas}
No decorrer da elaboração desta PAP, o formando desempenhou funções equivalentes às de um desenvolvedor de software \textit{full-stack} sénior. O trabalho foi realizado de forma maioritariamente autónoma no que toca à programação e design, contando com o acompanhamento regular e orientação pedagógica de modo a validar as decisões arquiteturais. As principais atividades executadas englobaram a modelação dos dados no Cloud Firestore, a escrita de regras de segurança para proteção dos dados confidenciais dos utilizadores, a codificação de lógica em React, a estruturação visual com Tailwind CSS, a implementação do suporte internacional multilíngue (através do ficheiro \texttt{i18n.js}) e a realização de testes funcionais.
\chapter{Descrição Técnica}
A arquitetura geral do \textbf{MyCloset} assenta num modelo cliente-servidor moderno suportado por tecnologias serverless (computação sem servidor). A Figura \ref{fig:arquitetura} ilustra o fluxo de comunicação entre o cliente web e a infraestrutura de dados.
\begin{figure}[h!]
\centering
% \includegraphics[width=0.7\textwidth]{imagens/arquitetura.png}
\begin{center}
\fbox{Cliente Web (React + Vite) $\longleftrightarrow$ Firebase Auth / Cloud Firestore / Cloud Messaging}
\end{center}
\caption{Esquema da Arquitetura Geral do MyCloset}
\label{fig:arquitetura}
\end{figure}
Ao nível do \textbf{Software}, as escolhas técnicas justificam-se pelas seguintes vantagens comparativas:
\begin{enumerate}
\item \textbf{React (Vite):} Permite estruturar a aplicação como uma Single Page Application (SPA). A reatividade do React garante que qualquer alteração de estado (como marcar uma roupa como suja) se reflita de imediato na interface sem recarregar a página. O Vite oferece tempos de build instantâneos e carregamento veloz.
\item \textbf{Cloud Firestore:} Como base de dados NoSQL orientada a documentos estruturados, permite guardar coleções de roupas e perfis de forma flexível. O Firestore escuta as alterações em tempo real, sincronizando instantaneamente a base de dados com a interface do utilizador.
\item \textbf{Tailwind CSS:} Proporciona um design esteticamente superior através de classes utilitárias. A aplicação do modo escuro é facilitada nativamente por classes como \texttt{dark:bg-gray-900}, permitindo criar transições visuais extremamente suaves e premium.
\item \textbf{Firebase Authentication:} Reduz drasticamente a complexidade de gerir chaves criptográficas e sessões seguras no lado do servidor, gerindo a privacidade de cada conta.
\end{enumerate}
Ao nível do \textbf{Hardware}, o desenvolvimento decorreu num computador portátil standard (Processador Core i5, 16GB de RAM). A infraestrutura de produção e alojamento é executada na infraestrutura de nuvem global da Google (Firebase Hosting e Google Cloud Platform), eliminando a necessidade de servidores físicos dedicados no cliente.
\section{Modelação de Dados no Cloud Firestore}
A base de dados do \textbf{MyCloset} está organizada na coleção principal de \texttt{artifacts} contendo o documento do projeto \texttt{my-closet-app}. Abaixo estão descritas as subcoleções principais e os respetivos esquemas de dados em formato de documentos:
\begin{itemize}
\item \textbf{Coleção de Peças de Roupa (\texttt{clothes}):}
Localizada em \texttt{/artifacts/my-closet-app/users/\{userId\}/clothes/\{itemId\}}.
\begin{itemize}
\item \texttt{id} (String): Identificador único do item.
\item \texttt{name} (String): Nome descritivo da peça de roupa.
\item \texttt{category} (String): Categoria da roupa (\textit{Tops}, \textit{Bottoms}, \textit{Calçado}, \textit{Casacos}, \textit{Acessórios}).
\item \texttt{color} (String): Cor ou combinação de cores do item.
\item \texttt{imageUrl} (String): URL da imagem alojada ou string comprimida em Base64.
\item \texttt{favorite} (Boolean): Estado de peça favorita.
\item \texttt{status} (String): Estado atual da peça no sistema (\texttt{active}, \texttt{laundry}, \texttt{trash}).
\item \texttt{sections} (Array of Strings): Identificadores das secções onde a roupa está incluída.
\item \texttt{createdAt} (Number/Timestamp): Data de registo do item.
\end{itemize}
\item \textbf{Coleção de Outfits (\texttt{looks}):}
Localizada em \texttt{/artifacts/my-closet-app/users/\{userId\}/looks/\{lookId\}}.
\begin{itemize}
\item \texttt{id} (String): Identificador único do outfit.
\item \texttt{name} (String): Nome descritivo do conjunto criado pelo utilizador.
\item \texttt{pieces} (Array of Strings): Lista de IDs das peças de roupa que constituem o look.
\item \texttt{createdAt} (Number): Timestamp de criação do look.
\end{itemize}
\item \textbf{Coleção de Planeamento Climatérico (\texttt{planner}):}
Localizada em \texttt{/artifacts/my-closet-app/users/\{userId\}/planner/\{date-string\}}.
O documento tem como ID a data de planeamento no formato \texttt{YYYY-MM-DD}.
\begin{itemize}
\item \texttt{lookId} (String): ID do outfit planeado para o respetivo dia.
\end{itemize}
\item \textbf{Coleção de Perfis Públicos (\texttt{publicProfiles}):}
Localizada em \texttt{/artifacts/my-closet-app/publicProfiles/\{userId\}}.
Contém dados de utilizadores cuja privacidade está definida como pública, permitindo a pesquisa comunitária.
\begin{itemize}
\item \texttt{uid} (String): ID de utilizador associado no Firebase Auth.
\item \texttt{username} (String): Nome de utilizador precedido por ``@''.
\item \texttt{fullName} (String): Nome completo do utilizador.
\item \texttt{bio} (String): Descrição de perfil.
\item \texttt{location} (String): Localidade (ex: Vila do Conde).
\item \texttt{avatar} (String): Foto de perfil codificada em Base64.
\item \texttt{isPrivate} (Boolean): Estado de privacidade do perfil.
\end{itemize}
\end{itemize}
\newpage
\section{Manual de Funcionamento}
Esta secção funciona como o manual do utilizador do \textbf{MyCloset}. Apresenta-se o ecrã e as imagens de cada página com a descrição pormenorizada de todos os botões e interações disponíveis.
\subsection{Ecrã de Autenticação (Login e Registo)}
O ecrã de autenticação (Figura \ref{fig:manual_auth}) é o primeiro contacto do utilizador com a plataforma \textbf{MyCloset}. Possui um layout moderno com animações interativas e gradientes visuais.
\begin{figure}[h!]
\centering
\includegraphics[width=0.45\textwidth]{imagens/auth.png}
\caption{Interface de Autenticação (Login e Registo)}
\label{fig:manual_auth}
\end{figure}
\noindent\textbf{Descrição dos Campos e Botões:}
\begin{itemize}
\item \textbf{Campo E-mail (Input):} Campo de preenchimento obrigatório para digitar o endereço de correio eletrónico associado à conta do utilizador.
\item \textbf{Campo Palavra-passe (Input):} Campo de texto mascarado para inserção da senha de segurança para autenticação.
\item \textbf{Botão ENTRAR / REGISTAR (Submissão):} Botão principal de ação. Efetua a chamada aos servidores do Firebase Auth para validar a credencial e aceder ao sistema, ou efetuar a criação da conta caso esteja no ecrã de Registo.
\item \textbf{Botão ``Esqueceu-se da palavra-passe?'' (Link):} Ao clicar, abre o modal de recuperação de conta. Permite redefinir a palavra-passe através do envio automático de um e-mail de recuperação do Firebase.
\item \textbf{Botão ``Criar Conta'' / ``Já tenho conta'' (Link de Alternância):} Altera de imediato o ecrã entre o modo de Início de Sessão (Login) e o modo de Criação de Conta (Registo), reconfigurando o formulário.
\item \textbf{Bandeiras de Idioma (PT, EN, ES, FR, DE):} Situadas na zona inferior do ecrã de autenticação, estas bandeiras interativas permitem alterar todo o idioma e textos visíveis na interface antes mesmo de iniciar sessão.
\end{itemize}
\subsection{Painel de Controlo (Dashboard)}
O Painel de Controlo (Figura \ref{fig:manual_dashboard}) apresenta um resumo executivo da conta do utilizador com estatísticas rápidas e o assistente climático.
\begin{figure}[h!]
\centering
\includegraphics[width=0.7\textwidth]{imagens/dashboard.png}
\caption{Painel de Controlo (Dashboard) com Cartões de Estatísticas}
\label{fig:manual_dashboard}
\end{figure}
\noindent\textbf{Descrição dos Campos e Botões:}
\begin{itemize}
\item \textbf{Cartão ``Roupas Prontas'':} Mostra a quantidade de roupas com estado ``ativo'' no armário. Ao ser premido, redireciona o utilizador para a página do Armário.
\item \textbf{Cartão ``Na Lavandaria'':} Exibe a contagem de peças enviadas para limpeza. Redireciona o utilizador para o ecrã da Lavandaria.
\item \textbf{Cartão ``Meus Outfits'':} Mostra o número total de conjuntos criados. Redireciona o utilizador para a página de gestão de Outfits.
\item \textbf{Card de Clima (``Hoje em Portugal''):} Apresenta as temperaturas meteorológicas reais/simuladas do dia atual e exibe conselhos de vestuário gerados dinamicamente com base nas temperaturas.
\item \textbf{Botão ``Explorar Sugestões'':} Localizado no Card de Clima, este botão de atalho rápido abre o guarda-roupa já pré-filtrado com as peças leves ou quentes recomendadas para as condições climatéricas do dia.
\item \textbf{Gráfico ``Top Cores'':} Componente visual que apresenta a distribuição percentual das cores mais abundantes no armário do utilizador.
\end{itemize}
\subsection{O Meu Armário (Closet)}
O ecrã principal do Armário (Figura \ref{fig:manual_closet}) contém a listagem de todas as roupas registadas ativas em formato de grelha com fotos interativas.
\begin{figure}[h!]
\centering
\includegraphics[width=0.75\textwidth]{imagens/closet.png}
\caption{Página O Meu Armário (Closet) e Grelha de Peças}
\label{fig:manual_closet}
\end{figure}
\noindent\textbf{Descrição dos Campos e Botões:}
\begin{itemize}
\item \textbf{Barra de Pesquisa (Input):} Permite digitar palavras-chave para filtrar as roupas pelo nome em tempo real.
\item \textbf{Botão ``Filtros Avançados'':} Abre o painel lateral de filtros complexos. Permite realizar filtragens combinadas por cor, categoria (Ex: Tops, Casacos), favoritos ou data de registo da peça.
\item \textbf{Botões de Secção (Ex: Trabalho, Festa, Todos):} Linha de botões horizontais rápidos que filtram instantaneamente o armário de acordo com a finalidade ou secção atribuída à peça.
\item \textbf{Botão ``Gerir Secções'' (Ícone Definições):} Abre o modal de gestão de secções, no qual o utilizador pode criar uma nova secção (com emoji à escolha) ou remover secções antigas.
\item \textbf{Ações nos Cards de Roupa (Hover):}
\begin{itemize}
\item \textbf{Botão Favorito (Coração):} Ao clicar no ícone do coração, marca a peça de roupa como favorita (mudando para vermelho) ou remove-a dos favoritos.
\item \textbf{Botão Editar (Ícone Lápis):} Abre o ecrã de edição de item para reconfigurar os dados da peça de roupa selecionada.
\item \textbf{Botão Lavar (Ícone Gotas):} Retira a peça de roupa do Armário ativo e envia-a diretamente para a Lavandaria, definindo o estado como ``laundry''.
\item \textbf{Botão Mover para Lixo (Ícone Lixeira):} Envia a peça de roupa para a Reciclagem (lixeira), de onde poderá ser restaurada ou apagada permanentemente.
\end{itemize}
\end{itemize}
\subsection{Carrinho (Wishlist)}
A Wishlist (Figura \ref{fig:manual_wishlist}) tem uma mecânica idêntica ao Armário, mas é dedicada a gerir as peças desejadas para compras futuras.
\begin{figure}[h!]
\centering
\includegraphics[width=0.7\textwidth]{imagens/wishlist.png}
\caption{Página Carrinho (Wishlist) para Compras Futuras}
\label{fig:manual_wishlist}
\end{figure}
\noindent\textbf{Descrição dos Campos e Botões:}
\begin{itemize}
\item \textbf{Botão ``Adicionar peça como compra futura'' (+):} Abre o ecrã para registar uma peça que o utilizador pretende adquirir no futuro.
\item \textbf{Ações e Filtros:} Os mesmos botões de pesquisa, filtros avançados e remoção rápida estão disponíveis, permitindo o planeamento eficaz de aquisições de moda.
\end{itemize}
\subsection{Lavandaria (Laundry)}
A Lavandaria (Figura \ref{fig:manual_laundry}) aloja temporariamente as roupas marcadas pelo utilizador como sujas, retirando-as das opções disponíveis para novos looks.
\begin{figure}[h!]
\centering
\includegraphics[width=0.7\textwidth]{imagens/laundry.png}
\caption{Interface da Lavandaria com Roupas a Lavar}
\label{fig:manual_laundry}
\end{figure}
\noindent\textbf{Descrição dos Campos e Botões:}
\begin{itemize}
\item \textbf{Botão ``Lavar'' (Ícone Gotas):} Presente em cada card de roupa na lavandaria, este botão aciona o processo de lavagem do item selecionado, movendo-o imediatamente de volta para o Armário principal.
\item \textbf{Texto/Área de Cesto Vazio:} Quando não há peças para lavar, exibe uma mensagem informativa incentivando o utilizador a manter o seu guarda-roupa limpo.
\end{itemize}
\subsection{Gestão de Outfits}
A página de Outfits (Figura \ref{fig:manual_outfits}) permite criar e visualizar combinações de roupas (looks completos) e partilhá-los na comunidade.
\begin{figure}[h!]
\centering
\includegraphics[width=0.75\textwidth]{imagens/outfits.png}
\caption{Ecrã de Outfits com Criação de Looks e Partilha}
\label{fig:manual_outfits}
\end{figure}
\noindent\textbf{Descrição dos Campos e Botões:}
\begin{itemize}
\item \textbf{Botão ``Criar Novo Outfit'':} Abre o editor interativo de looks.
\item \textbf{Campo ``Nome do Outfit'' (No Editor):} Permite introduzir o nome descritivo do conjunto de roupa (Ex: ``Casual Verão'').
\item \textbf{Grelha de Seleção de Roupas (No Editor):} Permite clicar nas roupas ativas do armário para as incluir no novo outfit. As peças selecionadas são destacadas na interface.
\item \textbf{Botão ``Guardar Outfit'' (No Editor):} Guarda permanentemente a combinação na conta do utilizador.
\item \textbf{Botão ``Cancelar'' (No Editor):} Descarta a criação e regressa à lista geral de outfits.
\item \textbf{Botão ``Partilhar'' (Ícone Share nos Looks salvos):} Gera uma hiperligação (URL) exclusiva do outfit e copia-a para a área de transferência do sistema, possibilitando a partilha exterior.
\item \textbf{Botão ``Editar'' (Lápis nos Looks salvos):} Abre o outfit de volta no editor para alterar o nome ou as peças incluídas.
\item \textbf{Botão ``Apagar'' (Lixeira nos Looks salvos):} Remove o look da base de dados do utilizador.
\end{itemize}
\subsection{Planeamento (Planner / Calendário)}
O Planeador (Figura \ref{fig:manual_planner}) permite ao utilizador gerir e agendar o que vai vestir ao longo dos dias, organizando as rotinas diárias de estilo.
\begin{figure}[h!]
\centering
\includegraphics[width=0.7\textwidth]{imagens/planner.png}
\caption{Calendário Dinâmico de Planeamento de Looks}
\label{fig:manual_planner}
\end{figure}
\noindent\textbf{Descrição dos Campos e Botões:}
\begin{itemize}
\item \textbf{Botão Mês / Semana (Alternador):} Permite escolher entre a visualização clássica mensal em formato de grelha ou uma linha temporal semanal detalhada.
\item \textbf{Setas de Navegação (Esquerda / Direita):} Permitem retroceder ou avançar nos meses ou semanas do calendário de forma dinâmica.
\item \textbf{Botão ``Hoje'':} Centra instantaneamente o calendário no dia atual de forma a facilitar o planeamento rápido do próprio dia.
\item \textbf{Célula de Dia (Botão Escolher Outfit):} Ao clicar num dia vazio do calendário, abre um modal exibindo os outfits salvos da conta. Ao selecionar um outfit, este é agendado para o dia.
\item \textbf{Botão ``Remover Outfit deste Dia'' (Ícone X vermelho):} Remove a associação do outfit agendado para aquele dia do calendário, deixando o dia livre para novo planeamento.
\end{itemize}
\subsection{Comunidade}
O ecrã da Comunidade (Figura \ref{fig:manual_community}) permite pesquisar perfis públicos na plataforma para obter inspirações e interagir de forma social.
\begin{figure}[h!]
\centering
\includegraphics[width=0.7\textwidth]{imagens/community.png}
\caption{Página da Comunidade e Pesquisa de Perfis}
\label{fig:manual_community}
\end{figure}
\noindent\textbf{Descrição dos Campos e Botões:}
\begin{itemize}
\item \textbf{Campo ``Procurar por @username...'' (Pesquisa):} Caixa de texto que permite filtrar perfis públicos de utilizadores através do seu nome de utilizador do MyCloset.
\item \textbf{Botão ``Ver Perfil'':} Ao clicar no utilizador encontrado na pesquisa, abre a vista do perfil público deste, apresentando as suas roupas e outfits públicos.
\item \textbf{Botão ``Copiar para o meu armário'' (Clonagem de Looks):} Ao aceder a um outfit de outro utilizador, este botão permite clonar e criar as peças correspondentes ou a combinação completa na conta do próprio utilizador de forma imediata.
\end{itemize}
\subsection{Definições (Settings)}
As Definições (Figura \ref{fig:manual_settings}) são o painel central de configuração de preferências visuais, notificações e operações críticas nos dados da conta.
\begin{figure}[h!]
\centering
\includegraphics[width=0.7\textwidth]{imagens/settings.png}
\caption{Painel de Definições, Lixeira e Zona Crítica}
\label{fig:manual_settings}
\end{figure}
\noindent\textbf{Descrição dos Campos e Botões:}
\begin{itemize}
\item \textbf{Toggle ``Modo Escuro'':} Alterna o tema de cores geral da interface entre o modo claro e escuro.
\item \textbf{Seletor ``Cor do Tema'':} Permite alterar a cor principal de destaque de toda a aplicação (Indigo, Esmeralda, Violeta, Âmbar, Rose).
\item \textbf{Dropdown ``Idioma da Aplicação'':} Permite traduzir a aplicação de forma completa em múltiplos idiomas (Português, Inglês, Espanhol, Francês, Alemão).
\item \textbf{Dropdown ``Tamanho dos itens'':} Ajusta a proporção dos cards de roupa exibidos no armário (Pequeno, Médio, Grande).
\item \textbf{Dropdown ``Página Inicial'':} Configura qual a página que é automaticamente apresentada após o utilizador efetuar o início de sessão.
\item \textbf{Toggle ``Perfil Privado'':} Ativa a privacidade da conta, ocultando o armário e outfits na pesquisa comunitária para outros utilizadores.
\item \textbf{Botão ``Exportar Dados (JSON)'':} Efetua o download instantâneo de um ficheiro contendo todas as roupas, conjuntos e informações da conta em formato estruturado JSON.
\item \textbf{Gestão da Lixeira (Reciclagem):}
\begin{itemize}
\item \textbf{Botão ``Restaurar'':} Devolve a peça selecionada da reciclagem de volta para o Armário principal.
\item \textbf{Botão ``Apagar permanentemente'' (Lixeira):} Exclui definitivamente a peça de roupa da base de dados sem possibilidade de recuperação.
\item \textbf{Botão ``Esvaziar'':} Limpa permanentemente todos os itens que estão de momento no lixo.
\end{itemize}
\item \textbf{Zona Crítica - Botão ``Limpar Tudo'':} Move todas as roupas ativas do armário principal de uma só vez para o lixo.
\end{itemize}
\subsection{Informações da Conta (Profile)}
A secção do Perfil (Figura \ref{fig:manual_profile}) gere as informações públicas do utilizador e fornece uma via direta de suporte técnico.
\begin{figure}[h!]
\centering
\includegraphics[width=0.7\textwidth]{imagens/profile.png}
\caption{Interface de Edição de Perfil e Formulário de Suporte}
\label{fig:manual_profile}
\end{figure}
\noindent\textbf{Descrição dos Campos e Botões:}
\begin{itemize}
\item \textbf{Foto de Perfil (Avatar interativo):} Ao clicar no círculo do avatar, abre-se o seletor de ficheiros local permitindo ao utilizador enviar uma imagem, a qual é processada, cortada e guardada no Firestore.
\item \textbf{Campos Nome de Utilizador, Nome Completo, Nascimento, Localidade e Bio (Inputs):} Permitem introduzir e atualizar a informação do utilizador que será exibida publicamente.
\item \textbf{Botão ``Guardar Alterações'' (Formulário Perfil):} Grava as atualizações do utilizador de forma síncrona no Firestore.
\item \textbf{Select Tipo de Feedback (Suporte):} Permite escolher entre ``Ideia / Sugestão'' ou ``Bug / Erro''.
\item \textbf{Botão ``Enviar Mensagem'' (Feedback):} Envia e guarda a sugestão inserida na coleção global de suporte para leitura pela administração do MyCloset.
\end{itemize}
\subsection{Atalhos e Menu Rápido}
No topo de todas as páginas principais da aplicação encontram-se elementos globais acessíveis a qualquer momento:
\begin{itemize}
\item \textbf{Botão de Colapso Lateral (Menu):} Abre ou fecha a sidebar lateral de navegação rápida para aumentar a área de trabalho visual do utilizador.
\item \textbf{Botão Brilho (Sparkles):} Localizado no topo superior direito, abre o modal do \textit{Outfit Diário}, sugerindo um conjunto planeado ou aleatório instantaneamente.
\item \textbf{Botão de Modo de Ecrã (Sol / Lua):} Permite alterar o tema entre claro e escuro instantaneamente a partir de qualquer ecrã.
\item \textbf{Botão Sino (Notificações):} Abre o histórico de notificações da conta (Ex: avisar se um outfit do utilizador foi guardado ou copiado por outro membro da Comunidade).
\item \textbf{Botão ``Adicionar Rápido'' (+):} Redireciona o utilizador de imediato para a página de registo de nova peça de roupa no armário.
\end{itemize}
\section{Implementação do Projeto}
A implementação do projeto focou-se na modularidade do código e no bom desempenho do processamento de dados. As decisões técnicas foram orientadas pelos seguintes aspetos:
\begin{itemize}
\item \textbf{Técnico:} A escolha do ecossistema React com Vite garantiu um desenvolvimento ágil assente em estados que respondem de imediato às interações. O uso de bases de dados não-relacionais Firestore permitiu simplificar as consultas através da ausência de esquemas estritos, ideal para o armazenamento ágil de perfis que contêm coleções internas de secções e imagens em Base64 de forma integrada. As regras de segurança aplicadas no Firebase impedem que utilizadores mal-intencionados visualizem coleções privadas de terceiros.
\item \textbf{Económico:} A utilização dos serviços Google Firebase em modo gratuito permitiu mitigar todos os custos de aquisição e manutenção de infraestruturas físicas de servidores ou de licenças de software comercial, tornando o projeto viável a custo zero de manutenção.
\end{itemize}
\chapter{Conclusões}
A realização deste projeto de Prova de Aptidão Profissional permitiu concretizar com sucesso todos os objetivos inicialmente estabelecidos para o desenvolvimento da plataforma \textbf{MyCloset}.
Os principais sucessos obtidos prendem-se com a criação de uma interface limpa, de elevada riqueza estética e visualmente sofisticada, que oferece uma fluidez extraordinária nas transições de ecrã e na reatividade de dados. A integração eficaz da geolocalização e conselhos de vestuário de acordo com a temperatura provou ser um elemento diferenciador. Além disso, a arquitetura multilíngue e o sistema de clonagem comunitária acrescentaram um valor comercial prático ao produto final.
No plano da autocrítica, embora a aplicação cumpra todas as suas exigências de forma exemplar, registaram-se pequenos desafios técnicos associados ao limite de armazenamento de imagens em Base64 diretamente nos documentos do Cloud Firestore, os quais recomendariam uma migração para o Firebase Storage em futuras versões.
O projeto provou ter grande utilidade prática, dotando o formando de competências profissionais nas tecnologias mais requisitadas pelo mercado de trabalho, consolidando os conhecimentos do curso profissional de Técnico de Informática de Gestão.
\section{Limitações do Trabalho}
Durante o desenvolvimento do projeto verificaram-se algumas limitações de operação e escolhas técnicas:
\begin{enumerate}
\item \textbf{Armazenamento de Imagens:} A persistência de fotos de roupas comprimidas em strings Base64 diretamente no banco de dados Firestore é célere e dispensa autenticação secundária, contudo, o limite máximo de 1MB por documento no Firestore limita a resolução final das fotografias carregadas pelo utilizador.
\item \textbf{Notificações FCM no Safari:} A receção de notificações em tempo real com base no Firebase Cloud Messaging apresenta incompatibilidades e restrições específicas nos browsers móveis Safari (iOS) em versões antigas, exigindo autorizações adicionais de segurança.
\end{enumerate}
\section{Apreciação Final}
Em conclusão, o desenvolvimento do \textbf{MyCloset} proporcionou um enorme enriquecimento pessoal e profissional. Foi possível vivenciar o ciclo completo de engenharia de software de uma aplicação web reativa, desde o levantamento inicial de requisitos e design de interfaces até à implantação segura em nuvem e documentação técnica detalhada. O resultado final é um website premium do qual me orgulho e que se apresenta apto a ser demonstrado perante o júri.
\chapter*{Webgrafia}
\begin{itemize}[leftmargin=*]
\item \textbf{React Documentation} -- Guia e documentação oficial da biblioteca React. Disponível em: \url{https://react.dev/} [Acedido em Junho de 2026].
\item \textbf{Tailwind CSS Documentation} -- Guias de desenho e estilização responsiva. Disponível em: \url{https://tailwindcss.com/docs} [Acedido em Junho de 2026].
\item \textbf{Firebase Product Documentation} -- Documentação técnica do Firebase Auth, Firestore e Cloud Messaging. Disponível em: \url{https://firebase.google.com/docs} [Acedido em Junho de 2026].
\item \textbf{Vite Guide} -- Guia oficial de empacotamento e build do Vite. Disponível em: \url{https://vitejs.dev/guide/} [Acedido em Junho de 2026].
\end{itemize}
\chapter*{Anexos}
Abaixo apresenta-se, como anexo técnico complementar, o ficheiro de configuração das regras de segurança (\texttt{firestore.rules}) utilizado no Cloud Firestore da Google Cloud Platform para garantir a privacidade dos dados de cada utilizador no \textbf{MyCloset}.
\begin{spacing}{1.2}
\begin{verbatim}
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// Permite que qualquer utilizador autenticado leia e escreva o seu perfil público
match /artifacts/my-closet-app/publicProfiles/{userId} {
allow read: if true;
allow write: if request.auth != null && request.auth.uid == userId;
}
// Regras de privacidade das roupas de cada utilizador
match /artifacts/my-closet-app/users/{userId}/clothes/{itemId} {
allow read: if request.auth != null && (request.auth.uid == userId ||
get(/databases/$(database)/documents/artifacts/my-closet-app/publicProfiles/$(userId)).data.isPrivate == false);
allow write: if request.auth != null && request.auth.uid == userId;
}
// Regras de privacidade dos looks criados
match /artifacts/my-closet-app/users/{userId}/looks/{lookId} {
allow read: if request.auth != null && (request.auth.uid == userId ||
get(/databases/$(database)/documents/artifacts/my-closet-app/publicProfiles/$(userId)).data.isPrivate == false);
allow write: if request.auth != null && request.auth.uid == userId;
}
}
}
\end{verbatim}
\end{spacing}
\end{document}