Estructura correcta: subida desde la raíz

This commit is contained in:
2026-07-16 16:09:23 -04:00
commit de83f8984a
85 changed files with 7301 additions and 0 deletions
@@ -0,0 +1,13 @@
import { supabase } from "./supabase";
export async function getEmployee(employeeNumber) {
const { data, error } = await supabase
.from("empleados_glm")
.select("*")
.eq("cedula", employeeNumber)
.single();
if (error) throw error;
return data;
}
@@ -0,0 +1,86 @@
import { supabase } from "./supabase";
/**
* Registra el cliente/proyecto de un carnet descargado en la tabla
* "carnet_empleados_creados_glm".
*
* @param {string} employeeNumber - Número de cédula limpio (sin guiones/espacios)
* @param {string} clienteProyecto - Nombre del cliente/proyecto seleccionado
* @returns {Promise<void>}
*/
export async function saveClienteProyecto(employeeNumber, clienteProyecto) {
const cleanCedula = String(employeeNumber || '').replace(/[-\s]/g, '');
const valorCliente = clienteProyecto || 'Generico';
if (!cleanCedula) {
throw new Error('Cédula vacía, no se puede guardar.');
}
const { error } = await supabase.rpc('upsert_carnet_cliente', {
p_cedula: cleanCedula,
p_cliente_proyecto: valorCliente
});
if (error) {
throw error;
}
}
/**
* Sube la foto de un empleado al bucket "foto_empleados".
*
* El nombre del archivo sigue el patrón:
* <cedula>_<cliente>.jpg — primera foto
* <cedula>_<cliente>1.jpg — segunda foto del mismo empleado+cliente
* <cedula>_<cliente>2.jpg — tercera, etc.
*
* @param {string} employeeNumber - Número de cédula limpio (sin guiones/espacios)
* @param {File} file - Archivo de imagen a subir
* @param {string} [clientKey=''] - Nombre del cliente/proyecto (p.ej. "claro", "nestle")
* @returns {Promise<string>} - URL pública del archivo subido
*/
export async function uploadEmployeePhoto(employeeNumber, file, clientKey = '') {
const extension = file.name.split('.').pop() || 'jpg';
// Normalizar el nombre del cliente: minúsculas, sin espacios ni caracteres especiales
const safeClient = clientKey
? '_' + clientKey.toLowerCase().replace(/[^a-z0-9]/g, '')
: '';
const baseName = `${employeeNumber}${safeClient}`;
// Buscar archivos existentes con el mismo prefijo para elegir el sufijo correcto
const { data: existingFiles } = await supabase.storage
.from('foto_empleados')
.list('', { search: baseName });
// Filtrar exactamente los archivos que tengan el mismo baseName base
const pattern = new RegExp(`^${baseName}(\\d*)\\.${extension}$`);
const matches = (existingFiles || []).filter(f => pattern.test(f.name));
let fileName;
if (matches.length === 0) {
// No existe ninguno: usar el nombre base sin sufijo numérico
fileName = `${baseName}.${extension}`;
} else {
// Extraer los sufijos numéricos usados y elegir el siguiente
const usedSuffixes = matches.map(f => {
const m = f.name.match(pattern);
return m ? parseInt(m[1] || '0', 10) : 0;
});
const nextSuffix = Math.max(...usedSuffixes) + 1;
fileName = `${baseName}${nextSuffix}.${extension}`;
}
const { error } = await supabase.storage
.from('foto_empleados')
.upload(fileName, file, { upsert: false });
if (error) throw error;
const { data } = supabase.storage
.from('foto_empleados')
.getPublicUrl(fileName);
return data.publicUrl;
}
@@ -0,0 +1,7 @@
import { createClient } from "@supabase/supabase-js";
const supabaseUrl = import.meta.env.VITE_SUPABASE_URL;
const supabaseAnonKey = import.meta.env.VITE_SUPABASE_ANON_KEY;
// Single client for auth (uses anon key)
export const supabase = createClient(supabaseUrl, supabaseAnonKey);