feat: Implement backend API and basic frontend structure
Adds initial backend API endpoints for fetching users and attendances, including basic filtering. Sets up the frontend routing with a layout component and includes placeholder pages for dashboard, users, and login. Refactors the README for local development setup.
This commit is contained in:
173
constants.ts
Normal file
173
constants.ts
Normal file
@@ -0,0 +1,173 @@
|
||||
|
||||
import { Attendance, FunnelStage, Tenant, User } from './types';
|
||||
|
||||
export const CURRENT_TENANT_ID = 'tenant_123';
|
||||
|
||||
export const TENANTS: Tenant[] = [
|
||||
{
|
||||
id: 'tenant_123',
|
||||
name: 'Fasto Corp',
|
||||
slug: 'fasto',
|
||||
admin_email: 'admin@fasto.com',
|
||||
status: 'active',
|
||||
user_count: 12,
|
||||
attendance_count: 1450,
|
||||
created_at: '2023-01-15T10:00:00Z'
|
||||
},
|
||||
{
|
||||
id: 'tenant_456',
|
||||
name: 'Acme Inc',
|
||||
slug: 'acme-inc',
|
||||
admin_email: 'contact@acme.com',
|
||||
status: 'trial',
|
||||
user_count: 5,
|
||||
attendance_count: 320,
|
||||
created_at: '2023-06-20T14:30:00Z'
|
||||
},
|
||||
{
|
||||
id: 'tenant_789',
|
||||
name: 'Globex Utils',
|
||||
slug: 'globex',
|
||||
admin_email: 'sysadmin@globex.com',
|
||||
status: 'inactive',
|
||||
user_count: 2,
|
||||
attendance_count: 45,
|
||||
created_at: '2022-11-05T09:15:00Z'
|
||||
},
|
||||
{
|
||||
id: 'tenant_101',
|
||||
name: 'Soylent Green',
|
||||
slug: 'soylent',
|
||||
admin_email: 'admin@soylent.com',
|
||||
status: 'active',
|
||||
user_count: 25,
|
||||
attendance_count: 5600,
|
||||
created_at: '2023-02-10T11:20:00Z'
|
||||
},
|
||||
];
|
||||
|
||||
export const USERS: User[] = [
|
||||
{
|
||||
id: 'sa1',
|
||||
tenant_id: 'system',
|
||||
name: 'Super Administrator',
|
||||
email: 'root@system.com',
|
||||
role: 'super_admin',
|
||||
team_id: '',
|
||||
avatar_url: 'https://ui-avatars.com/api/?name=Super+Admin&background=0f172a&color=fff',
|
||||
bio: 'Administrador do Sistema Global',
|
||||
status: 'active'
|
||||
},
|
||||
{
|
||||
id: 'u1',
|
||||
tenant_id: 'tenant_123',
|
||||
name: 'Lidya Chan',
|
||||
email: 'lidya@fasto.com',
|
||||
role: 'manager',
|
||||
team_id: 'sales_1',
|
||||
avatar_url: 'https://picsum.photos/id/1011/200/200',
|
||||
bio: 'Gerente de Vendas com mais de 10 anos de experiência em SaaS. Apaixonada por construção de equipes e crescimento de receita.',
|
||||
status: 'active'
|
||||
},
|
||||
{
|
||||
id: 'u2',
|
||||
tenant_id: 'tenant_123',
|
||||
name: 'Alex Noer',
|
||||
email: 'alex@fasto.com',
|
||||
role: 'agent',
|
||||
team_id: 'sales_1',
|
||||
avatar_url: 'https://picsum.photos/id/1012/200/200',
|
||||
bio: 'Melhor desempenho no Q3. Focado em clientes corporativos e relacionamentos de longo prazo.',
|
||||
status: 'active'
|
||||
},
|
||||
{
|
||||
id: 'u3',
|
||||
tenant_id: 'tenant_123',
|
||||
name: 'Angela Moss',
|
||||
email: 'angela@fasto.com',
|
||||
role: 'agent',
|
||||
team_id: 'sales_1',
|
||||
avatar_url: 'https://picsum.photos/id/1013/200/200',
|
||||
status: 'inactive'
|
||||
},
|
||||
{
|
||||
id: 'u4',
|
||||
tenant_id: 'tenant_123',
|
||||
name: 'Brian Samuel',
|
||||
email: 'brian@fasto.com',
|
||||
role: 'agent',
|
||||
team_id: 'sales_2',
|
||||
avatar_url: 'https://picsum.photos/id/1014/200/200',
|
||||
status: 'active'
|
||||
},
|
||||
{
|
||||
id: 'u5',
|
||||
tenant_id: 'tenant_123',
|
||||
name: 'Benny Chagur',
|
||||
email: 'benny@fasto.com',
|
||||
role: 'agent',
|
||||
team_id: 'sales_2',
|
||||
avatar_url: 'https://picsum.photos/id/1025/200/200',
|
||||
status: 'active'
|
||||
},
|
||||
];
|
||||
|
||||
const generateMockAttendances = (count: number): Attendance[] => {
|
||||
const origins = ['WhatsApp', 'Instagram', 'Website', 'LinkedIn', 'Referral'] as const;
|
||||
const stages = Object.values(FunnelStage);
|
||||
const products = ['Plano Premium', 'Plano Básico', 'Suíte Enterprise', 'Consultoria'];
|
||||
|
||||
return Array.from({ length: count }).map((_, i) => {
|
||||
const user = USERS.slice(1)[Math.floor(Math.random() * (USERS.length - 1))]; // Skip super admin
|
||||
const rand = Math.random();
|
||||
// Weighted stages for realism
|
||||
let stage = FunnelStage.IDENTIFICATION;
|
||||
let isConverted = false;
|
||||
|
||||
if (rand > 0.85) {
|
||||
stage = FunnelStage.WON;
|
||||
isConverted = true;
|
||||
} else if (rand > 0.7) {
|
||||
stage = FunnelStage.LOST;
|
||||
} else if (rand > 0.5) {
|
||||
stage = FunnelStage.NEGOTIATION;
|
||||
} else if (rand > 0.2) {
|
||||
stage = FunnelStage.IDENTIFICATION;
|
||||
} else {
|
||||
stage = FunnelStage.NO_CONTACT;
|
||||
}
|
||||
|
||||
// Force won/lost logic consistency
|
||||
if (stage === FunnelStage.WON) isConverted = true;
|
||||
|
||||
return {
|
||||
id: `att_${i}`,
|
||||
tenant_id: 'tenant_123',
|
||||
user_id: user.id,
|
||||
created_at: new Date(Date.now() - Math.floor(Math.random() * 60 * 24 * 60 * 60 * 1000)).toISOString(),
|
||||
summary: "Cliente perguntou sobre detalhes do produto e níveis de preços.",
|
||||
attention_points: Math.random() > 0.8 ? ["Resposta demorada", "Verificar tom de voz"] : [],
|
||||
improvement_points: ["Sugerir plano anual", "Fazer follow-up mais cedo"],
|
||||
score: Math.floor(Math.random() * (100 - 50) + 50),
|
||||
first_response_time_min: Math.floor(Math.random() * 120),
|
||||
handling_time_min: Math.floor(Math.random() * 45),
|
||||
funnel_stage: stage,
|
||||
origin: origins[Math.floor(Math.random() * origins.length)],
|
||||
product_requested: products[Math.floor(Math.random() * products.length)],
|
||||
product_sold: isConverted ? products[Math.floor(Math.random() * products.length)] : undefined,
|
||||
converted: isConverted,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
export const MOCK_ATTENDANCES = generateMockAttendances(300);
|
||||
|
||||
// Visual Constants
|
||||
export const COLORS = {
|
||||
primary: '#facc15', // Yellow-400
|
||||
secondary: '#1e293b', // Slate-800
|
||||
success: '#22c55e',
|
||||
warning: '#f59e0b',
|
||||
danger: '#ef4444',
|
||||
charts: ['#3b82f6', '#10b981', '#6366f1', '#f59e0b', '#ec4899', '#8b5cf6'],
|
||||
};
|
||||
Reference in New Issue
Block a user