feat:
- conexion supabase - autenticacion solo correos glm - pantalla gestor empleados
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
export interface Employee {
|
||||
id: string;
|
||||
employee_code: string;
|
||||
nombre: string;
|
||||
usuario: string | null;
|
||||
email: string | null;
|
||||
perfil: string | null;
|
||||
pais: string | null;
|
||||
regional: string | null;
|
||||
latitud: number;
|
||||
longitud: number;
|
||||
horas_por_dia: number;
|
||||
dias_por_semana: number;
|
||||
jornada_codigo: string;
|
||||
horas_descanso_por_dia: number;
|
||||
dias_descanso: string[];
|
||||
visitas_maximas_por_dia: number;
|
||||
activo: boolean;
|
||||
}
|
||||
|
||||
export type EmployeeInput = Omit<Employee, 'id'>;
|
||||
@@ -0,0 +1,17 @@
|
||||
export interface WorkSchedule {
|
||||
code: 'LUN_DOM_44' | 'LUN_SAB_40' | 'LUN_SAB_44' | 'LUN_VIE_40';
|
||||
label: string;
|
||||
weeklyHours: number;
|
||||
days: string[];
|
||||
}
|
||||
|
||||
export const WORK_SCHEDULES: WorkSchedule[] = [
|
||||
{ code: 'LUN_DOM_44', label: 'Lun a Dom - 44h', weeklyHours: 44, days: ['Lunes', 'Martes', 'Miercoles', 'Jueves', 'Viernes', 'Sabado', 'Domingo'] },
|
||||
{ code: 'LUN_SAB_40', label: 'Lun a Sáb - 40h', weeklyHours: 40, days: ['Lunes', 'Martes', 'Miercoles', 'Jueves', 'Viernes', 'Sabado'] },
|
||||
{ code: 'LUN_SAB_44', label: 'Lun a Sáb - 44h', weeklyHours: 44, days: ['Lunes', 'Martes', 'Miercoles', 'Jueves', 'Viernes', 'Sabado'] },
|
||||
{ code: 'LUN_VIE_40', label: 'Lun a Vie - 40h', weeklyHours: 40, days: ['Lunes', 'Martes', 'Miercoles', 'Jueves', 'Viernes'] }
|
||||
];
|
||||
|
||||
export function workSchedule(code: string): WorkSchedule {
|
||||
return WORK_SCHEDULES.find(schedule => schedule.code === code) ?? WORK_SCHEDULES[3];
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import { inject } from '@angular/core';
|
||||
import { CanActivateFn, Router } from '@angular/router';
|
||||
import { AuthService } from './auth.service';
|
||||
|
||||
export const authGuard: CanActivateFn = async () => {
|
||||
const auth = inject(AuthService);
|
||||
const router = inject(Router);
|
||||
return await auth.getSession() ? true : router.parseUrl('/login');
|
||||
};
|
||||
@@ -0,0 +1,37 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Session } from '@supabase/supabase-js';
|
||||
import { supabaseClient } from './supabase.client';
|
||||
|
||||
const CORPORATE_DOMAIN = '@gomezleemarketing.com';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class AuthService {
|
||||
private readonly client = supabaseClient;
|
||||
|
||||
async signIn(email: string, password: string): Promise<string | null> {
|
||||
const normalizedEmail = email.trim().toLowerCase();
|
||||
if (!normalizedEmail.endsWith(CORPORATE_DOMAIN)) {
|
||||
return `Solo se permiten correos ${CORPORATE_DOMAIN}.`;
|
||||
}
|
||||
const { error } = await this.client.auth.signInWithPassword({ email: normalizedEmail, password });
|
||||
return error?.message ?? null;
|
||||
}
|
||||
|
||||
async signInWithGoogle(): Promise<string | null> {
|
||||
const { error } = await this.client.auth.signInWithOAuth({
|
||||
provider: 'google',
|
||||
options: { redirectTo: `${window.location.origin}/home` }
|
||||
});
|
||||
return error?.message ?? null;
|
||||
}
|
||||
|
||||
async getSession(): Promise<Session | null> {
|
||||
const { data } = await this.client.auth.getSession();
|
||||
const email = data.session?.user.email?.toLowerCase() ?? '';
|
||||
return email.endsWith(CORPORATE_DOMAIN) ? data.session : null;
|
||||
}
|
||||
|
||||
async signOut(): Promise<void> {
|
||||
await this.client.auth.signOut();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Employee, EmployeeInput } from '../models/employee.model';
|
||||
import { workSchedule } from '../models/work-schedule.model';
|
||||
import * as XLSX from 'xlsx';
|
||||
import { supabaseClient } from './supabase.client';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class EmployeeService {
|
||||
private readonly client = supabaseClient;
|
||||
private readonly table = 'rutero_empleados';
|
||||
|
||||
async list(): Promise<Employee[]> {
|
||||
const { data: sessionData, error: sessionError } = await this.client.auth.getSession();
|
||||
if (sessionError) throw sessionError;
|
||||
if (!sessionData.session) throw new Error('No hay una sesión Supabase activa. Cierra sesión e inicia sesión nuevamente.');
|
||||
const { data, error } = await this.client.from(this.table).select('*').order('nombre');
|
||||
if (error) throw new Error(`Supabase ${error.code ?? 'error'}: ${error.message}`);
|
||||
return (data ?? []).map(row => ({
|
||||
...row,
|
||||
jornada_codigo: row.jornada_codigo ?? 'LUN_VIE_40',
|
||||
horas_descanso_por_dia: Number(row.horas_descanso_por_dia ?? 1),
|
||||
dias_descanso: Array.isArray(row.dias_descanso) ? row.dias_descanso : []
|
||||
})) as Employee[];
|
||||
}
|
||||
|
||||
async create(employee: EmployeeInput): Promise<void> {
|
||||
const { error } = await this.client.from(this.table).insert(employee);
|
||||
if (error) throw error;
|
||||
}
|
||||
|
||||
async upsert(employees: EmployeeInput[]): Promise<void> {
|
||||
const { error } = await this.client.from(this.table).upsert(employees, { onConflict: 'employee_code' });
|
||||
if (error) throw error;
|
||||
}
|
||||
|
||||
async update(id: string, employee: EmployeeInput): Promise<void> {
|
||||
const { error } = await this.client.from(this.table).update(employee).eq('id', id);
|
||||
if (error) throw error;
|
||||
}
|
||||
|
||||
async remove(id: string): Promise<void> {
|
||||
const { error } = await this.client.from(this.table).delete().eq('id', id);
|
||||
if (error) throw error;
|
||||
}
|
||||
|
||||
async activeEmployeesFile(): Promise<File> {
|
||||
const employees = (await this.list()).filter(employee => employee.activo);
|
||||
const rows = employees.map(employee => ({
|
||||
ID: employee.employee_code,
|
||||
'Nombre del empleado': employee.nombre,
|
||||
Latitud: employee.latitud,
|
||||
Longitud: employee.longitud,
|
||||
'Horas por día usuario': employee.horas_por_dia,
|
||||
'Horas por semana usuario': workSchedule(employee.jornada_codigo).weeklyHours,
|
||||
'Visitas maximas por dia': employee.visitas_maximas_por_dia,
|
||||
Jornada: employee.jornada_codigo,
|
||||
'Horas descanso por día': employee.horas_descanso_por_dia,
|
||||
'Días descanso': (employee.dias_descanso ?? []).join(', '),
|
||||
'Usuario activo': 'Sí'
|
||||
}));
|
||||
const workbook = XLSX.utils.book_new();
|
||||
XLSX.utils.book_append_sheet(workbook, XLSX.utils.json_to_sheet(rows), 'Usuarios');
|
||||
const data = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' });
|
||||
return new File([data], 'empleados_activos.xlsx', { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import { createClient } from '@supabase/supabase-js';
|
||||
import { environment } from '../../../environments/environment';
|
||||
|
||||
export const supabaseClient = createClient(environment.supabaseUrl, environment.supabaseAnonKey, {
|
||||
auth: { persistSession: true, autoRefreshToken: true, detectSessionInUrl: true }
|
||||
});
|
||||
Reference in New Issue
Block a user