Se corrigio el problema de los logos
This commit is contained in:
@@ -183,7 +183,7 @@ export interface UnitOfMeasureGeneralUpdate {
|
||||
}
|
||||
|
||||
export interface UnitOfMeasureGeneralListResponse {
|
||||
items: UnitOfMeasureGeneral[];
|
||||
items: UnitOfMeasureGeneral[];
|
||||
total: number;
|
||||
page: number;
|
||||
page_size: number;
|
||||
|
||||
@@ -10,10 +10,10 @@
|
||||
|
||||
const sidebar = useSidebar();
|
||||
|
||||
// Derivar la URL del logo
|
||||
// Derivar la URL del logo usando el endpoint específico
|
||||
let activeCompanyLogoUrl = $derived(
|
||||
companyStore.activeCompany?.logo
|
||||
? getBackendAssetUrl(companyStore.activeCompany.logo)
|
||||
? getBackendAssetUrl(`v1/a76/company/${companyStore.activeCompany.id}/logo/image?t=${new Date().getTime()}`)
|
||||
: null
|
||||
);
|
||||
|
||||
@@ -89,7 +89,7 @@
|
||||
<div class="flex size-6 items-center justify-center rounded-md border overflow-hidden">
|
||||
{#if company.logo}
|
||||
<img
|
||||
src={getBackendAssetUrl(company.logo)}
|
||||
src={getBackendAssetUrl(`v1/a76/company/${company.id}/logo/image`)}
|
||||
alt={company.name}
|
||||
class="size-full rounded object-cover"
|
||||
/>
|
||||
|
||||
@@ -144,6 +144,30 @@ class CompanyStore {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Actualiza los datos de une empresa en el store localmente
|
||||
* Útil para reflejar cambios inmediatos (ej: cambio de logo) sin recargar
|
||||
*/
|
||||
updateCompany(id: number, data: Partial<Company>) {
|
||||
// 1. Actualizar en la lista
|
||||
const index = this._companies.findIndex(c => c.id === id);
|
||||
if (index !== -1) {
|
||||
this._companies[index] = { ...this._companies[index], ...data };
|
||||
|
||||
// 2. Si es la activa, actualizar también
|
||||
if (this._activeCompany?.id === id) {
|
||||
this._activeCompany = { ...this._activeCompany, ...data };
|
||||
// Actualizar persistencia si es necesario
|
||||
if (typeof window !== 'undefined') {
|
||||
// Disparar evento para notificar cambios a componentes que no usan el store reactivo directo (si los hay)
|
||||
window.dispatchEvent(new CustomEvent('companyChanged', {
|
||||
detail: { companyId: id }
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Restaura la compañía activa desde localStorage
|
||||
*/
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
uploadCompanyLogo,
|
||||
type Company
|
||||
} from '$lib/api/dashboard/a76/general_catalogs/company';
|
||||
import { companyStore } from '$lib/stores/company.svelte';
|
||||
import { getBackendAssetUrl } from '$lib/utils';
|
||||
import { ArrowLeft, LoaderCircle, Save, Upload, X, Building2, FileText, User, Settings } from 'lucide-svelte';
|
||||
|
||||
@@ -25,15 +26,18 @@
|
||||
let loading = $state(false);
|
||||
let uploading = $state(false);
|
||||
let error = $state<string | null>(null);
|
||||
let activeTab = $state('general');
|
||||
|
||||
let logoFile = $state<File | null>(null);
|
||||
let logoPreview = $state<string | null>(null);
|
||||
let currentLogo = $state<string | null>(null);
|
||||
let uploadingLogo = $state(false);
|
||||
let activeTab = $state('general');
|
||||
|
||||
|
||||
// URL completa del logo derivada
|
||||
let currentLogoUrl = $derived(
|
||||
logoPreview || getBackendAssetUrl(currentLogo) || ''
|
||||
logoPreview
|
||||
? logoPreview
|
||||
: (currentLogo ? getBackendAssetUrl(`v1/a76/company/${id}/logo/image?t=${new Date().getTime()}`) : '')
|
||||
);
|
||||
|
||||
// 2. Estado Inicial (Reset)
|
||||
@@ -104,7 +108,15 @@
|
||||
is_service_company: item.is_service_company || false,
|
||||
order_format_type: item.order_format_type || '',
|
||||
ctpat_svi: item.ctpat_svi || '',
|
||||
trusted_exporter_number: item.trusted_exporter_number || ''
|
||||
trusted_exporter_number: item.trusted_exporter_number || '',
|
||||
logo: item.logo || '',
|
||||
previous_code: item.previous_code || 0,
|
||||
client_name: item.client_name || '',
|
||||
subassembly_mode: item.subassembly_mode || '',
|
||||
broker_company: item.broker_company || '',
|
||||
inter_db_name: item.inter_db_name || '',
|
||||
prevalidator_key: item.prevalidator_key || '',
|
||||
seventh_amendment: item.seventh_amendment || false
|
||||
};
|
||||
// Guardar la URL del logo actual si existe
|
||||
if (item.logo) {
|
||||
@@ -118,6 +130,9 @@
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const clean = (value: any) => (typeof value === 'string' ? value.trim() || null : value);
|
||||
|
||||
function handleLogoChange(event: Event) {
|
||||
const target = event.target as HTMLInputElement;
|
||||
const file = target.files?.[0];
|
||||
@@ -170,6 +185,9 @@
|
||||
currentLogo = response.data.logo_path;
|
||||
logoFile = null;
|
||||
logoPreview = null;
|
||||
|
||||
// Actualizar el store reactivamente
|
||||
companyStore.updateCompany(companyId, { logo: response.data.logo_path });
|
||||
}
|
||||
} catch (e: any) {
|
||||
error = `Error al subir el logo: ${e.message}`;
|
||||
@@ -178,33 +196,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
const clean = (value: any) => (typeof value === 'string' ? value.trim() || null : value);
|
||||
|
||||
async function handleFileSelect(e: Event) {
|
||||
const input = e.target as HTMLInputElement;
|
||||
if (!input.files || input.files.length === 0) return;
|
||||
|
||||
const file = input.files[0];
|
||||
if (!isEdit) {
|
||||
alert("Primero debes guardar la empresa antes de subir un logo.");
|
||||
return;
|
||||
}
|
||||
|
||||
uploading = true;
|
||||
try {
|
||||
const res = await uploadCompanyLogo(Number(id), file);
|
||||
if (res.data) {
|
||||
formData.logo = res.data.path;
|
||||
} else if (res.error) {
|
||||
alert("Error al subir imagen: " + res.error);
|
||||
}
|
||||
} catch (err) {
|
||||
alert("Error al intentar subir la imagen");
|
||||
} finally {
|
||||
uploading = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function handleSubmit() {
|
||||
error = null;
|
||||
loading = true;
|
||||
@@ -222,6 +213,7 @@
|
||||
main_activity: clean(formData.main_activity),
|
||||
program: clean(formData.program),
|
||||
program_number: clean(formData.program_number),
|
||||
prosec: Number(formData.prosec) || 0,
|
||||
prosec_authorization: clean(formData.prosec_authorization),
|
||||
responsible_name: clean(formData.responsible_name),
|
||||
responsible_last_name: clean(formData.responsible_last_name),
|
||||
@@ -239,7 +231,10 @@
|
||||
broker_company: clean(formData.broker_company),
|
||||
inter_db_name: clean(formData.inter_db_name),
|
||||
prevalidator_key: clean(formData.prevalidator_key),
|
||||
seventh_amendment: formData.seventh_amendment
|
||||
seventh_amendment: formData.seventh_amendment,
|
||||
// Ensure optional booleans are passed correctly or default to false/null if needed
|
||||
has_express_line: formData.has_express_line,
|
||||
is_service_company: formData.is_service_company
|
||||
};
|
||||
|
||||
const response = isEdit
|
||||
@@ -285,6 +280,8 @@
|
||||
<Tabs.Root bind:value={activeTab} class="w-full">
|
||||
<div class="min-h-[400px]">
|
||||
<Tabs.Content value="general" class="space-y-4 pt-4">
|
||||
|
||||
|
||||
<!-- Logo Upload Section -->
|
||||
<div class="grid gap-4 p-4 border rounded-lg bg-muted/30">
|
||||
<Label>Logo de la Empresa</Label>
|
||||
@@ -344,36 +341,9 @@
|
||||
<Label for="main_activity">Actividad Principal</Label>
|
||||
<Input id="main_activity" bind:value={formData.main_activity} />
|
||||
</div>
|
||||
<div class="grid grid-cols-1 gap-4 md:grid-cols-2">
|
||||
<div class="grid gap-2">
|
||||
<Label for="logo">Ruta del Logo</Label>
|
||||
<div class="flex items-center gap-2">
|
||||
<Input id="logo" bind:value={formData.logo} placeholder="/path/to/logo.png" />
|
||||
{#if isEdit}
|
||||
<div class="relative">
|
||||
<Button variant="outline" size="icon" disabled={uploading}>
|
||||
{#if uploading}
|
||||
<LoaderCircle class="h-4 w-4 animate-spin" />
|
||||
{:else}
|
||||
<Upload class="h-4 w-4" />
|
||||
{/if}
|
||||
</Button>
|
||||
<input
|
||||
type="file"
|
||||
accept="image/*"
|
||||
class="absolute inset-0 opacity-0 cursor-pointer"
|
||||
onchange={handleFileSelect}
|
||||
disabled={uploading}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
<p class="text-[0.8rem] text-muted-foreground">Sube una imagen para obtener su ruta local.</p>
|
||||
</div>
|
||||
<div class="grid gap-2">
|
||||
<Label for="client_name">Nombre Cliente (Maquila)</Label>
|
||||
<Input id="client_name" bind:value={formData.client_name} />
|
||||
</div>
|
||||
<div class="grid gap-2">
|
||||
<Label for="client_name">Nombre Cliente (Maquila)</Label>
|
||||
<Input id="client_name" bind:value={formData.client_name} />
|
||||
</div>
|
||||
</Tabs.Content>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user