feat: enhance absence management with new filters and reporting options, including PDF and Excel generation capabilities
This commit is contained in:
@@ -60,6 +60,36 @@
|
||||
const historico = $derived(historicoQuery?.data || []);
|
||||
const historicoAlteracoes = $derived(historicoAlteracoesQuery?.data || []);
|
||||
|
||||
// Dados para o gráfico de evolução
|
||||
const chartData = $derived(() => {
|
||||
if (!historico || historico.length === 0) return null;
|
||||
|
||||
// Ordenar por mês (crescente)
|
||||
const historicoOrdenado = [...historico].sort((a, b) => {
|
||||
if (a.mes < b.mes) return -1;
|
||||
if (a.mes > b.mes) return 1;
|
||||
return 0;
|
||||
});
|
||||
|
||||
return {
|
||||
labels: historicoOrdenado.map((h) => {
|
||||
const [ano, mesNum] = h.mes.split('-');
|
||||
const data = new Date(parseInt(ano), parseInt(mesNum) - 1, 1);
|
||||
return data.toLocaleDateString('pt-BR', { month: 'short', year: 'numeric' });
|
||||
}),
|
||||
datasets: [
|
||||
{
|
||||
label: 'Saldo Final (horas)',
|
||||
data: historicoOrdenado.map((h) => h.saldoFinalMinutos / 60),
|
||||
borderColor: 'rgb(59, 130, 246)',
|
||||
backgroundColor: 'rgba(59, 130, 246, 0.1)',
|
||||
tension: 0.4,
|
||||
fill: true
|
||||
}
|
||||
]
|
||||
};
|
||||
});
|
||||
|
||||
// Função para formatar mês
|
||||
function formatarMes(mes: string): string {
|
||||
const [ano, mesNum] = mes.split('-');
|
||||
@@ -476,22 +506,7 @@
|
||||
{/if}
|
||||
|
||||
<!-- Gráfico de Evolução -->
|
||||
{#if chartData}
|
||||
<div class="card bg-base-100 border-base-300 shadow-lg">
|
||||
<div class="card-body">
|
||||
<h3 class="mb-4 flex items-center gap-2 text-lg font-semibold">
|
||||
<TrendingUp class="h-5 w-5" strokeWidth={2} />
|
||||
Evolução do Banco de Horas
|
||||
</h3>
|
||||
<div class="h-64 w-full">
|
||||
<LineChart data={chartData} title="Evolução do Banco de Horas" height={256} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<!-- Gráfico de Evolução -->
|
||||
{#if chartData}
|
||||
{#if chartData && historico && historico.length > 0}
|
||||
<div class="card bg-base-100 border-base-300 shadow-lg">
|
||||
<div class="card-body">
|
||||
<h3 class="mb-4 flex items-center gap-2 text-lg font-semibold">
|
||||
|
||||
@@ -54,18 +54,17 @@
|
||||
erro = 'Usando relógio do PC';
|
||||
}
|
||||
|
||||
// Aplicar GMT offset ao timestamp
|
||||
// Quando GMT é 0, usar timestamp UTC puro e deixar toLocaleTimeString() fazer a conversão automática
|
||||
// Quando GMT ≠ 0, aplicar offset configurado ao timestamp
|
||||
// Aplicar GMT offset ao timestamp UTC
|
||||
// O offset é aplicado manualmente, então usamos UTC como base para evitar conversão dupla
|
||||
let timestampAjustado: number;
|
||||
if (gmtOffset !== 0) {
|
||||
// Aplicar offset configurado
|
||||
// Aplicar offset configurado ao timestamp UTC
|
||||
timestampAjustado = timestampBase + gmtOffset * 60 * 60 * 1000;
|
||||
} else {
|
||||
// Quando GMT = 0, manter timestamp UTC puro
|
||||
// O toLocaleTimeString() converterá automaticamente para o timezone local do navegador
|
||||
timestampAjustado = timestampBase;
|
||||
}
|
||||
// Armazenar o timestamp ajustado (não o Date, para evitar problemas de timezone)
|
||||
tempoAtual = new Date(timestampAjustado);
|
||||
} catch (error) {
|
||||
console.error('Erro ao obter tempo:', error);
|
||||
@@ -96,19 +95,25 @@
|
||||
});
|
||||
|
||||
const horaFormatada = $derived.by(() => {
|
||||
// Usar UTC como base pois já aplicamos o offset manualmente no timestamp
|
||||
// Isso evita conversão dupla pelo navegador
|
||||
return tempoAtual.toLocaleTimeString('pt-BR', {
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
second: '2-digit'
|
||||
second: '2-digit',
|
||||
timeZone: 'UTC' // Usar UTC como base pois já aplicamos o offset manualmente
|
||||
});
|
||||
});
|
||||
|
||||
const dataFormatada = $derived.by(() => {
|
||||
// Usar UTC como base pois já aplicamos o offset manualmente no timestamp
|
||||
// Isso evita conversão dupla pelo navegador
|
||||
return tempoAtual.toLocaleDateString('pt-BR', {
|
||||
weekday: 'long',
|
||||
day: '2-digit',
|
||||
month: 'long',
|
||||
year: 'numeric'
|
||||
year: 'numeric',
|
||||
timeZone: 'UTC' // Usar UTC como base pois já aplicamos o offset manualmente
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user