feat: bootstrap project

This commit is contained in:
Duarte
2026-05-31 20:22:50 +01:00
commit 66581ef584
65 changed files with 7915 additions and 0 deletions
@@ -0,0 +1,22 @@
# USXX - [Título Curto e Descritivo da User Story]
**Como** [tipo de utilizador / perfil]
**Quero** [desejo / ação que quer realizar]
**Para** [benefício / valor de negócio gerado]
## Descrição do Fluxo
[Breve descrição de como o utilizador interage com esta funcionalidade ou qual o fluxo principal.]
## Critérios de Aceitação
### 1. Interface Gráfica (UI)
- [ ] Detalhes visuais, ecrãs, campos e botões em PT-PT.
- [ ] Validações de formulários (campos obrigatórios, formatos específicos).
### 2. Comportamento e Regras de Negócio
- [ ] Regras que o sistema deve cumprir.
- [ ] Fluxos alternativos ou tratamento de erros.
### 3. Integração de Dados / Segurança
- [ ] Que dados devem ser guardados ou alterados na base de dados SQLite.
- [ ] Permissões de acesso (quem pode aceder/realizar esta ação).
@@ -0,0 +1,19 @@
# US00 - Inicialização do Utilizador Administrador (Seed/Bootstrap)
**Como** Sistema RefoodOne
**Quero** garantir que existe pelo menos um utilizador Administrador inicial na base de dados aquando do primeiro arranque
**Para** permitir que a equipa possa fazer login e começar a gerir o sistema.
## Descrição do Fluxo
Durante a inicialização da base de dados (ou execução das migrações/seed), o sistema deve verificar se já existe algum utilizador registado. Se a base de dados estiver vazia, deve criar automaticamente o utilizador administrador inicial com credenciais pré-definidas.
## Critérios de Aceitação
### 1. Utilizador Administrador Inicial
- **E-mail / Username**: `refoodpdn`
- **Palavra-passe**: `rpdn!2512` (deve ser guardada de forma segura na base de dados usando hash argon2 ou bcrypt)
- **Perfil (Role)**: `admin`
### 2. Comportamento e Regras de Negócio
- O bootstrap deve ocorrer apenas uma vez. Se o utilizador `refoodpdn` já existir, a rotina não deve duplicar o registo nem reescrever a palavra-passe caso esta tenha sido alterada pelo utilizador.
- O processo deve ser automático ao correr as migrações/inicialização do servidor ou através de um script de sementeira (seed) dedicado.
@@ -0,0 +1,27 @@
# US01 - Autenticação (Login)
**Como** utilizador do RefoodOne (Administrador, Gestor de Turno ou Voluntário)
**Quero** introduzir as minhas credenciais (nome de utilizador/email e palavra-passe)
**Para** aceder às funcionalidades específicas do meu perfil/função no sistema.
## Critérios de Aceitação
### 1. Interface de Login (PT-PT)
- Página limpa com o logótipo do Refood e o nome "RefoodOne" visível de forma não intrusiva.
- Campos de entrada:
- **E-mail** (obrigatório)
- **Palavra-passe** (obrigatório, com opção de ocultar/mostrar a palavra-passe)
- Botão de ação: **Entrar**
### 2. Validação e Segurança
- O sistema deve validar as credenciais contra a base de dados SQLite.
- A palavra-passe deve ser verificada de forma segura (usando hash bcrypt/argon2 conforme definido em `.clinrules`).
- Se as credenciais estiverem incorretas:
- Mostrar uma mensagem de erro em PT-PT: *"Utilizador ou palavra-passe incorretos."*
- Não revelar qual dos campos está incorreto por motivos de segurança.
- Cookies de sessão seguros devem ser utilizados após o login com sucesso.
### 3. Redirecionamento por Perfil (Role)
Após o login com sucesso, o utilizador deve ser redirecionado:
- **Administrador**: Redirecionar para a página de gestão de turnos
- **Voluntário**: Redirecionar diretamente para o ecrã de registo/entrega de comida (Entregas).
@@ -0,0 +1,29 @@
# US07 - Agrupamento do Menu de Navegação (Menu Gestão)
**Como** Utilizador autenticado do RefoodOne
**Quero** que as opções "Beneficiários", "Turnos" e "Entregas" sejam agrupadas num submenu sob um menu principal chamado "Gestão"
**Para** melhorar a organização do cabeçalho de navegação e tornar a interface mais limpa e intuitiva.
## Descrição do Fluxo
Ao fazer login na aplicação, o utilizador visualiza um cabeçalho de navegação (navbar) simplificado. Em vez de ter os links principais expostos diretamente, é exibido um item de menu interativo chamado **Gestão**. Ao clicar ou passar o cursor sobre este menu, abre-se um dropdown contendo as opções autorizadas para o perfil do utilizador.
## Critérios de Aceitação
### 1. Interface Gráfica (UI)
- **Menu Gestão**: Deve ser exibido como um menu dropdown na barra de navegação superior, com a etiqueta "Gestão" em PT-PT.
- **Opções do Submenu**: O dropdown deve conter as seguintes opções (quando aplicável ao perfil):
- **Beneficiários**
- **Turnos**
- **Entregas**
- **Estilo**: O dropdown deve seguir a estética Bootstrap 5, com comportamento responsivo (fechamento automático ao clicar fora e suporte a ecrãs táteis/mobile).
### 2. Comportamento e Regras de Negócio
- As opções visíveis no submenu devem respeitar rigorosamente as permissões de cada perfil de utilizador:
- **Administrador (Admin)**: Visualiza todas as opções no submenu (**Beneficiários**, **Turnos**, **Entregas**).
- **Gestor de Turno (Shift Manager)**: Visualiza as opções permitidas (**Turnos**, **Entregas** e **Beneficiários** conforme permissões de gestão).
- **Voluntário (Volunteer)**: Visualiza apenas a opção **Entregas** (ou redirecionado diretamente).
- O submenu só deve ser visível se o utilizador estiver autenticado.
### 3. Integração de Dados / Segurança
- O controlo de visibilidade dos links do submenu deve basear-se no objeto `data.user` carregado pelo layout principal (`+layout.svelte`).
- A proteção de rotas no servidor (`hooks.server.ts`) deve continuar a validar e bloquear acessos diretos caso o utilizador digite o URL manualmente.
@@ -0,0 +1,19 @@
# US08 - Modelo de Dados de Entregas
**Como** Sistema RefoodOne
**Quero** definir a estrutura e modelo de dados para o registo das entregas de cabazes aos beneficiários
**Para** garantir a integridade dos dados e o relacionamento correto entre as entregas, os beneficiários e os turnos.
## Critérios de Aceitação
### 1. Estrutura da Tabela `deliveries`
A tabela de entregas na base de dados SQLite deve conter os seguintes campos:
- **`id`**: Texto (Primary Key, UUID gerado automaticamente, não nulo).
- **`beneficiary_id`**: Texto (não nulo). Chave estrangeira que referencia a tabela `beneficiaries.id`.
- **`shift_id`**: Texto (não nulo). Chave estrangeira que referencia a tabela `shifts.id`.
- **`date`**: Texto (não nulo, formato 'YYYY-MM-DD'). Representa o dia em que a entrega foi efetuada.
- **`created_at`**: Inteiro (não nulo, timestamp). Guarda a data e hora do registo do sistema.
### 2. Integridade Referencial e Comportamento
- **Chave Estrangeira de Beneficiário**: A coluna `beneficiary_id` deve referenciar `beneficiaries(id)`. Deve incluir uma regra de eliminação em cascata (`ON DELETE CASCADE`), de modo a que se um beneficiário for removido, o seu histórico de entregas seja automaticamente apagado.
- **Chave Estrangeira de Turno**: A coluna `shift_id` deve referenciar `shifts(id)`. Deve incluir uma regra de eliminação em cascata (`ON DELETE CASCADE`), de modo a que se um turno for removido do sistema, os registos de entrega a ele associados sejam removidos.
@@ -0,0 +1,40 @@
# US09 - Interface de Registo de Entregas
**Como** Voluntário ou Administrador do RefoodOne
**Quero** um ecrã com botões grandes para cada beneficiário ativo e um popup de confirmação
**Para** registar de forma rápida e tátil as entregas de cabazes em dispositivos tablet.
## Descrição do Fluxo
O voluntário acede ao menu "Entregas". O ecrã apresenta uma grelha de botões táteis correspondentes a todos os beneficiários ativos. Ao tocar no botão de um beneficiário (ex: "#124"), abre-se um popup de confirmação exibindo os dados principais do beneficiário (Nome e Nº de Pessoas do Agregado). Ao clicar em "Confirmar", o sistema grava a entrega associando o turno ativo e a data corrente, e fecha o popup.
## Critérios de Aceitação
### 1. Interface Gráfica (UI)
- **Ecrã de Grelha (Grid)**:
- Apresenta botões organizados em grelha (vários por linha dependendo da resolução).
- Cada botão corresponde a um **beneficiário ativo**.
- O rótulo (label) do botão deve ser o **número do beneficiário** em destaque.
- Os botões devem ser dimensionados para facilitar o toque com o dedo (design tátil ideal para tablets).
- **Popup de Confirmação (Modal)**:
- Disparado ao clicar no botão de um beneficiário.
- Deve mostrar em destaque:
- **Nome do beneficiário**
- **Nº de pessoas do agregado familiar** (do registo do beneficiário)
- Botões de Ação no popup:
- **Confirmar** (submete o registo de entrega, cor verde)
- **Cancelar** (fecha o popup sem registar, cor cinzenta)
### 2. Comportamento e Regras de Negócio
- Apenas beneficiários com estado **Ativo** devem ser exibidos na grelha.
- **Prevenção de Duplicados (Desativação do Botão)**:
- Se um beneficiário já tiver uma entrega registada na data corrente (dia de hoje), o seu respetivo botão na grelha de entregas deve estar **desativado** (disabled).
- O botão desativado deve ter um aspeto visual distinto (ex: cor cinzenta ou verde-suave com um visto de "concluído") para indicar claramente que a entrega já foi efetuada no dia de hoje.
- **Gravação Automática**:
- Ao confirmar, o sistema regista a entrega na base de dados (`deliveries`).
- A data de entrega é preenchida pelo servidor com a **data atual** (no formato YYYY-MM-DD).
- O turno é determinado automaticamente pelo servidor com base no **dia da semana e hora atual** em que o registo está a ser submetido (se cair fora do horário de funcionamento de qualquer turno, associa-se o turno padrão ou mais próximo).
### 3. Integração de Dados / Segurança
- O ecrã deve carregar os dados dos beneficiários e turnos no servidor (`+page.server.ts`).
- A gravação deve ocorrer via SvelteKit Action (`POST` request) para garantir que a data e o turno sejam calculados e validados de forma segura no lado do servidor.
- Apenas utilizadores autenticados podem aceder e registar entregas.
@@ -0,0 +1,26 @@
# US10 - Nome do Beneficiário no Botão de Entrega
**Como** Voluntário do RefoodOne
**Quero** que o primeiro nome do beneficiário seja exibido por baixo do seu número no botão de registo de entrega
**Para** facilitar a identificação visual rápida do beneficiário antes de clicar e reduzir a probabilidade de enganos no registo.
## Descrição do Fluxo
Ao aceder ao ecrã de registo de entregas ("Entregas"), o voluntário vê a grelha de botões táteis. Cada botão agora exibe não apenas o número do beneficiário (ex: "#124"), mas também o seu **primeiro nome** (ex: "João") logo abaixo do número, numa fonte menor e legível.
## Critérios de Aceitação
### 1. Interface Gráfica (UI)
- **Rótulo do Botão (Button Label)**:
- O **Número do Beneficiário** continua a ser exibido em destaque na parte superior do botão.
- O **Primeiro Nome** do beneficiário deve ser exibido logo abaixo do número, centralizado, com estilo de texto menor (ex: classe Bootstrap `small` ou `text-muted`).
- **Tratamento do Nome**:
- Deve ser exibido **apenas o primeiro nome** (a primeira palavra do campo `name` na base de dados). Exemplo: "Maria Eduarda Santos" deve ser exibido como "Maria".
- O texto do nome deve ser ajustado ou truncado se necessário, para garantir que não quebre o layout quadrado do botão tátil.
### 2. Comportamento e Regras de Negócio
- O sistema deve extrair de forma robusta o primeiro nome a partir do nome completo registado na tabela `beneficiaries`.
- Se o campo do nome contiver apenas um nome, exibe esse nome normalmente.
- Se o nome contiver espaços ou hífens, extrai a primeira palavra delimitada por espaços.
### 3. Integração de Dados
- Os dados do beneficiário (`name` e `number`) são os mesmos carregados a partir da tabela `beneficiaries` no servidor. Não são necessárias alterações no modelo de dados da base de dados SQLite.
@@ -0,0 +1,26 @@
# US11 - Ajustes de Navegação (Menu Entregas e Gestão)
**Como** Utilizador do RefoodOne
**Quero** que o menu "Entregas" seja exibido diretamente na barra de navegação principal e que o menu "Gestão" (dropdown) seja visível apenas para Administradores (role `admin`)
**Para** otimizar o acesso rápido dos voluntários e gestores de turno à funcionalidade de entregas, mantendo os painéis administrativos visíveis apenas para os administradores.
## Descrição do Fluxo
Ao fazer login na aplicação:
- Um utilizador com o perfil **Administrador (Admin)** visualiza a opção **Gestão** (que contém os submenus **Beneficiários** e **Turnos**) e, ao lado desta, a opção **Entregas** exposta diretamente.
- Um utilizador com o perfil **Gestor de Turno** ou **Voluntário** visualiza apenas a opção **Entregas** diretamente exposta no cabeçalho principal. O menu **Gestão** fica ocultado para estes utilizadores.
## Critérios de Aceitação
### 1. Interface Gráfica (UI)
- **Menu Entregas**: Deve ser um link principal exposto diretamente no cabeçalho de navegação (navbar), posicionado ao lado do menu Gestão para administradores.
- **Menu Gestão (Dropdown)**:
- Fica visível **apenas** para utilizadores com o perfil de administrador (`role === 'admin'`).
- Passa a conter no seu submenu dropdown apenas as opções **Beneficiários** e **Turnos**.
- **Idioma**: Toda a barra de navegação deve continuar a utilizar termos em PT-PT.
### 2. Comportamento e Regras de Negócio
- Utilizadores com perfil `shift_manager` e `volunteer` não devem ter acesso visual ao menu Gestão.
- A proteção de rotas no servidor (`hooks.server.ts`) deve continuar a garantir que apenas `admin` aceda a `/admin/beneficiarios`, e que apenas `admin` e `shift_manager` acedam a `/admin/turnos`.
### 3. Integração de Dados
- O cabeçalho de navegação (`+layout.svelte`) lê o perfil de utilizador (`data.user.role`) a partir dos dados carregados do servidor para aplicar as regras de visibilidade.
@@ -0,0 +1,28 @@
# US12 - Apagar Registo de Entrega Diário
**Como** Utilizador do RefoodOne (Administrador / Gestor de Turno / Voluntário)
**Quero** poder apagar um registo de entrega efetuado hoje através de um botão na lista de entregas diárias
**Para** corrigir eventuais enganos no registo e permitir que o botão do beneficiário fique novamente ativo para novo registo.
## Descrição do Fluxo
Ao aceder ao ecrã de entregas:
1. O utilizador visualiza a lista "Entregas de Hoje" no fundo da página.
2. Cada linha da tabela de entregas apresenta uma nova coluna com um botão para apagar (ex: ícone de lixo/remover).
3. Ao clicar no botão de apagar, o registo de entrega é eliminado e o botão correspondente do beneficiário na grelha superior volta a ficar disponível (ativo/clicável) imediatamente.
## Critérios de Aceitação
### 1. Interface Gráfica (UI)
- **Tabela de Entregas**:
- Adição de uma nova coluna sem cabeçalho (ou cabeçalho "Ações") no final da tabela.
- Exibição de um botão de eliminação em cada linha (por exemplo, botão com ícone de caixote do lixo em tons vermelhos ou contornos suaves).
- **Grelha de Beneficiários**:
- Após a eliminação com sucesso, o botão do beneficiário correspondente deixa de estar no estado desabilitado/entregue e regressa ao estado ativo original.
### 2. Comportamento e Regras de Negócio
- O botão de apagar elimina definitivamente o registo de entrega da base de dados correspondente àquele dia e beneficiário.
- Deve ser usado um mecanismo reativo ou atualização de página (ex: `use:enhance`) para atualizar imediatamente a tabela de entregas e a grelha de botões de beneficiários sem necessidade de recarregar a página manualmente.
### 3. Integração de Dados / Segurança
- **Base de Dados**: O registo correspondente à entrega deve ser eliminado da tabela `entregas`.
- **Permissões**: Qualquer perfil autenticado com acesso ao ecrã de entregas pode efetuar a eliminação para retificar erros de registo imediatos.
@@ -0,0 +1,42 @@
# US13 - Gestão de Utilizadores
**Como** Administrador do RefoodOne
**Quero** poder visualizar e gerir as contas de utilizadores (voluntários, gestores de turno e administradores) do sistema
**Para** controlar os perfis de acesso e atualizar as credenciais dos utilizadores de forma segura.
## Descrição do Fluxo
Ao aceder ao sistema como administrador:
1. O utilizador encontra um novo submenu **Utilizadores** no menu dropdown principal **Gestão**.
2. Ao selecionar **Utilizadores**, é direcionado para o ecrã de listagem de utilizadores.
3. No ecrã de listagem, pode ver uma tabela contendo o **Nome de Utilizador** e o **Perfil (Role)** de cada conta registada. Cada linha tem uma opção/link para aceder ao detalhe do utilizador.
4. No ecrã de detalhe de um utilizador, o administrador pode:
- Alterar o **Nome de Utilizador**.
- Alterar o **Perfil** (selecionando numa lista dropdown as opções: *Administrador*, *Gestor de Turno*, *Voluntário*).
- Definir uma nova password na secção correspondente, inserindo a nova password e confirmando a mesma num segundo campo (não sendo necessária a password antiga).
5. O administrador clica em Guardar para persistir as alterações na base de dados.
## Critérios de Aceitação
### 1. Interface Gráfica (UI)
- **Menu Gestão**: Adicionar a ligação para "Utilizadores" no menu dropdown do cabeçalho principal.
- **Ecrã de Listagem**:
- Tabela com colunas: **Nome** (`username`) e **Perfil** (`role`).
- Botão ou ligação para editar o detalhe em cada linha de utilizador.
- **Ecrã de Detalhe**:
- Campo de texto para o **Nome de Utilizador**.
- Dropdown com as roles suportadas em PT-PT:
- *Administrador* (`admin`)
- *Gestor de Turno* (`shift_manager`)
- *Voluntário* (`volunteer`)
- Secção "Alterar Password" contendo dois campos de texto/password: **Nova Password** e **Confirmar Nova Password**.
- Mensagens de erro/sucesso claras em português.
### 2. Comportamento e Regras de Negócio
- Apenas utilizadores com a role `admin` podem aceder a estes ecrãs (tanto a listagem como o detalhe).
- Se a secção de password for preenchida, o sistema deve validar se as duas passwords coincidem e se cumprem requisitos mínimos de segurança (ex: tamanho mínimo).
- Se a secção de password for deixada em branco, o utilizador é guardado mantendo a password antiga sem alterações.
- O ecrã de detalhe também deve permitir criar um utilizador novo (ou ter um fluxo correspondente) com os mesmos campos.
### 3. Integração de Dados / Segurança
- **Segurança**: As novas passwords devem ser encriptadas de forma segura (ex: hashing) antes de guardar na tabela `users` da base de dados.
- **Controlo de Acesso**: Bloqueio de acesso a nível de rotas no servidor (`hooks.server.ts` ou páginas locais) para utilizadores que não tenham perfil `admin`.
@@ -0,0 +1,32 @@
# US14 - Homepage com Botões de Atalho (Tablet-Optimized)
**Como** Utilizador do RefoodOne
**Quero** ter uma página inicial simples com botões táteis de grande dimensão e ícones ilustrativos
**Para** aceder de forma rápida e intuitiva às funcionalidades autorizadas a partir de um tablet.
## Descrição do Fluxo
Ao iniciar a aplicação e fazer login:
1. O utilizador é direcionado para a Homepage (`/`).
2. Dependendo do seu perfil de utilizador, são apresentados botões táteis grandes organizados numa grelha responsiva:
- **Voluntário** e **Gestor de Turno**: Visualizam apenas o botão **Entregas** (com ícone de cabaz/cesto de compras).
- **Administrador**: Visualiza três botões: **Entregas** (ícone de cabaz), **Utilizadores** (ícone de pessoas/contas) e **Beneficiários** (ícone de grupo/lista).
3. Ao clicar num dos botões grandes, o utilizador é encaminhado para a respetiva secção do sistema.
## Critérios de Aceitação
### 1. Interface Gráfica (UI)
- **Design para Tablet**:
- Grelha centrada no ecrã com botões de tamanho generoso (ex: cartões táteis com pelo menos 140x140px), facilmente clicáveis com um dedo.
- Efeitos visuais modernos ao passar o rato (hover) ou tocar no ecrã.
- **Botões e Ícones**:
- **Entregas**: Rótulo "Entregas", com um ícone representativo de cabaz/cesto (SVG).
- **Beneficiários**: Rótulo "Beneficiários", com um ícone representativo de lista/pessoas (SVG).
- **Utilizadores**: Rótulo "Utilizadores", com um ícone representativo de utilizadores/chaves (SVG).
- **Idioma**: Todos os rótulos e textos em PT-PT.
### 2. Comportamento e Regras de Negócio
- A visualização dos botões deve respeitar rigorosamente o perfil do utilizador autenticado (`data.user.role`).
- Utilizadores sem o perfil `admin` (ex: `volunteer` e `shift_manager`) não devem ver os botões de administração (Beneficiários e Utilizadores) no ecrã inicial.
### 3. Integração de Dados
- A página lê a informação do utilizador a partir dos dados locais carregados (`data.user`) na rota raiz (`/`).