ee2967a075
Modulo 6 da Fase 1. noticesSelects.js extrai os 2 selects do noticeService (GLOBAL_NOTICE_SELECT, NOTICE_DISMISSAL_SELECT) + noticeService passa a usa-los (zero select inline). Conversations ganha foundation: 3 services (_tenantGuards, conversationsSelects, conversationsRepository). Channel factory (WhatsApp/SMS/Email) e composables ficam pra sessao dedicada — escopo M6 era so destravar o supabase.from() inline. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
118 lines
4.0 KiB
JavaScript
118 lines
4.0 KiB
JavaScript
/*
|
|
|--------------------------------------------------------------------------
|
|
| Agência PSI
|
|
|--------------------------------------------------------------------------
|
|
| Criado e desenvolvido por Leonardo Nohama
|
|
|
|
|
| Tecnologia aplicada à escuta.
|
|
| Estrutura para o cuidado.
|
|
|
|
|
| Arquivo: src/features/notices/noticeService.js
|
|
| Data: 2026
|
|
| Local: São Carlos/SP — Brasil
|
|
|--------------------------------------------------------------------------
|
|
| © 2026 — Todos os direitos reservados
|
|
|--------------------------------------------------------------------------
|
|
*/
|
|
// Serviço central de acesso ao Supabase para Global Notices
|
|
|
|
import { supabase } from '@/lib/supabase/client';
|
|
import { GLOBAL_NOTICE_SELECT, NOTICE_DISMISSAL_SELECT } from './noticesSelects';
|
|
|
|
// ── Leitura ────────────────────────────────────────────────────
|
|
|
|
/**
|
|
* Busca todos os notices ativos e dentro do período de exibição.
|
|
* A filtragem por role/context é feita no cliente (noticeStore)
|
|
* para evitar lógica de array no PostgREST.
|
|
*/
|
|
export async function fetchActiveNotices() {
|
|
const now = new Date().toISOString();
|
|
|
|
const { data, error } = await supabase.from('global_notices').select(GLOBAL_NOTICE_SELECT).eq('is_active', true).or(`starts_at.is.null,starts_at.lte.${now}`).or(`ends_at.is.null,ends_at.gte.${now}`).order('priority', { ascending: false });
|
|
|
|
if (error) throw error;
|
|
return data || [];
|
|
}
|
|
|
|
/**
|
|
* Busca todos os notices (sem filtro de ativo) — para o painel admin.
|
|
*/
|
|
export async function fetchAllNotices() {
|
|
const { data, error } = await supabase.from('global_notices').select(GLOBAL_NOTICE_SELECT).order('priority', { ascending: false }).order('created_at', { ascending: false });
|
|
|
|
if (error) throw error;
|
|
return data || [];
|
|
}
|
|
|
|
// ── Tracking ───────────────────────────────────────────────────
|
|
|
|
export async function trackView(noticeId) {
|
|
try {
|
|
await supabase.rpc('notice_track_view', { p_notice_id: noticeId });
|
|
} catch {
|
|
/* silencioso — tracking não deve quebrar o app */
|
|
}
|
|
}
|
|
|
|
export async function trackClick(noticeId) {
|
|
try {
|
|
await supabase.rpc('notice_track_click', { p_notice_id: noticeId });
|
|
} catch {}
|
|
}
|
|
|
|
// ── Dismiss scope: 'user' (persiste no banco) ─────────────────
|
|
|
|
export async function saveDismissal(noticeId, version) {
|
|
const {
|
|
data: { user }
|
|
} = await supabase.auth.getUser();
|
|
if (!user?.id) return;
|
|
|
|
await supabase.from('notice_dismissals').upsert({ notice_id: noticeId, user_id: user.id, version }, { onConflict: 'notice_id,user_id' });
|
|
}
|
|
|
|
export async function loadUserDismissals() {
|
|
const {
|
|
data: { user }
|
|
} = await supabase.auth.getUser();
|
|
if (!user?.id) return [];
|
|
|
|
const { data } = await supabase.from('notice_dismissals').select(NOTICE_DISMISSAL_SELECT).eq('user_id', user.id);
|
|
|
|
return data || [];
|
|
}
|
|
|
|
// ── Admin CRUD ─────────────────────────────────────────────────
|
|
|
|
export async function createNotice(payload) {
|
|
const {
|
|
data: { user }
|
|
} = await supabase.auth.getUser();
|
|
const { data, error } = await supabase
|
|
.from('global_notices')
|
|
.insert({ ...payload, created_by: user?.id })
|
|
.select()
|
|
.single();
|
|
|
|
if (error) throw error;
|
|
return data;
|
|
}
|
|
|
|
export async function updateNotice(id, payload) {
|
|
const { data, error } = await supabase.from('global_notices').update(payload).eq('id', id).select().single();
|
|
|
|
if (error) throw error;
|
|
return data;
|
|
}
|
|
|
|
export async function deleteNotice(id) {
|
|
const { error } = await supabase.from('global_notices').delete().eq('id', id);
|
|
|
|
if (error) throw error;
|
|
}
|
|
|
|
export async function toggleNoticeActive(id, isActive) {
|
|
return updateNotice(id, { is_active: isActive });
|
|
}
|