refactor: improve Svelte components and enhance user experience
- Updated various Svelte components to improve code readability and maintainability. - Standardized button classes across components for a consistent user interface. - Enhanced error handling and user feedback in modals and forms. - Cleaned up unnecessary imports and optimized component structure for better performance.
This commit is contained in:
@@ -1,426 +1,414 @@
|
||||
<script lang="ts">
|
||||
import { useConvexClient } from "convex-svelte";
|
||||
import { api } from "@sgse-app/backend/convex/_generated/api";
|
||||
import type { Id, Doc } from "@sgse-app/backend/convex/_generated/dataModel";
|
||||
import ErrorModal from "./ErrorModal.svelte";
|
||||
import { useConvexClient } from 'convex-svelte';
|
||||
import { api } from '@sgse-app/backend/convex/_generated/api';
|
||||
import type { Id, Doc } from '@sgse-app/backend/convex/_generated/dataModel';
|
||||
import ErrorModal from './ErrorModal.svelte';
|
||||
|
||||
type SolicitacaoAusencia = Doc<"solicitacoesAusencias"> & {
|
||||
funcionario?: Doc<"funcionarios"> | null;
|
||||
gestor?: Doc<"usuarios"> | null;
|
||||
time?: Doc<"times"> | null;
|
||||
};
|
||||
type SolicitacaoAusencia = Doc<'solicitacoesAusencias'> & {
|
||||
funcionario?: Doc<'funcionarios'> | null;
|
||||
gestor?: Doc<'usuarios'> | null;
|
||||
time?: Doc<'times'> | null;
|
||||
};
|
||||
|
||||
interface Props {
|
||||
solicitacao: SolicitacaoAusencia;
|
||||
gestorId: Id<"usuarios">;
|
||||
onSucesso?: () => void;
|
||||
onCancelar?: () => void;
|
||||
}
|
||||
interface Props {
|
||||
solicitacao: SolicitacaoAusencia;
|
||||
gestorId: Id<'usuarios'>;
|
||||
onSucesso?: () => void;
|
||||
onCancelar?: () => void;
|
||||
}
|
||||
|
||||
let { solicitacao, gestorId, onSucesso, onCancelar }: Props = $props();
|
||||
let { solicitacao, gestorId, onSucesso, onCancelar }: Props = $props();
|
||||
|
||||
const client = useConvexClient();
|
||||
const client = useConvexClient();
|
||||
|
||||
let motivoReprovacao = $state("");
|
||||
let processando = $state(false);
|
||||
let erro = $state("");
|
||||
let mostrarModalErro = $state(false);
|
||||
let mensagemErroModal = $state("");
|
||||
let motivoReprovacao = $state('');
|
||||
let processando = $state(false);
|
||||
let erro = $state('');
|
||||
let mostrarModalErro = $state(false);
|
||||
let mensagemErroModal = $state('');
|
||||
|
||||
function calcularDias(dataInicio: string, dataFim: string): number {
|
||||
const inicio = new Date(dataInicio);
|
||||
const fim = new Date(dataFim);
|
||||
const diff = fim.getTime() - inicio.getTime();
|
||||
return Math.ceil(diff / (1000 * 60 * 60 * 24)) + 1;
|
||||
}
|
||||
function calcularDias(dataInicio: string, dataFim: string): number {
|
||||
const inicio = new Date(dataInicio);
|
||||
const fim = new Date(dataFim);
|
||||
const diff = fim.getTime() - inicio.getTime();
|
||||
return Math.ceil(diff / (1000 * 60 * 60 * 24)) + 1;
|
||||
}
|
||||
|
||||
const totalDias = $derived(
|
||||
calcularDias(solicitacao.dataInicio, solicitacao.dataFim),
|
||||
);
|
||||
const totalDias = $derived(calcularDias(solicitacao.dataInicio, solicitacao.dataFim));
|
||||
|
||||
async function aprovar() {
|
||||
try {
|
||||
processando = true;
|
||||
erro = "";
|
||||
mostrarModalErro = false;
|
||||
async function aprovar() {
|
||||
try {
|
||||
processando = true;
|
||||
erro = '';
|
||||
mostrarModalErro = false;
|
||||
|
||||
await client.mutation(api.ausencias.aprovar, {
|
||||
solicitacaoId: solicitacao._id,
|
||||
gestorId: gestorId,
|
||||
});
|
||||
await client.mutation(api.ausencias.aprovar, {
|
||||
solicitacaoId: solicitacao._id,
|
||||
gestorId: gestorId
|
||||
});
|
||||
|
||||
if (onSucesso) onSucesso();
|
||||
} catch (e) {
|
||||
const mensagemErro = e instanceof Error ? e.message : String(e);
|
||||
if (onSucesso) onSucesso();
|
||||
} catch (e) {
|
||||
const mensagemErro = e instanceof Error ? e.message : String(e);
|
||||
|
||||
// Verificar se é erro de permissão
|
||||
if (
|
||||
mensagemErro.includes("permissão") ||
|
||||
mensagemErro.includes("permission") ||
|
||||
mensagemErro.includes("Você não tem permissão")
|
||||
) {
|
||||
mensagemErroModal =
|
||||
"Você não tem permissão para aprovar esta solicitação de ausência. Apenas o gestor responsável pelo time do funcionário pode realizar esta ação.";
|
||||
mostrarModalErro = true;
|
||||
} else {
|
||||
erro = mensagemErro;
|
||||
}
|
||||
} finally {
|
||||
processando = false;
|
||||
}
|
||||
}
|
||||
// Verificar se é erro de permissão
|
||||
if (
|
||||
mensagemErro.includes('permissão') ||
|
||||
mensagemErro.includes('permission') ||
|
||||
mensagemErro.includes('Você não tem permissão')
|
||||
) {
|
||||
mensagemErroModal =
|
||||
'Você não tem permissão para aprovar esta solicitação de ausência. Apenas o gestor responsável pelo time do funcionário pode realizar esta ação.';
|
||||
mostrarModalErro = true;
|
||||
} else {
|
||||
erro = mensagemErro;
|
||||
}
|
||||
} finally {
|
||||
processando = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function reprovar() {
|
||||
if (!motivoReprovacao.trim()) {
|
||||
erro = "Informe o motivo da reprovação";
|
||||
return;
|
||||
}
|
||||
async function reprovar() {
|
||||
if (!motivoReprovacao.trim()) {
|
||||
erro = 'Informe o motivo da reprovação';
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
processando = true;
|
||||
erro = "";
|
||||
mostrarModalErro = false;
|
||||
try {
|
||||
processando = true;
|
||||
erro = '';
|
||||
mostrarModalErro = false;
|
||||
|
||||
await client.mutation(api.ausencias.reprovar, {
|
||||
solicitacaoId: solicitacao._id,
|
||||
gestorId: gestorId,
|
||||
motivoReprovacao: motivoReprovacao.trim(),
|
||||
});
|
||||
await client.mutation(api.ausencias.reprovar, {
|
||||
solicitacaoId: solicitacao._id,
|
||||
gestorId: gestorId,
|
||||
motivoReprovacao: motivoReprovacao.trim()
|
||||
});
|
||||
|
||||
if (onSucesso) onSucesso();
|
||||
} catch (e) {
|
||||
const mensagemErro = e instanceof Error ? e.message : String(e);
|
||||
if (onSucesso) onSucesso();
|
||||
} catch (e) {
|
||||
const mensagemErro = e instanceof Error ? e.message : String(e);
|
||||
|
||||
// Verificar se é erro de permissão
|
||||
if (
|
||||
mensagemErro.includes("permissão") ||
|
||||
mensagemErro.includes("permission") ||
|
||||
mensagemErro.includes("Você não tem permissão")
|
||||
) {
|
||||
mensagemErroModal =
|
||||
"Você não tem permissão para reprovar esta solicitação de ausência. Apenas o gestor responsável pelo time do funcionário pode realizar esta ação.";
|
||||
mostrarModalErro = true;
|
||||
} else {
|
||||
erro = mensagemErro;
|
||||
}
|
||||
} finally {
|
||||
processando = false;
|
||||
}
|
||||
}
|
||||
// Verificar se é erro de permissão
|
||||
if (
|
||||
mensagemErro.includes('permissão') ||
|
||||
mensagemErro.includes('permission') ||
|
||||
mensagemErro.includes('Você não tem permissão')
|
||||
) {
|
||||
mensagemErroModal =
|
||||
'Você não tem permissão para reprovar esta solicitação de ausência. Apenas o gestor responsável pelo time do funcionário pode realizar esta ação.';
|
||||
mostrarModalErro = true;
|
||||
} else {
|
||||
erro = mensagemErro;
|
||||
}
|
||||
} finally {
|
||||
processando = false;
|
||||
}
|
||||
}
|
||||
|
||||
function fecharModalErro() {
|
||||
mostrarModalErro = false;
|
||||
mensagemErroModal = "";
|
||||
}
|
||||
function fecharModalErro() {
|
||||
mostrarModalErro = false;
|
||||
mensagemErroModal = '';
|
||||
}
|
||||
|
||||
function getStatusBadge(status: string) {
|
||||
const badges: Record<string, string> = {
|
||||
aguardando_aprovacao: "badge-warning",
|
||||
aprovado: "badge-success",
|
||||
reprovado: "badge-error",
|
||||
};
|
||||
return badges[status] || "badge-neutral";
|
||||
}
|
||||
function getStatusBadge(status: string) {
|
||||
const badges: Record<string, string> = {
|
||||
aguardando_aprovacao: 'badge-warning',
|
||||
aprovado: 'badge-success',
|
||||
reprovado: 'badge-error'
|
||||
};
|
||||
return badges[status] || 'badge-neutral';
|
||||
}
|
||||
|
||||
function getStatusTexto(status: string) {
|
||||
const textos: Record<string, string> = {
|
||||
aguardando_aprovacao: "Aguardando Aprovação",
|
||||
aprovado: "Aprovado",
|
||||
reprovado: "Reprovado",
|
||||
};
|
||||
return textos[status] || status;
|
||||
}
|
||||
function getStatusTexto(status: string) {
|
||||
const textos: Record<string, string> = {
|
||||
aguardando_aprovacao: 'Aguardando Aprovação',
|
||||
aprovado: 'Aprovado',
|
||||
reprovado: 'Reprovado'
|
||||
};
|
||||
return textos[status] || status;
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="aprovar-ausencia">
|
||||
<!-- Header -->
|
||||
<div class="mb-6">
|
||||
<h2 class="text-3xl font-bold text-primary mb-2">
|
||||
Aprovar/Reprovar Ausência
|
||||
</h2>
|
||||
<p class="text-base-content/70">Analise a solicitação e tome uma decisão</p>
|
||||
</div>
|
||||
<!-- Header -->
|
||||
<div class="mb-6">
|
||||
<h2 class="text-primary mb-2 text-3xl font-bold">Aprovar/Reprovar Ausência</h2>
|
||||
<p class="text-base-content/70">Analise a solicitação e tome uma decisão</p>
|
||||
</div>
|
||||
|
||||
<!-- Card Principal -->
|
||||
<div class="card bg-base-100 shadow-2xl border-t-4 border-orange-500">
|
||||
<div class="card-body">
|
||||
<!-- Informações do Funcionário -->
|
||||
<div class="mb-6">
|
||||
<h3 class="text-xl font-bold mb-4 flex items-center gap-2">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-6 w-6 text-primary"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"
|
||||
/>
|
||||
</svg>
|
||||
Funcionário
|
||||
</h3>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<p class="text-sm text-base-content/70">Nome</p>
|
||||
<p class="font-bold text-lg">
|
||||
{solicitacao.funcionario?.nome || "N/A"}
|
||||
</p>
|
||||
</div>
|
||||
{#if solicitacao.time}
|
||||
<div>
|
||||
<p class="text-sm text-base-content/70">Time</p>
|
||||
<div
|
||||
class="badge badge-lg font-semibold"
|
||||
style="background-color: {solicitacao.time
|
||||
.cor}20; border-color: {solicitacao.time
|
||||
.cor}; color: {solicitacao.time.cor}"
|
||||
>
|
||||
{solicitacao.time.nome}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<!-- Card Principal -->
|
||||
<div class="card bg-base-100 border-t-4 border-orange-500 shadow-2xl">
|
||||
<div class="card-body">
|
||||
<!-- Informações do Funcionário -->
|
||||
<div class="mb-6">
|
||||
<h3 class="mb-4 flex items-center gap-2 text-xl font-bold">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="text-primary h-6 w-6"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"
|
||||
/>
|
||||
</svg>
|
||||
Funcionário
|
||||
</h3>
|
||||
<div class="grid grid-cols-1 gap-4 md:grid-cols-2">
|
||||
<div>
|
||||
<p class="text-base-content/70 text-sm">Nome</p>
|
||||
<p class="text-lg font-bold">
|
||||
{solicitacao.funcionario?.nome || 'N/A'}
|
||||
</p>
|
||||
</div>
|
||||
{#if solicitacao.time}
|
||||
<div>
|
||||
<p class="text-base-content/70 text-sm">Time</p>
|
||||
<div
|
||||
class="badge badge-lg font-semibold"
|
||||
style="background-color: {solicitacao.time.cor}20; border-color: {solicitacao.time
|
||||
.cor}; color: {solicitacao.time.cor}"
|
||||
>
|
||||
{solicitacao.time.nome}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="divider"></div>
|
||||
<div class="divider"></div>
|
||||
|
||||
<!-- Período da Ausência -->
|
||||
<div class="mb-6">
|
||||
<h3 class="text-xl font-bold mb-4 flex items-center gap-2">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-6 w-6 text-primary"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
|
||||
/>
|
||||
</svg>
|
||||
Período da Ausência
|
||||
</h3>
|
||||
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||
<div
|
||||
class="stat bg-linear-to-br from-orange-50 to-amber-50 dark:from-orange-950 dark:to-amber-950 rounded-xl border-2 border-orange-500/30"
|
||||
>
|
||||
<div class="stat-title">Data Início</div>
|
||||
<div
|
||||
class="stat-value text-orange-600 dark:text-orange-400 text-2xl"
|
||||
>
|
||||
{new Date(solicitacao.dataInicio).toLocaleDateString("pt-BR")}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="stat bg-linear-to-br from-orange-50 to-amber-50 dark:from-orange-950 dark:to-amber-950 rounded-xl border-2 border-orange-500/30"
|
||||
>
|
||||
<div class="stat-title">Data Fim</div>
|
||||
<div
|
||||
class="stat-value text-orange-600 dark:text-orange-400 text-2xl"
|
||||
>
|
||||
{new Date(solicitacao.dataFim).toLocaleDateString("pt-BR")}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="stat bg-linear-to-br from-orange-50 to-amber-50 dark:from-orange-950 dark:to-amber-950 rounded-xl border-2 border-orange-500/30"
|
||||
>
|
||||
<div class="stat-title">Total de Dias</div>
|
||||
<div
|
||||
class="stat-value text-orange-600 dark:text-orange-400 text-3xl"
|
||||
>
|
||||
{totalDias}
|
||||
</div>
|
||||
<div class="stat-desc">dias corridos</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Período da Ausência -->
|
||||
<div class="mb-6">
|
||||
<h3 class="mb-4 flex items-center gap-2 text-xl font-bold">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="text-primary h-6 w-6"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
|
||||
/>
|
||||
</svg>
|
||||
Período da Ausência
|
||||
</h3>
|
||||
<div class="grid grid-cols-1 gap-4 md:grid-cols-3">
|
||||
<div
|
||||
class="stat rounded-xl border-2 border-orange-500/30 bg-linear-to-br from-orange-50 to-amber-50 dark:from-orange-950 dark:to-amber-950"
|
||||
>
|
||||
<div class="stat-title">Data Início</div>
|
||||
<div class="stat-value text-2xl text-orange-600 dark:text-orange-400">
|
||||
{new Date(solicitacao.dataInicio).toLocaleDateString('pt-BR')}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="stat rounded-xl border-2 border-orange-500/30 bg-linear-to-br from-orange-50 to-amber-50 dark:from-orange-950 dark:to-amber-950"
|
||||
>
|
||||
<div class="stat-title">Data Fim</div>
|
||||
<div class="stat-value text-2xl text-orange-600 dark:text-orange-400">
|
||||
{new Date(solicitacao.dataFim).toLocaleDateString('pt-BR')}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="stat rounded-xl border-2 border-orange-500/30 bg-linear-to-br from-orange-50 to-amber-50 dark:from-orange-950 dark:to-amber-950"
|
||||
>
|
||||
<div class="stat-title">Total de Dias</div>
|
||||
<div class="stat-value text-3xl text-orange-600 dark:text-orange-400">
|
||||
{totalDias}
|
||||
</div>
|
||||
<div class="stat-desc">dias corridos</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="divider"></div>
|
||||
<div class="divider"></div>
|
||||
|
||||
<!-- Motivo -->
|
||||
<div class="mb-6">
|
||||
<h3 class="text-xl font-bold mb-4 flex items-center gap-2">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-6 w-6 text-primary"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"
|
||||
/>
|
||||
</svg>
|
||||
Motivo da Ausência
|
||||
</h3>
|
||||
<div class="card bg-base-200">
|
||||
<div class="card-body">
|
||||
<p class="whitespace-pre-wrap">{solicitacao.motivo}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Motivo -->
|
||||
<div class="mb-6">
|
||||
<h3 class="mb-4 flex items-center gap-2 text-xl font-bold">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="text-primary h-6 w-6"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"
|
||||
/>
|
||||
</svg>
|
||||
Motivo da Ausência
|
||||
</h3>
|
||||
<div class="card bg-base-200">
|
||||
<div class="card-body">
|
||||
<p class="whitespace-pre-wrap">{solicitacao.motivo}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Status Atual -->
|
||||
<div class="mb-6">
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="text-sm font-semibold">Status:</span>
|
||||
<div class={`badge badge-lg ${getStatusBadge(solicitacao.status)}`}>
|
||||
{getStatusTexto(solicitacao.status)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Status Atual -->
|
||||
<div class="mb-6">
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="text-sm font-semibold">Status:</span>
|
||||
<div class={`badge badge-lg ${getStatusBadge(solicitacao.status)}`}>
|
||||
{getStatusTexto(solicitacao.status)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Erro -->
|
||||
{#if erro}
|
||||
<div class="alert alert-error mb-4">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="stroke-current shrink-0 h-6 w-6"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z"
|
||||
/>
|
||||
</svg>
|
||||
<span>{erro}</span>
|
||||
</div>
|
||||
{/if}
|
||||
<!-- Erro -->
|
||||
{#if erro}
|
||||
<div class="alert alert-error mb-4">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-6 w-6 shrink-0 stroke-current"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z"
|
||||
/>
|
||||
</svg>
|
||||
<span>{erro}</span>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<!-- Ações -->
|
||||
{#if solicitacao.status === "aguardando_aprovacao"}
|
||||
<div class="card-actions justify-end gap-4 mt-6">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-error btn-lg gap-2"
|
||||
onclick={reprovar}
|
||||
disabled={processando}
|
||||
>
|
||||
{#if processando}
|
||||
<span class="loading loading-spinner"></span>
|
||||
{:else}
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-5 w-5"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M6 18L18 6M6 6l12 12"
|
||||
/>
|
||||
</svg>
|
||||
{/if}
|
||||
Reprovar
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-success btn-lg gap-2"
|
||||
onclick={aprovar}
|
||||
disabled={processando}
|
||||
>
|
||||
{#if processando}
|
||||
<span class="loading loading-spinner"></span>
|
||||
{:else}
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-5 w-5"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M5 13l4 4L19 7"
|
||||
/>
|
||||
</svg>
|
||||
{/if}
|
||||
Aprovar
|
||||
</button>
|
||||
</div>
|
||||
<!-- Ações -->
|
||||
{#if solicitacao.status === 'aguardando_aprovacao'}
|
||||
<div class="card-actions mt-6 justify-end gap-4">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-error btn-lg gap-2"
|
||||
onclick={reprovar}
|
||||
disabled={processando}
|
||||
>
|
||||
{#if processando}
|
||||
<span class="loading loading-spinner"></span>
|
||||
{:else}
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-5 w-5"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M6 18L18 6M6 6l12 12"
|
||||
/>
|
||||
</svg>
|
||||
{/if}
|
||||
Reprovar
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-success btn-lg gap-2"
|
||||
onclick={aprovar}
|
||||
disabled={processando}
|
||||
>
|
||||
{#if processando}
|
||||
<span class="loading loading-spinner"></span>
|
||||
{:else}
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-5 w-5"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M5 13l4 4L19 7"
|
||||
/>
|
||||
</svg>
|
||||
{/if}
|
||||
Aprovar
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Modal de Reprovação -->
|
||||
{#if motivoReprovacao !== undefined}
|
||||
<div class="mt-4">
|
||||
<div class="form-control">
|
||||
<label class="label" for="motivo-reprovacao">
|
||||
<span class="label-text font-bold">Motivo da Reprovação</span>
|
||||
</label>
|
||||
<textarea
|
||||
id="motivo-reprovacao"
|
||||
class="textarea textarea-bordered h-24"
|
||||
placeholder="Informe o motivo da reprovação..."
|
||||
bind:value={motivoReprovacao}
|
||||
></textarea>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{:else}
|
||||
<div class="alert alert-info">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
class="stroke-current shrink-0 w-6 h-6"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
|
||||
></path>
|
||||
</svg>
|
||||
<span>Esta solicitação já foi processada.</span>
|
||||
</div>
|
||||
{/if}
|
||||
<!-- Modal de Reprovação -->
|
||||
{#if motivoReprovacao !== undefined}
|
||||
<div class="mt-4">
|
||||
<div class="form-control">
|
||||
<label class="label" for="motivo-reprovacao">
|
||||
<span class="label-text font-bold">Motivo da Reprovação</span>
|
||||
</label>
|
||||
<textarea
|
||||
id="motivo-reprovacao"
|
||||
class="textarea textarea-bordered h-24"
|
||||
placeholder="Informe o motivo da reprovação..."
|
||||
bind:value={motivoReprovacao}
|
||||
></textarea>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{:else}
|
||||
<div class="alert alert-info">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
class="h-6 w-6 shrink-0 stroke-current"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
|
||||
></path>
|
||||
</svg>
|
||||
<span>Esta solicitação já foi processada.</span>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<!-- Botão Cancelar -->
|
||||
<div class="mt-4 text-center">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-ghost"
|
||||
onclick={() => {
|
||||
if (onCancelar) onCancelar();
|
||||
}}
|
||||
disabled={processando}
|
||||
>
|
||||
Fechar
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Botão Cancelar -->
|
||||
<div class="mt-4 text-center">
|
||||
<button
|
||||
type="button"
|
||||
class="btn"
|
||||
onclick={() => {
|
||||
if (onCancelar) onCancelar();
|
||||
}}
|
||||
disabled={processando}
|
||||
>
|
||||
Fechar
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal de Erro -->
|
||||
<ErrorModal
|
||||
open={mostrarModalErro}
|
||||
title="Erro de Permissão"
|
||||
message={mensagemErroModal ||
|
||||
"Você não tem permissão para realizar esta ação."}
|
||||
onClose={fecharModalErro}
|
||||
open={mostrarModalErro}
|
||||
title="Erro de Permissão"
|
||||
message={mensagemErroModal || 'Você não tem permissão para realizar esta ação.'}
|
||||
onClose={fecharModalErro}
|
||||
/>
|
||||
|
||||
<style>
|
||||
.aprovar-ausencia {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.aprovar-ausencia {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user