456 lines
16 KiB
TypeScript
456 lines
16 KiB
TypeScript
import fs from 'fs';
|
|
import path from 'path';
|
|
import bcrypt from 'bcryptjs';
|
|
import { User, Course, Module, Lesson, Note, LessonProgress, WebhookLog, SubscriptionPayment, Plan } from '../types';
|
|
|
|
const DATA_DIR = process.env.DATA_DIR || (fs.existsSync('/app/data') ? '/app/data' : process.cwd());
|
|
const DB_FILE = path.join(DATA_DIR, 'database.json');
|
|
|
|
export interface DatabaseSchema {
|
|
users: User[];
|
|
courses: Course[];
|
|
modules: Module[];
|
|
lessons: Lesson[];
|
|
notes: Note[];
|
|
progress: LessonProgress[];
|
|
webhookLogs: WebhookLog[];
|
|
payments: SubscriptionPayment[];
|
|
activities: any[];
|
|
moduleGrades: any[];
|
|
certificates: any[];
|
|
notifications: any[];
|
|
settings: any; // SystemSettings
|
|
plans: Plan[];
|
|
}
|
|
|
|
const DEFAULT_DB: DatabaseSchema = {
|
|
users: [],
|
|
courses: [],
|
|
modules: [],
|
|
lessons: [],
|
|
notes: [],
|
|
progress: [],
|
|
webhookLogs: [],
|
|
payments: [],
|
|
activities: [],
|
|
moduleGrades: [],
|
|
certificates: [],
|
|
notifications: [],
|
|
settings: {
|
|
trialDurationDays: 7,
|
|
asaasEnvironment: 'sandbox',
|
|
asaasApiKey: '',
|
|
asaasWebhookUrl: '',
|
|
asaasWebhookSecret: '',
|
|
helpText: '# Central de Ajuda\n\nAqui você encontra todas as informações sobre os cursos e funcionamento da plataforma.'
|
|
},
|
|
plans: []
|
|
};
|
|
|
|
// Helper to load db
|
|
export function loadDb(): DatabaseSchema {
|
|
try {
|
|
if (!fs.existsSync(DB_FILE)) {
|
|
const db = createInitialDb();
|
|
saveDb(db);
|
|
return db;
|
|
}
|
|
const data = fs.readFileSync(DB_FILE, 'utf-8');
|
|
const parsedData = JSON.parse(data);
|
|
if (!parsedData.plans) {
|
|
parsedData.plans = [];
|
|
}
|
|
return parsedData;
|
|
} catch (err) {
|
|
console.error('Error loading database:', err);
|
|
return DEFAULT_DB;
|
|
}
|
|
}
|
|
|
|
// Helper to save db
|
|
export function saveDb(data: DatabaseSchema): void {
|
|
try {
|
|
fs.writeFileSync(DB_FILE, JSON.stringify(data, null, 2), 'utf-8');
|
|
} catch (err) {
|
|
console.error('Error saving database:', err);
|
|
}
|
|
}
|
|
|
|
function createInitialDb(): DatabaseSchema {
|
|
const salt = bcrypt.genSaltSync(10);
|
|
const adminPasswordHash = bcrypt.hashSync('admin123', salt);
|
|
const studentPasswordHash = bcrypt.hashSync('aluno123', salt);
|
|
|
|
const now = new Date().toISOString();
|
|
|
|
const users: User[] = [
|
|
{
|
|
id: 'usr_admin',
|
|
name: 'Sidney Gomes (Admin)',
|
|
email: 'sidney.gomes1989@gmail.com',
|
|
password: adminPasswordHash,
|
|
role: 'admin',
|
|
subscriptionStatus: 'ACTIVE',
|
|
asaasCustomerId: null,
|
|
cpf: '691.238.910-40',
|
|
whatsapp: '11999999999',
|
|
birthDate: '1989-05-15',
|
|
unlockedCourses: [],
|
|
createdAt: now
|
|
},
|
|
{
|
|
id: 'usr_student1',
|
|
name: 'João Silva',
|
|
email: 'joao@microtecflix.com',
|
|
password: studentPasswordHash,
|
|
role: 'student',
|
|
subscriptionStatus: 'ACTIVE',
|
|
asaasCustomerId: 'cus_00001',
|
|
cpf: '691.238.910-40',
|
|
whatsapp: '11999999999',
|
|
birthDate: '1989-05-15',
|
|
unlockedCourses: ['crs_excel'], // Excel starts unlocked for Joao
|
|
createdAt: new Date(Date.now() - 30 * 24 * 3600 * 1000).toISOString()
|
|
},
|
|
{
|
|
id: 'usr_student2',
|
|
name: 'Maria Santos',
|
|
email: 'maria@microtecflix.com',
|
|
password: studentPasswordHash,
|
|
role: 'student',
|
|
subscriptionStatus: 'ACTIVE',
|
|
asaasCustomerId: 'cus_00002',
|
|
cpf: '691.238.910-40',
|
|
whatsapp: '11999999999',
|
|
birthDate: '1989-05-15',
|
|
unlockedCourses: [],
|
|
createdAt: new Date(Date.now() - 15 * 24 * 3600 * 1000).toISOString()
|
|
},
|
|
{
|
|
id: 'usr_student3',
|
|
name: 'Pedro Oliveira',
|
|
email: 'pedro@microtecflix.com',
|
|
password: studentPasswordHash,
|
|
role: 'student',
|
|
subscriptionStatus: 'OVERDUE',
|
|
asaasCustomerId: 'cus_00003',
|
|
cpf: '691.238.910-40',
|
|
whatsapp: '11999999999',
|
|
birthDate: '1989-05-15',
|
|
unlockedCourses: [],
|
|
createdAt: new Date(Date.now() - 45 * 24 * 3600 * 1000).toISOString()
|
|
},
|
|
{
|
|
id: 'usr_student4',
|
|
name: 'Ana Costa',
|
|
email: 'ana@microtecflix.com',
|
|
password: studentPasswordHash,
|
|
role: 'student',
|
|
subscriptionStatus: 'CANCELED',
|
|
asaasCustomerId: 'cus_00004',
|
|
cpf: '691.238.910-40',
|
|
whatsapp: '11999999999',
|
|
birthDate: '1989-05-15',
|
|
unlockedCourses: [],
|
|
createdAt: new Date(Date.now() - 60 * 24 * 3600 * 1000).toISOString()
|
|
},
|
|
{
|
|
id: 'usr_student_test',
|
|
name: 'Aluno de Teste',
|
|
email: 'aluno@microtecflix.com',
|
|
password: studentPasswordHash,
|
|
role: 'student',
|
|
subscriptionStatus: 'ACTIVE',
|
|
asaasCustomerId: 'cus_test',
|
|
cpf: '691.238.910-40',
|
|
whatsapp: '11999999999',
|
|
birthDate: '1989-05-15',
|
|
unlockedCourses: [], // Starts with only the free courses unlocked
|
|
createdAt: now
|
|
}
|
|
];
|
|
|
|
const courses: Course[] = [
|
|
{
|
|
id: 'crs_windows',
|
|
title: 'Sistema Operacional Windows 11 para Escritório',
|
|
description: 'Domine o sistema operacional mais utilizado no mundo corporativo. Aprenda a organizar arquivos, configurar o painel de controle, gerenciar usuários e utilizar ferramentas de produtividade para escritório de forma ágil e segura.',
|
|
thumbnail: 'https://images.unsplash.com/photo-1624555130581-1d9cca783bc0?q=80&w=600&auto=format&fit=crop',
|
|
category: 'Sistemas Operacionais',
|
|
isLocked: false,
|
|
price: 0,
|
|
createdAt: now
|
|
},
|
|
{
|
|
id: 'crs_word',
|
|
title: 'Microsoft Word Profissional',
|
|
description: 'Crie relatórios, contratos, trabalhos acadêmicos nas normas ABNT e documentos de escritório altamente profissionais. Domine formatação avançada, tabelas, sumários automáticos e malas diretas dinâmicas.',
|
|
thumbnail: 'https://images.unsplash.com/photo-1586075010923-2dd4570fb338?q=80&w=600&auto=format&fit=crop',
|
|
category: 'Pacote Office',
|
|
isLocked: false,
|
|
price: 0,
|
|
createdAt: now
|
|
},
|
|
{
|
|
id: 'crs_excel',
|
|
title: 'Microsoft Excel - Do Básico ao Dashboard',
|
|
description: 'O software de planilhas mais exigido pelo mercado de trabalho mundial. Aprenda desde fórmulas fundamentais (SOMA, SE, PROCV, CONT.SE) até tabelas dinâmicas, gráficos executivos, automações e dashboards de impacto profissional.',
|
|
thumbnail: 'https://images.unsplash.com/photo-1551288049-bebda4e38f71?q=80&w=600&auto=format&fit=crop',
|
|
category: 'Pacote Office',
|
|
isLocked: true,
|
|
price: 89.90,
|
|
createdAt: now
|
|
},
|
|
{
|
|
id: 'crs_powerpoint',
|
|
title: 'PowerPoint para Apresentações de Impacto',
|
|
description: 'Aprenda a estruturar e desenhar apresentações profissionais e persuasivas para reuniões de negócios, projetos ou aulas. Domine o efeito de transição Transformar (Morph), inserção de mídias inteligentes e animações profissionais.',
|
|
thumbnail: 'https://images.unsplash.com/photo-1516321318423-f06f85e504b3?q=80&w=600&auto=format&fit=crop',
|
|
category: 'Pacote Office',
|
|
isLocked: true,
|
|
price: 59.90,
|
|
createdAt: now
|
|
}
|
|
];
|
|
|
|
const modules: Module[] = [
|
|
// Windows 11
|
|
{ id: 'mdl_win_1', courseId: 'crs_windows', title: 'Fundamentos e Área de Trabalho', order: 1, createdAt: now },
|
|
{ id: 'mdl_win_2', courseId: 'crs_windows', title: 'Configurações e Segurança de Dados', order: 2, createdAt: now },
|
|
// Word
|
|
{ id: 'mdl_wrd_1', courseId: 'crs_word', title: 'Interface e Formatação de Textos', order: 1, createdAt: now },
|
|
{ id: 'mdl_wrd_2', courseId: 'crs_word', title: 'Layouts, Tabelas e Sumários', order: 2, createdAt: now },
|
|
// Excel
|
|
{ id: 'mdl_exc_1', courseId: 'crs_excel', title: 'Células, Fórmulas e Funções Principais', order: 1, createdAt: now },
|
|
{ id: 'mdl_exc_2', courseId: 'crs_excel', title: 'Tabelas Dinâmicas e Dashboards', order: 2, createdAt: now },
|
|
// PowerPoint
|
|
{ id: 'mdl_ppt_1', courseId: 'crs_powerpoint', title: 'Layout de Slides e Formas', order: 1, createdAt: now },
|
|
{ id: 'mdl_ppt_2', courseId: 'crs_powerpoint', title: 'Transições Especiais e Apresentação', order: 2, createdAt: now }
|
|
];
|
|
|
|
const lessons: Lesson[] = [
|
|
// Windows - Módulo 1
|
|
{
|
|
id: 'lsn_win_1_1',
|
|
moduleId: 'mdl_win_1',
|
|
title: 'Dominando a Nova Área de Trabalho e Barra de Tarefas do Windows 11',
|
|
videoUrl: 'https://www.youtube.com/embed/9e9D_bZfT8o',
|
|
videoType: 'youtube',
|
|
order: 1,
|
|
content: 'Nesta aula, você aprenderá a se localizar e customizar a nova barra de tarefas centralizada e a área de trabalho do Windows 11.',
|
|
createdAt: now
|
|
},
|
|
{
|
|
id: 'lsn_win_1_2',
|
|
moduleId: 'mdl_win_1',
|
|
title: 'Gerenciador de Arquivos e Organização Eficiente de Pastas',
|
|
videoUrl: 'https://www.youtube.com/embed/Pj1_bAn_m4Y',
|
|
videoType: 'youtube',
|
|
order: 2,
|
|
content: 'Aprenda a criar estruturas de pastas organizadas, atalhos rápidos e a usar o novo explorador de arquivos com abas do Windows.',
|
|
createdAt: now
|
|
},
|
|
// Windows - Módulo 2
|
|
{
|
|
id: 'lsn_win_2_1',
|
|
moduleId: 'mdl_win_2',
|
|
title: 'Painel de Configurações e Segurança com Windows Defender',
|
|
videoUrl: 'https://www.youtube.com/embed/K8w3m_pM6lA',
|
|
videoType: 'youtube',
|
|
order: 1,
|
|
content: 'Como configurar rede wi-fi, dispositivos bluetooth, impressoras e garantir que seu antivírus integrado esteja sempre atualizado.',
|
|
createdAt: now
|
|
},
|
|
|
|
// Word - Módulo 1
|
|
{
|
|
id: 'lsn_wrd_1_1',
|
|
moduleId: 'mdl_wrd_1',
|
|
title: 'Conhecendo a Faixa de Opções e Formatando Fontes e Parágrafos',
|
|
videoUrl: 'https://www.youtube.com/embed/Epn879GkIis',
|
|
videoType: 'youtube',
|
|
order: 1,
|
|
content: 'Entenda os principais comandos da guia Página Inicial e como aplicar formatações essenciais de texto.',
|
|
createdAt: now
|
|
},
|
|
// Word - Módulo 2
|
|
{
|
|
id: 'lsn_wrd_2_1',
|
|
moduleId: 'mdl_wrd_2',
|
|
title: 'Criação de Sumários Automáticos com Estilos de Título',
|
|
videoUrl: 'https://www.youtube.com/embed/2_W6C3vjD1s',
|
|
videoType: 'youtube',
|
|
order: 1,
|
|
content: 'Evite o trabalho manual! Aprenda a usar os Estilos (Título 1, Título 2) para que o Microsoft Word gere seu sumário em um clique.',
|
|
createdAt: now
|
|
},
|
|
|
|
// Excel - Módulo 1
|
|
{
|
|
id: 'lsn_exc_1_1',
|
|
moduleId: 'mdl_exc_1',
|
|
title: 'Dominando Fórmulas Básicas: SOMA, MÉDIA e Função Lógica SE',
|
|
videoUrl: 'https://www.youtube.com/embed/3S-F9h-gRjA',
|
|
videoType: 'youtube',
|
|
order: 1,
|
|
content: 'Entenda a sintaxe de fórmulas no Excel, referências relativas/absolutas ($) e como aplicar a famosa função SE.',
|
|
createdAt: now
|
|
},
|
|
// Excel - Módulo 2
|
|
{
|
|
id: 'lsn_exc_2_1',
|
|
moduleId: 'mdl_exc_2',
|
|
title: 'Criando sua Primeira Tabela Dinâmica e Gráficos de Vendas',
|
|
videoUrl: 'https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerBlazes.mp4',
|
|
videoType: 'direct',
|
|
order: 1,
|
|
content: 'Aprenda a consolidar milhares de linhas de dados em resumos inteligentes usando tabelas dinâmicas.',
|
|
createdAt: now
|
|
},
|
|
|
|
// PowerPoint - Módulo 1
|
|
{
|
|
id: 'lsn_ppt_1_1',
|
|
moduleId: 'mdl_ppt_1',
|
|
title: 'Trabalhando com Layouts Próprios e Inserção de Imagens e Ícones',
|
|
videoUrl: 'https://www.youtube.com/embed/Y0iI9wzY_L4',
|
|
videoType: 'youtube',
|
|
order: 1,
|
|
content: 'Esqueça os designs prontos e ultrapassados! Aprenda a criar layouts autorais limpos, modernos e profissionais.',
|
|
createdAt: now
|
|
},
|
|
// PowerPoint - Módulo 2
|
|
{
|
|
id: 'lsn_ppt_2_1',
|
|
moduleId: 'mdl_ppt_2',
|
|
title: 'O Poder da Transição Transformar (Morph) em Apresentações',
|
|
videoUrl: 'https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ElephantsDream.mp4',
|
|
videoType: 'direct',
|
|
order: 1,
|
|
content: 'Aprenda a criar animações fluidas e dinâmicas dignas de cinema utilizando o Morph do PowerPoint.',
|
|
createdAt: now
|
|
}
|
|
];
|
|
|
|
const notes: Note[] = [
|
|
{
|
|
id: 'note_1',
|
|
userId: 'usr_student_test',
|
|
lessonId: 'lsn_win_1_1',
|
|
content: 'Anotação de Teste: Atalho Windows + D serve para mostrar ou ocultar a Área de Trabalho instantaneamente!',
|
|
createdAt: new Date(Date.now() - 1 * 24 * 3600 * 1000).toISOString()
|
|
}
|
|
];
|
|
|
|
const progress: LessonProgress[] = [
|
|
{
|
|
id: 'prog_1',
|
|
userId: 'usr_student_test',
|
|
lessonId: 'lsn_win_1_1',
|
|
watchedPercentage: 95,
|
|
completed: true,
|
|
updatedAt: new Date(Date.now() - 1 * 24 * 3600 * 1000).toISOString()
|
|
},
|
|
{
|
|
id: 'prog_2',
|
|
userId: 'usr_student_test',
|
|
lessonId: 'lsn_win_1_2',
|
|
watchedPercentage: 45,
|
|
completed: false,
|
|
updatedAt: now
|
|
}
|
|
];
|
|
|
|
const payments: SubscriptionPayment[] = [
|
|
{
|
|
id: 'pay_1',
|
|
userId: 'usr_student1',
|
|
value: 49.90,
|
|
status: 'CONFIRMED',
|
|
billingType: 'PIX',
|
|
invoiceUrl: 'https://www.asaas.com/i/fake_invoice_1',
|
|
dueDate: new Date(Date.now() - 5 * 24 * 3600 * 1000).toISOString().split('T')[0],
|
|
paidAt: new Date(Date.now() - 5 * 24 * 3600 * 1000).toISOString(),
|
|
createdAt: new Date(Date.now() - 6 * 24 * 3600 * 1000).toISOString()
|
|
},
|
|
{
|
|
id: 'pay_2',
|
|
userId: 'usr_student2',
|
|
value: 49.90,
|
|
status: 'CONFIRMED',
|
|
billingType: 'CREDIT_CARD',
|
|
invoiceUrl: 'https://www.asaas.com/i/fake_invoice_2',
|
|
dueDate: new Date(Date.now() - 2 * 24 * 3600 * 1000).toISOString().split('T')[0],
|
|
paidAt: new Date(Date.now() - 2 * 24 * 3600 * 1000).toISOString(),
|
|
createdAt: new Date(Date.now() - 2 * 24 * 3600 * 1000).toISOString()
|
|
},
|
|
{
|
|
id: 'pay_3',
|
|
userId: 'usr_student3',
|
|
value: 49.90,
|
|
status: 'OVERDUE',
|
|
billingType: 'BOLETO',
|
|
invoiceUrl: 'https://www.asaas.com/i/fake_invoice_3',
|
|
dueDate: new Date(Date.now() - 10 * 24 * 3600 * 1000).toISOString().split('T')[0],
|
|
paidAt: null,
|
|
createdAt: new Date(Date.now() - 10 * 24 * 3600 * 1000).toISOString()
|
|
},
|
|
{
|
|
id: 'pay_test_1',
|
|
userId: 'usr_student_test',
|
|
value: 49.90,
|
|
status: 'CONFIRMED',
|
|
billingType: 'PIX',
|
|
invoiceUrl: 'https://www.asaas.com/i/fake_invoice_test',
|
|
dueDate: new Date(Date.now() - 1 * 24 * 3600 * 1000).toISOString().split('T')[0],
|
|
paidAt: new Date(Date.now() - 1 * 24 * 3600 * 1000).toISOString(),
|
|
createdAt: new Date(Date.now() - 1 * 24 * 3600 * 1000).toISOString()
|
|
}
|
|
];
|
|
|
|
const webhookLogs: WebhookLog[] = [
|
|
{
|
|
id: 'wh_log_1',
|
|
event: 'PAYMENT_RECEIVED',
|
|
payload: JSON.stringify({ id: 'pay_1', subscription: 'sub_0001', value: 49.90, customer: 'cus_00001' }),
|
|
receivedAt: new Date(Date.now() - 5 * 24 * 3600 * 1000).toISOString()
|
|
},
|
|
{
|
|
id: 'wh_log_2',
|
|
event: 'PAYMENT_CONFIRMED',
|
|
payload: JSON.stringify({ id: 'pay_2', subscription: 'sub_0002', value: 49.90, customer: 'cus_00002' }),
|
|
receivedAt: new Date(Date.now() - 2 * 24 * 3600 * 1000).toISOString()
|
|
},
|
|
{
|
|
id: 'wh_log_3',
|
|
event: 'PAYMENT_OVERDUE',
|
|
payload: JSON.stringify({ id: 'pay_3', subscription: 'sub_0003', value: 49.90, customer: 'cus_00003' }),
|
|
receivedAt: new Date(Date.now() - 10 * 24 * 3600 * 1000).toISOString()
|
|
}
|
|
];
|
|
|
|
return {
|
|
users,
|
|
courses,
|
|
modules,
|
|
lessons,
|
|
notes,
|
|
progress,
|
|
webhookLogs,
|
|
payments,
|
|
activities: [],
|
|
moduleGrades: [],
|
|
certificates: [],
|
|
notifications: [],
|
|
settings: {
|
|
trialDurationDays: 7,
|
|
asaasEnvironment: 'sandbox',
|
|
asaasApiKey: '',
|
|
asaasWebhookUrl: '',
|
|
asaasWebhookSecret: '',
|
|
helpText: '# Central de Ajuda\n\nAqui você encontra todas as informações sobre os cursos e funcionamento da plataforma.'
|
|
},
|
|
plans: []
|
|
};
|
|
}
|