Merge pull request 'fix/informacion-empresa' (#402) from fix/informacion-empresa into development

Reviewed-on: ADUANASOFT/anexo76#402
This commit is contained in:
2026-05-15 21:10:46 +00:00
2 changed files with 93 additions and 15 deletions

View File

@@ -8,14 +8,14 @@
import { Button } from '$lib/components/ui/button';
import { Input } from '$lib/components/ui/input';
import { Plus, RefreshCw } from 'lucide-svelte';
import { Pencil, Plus, RefreshCw, Trash2 } from 'lucide-svelte';
import { goto } from '$app/navigation';
import { browser } from '$app/environment';
import * as m from '$lib/paraglide/messages.js';
import { useShortcuts } from '$lib/hooks/use-shortcuts';
import { obtenerAtajosListaEmpresa } from '$lib/config/shortcuts/dashboard/general_catalogs/company_information/list';
import { getCompanies } from '$lib/api/dashboard/a76/general_catalogs/company';
import { getCompanies, deleteCompany, type Company } from '$lib/api/dashboard/a76/general_catalogs/company';
import ErrorState from '$lib/components/dashboard/common/error-state.svelte';
import { currentUser } from '$lib/auth';
let { data } = $props();
@@ -46,13 +46,19 @@
let searchRfc = $state($page.url.searchParams.get('rfc') || '');
let timeout: ReturnType<typeof setTimeout>;
let allItems = $state(data.companies?.items || []);
let allItems = $state<Company[]>(data.companies?.items || []);
let currentPage = $state(data.companies?.page || 1);
let pageSize = $state(data.companies?.page_size || 50);
let totalItems = $state(data.companies?.total || 0);
let loading = $state(false);
let hasMore = $derived(allItems.length < totalItems);
// Selección de filas
let selectedIds = $state<(string | number)[]>([]);
const singleSelected = $derived<Company | null>(
selectedIds.length === 1 ? (allItems.find((item) => item.id === selectedIds[0]) ?? null) : null
);
$effect(() => {
if (data.companies) {
allItems = data.companies.items || [];
@@ -142,7 +148,43 @@
}
}
function handleRowClick(row: Company) {
const id = row.id;
selectedIds = selectedIds.includes(id) ? [] : [id];
}
function handleRowDoubleClick(row: Company) {
if (canView) {
goto(`/dashboard/general_catalogs/company_information/edit/${row.id}`);
}
}
function handleEditSelected() {
if (!singleSelected) return;
goto(`/dashboard/general_catalogs/company_information/edit/${singleSelected.id}`);
}
async function handleDeleteSelected() {
if (!singleSelected) return;
if (!confirm(`¿Estás seguro de eliminar la empresa "${singleSelected.name}"?\n\nNota: No se puede eliminar si tiene registros relacionados.`)) return;
loading = true;
error = null;
try {
const response = await deleteCompany(singleSelected.id);
if (!response.error) {
selectedIds = [];
await reloadData();
}
} catch (e) {
error = 'Error al eliminar la empresa';
} finally {
loading = false;
}
}
function handleSuccess() {
selectedIds = [];
reloadData();
}
</script>
@@ -168,9 +210,9 @@
</div>
{#if error || !canView}
<ErrorState
status={!canView ? 403 : status}
error={!canView ? 'Permission denied: cat_company.view' : (error || '')}
<ErrorState
status={!canView ? 403 : status}
error={!canView ? 'Permission denied: cat_company.view' : (error || '')}
onRetry={reloadData}
/>
{:else}
@@ -202,11 +244,10 @@
{loading}
{hasMore}
{loadMore}
onRowDoubleClick={(row) => {
if (canEdit) {
goto(`/dashboard/general_catalogs/company_information/edit/${row.id}`);
}
}}
{selectedIds}
onSelectedIdsChange={(ids) => (selectedIds = ids)}
onRowClick={handleRowClick}
onRowDoubleClick={handleRowDoubleClick}
/>
</div>
</Card.Content>
@@ -216,4 +257,40 @@
<div class="flex-none text-sm text-muted-foreground">
Mostrando {allItems.length} de {totalItems} registros
</div>
<div class="h-20"></div>
{#if canEdit || canDelete}
<div
class="fixed right-0 bottom-0 left-0 z-50 ml-[calc(var(--sidebar-width))] border-t bg-background/95 shadow-lg backdrop-blur group-has-data-[state=collapsed]/sidebar-wrapper:ml-[calc(var(--sidebar-width-icon))] supports-[backdrop-filter]:bg-background/80"
>
<div class="mx-auto max-w-[1400px] px-4 py-4">
<div class="flex justify-end gap-2">
{#if canEdit}
<Button
variant="outline"
size="sm"
onclick={handleEditSelected}
disabled={selectedIds.length !== 1}
>
<Pencil size={16} class="mr-2" />
Editar
</Button>
{/if}
{#if canDelete}
<Button
variant="outline"
size="sm"
onclick={handleDeleteSelected}
disabled={selectedIds.length !== 1}
class="text-destructive hover:bg-destructive/10 hover:text-destructive"
>
<Trash2 size={16} class="mr-2" />
Eliminar
</Button>
{/if}
</div>
</div>
</div>
{/if}
</div>

View File

@@ -49,9 +49,10 @@
const id = $derived($page.params.id);
const isEdit = $derived(!!id);
const title = $derived(isEdit ? 'Editar Empresa' : 'Nueva Empresa');
const canView = $derived(userHasCompanyCatalogAction($currentUser, 'view'));
const canCreate = $derived(userHasCompanyCatalogAction($currentUser, 'create'));
const canEdit = $derived(userHasCompanyCatalogAction($currentUser, 'edit'));
const canAccessEditor = $derived((isEdit && canEdit) || (!isEdit && canCreate));
const canAccessEditor = $derived((isEdit && (canEdit || canView)) || (!isEdit && canCreate));
const canMutate = $derived(isEdit ? canEdit : canCreate);
let loading = $state(false);
@@ -245,8 +246,8 @@
});
async function fetchData(companyId: string) {
if (!canEdit) {
error = 'Permission denied: cat_company.edit';
if (!canEdit && !canView) {
error = 'Permission denied: cat_company.view';
return;
}
loading = true;
@@ -779,7 +780,7 @@
{#if !canAccessEditor}
<div class="p-6">
<ErrorState status={403} error={isEdit ? 'Permission denied: cat_company.edit' : 'Permission denied: cat_company.create'} />
<ErrorState status={403} error={isEdit ? 'Permission denied: cat_company.view' : 'Permission denied: cat_company.create'} />
</div>
{:else}
<div class="mx-auto w-full max-w-6xl space-y-6 px-4 py-6 pb-48">