# README

## Tesouro Espiritual - Congregação Mariana

Um app para facilitar a contagem de tesouros, permitindo ao Padre Diretor ter uma noção de como está a vida espiritual dos membros e acompanhar seus avanços e dificuldades no caminho para a eternidade.

### Desafios

O App visa não ter custos com licenciamento, ou seja, publicar nas lojas Play Store e App Store sem custos adicionais. Para isso, utilizamos ferramentas de desenvolvimento no plano gratuito (Vercel e Firebase Spark). O ciclo de vida do app foi implementado de maneira a ser fácil de manter e escalável para ser acessível a outras congregações.

O sistema é estável graças ao uso do Firestore Firebase, proporcionando uma distribuição fácil e confiável, com baixa latência e conformidade com as normas do LGPD e GDPR. A escolha foi baseada na necessidade de um banco de dados NoSQL, já que o Supabase ainda não atendia a esse critério e enfrentava problemas de segurança de dados no momento da escolha.

A contagem geral dos tesouros para definir a saúde da congregação foi um desafio significativo. Lidando com um banco de dados não relacional, implementamos regras para melhor uso da filtragem geral, suportadas pelo Firebase com dados massivos.

### Arquitetura do Projeto

Desenvolvi o projeto usando Flutter na versão 3.13.9. Adotei uma abordagem simplificada para todas as funcionalidades do projeto, onde cada tela representa um módulo. Para gerenciamento de estado, utilizei o BloC. Na versão 2.0 do app, implementarei injeção de dependência para facilitar a escalabilidade e a manutenção futura, além de permitir o uso de outros tipos de banco de dados.

![Imagem do BloC](https://github.com/Mathvdias/tesouro/assets/74201503/3b0dd90b-066c-434c-8473-92d975789458)

Para evitar dependência excessiva de pacotes externos e lidar com problemas de versão do Flutter, implementei funcionalidades como cache, repositórios e validação de campos de login na pasta `package`. A migração para a nova versão do Flutter Web está em segundo plano para permitir a execução em WebAssembly (WASM), melhorando a performance e o carregamento nativo.

Utilizei o `DeferredWidget` para lidar com o carregamento em cache, permitindo menor latência na web. Isso divide o app em partes menores, carregadas conforme necessário.

```dart
typedef LibraryLoader = Future<void> Function();
typedef DeferredWidgetBuilder = Widget Function();

class DeferredWidget extends StatefulWidget {
  const DeferredWidget(
    this.libraryLoader,
    this.createWidget, {
    super.key,
    Widget? placeholder,
  }) : placeholder = placeholder ?? const DeferredLoadingPlaceholder();

  final LibraryLoader libraryLoader;
  final DeferredWidgetBuilder createWidget;
  final Widget placeholder;
  static final Map<LibraryLoader, Future<void>> _moduleLoaders = {};
  static final Set<LibraryLoader> _loadedModules = {};

  static Future<void> preload(LibraryLoader loader) {
    if (!_moduleLoaders.containsKey(loader)) {
      _moduleLoaders[loader] = loader().then((dynamic _) {
        _loadedModules.add(loader);
      });
    }
    return _moduleLoaders[loader]!;
  }

  @override
  State<DeferredWidget> createState() => _DeferredWidgetState();
}

class _DeferredWidgetState extends State<DeferredWidget> {
  _DeferredWidgetState();

  Widget? _loadedChild;
  DeferredWidgetBuilder? _loadedCreator;

  @override
  void initState() {
    if (DeferredWidget._loadedModules.contains(widget.libraryLoader)) {
      _onLibraryLoaded();
    } else {
      DeferredWidget.preload(widget.libraryLoader)
          .then((dynamic _) => _onLibraryLoaded());
    }
    super.initState();
  }

  void _onLibraryLoaded() {
    setState(() {
      _loadedCreator = widget.createWidget;
      _loadedChild = _loadedCreator!();
    });
  }

  @override
  Widget build(BuildContext context) {
    if (_loadedCreator != widget.createWidget && _loadedCreator != null) {
      _loadedCreator = widget.createWidget;
      _loadedChild = _loadedCreator!();
    }
    return _loadedChild ?? widget.placeholder;
  }
}
```

A implementação é feita da seguinte maneira:

```dart
import 'package:tesouro_cm/home/home.dart' deferred as home;

class HomeModule extends StatelessWidget {
  const HomeModule({
    super.key,
  });
  static Page<void> page() => const CupertinoPage<void>(
        child: HomeModule(),
        fullscreenDialog: true,
      );

  @override
  Widget build(BuildContext context) {
    return DeferredWidget(
      home.loadLibrary,
      () => home.HomePage(),
    );
  }
}
```

O `DeferredWidget` no código é um widget Flutter projetado para carregar dinamicamente uma biblioteca (ou módulo) quando necessário e exibir um widget associado a essa biblioteca após o carregamento. Ele é útil quando você deseja dividir seu aplicativo em partes menores (bibliotecas ou módulos) que são carregadas apenas quando necessário, economizando recursos e melhorando o desempenho inicial do aplicativo.

![Captura de Tela 2024-06-27 às 14 19 55](https://github.com/Mathvdias/tesouro/assets/74201503/576abad6-e0f1-4697-8447-cdf3b5363d4b)

Recursos como notificações push e analytics foram implementados na parte nativa da web, explorando recursos de cache, splash em CSS, bloqueio de modo desenvolvedor, metadados, e geração de PDF para salvar documentos gerados. Cada usuário tem um UUID gerado com 528 bits, garantindo uma taxa de colisão extremamente baixa de (2^{528}).

```dart
// RECURSO PARA CHAMAR UM ANCHOR PARA SALVAR ARQUIVOS
class FileSaveHelper {
  static Future<void> saveAndLaunchFile(
      List<int> bytes, String fileName) async {
    AnchorElement(
        href:
            'data:application/octet-stream;charset=utf-16le;base64,${base64.encode(bytes)}')
      ..setAttribute('download', fileName)
      ..click();
  }
}
```

### Funcionalidades

* **Nota**: O tesouro é um agrupamento de 14 itens para preenchimento mensal. O Tesouro Espiritual é um recurso usado pelas Congregações para contabilizar atos de piedade realizados ao longo do mês.
* **Login**
* **Criar usuário**
* **Recuperação de senha**
* **Gerar PDF do tesouro mensal**
* **Visualização do tesouro mensal, individual e da igreja**
* **Marcação do tesouro**
* **Escolher mês e dia para preenchimento do tesouro**
* **Notificações diárias às 21h**
* **Contagem geral dos membros por mês**
* **Recurso para redirecionamento ao site principal** [**salvemaria.com.br**](https://salvemaria.com.br)
* **Seção sobre com informações e FAQ**
* **Visualização de licenças usadas**
* **Console no Firebase para publicar notificações, bloquear/desbloquear usuários, recuperação de senha e confirmação de criação de conta**

### Design

Desenvolvi com base no Material Design 3 e todos os tipos de animações nativas do Flutter. Inclui acessibilidade para todos os botões com suporte a TalkBack e VoiceOver, além de responsividade para qualquer plataforma.

### Arquitetura

| <p><img src="https://github.com/Mathvdias/tesouro/assets/74201503/c0a4234d-7fa0-4dae-9a8d-7dc603ce9ee6" alt="Captura de Tela 2024-06-27 às 14 34 19"></p><p>Arquitetura do projeto</p> | <p><img src="https://github.com/Mathvdias/tesouro/assets/74201503/39512b74-1ae1-4b7a-a153-773d345ae78a" alt="Captura de Tela 2024-06-27 às 14 34 51"></p><p>Definição de cada feature/modulo</p> |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |

### Melhorias Futuras

* Implementação de injeção de dependência
* Exploração dos conceitos de SOLID e Clean Dart
* Migração para WebAssembly
* Implementação de testes unitários com cobertura acima de 80%
* Implementação de testes de widget
* Ciclo de melhoria contínua voltado para testes
* Desacoplamento do design system do Material Design
* Desacoplamento do app do Firebase
* Uso de feature flags
* Notificações push para dias não marcados
* Novas formas de distribuição PWA
* Adição de recursos de analytics
* Melhoria na integração com web
* Esconder variáveis de ambiente na Vercel

### Segurança

Por questões de segurança, apenas o domínio principal está configurado para funcionar no Firebase, impedindo o uso indevido do banco de dados e da autenticação. Essa configuração é feita via console do Firebase.

### Deploy

Cada nova versão é criada a partir da branch `main`. Novos recursos, correções e releases são desenvolvidos em branches separadas, respeitando boas práticas de engenharia de software. As configurações do projeto estão visíveis no line command

`firebase.json`, definindo as regras de acesso ao banco de dados e os recursos que precisam ser carregados. Na versão 2.0, planejo ajustar as branches para evitar conflitos na `main`.

* **Build Command**: `flutter/bin/flutter build web --release`
* **Output Directory**: `build/web`
* **Development Command**:

  ```sh
  FV=3.13.9; if cd flutter; then git pull; else git clone -b $FV https://github.com/flutter/flutter.git; fi && flutter/bin/flutter doctor && flutter/bin/flutter clean && flutter/bin/flutter config --enable-web
  ```

#### Console Firebase

![Captura de Tela 2024-06-27 às 14 40 24](https://github.com/Mathvdias/tesouro/assets/74201503/1af09014-ac3b-4ca4-81b4-7e39bcd06047)

[Firebase Console](https://console.cloud.google.com/apis/credentials/key/85d12d11-1bd3-477b-9af9-ae8fc1015f63?hl=pt-br\&project=tesourocm-28ec4)

#### Vercel Console

![Captura de Tela 2024-06-27 às 14 41 40](https://github.com/Mathvdias/tesouro/assets/74201503/40673879-78cb-4a20-a7a4-1b6ab8bc34e0)

[Vercel Console](https://vercel.com/matheus-projects-3de90591/tesouro)

#### Push Notifications

![Captura de Tela 2024-06-27 às 14 42 38](https://github.com/Mathvdias/tesouro/assets/74201503/d8ce0847-77ba-4337-8e7c-98f3b131c9f4)

### Instalação

Para instalar o APP Tesouro:

```sh
git clone https://github.com/Mathvdias/tesouro.git
cd tesouro
code .
flutter pub get
```

### **Nota**: Recomendo o uso do Puro para gerenciamento de versão do Flutter. **Versão do Flutter: 3.13.9**

### Design do app \[Telas]

| ![Screenshot 1](https://github.com/Mathvdias/tesouro/assets/74201503/ceab1936-7a7c-46d2-9e89-4fdc899903fb)                            | ![Screenshot 2](https://github.com/Mathvdias/tesouro/assets/74201503/a3b6d653-5b18-47be-9341-190384ab6831)  |
| ------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
| ![Screenshot 3](https://github.com/Mathvdias/tesouro/assets/74201503/3902c99d-d68b-4e48-a634-8a8633c8aea0)                            | ![Screenshot 4](https://github.com/Mathvdias/tesouro/assets/74201503/70366cfb-db50-4281-a67d-344b7ed05aad)  |
| ![Screenshot 5](https://github.com/Mathvdias/tesouro/assets/74201503/4849c3b8-8072-4f13-a177-99f4908260ea)                            | ![Screenshot 6](https://github.com/Mathvdias/tesouro/assets/74201503/41531cdc-8d08-496a-9b75-012740e019b8)  |
| ![Screenshot 7](https://github.com/Mathvdias/tesouro/assets/74201503/15879155-cbc1-4a6c-bc14-744c086abbd3)                            | ![Screenshot 8](https://github.com/Mathvdias/tesouro/assets/74201503/b898d0da-7b01-4513-9de4-fc1db77c6ecc)  |
| ![Screenshot 9](https://github.com/Mathvdias/tesouro/assets/74201503/06c81e14-dd16-4abb-85d1-f9dc728f629a)                            | ![Screenshot 10](https://github.com/Mathvdias/tesouro/assets/74201503/02bcbd80-bb95-477e-9cb5-d2e5ffbe632c) |
| ![Screenshot 11](https://github.com/Mathvdias/tesouro/assets/74201503/9b18aaa0-fe63-4976-8bc3-522c2d162c70)                           | ![Screenshot 12](https://github.com/Mathvdias/tesouro/assets/74201503/7c45686e-d354-440d-9785-516025466720) |
| ![Screenshot 13](https://github.com/Mathvdias/tesouro/assets/74201503/7334958c-27f9-4f88-928c-e8f8ac9e57fc)                           | ![Screenshot 14](https://github.com/Mathvdias/tesouro/assets/74201503/7061825a-f8de-49e0-88cc-f391a066a66d) |
| ![Captura de Tela 2024-06-27 às 15 37 44](https://github.com/Mathvdias/tesouro/assets/74201503/81b4503b-a596-4f49-aeea-6103f011bcfd) |                                                                                                             |

## Versão 1.0.0 do app

| ![loginv1](https://github.com/user-attachments/assets/29c1c168-b822-464a-a92c-349e53860fbc) | ![homev1](https://github.com/user-attachments/assets/951716f8-3b9c-42be-81f2-4f4907602bec) |
| ------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
| ![homev1](https://github.com/user-attachments/assets/2705f3d5-fe96-452f-84cb-01b57c659e12)  | ![homev1](https://github.com/user-attachments/assets/aed9fe79-0d4f-457a-b98e-abaabb5c25ff) |
| ![homev1](https://github.com/user-attachments/assets/617cef65-38e1-4da3-b5a5-308ab219e353)  | ![homev1](https://github.com/user-attachments/assets/7ac51c71-2ca7-4517-98f7-37b8eedae189) |

[**Acesse o Whitepaper do projeto**](https://matheusdias.gitbook.io/tesouro)
