feat: implement client overview dashboard and admin portal structure with API services and page components

This commit is contained in:
2026-07-09 17:37:54 +05:30
parent 3cf9e2997c
commit b667fe1082
17 changed files with 2196 additions and 73 deletions

View File

@@ -4,6 +4,7 @@ import { useNavigate } from 'react-router-dom';
import { useAuthStore } from '../../store/authStore';
import { accountService } from '../../api/accountService';
import { DbSelectionDialog } from './DbSelectionDialog';
import { useToastStore } from '../../store/toastStore';
export const Login: React.FC = () => {
const [username, setUsername] = useState('');
@@ -11,8 +12,8 @@ export const Login: React.FC = () => {
const [isInvalid, setIsInvalid] = useState(false);
const [loading, setLoading] = useState(false);
const [dialogOpen, setDialogOpen] = useState(false);
const [tempUserData, setTempUserData] = useState<any>(null);
const [tempLoginResult, setTempLoginResult] = useState<Awaited<ReturnType<typeof accountService.login>> | null>(null);
const { login, isAuthenticated } = useAuthStore();
const navigate = useNavigate();
@@ -26,53 +27,44 @@ export const Login: React.FC = () => {
const handleLogin = async () => {
setIsInvalid(false);
setLoading(true);
try {
const userData = await accountService.login(username, password);
if (!userData) {
const result = await accountService.login(username, password);
if (!result?.user) {
setIsInvalid(true);
useToastStore.getState().showToast('Invalid username or password.', 'error');
setLoading(false);
return;
}
const roles = userData.user_roles ? userData.user_roles.toLowerCase().split(',') : [];
if (roles.includes('sr_auditor')) {
// Open DB Selection Dialog
setTempUserData(userData);
setDialogOpen(true);
} else if (roles.includes('auditor')) {
// Direct login
login(userData);
navigate('/activity-feeds', { replace: true });
} else if (roles.includes('video_uploader')) {
// Direct login for dashboard
login(userData);
navigate('/activity-feeds', { replace: true });
} else {
alert("Your account is not configured to use this website. Please contact your admin for more info.");
}
// Every user picks which org/DB to work in after login.
setTempLoginResult(result);
setDialogOpen(true);
} catch (error) {
setIsInvalid(true);
useToastStore.getState().showToast('Invalid username or password.', 'error');
} finally {
setLoading(false);
}
};
const handleDbSelection = (selectedOrg?: any) => {
const handleDbSelection = (selectedOrg?: { org_id: string; db_name: string; org_name?: string }) => {
setDialogOpen(false);
if (selectedOrg && tempUserData) {
// Merge selected org details into user object
const finalUserData = {
...tempUserData,
if (selectedOrg && tempLoginResult) {
login({
access_token: tempLoginResult.access_token,
refresh_token: tempLoginResult.refresh_token,
user_id: tempLoginResult.user.user_id,
username: tempLoginResult.user.username,
email: tempLoginResult.user.email,
role: tempLoginResult.user.role_name,
org_id: selectedOrg.org_id,
db_name: selectedOrg.db_name,
selected_org_name: selectedOrg.org_name
};
login(finalUserData);
});
navigate('/activity-feeds', { replace: true });
}
setTempLoginResult(null);
};
return (
@@ -206,7 +198,6 @@ export const Login: React.FC = () => {
</Paper>
</Container>
{/* Database Selection Dialog for SR_AUDITOR */}
<DbSelectionDialog open={dialogOpen} onClose={handleDbSelection} />
</Box>
);