feat(cliente): ver y modificar los datos de contacto
Revisión con IA / ai-review (pull_request) Successful in 2m18s
Revisión con IA / ai-review (pull_request) Successful in 2m18s
El cliente no tenia forma de corregir su email ni su telefono despues del alta.
Nueva pantalla /cliente/perfil ("Mis datos", enlazada desde el dashboard) que
muestra nombre, email y telefono, y permite editarlos.
- GET/PATCH /api/cliente/perfil, ambos con la sesion del cliente.
- El telefono usa el mismo campo con el +54 9 fijo que el registro, y se guarda
normalizado en telefonoNorm para que el bot lo siga reconociendo.
- aLocalArgentino() saca el prefijo para mostrar: un cliente dado de alta por
WhatsApp tiene el numero guardado como 5491141984844 y en el formulario tiene
que verse 1141984844.
- Email y telefono se validan unicos contra los demas clientes (409), no contra
uno mismo. Si cambia el email se avisa que con ese va a entrar de ahora en mas,
porque es la identidad del magic link.
- El middleware protege /cliente/perfil como el resto del area del cliente.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { verificarSesion } from "@/lib/auth-admin";
|
||||
import { aFormatoWhatsapp, aLocalArgentino, esLocalArgentinoValido } from "@/lib/telefono";
|
||||
|
||||
const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||
|
||||
// Datos de contacto del cliente logueado. El teléfono se devuelve en formato local
|
||||
// (sin el +54 9) porque el formulario lo muestra como prefijo fijo.
|
||||
export async function GET() {
|
||||
const sesion = await verificarSesion("cliente_session");
|
||||
if (!sesion) return NextResponse.json({ error: "No autorizado" }, { status: 401 });
|
||||
|
||||
const cliente = await prisma.cliente.findUnique({
|
||||
where: { id: sesion.sub },
|
||||
select: { nombre: true, apellido: true, email: true, telefono: true, telefonoNorm: true },
|
||||
});
|
||||
if (!cliente) return NextResponse.json({ error: "Cliente no encontrado" }, { status: 404 });
|
||||
|
||||
return NextResponse.json({
|
||||
nombre: cliente.nombre,
|
||||
apellido: cliente.apellido,
|
||||
email: cliente.email ?? "",
|
||||
telefono: aLocalArgentino(cliente.telefonoNorm ?? cliente.telefono ?? ""),
|
||||
});
|
||||
}
|
||||
|
||||
export async function PATCH(req: NextRequest) {
|
||||
const sesion = await verificarSesion("cliente_session");
|
||||
if (!sesion) return NextResponse.json({ error: "No autorizado" }, { status: 401 });
|
||||
|
||||
const { nombre, apellido, email, telefono } = await req.json();
|
||||
|
||||
if (!nombre?.trim() || !apellido?.trim())
|
||||
return NextResponse.json({ error: "Nombre y apellido son obligatorios" }, { status: 400 });
|
||||
|
||||
if (!email?.trim() || !EMAIL_RE.test(email.trim()))
|
||||
return NextResponse.json({ error: "El email no es válido" }, { status: 400 });
|
||||
|
||||
if (!esLocalArgentinoValido(telefono ?? ""))
|
||||
return NextResponse.json(
|
||||
{ error: "El teléfono debe tener 10 dígitos, sin el 0 de la característica ni el 15" },
|
||||
{ status: 400 }
|
||||
);
|
||||
|
||||
const emailNuevo = email.trim().toLowerCase();
|
||||
const telefonoNorm = aFormatoWhatsapp(telefono);
|
||||
|
||||
// El email es con lo que se entra al sistema y el teléfono es con lo que el bot
|
||||
// reconoce al cliente: los dos tienen que seguir siendo únicos.
|
||||
const emailTomado = await prisma.cliente.findFirst({
|
||||
where: { email: emailNuevo, id: { not: sesion.sub } },
|
||||
select: { id: true },
|
||||
});
|
||||
if (emailTomado)
|
||||
return NextResponse.json({ error: "Ese email ya está registrado" }, { status: 409 });
|
||||
|
||||
const telefonoTomado = await prisma.cliente.findFirst({
|
||||
where: { telefonoNorm, id: { not: sesion.sub } },
|
||||
select: { id: true },
|
||||
});
|
||||
if (telefonoTomado)
|
||||
return NextResponse.json({ error: "Ese teléfono ya está registrado" }, { status: 409 });
|
||||
|
||||
const cliente = await prisma.cliente.update({
|
||||
where: { id: sesion.sub },
|
||||
data: {
|
||||
nombre: nombre.trim(),
|
||||
apellido: apellido.trim(),
|
||||
email: emailNuevo,
|
||||
telefono: aLocalArgentino(telefonoNorm),
|
||||
telefonoNorm,
|
||||
},
|
||||
select: { nombre: true, apellido: true, email: true, telefonoNorm: true },
|
||||
});
|
||||
|
||||
return NextResponse.json({
|
||||
ok: true,
|
||||
nombre: cliente.nombre,
|
||||
apellido: cliente.apellido,
|
||||
email: cliente.email ?? "",
|
||||
telefono: aLocalArgentino(cliente.telefonoNorm ?? ""),
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user