Merge branch 'feat-central-chamados' into feat-cibersecurity
This commit is contained in:
@@ -7,14 +7,12 @@
|
||||
import TicketTimeline from "$lib/components/chamados/TicketTimeline.svelte";
|
||||
import { chamadosStore } from "$lib/stores/chamados";
|
||||
import { resolve } from "$app/paths";
|
||||
import { useConvexWithAuth } from "$lib/hooks/useConvexWithAuth";
|
||||
|
||||
type Ticket = Doc<"tickets">;
|
||||
type SlaConfig = Doc<"slaConfigs">;
|
||||
|
||||
const client = useConvexClient();
|
||||
|
||||
let slaConfigs = $state<Array<SlaConfig>>([]);
|
||||
let carregandoSla = $state(true);
|
||||
let submitLoading = $state(false);
|
||||
let resetSignal = $state(0);
|
||||
let feedback = $state<{ tipo: "success" | "error"; mensagem: string; numero?: string } | null>(
|
||||
@@ -41,23 +39,11 @@
|
||||
},
|
||||
]);
|
||||
|
||||
onMount(() => {
|
||||
carregarSlaConfigs();
|
||||
$effect(() => {
|
||||
// Garante que o cliente Convex use o token do usuário logado
|
||||
useConvexWithAuth();
|
||||
});
|
||||
|
||||
async function carregarSlaConfigs() {
|
||||
try {
|
||||
carregandoSla = true;
|
||||
const lista = await client.query(api.chamados.listarSlaConfigs, {});
|
||||
slaConfigs = lista ?? [];
|
||||
} catch (error) {
|
||||
console.error("Erro ao carregar SLA:", error);
|
||||
slaConfigs = [];
|
||||
} finally {
|
||||
carregandoSla = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function uploadArquivo(file: File) {
|
||||
const uploadUrl = await client.mutation(api.chamados.generateUploadUrl, {});
|
||||
|
||||
@@ -98,7 +84,6 @@
|
||||
tipo: values.tipo,
|
||||
categoria: values.categoria,
|
||||
prioridade: values.prioridade,
|
||||
slaConfigId: values.slaConfigId,
|
||||
canalOrigem: values.canalOrigem,
|
||||
anexos,
|
||||
});
|
||||
@@ -186,53 +171,15 @@
|
||||
</p>
|
||||
<div class="mt-6">
|
||||
{#if resetSignal % 2 === 0}
|
||||
<TicketForm {slaConfigs} loading={submitLoading} on:submit={handleSubmit} />
|
||||
<TicketForm loading={submitLoading} on:submit={handleSubmit} />
|
||||
{:else}
|
||||
<TicketForm {slaConfigs} loading={submitLoading} on:submit={handleSubmit} />
|
||||
<TicketForm loading={submitLoading} on:submit={handleSubmit} />
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<aside class="space-y-6">
|
||||
<div class="rounded-3xl border border-base-200 bg-base-100/90 p-6 shadow-lg">
|
||||
<h3 class="font-semibold text-base-content">Configurações de SLA</h3>
|
||||
{#if carregandoSla}
|
||||
<div class="flex items-center justify-center py-6">
|
||||
<span class="loading loading-spinner loading-md"></span>
|
||||
</div>
|
||||
{:else if slaConfigs.length === 0}
|
||||
<p class="text-sm text-base-content/60">
|
||||
Nenhuma configuração customizada cadastrada. Os prazos padrão serão aplicados (Resposta:
|
||||
4h, Conclusão: 24h).
|
||||
</p>
|
||||
{:else}
|
||||
<div class="mt-4 space-y-4">
|
||||
{#each slaConfigs as sla (sla._id)}
|
||||
<div class="rounded-2xl border border-primary/20 bg-primary/5 p-4">
|
||||
<p class="text-sm font-semibold text-primary">{sla.nome}</p>
|
||||
<p class="text-xs text-base-content/60">{sla.descricao}</p>
|
||||
<div class="mt-3 grid grid-cols-2 gap-2 text-xs">
|
||||
<div class="rounded-xl bg-base-100/90 p-2 text-center">
|
||||
<p class="font-semibold">{sla.tempoRespostaHoras}h</p>
|
||||
<p class="text-base-content/60">Resposta</p>
|
||||
</div>
|
||||
<div class="rounded-xl bg-base-100/90 p-2 text-center">
|
||||
<p class="font-semibold">{sla.tempoConclusaoHoras}h</p>
|
||||
<p class="text-base-content/60">Conclusão</p>
|
||||
</div>
|
||||
</div>
|
||||
{#if sla.alertaAntecedenciaHoras}
|
||||
<p class="text-[11px] text-base-content/50 mt-2">
|
||||
Alerta {sla.alertaAntecedenciaHoras}h antes do prazo.
|
||||
</p>
|
||||
{/if}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="rounded-3xl border border-base-200 bg-base-100/90 p-6 shadow-lg">
|
||||
<h3 class="font-semibold text-base-content">Como funciona a timeline</h3>
|
||||
<p class="text-sm text-base-content/60 mb-4">
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { useConvexClient, useQuery } from 'convex-svelte';
|
||||
import { api } from '@sgse-app/backend/convex/_generated/api';
|
||||
import { resolve } from '$app/paths';
|
||||
import AprovarFerias from '$lib/components/AprovarFerias.svelte';
|
||||
import WizardSolicitacaoFerias from '$lib/components/ferias/WizardSolicitacaoFerias.svelte';
|
||||
import WizardSolicitacaoAusencia from '$lib/components/ausencias/WizardSolicitacaoAusencia.svelte';
|
||||
@@ -603,6 +604,29 @@ const meusTimesGestor = $derived(timesSubordinados);
|
||||
Minhas Ausências
|
||||
</button>
|
||||
|
||||
<a
|
||||
role="tab"
|
||||
href={resolve('/perfil/chamados')}
|
||||
class="tab tab-lg font-semibold transition-all duration-300 hover:bg-base-100"
|
||||
aria-label="Meus Chamados"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="mr-2 h-5 w-5"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d="M3 7h18M3 12h12M3 17h18"
|
||||
/>
|
||||
</svg>
|
||||
Meus Chamados
|
||||
</a>
|
||||
|
||||
{#if ehGestor}
|
||||
<button
|
||||
type="button"
|
||||
|
||||
@@ -14,6 +14,7 @@ import { chamadosStore } from "$lib/stores/chamados";
|
||||
prazoRestante,
|
||||
} from "$lib/utils/chamados";
|
||||
import { resolve } from "$app/paths";
|
||||
import { useConvexWithAuth } from "$lib/hooks/useConvexWithAuth";
|
||||
|
||||
type Ticket = Doc<"tickets">;
|
||||
|
||||
@@ -45,6 +46,10 @@ const ticketsFiltrados = $derived(
|
||||
onMount(() => {
|
||||
carregarChamados();
|
||||
});
|
||||
$effect(() => {
|
||||
// Configura o token de autenticação no cliente Convex
|
||||
useConvexWithAuth();
|
||||
});
|
||||
|
||||
async function carregarChamados() {
|
||||
try {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user