feat: apply logo, document database schema, update docs
- Move logo to marketplace/src/assets/ - Apply logo in Shell.tsx header - Add favicon and meta tags to index.html - Create docs/database-schema.md with ER diagram - Update README.md with database section - Update marketplace/README.md with assets section - Update seeder-api/README.md with new fields
This commit is contained in:
parent
15eb6d42e5
commit
091e8093c0
7 changed files with 327 additions and 5 deletions
13
README.md
13
README.md
|
|
@ -263,6 +263,19 @@ deno task dev
|
||||||
| **saveinmed-frontend** | Next.js | 15 | TailwindCSS 4 |
|
| **saveinmed-frontend** | Next.js | 15 | TailwindCSS 4 |
|
||||||
| **website** | Fresh (Deno) | v2 | TailwindCSS |
|
| **website** | Fresh (Deno) | v2 | TailwindCSS |
|
||||||
|
|
||||||
|
### Banco de Dados
|
||||||
|
|
||||||
|
O schema completo do banco de dados está documentado em [docs/database-schema.md](./docs/database-schema.md).
|
||||||
|
|
||||||
|
**Principais Tabelas**:
|
||||||
|
- `companies` - Farmácias e distribuidoras
|
||||||
|
- `users` - Usuários vinculados às empresas
|
||||||
|
- `products` - Catálogo de produtos
|
||||||
|
- `orders` / `order_items` - Pedidos e itens
|
||||||
|
- `cart_items` - Carrinho de compras
|
||||||
|
- `reviews` - Avaliações
|
||||||
|
- `shipments` - Envios
|
||||||
|
|
||||||
### Infraestrutura e Serviços
|
### Infraestrutura e Serviços
|
||||||
- **Banco de Dados**: PostgreSQL 14+
|
- **Banco de Dados**: PostgreSQL 14+
|
||||||
- **BaaS**: Appwrite 18
|
- **BaaS**: Appwrite 18
|
||||||
|
|
|
||||||
278
docs/database-schema.md
Normal file
278
docs/database-schema.md
Normal file
|
|
@ -0,0 +1,278 @@
|
||||||
|
# Database Schema - SaveInMed
|
||||||
|
|
||||||
|
Documentação do esquema de banco de dados PostgreSQL do SaveInMed.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Diagrama ER
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
erDiagram
|
||||||
|
COMPANIES ||--o{ USERS : "emprega"
|
||||||
|
COMPANIES ||--o{ PRODUCTS : "vende"
|
||||||
|
COMPANIES ||--o{ ORDERS : "compra (buyer)"
|
||||||
|
COMPANIES ||--o{ ORDERS : "vende (seller)"
|
||||||
|
COMPANIES ||--o{ CART_ITEMS : "possui"
|
||||||
|
ORDERS ||--o{ ORDER_ITEMS : "contém"
|
||||||
|
PRODUCTS ||--o{ ORDER_ITEMS : "inclui"
|
||||||
|
PRODUCTS ||--o{ CART_ITEMS : "referencia"
|
||||||
|
ORDERS ||--o| REVIEWS : "avalia"
|
||||||
|
ORDERS ||--o| SHIPMENTS : "envia"
|
||||||
|
|
||||||
|
COMPANIES {
|
||||||
|
uuid id PK
|
||||||
|
text cnpj UK
|
||||||
|
text corporate_name
|
||||||
|
text category
|
||||||
|
text license_number
|
||||||
|
boolean is_verified
|
||||||
|
float latitude
|
||||||
|
float longitude
|
||||||
|
text city
|
||||||
|
text state
|
||||||
|
text phone
|
||||||
|
text operating_hours
|
||||||
|
boolean is_24_hours
|
||||||
|
timestamptz created_at
|
||||||
|
timestamptz updated_at
|
||||||
|
}
|
||||||
|
|
||||||
|
USERS {
|
||||||
|
uuid id PK
|
||||||
|
uuid company_id FK
|
||||||
|
text role
|
||||||
|
text name
|
||||||
|
text username UK
|
||||||
|
text email UK
|
||||||
|
boolean email_verified
|
||||||
|
text password_hash
|
||||||
|
timestamptz created_at
|
||||||
|
timestamptz updated_at
|
||||||
|
}
|
||||||
|
|
||||||
|
PRODUCTS {
|
||||||
|
uuid id PK
|
||||||
|
uuid seller_id FK
|
||||||
|
text name
|
||||||
|
text description
|
||||||
|
text batch
|
||||||
|
date expires_at
|
||||||
|
bigint price_cents
|
||||||
|
bigint stock
|
||||||
|
timestamptz created_at
|
||||||
|
timestamptz updated_at
|
||||||
|
}
|
||||||
|
|
||||||
|
ORDERS {
|
||||||
|
uuid id PK
|
||||||
|
uuid buyer_id FK
|
||||||
|
uuid seller_id FK
|
||||||
|
text status
|
||||||
|
bigint total_cents
|
||||||
|
text shipping_recipient_name
|
||||||
|
text shipping_street
|
||||||
|
text shipping_number
|
||||||
|
text shipping_complement
|
||||||
|
text shipping_district
|
||||||
|
text shipping_city
|
||||||
|
text shipping_state
|
||||||
|
text shipping_zip_code
|
||||||
|
text shipping_country
|
||||||
|
timestamptz created_at
|
||||||
|
timestamptz updated_at
|
||||||
|
}
|
||||||
|
|
||||||
|
ORDER_ITEMS {
|
||||||
|
uuid id PK
|
||||||
|
uuid order_id FK
|
||||||
|
uuid product_id FK
|
||||||
|
bigint quantity
|
||||||
|
bigint unit_cents
|
||||||
|
text batch
|
||||||
|
date expires_at
|
||||||
|
}
|
||||||
|
|
||||||
|
CART_ITEMS {
|
||||||
|
uuid id PK
|
||||||
|
uuid buyer_id FK
|
||||||
|
uuid product_id FK
|
||||||
|
bigint quantity
|
||||||
|
bigint unit_cents
|
||||||
|
text batch
|
||||||
|
date expires_at
|
||||||
|
timestamptz created_at
|
||||||
|
timestamptz updated_at
|
||||||
|
}
|
||||||
|
|
||||||
|
REVIEWS {
|
||||||
|
uuid id PK
|
||||||
|
uuid order_id FK UK
|
||||||
|
uuid buyer_id FK
|
||||||
|
uuid seller_id FK
|
||||||
|
int rating
|
||||||
|
text comment
|
||||||
|
timestamptz created_at
|
||||||
|
}
|
||||||
|
|
||||||
|
SHIPMENTS {
|
||||||
|
uuid id PK
|
||||||
|
uuid order_id FK UK
|
||||||
|
text carrier
|
||||||
|
text tracking_code
|
||||||
|
text external_tracking
|
||||||
|
text status
|
||||||
|
timestamptz created_at
|
||||||
|
timestamptz updated_at
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Tabelas
|
||||||
|
|
||||||
|
### `companies`
|
||||||
|
Empresas (farmácias/distribuidoras) cadastradas na plataforma.
|
||||||
|
|
||||||
|
| Coluna | Tipo | Descrição |
|
||||||
|
|--------|------|-----------|
|
||||||
|
| `id` | UUID | Chave primária |
|
||||||
|
| `cnpj` | TEXT | CNPJ (único) |
|
||||||
|
| `corporate_name` | TEXT | Razão social |
|
||||||
|
| `category` | TEXT | Categoria (farmacia, distribuidora) |
|
||||||
|
| `license_number` | TEXT | Número da licença sanitária |
|
||||||
|
| `is_verified` | BOOLEAN | Se a empresa foi verificada |
|
||||||
|
| `latitude` | FLOAT | Latitude da localização |
|
||||||
|
| `longitude` | FLOAT | Longitude da localização |
|
||||||
|
| `city` | TEXT | Cidade |
|
||||||
|
| `state` | TEXT | Estado (UF) |
|
||||||
|
| `phone` | TEXT | Telefone de contato |
|
||||||
|
| `operating_hours` | TEXT | Horário de funcionamento |
|
||||||
|
| `is_24_hours` | BOOLEAN | Funciona 24 horas |
|
||||||
|
| `created_at` | TIMESTAMPTZ | Data de criação |
|
||||||
|
| `updated_at` | TIMESTAMPTZ | Data de atualização |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `users`
|
||||||
|
Usuários vinculados às empresas.
|
||||||
|
|
||||||
|
| Coluna | Tipo | Descrição |
|
||||||
|
|--------|------|-----------|
|
||||||
|
| `id` | UUID | Chave primária |
|
||||||
|
| `company_id` | UUID | FK para companies |
|
||||||
|
| `role` | TEXT | Perfil (Dono, Colaborador, Entregador, Admin) |
|
||||||
|
| `name` | TEXT | Nome completo |
|
||||||
|
| `username` | TEXT | Login único |
|
||||||
|
| `email` | TEXT | Email único |
|
||||||
|
| `email_verified` | BOOLEAN | Email verificado |
|
||||||
|
| `password_hash` | TEXT | Hash da senha (bcrypt) |
|
||||||
|
| `created_at` | TIMESTAMPTZ | Data de criação |
|
||||||
|
| `updated_at` | TIMESTAMPTZ | Data de atualização |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `products`
|
||||||
|
Produtos cadastrados para venda.
|
||||||
|
|
||||||
|
| Coluna | Tipo | Descrição |
|
||||||
|
|--------|------|-----------|
|
||||||
|
| `id` | UUID | Chave primária |
|
||||||
|
| `seller_id` | UUID | FK para companies (vendedor) |
|
||||||
|
| `name` | TEXT | Nome do produto |
|
||||||
|
| `description` | TEXT | Descrição |
|
||||||
|
| `batch` | TEXT | Lote |
|
||||||
|
| `expires_at` | DATE | Data de validade |
|
||||||
|
| `price_cents` | BIGINT | Preço em centavos |
|
||||||
|
| `stock` | BIGINT | Quantidade em estoque |
|
||||||
|
| `created_at` | TIMESTAMPTZ | Data de criação |
|
||||||
|
| `updated_at` | TIMESTAMPTZ | Data de atualização |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `orders`
|
||||||
|
Pedidos de compra.
|
||||||
|
|
||||||
|
| Coluna | Tipo | Descrição |
|
||||||
|
|--------|------|-----------|
|
||||||
|
| `id` | UUID | Chave primária |
|
||||||
|
| `buyer_id` | UUID | FK para companies (comprador) |
|
||||||
|
| `seller_id` | UUID | FK para companies (vendedor) |
|
||||||
|
| `status` | TEXT | Status (Pendente, Pago, Faturado, Entregue) |
|
||||||
|
| `total_cents` | BIGINT | Total em centavos |
|
||||||
|
| `shipping_*` | TEXT | Campos de endereço de entrega |
|
||||||
|
| `created_at` | TIMESTAMPTZ | Data de criação |
|
||||||
|
| `updated_at` | TIMESTAMPTZ | Data de atualização |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `order_items`
|
||||||
|
Itens de um pedido.
|
||||||
|
|
||||||
|
| Coluna | Tipo | Descrição |
|
||||||
|
|--------|------|-----------|
|
||||||
|
| `id` | UUID | Chave primária |
|
||||||
|
| `order_id` | UUID | FK para orders |
|
||||||
|
| `product_id` | UUID | FK para products |
|
||||||
|
| `quantity` | BIGINT | Quantidade |
|
||||||
|
| `unit_cents` | BIGINT | Preço unitário em centavos |
|
||||||
|
| `batch` | TEXT | Lote do produto |
|
||||||
|
| `expires_at` | DATE | Validade do produto |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `cart_items`
|
||||||
|
Itens no carrinho de compras.
|
||||||
|
|
||||||
|
| Coluna | Tipo | Descrição |
|
||||||
|
|--------|------|-----------|
|
||||||
|
| `id` | UUID | Chave primária |
|
||||||
|
| `buyer_id` | UUID | FK para companies |
|
||||||
|
| `product_id` | UUID | FK para products |
|
||||||
|
| `quantity` | BIGINT | Quantidade |
|
||||||
|
| `unit_cents` | BIGINT | Preço unitário |
|
||||||
|
| `batch` | TEXT | Lote |
|
||||||
|
| `expires_at` | DATE | Validade |
|
||||||
|
| `created_at` | TIMESTAMPTZ | Data de criação |
|
||||||
|
| `updated_at` | TIMESTAMPTZ | Data de atualização |
|
||||||
|
|
||||||
|
> **UNIQUE**: (buyer_id, product_id)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `reviews`
|
||||||
|
Avaliações de pedidos.
|
||||||
|
|
||||||
|
| Coluna | Tipo | Descrição |
|
||||||
|
|--------|------|-----------|
|
||||||
|
| `id` | UUID | Chave primária |
|
||||||
|
| `order_id` | UUID | FK para orders (único) |
|
||||||
|
| `buyer_id` | UUID | FK para companies |
|
||||||
|
| `seller_id` | UUID | FK para companies |
|
||||||
|
| `rating` | INT | Nota (1-5) |
|
||||||
|
| `comment` | TEXT | Comentário |
|
||||||
|
| `created_at` | TIMESTAMPTZ | Data de criação |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `shipments`
|
||||||
|
Envios de pedidos.
|
||||||
|
|
||||||
|
| Coluna | Tipo | Descrição |
|
||||||
|
|--------|------|-----------|
|
||||||
|
| `id` | UUID | Chave primária |
|
||||||
|
| `order_id` | UUID | FK para orders (único) |
|
||||||
|
| `carrier` | TEXT | Transportadora |
|
||||||
|
| `tracking_code` | TEXT | Código de rastreio interno |
|
||||||
|
| `external_tracking` | TEXT | Código de rastreio externo |
|
||||||
|
| `status` | TEXT | Status (Enviado, Em Trânsito, Entregue) |
|
||||||
|
| `created_at` | TIMESTAMPTZ | Data de criação |
|
||||||
|
| `updated_at` | TIMESTAMPTZ | Data de atualização |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Convenções
|
||||||
|
|
||||||
|
- **Valores monetários**: Sempre em centavos (BIGINT)
|
||||||
|
- **IDs**: UUID v4 ou v7
|
||||||
|
- **Timestamps**: TIMESTAMPTZ (UTC)
|
||||||
|
- **Soft delete**: Não implementado (delete real)
|
||||||
|
|
@ -102,6 +102,24 @@ marketplace/
|
||||||
└── README.md
|
└── README.md
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## 🎨 Assets
|
||||||
|
|
||||||
|
Os arquivos de assets estão em `src/assets/`:
|
||||||
|
|
||||||
|
| Arquivo | Descrição |
|
||||||
|
|---------|-----------|
|
||||||
|
| `logo.png` | Logo oficial SaveInMed |
|
||||||
|
|
||||||
|
### Cores da Marca (Tailwind)
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// tailwind.config.ts
|
||||||
|
colors: {
|
||||||
|
healthGreen: '#2D9CDB', // Azul claro
|
||||||
|
medicalBlue: '#0F4C81' // Azul escuro (cor principal)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## 🧪 Testes
|
## 🧪 Testes
|
||||||
|
|
||||||
O projeto utiliza **Vitest** para testes unitários:
|
O projeto utiliza **Vitest** para testes unitários:
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,10 @@
|
||||||
<html lang="pt-BR">
|
<html lang="pt-BR">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
<link rel="icon" type="image/png" href="/src/assets/logo.png" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Marketplace Farmacêutico B2B</title>
|
<meta name="description" content="SaveInMed - Marketplace B2B Farmacêutico. Conectando farmácias e distribuidoras." />
|
||||||
|
<title>SaveInMed - Marketplace Farmacêutico B2B</title>
|
||||||
</head>
|
</head>
|
||||||
<body class="bg-gray-100">
|
<body class="bg-gray-100">
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
|
|
|
||||||
BIN
marketplace/src/assets/logo.png
Normal file
BIN
marketplace/src/assets/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
|
|
@ -91,11 +91,11 @@ export function Shell({ children }: { children: React.ReactNode }) {
|
||||||
<div className="min-h-screen bg-gray-100">
|
<div className="min-h-screen bg-gray-100">
|
||||||
<header className="flex items-center justify-between bg-medicalBlue px-6 py-4 text-white shadow-md">
|
<header className="flex items-center justify-between bg-medicalBlue px-6 py-4 text-white shadow-md">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<div className="h-10 w-10 rounded-full bg-white/10 text-center text-xl font-bold leading-10">MP</div>
|
<img src="/src/assets/logo.png" alt="SaveInMed" className="h-10 w-auto" />
|
||||||
<div>
|
<div>
|
||||||
<p className="text-lg font-semibold">Marketplace Farmacêutico B2B</p>
|
<p className="text-lg font-semibold">SaveInMed</p>
|
||||||
<p className="text-sm text-gray-100">
|
<p className="text-sm text-gray-100">
|
||||||
{isAdmin ? 'Painel Administrativo' : isOwner ? 'Painel do Dono' : 'Dashboard'}
|
{isAdmin ? 'Painel Administrativo' : isOwner ? 'Painel do Dono' : 'Marketplace B2B'}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,18 @@ Microserviço utilitário para popular o banco de dados com dados de teste para
|
||||||
1. **REMOVE** todas as tabelas existentes (`companies`, `products`, `users`, etc.)
|
1. **REMOVE** todas as tabelas existentes (`companies`, `products`, `users`, etc.)
|
||||||
2. **RECRIA** as tabelas do zero.
|
2. **RECRIA** as tabelas do zero.
|
||||||
|
|
||||||
|
### Campos da Tabela `companies`
|
||||||
|
|
||||||
|
O seeder cria a tabela `companies` com os seguintes campos:
|
||||||
|
|
||||||
|
| Campo | Tipo | Descrição |
|
||||||
|
|-------|------|-----------|
|
||||||
|
| `phone` | TEXT | Telefone de contato |
|
||||||
|
| `operating_hours` | TEXT | Horário de funcionamento |
|
||||||
|
| `is_24_hours` | BOOLEAN | Se funciona 24h |
|
||||||
|
|
||||||
|
> Para schema completo, veja [docs/database-schema.md](../docs/database-schema.md)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🎯 Modos de Operação
|
## 🎯 Modos de Operação
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue