Limpieza y correcion de warnings en ultimos cambios
This commit is contained in:
@@ -34,7 +34,7 @@ export function createColumns(onSuccess?: () => void): ColumnDef<Part>[] {
|
||||
// Usamos el componente Checkbox si es posible, pero para snippets crudos en TanStack 5
|
||||
// a veces es más directo un input o un Snippet de Svelte.
|
||||
// Aquí usaremos renderComponent para el Checkbox real.
|
||||
return "";
|
||||
return "<span></span>";
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -162,9 +162,7 @@ export function createColumns(onSuccess?: () => void): ColumnDef<Part>[] {
|
||||
const { um } = getUm();
|
||||
return {
|
||||
render: () =>
|
||||
`<span class="inline-flex items-center rounded-sm bg-blue-50 dark:bg-blue-900 text-blue-700 dark:text-blue-300 px-1.5 py-0.5 text-[10px] font-bold ring-1 ring-inset ring-blue-700/10">
|
||||
${um || '-'}
|
||||
</span>`
|
||||
`<span class="inline-flex items-center rounded-sm bg-blue-50 dark:bg-blue-900 text-blue-700 dark:text-blue-300 px-1.5 py-0.5 text-[10px] font-bold ring-1 ring-inset ring-blue-700/10">${um || '-'}</span>`
|
||||
};
|
||||
});
|
||||
return renderSnippet(umSnippet, { um: row.original.unit_of_measure });
|
||||
@@ -246,7 +244,7 @@ export function createColumns(onSuccess?: () => void): ColumnDef<Part>[] {
|
||||
const { weight, type } = getWeight();
|
||||
return {
|
||||
render: () => {
|
||||
if (weight === null || weight === undefined) return '-';
|
||||
if (weight === null || weight === undefined) return '<span>-</span>';
|
||||
return `<div class="text-xs font-mono">${Number(weight).toFixed(4)} ${type || ''}</div>`;
|
||||
}
|
||||
};
|
||||
@@ -281,7 +279,7 @@ export function createColumns(onSuccess?: () => void): ColumnDef<Part>[] {
|
||||
cell: ({ row }) => {
|
||||
const dateSnippet = createRawSnippet<[{ date: string }]>((getDate) => {
|
||||
const { date } = getDate();
|
||||
if (!date) return { render: () => '-' };
|
||||
if (!date) return { render: () => '<span>-</span>' };
|
||||
const formatted = new Date(date).toLocaleDateString('es-MX', {
|
||||
year: 'numeric',
|
||||
month: '2-digit',
|
||||
|
||||
@@ -152,9 +152,7 @@ export function createColumns(
|
||||
const { type, colorClass } = getProps();
|
||||
return {
|
||||
render: () =>
|
||||
`<span class="inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium ${colorClass}">
|
||||
${type || '-'}
|
||||
</span>`
|
||||
`<span class="inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium ${colorClass}">${type || '-'}</span>`
|
||||
};
|
||||
});
|
||||
return renderSnippet(typeSnippet, { type: invoiceType, colorClass });
|
||||
|
||||
@@ -53,11 +53,15 @@
|
||||
},
|
||||
onStateChange: (updater: any) => {
|
||||
if (onSortingChange) {
|
||||
const nextSorting = typeof updater === 'function' ? updater(sorting) : updater;
|
||||
if (nextSorting.sorting !== undefined) {
|
||||
onSortingChange(nextSorting.sorting);
|
||||
} else {
|
||||
onSortingChange(nextSorting);
|
||||
const currentState = table.getState();
|
||||
const nextState = typeof updater === 'function' ? updater(currentState) : updater;
|
||||
|
||||
// Identify if this was a sorting update or at least contains sorting
|
||||
if (nextState && nextState.sorting !== undefined) {
|
||||
onSortingChange(nextState.sorting);
|
||||
} else if (Array.isArray(nextState)) {
|
||||
// Fallback for when updater might return just the array slice
|
||||
onSortingChange(nextState);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -64,12 +64,14 @@
|
||||
: null
|
||||
);
|
||||
|
||||
// Ensure descriptions.has_serial has default
|
||||
$effect(() => {
|
||||
if (descriptions && descriptions.has_serial === undefined) {
|
||||
descriptions.has_serial = false;
|
||||
const internalHasSerial = $derived(descriptions?.has_serial === true);
|
||||
function toggleHasSerial() {
|
||||
if (descriptions) {
|
||||
descriptions.has_serial = !descriptions.has_serial;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const hasSerial = $derived(internalHasSerial);
|
||||
|
||||
// Ensure current serie has defaults for form fields
|
||||
$effect(() => {
|
||||
@@ -83,7 +85,6 @@
|
||||
}
|
||||
});
|
||||
|
||||
const hasSerial = $derived(Boolean(descriptions?.has_serial));
|
||||
const invoiceNumber = $derived(invoice?.invoice_number || '');
|
||||
const invoiceLine = $derived(lineItem?.line_number != null ? String(lineItem.line_number) : '');
|
||||
const partNumber = $derived((lineItem as any)?.part_number_display || lineItem?.part_number || '');
|
||||
@@ -137,7 +138,11 @@
|
||||
|
||||
<div class="flex items-center justify-between gap-2 flex-wrap">
|
||||
<div class="flex items-center space-x-1.5">
|
||||
<Checkbox id="has_serial" bind:checked={descriptions.has_serial} />
|
||||
<Checkbox
|
||||
id="has_serial"
|
||||
checked={descriptions?.has_serial === true}
|
||||
onCheckedChange={(v: boolean) => { if (descriptions) descriptions.has_serial = v; }}
|
||||
/>
|
||||
<Label for="has_serial" class="text-xs font-normal">Lleva serie (LLEVASERIE)</Label>
|
||||
</div>
|
||||
<Button
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
import { toast } from 'svelte-sonner';
|
||||
import { helpApi, type HelpArticle } from '$lib/api/help';
|
||||
import { helpStore } from '$lib/stores/help.svelte';
|
||||
import { browser } from '$app/environment';
|
||||
|
||||
// Nota: Estas librerías deben ser instaladas: npm install marked dompurify @types/dompurify
|
||||
// Si no están, fallará el import. El usuario debe instalarlas.
|
||||
@@ -133,96 +134,100 @@
|
||||
</Sheet.Trigger>
|
||||
<Sheet.Content side="right" class="w-[400px] sm:w-[540px]">
|
||||
<Sheet.Header>
|
||||
<Sheet.Title class="flex items-center gap-2">
|
||||
{#if selectedArticle}
|
||||
<Button variant="ghost" size="icon" onclick={() => (selectedArticle = null)}>
|
||||
<ChevronLeft size={20} />
|
||||
</Button>
|
||||
{/if}
|
||||
Base de Conocimientos
|
||||
</Sheet.Title>
|
||||
</Sheet.Header>
|
||||
<Sheet.Title class="flex items-center gap-2">
|
||||
{#if selectedArticle}
|
||||
<Button variant="ghost" size="icon" onclick={() => (selectedArticle = null)}>
|
||||
<ChevronLeft size={20} />
|
||||
</Button>
|
||||
{/if}
|
||||
<span>Base de Conocimientos</span>
|
||||
</Sheet.Title>
|
||||
</Sheet.Header>
|
||||
|
||||
<div class="mt-6 flex h-[calc(100vh-120px)] flex-col">
|
||||
{#if !selectedArticle}
|
||||
<div class="space-y-4">
|
||||
<div class="flex items-center justify-between">
|
||||
<h3 class="text-lg font-medium">Artículos Disponibles</h3>
|
||||
{#if isAdmin}
|
||||
<Button variant="outline" size="sm" onclick={startCreate}>
|
||||
<Plus size={16} class="mr-2" /> Agregar Nuevo
|
||||
</Button>
|
||||
<div class="mt-6 flex h-[calc(100vh-120px)] flex-col">
|
||||
{#if !selectedArticle}
|
||||
<div class="space-y-4">
|
||||
<div class="flex items-center justify-between">
|
||||
<h3 class="text-lg font-medium">Artículos Disponibles</h3>
|
||||
{#if isAdmin}
|
||||
<Button variant="outline" size="sm" onclick={startCreate}>
|
||||
<Plus size={16} class="mr-2" /> <span>Agregar Nuevo</span>
|
||||
</Button>
|
||||
{/if}
|
||||
</div>
|
||||
{#if isLoading}
|
||||
<p class="py-10 text-center text-sm text-muted-foreground">Cargando...</p>
|
||||
{:else if articles.length === 0}
|
||||
<p class="py-10 text-center text-sm text-muted-foreground">
|
||||
No hay artículos de ayuda disponibles.
|
||||
</p>
|
||||
{/if}
|
||||
<div class="grid gap-2">
|
||||
{#each articles as article (article.uuid)}
|
||||
<button
|
||||
onclick={() => selectArticle(article)}
|
||||
class="flex flex-col items-start rounded-lg border p-4 text-left transition-colors hover:bg-accent"
|
||||
>
|
||||
<span class="font-semibold">{article.title}</span>
|
||||
<span class="text-xs text-muted-foreground">
|
||||
Última edición: {browser ? new Date(article.updated_at).toLocaleDateString() : article.updated_at.split('T')[0]}
|
||||
</span>
|
||||
</button>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="flex flex-1 flex-col gap-4">
|
||||
{#if isEditing}
|
||||
<div class="space-y-4">
|
||||
<input
|
||||
bind:value={editTitle}
|
||||
class="w-full rounded-md border bg-transparent p-2 text-xl font-bold"
|
||||
placeholder="Título del artículo"
|
||||
/>
|
||||
<textarea
|
||||
bind:value={editContent}
|
||||
class="min-h-[400px] w-full flex-1 rounded-md border bg-transparent p-4 font-mono text-sm focus:ring-1 focus:ring-primary focus:outline-none"
|
||||
placeholder="Escribe en Markdown..."
|
||||
></textarea>
|
||||
<div class="flex justify-end gap-2">
|
||||
<Button
|
||||
variant="outline"
|
||||
onclick={() => {
|
||||
isEditing = false;
|
||||
if (isCreating) selectedArticle = null;
|
||||
isCreating = false;
|
||||
}}
|
||||
>
|
||||
<X size={16} class="mr-2" /> <span>Cancelar</span>
|
||||
</Button>
|
||||
<Button onclick={saveChanges}>
|
||||
<Save size={16} class="mr-2" /> <span>Guardar Cambios</span>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="flex flex-col gap-4">
|
||||
<div class="flex items-center justify-between">
|
||||
<h2 class="text-2xl font-bold">{selectedArticle.title}</h2>
|
||||
{#if isAdmin}
|
||||
<Button variant="outline" size="sm" onclick={startEdit}>
|
||||
<Edit2 size={16} class="mr-2" /> <span>Editar</span>
|
||||
</Button>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="prose prose-sm max-w-none border-t pt-4 dark:prose-invert">
|
||||
{#if browser}
|
||||
{@html renderMarkdown(selectedArticle.content)}
|
||||
{:else}
|
||||
<div class="whitespace-pre-wrap">{selectedArticle.content}</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{#if isLoading}
|
||||
<p class="py-10 text-center text-sm text-muted-foreground">Cargando...</p>
|
||||
{:else if articles.length === 0}
|
||||
<p class="py-10 text-center text-sm text-muted-foreground">
|
||||
No hay artículos de ayuda disponibles.
|
||||
</p>
|
||||
{/if}
|
||||
<div class="grid gap-2">
|
||||
{#each articles as article}
|
||||
<button
|
||||
onclick={() => selectArticle(article)}
|
||||
class="flex flex-col items-start rounded-lg border p-4 text-left transition-colors hover:bg-accent"
|
||||
>
|
||||
<span class="font-semibold">{article.title}</span>
|
||||
<span class="text-xs text-muted-foreground"
|
||||
>Última edición: {new Date(article.updated_at).toLocaleDateString()}</span
|
||||
>
|
||||
</button>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="flex flex-1 flex-col gap-4">
|
||||
{#if isEditing}
|
||||
<div class="space-y-4">
|
||||
<input
|
||||
bind:value={editTitle}
|
||||
class="w-full rounded-md border bg-transparent p-2 text-xl font-bold"
|
||||
placeholder="Título del artículo"
|
||||
/>
|
||||
<textarea
|
||||
bind:value={editContent}
|
||||
class="min-h-[400px] w-full flex-1 rounded-md border bg-transparent p-4 font-mono text-sm focus:ring-1 focus:ring-primary focus:outline-none"
|
||||
placeholder="Escribe en Markdown..."
|
||||
></textarea>
|
||||
<div class="flex justify-end gap-2">
|
||||
<Button
|
||||
variant="outline"
|
||||
onclick={() => {
|
||||
isEditing = false;
|
||||
if (isCreating) selectedArticle = null;
|
||||
isCreating = false;
|
||||
}}
|
||||
>
|
||||
<X size={16} class="mr-2" /> Cancelar
|
||||
</Button>
|
||||
<Button onclick={saveChanges}>
|
||||
<Save size={16} class="mr-2" /> Guardar Cambios
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="flex flex-col gap-4">
|
||||
<div class="flex items-center justify-between">
|
||||
<h2 class="text-2xl font-bold">{selectedArticle.title}</h2>
|
||||
{#if isAdmin}
|
||||
<Button variant="outline" size="sm" onclick={startEdit}>
|
||||
<Edit2 size={16} class="mr-2" /> Editar
|
||||
</Button>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="prose prose-sm max-w-none border-t pt-4 dark:prose-invert">
|
||||
{@html renderMarkdown(selectedArticle.content)}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</Sheet.Content>
|
||||
</Sheet.Root>
|
||||
|
||||
|
||||
@@ -49,7 +49,8 @@ export function createSvelteTable<TData extends RowData>(options: TableOptions<T
|
||||
);
|
||||
|
||||
const table = createTable(resolvedOptions);
|
||||
let state = $state<Partial<TableState>>(table.initialState);
|
||||
// Use JSON parse/stringify to ensure we get a clean, non-proxy initial state object
|
||||
let state = $state<Partial<TableState>>(JSON.parse(JSON.stringify(table.initialState)));
|
||||
|
||||
function updateOptions() {
|
||||
table.setOptions((prev) => {
|
||||
@@ -105,8 +106,7 @@ export function mergeObjects<Sources extends readonly MaybeThunk<any>[]>(
|
||||
return new Proxy(Object.create(null), {
|
||||
get(_, key) {
|
||||
const src = findSourceWithKey(key);
|
||||
|
||||
return src?.[key as never];
|
||||
return src ? src[key as never] : undefined;
|
||||
},
|
||||
|
||||
has(_, key) {
|
||||
|
||||
Reference in New Issue
Block a user