feat: add domain models and repositories for user, spool presets, and filaments
- Introduced SpoolPreset and User domain models with necessary DTOs and utility functions. - Created AuthRepository, FilamentRepository, and SpoolPresetRepository interfaces for authentication and data management. - Implemented UI components for filament display, including ColorSwatch, FilamentCard, and StockBar. - Developed layout components such as Header and Screen for consistent app structure. - Added reusable UI components like Badge, Button, Card, and Input for better user interaction. - Established global constants and theme settings for consistent styling across the application. - Implemented utility functions for filament calculations and formatting. - Created Zustand stores for managing authentication, filament, and preset states. - Configured TypeScript settings for improved development experience.
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Dados agregados do dashboard.
|
||||
* Construído a partir dos filamentos do usuário.
|
||||
*/
|
||||
export interface DashboardData {
|
||||
totalStockKg: number;
|
||||
lowStockCount: number;
|
||||
byMaterial: MaterialSummary[];
|
||||
lowStockFilaments: LowStockFilament[];
|
||||
recentFilaments: RecentFilament[];
|
||||
}
|
||||
|
||||
export interface MaterialSummary {
|
||||
material: string;
|
||||
count: number;
|
||||
totalKg: number;
|
||||
}
|
||||
|
||||
export interface LowStockFilament {
|
||||
id: string;
|
||||
name: string; // ex: "PETG White"
|
||||
brand: string;
|
||||
material: string;
|
||||
netWeightG: number;
|
||||
percentage: number;
|
||||
colorHex: string;
|
||||
}
|
||||
|
||||
export interface RecentFilament {
|
||||
id: string;
|
||||
name: string;
|
||||
brand: string;
|
||||
material: string;
|
||||
netWeightG: number;
|
||||
percentage: number;
|
||||
colorHex: string;
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
import type { Material } from '@shared/constants';
|
||||
|
||||
/**
|
||||
* Entidade de domínio: Filamento.
|
||||
*
|
||||
* Representa um rolo de filamento no inventário do usuário.
|
||||
* Esta é uma entidade pura — sem dependências de UI, API ou banco de dados.
|
||||
*/
|
||||
export interface Filament {
|
||||
readonly id: string;
|
||||
readonly userId: string;
|
||||
material: Material;
|
||||
brand: string;
|
||||
model: string | null;
|
||||
colorHex: string;
|
||||
spoolPresetId: string;
|
||||
totalWeightG: number;
|
||||
netWeightG: number;
|
||||
tempHotendC: number | null;
|
||||
tempBedC: number | null;
|
||||
flowFactorPct: number | null;
|
||||
notes: string | null;
|
||||
readonly updatedAt: string; // ISO 8601 — usado no sync offline
|
||||
readonly createdAt: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* DTO para criação de um novo filamento.
|
||||
* Campos calculados (netWeightG) são omitidos — derivados no use case.
|
||||
*/
|
||||
export type CreateFilamentInput = Omit<Filament, 'id' | 'userId' | 'netWeightG' | 'createdAt' | 'updatedAt'>;
|
||||
|
||||
/**
|
||||
* DTO para atualização de um filamento existente.
|
||||
*/
|
||||
export type UpdateFilamentInput = Partial<CreateFilamentInput>;
|
||||
|
||||
/**
|
||||
* Filtros disponíveis na listagem de filamentos.
|
||||
*/
|
||||
export interface FilamentFilter {
|
||||
material?: Material;
|
||||
brand?: string;
|
||||
search?: string;
|
||||
stockLevel?: 'low' | 'medium' | 'ok';
|
||||
sortBy?: 'net_weight_asc' | 'net_weight_desc' | 'created_at_desc';
|
||||
page?: number;
|
||||
perPage?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calcula a porcentagem de filamento disponível em relação ao peso total
|
||||
* de um rolo cheio (1000g por convenção).
|
||||
*/
|
||||
export function calcFilamentPercentage(filament: Filament): number {
|
||||
const base = 1000;
|
||||
return Math.min(100, Math.max(0, Math.round((filament.netWeightG / base) * 100)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calcula o peso líquido dado o peso total e o peso do carretel vazio.
|
||||
*/
|
||||
export function calcNetWeight(totalWeightG: number, spoolWeightG: number): number {
|
||||
return Math.max(0, totalWeightG - spoolWeightG);
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Entidade de domínio: Preset de Carretel.
|
||||
*
|
||||
* Representa o peso do carretel vazio de uma marca/modelo.
|
||||
* Presets do sistema (isSystem = true) são somente leitura.
|
||||
*/
|
||||
export interface SpoolPreset {
|
||||
readonly id: string;
|
||||
name: string;
|
||||
spoolWeightG: number;
|
||||
readonly isSystem: boolean;
|
||||
readonly userId: string | null; // null para presets do sistema
|
||||
readonly createdAt: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* DTO para criação de um preset customizado.
|
||||
*/
|
||||
export type CreateSpoolPresetInput = Pick<SpoolPreset, 'name' | 'spoolWeightG'>;
|
||||
|
||||
/**
|
||||
* DTO para atualização de um preset customizado.
|
||||
*/
|
||||
export type UpdateSpoolPresetInput = Partial<CreateSpoolPresetInput>;
|
||||
|
||||
/**
|
||||
* Guard: retorna true se o preset pode ser editado/deletado pelo usuário.
|
||||
*/
|
||||
export function isUserOwnedPreset(preset: SpoolPreset): boolean {
|
||||
return !preset.isSystem && preset.userId !== null;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* Entidade de domínio: Usuário.
|
||||
*
|
||||
* Representa o usuário autenticado na sessão.
|
||||
*/
|
||||
export interface User {
|
||||
readonly id: string;
|
||||
email: string;
|
||||
name: string | null;
|
||||
readonly googleId: string | null;
|
||||
readonly createdAt: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sessão de autenticação persistida localmente.
|
||||
*/
|
||||
export interface AuthSession {
|
||||
readonly accessToken: string;
|
||||
readonly refreshToken: string;
|
||||
readonly user: User;
|
||||
}
|
||||
|
||||
/**
|
||||
* DTO para login com e-mail/senha.
|
||||
*/
|
||||
export interface LoginInput {
|
||||
email: string;
|
||||
password: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* DTO para cadastro.
|
||||
*/
|
||||
export interface RegisterInput {
|
||||
email: string;
|
||||
password: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* DTO para autenticação via OAuth Google.
|
||||
*/
|
||||
export interface GoogleOAuthInput {
|
||||
idToken: string;
|
||||
}
|
||||
Reference in New Issue
Block a user