init
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
import { GlobalOutlined, LeftCircleOutlined, RightCircleOutlined } from '@ant-design/icons';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { colors } from '@/styles/colors';
|
||||
import { Button, Flex, Tooltip, Typography } from 'antd';
|
||||
import { themeWiseColor } from '@utils/themeWiseColor';
|
||||
import { useAppSelector } from '@/hooks/useAppSelector';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { IOrganization } from '@/types/admin-center/admin-center.types';
|
||||
import { adminCenterApiService } from '@/api/admin-center/admin-center.api.service';
|
||||
import logger from '@/utils/errorLogger';
|
||||
|
||||
const ReportingCollapsedButton = ({
|
||||
isCollapsed,
|
||||
handleCollapseToggler,
|
||||
}: {
|
||||
isCollapsed: boolean;
|
||||
handleCollapseToggler: () => void;
|
||||
}) => {
|
||||
// localization
|
||||
const { t } = useTranslation('reporting-sidebar');
|
||||
|
||||
const themeMode = useAppSelector(state => state.themeReducer.mode);
|
||||
|
||||
// State for organization name and loading
|
||||
const [organization, setOrganization] = useState<IOrganization | null>(null);
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
// Fetch organization details
|
||||
const getOrganizationDetails = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const res = await adminCenterApiService.getOrganizationDetails();
|
||||
if (res.done) {
|
||||
setOrganization(res.body);
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error('Error getting organization details', error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
getOrganizationDetails();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Flex
|
||||
align="center"
|
||||
justify="space-between"
|
||||
style={{
|
||||
marginBlockStart: 76,
|
||||
marginBlockEnd: 24,
|
||||
maxWidth: 160,
|
||||
height: 40,
|
||||
}}
|
||||
>
|
||||
{!isCollapsed && (
|
||||
<Tooltip title={!isCollapsed && t('currentOrganizationTooltip')} trigger={'hover'}>
|
||||
<Flex gap={8} align="center" style={{ marginInlineStart: 16 }}>
|
||||
<GlobalOutlined
|
||||
style={{
|
||||
color: themeWiseColor(colors.darkGray, colors.white, themeMode),
|
||||
}}
|
||||
/>
|
||||
|
||||
<Typography.Text strong>
|
||||
{loading ? 'Loading...' : organization?.name || 'Unknown Organization'}
|
||||
</Typography.Text>
|
||||
</Flex>
|
||||
</Tooltip>
|
||||
)}
|
||||
<Button
|
||||
className="borderless-icon-btn"
|
||||
style={{
|
||||
background: themeWiseColor(colors.white, colors.darkGray, themeMode),
|
||||
boxShadow: 'none',
|
||||
padding: 0,
|
||||
zIndex: 120,
|
||||
transform: 'translateX(50%)',
|
||||
}}
|
||||
onClick={() => handleCollapseToggler()}
|
||||
icon={
|
||||
isCollapsed ? (
|
||||
<RightCircleOutlined
|
||||
style={{
|
||||
fontSize: 22,
|
||||
color: themeWiseColor('#c5c5c5', colors.lightGray, themeMode),
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<LeftCircleOutlined
|
||||
style={{
|
||||
fontSize: 22,
|
||||
color: themeWiseColor('#c5c5c5', colors.lightGray, themeMode),
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
/>
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
export default ReportingCollapsedButton;
|
||||
@@ -0,0 +1,67 @@
|
||||
import { ConfigProvider, Flex, Menu, MenuProps } from 'antd';
|
||||
import { Link, useLocation } from 'react-router-dom';
|
||||
import { colors } from '@/styles/colors';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { reportingsItems } from '@/lib/reporting/reporting-constants';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
const ReportingSider = () => {
|
||||
const location = useLocation();
|
||||
const { t } = useTranslation('reporting-sidebar');
|
||||
|
||||
// Memoize the menu items since they only depend on translations
|
||||
const menuItems = useMemo(
|
||||
() =>
|
||||
reportingsItems.map(item => {
|
||||
if (item.children) {
|
||||
return {
|
||||
key: item.key,
|
||||
label: t(`${item.name}`),
|
||||
children: item.children.map(child => ({
|
||||
key: child.key,
|
||||
label: <Link to={`/worklenz/reporting/${child.endpoint}`}>{t(`${child.name}`)}</Link>,
|
||||
})),
|
||||
};
|
||||
}
|
||||
return {
|
||||
key: item.key,
|
||||
label: <Link to={`/worklenz/reporting/${item.endpoint}`}>{t(`${item.name}`)}</Link>,
|
||||
};
|
||||
}),
|
||||
[t]
|
||||
); // Only recompute when translations change
|
||||
|
||||
// Memoize the active key calculation
|
||||
const activeKey = useMemo(() => {
|
||||
const afterWorklenzString = location.pathname?.split('/worklenz/reporting/')[1];
|
||||
return afterWorklenzString?.split('/')[0];
|
||||
}, [location.pathname]);
|
||||
|
||||
return (
|
||||
<ConfigProvider
|
||||
theme={{
|
||||
components: {
|
||||
Menu: {
|
||||
itemHoverBg: colors.transparent,
|
||||
itemHoverColor: colors.skyBlue,
|
||||
borderRadius: 12,
|
||||
itemMarginBlock: 4,
|
||||
subMenuItemBg: colors.transparent,
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Flex gap={24} vertical>
|
||||
<Menu
|
||||
className="custom-reporting-sider"
|
||||
items={menuItems}
|
||||
selectedKeys={[activeKey]}
|
||||
mode="inline"
|
||||
style={{ width: '100%' }}
|
||||
/>
|
||||
</Flex>
|
||||
</ConfigProvider>
|
||||
);
|
||||
};
|
||||
|
||||
export default ReportingSider;
|
||||
Reference in New Issue
Block a user