agenda: services nome unico por owner + cadastro in-flow

services: useServices.save e ServiceQuickCreateDialog agora validam nome
unico por owner (ilike, case-insensitive; ignora self no update). Antes
era possivel criar dois servicos com nome igual via paths diferentes.

cadastro in-flow: ComponentCadastroRapido e PatientCadastroDialog ganham
prop hideViewListButton. Quando true (uso dentro de outro fluxo, ex:
cadastrar paciente direto no AgendaEventDialog), esconde "Salvar e ver
pacientes" — navegar pra lista abandonaria o evento em edicao.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Leonardo
2026-05-11 10:44:27 -03:00
parent 8b0e633aac
commit 8e3c09d1b1
4 changed files with 49 additions and 7 deletions
@@ -67,10 +67,23 @@ async function onSave() {
}
saving.value = true;
try {
const name = form.value.name.trim().slice(0, 120);
// Nome unico por owner (case-insensitive) — espelha a validacao
// do useServices.save() pra impedir duplicata tambem quando o
// cadastro vem do quick-create dentro do AgendaEventDialog.
const { data: dups, error: dupErr } = await supabase.from('services').select('id').eq('owner_id', ownerId).ilike('name', name).limit(1);
if (dupErr) throw dupErr;
if (dups && dups.length > 0) {
toast.add({ severity: 'warn', summary: 'Nome em uso', detail: 'Já existe um serviço com este nome.', life: 3500 });
saving.value = false;
return;
}
const payload = {
owner_id: ownerId,
tenant_id: tid,
name: form.value.name.trim().slice(0, 120),
name,
price: Number(form.value.price),
duration_min: form.value.duration_min ? Number(form.value.duration_min) : null,
description: form.value.description?.trim().slice(0, 500) || null,
@@ -54,6 +54,21 @@ export function useServices() {
async function save(payload) {
error.value = '';
try {
const name = payload.name?.trim();
if (!name) throw new Error('Nome do serviço é obrigatório.');
if (!payload.owner_id) throw new Error('Owner ausente.');
// Nome unico por owner (case-insensitive). No update,
// ignora o proprio id pra nao conflitar consigo mesmo
// quando o usuario salva sem mudar o nome.
let dupQuery = supabase.from('services').select('id').eq('owner_id', payload.owner_id).ilike('name', name).limit(1);
if (payload.id) dupQuery = dupQuery.neq('id', payload.id);
const { data: dups, error: dupErr } = await dupQuery;
if (dupErr) throw dupErr;
if (dups && dups.length > 0) {
throw new Error('Já existe um serviço com este nome.');
}
if (payload.id) {
const { id, owner_id, tenant_id, ...fields } = payload;
const { error: err } = await supabase.from('services').update(fields).eq('id', id).eq('owner_id', owner_id);