# Área de Notificações
## Estrutura
- Texto (com limitação de caracteres?);
- Data de envio (DD/MM/AAAA);
- Categorias (Campanhas, Financeiro, Insights);
- Ícone de categoria;
- Notificação lida/não-lida;
- Link de redirecionamento (opcional);
- CTA (opcional);
## Conteúdos
### Campanha
- **Sua campanha "XXXX" está terminando**
-- Direcionamento: Página de campanhas
-- Dados: Campanhas com data de término definidas
-- Periodicidade: 2 dias antes da data de término
### Financeiro
- **Confirmação de crédito**
-- Direcionamento: Página do extrato do financeiro
-- Dados: Transação financeira da conta
-- Periodicidade: Envio pontual
- **RA não realizado por falta de saldo**
-- Direcionamento: Página de financeiro
-- Dados: RA não realizado
-- Periodicidade: Envio pontual
### Insights
- **Campanha com Orçamento Diário abaixo do mínimo**
-- Direcionamento: Página da campanha
-- Dados: Conta com campanha ativa + orçamento diário abaixo do mínimo
-- Periodicidade: Envio único
- **Relatório semanal**
-- Direcionamento: CTA Download
-- Dados: Relatório da semana vigente
-- Periodicidade: Envio semanal
- **Sua campanha "XXXX(PADS)" possui X grupos de anúncio com anúncios abaixo da média. Ajuste agora!**
-- Direcionamento: Página da campanha citada
-- Dados: Campanhas ativas com itens farol vermelho
-- Periodicidade: Reenvio a cada 15 dias
## Back End
Notas sobre serialização:
* ObjectId será transformado em string
* Set será transformado em objeto:
* { 1, 2, 3 } => { 1: true, 2: true, 3: true}
### Comunicação back <-> front
Investigar: Server sent events, WebSocket. No pior dos casos faremos poll constante.
### Tokens especiais na URL:
`<app>`: Substitui por app.b2wads.com ou app-staging.b2wads.com
`<api>`: Substitui por api.b2wads.com ou api-staging.b2wads.com
`<token>`: Substitui pelo token atual do usuário
Substituições feitas pelo front-end
### Mongo
```typescript=
enum NotificationCategory {
Campaigns,
Financial,
Insights
}
enum NotificationType {
Manual,
CampaignEnding,
CreditConfirmation,
AutoTransferNoCredit,
DailyBudgetBelowMinimum,
PeriodicReport,
LowAverageCpc,
}
interface Cta {
type: string;
}
interface RedirectCta extends Cta {
type: "Redirect";
url: string;
}
interface Notification {
id: ObjectId;
type: NotificationType;
accountId: ObjectId;
text: string;
createdAt: Date;
category: NotificationCategory;
clickUrl: string;
readBy: Set<ObjectId>;
ctas: Cta[];
}
```
### Interface REST
#### PUT /notifications/read/
Marca todas as notificações do usuário atualmente logado como lidas
##### Retorno
204 No Content, sem body
#### PUT /notifications/{id}/read/
Marca notificação como lida ou não lida pelo usuário atualmente logado
##### Retorno
204 No Content, sem body
##### Body
```typescript=
interface MarkReadParameters {
read: bool;
}
```
#### GET /notifications/
Endpoint de notificações já existentes
##### Query String
```typescript=
interface GetNotificationsParameters {
from: String; // Cursor para os próximos elementos
limit: Number; // Número máximo de notificações à retornar
}
```
##### Retorno
200 OK
###### Body
```typescript=
{
results: Notification[]; // ordenado por data de criação
next: String; // Cursor para os próximos elementos
}
```
### GET /notifications/unread
Endpoint de contagem de notificações não lidas
#### Query string
```typescript=
interface GetUnreadCountParameters {
// campos temporários, remover depois
userId: String;
accountId: ObjectId;
}
```
#### Retorno
200 OK
###### Body
```typescript=
Number
```
#### GET /notifications/stream/accountId/{accountId}
Endpoint de server sent events para novas notificações.
##### Query string (enviado na requisição inicial)
```typescript=
interface NotificationStreamParameters {
// Timestamp da última notificação recebida (via GET /notifications)
// Usado para fazer enviar notificações
// que chegaram entre as duas requisições
lastReceived: Date;
}
```
##### Eventos
###### Formato padrão
```typescript=
interface Message<T> {
type: string;
payload: T;
}
```
###### Handshake
```typescript=
interface Handshake {}
interface HandshakeMessage extends Message {
type: "Handshake";
payload: Handshake;
}
```
###### Nova notificação
```typescript=
interface NewNotificationMessage extends Message {
type: "NewNotification";
payload: Notification;
}
```
###### Mensagem marcada como lida ou não lida
```typescript=
interface MessageReadChanged {
id: ObjectId;
userId: string;
read: bool;
}
interface NotificationReadMessage extends Message {
type: "NotificationReadChanged";
payload: NotificationReadChanged;
}
```
### Consumidor de mensagens
Precisamos de algum worker que tenha uma fila que receba de múltiplas routing keys e crie as entidades das notificações no MongoDB (e despache para web?)
### Notificações específicas
* Campanha terminando
* Cronjob diário?
* Algo no publicador?
* Confirmação de crédito
* Adaptar o Billing para escrever em uma routing key quando ocorrer o crédito
* RA não realizado por falta de saldo
* O auto manager já dispara um email para o MNS. Adapter para escrever em routing key
* Orçamento diário abaixo do mínimo
* Escrever script para ser executado periodicamente
* Relatório semanal
* Cronjob semanal criando notificação enviando para o link do xlsx com filtro da semana pré-definido
* Anúncio abaixo do CPC médio da categoria
* Ao fim do ETL do farol de CPC, consultar campanhas abaixo da média e enviar pra routing key de notificações, que confere se há alguma notificação do mesmo tipo nos últimos 15 dias.
## Front End
### Geral
- [ ] Jest tests
- [ ] Cypress tests
### Sessão:
- [x] Botão no header (sininho) com badge numerado;
- [x] Espaço de notificações (vide Ajuda);
- [ ] Marcar todas como lida;
- [ ] Scrollable ("paginação" automática);
### Modelo unitário:
- [x] ~~Ícone da categoria;~~
- [x] ~~Texto;~~
- [x] ~~Data de envio (DD/MM/AAAA);~~
- [x] ~~Hover: botão opções (Marcar como lida/não-lida);~~
- [x] ~~Card clicável (link de redirecionamento de acordo com categoria)~~;
- [x] ~~Botão CTA~~;
### Marcar como lida/não-lida:
- [ ] Atualizar `unreadNotifications` ao marcar notificação;
- [ ] Atualizar `unreadNotifications` ao marcar todas notificações;
### Outros
- ~~altText ou title do ícone com nome da categoria;~~
- Ao receber notificação nova enquanto dentro da plataforma, atualizar número de notificações (sem toaster);
### Links úteis
[Miro](https://miro.com/app/board/o9J_laq5T8Y=/)
[Figma](https://www.figma.com/file/n9OrzASBYNiNMmqgRlBppY/Notifica%C3%A7%C3%B5es)
[Server sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events)
[Shared worker](https://developer.mozilla.org/en-US/docs/Web/API/SharedWorker)
[Frontend PR Github](https://github.com/b2wads/b2wads-webapp/pull/395)