docs: adiciona estrutura de governança por contexto (AGENT, DOMAIN, DESIGN_SYSTEM, TASKS)
This commit is contained in:
parent
722d7bf82a
commit
ebbbda5328
2 changed files with 102 additions and 74 deletions
28
frontend/DESIGN_SYSTEM.md
Normal file
28
frontend/DESIGN_SYSTEM.md
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
# SaveInMed - Design System
|
||||
|
||||
Diretrizes visuais para o frontend do SaveInMed.
|
||||
|
||||
## 🎨 Paleta de Cores
|
||||
- **Primária**: `blue-600` (#2563EB) - Botões principais, links ativos.
|
||||
- **Sucesso**: `green-600` (#16A34A) - Confirmações, status "Entregue".
|
||||
- **Aviso**: `yellow-500` (#EAB308) - Alertas, status "Pendente".
|
||||
- **Erro**: `red-600` (#DC2626) - Botões de deletar, mensagens de erro.
|
||||
- **Fundo**: `gray-50` (#F9FAFB) - Background das páginas.
|
||||
|
||||
## 🔡 Tipografia
|
||||
- **Títulos**: Inter ou Sans-serif, font-bold, text-gray-900.
|
||||
- **Corpo**: Inter, text-gray-600.
|
||||
|
||||
## 🧩 Componentes Padrão
|
||||
- **Botões**:
|
||||
- `bg-blue-600 hover:bg-blue-700 text-white rounded-lg px-4 py-2 transition-colors`
|
||||
- **Inputs**:
|
||||
- `border border-gray-300 focus:ring-2 focus:ring-blue-500 rounded-lg`
|
||||
- **Cards**:
|
||||
- `bg-white shadow-sm border border-gray-100 rounded-xl p-6`
|
||||
|
||||
## 📦 Ícones
|
||||
- **Biblioteca**: `Heroicons 24/outline`
|
||||
- **Home**: `HomeIcon`
|
||||
- **Carrinho**: `ShoppingCartIcon`
|
||||
- **Usuário**: `UserIcon`
|
||||
|
|
@ -15,21 +15,21 @@ const LoginPageContent = () => {
|
|||
const { setEmpresaId } = useEmpresa();
|
||||
const searchParams = useSearchParams();
|
||||
|
||||
// Estados do formulÃÆ’ƒÂ¡rio
|
||||
const [email, setEmail] = useState<string>(""); // Email do usuÃÆ’ƒÂ¡rio
|
||||
const [password, setPassword] = useState<string>(""); // Senha do usuÃÆ’ƒÂ¡rio
|
||||
// Estados do formulário
|
||||
const [email, setEmail] = useState<string>(""); // Email do usuário
|
||||
const [password, setPassword] = useState<string>(""); // Senha do usuário
|
||||
const [name, setName] = useState<string>(""); // Nome completo (apenas para registro)
|
||||
const [loading, setLoading] = useState<boolean>(false); // Estado de carregamento
|
||||
const [error, setError] = useState<string>(""); // Mensagens de erro
|
||||
const [isLogin, setIsLogin] = useState<boolean>(true); // Alterna entre login e registro
|
||||
const [checkingAuth, setCheckingAuth] = useState<boolean>(true); // VerificaÃÆ’ƒÂÂÂ§ÃÆ’ƒÂ£o inicial de autenticaÃÆ’ƒÂÂÂ§ÃÆ’ƒÂ£o
|
||||
const [checkingAuth, setCheckingAuth] = useState<boolean>(true); // Verificação inicial de autenticação
|
||||
const [showPassword, setShowPassword] = useState<boolean>(false); // Controla visibilidade da senha
|
||||
const [accessToken, setAccessToken] = useState<string>(""); // Token de acesso da API
|
||||
const [showSuccessModal, setShowSuccessModal] = useState<boolean>(false); // Modal de sucesso do cadastro
|
||||
const [showPendingModal, setShowPendingModal] = useState<boolean>(false); // Modal de cadastro pendente
|
||||
|
||||
/**
|
||||
* Verifica parÃÆ’ƒÂ¢metros da URL para definir aba inicial
|
||||
* Verifica par¢metros da URL para definir aba inicial
|
||||
*/
|
||||
useEffect(() => {
|
||||
const tab = searchParams.get('tab');
|
||||
|
|
@ -39,13 +39,13 @@ const LoginPageContent = () => {
|
|||
}, [searchParams]);
|
||||
|
||||
/**
|
||||
* Verifica se o usuÃÆ’ƒÂ¡rio jÃÆ’ƒÂ¡ estÃÆ’ƒÂ¡ autenticado ao carregar a pÃÆ’ƒÂ¡gina
|
||||
* Verifica se o usuário já está autenticado ao carregar a página
|
||||
* Se estiver autenticado, redireciona para o dashboard
|
||||
*/
|
||||
useEffect(() => {
|
||||
const checkAuth = async () => {
|
||||
try {
|
||||
// Verificar se hÃÆ’ƒÂ¡ token armazenado
|
||||
// Verificar se há token armazenado
|
||||
const storedToken = localStorage.getItem('access_token');
|
||||
|
||||
if (!storedToken) {
|
||||
|
|
@ -53,14 +53,14 @@ const LoginPageContent = () => {
|
|||
return;
|
||||
}
|
||||
|
||||
// Verificar autenticaÃÆ’ÂÂ§ÃÆ’£o usando API com o token no header Authorization
|
||||
// Verificar autenticação usando API com o token no header Authorization
|
||||
const response = await fetch(
|
||||
`${API_V1_BASE_URL}/auth/me`,
|
||||
{
|
||||
method: "GET",
|
||||
headers: {
|
||||
"accept": "application/json",
|
||||
"Authorization": `Bearer ${storedToken}`, // Usar Authorization ao invÃÆ’ƒÂ©s de Cookie
|
||||
"Authorization": `Bearer ${storedToken}`, // Usar Authorization ao invés de Cookie
|
||||
},
|
||||
}
|
||||
);
|
||||
|
|
@ -71,7 +71,7 @@ const LoginPageContent = () => {
|
|||
router.push("/dashboard");
|
||||
} else {
|
||||
const errorText = await response.text();
|
||||
// Limpar token invÃÆ’ƒÂ¡lido
|
||||
// Limpar token inválido
|
||||
localStorage.removeItem('access_token');
|
||||
}
|
||||
} catch (error) {
|
||||
|
|
@ -83,9 +83,9 @@ const LoginPageContent = () => {
|
|||
}, [router]);
|
||||
|
||||
/**
|
||||
* FunÃÆ’ÂÂ§ÃÆ’£o para realizar login do usuÃÆ’¡rio usando API
|
||||
* @param email - Email do usuÃÆ’ƒÂ¡rio (usado como identificador)
|
||||
* @param password - Senha do usuÃÆ’ƒÂ¡rio
|
||||
* Função para realizar login do usuário usando API
|
||||
* @param email - Email do usuário (usado como identificador)
|
||||
* @param password - Senha do usuário
|
||||
*/
|
||||
const login = async (email: string, password: string) => {
|
||||
setLoading(true);
|
||||
|
|
@ -108,32 +108,32 @@ const LoginPageContent = () => {
|
|||
})
|
||||
});
|
||||
|
||||
// Ler e logar o corpo da resposta (usando clone para nÃÆ’ƒÂ£o consumir o body original)
|
||||
// Ler e logar o corpo da resposta (usando clone para não consumir o body original)
|
||||
const respClone = response.clone();
|
||||
const respText = await respClone.text();
|
||||
let respBody: any = respText;
|
||||
try {
|
||||
respBody = JSON.parse(respText);
|
||||
} catch {
|
||||
// corpo nÃÆ’ƒÂ£o ÃÆ’ƒÂ© JSON, manter como texto
|
||||
// corpo não é JSON, manter como texto
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
// Extrair mensagem de erro do backend
|
||||
let errorMessage = respBody?.message || respBody?.error || respBody?.detail || respText;
|
||||
|
||||
// Tratar cÃÆ’ƒÂ³digos de status especÃÆ’ƒÂÂÂficos
|
||||
// Tratar códigos de status específicos
|
||||
if (response.status === 401) {
|
||||
errorMessage = "Email ou senha incorretos. Verifique suas credenciais.";
|
||||
} else if (response.status === 403) {
|
||||
errorMessage = "Acesso negado. Sua conta pode estar inativa.";
|
||||
} else if (response.status === 404) {
|
||||
errorMessage = "UsuÃÆ’ƒÂ¡rio nÃÆ’ƒÂ£o encontrado. Verifique o email informado.";
|
||||
errorMessage = "Usuário não encontrado. Verifique o email informado.";
|
||||
} else if (response.status >= 500) {
|
||||
errorMessage = "Erro interno do servidor. Tente novamente em alguns minutos.";
|
||||
}
|
||||
|
||||
// Aplicar traduÃÆ’ƒÂÂÂ§ÃÆ’ƒÂ£o se disponÃÆ’ƒÂÂÂvel
|
||||
// Aplicar tradução se disponível
|
||||
const translatedError = translateError(errorMessage);
|
||||
throw new Error(translatedError);
|
||||
}
|
||||
|
|
@ -158,24 +158,24 @@ const LoginPageContent = () => {
|
|||
if (meResponse.ok) {
|
||||
const userData = await meResponse.json();
|
||||
} else {
|
||||
console.log("ÃÆ’¢ÂÂÂÃɉ۪ Falha no /me:", await meResponse.text());
|
||||
console.log("¢Ãɉ۪ Falha no /me:", await meResponse.text());
|
||||
}
|
||||
|
||||
} else {
|
||||
throw new Error("Token nÃÆ’ƒÂ£o recebido do servidor");
|
||||
throw new Error("Token não recebido do servidor");
|
||||
}
|
||||
|
||||
// 4. Armazenar informaÃÆ’ƒÂÂÂ§ÃÆ’ƒÂµes do usuÃÆ’ƒÂ¡rio no localStorage
|
||||
// 4. Armazenar informaçµes do usuário no localStorage
|
||||
if (loginData.user) {
|
||||
localStorage.setItem('user', JSON.stringify(loginData.user));
|
||||
|
||||
// Verificar se o registro estÃÆ’ƒÂ¡ completo
|
||||
// Verificar se o registro está completo
|
||||
if (loginData.user["registro-completo"] === false) {
|
||||
setShowPendingModal(true);
|
||||
return; // NÃÆ’ƒÂ£o continuar com o redirecionamento
|
||||
return; // Não continuar com o redirecionamento
|
||||
}
|
||||
|
||||
// Armazenar ID do endereÃÆ’ƒÂ§o se disponÃÆ’ƒÂÂÂvel
|
||||
// Armazenar ID do endereço se disponível
|
||||
// Backend pode retornar "endereco" (singular) ou "enderecos" (plural array)
|
||||
let enderecoId = loginData.user.endereco;
|
||||
|
||||
|
|
@ -189,7 +189,7 @@ const LoginPageContent = () => {
|
|||
}
|
||||
}
|
||||
|
||||
// 5. Verificar e armazenar empresa ID se disponÃÆ’ƒÂÂÂvel
|
||||
// 5. Verificar e armazenar empresa ID se disponível
|
||||
if (loginData.user?.empresaId) {
|
||||
setEmpresaId(loginData.user.empresaId);
|
||||
}
|
||||
|
|
@ -198,16 +198,16 @@ const LoginPageContent = () => {
|
|||
router.push("/dashboard");
|
||||
|
||||
} catch (error: any) {
|
||||
console.error("ÃÆ’¢ÂÂÂÃɉ۪ Erro no login:", error);
|
||||
console.error("¢Ãɉ۪ Erro no login:", error);
|
||||
|
||||
// Definir mensagem de erro amigÃÆ’ƒÂ¡vel
|
||||
// Definir mensagem de erro amigável
|
||||
let friendlyMessage = error.message;
|
||||
|
||||
// Se for um erro de rede
|
||||
if (error.name === 'TypeError' || error.message.includes('fetch')) {
|
||||
friendlyMessage = "Erro de conexÃÆ’ƒÂ£o. Verifique sua internet e tente novamente.";
|
||||
friendlyMessage = "Erro de conexão. Verifique sua internet e tente novamente.";
|
||||
}
|
||||
// Se for um erro genÃÆ’ƒÂ©rico sem mensagem clara
|
||||
// Se for um erro genérico sem mensagem clara
|
||||
else if (!error.message || error.message.length < 5) {
|
||||
friendlyMessage = "Erro inesperado. Verifique suas credenciais e tente novamente.";
|
||||
}
|
||||
|
|
@ -219,7 +219,7 @@ const LoginPageContent = () => {
|
|||
};
|
||||
|
||||
/**
|
||||
* FunÃÆ’ÂÂ§ÃÆ’£o para registrar novo usuÃÆ’¡rio usando API
|
||||
* Função para registrar novo usuário usando API
|
||||
* Cria conta e mostra mensagem de sucesso
|
||||
*/
|
||||
const register = async () => {
|
||||
|
|
@ -235,12 +235,12 @@ const LoginPageContent = () => {
|
|||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
identificador: email, // identificador = email do usuÃÆ’ƒÂ¡rio (usado no login)
|
||||
identificador: email, // identificador = email do usuário (usado no login)
|
||||
email: email,
|
||||
nome: name, // nome = nome completo do usuÃÆ’ƒÂ¡rio
|
||||
nome: name, // nome = nome completo do usuário
|
||||
senha: password,
|
||||
nivel: "owner", // valor estÃÆ’ƒÂ¡tico
|
||||
"registro-completo": false // valor estÃÆ’ƒÂ¡tico - registro incompleto por padrÃÆ’ƒÂ£o
|
||||
nivel: "owner", // valor estático
|
||||
"registro-completo": false // valor estático - registro incompleto por padrão
|
||||
})
|
||||
});
|
||||
|
||||
|
|
@ -248,25 +248,25 @@ const LoginPageContent = () => {
|
|||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}));
|
||||
|
||||
// Tratar cÃÆ’ƒÂ³digos de status especÃÆ’ƒÂÂÂficos
|
||||
// Tratar códigos de status específicos
|
||||
let errorMessage = errorData.message || 'Falha no registro';
|
||||
|
||||
if (response.status === 409 || errorMessage.includes('already exists') || errorMessage.includes('jÃÆ’ƒÂ¡ existe')) {
|
||||
errorMessage = 'Este email jÃÆ’ƒÂ¡ estÃÆ’ƒÂ¡ cadastrado. Tente fazer login ou use outro email.';
|
||||
if (response.status === 409 || errorMessage.includes('already exists') || errorMessage.includes('já existe')) {
|
||||
errorMessage = 'Este email já está cadastrado. Tente fazer login ou use outro email.';
|
||||
} else if (response.status === 400) {
|
||||
errorMessage = 'Dados invÃÆ’ƒÂ¡lidos. Verifique se todos os campos estÃÆ’ƒÂ£o preenchidos corretamente.';
|
||||
errorMessage = 'Dados inválidos. Verifique se todos os campos estão preenchidos corretamente.';
|
||||
} else if (response.status >= 500) {
|
||||
errorMessage = 'Erro interno do servidor. Tente novamente em alguns minutos.';
|
||||
}
|
||||
|
||||
// Aplicar traduÃÆ’ƒÂÂÂ§ÃÆ’ƒÂ£o se disponÃÆ’ƒÂÂÂvel
|
||||
// Aplicar tradução se disponível
|
||||
const translatedError = translateError(errorMessage);
|
||||
throw new Error(translatedError);
|
||||
}
|
||||
|
||||
const registerData = await response.json();
|
||||
|
||||
// 2. Fazer login automÃÆ’ƒÂ¡tico apÃÆ’ƒÂ³s registro para obter token
|
||||
// 2. Fazer login automático após registro para obter token
|
||||
const loginResponse = await fetch(`${baseUrl}/auth/login`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
|
|
@ -282,13 +282,13 @@ const LoginPageContent = () => {
|
|||
});
|
||||
|
||||
if (!loginResponse.ok) {
|
||||
console.error("ÃÆ’¢ÂÂÂÃɉ۪ Erro no login automÃÆ’ƒÂ¡tico:", loginResponse.status);
|
||||
throw new Error('Erro ao fazer login automÃÆ’ƒÂ¡tico apÃÆ’ƒÂ³s registro');
|
||||
console.error("¢Ãɉ۪ Erro no login automático:", loginResponse.status);
|
||||
throw new Error('Erro ao fazer login automático após registro');
|
||||
}
|
||||
|
||||
const loginData = await loginResponse.json();
|
||||
|
||||
// 3. Armazenar token e dados do usuÃÆ’ƒÂ¡rio
|
||||
// 3. Armazenar token e dados do usuário
|
||||
if (loginData.access_token) {
|
||||
localStorage.setItem('access_token', loginData.access_token);
|
||||
}
|
||||
|
|
@ -297,20 +297,20 @@ const LoginPageContent = () => {
|
|||
localStorage.setItem('user', JSON.stringify(loginData.user));
|
||||
}
|
||||
|
||||
// 4. Redirecionar para completar registro com token vÃÆ’ƒÂ¡lido
|
||||
// 4. Redirecionar para completar registro com token válido
|
||||
router.push(`/completar-registro?nome=${encodeURIComponent(name)}&email=${encodeURIComponent(email)}`);
|
||||
|
||||
} catch (error: any) {
|
||||
console.error("ÃÆ’¢ÂÂÂÃɉ۪ Erro no registro:", error);
|
||||
console.error("¢Ãɉ۪ Erro no registro:", error);
|
||||
|
||||
// Definir mensagem de erro amigÃÆ’ƒÂ¡vel
|
||||
// Definir mensagem de erro amigável
|
||||
let friendlyMessage = error.message;
|
||||
|
||||
// Se for um erro de rede
|
||||
if (error.name === 'TypeError' || error.message.includes('fetch')) {
|
||||
friendlyMessage = "Erro de conexÃÆ’ƒÂ£o. Verifique sua internet e tente novamente.";
|
||||
friendlyMessage = "Erro de conexão. Verifique sua internet e tente novamente.";
|
||||
}
|
||||
// Se for um erro genÃÆ’ƒÂ©rico sem mensagem clara
|
||||
// Se for um erro genérico sem mensagem clara
|
||||
else if (!error.message || error.message.length < 5) {
|
||||
friendlyMessage = "Erro inesperado durante o cadastro. Tente novamente.";
|
||||
}
|
||||
|
|
@ -322,11 +322,11 @@ const LoginPageContent = () => {
|
|||
};
|
||||
|
||||
/**
|
||||
* FunÃÆ’ƒÂÂÂ§ÃÆ’ƒÂ£o para notificar administrador sobre novo cadastro
|
||||
* Função para notificar administrador sobre novo cadastro
|
||||
*/
|
||||
const notifyAdmin = async (userData: { nome: string, email: string, identificador: string }) => {
|
||||
try {
|
||||
// Enviar notificaÃÆ’ƒÂÂÂ§ÃÆ’ƒÂµes via API (usando Resend para emails reais)
|
||||
// Enviar notificaçµes via API (usando Resend para emails reais)
|
||||
await fetch('/api/notify-admin-resend', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
|
|
@ -335,13 +335,13 @@ const LoginPageContent = () => {
|
|||
body: JSON.stringify(userData)
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Erro ao enviar notificaÃÆ’ƒÂÂÂ§ÃÆ’ƒÂµes:", error);
|
||||
// NÃÆ’ƒÂ£o bloquear o cadastro por erro de notificaÃÆ’ƒÂÂÂ§ÃÆ’ƒÂ£o
|
||||
console.error("Erro ao enviar notificaçµes:", error);
|
||||
// Não bloquear o cadastro por erro de notificação
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* FunÃÆ’ƒÂÂÂ§ÃÆ’ƒÂ£o para fechar modal de sucesso e redirecionar
|
||||
* Função para fechar modal de sucesso e redirecionar
|
||||
*/
|
||||
const handleSuccessModalClose = () => {
|
||||
setShowSuccessModal(false);
|
||||
|
|
@ -349,25 +349,25 @@ const LoginPageContent = () => {
|
|||
};
|
||||
|
||||
/**
|
||||
* FunÃÆ’ƒÂÂÂ§ÃÆ’ƒÂ£o para fechar modal de cadastro pendente
|
||||
* Função para fechar modal de cadastro pendente
|
||||
*/
|
||||
const handlePendingModalClose = () => {
|
||||
setShowPendingModal(false);
|
||||
// Fazer logout para limpar dados do usuÃÆ’ƒÂ¡rio
|
||||
// Fazer logout para limpar dados do usuário
|
||||
localStorage.removeItem('access_token');
|
||||
localStorage.removeItem('user');
|
||||
setAccessToken("");
|
||||
// Redirecionar para pÃÆ’ƒÂ¡gina inicial
|
||||
// Redirecionar para página inicial
|
||||
router.push('/');
|
||||
};
|
||||
|
||||
// Tela de carregamento durante verificaÃÆ’ƒÂÂÂ§ÃÆ’ƒÂ£o de autenticaÃÆ’ƒÂÂÂ§ÃÆ’ƒÂ£o
|
||||
// Tela de carregamento durante verificação de autenticação
|
||||
if (checkingAuth) {
|
||||
return (
|
||||
<div className="min-h-screen bg-gray-50 flex items-center justify-center">
|
||||
<div className="text-center">
|
||||
<div className="w-16 h-16 border-4 border-blue-600 border-t-transparent rounded-full animate-spin mx-auto mb-4"></div>
|
||||
<p className="text-gray-600">Verificando autenticaÃÆ’ƒÂÂÂ§ÃÆ’ƒÂ£o...</p>
|
||||
<p className="text-gray-600">Verificando autenticação...</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
@ -376,7 +376,7 @@ const LoginPageContent = () => {
|
|||
return (
|
||||
<div className="min-h-screen bg-gray-50 flex items-center justify-center p-4">
|
||||
<div className="bg-white rounded-2xl shadow-xl overflow-hidden w-full max-w-md">
|
||||
{/* CabeÃÆ’ƒÂ§alho com logo e slogan */}
|
||||
{/* Cabeçalho com logo e slogan */}
|
||||
<div className="bg-gradient-to-r from-blue-600 to-blue-700 p-1 text-center">
|
||||
<div className="mx-auto -mb-2 flex items-center justify-center">
|
||||
<Image
|
||||
|
|
@ -392,9 +392,9 @@ const LoginPageContent = () => {
|
|||
<p className="text-gray-300">Plataforma B2B de Medicamentos</p>
|
||||
</div>
|
||||
|
||||
{/* FormulÃÆ’ƒÂ¡rio de login/registro */}
|
||||
{/* Formulário de login/registro */}
|
||||
<div className="p-6">
|
||||
{/* BotÃÆ’ƒÂµes de alternÃÆ’ƒÂ¢ncia entre Login e Cadastro */}
|
||||
{/* Botµes de altern¢ncia entre Login e Cadastro */}
|
||||
<div className="flex bg-gray-100 rounded-lg p-1 mb-6">
|
||||
<button
|
||||
onClick={() => setIsLogin(true)}
|
||||
|
|
@ -464,7 +464,7 @@ const LoginPageContent = () => {
|
|||
</div>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="JoÃÆ’ƒÂ£o Silva"
|
||||
placeholder="João Silva"
|
||||
value={name}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
className="w-full pl-10 pr-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-colors text-gray-900 placeholder-gray-500"
|
||||
|
|
@ -527,7 +527,7 @@ const LoginPageContent = () => {
|
|||
</div>
|
||||
<input
|
||||
type={showPassword ? "text" : "password"}
|
||||
placeholder="ÃÆ’¢â‚¬ÂÂÂ¢ÃÆ’¢â‚¬ÂÂÂ¢ÃÆ’¢â‚¬ÂÂÂ¢ÃÆ’¢â‚¬ÂÂÂ¢ÃÆ’¢â‚¬ÂÂÂ¢ÃÆ’¢â‚¬ÂÂÂ¢ÃÆ’¢â‚¬ÂÂÂ¢ÃÆ’¢â‚¬Â¢"
|
||||
placeholder="¢â‚¬¢Â¢Ã¢â€šÂ¬¢Â¢Ã¢â€šÂ¬¢Â¢Ã¢â€šÂ¬¢Â¢Ã¢â€šÂ¬¢Â¢Ã¢â€šÂ¬¢Â¢Ã¢â€šÂ¬¢Â¢Ã¢â€šÂ¬¢"
|
||||
value={password}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
className="w-full pl-10 pr-12 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-colors text-gray-900 placeholder-gray-500"
|
||||
|
|
@ -576,7 +576,7 @@ const LoginPageContent = () => {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{/* BotÃÆ’ƒÂµes de Submit */}
|
||||
{/* Botµes de Submit */}
|
||||
<div className="space-y-3 pt-2">
|
||||
{isLogin ? (
|
||||
<button
|
||||
|
|
@ -708,18 +708,18 @@ const LoginPageContent = () => {
|
|||
</h2>
|
||||
</div>
|
||||
|
||||
{/* ConteÃÆ’ƒÂºdo do Modal */}
|
||||
{/* Conteúdo do Modal */}
|
||||
<div className="p-6 text-center">
|
||||
<div className="mb-6">
|
||||
<p className="text-gray-700 text-lg leading-relaxed">
|
||||
Seu cadastro foi enviado com <strong>sucesso</strong>!
|
||||
</p>
|
||||
<p className="text-gray-600 mt-3">
|
||||
Nossa equipe entrarÃÆ’ƒÂ¡ em contato em breve para finalizar seu acesso ÃÆ’ƒÂ plataforma.
|
||||
Nossa equipe entrará em contato em breve para finalizar seu acesso plataforma.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* ÃÆ’ƒÂÂÂcone decorativo */}
|
||||
{/* cone decorativo */}
|
||||
<div className="flex justify-center mb-6">
|
||||
<div className="flex space-x-2">
|
||||
<div className="w-3 h-3 bg-green-500 rounded-full animate-pulse"></div>
|
||||
|
|
@ -728,7 +728,7 @@ const LoginPageContent = () => {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{/* BotÃÆ’ƒÂ£o de OK */}
|
||||
{/* Botão de OK */}
|
||||
<button
|
||||
onClick={handleSuccessModalClose}
|
||||
className="w-full bg-gradient-to-r from-green-500 to-green-600 hover:from-green-600 hover:to-green-700 text-white font-semibold py-4 px-6 rounded-xl transition-all duration-200 transform hover:scale-105 focus:outline-none focus:ring-4 focus:ring-green-200"
|
||||
|
|
@ -766,21 +766,21 @@ const LoginPageContent = () => {
|
|||
</h2>
|
||||
</div>
|
||||
|
||||
{/* ConteÃÆ’ƒÂºdo do Modal */}
|
||||
{/* Conteúdo do Modal */}
|
||||
<div className="p-6 text-center">
|
||||
<div className="mb-6">
|
||||
<p className="text-gray-700 text-lg leading-relaxed">
|
||||
Seu cadastro estÃÆ’ƒÂ¡ <strong>pendente de validaÃÆ’ƒÂÂÂ§ÃÆ’ƒÂ£o</strong>!
|
||||
Seu cadastro está <strong>pendente de validação</strong>!
|
||||
</p>
|
||||
<p className="text-gray-600 mt-3">
|
||||
Nossa equipe ainda estÃÆ’ƒÂ¡ analisando suas informaÃÆ’ƒÂÂÂ§ÃÆ’ƒÂµes. VocÃÆ’ƒÂª receberÃÆ’ƒÂ¡ uma confirmaÃÆ’ƒÂÂÂ§ÃÆ’ƒÂ£o em breve.
|
||||
Nossa equipe ainda está analisando suas informaçµes. Você receberá uma confirmação em breve.
|
||||
</p>
|
||||
<p className="text-gray-600 mt-3">
|
||||
Qualquer dÃÆ’ƒÂºvida, entre em contato conosco.
|
||||
Qualquer dúvida, entre em contato conosco.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* ÃÆ’ƒÂÂÂcone decorativo */}
|
||||
{/* cone decorativo */}
|
||||
<div className="flex justify-center mb-6">
|
||||
<div className="flex space-x-2">
|
||||
<div className="w-3 h-3 bg-yellow-500 rounded-full animate-pulse"></div>
|
||||
|
|
@ -789,7 +789,7 @@ const LoginPageContent = () => {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{/* BotÃÆ’ƒÂ£o de OK */}
|
||||
{/* Botão de OK */}
|
||||
<button
|
||||
onClick={handlePendingModalClose}
|
||||
className="w-full bg-gradient-to-r from-yellow-500 to-orange-500 hover:from-yellow-600 hover:to-orange-600 text-white font-semibold py-4 px-6 rounded-xl transition-all duration-200 transform hover:scale-105 focus:outline-none focus:ring-4 focus:ring-yellow-200"
|
||||
|
|
|
|||
Loading…
Reference in a new issue