initial: Backend Auth Module + Design System + Complete Documentation

- Setup NestJS with TypeScript, ConfigModule, JWT authentication
- Implemented Auth Module with signup, login, logout endpoints
- Created DTOs with validation (SignupDto, LoginDto)
- JWT Strategy with Passport integration for token validation
- JwtAuthGuard for route protection with Bearer tokens
- CurrentUser decorator for dependency injection
- Supabase integration for user management and auth
- Complete API documentation (API.md) with all endpoints
- Design System for Web (Next.js + Tailwind) and Mobile (Flutter)
- Comprehensive project documentation and roadmap
- Environment configuration with Joi schema validation
- Ready for Tasks Module and RLS implementation
This commit is contained in:
Erik Silva
2025-12-01 01:17:00 -03:00
commit 35272b8f87
56 changed files with 20691 additions and 0 deletions

773
docs/instrucoes-design.md Normal file
View File

@@ -0,0 +1,773 @@
# 🎨 TASK MANAGER - Design System & Guia de Interface
## 🌈 Paleta de Cores
### Cores Principais
- **Primary (Azul)**: `#2563EB` - Ações principais, links, seleção
- **Primary Dark**: `#1D4ED8` - Estados hover/ativo
- **Primary Light**: `#DBEAFE` - Backgrounds, estados desabilitados
- **White**: `#FFFFFF` - Backgrounds principal
- **Black**: `#000000` - Texto principal, contrastes fortes
- **Gray 50**: `#F9FAFB` - Backgrounds secundários
- **Gray 100**: `#F3F4F6` - Borders leves
- **Gray 200**: `#E5E7EB` - Borders padrão
- **Gray 400**: `#9CA3AF` - Texto secundário, placeholders
- **Gray 600**: `#4B5563` - Texto terciário
### Cores de Status
- **Success**: `#10B981` - Tarefas concluídas
- **Warning**: `#F59E0B` - Alertas
- **Error**: `#EF4444` - Erros, deletar
- **Info**: `#06B6D4` - Informações
---
## 🔤 Tipografia (Google Fonts)
### Fonte Principal: **Inter**
- Link: https://fonts.google.com/specimen/Inter
- Uso: Corpo de texto, UI, labels
### Fonte Secundária: **Poppins**
- Link: https://fonts.google.com/specimen/Poppins
- Uso: Títulos, headings, destaque
### Escala Tipográfica
| Nome | Tamanho | Weight | Line Height | Letra-espaçamento | Uso |
|------|---------|--------|-------------|------------------|-----|
| **H1** | 32px | 700 (Bold) | 40px | -0.5px | Títulos principais |
| **H2** | 24px | 700 (Bold) | 32px | -0.3px | Subtítulos |
| **H3** | 18px | 600 (SemiBold) | 28px | -0.2px | Seções |
| **Body Large** | 16px | 400 (Regular) | 24px | 0px | Texto principal |
| **Body Normal** | 14px | 400 (Regular) | 22px | 0px | Descrições |
| **Body Small** | 12px | 400 (Regular) | 18px | 0.2px | Ajuda, captions |
| **Label** | 12px | 600 (SemiBold) | 18px | 0.5px | Labels de campos |
| **Button** | 14px | 600 (SemiBold) | 20px | 0.5px | Texto de botões |
### Importação no CSS/Next.js
```css
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Poppins:wght@600;700&display=swap');
:root {
--font-inter: 'Inter', sans-serif;
--font-poppins: 'Poppins', sans-serif;
}
```
---
## 🎯 Espaçamento (8px Base)
Seguindo o padrão Material Design + Tailwind, usando múltiplos de 8px:
| Token | Valor | Uso |
|-------|-------|-----|
| **xs** | 4px | Micro-espaçamentos |
| **sm** | 8px | Padding pequeno |
| **md** | 12px | Padding padrão |
| **lg** | 16px | Espaçamento interno |
| **xl** | 24px | Separação entre elementos |
| **2xl** | 32px | Separação entre seções |
| **3xl** | 48px | Grandes divisores |
| **4xl** | 64px | Muito grandes |
### Exemplos de Aplicação
- **Padding de Botão**: 12px (vertical) × 16px (horizontal)
- **Padding de Card**: 24px
- **Gap entre inputs**: 16px
- **Margin entre seções**: 32px
---
## 🎨 Componentes - Design System
### 1⃣ **BOTÕES**
#### Botão Primary (Padrão)
```
Tamanho: 48px altura
Padding: 12px vertical × 16px horizontal
Background: #2563EB
Text: White, 14px Bold
Border Radius: 8px
Font Weight: 600
```
**Estados:**
- **Default**: Background #2563EB
- **Hover**: Background #1D4ED8, Sombra leve
- **Active**: Background #1D4ED8, sem sombra
- **Disabled**: Background #E5E7EB, Text #9CA3AF, sem cursor
#### Botão Secondary
```
Background: #F3F4F6
Text: #000000, 14px Bold
Border: 1px #E5E7EB
Border Radius: 8px
```
#### Botão Tertiary (Text only)
```
Background: transparent
Text: #2563EB, 14px Bold
Padding: 12px 16px
```
#### Botão Danger
```
Background: #EF4444
Text: White, 14px Bold
Sombra: 0px 4px 12px rgba(239, 68, 68, 0.2)
```
#### Botão com Ícone
```
Spacing entre ícone e texto: 8px
Ícone tamanho: 20px × 20px
```
---
### 2⃣ **CAMPOS DE ENTRADA (Inputs)**
#### Input Padrão
```
Altura: 44px
Padding: 12px 16px
Border: 1px #E5E7EB
Border Radius: 8px
Font: Inter 14px
Background: #FFFFFF
```
**Estados:**
- **Default**: Border #E5E7EB, Background #FFFFFF
- **Focus**: Border #2563EB (2px), Background #FFFFFF, Box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1)
- **Filled**: Border #2563EB
- **Error**: Border #EF4444, Background #FEF2F2
- **Disabled**: Border #E5E7EB, Background #F9FAFB, Text #9CA3AF
#### Placeholder
```
Color: #9CA3AF
Font Style: Regular
```
#### Label
```
Font: Poppins 12px SemiBold
Color: #000000
Margin Bottom: 8px
Required indicator (*): Color #EF4444
```
#### Help Text
```
Font: Inter 12px Regular
Color: #6B7280
Margin Top: 4px
```
#### Error Message
```
Font: Inter 12px Regular
Color: #EF4444
Icon: 16px × 16px (⚠️)
Margin Top: 4px
```
---
### 3⃣ **CARDS**
```
Background: #FFFFFF
Border: 1px #E5E7EB
Border Radius: 12px
Padding: 24px
Box Shadow: 0px 1px 3px rgba(0, 0, 0, 0.1)
```
**Hover (Interactive):**
```
Box Shadow: 0px 4px 12px rgba(0, 0, 0, 0.08)
Transition: 150ms
```
#### Task Card
```
Padding: 16px
Border Radius: 12px
Background: #FFFFFF
Border: 1px #E5E7EB
Estrutura:
├── Checkbox (20px × 20px)
├── Conteúdo (Flex: 1)
│ ├── Título: 14px Bold, #000000
│ └── Descrição: 13px Regular, #6B7280
└── Menu/Delete: 24px × 24px (Right)
Spacing: 12px entre elementos
```
---
### 4⃣ **CHECKBOX & RADIO**
#### Checkbox
```
Tamanho: 20px × 20px
Border: 2px #E5E7EB
Border Radius: 4px
Background: #FFFFFF
Padding: 2px (interno)
```
**Estados:**
- **Unchecked**: Border #E5E7EB, Background #FFFFFF
- **Checked**: Border #2563EB, Background #2563EB, Ícone ✓ branco
- **Focus**: Box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1)
- **Disabled**: Border #E5E7EB, Background #F3F4F6
---
### 5⃣ **TABS**
```
Height: 48px
Font: Inter 14px SemiBold
Color: #6B7280 (inactive), #2563EB (active)
Border Bottom: 2px #2563EB (active)
Padding: 16px horizontal
```
---
### 6⃣ **MODALS/DIALOGS**
```
Background: #FFFFFF
Border Radius: 16px
Padding: 32px
Width: 90% (mobile), 520px (desktop)
Max Height: 90vh
Box Shadow: 0px 20px 25px rgba(0, 0, 0, 0.15)
Overlay: rgba(0, 0, 0, 0.5)
```
**Estrutura:**
```
├── Header
│ ├── Título: H2
│ └── Close button: 24px (top right)
├── Content
│ └── Padding: 24px 0
└── Footer (Actions)
├── Button Secondary (Cancel): Left
└── Button Primary (Confirm): Right
└── Spacing: 12px entre botões
```
---
### 7⃣ **ÍCONES (Google Icons)**
Link: https://fonts.google.com/icons
**Tamanhos Padrão:**
- **Small**: 16px - Lado de inputs, help text
- **Normal**: 20px - Ícones em botões, menus
- **Large**: 24px - Ícones principais, headers
- **XL**: 32px - Ícones de estado vazio, sucesso
**Cor Principal**: #2563EB
**Cor Secundária**: #6B7280
**Cor Erro**: #EF4444
**Ícones Recomendados:**
- check_circle (Concluído)
- radio_button_unchecked (Não concluído)
- delete (Deletar)
- edit (Editar)
- close (Fechar)
- menu (Menu)
- search (Buscar)
- add (Adicionar)
- logout (Sair)
- login (Entrar)
- person (Perfil)
- error (Erro)
- warning (Aviso)
- info (Info)
---
## 📱 **NEXT.JS - Estrutura de Componentes**
### Diretório
```
frontend-next/
├── src/
│ ├── components/
│ │ ├── ui/
│ │ │ ├── Button.tsx
│ │ │ ├── Input.tsx
│ │ │ ├── Card.tsx
│ │ │ ├── Checkbox.tsx
│ │ │ ├── Modal.tsx
│ │ │ ├── Toast.tsx
│ │ │ └── Spinner.tsx
│ │ ├── forms/
│ │ │ ├── TaskForm.tsx
│ │ │ ├── LoginForm.tsx
│ │ │ └── SignupForm.tsx
│ │ ├── tasks/
│ │ │ ├── TaskItem.tsx
│ │ │ ├── TaskList.tsx
│ │ │ └── TaskFilters.tsx
│ │ ├── layout/
│ │ │ ├── Header.tsx
│ │ │ ├── Sidebar.tsx
│ │ │ └── Footer.tsx
│ │ └── common/
│ │ ├── EmptyState.tsx
│ │ └── LoadingState.tsx
│ ├── lib/
│ │ ├── styles/
│ │ │ ├── colors.ts
│ │ │ ├── spacing.ts
│ │ │ ├── typography.ts
│ │ │ └── shadows.ts
│ │ └── utils.ts
│ ├── app/
│ │ ├── globals.css
│ │ ├── layout.tsx
│ │ ├── page.tsx
│ │ ├── (auth)/
│ │ │ ├── login/page.tsx
│ │ │ └── signup/page.tsx
│ │ └── (dashboard)/
│ │ └── tasks/page.tsx
│ └── styles/
│ └── tailwind.config.ts
```
### Configuração Tailwind (tailwind.config.ts)
```typescript
import type { Config } from 'tailwindcss'
export default {
content: [
'./src/pages/**/*.{js,ts,jsx,tsx,mdx}',
'./src/components/**/*.{js,ts,jsx,tsx,mdx}',
'./src/app/**/*.{js,ts,jsx,tsx,mdx}',
],
theme: {
extend: {
colors: {
primary: {
DEFAULT: '#2563EB',
dark: '#1D4ED8',
light: '#DBEAFE',
},
gray: {
50: '#F9FAFB',
100: '#F3F4F6',
200: '#E5E7EB',
400: '#9CA3AF',
600: '#4B5563',
},
status: {
success: '#10B981',
warning: '#F59E0B',
error: '#EF4444',
info: '#06B6D4',
},
},
fontFamily: {
inter: ['var(--font-inter)', 'sans-serif'],
poppins: ['var(--font-poppins)', 'sans-serif'],
},
fontSize: {
'h1': ['32px', { lineHeight: '40px', fontWeight: '700', letterSpacing: '-0.5px' }],
'h2': ['24px', { lineHeight: '32px', fontWeight: '700', letterSpacing: '-0.3px' }],
'h3': ['18px', { lineHeight: '28px', fontWeight: '600', letterSpacing: '-0.2px' }],
'body-lg': ['16px', { lineHeight: '24px', fontWeight: '400' }],
'body': ['14px', { lineHeight: '22px', fontWeight: '400' }],
'body-sm': ['12px', { lineHeight: '18px', fontWeight: '400', letterSpacing: '0.2px' }],
'label': ['12px', { lineHeight: '18px', fontWeight: '600', letterSpacing: '0.5px' }],
'btn': ['14px', { lineHeight: '20px', fontWeight: '600', letterSpacing: '0.5px' }],
},
spacing: {
'xs': '4px',
'sm': '8px',
'md': '12px',
'lg': '16px',
'xl': '24px',
'2xl': '32px',
'3xl': '48px',
'4xl': '64px',
},
borderRadius: {
'sm': '4px',
'md': '8px',
'lg': '12px',
'xl': '16px',
},
boxShadow: {
'sm': '0px 1px 3px rgba(0, 0, 0, 0.1)',
'md': '0px 4px 12px rgba(0, 0, 0, 0.08)',
'lg': '0px 20px 25px rgba(0, 0, 0, 0.15)',
'focus': '0 0 0 3px rgba(37, 99, 235, 0.1)',
},
},
},
plugins: [],
} satisfies Config
```
---
## 🚀 **FLUTTER - Design System**
### Diretório
```
mobile/
├── lib/
│ ├── config/
│ │ ├── theme.dart
│ │ ├── colors.dart
│ │ ├── typography.dart
│ │ └── spacing.dart
│ ├── widgets/
│ │ ├── buttons/
│ │ │ ├── primary_button.dart
│ │ │ ├── secondary_button.dart
│ │ │ └── tertiary_button.dart
│ │ ├── inputs/
│ │ │ ├── text_input.dart
│ │ │ ├── checkbox_input.dart
│ │ │ └── form_field.dart
│ │ ├── cards/
│ │ │ ├── task_card.dart
│ │ │ └── card.dart
│ │ ├── common/
│ │ │ ├── modal.dart
│ │ │ ├── empty_state.dart
│ │ │ └── loading_state.dart
│ │ └── app/
│ │ ├── app_bar.dart
│ │ └── bottom_nav.dart
│ ├── screens/
│ │ ├── auth/
│ │ │ ├── login_screen.dart
│ │ │ └── signup_screen.dart
│ │ ├── tasks/
│ │ │ ├── tasks_screen.dart
│ │ │ ├── task_detail_screen.dart
│ │ │ └── create_task_screen.dart
│ │ └── profile/
│ │ └── profile_screen.dart
│ └── main.dart
```
### Colors (colors.dart)
```dart
abstract class AppColors {
// Primary
static const Color primary = Color(0xFF2563EB);
static const Color primaryDark = Color(0xFF1D4ED8);
static const Color primaryLight = Color(0xFFDBEAFE);
// Base
static const Color white = Color(0xFFFFFFFF);
static const Color black = Color(0xFF000000);
// Gray
static const Color gray50 = Color(0xFFF9FAFB);
static const Color gray100 = Color(0xFFF3F4F6);
static const Color gray200 = Color(0xFFE5E7EB);
static const Color gray400 = Color(0xFF9CA3AF);
static const Color gray600 = Color(0xFF4B5563);
// Status
static const Color success = Color(0xFF10B981);
static const Color warning = Color(0xFFF59E0B);
static const Color error = Color(0xFFEF4444);
static const Color info = Color(0xFF06B6D4);
}
```
### Theme (theme.dart)
```dart
import 'package:flutter/material.dart';
import 'colors.dart';
final ThemeData appTheme = ThemeData(
useMaterial3: true,
colorScheme: ColorScheme(
brightness: Brightness.light,
primary: AppColors.primary,
onPrimary: AppColors.white,
secondary: AppColors.gray600,
onSecondary: AppColors.white,
error: AppColors.error,
onError: AppColors.white,
background: AppColors.white,
onBackground: AppColors.black,
surface: AppColors.white,
onSurface: AppColors.black,
),
fontFamily: 'Inter',
textTheme: TextTheme(
displayLarge: TextStyle(
fontSize: 32,
fontWeight: FontWeight.w700,
letterSpacing: -0.5,
fontFamily: 'Poppins',
),
displayMedium: TextStyle(
fontSize: 24,
fontWeight: FontWeight.w700,
letterSpacing: -0.3,
fontFamily: 'Poppins',
),
headlineSmall: TextStyle(
fontSize: 18,
fontWeight: FontWeight.w600,
letterSpacing: -0.2,
fontFamily: 'Poppins',
),
bodyLarge: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w400,
height: 1.5,
),
bodyMedium: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w400,
height: 1.57,
),
bodySmall: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w400,
letterSpacing: 0.2,
height: 1.5,
),
labelMedium: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w600,
letterSpacing: 0.5,
),
),
);
```
### Spacing (spacing.dart)
```dart
abstract class AppSpacing {
static const double xs = 4.0;
static const double sm = 8.0;
static const double md = 12.0;
static const double lg = 16.0;
static const double xl = 24.0;
static const double xxl = 32.0;
static const double xxxl = 48.0;
static const double xxxxl = 64.0;
}
```
### Exemplo de Componente - Primary Button
```dart
class PrimaryButton extends StatelessWidget {
final String label;
final VoidCallback onPressed;
final bool isLoading;
final bool isEnabled;
final IconData? icon;
const PrimaryButton({
required this.label,
required this.onPressed,
this.isLoading = false,
this.isEnabled = true,
this.icon,
});
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: isEnabled && !isLoading ? onPressed : null,
style: ElevatedButton.styleFrom(
backgroundColor: AppColors.primary,
disabledBackgroundColor: AppColors.gray200,
padding: EdgeInsets.symmetric(
vertical: AppSpacing.md,
horizontal: AppSpacing.lg,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
elevation: 0,
),
child: isLoading
? SizedBox(
height: 20,
width: 20,
child: CircularProgressIndicator(
strokeWidth: 2,
valueColor: AlwaysStoppedAnimation<Color>(
isEnabled ? AppColors.white : AppColors.gray400,
),
),
)
: Row(
mainAxisSize: MainAxisSize.min,
children: [
if (icon != null) ...[
Icon(icon, size: 20),
SizedBox(width: AppSpacing.sm),
],
Text(label),
],
),
);
}
}
```
---
## 🎯 **PADRÕES DE LAYOUT**
### Responsividade Next.js
```
Mobile: < 640px (default)
Tablet: 640px - 1024px
Desktop: > 1024px
```
### Breakpoints (Tailwind)
```typescript
sm: '640px'
md: '768px'
lg: '1024px'
xl: '1280px'
2xl: '1536px'
```
### Safe Area (Flutter)
```dart
Scaffold(
body: SafeArea(
child: SingleChildScrollView(
padding: EdgeInsets.all(AppSpacing.lg),
child: YourContent(),
),
),
)
```
---
## 📐 **ANIMAÇÕES & TRANSIÇÕES**
### Next.js (Tailwind)
```
Duration padrão: 150ms
Easing: cubic-bezier(0.4, 0, 0.2, 1)
Propriedades: transform, opacity, color, box-shadow
```
**Exemplo:**
```css
.button {
@apply transition-all duration-150 ease-in-out;
}
.button:hover {
@apply scale-105 shadow-md;
}
```
### Flutter
```dart
Duration animationDuration = Duration(milliseconds: 150);
Curve animationCurve = Curves.easeInOut;
```
---
## ✅ **ACESSIBILIDADE**
### Contraste de Cores (WCAG AA)
- Ratio mínimo: 4.5:1 para textos normais
- Ratio mínimo: 3:1 para textos grandes
### Next.js
- Usar `<label htmlFor="">` para inputs
- Alt text em imagens
- Semantic HTML (button, form, etc)
### Flutter
- Semantics widget para leitura de tela
- Sufficient touch targets (mínimo 48x48 dp)
---
## 📋 **CHECKLIST DE DESIGN**
- [ ] Cores aplicadas conforme paleta
- [ ] Tipografia usando Inter e Poppins
- [ ] Espaçamento em múltiplos de 8px
- [ ] Componentes com 4 estados (default, hover, active, disabled)
- [ ] Ícones do Google Icons (20px padrão)
- [ ] Botões com altura mínima de 48px
- [ ] Inputs com altura de 44px
- [ ] Cards com border-radius 12px
- [ ] Box shadows consistentes
- [ ] Responsive design funcional
- [ ] Acessibilidade testada
- [ ] Loading states em todas as ações
- [ ] Error states claros
- [ ] Empty states amigáveis
---
## 🔗 **REFERÊNCIAS & RECURSOS**
### Ferramentas
- **Figma**: Para prototipar (opcional)
- **Google Fonts**: https://fonts.google.com
- **Google Icons**: https://fonts.google.com/icons
- **Color Checker**: https://webaim.org/resources/contrastchecker/
### Documentação
- **Tailwind CSS**: https://tailwindcss.com/docs
- **Next.js**: https://nextjs.org/docs
- **Flutter**: https://flutter.dev/docs
- **Material Design 3**: https://m3.material.io/
---
## 💾 **IMPLEMENTAÇÃO IMEDIATA**
### Next.js - Setup Inicial
1. Configurar Tailwind config com tokens
2. Criar componentes base (Button, Input, Card)
3. Importar Google Fonts em globals.css
4. Testar componentes em storybook (opcional)
### Flutter - Setup Inicial
1. Adicionar Google Fonts package
2. Criar arquivos de theme
3. Implementar componentes customizados
4. Testar em multiple devices
---
**Mantém Fidelidade ao Design em TODAS as screens! 🎯**