fix(nav): corrige sistema de navegação pós-login e sincronização de URL
Causa raiz do login não navegar: getCurrentRole() retornava null quando vinculos.role era NULL no banco, fazendo isViewAllowed() retornar false e handleNavigate() falhar silenciosamente sem nenhum feedback. Fixes: - backend.ts: getCurrentRole usa workspace?.role || 'paciente' para garantir que nunca retorne null/undefined - App.tsx: onLoginSuccess usa setCurrentView+navigate diretamente, sem passar pela guarda de permissão (desnecessária pós-autenticação) - App.tsx: mount effect sempre chama navigate(currentView) para sincronizar a URL com a view real — antes só executava com hash vazio, deixando /#/login na URL ao recarregar com usuário autenticado - LoginView.tsx: remove spinner isInitializing de 3s que bloqueava o formulário em toda montagem do componente Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+7
-5
@@ -210,11 +210,11 @@ const App: React.FC = () => {
|
|||||||
document.documentElement.style.setProperty('--brand-color-soft', `${clinColor}11`);
|
document.documentElement.style.setProperty('--brand-color-soft', `${clinColor}11`);
|
||||||
}, [clinColor]);
|
}, [clinColor]);
|
||||||
|
|
||||||
// On mount: if there's no hash yet, write the current view into the URL
|
// On mount: always sync URL to match the actual current view.
|
||||||
|
// This handles auth redirects (e.g. reload at /#/login while authenticated shows dashboard
|
||||||
|
// but URL would stay /#/login without this call).
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!window.location.hash || window.location.hash === '#update_db') {
|
navigate(currentView);
|
||||||
navigate(currentView);
|
|
||||||
}
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@@ -244,7 +244,9 @@ const App: React.FC = () => {
|
|||||||
default:
|
default:
|
||||||
return <LoginView onLoginSuccess={() => {
|
return <LoginView onLoginSuccess={() => {
|
||||||
const role = HybridBackend.getCurrentRole();
|
const role = HybridBackend.getCurrentRole();
|
||||||
handleNavigate(getDefaultViewForRole(role));
|
const view = getDefaultViewForRole(role);
|
||||||
|
setCurrentView(view);
|
||||||
|
navigate(view);
|
||||||
}} />;
|
}} />;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ export const HybridBackend = {
|
|||||||
|
|
||||||
getCurrentRole: (): string => {
|
getCurrentRole: (): string => {
|
||||||
const workspace = HybridBackend.getActiveWorkspace();
|
const workspace = HybridBackend.getActiveWorkspace();
|
||||||
return workspace ? workspace.role : 'paciente';
|
return workspace?.role || 'paciente';
|
||||||
},
|
},
|
||||||
|
|
||||||
getDashboardStats: async () => {
|
getDashboardStats: async () => {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { Database, Lock, User, ArrowRight, ShieldCheck, Loader2 } from 'lucide-react';
|
import { Database, Lock, User, ArrowRight, ShieldCheck } from 'lucide-react';
|
||||||
import { HybridBackend } from '../services/backend.ts';
|
import { HybridBackend } from '../services/backend.ts';
|
||||||
|
|
||||||
interface LoginViewProps {
|
interface LoginViewProps {
|
||||||
@@ -11,12 +11,6 @@ export const LoginView: React.FC<LoginViewProps> = ({ onLoginSuccess }) => {
|
|||||||
const [password, setPassword] = useState('');
|
const [password, setPassword] = useState('');
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [error, setError] = useState('');
|
const [error, setError] = useState('');
|
||||||
const [isInitializing, setIsInitializing] = useState(true);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const timer = setTimeout(() => setIsInitializing(false), 3000);
|
|
||||||
return () => clearTimeout(timer);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const handleSubmit = async (e: React.FormEvent) => {
|
const handleSubmit = async (e: React.FormEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@@ -37,16 +31,6 @@ export const LoginView: React.FC<LoginViewProps> = ({ onLoginSuccess }) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (isInitializing) {
|
|
||||||
return (
|
|
||||||
<div className="min-h-screen bg-gray-50 flex flex-col items-center justify-center p-4">
|
|
||||||
<Loader2 className="animate-spin text-blue-600 mb-4" size={48} />
|
|
||||||
<h2 className="text-gray-500 font-bold uppercase tracking-widest text-sm">Inicializando Sistema...</h2>
|
|
||||||
<span className="text-gray-400 text-xs mt-2 font-mono font-bold bg-gray-200 px-2 py-1 rounded">V1.0.2</span>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-gray-50 flex items-center justify-center p-4">
|
<div className="min-h-screen bg-gray-50 flex items-center justify-center p-4">
|
||||||
<div className="max-w-md w-full bg-white rounded-2xl shadow-xl overflow-hidden border border-gray-100">
|
<div className="max-w-md w-full bg-white rounded-2xl shadow-xl overflow-hidden border border-gray-100">
|
||||||
|
|||||||
Reference in New Issue
Block a user