Fix page with lint errors #18
@@ -3,7 +3,7 @@
|
|||||||
import {
|
import {
|
||||||
ExternalLink,
|
ExternalLink,
|
||||||
FileText,
|
FileText,
|
||||||
File,
|
File as FileIcon,
|
||||||
Upload,
|
Upload,
|
||||||
Trash2,
|
Trash2,
|
||||||
Eye,
|
Eye,
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
value?: string; // storageId
|
value?: string; // storageId
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
required?: boolean;
|
required?: boolean;
|
||||||
onUpload: (file: File) => Promise<void>;
|
onUpload: (file: globalThis.File) => Promise<void>;
|
||||||
onRemove: () => Promise<void>;
|
onRemove: () => Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,38 +48,33 @@
|
|||||||
"image/png",
|
"image/png",
|
||||||
];
|
];
|
||||||
|
|
||||||
// Buscar URL do arquivo quando houver um storageId
|
// Buscar URL do arquivo quando houver um storageId
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
if (value && !fileName) {
|
if (value && !fileName) {
|
||||||
// Tem storageId mas não é um upload recente
|
// Tem storageId mas não é um upload recente
|
||||||
loadExistingFile(value);
|
loadExistingFile(value);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
async function loadExistingFile(storageId: string) {
|
|
||||||
try {
|
|
||||||
const url = await client.storage.getUrl(storageId as any);
|
|
||||||
if (url) {
|
|
||||||
fileUrl = url;
|
|
||||||
fileName = "Documento anexado";
|
|
||||||
// Detectar tipo pelo URL ou assumir PDF
|
|
||||||
if (url.includes(".pdf") || url.includes("application/pdf")) {
|
|
||||||
fileType = "application/pdf";
|
|
||||||
} else {
|
|
||||||
fileType = "image/jpeg";
|
|
||||||
previewUrl = url; // Para imagens, a URL serve como preview
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Erro ao carregar arquivo existente:", err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
async function loadExistingFile(storageId: string) {
|
||||||
|
try {
|
||||||
|
const url = await client.storage.getUrl(storageId as any);
|
||||||
|
if (url) {
|
||||||
async function handleFileSelect(event: Event) {
|
async function handleFileSelect(event: Event) {
|
||||||
const target = event.target as HTMLInputElement;
|
const target = event.target as HTMLInputElement;
|
||||||
const file = target.files?.[0];
|
const file = target.files?.[0];
|
||||||
|
// Detectar tipo pelo URL ou assumir PDF
|
||||||
if (!file) return;
|
if (url.includes('.pdf') || url.includes('application/pdf')) {
|
||||||
|
fileType = 'application/pdf';
|
||||||
|
} else {
|
||||||
|
fileType = 'image/jpeg';
|
||||||
|
previewUrl = url; // Para imagens, a URL serve como preview
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Erro ao carregar arquivo existente:', err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
error = null;
|
error = null;
|
||||||
|
|
||||||
@@ -187,32 +182,22 @@
|
|||||||
{disabled}
|
{disabled}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{#if value || fileName}
|
{#if value || fileName}
|
||||||
<div
|
<div class="border-base-300 bg-base-100 flex items-center gap-2 rounded-lg border p-3">
|
||||||
class="flex items-center gap-2 p-3 border border-base-300 rounded-lg bg-base-100"
|
<!-- Preview -->
|
||||||
>
|
<div class="shrink-0">
|
||||||
<!-- Preview -->
|
{#if previewUrl}
|
||||||
<div class="shrink-0">
|
<img src={previewUrl} alt="Preview" class="h-12 w-12 rounded object-cover" />
|
||||||
{#if previewUrl}
|
{:else if fileType === 'application/pdf' || fileName.endsWith('.pdf')}
|
||||||
<img
|
<div class="bg-error/10 flex h-12 w-12 items-center justify-center rounded">
|
||||||
src={previewUrl}
|
<FileText class="text-error h-6 w-6" strokeWidth={2} />
|
||||||
alt="Preview"
|
</div>
|
||||||
class="w-12 h-12 object-cover rounded"
|
{:else}
|
||||||
/>
|
<div class="bg-success/10 flex h-12 w-12 items-center justify-center rounded">
|
||||||
{:else if fileType === "application/pdf" || fileName.endsWith(".pdf")}
|
<File class="text-success h-6 w-6" strokeWidth={2} />
|
||||||
<div
|
</div>
|
||||||
class="w-12 h-12 bg-error/10 rounded flex items-center justify-center"
|
{/if}
|
||||||
>
|
</div>
|
||||||
<FileText class="h-6 w-6 text-error" strokeWidth={2} />
|
|
||||||
</div>
|
|
||||||
{:else}
|
|
||||||
<div
|
|
||||||
class="w-12 h-12 bg-success/10 rounded flex items-center justify-center"
|
|
||||||
>
|
|
||||||
<File class="h-6 w-6 text-success" strokeWidth={2} />
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- File info -->
|
<!-- File info -->
|
||||||
<div class="flex-1 min-w-0">
|
<div class="flex-1 min-w-0">
|
||||||
|
|||||||
@@ -11,15 +11,16 @@
|
|||||||
categoriasDocumentos,
|
categoriasDocumentos,
|
||||||
getDocumentosByCategoria
|
getDocumentosByCategoria
|
||||||
} from '$lib/utils/documentos';
|
} from '$lib/utils/documentos';
|
||||||
|
import type { Id, Doc } from '@sgse-app/backend/convex/_generated/dataModel';
|
||||||
|
|
||||||
const client = useConvexClient();
|
const client = useConvexClient();
|
||||||
|
|
||||||
let funcionarioId = $derived($page.params.funcionarioId as string);
|
let funcionarioId = $derived($page.params.funcionarioId as Id<'funcionarios'>);
|
||||||
|
|
||||||
let funcionario = $state<any>(null);
|
let funcionario = $state<Doc<'funcionarios'> | null>(null);
|
||||||
let documentosStorage = $state<Record<string, string | undefined>>({});
|
let documentosStorage = $state<Record<string, string | undefined>>({});
|
||||||
let loading = $state(true);
|
let loading = $state(true);
|
||||||
let filtro = $state<string>('todos'); // todos, enviados, pendentes
|
let filtro = $state<'todos' | 'enviados' | 'pendentes'>('todos'); // todos, enviados, pendentes
|
||||||
|
|
||||||
async function load() {
|
async function load() {
|
||||||
try {
|
try {
|
||||||
@@ -27,7 +28,7 @@
|
|||||||
|
|
||||||
// Carregar dados do funcionário
|
// Carregar dados do funcionário
|
||||||
const data = await client.query(api.funcionarios.getById, {
|
const data = await client.query(api.funcionarios.getById, {
|
||||||
id: funcionarioId as any
|
id: funcionarioId
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!data) {
|
if (!data) {
|
||||||
@@ -39,8 +40,10 @@
|
|||||||
|
|
||||||
// Mapear storage IDs dos documentos
|
// Mapear storage IDs dos documentos
|
||||||
documentos.forEach((doc) => {
|
documentos.forEach((doc) => {
|
||||||
if ((data as any)[doc.campo]) {
|
const campo = doc.campo as keyof Doc<'funcionarios'>;
|
||||||
documentosStorage[doc.campo] = (data as any)[doc.campo];
|
const valor = data[campo];
|
||||||
|
if (typeof valor === 'string') {
|
||||||
|
documentosStorage[doc.campo] = valor;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -63,13 +66,23 @@
|
|||||||
body: file
|
body: file
|
||||||
});
|
});
|
||||||
|
|
||||||
const { storageId } = await result.json();
|
const uploadResponse = await result.json();
|
||||||
|
if (
|
||||||
|
!uploadResponse ||
|
||||||
|
typeof uploadResponse !== 'object' ||
|
||||||
|
!('storageId' in uploadResponse) ||
|
||||||
|
typeof uploadResponse.storageId !== 'string'
|
||||||
|
) {
|
||||||
|
throw new Error('Resposta inválida ao fazer upload');
|
||||||
|
}
|
||||||
|
|
||||||
|
const storageId = uploadResponse.storageId;
|
||||||
|
|
||||||
// Atualizar documento no funcionário
|
// Atualizar documento no funcionário
|
||||||
await client.mutation(api.documentos.updateDocumento, {
|
await client.mutation(api.documentos.updateDocumento, {
|
||||||
funcionarioId: funcionarioId as any,
|
funcionarioId,
|
||||||
campo,
|
campo,
|
||||||
storageId: storageId as any
|
storageId: storageId as Id<'_storage'>
|
||||||
});
|
});
|
||||||
|
|
||||||
// Atualizar localmente
|
// Atualizar localmente
|
||||||
@@ -77,8 +90,11 @@
|
|||||||
|
|
||||||
// Recarregar
|
// Recarregar
|
||||||
await load();
|
await load();
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
throw new Error(err?.message || 'Erro ao fazer upload');
|
if (err instanceof Error && err.message) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
throw new Error('Erro ao fazer upload');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,7 +102,7 @@
|
|||||||
try {
|
try {
|
||||||
// Atualizar documento no funcionário (set to null)
|
// Atualizar documento no funcionário (set to null)
|
||||||
await client.mutation(api.documentos.updateDocumento, {
|
await client.mutation(api.documentos.updateDocumento, {
|
||||||
funcionarioId: funcionarioId as any,
|
funcionarioId,
|
||||||
campo,
|
campo,
|
||||||
storageId: null
|
storageId: null
|
||||||
});
|
});
|
||||||
@@ -96,8 +112,10 @@
|
|||||||
|
|
||||||
// Recarregar
|
// Recarregar
|
||||||
await load();
|
await load();
|
||||||
} catch (err: any) {
|
} catch (err) {
|
||||||
alert('Erro ao remover documento: ' + (err?.message || ''));
|
const mensagem =
|
||||||
|
err instanceof Error && err.message ? err.message : 'Erro ao remover documento';
|
||||||
|
alert('Erro ao remover documento: ' + mensagem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,7 +148,9 @@
|
|||||||
<div class="breadcrumbs mb-4 text-sm">
|
<div class="breadcrumbs mb-4 text-sm">
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<a href={resolve('/recursos-humanos')} class="text-primary hover:underline">Recursos Humanos</a>
|
<a href={resolve('/recursos-humanos')} class="text-primary hover:underline"
|
||||||
|
>Recursos Humanos</a
|
||||||
|
>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href={resolve('/recursos-humanos/funcionarios')} class="text-primary hover:underline"
|
<a href={resolve('/recursos-humanos/funcionarios')} class="text-primary hover:underline"
|
||||||
@@ -305,7 +325,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Documentos por Categoria -->
|
<!-- Documentos por Categoria -->
|
||||||
{#each categoriasDocumentos as categoria}
|
{#each categoriasDocumentos as categoria (categoria)}
|
||||||
{@const docsCategoria = getDocumentosByCategoria(categoria).filter((doc) => {
|
{@const docsCategoria = getDocumentosByCategoria(categoria).filter((doc) => {
|
||||||
const temDocumento = !!documentosStorage[doc.campo];
|
const temDocumento = !!documentosStorage[doc.campo];
|
||||||
if (filtro === 'enviados') return temDocumento;
|
if (filtro === 'enviados') return temDocumento;
|
||||||
@@ -322,7 +342,7 @@
|
|||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<div class="grid grid-cols-1 gap-4 md:grid-cols-2">
|
<div class="grid grid-cols-1 gap-4 md:grid-cols-2">
|
||||||
{#each docsCategoria as doc}
|
{#each docsCategoria as doc (doc.campo)}
|
||||||
<FileUpload
|
<FileUpload
|
||||||
label={doc.nome}
|
label={doc.nome}
|
||||||
helpUrl={doc.helpUrl}
|
helpUrl={doc.helpUrl}
|
||||||
|
|||||||
@@ -483,7 +483,9 @@
|
|||||||
<div class="breadcrumbs mb-4 text-sm">
|
<div class="breadcrumbs mb-4 text-sm">
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<a href={resolve('/recursos-humanos')} class="text-primary hover:underline">Recursos Humanos</a>
|
<a href={resolve('/recursos-humanos')} class="text-primary hover:underline"
|
||||||
|
>Recursos Humanos</a
|
||||||
|
>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href={resolve('/recursos-humanos/funcionarios')} class="text-primary hover:underline"
|
<a href={resolve('/recursos-humanos/funcionarios')} class="text-primary hover:underline"
|
||||||
|
|||||||
Reference in New Issue
Block a user