Enhance Header component to display user roles alongside names. Update Sidebar menu item label for clarity. Refactor Modules component to utilize new MyModule type and fetch modules with updated service method. Comment out unused code in RolesTable and Dashboard components for cleaner codebase. Add MyModule and MyModulesResponse types for better type safety in module handling.
This commit is contained in:
parent
cdd53a601c
commit
dd71820ac9
@ -17,7 +17,7 @@ interface HeaderProps {
|
|||||||
export const Header = ({ breadcrumbs, currentPage, onMenuClick }: HeaderProps): ReactElement => {
|
export const Header = ({ breadcrumbs, currentPage, onMenuClick }: HeaderProps): ReactElement => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const { user, isLoading } = useAppSelector((state) => state.auth);
|
const { user, isLoading,roles } = useAppSelector((state) => state.auth);
|
||||||
const [isDropdownOpen, setIsDropdownOpen] = useState<boolean>(false);
|
const [isDropdownOpen, setIsDropdownOpen] = useState<boolean>(false);
|
||||||
const dropdownRef = useRef<HTMLDivElement>(null);
|
const dropdownRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
@ -35,7 +35,7 @@ export const Header = ({ breadcrumbs, currentPage, onMenuClick }: HeaderProps):
|
|||||||
// Get user display name
|
// Get user display name
|
||||||
const getUserDisplayName = (): string => {
|
const getUserDisplayName = (): string => {
|
||||||
if (user?.first_name && user?.last_name) {
|
if (user?.first_name && user?.last_name) {
|
||||||
return `${user.first_name} ${user.last_name}`;
|
return `${user.first_name} - ${roles[0] || 'N/A'}`;
|
||||||
}
|
}
|
||||||
return user?.email?.split('@')[0] || 'Admin';
|
return user?.email?.split('@')[0] || 'Admin';
|
||||||
};
|
};
|
||||||
|
|||||||
@ -48,7 +48,7 @@ const tenantAdminPlatformMenu: MenuItem[] = [
|
|||||||
{ icon: LayoutDashboard, label: 'Dashboard', path: '/tenant' },
|
{ icon: LayoutDashboard, label: 'Dashboard', path: '/tenant' },
|
||||||
{ icon: Shield, label: 'Roles', path: '/tenant/roles', requiredPermission: { resource: 'roles' } },
|
{ icon: Shield, label: 'Roles', path: '/tenant/roles', requiredPermission: { resource: 'roles' } },
|
||||||
{ icon: Users, label: 'Users', path: '/tenant/users', requiredPermission: { resource: 'users' } },
|
{ icon: Users, label: 'Users', path: '/tenant/users', requiredPermission: { resource: 'users' } },
|
||||||
{ icon: Package, label: 'TenantModules', path: '/tenant/modules', requiredPermission: { resource: 'tenants' } },
|
{ icon: Package, label: 'Modules', path: '/tenant/modules' },
|
||||||
];
|
];
|
||||||
|
|
||||||
const tenantAdminSystemMenu: MenuItem[] = [
|
const tenantAdminSystemMenu: MenuItem[] = [
|
||||||
|
|||||||
@ -215,15 +215,15 @@ export const RolesTable = ({ tenantId, showHeader = true, compact = false }: Rol
|
|||||||
</span>
|
</span>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
key: 'is_system',
|
// key: 'is_system',
|
||||||
label: 'System Role',
|
// label: 'System Role',
|
||||||
render: (role) => (
|
// render: (role) => (
|
||||||
<span className="text-sm font-normal text-[#0f1724]">
|
// <span className="text-sm font-normal text-[#0f1724]">
|
||||||
{role.is_system ? 'Yes' : 'No'}
|
// {role.is_system ? 'Yes' : 'No'}
|
||||||
</span>
|
// </span>
|
||||||
),
|
// ),
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
key: 'created_at',
|
key: 'created_at',
|
||||||
label: 'Created Date',
|
label: 'Created Date',
|
||||||
|
|||||||
@ -65,13 +65,13 @@ const StatCard = ({ icon: Icon, value, label, status, statusLabel }: StatCardPro
|
|||||||
|
|
||||||
const Dashboard = (): ReactElement => {
|
const Dashboard = (): ReactElement => {
|
||||||
const statCards: StatCardProps[] = [
|
const statCards: StatCardProps[] = [
|
||||||
{
|
// {
|
||||||
icon: Info,
|
// icon: Info,
|
||||||
value: '18',
|
// value: '18',
|
||||||
label: 'Open CAPAs',
|
// label: 'Open CAPAs',
|
||||||
status: 'success',
|
// status: 'success',
|
||||||
statusLabel: 'Success',
|
// statusLabel: 'Success',
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
icon: FileCheck,
|
icon: FileCheck,
|
||||||
value: '7',
|
value: '7',
|
||||||
|
|||||||
@ -7,9 +7,8 @@ import {
|
|||||||
type Column,
|
type Column,
|
||||||
} from '@/components/shared';
|
} from '@/components/shared';
|
||||||
import { useAppSelector } from '@/hooks/redux-hooks';
|
import { useAppSelector } from '@/hooks/redux-hooks';
|
||||||
import { tenantService } from '@/services/tenant-service';
|
|
||||||
import type { AssignedModule } from '@/types/tenant';
|
|
||||||
import { moduleService } from '@/services/module-service';
|
import { moduleService } from '@/services/module-service';
|
||||||
|
import type { MyModule } from '@/types/module';
|
||||||
|
|
||||||
// Helper function to get status badge variant
|
// Helper function to get status badge variant
|
||||||
const getStatusVariant = (status: string | null): 'success' | 'failure' | 'process' => {
|
const getStatusVariant = (status: string | null): 'success' | 'failure' | 'process' => {
|
||||||
@ -28,24 +27,17 @@ const getStatusVariant = (status: string | null): 'success' | 'failure' | 'proce
|
|||||||
|
|
||||||
const Modules = (): ReactElement => {
|
const Modules = (): ReactElement => {
|
||||||
const { roles, tenantId } = useAppSelector((state) => state.auth);
|
const { roles, tenantId } = useAppSelector((state) => state.auth);
|
||||||
// const tenantId = useAppSelector((state) => state.auth.tenantId);
|
const [modules, setModules] = useState<MyModule[]>([]);
|
||||||
const [modules, setModules] = useState<AssignedModule[]>([]);
|
|
||||||
const [isLoading, setIsLoading] = useState<boolean>(true);
|
const [isLoading, setIsLoading] = useState<boolean>(true);
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
|
|
||||||
const fetchTenantModules = async (): Promise<void> => {
|
const fetchTenantModules = async (): Promise<void> => {
|
||||||
if (!tenantId) {
|
|
||||||
setError('Tenant ID not found');
|
|
||||||
setIsLoading(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
setError(null);
|
setError(null);
|
||||||
const response = await tenantService.getById(tenantId);
|
const response = await moduleService.getMyModules();
|
||||||
if (response.success && response.data.assignedModules) {
|
if (response.success && response.data) {
|
||||||
setModules(response.data.assignedModules);
|
setModules(response.data);
|
||||||
} else {
|
} else {
|
||||||
setError('Failed to load modules');
|
setError('Failed to load modules');
|
||||||
}
|
}
|
||||||
@ -58,7 +50,7 @@ const Modules = (): ReactElement => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchTenantModules();
|
fetchTenantModules();
|
||||||
}, [tenantId]);
|
}, []);
|
||||||
|
|
||||||
// Launch module handler
|
// Launch module handler
|
||||||
const handleLaunchModule = async (moduleId: string): Promise<void> => {
|
const handleLaunchModule = async (moduleId: string): Promise<void> => {
|
||||||
@ -88,7 +80,7 @@ const Modules = (): ReactElement => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Define table columns
|
// Define table columns
|
||||||
const columns: Column<AssignedModule>[] = [
|
const columns: Column<MyModule>[] = [
|
||||||
{
|
{
|
||||||
key: 'module_id',
|
key: 'module_id',
|
||||||
label: 'Module ID',
|
label: 'Module ID',
|
||||||
@ -149,7 +141,7 @@ const Modules = (): ReactElement => {
|
|||||||
];
|
];
|
||||||
|
|
||||||
// Mobile card renderer
|
// Mobile card renderer
|
||||||
const mobileCardRenderer = (module: AssignedModule) => (
|
const mobileCardRenderer = (module: MyModule) => (
|
||||||
<div className="p-4">
|
<div className="p-4">
|
||||||
<div className="flex items-start justify-between gap-3 mb-3">
|
<div className="flex items-start justify-between gap-3 mb-3">
|
||||||
<div className="flex-1 min-w-0">
|
<div className="flex-1 min-w-0">
|
||||||
|
|||||||
@ -218,15 +218,15 @@ const Roles = (): ReactElement => {
|
|||||||
</span>
|
</span>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
key: 'is_system',
|
// key: 'is_system',
|
||||||
label: 'System Role',
|
// label: 'System Role',
|
||||||
render: (role) => (
|
// render: (role) => (
|
||||||
<span className="text-sm font-normal text-[#0f1724]">
|
// <span className="text-sm font-normal text-[#0f1724]">
|
||||||
{role.is_system ? 'Yes' : 'No'}
|
// {role.is_system ? 'Yes' : 'No'}
|
||||||
</span>
|
// </span>
|
||||||
),
|
// ),
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
key: 'created_at',
|
key: 'created_at',
|
||||||
label: 'Created Date',
|
label: 'Created Date',
|
||||||
|
|||||||
@ -245,11 +245,11 @@ const TenantLogin = (): ReactElement => {
|
|||||||
<div className="w-full max-w-[507px] flex flex-col gap-5">
|
<div className="w-full max-w-[507px] flex flex-col gap-5">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
<div className="flex items-center justify-between">
|
{/* <div className="flex items-center justify-between">
|
||||||
<div className="bg-[#edf3fe] px-2.5 py-1 rounded-full">
|
<div className="bg-[#edf3fe] px-2.5 py-1 rounded-full">
|
||||||
<span className="text-[11px] font-medium text-[#0f1724]">Tenant Admin Portal</span>
|
<span className="text-[11px] font-medium text-[#0f1724]">Tenant Admin Portal</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div> */}
|
||||||
<h1 className="text-[22px] font-semibold text-[#0f1724]">Sign in to your tenant</h1>
|
<h1 className="text-[22px] font-semibold text-[#0f1724]">Sign in to your tenant</h1>
|
||||||
<p className="text-sm font-normal text-[#6b7280]">
|
<p className="text-sm font-normal text-[#6b7280]">
|
||||||
Use your work email or configured SSO provider to access the admin portal.
|
Use your work email or configured SSO provider to access the admin portal.
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import apiClient from './api-client';
|
import apiClient from './api-client';
|
||||||
import type { ModulesResponse, GetModuleResponse, CreateModuleRequest, CreateModuleResponse, LaunchModuleResponse } from '@/types/module';
|
import type { ModulesResponse, GetModuleResponse, CreateModuleRequest, CreateModuleResponse, LaunchModuleResponse, MyModulesResponse } from '@/types/module';
|
||||||
|
|
||||||
export const moduleService = {
|
export const moduleService = {
|
||||||
getAll: async (
|
getAll: async (
|
||||||
@ -75,4 +75,8 @@ export const moduleService = {
|
|||||||
const response = await apiClient.post<LaunchModuleResponse>(url);
|
const response = await apiClient.post<LaunchModuleResponse>(url);
|
||||||
return response.data;
|
return response.data;
|
||||||
},
|
},
|
||||||
|
getMyModules: async (): Promise<MyModulesResponse> => {
|
||||||
|
const response = await apiClient.get<MyModulesResponse>('/modules/my');
|
||||||
|
return response.data;
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -101,3 +101,27 @@ export interface LaunchModuleResponse {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface MyModule {
|
||||||
|
id: string;
|
||||||
|
module_id: string;
|
||||||
|
name: string;
|
||||||
|
description: string | null;
|
||||||
|
version: string;
|
||||||
|
status: string;
|
||||||
|
base_url: string;
|
||||||
|
health_status: string | null;
|
||||||
|
assigned_at: string;
|
||||||
|
tenant_settings: Record<string, unknown> | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MyModulesResponse {
|
||||||
|
success: boolean;
|
||||||
|
data: MyModule[];
|
||||||
|
meta: {
|
||||||
|
tenant_id: string;
|
||||||
|
is_super_admin: boolean;
|
||||||
|
is_tenant_admin: boolean;
|
||||||
|
total: number;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user