Agenda, Agendador, Configurações

This commit is contained in:
Leonardo
2026-03-12 08:58:36 -03:00
parent f733db8436
commit f4b185ae17
197 changed files with 33405 additions and 6507 deletions
+119
View File
@@ -0,0 +1,119 @@
// src/composables/useFeriados.js
// Fonte única de verdade para feriados: nacionais (algoritmo) + municipais (Supabase).
import { ref, computed } from 'vue'
import { supabase } from '@/lib/supabase/client'
import { getFeriadosNacionais } from '@/utils/feriadosBR'
export function useFeriados () {
const ano = ref(new Date().getFullYear())
const loading = ref(false)
const municipais = ref([]) // linhas da tabela `feriados`
// ── Nacionais (algoritmo, sem DB) ─────────────────────────
const nacionais = computed(() =>
getFeriadosNacionais(ano.value).map(f => ({ ...f, tipo: 'nacional' }))
)
// ── Todos juntos, ordenados por data ─────────────────────
const todos = computed(() => [
...nacionais.value,
...municipais.value.map(f => ({ ...f, tipo: f.tipo || 'municipal' }))
].sort((a, b) => a.data.localeCompare(b.data)))
// ── Feriados de um mês (112) ─────────────────────────────
function doMes (mes) {
const m = String(mes).padStart(2, '0')
const prefix = `${ano.value}-${m}`
return todos.value.filter(f => f.data.startsWith(prefix))
}
// ── Próximos N dias ───────────────────────────────────────
function proximos (dias = 30) {
const hoje = new Date()
const limite = new Date(hoje)
limite.setDate(limite.getDate() + dias)
const hojeISO = toISO(hoje)
const limiteISO = toISO(limite)
return todos.value.filter(f => f.data >= hojeISO && f.data <= limiteISO)
}
function toISO (d) {
return `${d.getFullYear()}-${String(d.getMonth()+1).padStart(2,'0')}-${String(d.getDate()).padStart(2,'0')}`
}
// ── Load municipais do Supabase ───────────────────────────
async function load (tenantId, year) {
if (year) ano.value = year
if (!tenantId) return
loading.value = true
try {
// Busca feriados do tenant + feriados globais (tenant_id null, cadastrados pelo SAAS)
const { data, error } = await supabase
.from('feriados')
.select('*')
.or(`tenant_id.eq.${tenantId},tenant_id.is.null`)
.gte('data', `${ano.value}-01-01`)
.lte('data', `${ano.value}-12-31`)
.order('data')
if (error) throw error
municipais.value = data || []
} finally {
loading.value = false
}
}
// ── Criar feriado municipal ───────────────────────────────
async function criar (payload) {
const { data, error } = await supabase
.from('feriados')
.insert(payload)
.select()
.single()
if (error) throw error
municipais.value = [...municipais.value, data].sort((a, b) => a.data.localeCompare(b.data))
return data
}
// ── Remover feriado municipal ─────────────────────────────
async function remover (id) {
const { error } = await supabase.from('feriados').delete().eq('id', id)
if (error) throw error
municipais.value = municipais.value.filter(f => f.id !== id)
}
// ── Verificar duplicata ───────────────────────────────────
function isDuplicata (data, nome) {
return todos.value.some(f => f.data === data && f.nome.trim().toLowerCase() === nome.trim().toLowerCase())
}
// ── Converter para eventos do FullCalendar (background) ──
function toFcEvents (lista) {
return lista.map(f => ({
id: `feriado_${f.id || f.data}_${f.nome}`,
title: f.nome,
start: f.data,
allDay: true,
display: 'background',
color: 'rgba(251, 191, 36, 0.25)',
extendedProps: { _feriado: true, tipo: f.tipo }
}))
}
const fcEvents = computed(() => toFcEvents(todos.value))
return {
ano,
loading,
nacionais,
municipais,
todos,
fcEvents,
load,
criar,
remover,
doMes,
proximos,
isDuplicata
}
}