MelissaPaciente Fase 5: Tab Agenda completa (KPIs + filtros + grupos por mes + acoes)
EXTENSAO src/features/patients/utils/patientFormatters.js: +2 helpers
- fmtHourShort (HH:MM 24h pt-br) — usado na coluna data dos cards
- fmtDayShort (DOW abreviado pt-br sem ponto) — usado na coluna data
EXTENSAO src/features/patients/composables/usePatientSessions.js
- Novo ref `busy` pra disable de buttons durante mutation
- _lastPatientId guardado internamente pra auto-reload
- Nova funcao `updateStatus(sessionId, novoStatus)` que faz
supabase.from('agenda_eventos').update({status}) + auto-reload da
lista de sessoes. Retorna {ok, error?}.
MELISSAPACIENTE.VUE — script
- agendaFilter ref ('all' default) + AGENDA_FILTERS array com 6 opcoes
(Todas, Proximas, Passadas, Realizadas, Faltas, Canceladas)
- agendaSessoesFiltradas computed: filtra por future/past/status (regex)
- agendaAgrupadas computed: agrupa por "Mes de YYYY" DESC
- updateSessionStatus(ev, status, msg): chama sessionsHook.updateStatus +
toast de sucesso/erro
- Removido `void toast` (toast usado de verdade agora)
MELISSAPACIENTE.VUE — Tab Agenda reescrita (substitui placeholder Fase 1)
- 4 KPI cards no padrao Visao Geral (numerados 01-04):
Total / Realizadas (% do total) / Faltas (cor adaptativa) / Proxima
- 6 filter chips redondas (cor primary quando active)
- Empty state contextual (sem sessoes vs filtro vazio)
- Grupos por mes com header (label + badge count)
- Cards 3-col: data column (DOW + dia + hora) | main (status tag + chips
modalidade/duracao + relative + titulo + note 2-line clamp) | actions
(3 buttons: ok/warn/danger com tooltip + cor adaptativa no hover)
- Mobile: stack date+main em 2 cols; actions full-width abaixo
CSS: ~150L novos. Padrao visual Melissa: data column estilo calendario,
actions hover muda cor por intent (verde realiz / amarelo falta / vermelho
cancel), border-left por status.
ESLint: 0 errors da minha mudanca.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -16,8 +16,11 @@ export function usePatientSessions() {
|
||||
const sessions = ref([]);
|
||||
const loading = ref(false);
|
||||
const error = ref('');
|
||||
const busy = ref(false); // mutations em curso (updateStatus etc)
|
||||
let _lastPatientId = null;
|
||||
|
||||
async function load(patientId) {
|
||||
_lastPatientId = patientId || null;
|
||||
if (!patientId) {
|
||||
sessions.value = [];
|
||||
return;
|
||||
@@ -81,11 +84,36 @@ export function usePatientSessions() {
|
||||
.slice(0, 6)
|
||||
);
|
||||
|
||||
/**
|
||||
* Atualiza o status de uma sessao (mutation). Recarrega a lista do paciente
|
||||
* ao final pra refletir o novo estado nos computeds derivados.
|
||||
* Retorna {ok: true} ou {ok: false, error: msg}.
|
||||
*/
|
||||
async function updateStatus(sessionId, novoStatus) {
|
||||
if (!sessionId || busy.value) return { ok: false, error: 'busy' };
|
||||
busy.value = true;
|
||||
try {
|
||||
const { error: err } = await supabase
|
||||
.from('agenda_eventos')
|
||||
.update({ status: novoStatus })
|
||||
.eq('id', sessionId);
|
||||
if (err) throw err;
|
||||
if (_lastPatientId) await load(_lastPatientId);
|
||||
return { ok: true };
|
||||
} catch (e) {
|
||||
return { ok: false, error: e?.message || 'Erro ao atualizar status' };
|
||||
} finally {
|
||||
busy.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
sessions,
|
||||
loading,
|
||||
error,
|
||||
busy,
|
||||
load,
|
||||
updateStatus,
|
||||
proximaSessao,
|
||||
ultimaSessao,
|
||||
totalSessoes,
|
||||
|
||||
@@ -122,6 +122,26 @@ export function fmtDateBR(v) {
|
||||
return `${String(d.getDate()).padStart(2, '0')}/${String(d.getMonth() + 1).padStart(2, '0')}/${d.getFullYear()}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hora curta HH:MM (24h pt-br).
|
||||
*/
|
||||
export function fmtHourShort(iso) {
|
||||
if (!iso) return '';
|
||||
const d = new Date(iso);
|
||||
if (Number.isNaN(d.getTime())) return '';
|
||||
return `${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dia da semana abreviado pt-br (seg/ter/qua...).
|
||||
*/
|
||||
export function fmtDayShort(iso) {
|
||||
if (!iso) return '';
|
||||
const d = new Date(iso);
|
||||
if (Number.isNaN(d.getTime())) return '';
|
||||
return d.toLocaleDateString('pt-BR', { weekday: 'short' }).replace('.', '');
|
||||
}
|
||||
|
||||
export function fmtDateTimeBR(iso) {
|
||||
if (!iso) return '—';
|
||||
const d = new Date(iso);
|
||||
|
||||
Reference in New Issue
Block a user