feat: implement real tenant creation functionality
All checks were successful
Build and Deploy / build-and-push (push) Successful in 2m6s

This commit is contained in:
Cauê Faleiros
2026-02-24 14:38:54 -03:00
parent 96a96498b9
commit 237f03f407
2 changed files with 68 additions and 1 deletions

View File

@@ -123,13 +123,55 @@ app.get('/api/attendances/:id', async (req, res) => {
// --- Rotas de Tenants (Super Admin) --- // --- Rotas de Tenants (Super Admin) ---
app.get('/api/tenants', async (req, res) => { app.get('/api/tenants', async (req, res) => {
try { try {
const [rows] = await pool.query('SELECT * FROM tenants'); const query = `
SELECT t.*,
(SELECT COUNT(*) FROM users u WHERE u.tenant_id = t.id) as user_count,
(SELECT COUNT(*) FROM attendances a WHERE a.tenant_id = t.id) as attendance_count
FROM tenants t
`;
const [rows] = await pool.query(query);
res.json(rows); res.json(rows);
} catch (error) { } catch (error) {
res.status(500).json({ error: error.message }); res.status(500).json({ error: error.message });
} }
}); });
// Criar Tenant
app.post('/api/tenants', async (req, res) => {
const { name, slug, admin_email, status } = req.body;
const crypto = require('crypto');
const connection = await pool.getConnection();
try {
await connection.beginTransaction();
const tenantId = `tenant_${crypto.randomUUID().split('-')[0]}`;
// 1. Criar Tenant
await connection.query(
'INSERT INTO tenants (id, name, slug, admin_email, status) VALUES (?, ?, ?, ?, ?)',
[tenantId, name, slug, admin_email, status || 'active']
);
// 2. Criar Usuário Admin Default
const userId = `u_${crypto.randomUUID().split('-')[0]}`;
await connection.query(
'INSERT INTO users (id, tenant_id, name, email, role, status) VALUES (?, ?, ?, ?, ?, ?)',
[userId, tenantId, 'Admin', admin_email, 'admin', 'active']
);
await connection.commit();
res.status(201).json({ message: 'Tenant created successfully', id: tenantId });
} catch (error) {
await connection.rollback();
console.error('Erro ao criar tenant:', error);
res.status(500).json({ error: error.message });
} finally {
connection.release();
}
});
// Serve index.html for any unknown routes (for client-side routing) // Serve index.html for any unknown routes (for client-side routing)
if (process.env.NODE_ENV === 'production') { if (process.env.NODE_ENV === 'production') {
app.get('*', (req, res) => { app.get('*', (req, res) => {

View File

@@ -67,3 +67,28 @@ export const getAttendanceById = async (id: string): Promise<Attendance | undefi
return undefined; return undefined;
} }
}; };
export const getTenants = async (): Promise<any[]> => {
try {
const response = await fetch(`${API_URL}/tenants`);
if (!response.ok) throw new Error('Falha ao buscar tenants');
return await response.json();
} catch (error) {
console.error("API Error (getTenants):", error);
return [];
}
};
export const createTenant = async (tenantData: any): Promise<boolean> => {
try {
const response = await fetch(`${API_URL}/tenants`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(tenantData)
});
return response.ok;
} catch (error) {
console.error("API Error (createTenant):", error);
return false;
}
};