feat: replace mock system with real backend, RBAC, and Teams management
All checks were successful
Build and Deploy / build-and-push (push) Successful in 2m3s
All checks were successful
Build and Deploy / build-and-push (push) Successful in 2m3s
- Implemented real JWT authentication and persistent user sessions - Replaced all hardcoded mock data with dynamic MySQL-backed API calls - Created new 'Times' (Teams) dashboard with performance metrics - Renamed 'Equipe' to 'Membros' and centralized team management - Added Role-Based Access Control (RBAC) for Admin/Manager/Agent roles - Implemented secure invite-only member creation and password setup flow - Enhanced Login with password visibility and real-time validation - Added safe delete confirmation modal and custom Toast notifications
This commit is contained in:
@@ -50,14 +50,19 @@ export const getUserById = async (id: string): Promise<User | undefined> => {
|
||||
try {
|
||||
const response = await fetch(`${API_URL}/users/${id}`);
|
||||
if (!response.ok) return undefined;
|
||||
return await response.json();
|
||||
|
||||
const contentType = response.headers.get("content-type");
|
||||
if (contentType && contentType.indexOf("application/json") !== -1) {
|
||||
return await response.json();
|
||||
}
|
||||
return undefined;
|
||||
} catch (error) {
|
||||
console.error("API Error (getUserById):", error);
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
export const updateUser = async (id: string, userData: { name: string, bio: string }): Promise<boolean> => {
|
||||
export const updateUser = async (id: string, userData: any): Promise<boolean> => {
|
||||
try {
|
||||
const response = await fetch(`${API_URL}/users/${id}`, {
|
||||
method: 'PUT',
|
||||
@@ -71,11 +76,42 @@ export const updateUser = async (id: string, userData: { name: string, bio: stri
|
||||
}
|
||||
};
|
||||
|
||||
export const createMember = async (userData: any): Promise<boolean> => {
|
||||
try {
|
||||
const response = await fetch(`${API_URL}/users`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(userData)
|
||||
});
|
||||
return response.ok;
|
||||
} catch (error) {
|
||||
console.error("API Error (createMember):", error);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
export const deleteUser = async (id: string): Promise<boolean> => {
|
||||
try {
|
||||
const response = await fetch(`${API_URL}/users/${id}`, {
|
||||
method: 'DELETE'
|
||||
});
|
||||
return response.ok;
|
||||
} catch (error) {
|
||||
console.error("API Error (deleteUser):", error);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
export const getAttendanceById = async (id: string): Promise<Attendance | undefined> => {
|
||||
try {
|
||||
const response = await fetch(`${API_URL}/attendances/${id}`);
|
||||
if (!response.ok) return undefined;
|
||||
return await response.json();
|
||||
|
||||
const contentType = response.headers.get("content-type");
|
||||
if (contentType && contentType.indexOf("application/json") !== -1) {
|
||||
return await response.json();
|
||||
}
|
||||
return undefined;
|
||||
} catch (error) {
|
||||
console.error("API Error (getAttendanceById):", error);
|
||||
return undefined;
|
||||
@@ -86,13 +122,57 @@ 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();
|
||||
|
||||
const contentType = response.headers.get("content-type");
|
||||
if (contentType && contentType.indexOf("application/json") !== -1) {
|
||||
return await response.json();
|
||||
}
|
||||
return [];
|
||||
} catch (error) {
|
||||
console.error("API Error (getTenants):", error);
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
export const getTeams = async (tenantId: string): Promise<any[]> => {
|
||||
try {
|
||||
const response = await fetch(`${API_URL}/teams?tenantId=${tenantId}`);
|
||||
if (!response.ok) throw new Error('Falha ao buscar equipes');
|
||||
return await response.json();
|
||||
} catch (error) {
|
||||
console.error("API Error (getTeams):", error);
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
export const createTeam = async (teamData: any): Promise<boolean> => {
|
||||
try {
|
||||
const response = await fetch(`${API_URL}/teams`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(teamData)
|
||||
});
|
||||
return response.ok;
|
||||
} catch (error) {
|
||||
console.error("API Error (createTeam):", error);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
export const updateTeam = async (id: string, teamData: any): Promise<boolean> => {
|
||||
try {
|
||||
const response = await fetch(`${API_URL}/teams/${id}`, {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(teamData)
|
||||
});
|
||||
return response.ok;
|
||||
} catch (error) {
|
||||
console.error("API Error (updateTeam):", error);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
export const createTenant = async (tenantData: any): Promise<boolean> => {
|
||||
try {
|
||||
const response = await fetch(`${API_URL}/tenants`, {
|
||||
@@ -106,3 +186,87 @@ export const createTenant = async (tenantData: any): Promise<boolean> => {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// --- Auth Functions ---
|
||||
|
||||
export const login = async (credentials: any): Promise<any> => {
|
||||
const response = await fetch(`${API_URL}/auth/login`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(credentials)
|
||||
});
|
||||
|
||||
const contentType = response.headers.get("content-type");
|
||||
const isJson = contentType && contentType.indexOf("application/json") !== -1;
|
||||
|
||||
if (!response.ok) {
|
||||
const error = isJson ? await response.json() : { error: 'Erro no servidor' };
|
||||
throw new Error(error.error || 'Erro no login');
|
||||
}
|
||||
|
||||
return isJson ? await response.json() : null;
|
||||
};
|
||||
|
||||
export const register = async (userData: any): Promise<boolean> => {
|
||||
const response = await fetch(`${API_URL}/auth/register`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(userData)
|
||||
});
|
||||
if (!response.ok) {
|
||||
const error = await response.json();
|
||||
throw new Error(error.error || 'Erro no registro');
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
export const verifyCode = async (data: any): Promise<boolean> => {
|
||||
const response = await fetch(`${API_URL}/auth/verify`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
if (!response.ok) {
|
||||
const error = await response.json();
|
||||
throw new Error(error.error || 'Código inválido ou expirado');
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
export const forgotPassword = async (email: string): Promise<string> => {
|
||||
const response = await fetch(`${API_URL}/auth/forgot-password`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ email })
|
||||
});
|
||||
|
||||
const contentType = response.headers.get("content-type");
|
||||
const isJson = contentType && contentType.indexOf("application/json") !== -1;
|
||||
|
||||
if (!response.ok) {
|
||||
const error = isJson ? await response.json() : { error: 'Erro no servidor' };
|
||||
throw new Error(error.error || 'Erro ao processar solicitação');
|
||||
}
|
||||
|
||||
const data = isJson ? await response.json() : { message: 'Solicitação processada' };
|
||||
return data.message;
|
||||
};
|
||||
|
||||
export const resetPassword = async (password: string, token: string): Promise<string> => {
|
||||
const response = await fetch(`${API_URL}/auth/reset-password`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ password, token })
|
||||
});
|
||||
|
||||
const contentType = response.headers.get("content-type");
|
||||
const isJson = contentType && contentType.indexOf("application/json") !== -1;
|
||||
|
||||
if (!response.ok) {
|
||||
const error = isJson ? await response.json() : { error: 'Erro no servidor' };
|
||||
throw new Error(error.error || 'Erro ao resetar senha');
|
||||
}
|
||||
|
||||
const data = isJson ? await response.json() : { message: 'Senha redefinida' };
|
||||
return data.message;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user