Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
411 changes: 141 additions & 270 deletions README.md

Large diffs are not rendered by default.

33 changes: 10 additions & 23 deletions backend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"jimp": "^1.6.0",
"jsonwebtoken": "^9.0.2",
"multer": "^1.4.5-lts.2",
"sql.js": "^1.14.1",
"uuid": "^10.0.0"
},
"devDependencies": {
Expand Down
86 changes: 86 additions & 0 deletions backend/seed-clients-reviews.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
const Database = require('better-sqlite3');
const path = require('path');
const { v4: uuidv4 } = require('uuid');

const DB_PATH = path.join(__dirname, 'data', 'iworkg.db');
const db = new Database(DB_PATH);
db.pragma('foreign_keys = ON');

// ── 10 novos clientes (só clientes, não prestadores) ──
const clients = [
{ name: 'Marina Telles', phone: '5535988771122' },
{ name: 'Augusto Cesar', phone: '5511988663344' },
{ name: 'Helena Dutra', phone: '5521988556677' },
{ name: 'Nelson Freitas', phone: '5531988445566' },
{ name: 'Cintia Lacerda', phone: '5535988334455' },
{ name: 'Otávio Rangel', phone: '5519988223344' },
{ name: 'Renata Borges', phone: '5521988112233' },
{ name: 'Fabrício Neves', phone: '5531988001122' },
{ name: 'Tatiane Moura', phone: '5535988990011' },
{ name: 'Valdir Coelho', phone: '5511988779900' },
];

const categories = db.prepare("SELECT id, name FROM categories LIMIT 12").all();
const providers = db.prepare("SELECT u.id, u.name, pp.id as profile_id FROM users u JOIN provider_profiles pp ON pp.user_id = u.id ORDER BY RANDOM()").all();

const baseLat = -21.7884;
const baseLng = -46.5616;

const requestTitles = [
['Troca de resistência de chuveiro', 'Chuveiro Lorenzetti parou de esquentar. Preciso trocar a resistência.'],
['Instalação de ventilador de teto', 'Comprei 2 ventiladores e preciso instalar na sala e no quarto.'],
['Reparo de tomada queimada', 'Uma tomada da cozinha soltou faísca e parou de funcionar.'],
['Entupimento de pia', 'Pia da cozinha entupida, água não desce. Preciso urgente.'],
['Reboco de parede', 'Parede do quintal descascando, aproximadamente 6m².'],
['Pintura de portão', 'Portão de ferro enferrujando, preciso lixar e pintar.'],
['Montagem de estante', 'Estante de 8 prateleiras nova na caixa. Preciso montar.'],
['Gramado para plantar', 'Preparar terreno de 30m² para plantar grama esmeralda.'],
['Limpeza de caixa dágua', 'Caixa dágua de 1000L precisa de limpeza.'],
['Chave quebrada na fechadura', 'A chave quebrou dentro da fechadura do portão. Preciso extrair e trocar.'],
];

const reviewTexts = [
'Excelente profissional! Chegou no horário, service rápido e bem feito. Super recomendo.',
'Muito bom! Resolveu o problema que outros não conseguiram. Preço justo.',
'Profissional muito competente e educado. Deixou tudo limpo depois do service. Nota 10!',
'Fez um ótimo trabalho, mas atrasou 30 minutos. No geral, recomendo.',
'Atendimento excelente, resolveu rapidinho. Voltarei a chamar quando precisar.',
'Profissional de confiança, explicou tudo que ia fazer. Muito satisfeita com o resultado.',
'Preço um pouco acima da média, mas o service foi impecável. Valeu cada centavo.',
'Muito atencioso e caprichoso. O service ficou melhor do que eu esperava.',
'Pontual e eficiente. Resolveu em 1h o que eu achava que levaria o dia todo.',
'Trabalho bem feito, material de qualidade. Já indiquei pra vizinhança.',
];

const insertUser = db.prepare('INSERT INTO users (id, name, phone, role) VALUES (?, ?, ?, ?)');
const insertRequest = db.prepare(`INSERT INTO service_requests (id, client_id, title, description, category_id, urgency, latitude, longitude, city, state, address, budget, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, datetime('now', ?))`);
const insertReview = db.prepare('INSERT INTO reviews (id, provider_id, client_id, rating, comment) VALUES (?, ?, ?, ?, ?)');

const tx = db.transaction(() => {
for (let i = 0; i < 10; i++) {
const c = clients[i];
const userId = uuidv4();
insertUser.run(userId, c.name, c.phone, 'client');

// Create a service request
const cat = categories[Math.floor(Math.random() * categories.length)];
const urgency = ['Alta', 'Média', 'Baixa'][Math.floor(Math.random() * 3)];
const lat = baseLat + (Math.random() - 0.5) * 0.03;
const lng = baseLng + (Math.random() - 0.5) * 0.03;
const budget = Math.random() > 0.4 ? Math.round(Math.random() * 500 + 50) : null;
const [title, desc] = requestTitles[i];
const offset = `-${Math.floor(Math.random() * 72)} hours`;

const requestId = uuidv4();
insertRequest.run(requestId, userId, title, desc, cat.id, urgency, lat, lng, 'Poços de Caldas', 'MG', `Rua Exemplo, ${100 + i * 10}`, budget, offset);

// Leave a review for a random provider
const provider = providers[Math.floor(Math.random() * providers.length)];
const rating = Math.floor(Math.random() * 2) + 4; // 4 or 5
insertReview.run(uuidv4(), provider.profile_id, userId, rating, reviewTexts[i]);
}
});

tx();
console.log('✅ +10 clientes, +10 pedidos, +10 avaliações criados!');
db.close();
59 changes: 59 additions & 0 deletions backend/seed-more-requests.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
const Database = require('better-sqlite3');
const path = require('path');
const { v4: uuidv4 } = require('uuid');

const DB_PATH = path.join(__dirname, 'data', 'iworkg.db');
const db = new Database(DB_PATH);

// Create 5 new client users so requests come from different people
const newClients = [
{ name: 'Roberto Alves', phone: '5535999887766', email: 'roberto@email.com' },
{ name: 'Fernanda Gomes', phone: '5519988776655', email: 'fernanda@email.com' },
{ name: 'Cláudio Mendes', phone: '5511977665544', email: 'claudio@email.com' },
{ name: 'Patrícia Santos', phone: '5521999887744', email: 'patricia@email.com' },
{ name: 'Luiz Fernando', phone: '5531998776622', email: 'luiz@email.com' },
];

const categories = db.prepare("SELECT id, name FROM categories LIMIT 12").all();
const baseLat = -21.7884;
const baseLng = -46.5616;

const insertUser = db.prepare('INSERT INTO users (id, name, phone, email, role) VALUES (?, ?, ?, ?, ?)');
const insertRequest = db.prepare(`INSERT INTO service_requests (id, client_id, title, description, category_id, urgency, latitude, longitude, city, state, address, budget, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, datetime('now', ?))`);

const requests = [
'Preciso de eletricista para instalar lustre', 'Lustre de 8 lâmpadas, pé direito alto. Preciso de profissional com escada.',
'Vazamento no banheiro', 'Água infiltrando no rejunte do box. Preciso de avaliação e reparo.',
'Pintura de fachada', 'Fachada de casa de 2 andares, aproximadamente 80m². Tinta já comprada.',
'Jardim abandonado', 'Jardim de 50m² tomado por mato. Preciso de limpeza e replantio.',
'Montagem de cozinha planejada', 'Cozinha Itatiaia 12 módulos. Preciso de montador com experiência.',
];

const tx = db.transaction(() => {
for (let i = 0; i < newClients.length; i++) {
const c = newClients[i];
const userId = uuidv4();
insertUser.run(userId, c.name, c.phone, c.email, 'client');

const cat = categories[Math.floor(Math.random() * categories.length)];
const urgency = ['Alta', 'Média', 'Baixa'][Math.floor(Math.random() * 3)];
const lat = baseLat + (Math.random() - 0.5) * 0.03;
const lng = baseLng + (Math.random() - 0.5) * 0.03;
const budget = Math.random() > 0.5 ? Math.round(Math.random() * 500 + 50) : null;

const title = requests[i * 2];
const desc = requests[i * 2 + 1];
const offset = `-${Math.floor(Math.random() * 48)} hours`;

insertRequest.run(
uuidv4(), userId, title, desc, cat.id, urgency,
lat, lng, 'Poços de Caldas', 'MG',
`Rua de Teste, ${Math.floor(Math.random() * 500)}`,
budget, offset
);
}
});

tx();
console.log('✅ 5 novos clientes + 5 pedidos de outras pessoas criados!');
db.close();
65 changes: 65 additions & 0 deletions backend/seed-providers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
const Database = require('better-sqlite3');
const path = require('path');
const { v4: uuidv4 } = require('uuid');

const DB_PATH = path.join(__dirname, 'data', 'iworkg.db');
const db = new Database(DB_PATH);
db.pragma('foreign_keys = ON');

const providers = [
{ name: 'Ricardo Nunes', category: 'cat-eletricista', description: 'Eletricista especializado em automação residencial. Instalo tomadas inteligentes, sensores e sistemas de iluminação automatizada.', experience: 14, city: 'Poços de Caldas', state: 'MG', lat: -21.792, lng: -46.550, address: 'Rua Paraná, 70' },
{ name: 'Camila Torres', category: 'cat-eletricista', description: 'Eletricista predial. Manutenção preventiva, quadros de distribuição, padrão de entrada e aterramento.', experience: 6, city: 'Andradas', state: 'MG', lat: -22.068, lng: -46.568, address: 'Av. Ricarti Teixeira, 300' },
{ name: 'Thiago Moura', category: 'cat-encanador', description: 'Encanador especialista em sistemas de aquecimento solar. Instalação e manutenção de boilers e placas solares.', experience: 9, city: 'Poços de Caldas', state: 'MG', lat: -21.782, lng: -46.555, address: 'Rua Santa Catarina, 45' },
{ name: 'Patrícia Diniz', category: 'cat-pedreiro', description: 'Pedreira com foco em acabamentos de luxo. Porcelanato, mármore, granito e revestimentos importados.', experience: 18, city: 'Poços de Caldas', state: 'MG', lat: -21.793, lng: -46.562, address: 'Av. Santo Antônio, 1500' },
{ name: 'Gustavo Teixeira', category: 'cat-pedreiro', description: 'Pedreiro de obras rápidas. Pequenas reformas, reparos em muros, calçadas e contrapisos. Dias e sábados.', experience: 7, city: 'Caldas', state: 'MG', lat: -21.924, lng: -46.386, address: 'Rua do Comércio, 88' },
{ name: 'Sandra Vieira', category: 'cat-pintor', description: 'Pintora decorativa. Técnicas de marmorização, textura espanhola e pintura artística em paredes e tetos.', experience: 12, city: 'Poços de Caldas', state: 'MG', lat: -21.788, lng: -46.558, address: 'Rua Goiás, 200' },
{ name: 'Felipe Barros', category: 'cat-marceneiro', description: 'Marceneiro criativo. Móveis rústicos, pallets reaproveitados, estantes personalizadas e brinquedos de madeira.', experience: 5, city: 'Botelhos', state: 'MG', lat: -21.638, lng: -46.393, address: 'Rua Principal, 120' },
{ name: 'Amanda Lopes', category: 'cat-jardineiro', description: 'Paisagista especializada em jardins tropicais. Palmeiras, bromélias, orquídeas e lagos ornamentais com peixes.', experience: 10, city: 'Poços de Caldas', state: 'MG', lat: -21.785, lng: -46.564, address: 'Alameda das Flores, 55' },
{ name: 'Renato Campos', category: 'cat-faxineiro', description: 'Faxineiro especializado em limpeza pós-obra. Remoção de entulho fino, limpeza de vidros e rejunte.', experience: 3, city: 'Poços de Caldas', state: 'MG', lat: -21.790, lng: -46.553, address: 'Rua Piauí, 90' },
{ name: 'Daniela Pires', category: 'cat-mecanico', description: 'Mecânica de motos. Revisão geral, troca de relação, carburador e injeção eletrônica. Busco e entrego.', experience: 8, city: 'Poços de Caldas', state: 'MG', lat: -21.786, lng: -46.566, address: 'Av. João Pinheiro, 780' },
{ name: 'Eduardo Faria', category: 'cat-tecnico-refrigeracao', description: 'Técnico HVAC. Instalação de sistemas de climatização central, splits, multisplits e dutos de ventilação.', experience: 13, city: 'Poços de Caldas', state: 'MG', lat: -21.789, lng: -46.551, address: 'Rua Ceará, 32' },
{ name: 'Vanessa Castro', category: 'cat-chaveiro', description: 'Chaveira automotiva. Codificação de chaves com chip, conserto de fechaduras de carros e abertura de porta.', experience: 6, city: 'Poços de Caldas', state: 'MG', lat: -21.787, lng: -46.557, address: 'Rua Pernambuco, 14' },
{ name: 'Bruno Azevedo', category: 'cat-diarista', description: 'Diarista com referências. Limpeza geral, lavanderia, organização de closets e armários. Material incluso.', experience: 9, city: 'Poços de Caldas', state: 'MG', lat: -21.791, lng: -46.559, address: 'Rua Alagoas, 180' },
{ name: 'Letícia Dantas', category: 'cat-diarista', description: 'Diarista de confiança há 7 anos na mesma família. Cozinho, limpo e cuido de pets durante a faxina.', experience: 7, city: 'Poços de Caldas', state: 'MG', lat: -21.783, lng: -46.563, address: 'Rua Maranhão, 65' },
{ name: 'André Matos', category: 'cat-montador', description: 'Montador de móveis profissionais. Montagem de cozinhas planejadas, racks, painéis de TV e home theater.', experience: 11, city: 'Poços de Caldas', state: 'MG', lat: -21.784, lng: -46.556, address: 'Av. Francisco Salles, 2100' },
{ name: 'Carla Souza', category: 'cat-montador', description: 'Montadora de estruturas metálicas. Telhados, galpões, mezaninos e estruturas para energia solar.', experience: 4, city: 'Andradas', state: 'MG', lat: -22.070, lng: -46.565, address: 'Rua do Rosário, 55' },
{ name: 'Henrique Moraes', category: 'cat-eletricista', description: 'Eletricista de emergência 24h. Curto-circuito, queda de energia parcial, disjuntor desarmando. Chego em 30min.', experience: 16, city: 'Poços de Caldas', state: 'MG', lat: -21.790, lng: -46.560, address: 'Rua Sergipe, 22' },
{ name: 'Tatiana Reis', category: 'cat-pintor', description: 'Pintora de fachadas e áreas externas. Trabalho com tinta elastomérica, hidrorepelente e grafite artístico.', experience: 8, city: 'Poços de Caldas', state: 'MG', lat: -21.788, lng: -46.565, address: 'Rua Tocantins, 40' },
{ name: 'Marcelo Brito', category: 'cat-encanador', description: 'Encanador de emergência. Vazamentos, entupimentos, troca de registros e instalação de bombas dagua.', experience: 20, city: 'Poços de Caldas', state: 'MG', lat: -21.785, lng: -46.552, address: 'Rua Amapá, 15' },
{ name: 'Gabriela Xavier', category: 'cat-mecanico', description: 'Mecânica de carros importados. Especialidade em BMW, Audi e Mercedes. Scanner automotivo e reprogramação.', experience: 10, city: 'Poços de Caldas', state: 'MG', lat: -21.792, lng: -46.564, address: 'Av. Mansur Frayha, 3200' },
];

function generatePhone() {
const ddds = ['35', '19', '11', '21', '31'];
const ddd = ddds[Math.floor(Math.random() * ddds.length)];
const num = String(Math.floor(Math.random() * 900000000 + 100000000));
return `55${ddd}${num}`;
}

const insertUser = db.prepare('INSERT INTO users (id, name, phone, role) VALUES (?, ?, ?, ?)');
const insertProfile = db.prepare('INSERT INTO provider_profiles (id, user_id, category_id, description, rating, review_count, experience_years, service_radius_km, address, latitude, longitude, city, state, active) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1)');

const tx = db.transaction(() => {
for (const p of providers) {
const userId = uuidv4();
const phone = generatePhone();
const profileId = uuidv4();
insertUser.run(userId, p.name, phone, 'provider');
insertProfile.run(
profileId, userId, p.category, p.description,
Math.round((3 + Math.random() * 2) * 10) / 10,
Math.floor(Math.random() * 30),
p.experience,
Math.floor(Math.random() * 30) + 5,
p.address,
p.lat + (Math.random() - 0.5) * 0.01,
p.lng + (Math.random() - 0.5) * 0.01,
p.city,
p.state
);
}
});

tx();
console.log('✅ +' + providers.length + ' prestadores adicionados!');
db.close();
Loading
Loading