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:
773
docs/instrucoes-design.md
Normal file
773
docs/instrucoes-design.md
Normal 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! 🎯**
|
||||
238
docs/instrucoes-gerais.md
Normal file
238
docs/instrucoes-gerais.md
Normal file
@@ -0,0 +1,238 @@
|
||||
# 📱 TASK MANAGER - Plano de Desenvolvimento
|
||||
|
||||
## 🎯 Objetivo
|
||||
|
||||
Criar uma aplicação **multi-plataforma sincronizada em tempo real** de gerenciamento de tarefas para estudar desenvolvimento fullstack moderno com TypeScript.
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ Stack Tecnológica
|
||||
|
||||
### Backend
|
||||
- **NestJS** - Framework Node.js com TypeScript
|
||||
- **Supabase** (`https://supabase.stackbackup.cloud`) - PostgreSQL + Auth + Realtime
|
||||
- **PostgreSQL** - Banco de dados relacional
|
||||
- **Docker** - Containerização
|
||||
|
||||
### Frontend Web
|
||||
- **Next.js 14** - Framework React com App Router
|
||||
- **TailwindCSS** - Framework CSS utility-first
|
||||
- **TypeScript** - Linguagem principal
|
||||
- **Supabase Client** - Cliente JavaScript
|
||||
|
||||
### Mobile
|
||||
- **Flutter** - Framework multi-plataforma (Android/iOS)
|
||||
- **Dart** - Linguagem do Flutter
|
||||
- **Provider** - State management
|
||||
- **Supabase Flutter** - Cliente Dart
|
||||
|
||||
### Ferramentas
|
||||
- **Git/GitHub** - Controle de versão
|
||||
- **VS Code** - IDE
|
||||
|
||||
---
|
||||
|
||||
## 📋 Funcionalidades (MVP)
|
||||
|
||||
### Autenticação
|
||||
- [ ] Cadastro de usuário (email + senha)
|
||||
- [ ] Login
|
||||
- [ ] Logout
|
||||
- [ ] Recuperação de senha
|
||||
- [ ] Sessão persistente
|
||||
|
||||
### Gerenciamento de Tarefas (CRUD)
|
||||
- [ ] Criar tarefa (título + descrição opcional)
|
||||
- [ ] Listar tarefas do usuário
|
||||
- [ ] Marcar como concluída/pendente
|
||||
- [ ] Editar tarefa
|
||||
- [ ] Deletar tarefa
|
||||
- [ ] Filtrar (Todas/Ativas/Concluídas)
|
||||
|
||||
### Sincronização em Tempo Real
|
||||
- [ ] Supabase Realtime (WebSockets)
|
||||
- [ ] Sincronização instantânea entre web e mobile
|
||||
- [ ] Atualização automática em múltiplos dispositivos
|
||||
|
||||
---
|
||||
|
||||
## 🗄️ Banco de Dados
|
||||
|
||||
### Tabela: `tasks`
|
||||
```
|
||||
id (UUID) - Chave primária
|
||||
user_id (UUID) - Referência ao usuário (RLS habilitado)
|
||||
title (TEXT) - Título da tarefa
|
||||
description (TEXT) - Descrição opcional
|
||||
completed (BOOLEAN) - Status da tarefa
|
||||
created_at (TIMESTAMP) - Data de criação
|
||||
updated_at (TIMESTAMP) - Data de atualização
|
||||
```
|
||||
|
||||
### Segurança
|
||||
- Row Level Security (RLS) habilitado
|
||||
- Usuário só acessa suas próprias tarefas
|
||||
|
||||
---
|
||||
|
||||
## 📦 Estrutura do Projeto
|
||||
|
||||
```
|
||||
task-manager/
|
||||
├── backend/
|
||||
│ ├── src/
|
||||
│ │ ├── auth/
|
||||
│ │ ├── tasks/
|
||||
│ │ ├── common/
|
||||
│ │ └── main.ts
|
||||
│ ├── .env
|
||||
│ ├── Dockerfile
|
||||
│ └── package.json
|
||||
├── frontend-web/
|
||||
│ ├── src/
|
||||
│ │ ├── app/
|
||||
│ │ ├── components/
|
||||
│ │ ├── lib/
|
||||
│ │ └── styles/
|
||||
│ ├── .env.local
|
||||
│ └── next.config.js
|
||||
├── mobile/
|
||||
│ ├── lib/
|
||||
│ │ ├── models/
|
||||
│ │ ├── services/
|
||||
│ │ ├── screens/
|
||||
│ │ ├── widgets/
|
||||
│ │ └── main.dart
|
||||
│ └── pubspec.yaml
|
||||
├── docker-compose.yml
|
||||
└── README.md
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Roadmap de Desenvolvimento
|
||||
|
||||
### Fase 1: Backend (NestJS + Supabase)
|
||||
- [ ] Configurar projeto NestJS com TypeScript
|
||||
- [ ] Integrar Supabase SDK
|
||||
- [ ] Criar módulo de Autenticação
|
||||
- [ ] Criar módulo de Tarefas
|
||||
- [ ] Implementar RLS no banco
|
||||
- [ ] Documentar API
|
||||
- [ ] Dockerfile para backend
|
||||
|
||||
### Fase 2: Frontend Web (Next.js)
|
||||
- [ ] Criar projeto Next.js 14
|
||||
- [ ] Configurar Supabase Client
|
||||
- [ ] Implementar layout e componentes
|
||||
- [ ] Integrar autenticação
|
||||
- [ ] Criar páginas de tarefas
|
||||
- [ ] Implementar Realtime
|
||||
- [ ] Responsividade com Tailwind
|
||||
- [ ] Dockerfile para frontend
|
||||
|
||||
### Fase 3: Mobile (Flutter)
|
||||
- [ ] Criar projeto Flutter
|
||||
- [ ] Integrar Supabase Flutter SDK
|
||||
- [ ] Implementar autenticação
|
||||
- [ ] Criar telas de tarefas
|
||||
- [ ] State management com Provider
|
||||
- [ ] Sincronização em tempo real
|
||||
- [ ] Build para Android e iOS
|
||||
|
||||
### Fase 4: DevOps e Deploy
|
||||
- [ ] Docker Compose para local
|
||||
- [ ] CI/CD pipeline
|
||||
- [ ] Deploy backend (Railway/Render)
|
||||
- [ ] Deploy frontend (Vercel)
|
||||
- [ ] Deploy mobile (App Store/Play Store)
|
||||
|
||||
---
|
||||
|
||||
## 📚 Conhecimentos a Adquirir
|
||||
|
||||
### TypeScript
|
||||
- [ ] Tipos básicos e avançados
|
||||
- [ ] Interfaces e tipos genéricos
|
||||
- [ ] Decoradores (usado no NestJS)
|
||||
|
||||
### NestJS
|
||||
- [ ] Módulos e Providers
|
||||
- [ ] Controllers e Services
|
||||
- [ ] Middleware e Guards
|
||||
- [ ] Integração com banco de dados
|
||||
|
||||
### Supabase
|
||||
- [ ] Row Level Security (RLS)
|
||||
- [ ] Autenticação com JWT
|
||||
- [ ] Realtime Subscriptions
|
||||
- [ ] Migrations SQL
|
||||
|
||||
### Next.js 14
|
||||
- [ ] App Router vs Pages Router
|
||||
- [ ] Server Components e Client Components
|
||||
- [ ] API Routes
|
||||
- [ ] Deployment na Vercel
|
||||
|
||||
### Flutter
|
||||
- [ ] Widgets e layouts
|
||||
- [ ] State management (Provider)
|
||||
- [ ] HTTP client
|
||||
- [ ] Navegação
|
||||
|
||||
---
|
||||
|
||||
## ⚙️ Variáveis de Ambiente
|
||||
|
||||
### Backend (.env)
|
||||
```
|
||||
SUPABASE_URL=https://supabase.stackbackup.cloud
|
||||
SUPABASE_KEY=[SUPABASE_ANON_KEY]
|
||||
JWT_SECRET=[SEU_JWT_SECRET]
|
||||
DATABASE_URL=[CONNECTION_STRING]
|
||||
```
|
||||
|
||||
### Frontend Web (.env.local)
|
||||
```
|
||||
NEXT_PUBLIC_SUPABASE_URL=https://supabase.stackbackup.cloud
|
||||
NEXT_PUBLIC_SUPABASE_ANON_KEY=[SUPABASE_ANON_KEY]
|
||||
```
|
||||
|
||||
### Mobile (flutter_dotenv)
|
||||
```
|
||||
SUPABASE_URL=https://supabase.stackbackup.cloud
|
||||
SUPABASE_ANON_KEY=[SUPABASE_ANON_KEY]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔗 Referências Úteis
|
||||
|
||||
- **Supabase**: https://supabase.stackbackup.cloud
|
||||
- **NestJS Docs**: https://docs.nestjs.com
|
||||
- **Next.js Docs**: https://nextjs.org/docs
|
||||
- **Flutter Docs**: https://flutter.dev/docs
|
||||
- **Supabase Flutter**: https://supabase.com/docs/reference/flutter/introduction
|
||||
|
||||
---
|
||||
|
||||
## ✅ Checklist de Início
|
||||
|
||||
- [ ] Criar repositório GitHub
|
||||
- [ ] Clonar e configurar localmente
|
||||
- [ ] Testar acesso ao Supabase
|
||||
- [ ] Instalar dependências
|
||||
- [ ] Executar docker-compose
|
||||
- [ ] Rodar servidor local
|
||||
- [ ] Validar fluxo de autenticação
|
||||
|
||||
---
|
||||
|
||||
## 📌 Próximos Passos
|
||||
|
||||
1. **Hoje**: Revisar este plano
|
||||
2. **Amanhã**: Começar pelo Backend (NestJS)
|
||||
3. **Depois**: Frontend Web (Next.js)
|
||||
4. **Então**: Mobile (Flutter)
|
||||
|
||||
Tudo em TypeScript, tudo integrado, tudo em tempo real! 🔥
|
||||
Reference in New Issue
Block a user