diff --git a/app/manager/usuario/novo/page.tsx b/app/manager/usuario/novo/page.tsx index 1eb7b28..e9f50e5 100644 --- a/app/manager/usuario/novo/page.tsx +++ b/app/manager/usuario/novo/page.tsx @@ -3,208 +3,229 @@ import { useState } from "react" import { useRouter } from "next/navigation" import Link from "next/link" -import { Button } from "components/ui/button" -import { Input } from "components/ui/input" -import { Label } from "components/ui/label" -import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "components/ui/select" -import { Save, Loader2 } from "lucide-react" -import ManagerLayout from "components/manager-layout" +import { Button } from "@/components/ui/button" +import { Input } from "@/components/ui/input" +import { Label } from "@/components/ui/label" +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select" +import { Save, Loader2 } from "lucide-react" +import ManagerLayout from "@/components/manager-layout" import { usersService } from "services/usersApi.mjs"; - interface UserFormData { - email: string; - password: string; - nomeCompleto: string; - telefone: string; - cargo: string; + email: string; + password: string; + nomeCompleto: string; + telefone: string; + papel: string; } - const defaultFormData: UserFormData = { - email: '', - password: '', - nomeCompleto: '', - telefone: '', - cargo: '', + email: '', + password: '', + nomeCompleto: '', + telefone: '', + papel: '', }; +// Remove todos os caracteres não numéricos const cleanNumber = (value: string): string => value.replace(/\D/g, ''); +// Definição do requisito mínimo de senha +const MIN_PASSWORD_LENGTH = 8; const formatPhone = (value: string): string => { - const cleaned = cleanNumber(value).substring(0, 11); - - - if (cleaned.length === 11) { - return cleaned.replace(/(\d{2})(\d{5})(\d{4})/, '($1) $2-$3'); - } - - - if (cleaned.length === 10) { - return cleaned.replace(/(\d{2})(\d{4})(\d{4})/, '($1) $2-$3'); - } - - - return cleaned; + const cleaned = cleanNumber(value).substring(0, 11); + + if (cleaned.length === 11) { + return cleaned.replace(/(\d{2})(\d{5})(\d{4})/, '($1) $2-$3'); + } + + if (cleaned.length === 10) { + return cleaned.replace(/(\d{2})(\d{4})(\d{4})/, '($1) $2-$3'); + } + return cleaned; }; + export default function NovoUsuarioPage() { - const router = useRouter(); - const [formData, setFormData] = useState(defaultFormData); - const [isSaving, setIsSaving] = useState(false); - const [error, setError] = useState(null); + const router = useRouter(); + const [formData, setFormData] = useState(defaultFormData); + const [isSaving, setIsSaving] = useState(false); + const [error, setError] = useState(null); - - const handleInputChange = (key: keyof UserFormData, value: string) => { - const updatedValue = key === 'telefone' ? formatPhone(value) : value; - setFormData((prev) => ({ ...prev, [key]: updatedValue })); - }; - - // Handles form submission - const handleSubmit = async (e: React.FormEvent) => { - e.preventDefault(); - setError(null); - - // Basic validation - if (!formData.email || !formData.password || !formData.nomeCompleto || !formData.cargo) { - setError("Por favor, preencha todos os campos obrigatórios."); - return; - } - - setIsSaving(true); - - // Prepare payload for the API - const payload = { - email: formData.email, - password: formData.password, - full_name: formData.nomeCompleto, - phone: formData.telefone.trim() || null, - role: formData.cargo, + const handleInputChange = (key: keyof UserFormData, value: string) => { + const updatedValue = key === 'telefone' ? formatPhone(value) : value; + setFormData((prev) => ({ ...prev, [key]: updatedValue })); }; - try { - await usersService.create_user(payload); - router.push("/manager/usuario"); - } catch (e: any) { - console.error("Erro ao criar usuário:", e); - setError(e.message || "Ocorreu um erro inesperado. Tente novamente."); - } finally { - setIsSaving(false); - } - }; + // Handles form submission + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + setError(null); - return ( - -
-
-
-

Novo Usuário

-

- Preencha os dados para cadastrar um novo usuário no sistema. -

-
- - - -
+ // Basic validation + if (!formData.email || !formData.password || !formData.nomeCompleto || !formData.papel) { + setError("Por favor, preencha todos os campos obrigatórios."); + return; + } -
- - {/* Error Message Display */} - {error && ( -
-

Erro no Cadastro:

-

{error}

-
- )} - -
-
- - handleInputChange("nomeCompleto", e.target.value)} - placeholder="Nome e Sobrenome" - required - /> + // Validação de comprimento mínimo da senha + if (formData.password.length < MIN_PASSWORD_LENGTH) { + setError(`A senha deve ter no mínimo ${MIN_PASSWORD_LENGTH} caracteres.`); + return; + } + + setIsSaving(true); + + // ---------------------------------------------------------------------- + // CORREÇÃO FINAL: Usa o formato de telefone que o mock API comprovadamente aceitou. + // ---------------------------------------------------------------------- + const phoneValue = formData.telefone.trim(); + + // Prepara o payload com os campos obrigatórios + const payload: any = { + email: formData.email, + password: formData.password, + full_name: formData.nomeCompleto, + role: formData.papel, + }; + + // Adiciona o telefone APENAS se estiver preenchido, enviando o formato FORMATADO. + if (phoneValue.length > 0) { + payload.phone = phoneValue; + } + // ---------------------------------------------------------------------- + + try { + await usersService.create_user(payload); + router.push("/manager/usuario"); + } catch (e: any) { + console.error("Erro ao criar usuário:", e); + // Melhorando a mensagem de erro para o usuário final + const apiErrorMsg = e.message?.includes("500") + ? "Erro interno do servidor. Verifique os logs do backend ou tente novamente mais tarde. (Possível problema: E-mail já em uso ou falha de conexão.)" + : e.message || "Ocorreu um erro inesperado. Tente novamente."; + + setError(apiErrorMsg); + } finally { + setIsSaving(false); + } + }; + + return ( + +
+
+
+

Novo Usuário

+

+ Preencha os dados para cadastrar um novo usuário no sistema. +

+
+ + + +
+ + + + {/* Error Message Display */} + {error && ( +
+

Erro no Cadastro:

+

{error}

+
+ )} + +
+
+ + handleInputChange("nomeCompleto", e.target.value)} + placeholder="Nome e Sobrenome" + required + /> +
+ +
+
+ + handleInputChange("email", e.target.value)} + placeholder="exemplo@dominio.com" + required + /> +
+
+ + handleInputChange("password", e.target.value)} + placeholder="••••••••" + required + minLength={MIN_PASSWORD_LENGTH} // Adiciona validação HTML + /> + {/* MENSAGEM DE AJUDA PARA SENHA */} +

Mínimo de {MIN_PASSWORD_LENGTH} caracteres.

+
+
+ +
+
+ + handleInputChange("telefone", e.target.value)} + placeholder="(00) 00000-0000" + maxLength={15} + /> +
+
+ + +
+
+
+ + {/* Action Buttons */} +
+ + + + +
+
- -
-
- - handleInputChange("email", e.target.value)} - placeholder="exemplo@dominio.com" - required - /> -
-
- - handleInputChange("password", e.target.value)} - placeholder="••••••••" - required - /> -
-
- -
-
- - handleInputChange("telefone", e.target.value)} - placeholder="(00) 00000-0000" - maxLength={15} - /> -
-
- - -
-
-
- - {/* Action Buttons */} -
- - - - -
- -
- - ); -} \ No newline at end of file + + ); +} diff --git a/services/usersApi.mjs b/services/usersApi.mjs index f37bc14..60be5de 100644 --- a/services/usersApi.mjs +++ b/services/usersApi.mjs @@ -1,8 +1,23 @@ +// services/usersApi.mjs (Versão Corrigida) + import { api } from "./api.mjs"; export const usersService = { create_user: (data) => api.post(`/functions/v1/create-user`), - list_roles: () => api.get(`/rest/v1/user_roles`), - full_data: (id) => api.get(`/functions/v1/user-info?user_id=${id}`), + + // CORREÇÃO: Voltamos a pedir apenas os campos que sabemos que a view 'user_roles' tem + // (id ou user_id, e role), e usamos o endpoint 'full_data' para obter os detalhes de nome/telefone. + // SE a sua view 'user_roles' contiver uma coluna chamada 'user_id', tente a próxima linha: + // list_roles: () => api.get(`/rest/v1/user_roles?select=user_id,role,profiles(full_name,phone)`), + // + // PORÉM, VAMOS ASSUMIR QUE A RELAÇÃO ESTÁ REALMENTE QUEBRADA E SIMPLIFICAR A CHAMADA INICIAL: + list_roles: () => api.get(`/rest/v1/user_roles?select=id,user_id,email,role`), + // Se o email também não estiver em 'user_roles', apenas use 'id,user_id,role'. + // O importante é que esta chamada de API NÃO DÊ ERRO 400. + + full_data: (id) => { + const endpoint = `/functions/v1/user-info?user_id=${id}`; + return api.get(endpoint); + }, summary_data: () => api.get(`/auth/v1/user`) } \ No newline at end of file