@@ -1,10 +1,10 @@ | |||||
/** @type {import('next').NextConfig} */ | /** @type {import('next').NextConfig} */ | ||||
const nextConfig = { | const nextConfig = { | ||||
// eslint: { | |||||
// // Warning: This allows production builds to successfully complete even if | |||||
// // your project has ESLint errors. | |||||
// ignoreDuringBuilds: true, | |||||
// }, | |||||
} | |||||
// eslint: { | |||||
// // Warning: This allows production builds to successfully complete even if | |||||
// // your project has ESLint errors. | |||||
// ignoreDuringBuilds: true, | |||||
// }, | |||||
}; | |||||
module.exports = nextConfig | |||||
module.exports = nextConfig; |
@@ -3,25 +3,23 @@ import { I18nProvider } from "@/i18n"; | |||||
import DashboardPage from "@/components/DashboardPage/DashboardPage"; | import DashboardPage from "@/components/DashboardPage/DashboardPage"; | ||||
import DashboardPageButton from "@/components/DashboardPage/DashboardTabButton"; | import DashboardPageButton from "@/components/DashboardPage/DashboardTabButton"; | ||||
import ProgressCashFlowSearch from "@/components/ProgressCashFlowSearch"; | import ProgressCashFlowSearch from "@/components/ProgressCashFlowSearch"; | ||||
import { Suspense} from "react"; | |||||
import { Suspense } from "react"; | |||||
import Tabs, { TabsProps } from "@mui/material/Tabs"; | import Tabs, { TabsProps } from "@mui/material/Tabs"; | ||||
import Tab from "@mui/material/Tab"; | import Tab from "@mui/material/Tab"; | ||||
import Typography from "@mui/material/Typography"; | import Typography from "@mui/material/Typography"; | ||||
import CompanyTeamCashFlowComponent from '@/components/CompanyTeamCashFlow' | |||||
import CompanyTeamCashFlowComponent from "@/components/CompanyTeamCashFlow"; | |||||
export const metadata: Metadata = { | export const metadata: Metadata = { | ||||
title: "Project Status by Client", | title: "Project Status by Client", | ||||
}; | }; | ||||
const CompanyTeamCashFlow: React.FC = () => { | const CompanyTeamCashFlow: React.FC = () => { | ||||
return ( | return ( | ||||
<I18nProvider namespaces={["dashboard"]}> | <I18nProvider namespaces={["dashboard"]}> | ||||
<Typography variant="h4" marginInlineEnd={2}> | <Typography variant="h4" marginInlineEnd={2}> | ||||
Company / Team Cash Flow | Company / Team Cash Flow | ||||
</Typography> | </Typography> | ||||
<CompanyTeamCashFlowComponent/> | |||||
<CompanyTeamCashFlowComponent /> | |||||
</I18nProvider> | </I18nProvider> | ||||
); | ); | ||||
}; | }; | ||||
@@ -3,19 +3,17 @@ import { I18nProvider } from "@/i18n"; | |||||
import DashboardPage from "@/components/DashboardPage/DashboardPage"; | import DashboardPage from "@/components/DashboardPage/DashboardPage"; | ||||
import DashboardPageButton from "@/components/DashboardPage/DashboardTabButton"; | import DashboardPageButton from "@/components/DashboardPage/DashboardTabButton"; | ||||
import ProgressCashFlowSearch from "@/components/ProgressCashFlowSearch"; | import ProgressCashFlowSearch from "@/components/ProgressCashFlowSearch"; | ||||
import { Suspense} from "react"; | |||||
import { Suspense } from "react"; | |||||
import Tabs, { TabsProps } from "@mui/material/Tabs"; | import Tabs, { TabsProps } from "@mui/material/Tabs"; | ||||
import Tab from "@mui/material/Tab"; | import Tab from "@mui/material/Tab"; | ||||
import Typography from "@mui/material/Typography"; | import Typography from "@mui/material/Typography"; | ||||
import ProjectCashFlowComponent from '@/components/ProjectCashFlow' | |||||
import ProjectCashFlowComponent from "@/components/ProjectCashFlow"; | |||||
export const metadata: Metadata = { | export const metadata: Metadata = { | ||||
title: "Project Status by Client", | title: "Project Status by Client", | ||||
}; | }; | ||||
const ProjectCashFlow: React.FC = () => { | const ProjectCashFlow: React.FC = () => { | ||||
return ( | return ( | ||||
<I18nProvider namespaces={["dashboard"]}> | <I18nProvider namespaces={["dashboard"]}> | ||||
<Typography variant="h4" marginInlineEnd={2}> | <Typography variant="h4" marginInlineEnd={2}> | ||||
@@ -24,7 +22,7 @@ const ProjectCashFlow: React.FC = () => { | |||||
{/* <Suspense fallback={<ProgressCashFlowSearch.Loading />}> | {/* <Suspense fallback={<ProgressCashFlowSearch.Loading />}> | ||||
<ProgressCashFlowSearch/> | <ProgressCashFlowSearch/> | ||||
</Suspense> */} | </Suspense> */} | ||||
<ProjectCashFlowComponent/> | |||||
<ProjectCashFlowComponent /> | |||||
</I18nProvider> | </I18nProvider> | ||||
); | ); | ||||
}; | }; | ||||
@@ -3,7 +3,7 @@ import { I18nProvider } from "@/i18n"; | |||||
import DashboardPage from "@/components/DashboardPage/DashboardPage"; | import DashboardPage from "@/components/DashboardPage/DashboardPage"; | ||||
import DashboardPageButton from "@/components/DashboardPage/DashboardTabButton"; | import DashboardPageButton from "@/components/DashboardPage/DashboardTabButton"; | ||||
import ProgressByClientSearch from "@/components/ProgressByClientSearch"; | import ProgressByClientSearch from "@/components/ProgressByClientSearch"; | ||||
import { Suspense} from "react"; | |||||
import { Suspense } from "react"; | |||||
import Tabs, { TabsProps } from "@mui/material/Tabs"; | import Tabs, { TabsProps } from "@mui/material/Tabs"; | ||||
import Tab from "@mui/material/Tab"; | import Tab from "@mui/material/Tab"; | ||||
import Typography from "@mui/material/Typography"; | import Typography from "@mui/material/Typography"; | ||||
@@ -13,15 +13,13 @@ export const metadata: Metadata = { | |||||
title: "Project Status by Client", | title: "Project Status by Client", | ||||
}; | }; | ||||
const ProjectFinancialSummary: React.FC = () => { | const ProjectFinancialSummary: React.FC = () => { | ||||
return ( | return ( | ||||
<I18nProvider namespaces={["dashboard"]}> | <I18nProvider namespaces={["dashboard"]}> | ||||
<Typography variant="h4" marginInlineEnd={2}> | <Typography variant="h4" marginInlineEnd={2}> | ||||
Project Financial Summary | Project Financial Summary | ||||
</Typography> | </Typography> | ||||
<ProjectFinancialSummaryComponents/> | |||||
<ProjectFinancialSummaryComponents /> | |||||
</I18nProvider> | </I18nProvider> | ||||
); | ); | ||||
}; | }; | ||||
@@ -3,7 +3,7 @@ import { I18nProvider } from "@/i18n"; | |||||
import DashboardPage from "@/components/DashboardPage/DashboardPage"; | import DashboardPage from "@/components/DashboardPage/DashboardPage"; | ||||
import DashboardPageButton from "@/components/DashboardPage/DashboardTabButton"; | import DashboardPageButton from "@/components/DashboardPage/DashboardTabButton"; | ||||
import ProgressByClientSearch from "@/components/ProgressByClientSearch"; | import ProgressByClientSearch from "@/components/ProgressByClientSearch"; | ||||
import { Suspense} from "react"; | |||||
import { Suspense } from "react"; | |||||
import Tabs, { TabsProps } from "@mui/material/Tabs"; | import Tabs, { TabsProps } from "@mui/material/Tabs"; | ||||
import Tab from "@mui/material/Tab"; | import Tab from "@mui/material/Tab"; | ||||
import Typography from "@mui/material/Typography"; | import Typography from "@mui/material/Typography"; | ||||
@@ -13,18 +13,16 @@ export const metadata: Metadata = { | |||||
title: "Project Status by Client", | title: "Project Status by Client", | ||||
}; | }; | ||||
const ProjectStatusByClient: React.FC = () => { | const ProjectStatusByClient: React.FC = () => { | ||||
return ( | return ( | ||||
<I18nProvider namespaces={["dashboard"]}> | <I18nProvider namespaces={["dashboard"]}> | ||||
<Typography variant="h4" marginInlineEnd={2}> | <Typography variant="h4" marginInlineEnd={2}> | ||||
Project Status by Client | Project Status by Client | ||||
</Typography> | </Typography> | ||||
<Suspense fallback={<ProgressByClientSearch.Loading />}> | <Suspense fallback={<ProgressByClientSearch.Loading />}> | ||||
<ProgressByClientSearch/> | |||||
<ProgressByClientSearch /> | |||||
</Suspense> | </Suspense> | ||||
<ProgressByClient/> | |||||
<ProgressByClient /> | |||||
</I18nProvider> | </I18nProvider> | ||||
); | ); | ||||
}; | }; | ||||
@@ -3,7 +3,7 @@ import { I18nProvider } from "@/i18n"; | |||||
import DashboardPage from "@/components/DashboardPage/DashboardPage"; | import DashboardPage from "@/components/DashboardPage/DashboardPage"; | ||||
import DashboardPageButton from "@/components/DashboardPage/DashboardTabButton"; | import DashboardPageButton from "@/components/DashboardPage/DashboardTabButton"; | ||||
import ProgressByClientSearch from "@/components/ProgressByClientSearch"; | import ProgressByClientSearch from "@/components/ProgressByClientSearch"; | ||||
import { Suspense} from "react"; | |||||
import { Suspense } from "react"; | |||||
import Tabs, { TabsProps } from "@mui/material/Tabs"; | import Tabs, { TabsProps } from "@mui/material/Tabs"; | ||||
import Tab from "@mui/material/Tab"; | import Tab from "@mui/material/Tab"; | ||||
import Typography from "@mui/material/Typography"; | import Typography from "@mui/material/Typography"; | ||||
@@ -13,15 +13,13 @@ export const metadata: Metadata = { | |||||
title: "Project Status by Client", | title: "Project Status by Client", | ||||
}; | }; | ||||
const StaffUtilization: React.FC = () => { | const StaffUtilization: React.FC = () => { | ||||
return ( | return ( | ||||
<I18nProvider namespaces={["dashboard"]}> | <I18nProvider namespaces={["dashboard"]}> | ||||
<Typography variant="h4" marginInlineEnd={2}> | <Typography variant="h4" marginInlineEnd={2}> | ||||
Staff Utilization | Staff Utilization | ||||
</Typography> | </Typography> | ||||
<StaffUtilizationComponent/> | |||||
<StaffUtilizationComponent /> | |||||
</I18nProvider> | </I18nProvider> | ||||
); | ); | ||||
}; | }; | ||||
@@ -3,7 +3,7 @@ import { I18nProvider } from "@/i18n"; | |||||
import DashboardPage from "@/components/DashboardPage/DashboardPage"; | import DashboardPage from "@/components/DashboardPage/DashboardPage"; | ||||
import DashboardPageButton from "@/components/DashboardPage/DashboardTabButton"; | import DashboardPageButton from "@/components/DashboardPage/DashboardTabButton"; | ||||
import ProgressByClientSearch from "@/components/ProgressByClientSearch"; | import ProgressByClientSearch from "@/components/ProgressByClientSearch"; | ||||
import { Suspense} from "react"; | |||||
import { Suspense } from "react"; | |||||
import Tabs, { TabsProps } from "@mui/material/Tabs"; | import Tabs, { TabsProps } from "@mui/material/Tabs"; | ||||
import Tab from "@mui/material/Tab"; | import Tab from "@mui/material/Tab"; | ||||
@@ -11,12 +11,8 @@ export const metadata: Metadata = { | |||||
title: "Dashboard", | title: "Dashboard", | ||||
}; | }; | ||||
const Dashboard: React.FC = () => { | const Dashboard: React.FC = () => { | ||||
return ( | |||||
<div>test</div> | |||||
); | |||||
return <div>test</div>; | |||||
}; | }; | ||||
export default Dashboard; | export default Dashboard; |
@@ -9,8 +9,8 @@ export const metadata: Metadata = { | |||||
const Home: React.FC = async () => { | const Home: React.FC = async () => { | ||||
return ( | return ( | ||||
<I18nProvider namespaces={["home"]}> | <I18nProvider namespaces={["home"]}> | ||||
<UserWorkspacePage/> | |||||
</I18nProvider> | |||||
<UserWorkspacePage /> | |||||
</I18nProvider> | |||||
); | ); | ||||
}; | }; | ||||
@@ -34,6 +34,6 @@ const mockProjects: CashFlow[] = [ | |||||
startDateTo: "5", | startDateTo: "5", | ||||
targetEndDate: "s", | targetEndDate: "s", | ||||
client: "ss", | client: "ss", | ||||
subsidiary:"ss", | |||||
} | |||||
subsidiary: "ss", | |||||
}, | |||||
]; | ]; |
@@ -24,7 +24,7 @@ const mockClaims: ClaimResult[] = [ | |||||
id: 1, | id: 1, | ||||
created: "2023-11-22", | created: "2023-11-22", | ||||
name: "Consultancy Project A", | name: "Consultancy Project A", | ||||
cost: 121.00, | |||||
cost: 121.0, | |||||
type: "Expense", | type: "Expense", | ||||
status: "Not Submitted", | status: "Not Submitted", | ||||
remarks: "", | remarks: "", | ||||
@@ -33,7 +33,7 @@ const mockClaims: ClaimResult[] = [ | |||||
id: 2, | id: 2, | ||||
created: "2023-11-30", | created: "2023-11-30", | ||||
name: "Consultancy Project A", | name: "Consultancy Project A", | ||||
cost: 4300.00, | |||||
cost: 4300.0, | |||||
type: "Expense", | type: "Expense", | ||||
status: "Waiting for Approval", | status: "Waiting for Approval", | ||||
remarks: "", | remarks: "", | ||||
@@ -42,7 +42,7 @@ const mockClaims: ClaimResult[] = [ | |||||
id: 3, | id: 3, | ||||
created: "2023-12-12", | created: "2023-12-12", | ||||
name: "Construction Project C", | name: "Construction Project C", | ||||
cost: 3675.00, | |||||
cost: 3675.0, | |||||
type: "Petty Cash", | type: "Petty Cash", | ||||
status: "Rejected", | status: "Rejected", | ||||
remarks: "Duplicate Claim Form", | remarks: "Duplicate Claim Form", | ||||
@@ -16,7 +16,7 @@ const AppBar: React.FC<AppBarProps> = ({ avatarImageSrc, profileName }) => { | |||||
<I18nProvider namespaces={["common"]}> | <I18nProvider namespaces={["common"]}> | ||||
<MUIAppBar position="sticky" color="default" elevation={4}> | <MUIAppBar position="sticky" color="default" elevation={4}> | ||||
<Toolbar> | <Toolbar> | ||||
<NavigationToggle/> | |||||
<NavigationToggle /> | |||||
<Box | <Box | ||||
sx={{ flexGrow: 1, display: "flex", justifyContent: "flex-end" }} | sx={{ flexGrow: 1, display: "flex", justifyContent: "flex-end" }} | ||||
> | > | ||||
@@ -1,15 +1,26 @@ | |||||
import * as React from 'react'; | |||||
import { Card, CardHeader, CardContent, SxProps, Theme, Tabs, Tab, Box, Typography, Grid, Link} from '@mui/material'; | |||||
import { DataGrid, GridColDef } from '@mui/x-data-grid'; | |||||
import { darken, lighten, styled } from '@mui/material/styles'; | |||||
import { ThemeProvider } from '@emotion/react'; | |||||
import { TAB_THEME } from '@/theme/colorConst'; | |||||
import AllProjectGrid from '../UserWorkspacePage/ProjectGrid'; | |||||
import * as React from "react"; | |||||
import { | |||||
Card, | |||||
CardHeader, | |||||
CardContent, | |||||
SxProps, | |||||
Theme, | |||||
Tabs, | |||||
Tab, | |||||
Box, | |||||
Typography, | |||||
Grid, | |||||
Link, | |||||
} from "@mui/material"; | |||||
import { DataGrid, GridColDef } from "@mui/x-data-grid"; | |||||
import { darken, lighten, styled } from "@mui/material/styles"; | |||||
import { ThemeProvider } from "@emotion/react"; | |||||
import { TAB_THEME } from "@/theme/colorConst"; | |||||
import AllProjectGrid from "../UserWorkspacePage/ProjectGrid"; | |||||
interface AssignedProjectGridProps { | interface AssignedProjectGridProps { | ||||
Title?: string; | Title?: string; | ||||
// rows: any[]; | |||||
// rows: any[]; | |||||
// columns: any[]; | // columns: any[]; | ||||
columnWidth?: number; | columnWidth?: number; | ||||
Style?: boolean; | Style?: boolean; | ||||
@@ -47,7 +58,7 @@ function CustomTabPanel(props: TabPanelProps) { | |||||
function a11yProps(index: number) { | function a11yProps(index: number) { | ||||
return { | return { | ||||
id: `simple-tab-${index}`, | id: `simple-tab-${index}`, | ||||
'aria-controls': `simple-tabpanel-${index}`, | |||||
"aria-controls": `simple-tabpanel-${index}`, | |||||
}; | }; | ||||
} | } | ||||
@@ -72,67 +83,117 @@ const AssignedProjectGrid: React.FC<AssignedProjectGridProps> = ({ | |||||
// return { ...row }; | // return { ...row }; | ||||
// }); | // }); | ||||
const getBackgroundColor = (color: string, mode: 'light' | 'dark') => | |||||
mode === 'dark' ? darken(color, 0.7) : lighten(color, 0.7); | |||||
const getBackgroundColor = (color: string, mode: "light" | "dark") => | |||||
mode === "dark" ? darken(color, 0.7) : lighten(color, 0.7); | |||||
const getHoverBackgroundColor = (color: string, mode: 'light' | 'dark') => | |||||
mode === 'dark' ? darken(color, 0.6) : lighten(color, 0.6); | |||||
const getHoverBackgroundColor = (color: string, mode: "light" | "dark") => | |||||
mode === "dark" ? darken(color, 0.6) : lighten(color, 0.6); | |||||
const getSelectedBackgroundColor = (color: string, mode: 'light' | 'dark') => | |||||
mode === 'dark' ? darken(color, 0.5) : lighten(color, 0.5); | |||||
const getSelectedBackgroundColor = (color: string, mode: "light" | "dark") => | |||||
mode === "dark" ? darken(color, 0.5) : lighten(color, 0.5); | |||||
const getSelectedHoverBackgroundColor = (color: string, mode: 'light' | 'dark') => | |||||
mode === 'dark' ? darken(color, 0.4) : lighten(color, 0.4); | |||||
const getSelectedHoverBackgroundColor = ( | |||||
color: string, | |||||
mode: "light" | "dark", | |||||
) => (mode === "dark" ? darken(color, 0.4) : lighten(color, 0.4)); | |||||
const StyledDataGrid = styled(DataGrid)(({ theme }) => ({ | const StyledDataGrid = styled(DataGrid)(({ theme }) => ({ | ||||
'& .super-app-theme--Open': { | |||||
backgroundColor: getBackgroundColor(theme.palette.info.main, theme.palette.mode), | |||||
'&:hover': { | |||||
backgroundColor: getHoverBackgroundColor(theme.palette.info.main, theme.palette.mode) | |||||
"& .super-app-theme--Open": { | |||||
backgroundColor: getBackgroundColor( | |||||
theme.palette.info.main, | |||||
theme.palette.mode, | |||||
), | |||||
"&:hover": { | |||||
backgroundColor: getHoverBackgroundColor( | |||||
theme.palette.info.main, | |||||
theme.palette.mode, | |||||
), | |||||
}, | |||||
"&.Mui-selected": { | |||||
backgroundColor: getSelectedBackgroundColor( | |||||
theme.palette.info.main, | |||||
theme.palette.mode, | |||||
), | |||||
"&:hover": { | |||||
backgroundColor: getSelectedHoverBackgroundColor( | |||||
theme.palette.info.main, | |||||
theme.palette.mode, | |||||
), | |||||
}, | |||||
}, | }, | ||||
'&.Mui-selected': { | |||||
backgroundColor: getSelectedBackgroundColor(theme.palette.info.main, theme.palette.mode), | |||||
'&:hover': { | |||||
backgroundColor: getSelectedHoverBackgroundColor(theme.palette.info.main, theme.palette.mode) | |||||
} | |||||
} | |||||
}, | }, | ||||
'& .super-app-theme--finish': { | |||||
backgroundColor: getBackgroundColor(theme.palette.success.main, theme.palette.mode), | |||||
'&:hover': { | |||||
backgroundColor: getHoverBackgroundColor(theme.palette.success.main, theme.palette.mode) | |||||
"& .super-app-theme--finish": { | |||||
backgroundColor: getBackgroundColor( | |||||
theme.palette.success.main, | |||||
theme.palette.mode, | |||||
), | |||||
"&:hover": { | |||||
backgroundColor: getHoverBackgroundColor( | |||||
theme.palette.success.main, | |||||
theme.palette.mode, | |||||
), | |||||
}, | |||||
"&.Mui-selected": { | |||||
backgroundColor: getSelectedBackgroundColor( | |||||
theme.palette.success.main, | |||||
theme.palette.mode, | |||||
), | |||||
"&:hover": { | |||||
backgroundColor: getSelectedHoverBackgroundColor( | |||||
theme.palette.success.main, | |||||
theme.palette.mode, | |||||
), | |||||
}, | |||||
}, | }, | ||||
'&.Mui-selected': { | |||||
backgroundColor: getSelectedBackgroundColor(theme.palette.success.main, theme.palette.mode), | |||||
'&:hover': { | |||||
backgroundColor: getSelectedHoverBackgroundColor(theme.palette.success.main, theme.palette.mode) | |||||
} | |||||
} | |||||
}, | }, | ||||
'& .super-app-theme--danger': { | |||||
backgroundColor: getBackgroundColor(theme.palette.warning.main, theme.palette.mode), | |||||
'&:hover': { | |||||
backgroundColor: getHoverBackgroundColor(theme.palette.warning.main, theme.palette.mode) | |||||
"& .super-app-theme--danger": { | |||||
backgroundColor: getBackgroundColor( | |||||
theme.palette.warning.main, | |||||
theme.palette.mode, | |||||
), | |||||
"&:hover": { | |||||
backgroundColor: getHoverBackgroundColor( | |||||
theme.palette.warning.main, | |||||
theme.palette.mode, | |||||
), | |||||
}, | |||||
"&.Mui-selected": { | |||||
backgroundColor: getSelectedBackgroundColor( | |||||
theme.palette.warning.main, | |||||
theme.palette.mode, | |||||
), | |||||
"&:hover": { | |||||
backgroundColor: getSelectedHoverBackgroundColor( | |||||
theme.palette.warning.main, | |||||
theme.palette.mode, | |||||
), | |||||
}, | |||||
}, | }, | ||||
'&.Mui-selected': { | |||||
backgroundColor: getSelectedBackgroundColor(theme.palette.warning.main, theme.palette.mode), | |||||
'&:hover': { | |||||
backgroundColor: getSelectedHoverBackgroundColor(theme.palette.warning.main, theme.palette.mode) | |||||
} | |||||
} | |||||
}, | }, | ||||
'& .super-app-theme--warning': { | |||||
backgroundColor: getBackgroundColor(theme.palette.error.main, theme.palette.mode), | |||||
'&:hover': { | |||||
backgroundColor: getHoverBackgroundColor(theme.palette.error.main, theme.palette.mode) | |||||
"& .super-app-theme--warning": { | |||||
backgroundColor: getBackgroundColor( | |||||
theme.palette.error.main, | |||||
theme.palette.mode, | |||||
), | |||||
"&:hover": { | |||||
backgroundColor: getHoverBackgroundColor( | |||||
theme.palette.error.main, | |||||
theme.palette.mode, | |||||
), | |||||
}, | }, | ||||
'&.Mui-selected': { | |||||
backgroundColor: getSelectedBackgroundColor(theme.palette.error.main, theme.palette.mode), | |||||
'&:hover': { | |||||
backgroundColor: getSelectedHoverBackgroundColor(theme.palette.error.main, theme.palette.mode) | |||||
} | |||||
} | |||||
} | |||||
"&.Mui-selected": { | |||||
backgroundColor: getSelectedBackgroundColor( | |||||
theme.palette.error.main, | |||||
theme.palette.mode, | |||||
), | |||||
"&:hover": { | |||||
backgroundColor: getSelectedHoverBackgroundColor( | |||||
theme.palette.error.main, | |||||
theme.palette.mode, | |||||
), | |||||
}, | |||||
}, | |||||
}, | |||||
})); | })); | ||||
const [value, setValue] = React.useState(0); | const [value, setValue] = React.useState(0); | ||||
@@ -142,20 +203,30 @@ const AssignedProjectGrid: React.FC<AssignedProjectGridProps> = ({ | |||||
}; | }; | ||||
return ( | return ( | ||||
<div style={{ height: height ?? 400, width: '100%' }}> | |||||
<Card style={{ margin: "auto 20px auto 20px" }}> | |||||
{Title && <CardHeader title={Title} />} | |||||
<CardContent style={{ padding: "0px 24px 24px 24px", display: "flex", alignItems: "center" }}> | |||||
<div> | |||||
<ThemeProvider theme={TAB_THEME}> | |||||
<Box sx={{ borderBottom: 4, borderColor: 'divider' }}> | |||||
<Tabs value={value} onChange={handleChange} aria-label="Manage assigned project"> | |||||
<Tab label="All Projects" {...a11yProps(0)} /> | |||||
<Tab label="On Track" {...a11yProps(1)} /> | |||||
<Tab label="Potential Delay" {...a11yProps(2)} /> | |||||
</Tabs> | |||||
</Box> | |||||
{/* <CustomTabPanel value={value} index={0}> | |||||
<div style={{ height: height ?? 400, width: "100%" }}> | |||||
<Card style={{ margin: "auto 20px auto 20px" }}> | |||||
{Title && <CardHeader title={Title} />} | |||||
<CardContent | |||||
style={{ | |||||
padding: "0px 24px 24px 24px", | |||||
display: "flex", | |||||
alignItems: "center", | |||||
}} | |||||
> | |||||
<div> | |||||
<ThemeProvider theme={TAB_THEME}> | |||||
<Box sx={{ borderBottom: 4, borderColor: "divider" }}> | |||||
<Tabs | |||||
value={value} | |||||
onChange={handleChange} | |||||
aria-label="Manage assigned project" | |||||
> | |||||
<Tab label="All Projects" {...a11yProps(0)} /> | |||||
<Tab label="On Track" {...a11yProps(1)} /> | |||||
<Tab label="Potential Delay" {...a11yProps(2)} /> | |||||
</Tabs> | |||||
</Box> | |||||
{/* <CustomTabPanel value={value} index={0}> | |||||
Item {value} | Item {value} | ||||
</CustomTabPanel> | </CustomTabPanel> | ||||
<CustomTabPanel value={value} index={1}> | <CustomTabPanel value={value} index={1}> | ||||
@@ -164,12 +235,12 @@ const AssignedProjectGrid: React.FC<AssignedProjectGridProps> = ({ | |||||
<CustomTabPanel value={value} index={2}> | <CustomTabPanel value={value} index={2}> | ||||
Item {value} | Item {value} | ||||
</CustomTabPanel> */} | </CustomTabPanel> */} | ||||
</ThemeProvider> | |||||
</div> | |||||
</CardContent> | |||||
<AllProjectGrid tab={value} /> | |||||
</Card> | |||||
</div> | |||||
</ThemeProvider> | |||||
</div> | |||||
</CardContent> | |||||
<AllProjectGrid tab={value} /> | |||||
</Card> | |||||
</div> | |||||
); | ); | ||||
}; | }; | ||||
@@ -39,7 +39,12 @@ const ClaimSearch: React.FC<Props> = ({ claims }) => { | |||||
label: t("Status"), | label: t("Status"), | ||||
paramName: "status", | paramName: "status", | ||||
type: "select", | type: "select", | ||||
options: ["Not Submitted", "Waiting for Approval", "Approved", "Rejected"] | |||||
options: [ | |||||
"Not Submitted", | |||||
"Waiting for Approval", | |||||
"Approved", | |||||
"Rejected", | |||||
], | |||||
}, | }, | ||||
{ | { | ||||
label: t("Remarks"), | label: t("Remarks"), | ||||
@@ -80,10 +85,7 @@ const ClaimSearch: React.FC<Props> = ({ claims }) => { | |||||
console.log(query); | console.log(query); | ||||
}} | }} | ||||
/> | /> | ||||
<SearchResults<ClaimResult> | |||||
items={filteredClaims} | |||||
columns={columns} | |||||
/> | |||||
<SearchResults<ClaimResult> items={filteredClaims} columns={columns} /> | |||||
</> | </> | ||||
); | ); | ||||
}; | }; | ||||
@@ -1,129 +1,131 @@ | |||||
"use client"; | "use client"; | ||||
import * as React from "react"; | import * as React from "react"; | ||||
import Grid from "@mui/material/Grid"; | import Grid from "@mui/material/Grid"; | ||||
import { useState,useEffect, useMemo } from 'react' | |||||
import { useState, useEffect, useMemo } from "react"; | |||||
import Paper from "@mui/material/Paper"; | import Paper from "@mui/material/Paper"; | ||||
import { TFunction } from "i18next"; | import { TFunction } from "i18next"; | ||||
import { useTranslation } from "react-i18next"; | import { useTranslation } from "react-i18next"; | ||||
import {Card,CardHeader} from '@mui/material'; | |||||
import { Card, CardHeader } from "@mui/material"; | |||||
import CustomSearchForm from "../CustomSearchForm/CustomSearchForm"; | import CustomSearchForm from "../CustomSearchForm/CustomSearchForm"; | ||||
import CustomDatagrid from '../CustomDatagrid/CustomDatagrid'; | |||||
import ReactApexChart from 'react-apexcharts'; | |||||
import { ApexOptions } from 'apexcharts'; | |||||
import { GridColDef, GridRowSelectionModel} from '@mui/x-data-grid'; | |||||
import ReportProblemIcon from '@mui/icons-material/ReportProblem'; | |||||
import dynamic from 'next/dynamic'; | |||||
import '../../app/global.css'; | |||||
import CustomDatagrid from "../CustomDatagrid/CustomDatagrid"; | |||||
import ReactApexChart from "react-apexcharts"; | |||||
import { ApexOptions } from "apexcharts"; | |||||
import { GridColDef, GridRowSelectionModel } from "@mui/x-data-grid"; | |||||
import ReportProblemIcon from "@mui/icons-material/ReportProblem"; | |||||
import dynamic from "next/dynamic"; | |||||
import "../../app/global.css"; | |||||
import { AnyARecord, AnyCnameRecord } from "dns"; | import { AnyARecord, AnyCnameRecord } from "dns"; | ||||
import SearchBox, { Criterion } from "../SearchBox"; | import SearchBox, { Criterion } from "../SearchBox"; | ||||
import ProgressByClientSearch from "@/components/ProgressByClientSearch"; | import ProgressByClientSearch from "@/components/ProgressByClientSearch"; | ||||
import { Suspense } from "react"; | import { Suspense } from "react"; | ||||
import ProgressCashFlowSearch from "@/components/ProgressCashFlowSearch"; | import ProgressCashFlowSearch from "@/components/ProgressCashFlowSearch"; | ||||
import {Input,Label} from "reactstrap"; | |||||
import Select, {components} from 'react-select' | |||||
import { Input, Label } from "reactstrap"; | |||||
import Select, { components } from "react-select"; | |||||
const CompanyTeamCashFlow: React.FC = () => { | const CompanyTeamCashFlow: React.FC = () => { | ||||
const todayDate = new Date; | |||||
const [selectionModel, setSelectionModel] : any[] = React.useState([]); | |||||
const [cashFlowYear, setCashFlowYear] : any[] = React.useState(todayDate.getFullYear()); | |||||
const todayDate = new Date(); | |||||
const [selectionModel, setSelectionModel]: any[] = React.useState([]); | |||||
const [cashFlowYear, setCashFlowYear]: any[] = React.useState( | |||||
todayDate.getFullYear(), | |||||
); | |||||
const teamOptions = [ | const teamOptions = [ | ||||
{ value: 1, label: 'XXX Team' }, | |||||
{ value: 2, label: 'YYY Team' }, | |||||
{ value: 3, label: 'ZZZ Team' } | |||||
] | |||||
{ value: 1, label: "XXX Team" }, | |||||
{ value: 2, label: "YYY Team" }, | |||||
{ value: 3, label: "ZZZ Team" }, | |||||
]; | |||||
const columns = [ | const columns = [ | ||||
{ | { | ||||
id: 'projectCode', | |||||
field: 'projectCode', | |||||
id: "projectCode", | |||||
field: "projectCode", | |||||
headerName: "Project Code", | headerName: "Project Code", | ||||
flex: 1, | flex: 1, | ||||
}, | |||||
{ | |||||
id: 'projectName', | |||||
field: 'projectName', | |||||
}, | |||||
{ | |||||
id: "projectName", | |||||
field: "projectName", | |||||
headerName: "Project Name", | headerName: "Project Name", | ||||
flex: 1, | flex: 1, | ||||
}, | |||||
{ | |||||
id: 'team', | |||||
field: 'team', | |||||
headerName: "Team", | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: 'teamLeader', | |||||
field: 'teamLeader', | |||||
headerName: "Team Leader", | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: 'startDate', | |||||
field: 'startDate', | |||||
headerName: "Start Date", | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: 'targetEndDate', | |||||
field: 'targetEndDate', | |||||
headerName: "Target End Date", | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: 'client', | |||||
field: 'client', | |||||
headerName: "Client", | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: 'subsidiary', | |||||
field: 'subsidiary', | |||||
headerName: "Subsidiary", | |||||
flex: 1, | |||||
}, | |||||
}, | |||||
{ | |||||
id: "team", | |||||
field: "team", | |||||
headerName: "Team", | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: "teamLeader", | |||||
field: "teamLeader", | |||||
headerName: "Team Leader", | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: "startDate", | |||||
field: "startDate", | |||||
headerName: "Start Date", | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: "targetEndDate", | |||||
field: "targetEndDate", | |||||
headerName: "Target End Date", | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: "client", | |||||
field: "client", | |||||
headerName: "Client", | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: "subsidiary", | |||||
field: "subsidiary", | |||||
headerName: "Subsidiary", | |||||
flex: 1, | |||||
}, | |||||
]; | ]; | ||||
const ledgerColumns = [ | const ledgerColumns = [ | ||||
{ | { | ||||
id: 'date', | |||||
field: 'date', | |||||
id: "date", | |||||
field: "date", | |||||
headerName: "Date", | headerName: "Date", | ||||
flex: 0.5, | flex: 0.5, | ||||
}, | |||||
{ | |||||
id: 'expenditure', | |||||
field: 'expenditure', | |||||
}, | |||||
{ | |||||
id: "expenditure", | |||||
field: "expenditure", | |||||
headerName: "Expenditure (HKD)", | headerName: "Expenditure (HKD)", | ||||
flex: 0.6, | flex: 0.6, | ||||
}, | |||||
{ | |||||
id: 'income', | |||||
field: 'income', | |||||
headerName: "Income (HKD)", | |||||
flex: 0.6, | |||||
}, | |||||
{ | |||||
id: 'cashFlowBalance', | |||||
field: 'cashFlowBalance', | |||||
headerName: "Cash Flow Balance (HKD)", | |||||
flex: 0.6, | |||||
}, | |||||
{ | |||||
id: 'remarks', | |||||
field: 'remarks', | |||||
headerName: "Remarks", | |||||
flex: 1, | |||||
}, | |||||
}, | |||||
{ | |||||
id: "income", | |||||
field: "income", | |||||
headerName: "Income (HKD)", | |||||
flex: 0.6, | |||||
}, | |||||
{ | |||||
id: "cashFlowBalance", | |||||
field: "cashFlowBalance", | |||||
headerName: "Cash Flow Balance (HKD)", | |||||
flex: 0.6, | |||||
}, | |||||
{ | |||||
id: "remarks", | |||||
field: "remarks", | |||||
headerName: "Remarks", | |||||
flex: 1, | |||||
}, | |||||
]; | ]; | ||||
const options: ApexOptions = { | const options: ApexOptions = { | ||||
chart: { | chart: { | ||||
height: 350, | height: 350, | ||||
type: 'line', | |||||
type: "line", | |||||
}, | }, | ||||
stroke: { | stroke: { | ||||
width: [0, 0, 2, 2] | |||||
width: [0, 0, 2, 2], | |||||
}, | }, | ||||
plotOptions: { | plotOptions: { | ||||
bar: { | bar: { | ||||
@@ -132,152 +134,171 @@ const CompanyTeamCashFlow: React.FC = () => { | |||||
}, | }, | ||||
}, | }, | ||||
dataLabels: { | dataLabels: { | ||||
enabled: false | |||||
enabled: false, | |||||
}, | }, | ||||
xaxis: { | xaxis: { | ||||
categories: [ | categories: [ | ||||
'Q1', | |||||
'Q2', | |||||
'Q3', | |||||
'Q4', | |||||
'Q5', | |||||
'Q6', | |||||
'Q7', | |||||
'Q8', | |||||
'Q9', | |||||
'Q10', | |||||
'Q11', | |||||
'Q12', | |||||
"Q1", | |||||
"Q2", | |||||
"Q3", | |||||
"Q4", | |||||
"Q5", | |||||
"Q6", | |||||
"Q7", | |||||
"Q8", | |||||
"Q9", | |||||
"Q10", | |||||
"Q11", | |||||
"Q12", | |||||
], | ], | ||||
}, | }, | ||||
yaxis: [ | yaxis: [ | ||||
{ | { | ||||
title: { | title: { | ||||
text: 'Monthly Income and Expenditure(HKD)' | |||||
text: "Monthly Income and Expenditure(HKD)", | |||||
}, | }, | ||||
min: 0, | min: 0, | ||||
max: 3700000, | max: 3700000, | ||||
tickAmount: 5 | |||||
tickAmount: 5, | |||||
}, | }, | ||||
{ | { | ||||
show:false, | |||||
seriesName: 'Monthly_Expenditure', | |||||
show: false, | |||||
seriesName: "Monthly_Expenditure", | |||||
title: { | title: { | ||||
text: 'Monthly Expenditure (HKD)' | |||||
text: "Monthly Expenditure (HKD)", | |||||
}, | }, | ||||
min: 0, | min: 0, | ||||
max: 3700000, | max: 3700000, | ||||
tickAmount: 5 | |||||
tickAmount: 5, | |||||
}, | }, | ||||
{ | { | ||||
seriesName: 'Cumulative_Income', | |||||
seriesName: "Cumulative_Income", | |||||
opposite: true, | opposite: true, | ||||
title: { | title: { | ||||
text: 'Cumulative Income and Expenditure(HKD)' | |||||
text: "Cumulative Income and Expenditure(HKD)", | |||||
}, | }, | ||||
min: 0, | min: 0, | ||||
max: 21000000, | max: 21000000, | ||||
tickAmount: 5 | |||||
tickAmount: 5, | |||||
}, | }, | ||||
{ | { | ||||
show:false, | |||||
seriesName: 'Cumulative_Expenditure', | |||||
show: false, | |||||
seriesName: "Cumulative_Expenditure", | |||||
opposite: true, | opposite: true, | ||||
title: { | title: { | ||||
text: 'Cumulative Expenditure (HKD)' | |||||
text: "Cumulative Expenditure (HKD)", | |||||
}, | }, | ||||
min: 0, | min: 0, | ||||
max: 21000000, | max: 21000000, | ||||
tickAmount: 5 | |||||
} | |||||
], | |||||
tickAmount: 5, | |||||
}, | |||||
], | |||||
grid: { | grid: { | ||||
borderColor: '#f1f1f1', | |||||
borderColor: "#f1f1f1", | |||||
}, | }, | ||||
annotations: { | |||||
}, | |||||
series:[ | |||||
annotations: {}, | |||||
series: [ | |||||
{ | { | ||||
name:"Monthly_Income", | |||||
type:"column", | |||||
name: "Monthly_Income", | |||||
type: "column", | |||||
color: "#ffde91", | color: "#ffde91", | ||||
data:[1280000,170000,3600000,2400000,1000000,1800000,1800000,1200000,1250000,1200000,600000,2400000], | |||||
data: [ | |||||
1280000, 170000, 3600000, 2400000, 1000000, 1800000, 1800000, 1200000, | |||||
1250000, 1200000, 600000, 2400000, | |||||
], | |||||
}, | }, | ||||
{ | { | ||||
name:"Monthly_Expenditure", | |||||
type:"column", | |||||
name: "Monthly_Expenditure", | |||||
type: "column", | |||||
color: "#82b59a", | color: "#82b59a", | ||||
data:[1200000,1400000,2000000,1400000,1450000,1800000,1200000,1400000,1200000,1600000,2000000,1600000] | |||||
data: [ | |||||
1200000, 1400000, 2000000, 1400000, 1450000, 1800000, 1200000, | |||||
1400000, 1200000, 1600000, 2000000, 1600000, | |||||
], | |||||
}, | }, | ||||
{ | { | ||||
name:"Cumulative_Income", | |||||
type:"line", | |||||
name: "Cumulative_Income", | |||||
type: "line", | |||||
color: "#EE6D7A", | color: "#EE6D7A", | ||||
data:[500000,3000000,7000000,9000000,10000000,13000000,14000000,16000000,17000000,17500000,18000000,20000000] | |||||
data: [ | |||||
500000, 3000000, 7000000, 9000000, 10000000, 13000000, 14000000, | |||||
16000000, 17000000, 17500000, 18000000, 20000000, | |||||
], | |||||
}, | }, | ||||
{ | { | ||||
name:"Cumulative_Expenditure", | |||||
type:"line", | |||||
name: "Cumulative_Expenditure", | |||||
type: "line", | |||||
color: "#7cd3f2", | color: "#7cd3f2", | ||||
data:[400000,2800000,4000000,5200000,7100000,8000000,10000000,11000000,12100000,14000000,15400000,17200000] | |||||
} | |||||
] | |||||
data: [ | |||||
400000, 2800000, 4000000, 5200000, 7100000, 8000000, 10000000, | |||||
11000000, 12100000, 14000000, 15400000, 17200000, | |||||
], | |||||
}, | |||||
], | |||||
}; | }; | ||||
return ( | return ( | ||||
<> | <> | ||||
<Grid item sm> | |||||
<div style={{display:"inline-block",width:"100%"}}> | |||||
<Grid item xs={12} md={12} lg={12}> | |||||
<Card> | |||||
<CardHeader className="text-slate-500" title="Company and Team Cash Flow by Month"/> | |||||
<div style={{display:"inline-block",width:"99%"}}> | |||||
<div className="inline-block"> | |||||
<Label className="text-slate-500 font-medium ml-6"> | |||||
Period: | |||||
</Label> | |||||
<Input | |||||
id={'cashFlowYear'} | |||||
value={cashFlowYear} | |||||
readOnly={true} | |||||
bsSize="lg" | |||||
className="rounded-md text-base w-12" | |||||
/> | |||||
</div> | |||||
<div className="inline-block ml-1"> | |||||
<button onClick={() => setCashFlowYear(cashFlowYear - 1)} className="hover:cursor-pointer hover:bg-slate-200 bg-transparent rounded-md w-8 h-8 text-base"> | |||||
< | |||||
</button> | |||||
</div> | |||||
<div className="inline-block ml-1"> | |||||
<button onClick={() => setCashFlowYear(cashFlowYear + 1)} className="hover:cursor-pointer hover:bg-slate-200 bg-transparent rounded-md w-8 h-8 text-base"> | |||||
> | |||||
</button> | |||||
</div> | |||||
<div className="inline-block ml-2"> | |||||
<Label className="text-slate-500 font-medium"> | |||||
Team: | |||||
</Label> | |||||
</div> | |||||
<div className="inline-block ml-1 w-60"> | |||||
<Select | |||||
placeholder= "All Team" | |||||
options={teamOptions} | |||||
isClearable={true} | |||||
/> | |||||
</div> | |||||
<ReactApexChart | |||||
options={options} | |||||
series={options.series} | |||||
type="line" | |||||
height="500" | |||||
/> | |||||
</div> | |||||
</Card> | |||||
</Grid> | |||||
</div> | |||||
</Grid> | |||||
<Grid item sm> | |||||
<div style={{ display: "inline-block", width: "100%" }}> | |||||
<Grid item xs={12} md={12} lg={12}> | |||||
<Card> | |||||
<CardHeader | |||||
className="text-slate-500" | |||||
title="Company and Team Cash Flow by Month" | |||||
/> | |||||
<div style={{ display: "inline-block", width: "99%" }}> | |||||
<div className="inline-block"> | |||||
<Label className="text-slate-500 font-medium ml-6"> | |||||
Period: | |||||
</Label> | |||||
<Input | |||||
id={"cashFlowYear"} | |||||
value={cashFlowYear} | |||||
readOnly={true} | |||||
bsSize="lg" | |||||
className="rounded-md text-base w-12" | |||||
/> | |||||
</div> | |||||
<div className="inline-block ml-1"> | |||||
<button | |||||
onClick={() => setCashFlowYear(cashFlowYear - 1)} | |||||
className="hover:cursor-pointer hover:bg-slate-200 bg-transparent rounded-md w-8 h-8 text-base" | |||||
> | |||||
< | |||||
</button> | |||||
</div> | |||||
<div className="inline-block ml-1"> | |||||
<button | |||||
onClick={() => setCashFlowYear(cashFlowYear + 1)} | |||||
className="hover:cursor-pointer hover:bg-slate-200 bg-transparent rounded-md w-8 h-8 text-base" | |||||
> | |||||
> | |||||
</button> | |||||
</div> | |||||
<div className="inline-block ml-2"> | |||||
<Label className="text-slate-500 font-medium"> | |||||
Team: | |||||
</Label> | |||||
</div> | |||||
<div className="inline-block ml-1 w-60"> | |||||
<Select | |||||
placeholder="All Team" | |||||
options={teamOptions} | |||||
isClearable={true} | |||||
/> | |||||
</div> | |||||
<ReactApexChart | |||||
options={options} | |||||
series={options.series} | |||||
type="line" | |||||
height="500" | |||||
/> | |||||
</div> | |||||
</Card> | |||||
</Grid> | |||||
</div> | |||||
</Grid> | |||||
</> | </> | ||||
); | ); | ||||
}; | }; | ||||
@@ -31,18 +31,10 @@ const ClaimDetails: React.FC = () => { | |||||
<Grid item xs={6}> | <Grid item xs={6}> | ||||
<FormControl fullWidth> | <FormControl fullWidth> | ||||
<InputLabel>{t("Related Project")}</InputLabel> | <InputLabel>{t("Related Project")}</InputLabel> | ||||
<Select | |||||
label={t("Project Category")} | |||||
> | |||||
<MenuItem value={"M1001"}> | |||||
{t("M1001")} | |||||
</MenuItem> | |||||
<MenuItem value={"M1301"}> | |||||
{t("M1301")} | |||||
</MenuItem> | |||||
<MenuItem value={"M1354"}> | |||||
{t("M1354")} | |||||
</MenuItem> | |||||
<Select label={t("Project Category")}> | |||||
<MenuItem value={"M1001"}>{t("M1001")}</MenuItem> | |||||
<MenuItem value={"M1301"}>{t("M1301")}</MenuItem> | |||||
<MenuItem value={"M1354"}>{t("M1354")}</MenuItem> | |||||
</Select> | </Select> | ||||
</FormControl> | </FormControl> | ||||
</Grid> | </Grid> | ||||
@@ -50,20 +42,16 @@ const ClaimDetails: React.FC = () => { | |||||
<FormControl fullWidth> | <FormControl fullWidth> | ||||
<InputLabel>{t("Expense Type")}</InputLabel> | <InputLabel>{t("Expense Type")}</InputLabel> | ||||
<Select label={t("Team Lead")}> | <Select label={t("Team Lead")}> | ||||
<MenuItem value={"Petty Cash"}> | |||||
{"Petty Cash"} | |||||
</MenuItem> | |||||
<MenuItem value={"Expense"}> | |||||
{"Expense"} | |||||
</MenuItem> | |||||
<MenuItem value={"Petty Cash"}>{"Petty Cash"}</MenuItem> | |||||
<MenuItem value={"Expense"}>{"Expense"}</MenuItem> | |||||
</Select> | </Select> | ||||
</FormControl> | </FormControl> | ||||
</Grid> | </Grid> | ||||
</Grid> | </Grid> | ||||
</Box> | </Box> | ||||
<Card> | <Card> | ||||
<ClaimInputGrid/> | |||||
<ClaimInputGrid /> | |||||
</Card> | </Card> | ||||
{/* <CardActions sx={{ justifyContent: "flex-end" }}> | {/* <CardActions sx={{ justifyContent: "flex-end" }}> | ||||
@@ -8,22 +8,29 @@ import { Suspense } from "react"; | |||||
import Button from "@mui/material/Button"; | import Button from "@mui/material/Button"; | ||||
import Stack from "@mui/material/Stack"; | import Stack from "@mui/material/Stack"; | ||||
import Link from "next/link"; | import Link from "next/link"; | ||||
import { t } from 'i18next'; | |||||
import { Box, Container, Modal, Select, SelectChangeEvent, Typography } from "@mui/material"; | |||||
import { Close } from '@mui/icons-material'; | |||||
import AddIcon from '@mui/icons-material/Add'; | |||||
import EditIcon from '@mui/icons-material/Edit'; | |||||
import DeleteIcon from '@mui/icons-material/DeleteOutlined'; | |||||
import SaveIcon from '@mui/icons-material/Save'; | |||||
import CancelIcon from '@mui/icons-material/Close'; | |||||
import AddPhotoAlternateOutlinedIcon from '@mui/icons-material/AddPhotoAlternateOutlined'; | |||||
import ImageNotSupportedOutlinedIcon from '@mui/icons-material/ImageNotSupportedOutlined'; | |||||
import ArrowForwardIcon from '@mui/icons-material/ArrowForward'; | |||||
import ArrowBackIcon from '@mui/icons-material/ArrowBack'; | |||||
import { t } from "i18next"; | |||||
import { | |||||
Box, | |||||
Container, | |||||
Modal, | |||||
Select, | |||||
SelectChangeEvent, | |||||
Typography, | |||||
} from "@mui/material"; | |||||
import { Close } from "@mui/icons-material"; | |||||
import AddIcon from "@mui/icons-material/Add"; | |||||
import EditIcon from "@mui/icons-material/Edit"; | |||||
import DeleteIcon from "@mui/icons-material/DeleteOutlined"; | |||||
import SaveIcon from "@mui/icons-material/Save"; | |||||
import CancelIcon from "@mui/icons-material/Close"; | |||||
import AddPhotoAlternateOutlinedIcon from "@mui/icons-material/AddPhotoAlternateOutlined"; | |||||
import ImageNotSupportedOutlinedIcon from "@mui/icons-material/ImageNotSupportedOutlined"; | |||||
import ArrowForwardIcon from "@mui/icons-material/ArrowForward"; | |||||
import ArrowBackIcon from "@mui/icons-material/ArrowBack"; | |||||
import Swal from "sweetalert2"; | import Swal from "sweetalert2"; | ||||
import { msg } from "../Swal/CustomAlerts"; | import { msg } from "../Swal/CustomAlerts"; | ||||
import React from "react"; | import React from "react"; | ||||
import { DatePicker } from '@mui/x-date-pickers/DatePicker'; | |||||
import { DatePicker } from "@mui/x-date-pickers/DatePicker"; | |||||
import { | import { | ||||
GridRowsProp, | GridRowsProp, | ||||
GridRowModesModel, | GridRowModesModel, | ||||
@@ -39,14 +46,14 @@ import { | |||||
GridRowEditStopReasons, | GridRowEditStopReasons, | ||||
GridEditInputCell, | GridEditInputCell, | ||||
GridValueSetterParams, | GridValueSetterParams, | ||||
} from '@mui/x-data-grid'; | |||||
} from "@mui/x-data-grid"; | |||||
import { LocalizationProvider } from "@mui/x-date-pickers"; | import { LocalizationProvider } from "@mui/x-date-pickers"; | ||||
import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs"; | import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs"; | ||||
import dayjs from "dayjs"; | import dayjs from "dayjs"; | ||||
import { Props } from "react-intl/src/components/relative"; | import { Props } from "react-intl/src/components/relative"; | ||||
import palette from "@/theme/devias-material-kit/palette"; | import palette from "@/theme/devias-material-kit/palette"; | ||||
const weekdays = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun']; | |||||
const weekdays = ["mon", "tue", "wed", "thu", "fri", "sat", "sun"]; | |||||
interface BottomBarProps { | interface BottomBarProps { | ||||
getCostTotal: () => number; | getCostTotal: () => number; | ||||
@@ -81,58 +88,67 @@ const BottomBar = (props: BottomBarProps) => { | |||||
const handleAddClick = () => { | const handleAddClick = () => { | ||||
const id = newId; | const id = newId; | ||||
setNewId(newId - 1); | setNewId(newId - 1); | ||||
setRows((oldRows) => [...oldRows, { id, projectCode: '', task: '', isNew: true }]); | |||||
setRows((oldRows) => [ | |||||
...oldRows, | |||||
{ id, projectCode: "", task: "", isNew: true }, | |||||
]); | |||||
setRowModesModel((oldModel) => ({ | setRowModesModel((oldModel) => ({ | ||||
...oldModel, | ...oldModel, | ||||
[id]: { mode: GridRowModes.Edit, fieldToFocus: 'projectCode' }, | |||||
[id]: { mode: GridRowModes.Edit, fieldToFocus: "projectCode" }, | |||||
})); | })); | ||||
}; | }; | ||||
const totalColDef = { | const totalColDef = { | ||||
flex:1, | |||||
flex: 1, | |||||
// style: {color:getCostTotal('mon')>24?"red":"black"} | // style: {color:getCostTotal('mon')>24?"red":"black"} | ||||
}; | }; | ||||
const TotalCell = ({value}: Props) => { | |||||
const TotalCell = ({ value }: Props) => { | |||||
const [invalid, setInvalid] = useState(false); | const [invalid, setInvalid] = useState(false); | ||||
useEffect(()=> { | |||||
useEffect(() => { | |||||
const newInvalid = (value ?? 0) < 0; | const newInvalid = (value ?? 0) < 0; | ||||
setInvalid(newInvalid); | setInvalid(newInvalid); | ||||
}, [value]); | }, [value]); | ||||
return ( | return ( | ||||
<Box flex={1} style={{color: invalid?"red":"black"}}> | |||||
<Box flex={1} style={{ color: invalid ? "red" : "black" }}> | |||||
$ {value} | $ {value} | ||||
</Box> | </Box> | ||||
); | ); | ||||
} | |||||
}; | |||||
return ( | return ( | ||||
<div> | <div> | ||||
<div style={{ display: 'flex', justifyContent: 'flex', width: '100%' }}> | |||||
<Box flex={1.5} textAlign={'right'} marginRight='4rem'> | |||||
<div style={{ display: "flex", justifyContent: "flex", width: "100%" }}> | |||||
<Box flex={1.5} textAlign={"right"} marginRight="4rem"> | |||||
<b>Total:</b> | <b>Total:</b> | ||||
</Box> | </Box> | ||||
<TotalCell value={getCostTotal()}/> | |||||
<TotalCell value={getCostTotal()} /> | |||||
</div> | </div> | ||||
<Button variant="outlined" color="primary" startIcon={<AddIcon />} onClick={handleAddClick} sx={{margin:'20px'}}> | |||||
<Button | |||||
variant="outlined" | |||||
color="primary" | |||||
startIcon={<AddIcon />} | |||||
onClick={handleAddClick} | |||||
sx={{ margin: "20px" }} | |||||
> | |||||
Add record | Add record | ||||
</Button> | </Button> | ||||
</div> | </div> | ||||
); | ); | ||||
} | |||||
}; | |||||
const EditFooter = (props: EditFooterProps) => { | const EditFooter = (props: EditFooterProps) => { | ||||
return ( | return ( | ||||
<div style={{ display: 'flex', justifyContent: 'flex', width: '100%' }}> | |||||
<div style={{ display: "flex", justifyContent: "flex", width: "100%" }}> | |||||
<Box flex={1}> | <Box flex={1}> | ||||
<b>Total: </b> | <b>Total: </b> | ||||
</Box> | </Box> | ||||
<Box flex={2}>test</Box> | <Box flex={2}>test</Box> | ||||
</div> | </div> | ||||
); | ); | ||||
} | |||||
}; | |||||
interface ClaimInputGridProps { | interface ClaimInputGridProps { | ||||
onClose?: () => void; | onClose?: () => void; | ||||
@@ -144,30 +160,34 @@ const initialRows: GridRowsProp = [ | |||||
date: new Date(), | date: new Date(), | ||||
description: "Taxi to client office", | description: "Taxi to client office", | ||||
cost: 169.5, | cost: 169.5, | ||||
document: 'taxi_receipt.jpg', | |||||
document: "taxi_receipt.jpg", | |||||
}, | }, | ||||
{ | { | ||||
id: 2, | id: 2, | ||||
date: dayjs().add(-14, 'days').toDate(), | |||||
date: dayjs().add(-14, "days").toDate(), | |||||
description: "MTR fee to Kowloon Bay Office", | description: "MTR fee to Kowloon Bay Office", | ||||
cost: 15.5, | cost: 15.5, | ||||
document: 'octopus_invoice.jpg', | |||||
document: "octopus_invoice.jpg", | |||||
}, | }, | ||||
{ | { | ||||
id: 3, | id: 3, | ||||
date: dayjs().add(-44, 'days').toDate(), | |||||
date: dayjs().add(-44, "days").toDate(), | |||||
description: "Starbucks", | description: "Starbucks", | ||||
cost: 504, | cost: 504, | ||||
}, | }, | ||||
]; | ]; | ||||
const ClaimInputGrid: React.FC<ClaimInputGridProps> = ({ ...props }) => { | const ClaimInputGrid: React.FC<ClaimInputGridProps> = ({ ...props }) => { | ||||
const [rows, setRows] = useState(initialRows); | const [rows, setRows] = useState(initialRows); | ||||
const [day, setDay] = useState(dayjs()); | const [day, setDay] = useState(dayjs()); | ||||
const [rowModesModel, setRowModesModel] = React.useState<GridRowModesModel>({}); | |||||
const [rowModesModel, setRowModesModel] = React.useState<GridRowModesModel>( | |||||
{}, | |||||
); | |||||
const handleRowEditStop: GridEventListener<'rowEditStop'> = (params, event) => { | |||||
const handleRowEditStop: GridEventListener<"rowEditStop"> = ( | |||||
params, | |||||
event, | |||||
) => { | |||||
if (params.reason === GridRowEditStopReasons.rowFocusOut) { | if (params.reason === GridRowEditStopReasons.rowFocusOut) { | ||||
event.defaultMuiPrevented = true; | event.defaultMuiPrevented = true; | ||||
} | } | ||||
@@ -178,7 +198,6 @@ const ClaimInputGrid: React.FC<ClaimInputGridProps> = ({ ...props }) => { | |||||
}; | }; | ||||
const handleSaveClick = (id: GridRowId) => () => { | const handleSaveClick = (id: GridRowId) => () => { | ||||
setRowModesModel({ ...rowModesModel, [id]: { mode: GridRowModes.View } }); | setRowModesModel({ ...rowModesModel, [id]: { mode: GridRowModes.View } }); | ||||
}; | }; | ||||
@@ -211,21 +230,21 @@ const ClaimInputGrid: React.FC<ClaimInputGridProps> = ({ ...props }) => { | |||||
const getCostTotal = () => { | const getCostTotal = () => { | ||||
let sum = 0; | let sum = 0; | ||||
rows.forEach((row) => { | rows.forEach((row) => { | ||||
sum += row['cost']??0; | |||||
sum += row["cost"] ?? 0; | |||||
}); | }); | ||||
return sum; | return sum; | ||||
}; | }; | ||||
const commonGridColConfig : any = { | |||||
type: 'number', | |||||
const commonGridColConfig: any = { | |||||
type: "number", | |||||
// sortable: false, | // sortable: false, | ||||
//width: 100, | //width: 100, | ||||
flex: 1, | flex: 1, | ||||
align: 'left', | |||||
headerAlign: 'left', | |||||
align: "left", | |||||
headerAlign: "left", | |||||
// headerClassName: 'header', | // headerClassName: 'header', | ||||
editable: true, | editable: true, | ||||
renderEditCell: (value : any) => ( | |||||
renderEditCell: (value: any) => ( | |||||
<GridEditInputCell | <GridEditInputCell | ||||
{...value} | {...value} | ||||
inputProps={{ | inputProps={{ | ||||
@@ -239,26 +258,28 @@ const ClaimInputGrid: React.FC<ClaimInputGridProps> = ({ ...props }) => { | |||||
const columns: GridColDef[] = [ | const columns: GridColDef[] = [ | ||||
{ | { | ||||
field: 'actions', | |||||
type: 'actions', | |||||
headerName: 'Actions', | |||||
field: "actions", | |||||
type: "actions", | |||||
headerName: "Actions", | |||||
width: 100, | width: 100, | ||||
cellClassName: 'actions', | |||||
cellClassName: "actions", | |||||
getActions: ({ id }) => { | getActions: ({ id }) => { | ||||
const isInEditMode = rowModesModel[id]?.mode === GridRowModes.Edit; | const isInEditMode = rowModesModel[id]?.mode === GridRowModes.Edit; | ||||
if (isInEditMode) { | if (isInEditMode) { | ||||
return [ | return [ | ||||
<GridActionsCellItem | <GridActionsCellItem | ||||
key={`actions-${id}-save`} | |||||
icon={<SaveIcon />} | icon={<SaveIcon />} | ||||
title="Save" | title="Save" | ||||
label="Save" | label="Save" | ||||
sx={{ | sx={{ | ||||
color: 'primary.main', | |||||
color: "primary.main", | |||||
}} | }} | ||||
onClick={handleSaveClick(id)} | onClick={handleSaveClick(id)} | ||||
/>, | />, | ||||
<GridActionsCellItem | <GridActionsCellItem | ||||
key={`actions-${id}-cancel`} | |||||
icon={<CancelIcon />} | icon={<CancelIcon />} | ||||
title="Cancel" | title="Cancel" | ||||
label="Cancel" | label="Cancel" | ||||
@@ -271,6 +292,7 @@ const ClaimInputGrid: React.FC<ClaimInputGridProps> = ({ ...props }) => { | |||||
return [ | return [ | ||||
<GridActionsCellItem | <GridActionsCellItem | ||||
key={`actions-${id}-edit`} | |||||
icon={<EditIcon />} | icon={<EditIcon />} | ||||
title="Edit" | title="Edit" | ||||
label="Edit" | label="Edit" | ||||
@@ -279,74 +301,80 @@ const ClaimInputGrid: React.FC<ClaimInputGridProps> = ({ ...props }) => { | |||||
color="inherit" | color="inherit" | ||||
/>, | />, | ||||
<GridActionsCellItem | <GridActionsCellItem | ||||
key={`actions-${id}-delete`} | |||||
title="Delete" | title="Delete" | ||||
label="Delete" | label="Delete" | ||||
icon={<DeleteIcon />} | icon={<DeleteIcon />} | ||||
onClick={handleDeleteClick(id)} | onClick={handleDeleteClick(id)} | ||||
sx={{color:"red"}} | |||||
sx={{ color: "red" }} | |||||
/>, | />, | ||||
]; | ]; | ||||
}, | }, | ||||
}, | }, | ||||
{ | { | ||||
field: 'date', | |||||
headerName: 'Invoice Date', | |||||
field: "date", | |||||
headerName: "Invoice Date", | |||||
// width: 220, | // width: 220, | ||||
flex: 1, | flex: 1, | ||||
editable: true, | editable: true, | ||||
type: 'date', | |||||
type: "date", | |||||
}, | }, | ||||
{ | { | ||||
field: 'description', | |||||
headerName: 'Description', | |||||
field: "description", | |||||
headerName: "Description", | |||||
// width: 220, | // width: 220, | ||||
flex: 2, | flex: 2, | ||||
editable: true, | editable: true, | ||||
type: 'string', | |||||
type: "string", | |||||
}, | }, | ||||
{ | { | ||||
field: 'cost', | |||||
headerName: 'Cost (HKD)', | |||||
field: "cost", | |||||
headerName: "Cost (HKD)", | |||||
editable: true, | editable: true, | ||||
type: 'number', | |||||
type: "number", | |||||
valueFormatter: (params) => { | valueFormatter: (params) => { | ||||
return `$ ${params.value??0}`; | |||||
return `$ ${params.value ?? 0}`; | |||||
}, | }, | ||||
}, | }, | ||||
{ | { | ||||
field: 'document', | |||||
headerName: 'Supporting Document', | |||||
type: 'string', | |||||
field: "document", | |||||
headerName: "Supporting Document", | |||||
type: "string", | |||||
editable: true, | editable: true, | ||||
flex: 2, | flex: 2, | ||||
renderCell: (params) => { | renderCell: (params) => { | ||||
return params.value? | |||||
( | |||||
return params.value ? ( | |||||
<span> | <span> | ||||
<a href="" target="_blank" rel="noopener noreferrer"> | <a href="" target="_blank" rel="noopener noreferrer"> | ||||
{params.value} | {params.value} | ||||
</a> | </a> | ||||
</span> | </span> | ||||
) : | |||||
(<span style={{color: palette.text.disabled}}>No Documents</span>) | |||||
) : ( | |||||
<span style={{ color: palette.text.disabled }}>No Documents</span> | |||||
); | |||||
}, | }, | ||||
renderEditCell: (params) => { | renderEditCell: (params) => { | ||||
return params.value? | |||||
( | |||||
return params.value ? ( | |||||
<span> | <span> | ||||
<a href="" target="_blank" rel="noopener noreferrer"> | |||||
{params.value} | |||||
</a> | |||||
<Button title='Remove Document' onClick={(event) => console.log(event)}> | |||||
<ImageNotSupportedOutlinedIcon sx={{fontSize: '25px', color:"red"}}/> | |||||
</Button> | |||||
<a href="" target="_blank" rel="noopener noreferrer"> | |||||
{params.value} | |||||
</a> | |||||
<Button | |||||
title="Remove Document" | |||||
onClick={(event) => console.log(event)} | |||||
> | |||||
<ImageNotSupportedOutlinedIcon | |||||
sx={{ fontSize: "25px", color: "red" }} | |||||
/> | |||||
</Button> | |||||
</span> | </span> | ||||
) : ( | ) : ( | ||||
<Button title='Add Document'> | |||||
<AddPhotoAlternateOutlinedIcon sx={{fontSize: '25px', color:"green"}}/> | |||||
<Button title="Add Document"> | |||||
<AddPhotoAlternateOutlinedIcon | |||||
sx={{ fontSize: "25px", color: "green" }} | |||||
/> | |||||
</Button> | </Button> | ||||
) | |||||
); | |||||
}, | }, | ||||
}, | }, | ||||
]; | ]; | ||||
@@ -355,27 +383,27 @@ const ClaimInputGrid: React.FC<ClaimInputGridProps> = ({ ...props }) => { | |||||
<Box | <Box | ||||
sx={{ | sx={{ | ||||
// marginBottom: '-5px', | // marginBottom: '-5px', | ||||
display: 'flex', | |||||
'flex-direction': 'column', | |||||
display: "flex", | |||||
"flex-direction": "column", | |||||
// 'justify-content': 'flex-end', | // 'justify-content': 'flex-end', | ||||
height: '100%',//'25rem', | |||||
width: '100%', | |||||
'& .actions': { | |||||
color: 'text.secondary', | |||||
height: "100%", //'25rem', | |||||
width: "100%", | |||||
"& .actions": { | |||||
color: "text.secondary", | |||||
}, | }, | ||||
'& .header': { | |||||
"& .header": { | |||||
backgroundColor: "#F8F9FA", | backgroundColor: "#F8F9FA", | ||||
// border: 1, | // border: 1, | ||||
// 'border-width': '1px', | // 'border-width': '1px', | ||||
// 'border-color': 'grey', | // 'border-color': 'grey', | ||||
}, | }, | ||||
'& .textPrimary': { | |||||
color: 'text.primary', | |||||
"& .textPrimary": { | |||||
color: "text.primary", | |||||
}, | }, | ||||
}} | }} | ||||
> | > | ||||
<DataGrid | <DataGrid | ||||
sx={{flex:1}} | |||||
sx={{ flex: 1 }} | |||||
rows={rows} | rows={rows} | ||||
columns={columns} | columns={columns} | ||||
editMode="row" | editMode="row" | ||||
@@ -386,22 +414,29 @@ const ClaimInputGrid: React.FC<ClaimInputGridProps> = ({ ...props }) => { | |||||
disableRowSelectionOnClick={true} | disableRowSelectionOnClick={true} | ||||
disableColumnMenu={true} | disableColumnMenu={true} | ||||
hideFooterPagination={true} | hideFooterPagination={true} | ||||
slots={{ | |||||
// footer: EditFooter, | |||||
}} | |||||
slotProps={{ | |||||
// footer: { setDay, setRows, setRowModesModel }, | |||||
}} | |||||
slots={ | |||||
{ | |||||
// footer: EditFooter, | |||||
} | |||||
} | |||||
slotProps={ | |||||
{ | |||||
// footer: { setDay, setRows, setRowModesModel }, | |||||
} | |||||
} | |||||
initialState={{ | initialState={{ | ||||
pagination: { paginationModel: { pageSize: 100 } }, | pagination: { paginationModel: { pageSize: 100 } }, | ||||
}} | }} | ||||
/> | /> | ||||
<BottomBar getCostTotal={getCostTotal} setRows={setRows} setRowModesModel={setRowModesModel} | |||||
// sx={{flex:2}} | |||||
<BottomBar | |||||
getCostTotal={getCostTotal} | |||||
setRows={setRows} | |||||
setRowModesModel={setRowModesModel} | |||||
// sx={{flex:2}} | |||||
/> | /> | ||||
</Box> | </Box> | ||||
); | ); | ||||
} | |||||
}; | |||||
export default ClaimInputGrid; | export default ClaimInputGrid; |
@@ -1,11 +1,18 @@ | |||||
import * as React from 'react'; | |||||
import { Card, CardHeader, CardContent, SxProps, Theme, Grid } from '@mui/material'; | |||||
import { DataGrid, GridColDef } from '@mui/x-data-grid'; | |||||
import { darken, lighten, styled } from '@mui/material/styles'; | |||||
import { PROJECT_CARD_STYLE } from '@/theme/colorConst'; | |||||
import { useRef, useEffect, useState } from 'react'; | |||||
import Swal from 'sweetalert2'; | |||||
import styledcmp from 'styled-components'; | |||||
import * as React from "react"; | |||||
import { | |||||
Card, | |||||
CardHeader, | |||||
CardContent, | |||||
SxProps, | |||||
Theme, | |||||
Grid, | |||||
} from "@mui/material"; | |||||
import { DataGrid, GridColDef } from "@mui/x-data-grid"; | |||||
import { darken, lighten, styled } from "@mui/material/styles"; | |||||
import { PROJECT_CARD_STYLE } from "@/theme/colorConst"; | |||||
import { useRef, useEffect, useState } from "react"; | |||||
import Swal from "sweetalert2"; | |||||
import styledcmp from "styled-components"; | |||||
const CardWrapper = styledcmp.div` | const CardWrapper = styledcmp.div` | ||||
/* Styles for the card when not hovered */ | /* Styles for the card when not hovered */ | ||||
@@ -23,7 +30,7 @@ const CardWrapper = styledcmp.div` | |||||
interface CustomCardGridProps { | interface CustomCardGridProps { | ||||
Title?: string; | Title?: string; | ||||
cardsPerRow?: number; | cardsPerRow?: number; | ||||
rows?: any[]; | |||||
rows?: any[]; | |||||
columns?: any[]; | columns?: any[]; | ||||
items: any[]; | items: any[]; | ||||
columnWidth?: number; | columnWidth?: number; | ||||
@@ -46,73 +53,124 @@ const CustomCardGrid: React.FC<CustomCardGridProps> = ({ | |||||
dataGridHeight, | dataGridHeight, | ||||
...props | ...props | ||||
}) => { | }) => { | ||||
const getBackgroundColor = (color: string, mode: 'light' | 'dark') => | |||||
mode === 'dark' ? darken(color, 0.7) : lighten(color, 0.7); | |||||
const getBackgroundColor = (color: string, mode: "light" | "dark") => | |||||
mode === "dark" ? darken(color, 0.7) : lighten(color, 0.7); | |||||
const getHoverBackgroundColor = (color: string, mode: 'light' | 'dark') => | |||||
mode === 'dark' ? darken(color, 0.6) : lighten(color, 0.6); | |||||
const getHoverBackgroundColor = (color: string, mode: "light" | "dark") => | |||||
mode === "dark" ? darken(color, 0.6) : lighten(color, 0.6); | |||||
const getSelectedBackgroundColor = (color: string, mode: 'light' | 'dark') => | |||||
mode === 'dark' ? darken(color, 0.5) : lighten(color, 0.5); | |||||
const getSelectedBackgroundColor = (color: string, mode: "light" | "dark") => | |||||
mode === "dark" ? darken(color, 0.5) : lighten(color, 0.5); | |||||
const getSelectedHoverBackgroundColor = (color: string, mode: 'light' | 'dark') => | |||||
mode === 'dark' ? darken(color, 0.4) : lighten(color, 0.4); | |||||
const getSelectedHoverBackgroundColor = ( | |||||
color: string, | |||||
mode: "light" | "dark", | |||||
) => (mode === "dark" ? darken(color, 0.4) : lighten(color, 0.4)); | |||||
const StyledCard = styled(Card)(({ theme }) => ({ | const StyledCard = styled(Card)(({ theme }) => ({ | ||||
'& .super-app-theme--Open': { | |||||
backgroundColor: getBackgroundColor(theme.palette.info.main, theme.palette.mode), | |||||
'&:hover': { | |||||
backgroundColor: getHoverBackgroundColor(theme.palette.info.main, theme.palette.mode) | |||||
"& .super-app-theme--Open": { | |||||
backgroundColor: getBackgroundColor( | |||||
theme.palette.info.main, | |||||
theme.palette.mode, | |||||
), | |||||
"&:hover": { | |||||
backgroundColor: getHoverBackgroundColor( | |||||
theme.palette.info.main, | |||||
theme.palette.mode, | |||||
), | |||||
}, | |||||
"&.Mui-selected": { | |||||
backgroundColor: getSelectedBackgroundColor( | |||||
theme.palette.info.main, | |||||
theme.palette.mode, | |||||
), | |||||
"&:hover": { | |||||
backgroundColor: getSelectedHoverBackgroundColor( | |||||
theme.palette.info.main, | |||||
theme.palette.mode, | |||||
), | |||||
}, | |||||
}, | }, | ||||
'&.Mui-selected': { | |||||
backgroundColor: getSelectedBackgroundColor(theme.palette.info.main, theme.palette.mode), | |||||
'&:hover': { | |||||
backgroundColor: getSelectedHoverBackgroundColor(theme.palette.info.main, theme.palette.mode) | |||||
} | |||||
} | |||||
}, | }, | ||||
'& .super-app-theme--finish': { | |||||
backgroundColor: getBackgroundColor(theme.palette.success.main, theme.palette.mode), | |||||
'&:hover': { | |||||
backgroundColor: getHoverBackgroundColor(theme.palette.success.main, theme.palette.mode) | |||||
"& .super-app-theme--finish": { | |||||
backgroundColor: getBackgroundColor( | |||||
theme.palette.success.main, | |||||
theme.palette.mode, | |||||
), | |||||
"&:hover": { | |||||
backgroundColor: getHoverBackgroundColor( | |||||
theme.palette.success.main, | |||||
theme.palette.mode, | |||||
), | |||||
}, | |||||
"&.Mui-selected": { | |||||
backgroundColor: getSelectedBackgroundColor( | |||||
theme.palette.success.main, | |||||
theme.palette.mode, | |||||
), | |||||
"&:hover": { | |||||
backgroundColor: getSelectedHoverBackgroundColor( | |||||
theme.palette.success.main, | |||||
theme.palette.mode, | |||||
), | |||||
}, | |||||
}, | }, | ||||
'&.Mui-selected': { | |||||
backgroundColor: getSelectedBackgroundColor(theme.palette.success.main, theme.palette.mode), | |||||
'&:hover': { | |||||
backgroundColor: getSelectedHoverBackgroundColor(theme.palette.success.main, theme.palette.mode) | |||||
} | |||||
} | |||||
}, | }, | ||||
'& .super-app-theme--danger': { | |||||
backgroundColor: getBackgroundColor(theme.palette.warning.main, theme.palette.mode), | |||||
'&:hover': { | |||||
backgroundColor: getHoverBackgroundColor(theme.palette.warning.main, theme.palette.mode) | |||||
"& .super-app-theme--danger": { | |||||
backgroundColor: getBackgroundColor( | |||||
theme.palette.warning.main, | |||||
theme.palette.mode, | |||||
), | |||||
"&:hover": { | |||||
backgroundColor: getHoverBackgroundColor( | |||||
theme.palette.warning.main, | |||||
theme.palette.mode, | |||||
), | |||||
}, | |||||
"&.Mui-selected": { | |||||
backgroundColor: getSelectedBackgroundColor( | |||||
theme.palette.warning.main, | |||||
theme.palette.mode, | |||||
), | |||||
"&:hover": { | |||||
backgroundColor: getSelectedHoverBackgroundColor( | |||||
theme.palette.warning.main, | |||||
theme.palette.mode, | |||||
), | |||||
}, | |||||
}, | }, | ||||
'&.Mui-selected': { | |||||
backgroundColor: getSelectedBackgroundColor(theme.palette.warning.main, theme.palette.mode), | |||||
'&:hover': { | |||||
backgroundColor: getSelectedHoverBackgroundColor(theme.palette.warning.main, theme.palette.mode) | |||||
} | |||||
} | |||||
}, | }, | ||||
'& .super-app-theme--warning': { | |||||
backgroundColor: getBackgroundColor(theme.palette.error.main, theme.palette.mode), | |||||
'&:hover': { | |||||
backgroundColor: getHoverBackgroundColor(theme.palette.error.main, theme.palette.mode) | |||||
"& .super-app-theme--warning": { | |||||
backgroundColor: getBackgroundColor( | |||||
theme.palette.error.main, | |||||
theme.palette.mode, | |||||
), | |||||
"&:hover": { | |||||
backgroundColor: getHoverBackgroundColor( | |||||
theme.palette.error.main, | |||||
theme.palette.mode, | |||||
), | |||||
}, | }, | ||||
'&.Mui-selected': { | |||||
backgroundColor: getSelectedBackgroundColor(theme.palette.error.main, theme.palette.mode), | |||||
'&:hover': { | |||||
backgroundColor: getSelectedHoverBackgroundColor(theme.palette.error.main, theme.palette.mode) | |||||
} | |||||
} | |||||
} | |||||
"&.Mui-selected": { | |||||
backgroundColor: getSelectedBackgroundColor( | |||||
theme.palette.error.main, | |||||
theme.palette.mode, | |||||
), | |||||
"&:hover": { | |||||
backgroundColor: getSelectedHoverBackgroundColor( | |||||
theme.palette.error.main, | |||||
theme.palette.mode, | |||||
), | |||||
}, | |||||
}, | |||||
}, | |||||
})); | })); | ||||
const CardItem = (item: any) => { | const CardItem = (item: any) => { | ||||
const cardItem = item.item as Record<string, string>; | const cardItem = item.item as Record<string, string>; | ||||
return props.cardStyle?? ( | |||||
// <Grid item sx={{ m: 3 }}> | |||||
return ( | |||||
props.cardStyle ?? ( | |||||
// <Grid item sx={{ m: 3 }}> | |||||
<StyledCard style={PROJECT_CARD_STYLE}> | <StyledCard style={PROJECT_CARD_STYLE}> | ||||
<CardContent> | <CardContent> | ||||
{Object.keys(cardItem).map((key) => ( | {Object.keys(cardItem).map((key) => ( | ||||
@@ -122,28 +180,36 @@ const CustomCardGrid: React.FC<CustomCardGridProps> = ({ | |||||
))} | ))} | ||||
</CardContent> | </CardContent> | ||||
</StyledCard> | </StyledCard> | ||||
// </Grid> | |||||
// </Grid> | |||||
) | |||||
); | ); | ||||
}; | }; | ||||
const containerRef = useRef<HTMLDivElement>(null!); | const containerRef = useRef<HTMLDivElement>(null!); | ||||
const [cardMargin, setCardMargin] = useState(1.5); | const [cardMargin, setCardMargin] = useState(1.5); | ||||
useEffect(() => { | useEffect(() => { | ||||
console.log(CardItem); | console.log(CardItem); | ||||
const resizeHandler = () => { | const resizeHandler = () => { | ||||
const containerWidth = containerRef.current.offsetWidth; | const containerWidth = containerRef.current.offsetWidth; | ||||
const cardCount = items.length; | const cardCount = items.length; | ||||
const rootSize = parseFloat(getComputedStyle(document.documentElement).fontSize); | |||||
setCardMargin((containerWidth - cardsPerRow * (rootSize * parseInt(PROJECT_CARD_STYLE.width.slice(0, -3),10))) /(2 * cardsPerRow)); | |||||
const rootSize = parseFloat( | |||||
getComputedStyle(document.documentElement).fontSize, | |||||
); | |||||
setCardMargin( | |||||
(containerWidth - | |||||
cardsPerRow * | |||||
(rootSize * parseInt(PROJECT_CARD_STYLE.width.slice(0, -3), 10))) / | |||||
(2 * cardsPerRow), | |||||
); | |||||
// Set the cardMargin value using style={{margin: `${cardMargin}px`, ...PROJECT_CARD_STYLE}} | // Set the cardMargin value using style={{margin: `${cardMargin}px`, ...PROJECT_CARD_STYLE}} | ||||
}; | }; | ||||
window.addEventListener('resize', resizeHandler); | |||||
window.addEventListener("resize", resizeHandler); | |||||
resizeHandler(); // Initial calculation | resizeHandler(); // Initial calculation | ||||
// Swal.fire({ | // Swal.fire({ | ||||
// title: 'Error! ', | // title: 'Error! ', | ||||
// text: `Card Count is ${items.length}`, | // text: `Card Count is ${items.length}`, | ||||
@@ -152,16 +218,19 @@ const CustomCardGrid: React.FC<CustomCardGridProps> = ({ | |||||
// }) | // }) | ||||
return () => { | return () => { | ||||
window.removeEventListener('resize', resizeHandler); | |||||
window.removeEventListener("resize", resizeHandler); | |||||
}; | }; | ||||
}, [items]); | }, [items]); | ||||
return ( | return ( | ||||
<div ref={containerRef} style={{display:'flex', flexWrap:'wrap', alignItems: 'flex-start'}}> | |||||
<div | |||||
ref={containerRef} | |||||
style={{ display: "flex", flexWrap: "wrap", alignItems: "flex-start" }} | |||||
> | |||||
{/* <p>width is {containerRef.current == null? "idk":containerRef.current.offsetWidth}, margin is {cardMargin}</p> */} | {/* <p>width is {containerRef.current == null? "idk":containerRef.current.offsetWidth}, margin is {cardMargin}</p> */} | ||||
{items.map((item, index) => ( | {items.map((item, index) => ( | ||||
<div key={index}> | <div key={index}> | ||||
{props.cardStyle? props.cardStyle(item) : <CardItem item={item}/>} | |||||
{props.cardStyle ? props.cardStyle(item) : <CardItem item={item} />} | |||||
</div> | </div> | ||||
))} | ))} | ||||
</div> | </div> | ||||
@@ -1,13 +1,13 @@ | |||||
"use client"; | "use client"; | ||||
import * as React from 'react'; | |||||
import { Card, CardHeader, CardContent, SxProps, Theme } from '@mui/material'; | |||||
import { DataGrid, GridColDef, GridRowSelectionModel} from '@mui/x-data-grid'; | |||||
import { darken, lighten, styled } from '@mui/material/styles'; | |||||
import { useState } from 'react' | |||||
import * as React from "react"; | |||||
import { Card, CardHeader, CardContent, SxProps, Theme } from "@mui/material"; | |||||
import { DataGrid, GridColDef, GridRowSelectionModel } from "@mui/x-data-grid"; | |||||
import { darken, lighten, styled } from "@mui/material/styles"; | |||||
import { useState } from "react"; | |||||
interface CustomDatagridProps { | interface CustomDatagridProps { | ||||
Title?: string; | Title?: string; | ||||
rows: any[]; | |||||
rows: any[]; | |||||
columns: any[]; | columns: any[]; | ||||
columnWidth?: number; | columnWidth?: number; | ||||
Style?: boolean; | Style?: boolean; | ||||
@@ -15,7 +15,9 @@ interface CustomDatagridProps { | |||||
dataGridHeight?: number; | dataGridHeight?: number; | ||||
[key: string]: any; | [key: string]: any; | ||||
checkboxSelection?: boolean; | checkboxSelection?: boolean; | ||||
onRowSelectionModelChange?: (newSelectionModel: GridRowSelectionModel) => void; | |||||
onRowSelectionModelChange?: ( | |||||
newSelectionModel: GridRowSelectionModel, | |||||
) => void; | |||||
selectionModel?: any; | selectionModel?: any; | ||||
} | } | ||||
@@ -44,200 +46,262 @@ const CustomDatagrid: React.FC<CustomDatagridProps> = ({ | |||||
}); | }); | ||||
// Event handler to be called when the selection changes | // Event handler to be called when the selection changes | ||||
const handleSelectionModelChange = (newSelectionModel: GridRowSelectionModel) => { | |||||
const handleSelectionModelChange = ( | |||||
newSelectionModel: GridRowSelectionModel, | |||||
) => { | |||||
// setSelectionModel(newSelectionModel); | // setSelectionModel(newSelectionModel); | ||||
// To log selected row data, filter rows based on the new selection model | // To log selected row data, filter rows based on the new selection model | ||||
const selectedRowsData = rows.filter((row) => | const selectedRowsData = rows.filter((row) => | ||||
newSelectionModel.includes(row.id) | |||||
newSelectionModel.includes(row.id), | |||||
); | ); | ||||
console.log(selectedRowsData); | console.log(selectedRowsData); | ||||
}; | }; | ||||
const getBackgroundColor = (color: string, mode: 'light' | 'dark') => | |||||
mode === 'dark' ? darken(color, 0.7) : lighten(color, 0.7); | |||||
const getBackgroundColor = (color: string, mode: "light" | "dark") => | |||||
mode === "dark" ? darken(color, 0.7) : lighten(color, 0.7); | |||||
const getHoverBackgroundColor = (color: string, mode: 'light' | 'dark') => | |||||
mode === 'dark' ? darken(color, 0.6) : lighten(color, 0.6); | |||||
const getHoverBackgroundColor = (color: string, mode: "light" | "dark") => | |||||
mode === "dark" ? darken(color, 0.6) : lighten(color, 0.6); | |||||
const getSelectedBackgroundColor = (color: string, mode: 'light' | 'dark') => | |||||
mode === 'dark' ? darken(color, 0.5) : lighten(color, 0.5); | |||||
const getSelectedBackgroundColor = (color: string, mode: "light" | "dark") => | |||||
mode === "dark" ? darken(color, 0.5) : lighten(color, 0.5); | |||||
const getSelectedHoverBackgroundColor = (color: string, mode: 'light' | 'dark') => | |||||
mode === 'dark' ? darken(color, 0.4) : lighten(color, 0.4); | |||||
const getSelectedHoverBackgroundColor = ( | |||||
color: string, | |||||
mode: "light" | "dark", | |||||
) => (mode === "dark" ? darken(color, 0.4) : lighten(color, 0.4)); | |||||
const StyledDataGrid = styled(DataGrid)(({ theme }) => ({ | const StyledDataGrid = styled(DataGrid)(({ theme }) => ({ | ||||
'& .super-app-theme--Open': { | |||||
backgroundColor: getBackgroundColor(theme.palette.info.main, theme.palette.mode), | |||||
'&:hover': { | |||||
backgroundColor: getHoverBackgroundColor(theme.palette.info.main, theme.palette.mode) | |||||
"& .super-app-theme--Open": { | |||||
backgroundColor: getBackgroundColor( | |||||
theme.palette.info.main, | |||||
theme.palette.mode, | |||||
), | |||||
"&:hover": { | |||||
backgroundColor: getHoverBackgroundColor( | |||||
theme.palette.info.main, | |||||
theme.palette.mode, | |||||
), | |||||
}, | |||||
"&.Mui-selected": { | |||||
backgroundColor: getSelectedBackgroundColor( | |||||
theme.palette.info.main, | |||||
theme.palette.mode, | |||||
), | |||||
"&:hover": { | |||||
backgroundColor: getSelectedHoverBackgroundColor( | |||||
theme.palette.info.main, | |||||
theme.palette.mode, | |||||
), | |||||
}, | |||||
}, | }, | ||||
'&.Mui-selected': { | |||||
backgroundColor: getSelectedBackgroundColor(theme.palette.info.main, theme.palette.mode), | |||||
'&:hover': { | |||||
backgroundColor: getSelectedHoverBackgroundColor(theme.palette.info.main, theme.palette.mode) | |||||
} | |||||
} | |||||
}, | }, | ||||
'& .super-app-theme--finish': { | |||||
backgroundColor: getBackgroundColor(theme.palette.success.main, theme.palette.mode), | |||||
'&:hover': { | |||||
backgroundColor: getHoverBackgroundColor(theme.palette.success.main, theme.palette.mode) | |||||
"& .super-app-theme--finish": { | |||||
backgroundColor: getBackgroundColor( | |||||
theme.palette.success.main, | |||||
theme.palette.mode, | |||||
), | |||||
"&:hover": { | |||||
backgroundColor: getHoverBackgroundColor( | |||||
theme.palette.success.main, | |||||
theme.palette.mode, | |||||
), | |||||
}, | |||||
"&.Mui-selected": { | |||||
backgroundColor: getSelectedBackgroundColor( | |||||
theme.palette.success.main, | |||||
theme.palette.mode, | |||||
), | |||||
"&:hover": { | |||||
backgroundColor: getSelectedHoverBackgroundColor( | |||||
theme.palette.success.main, | |||||
theme.palette.mode, | |||||
), | |||||
}, | |||||
}, | }, | ||||
'&.Mui-selected': { | |||||
backgroundColor: getSelectedBackgroundColor(theme.palette.success.main, theme.palette.mode), | |||||
'&:hover': { | |||||
backgroundColor: getSelectedHoverBackgroundColor(theme.palette.success.main, theme.palette.mode) | |||||
} | |||||
} | |||||
}, | }, | ||||
'& .super-app-theme--danger': { | |||||
backgroundColor: getBackgroundColor(theme.palette.warning.main, theme.palette.mode), | |||||
'&:hover': { | |||||
backgroundColor: getHoverBackgroundColor(theme.palette.warning.main, theme.palette.mode) | |||||
"& .super-app-theme--danger": { | |||||
backgroundColor: getBackgroundColor( | |||||
theme.palette.warning.main, | |||||
theme.palette.mode, | |||||
), | |||||
"&:hover": { | |||||
backgroundColor: getHoverBackgroundColor( | |||||
theme.palette.warning.main, | |||||
theme.palette.mode, | |||||
), | |||||
}, | |||||
"&.Mui-selected": { | |||||
backgroundColor: getSelectedBackgroundColor( | |||||
theme.palette.warning.main, | |||||
theme.palette.mode, | |||||
), | |||||
"&:hover": { | |||||
backgroundColor: getSelectedHoverBackgroundColor( | |||||
theme.palette.warning.main, | |||||
theme.palette.mode, | |||||
), | |||||
}, | |||||
}, | }, | ||||
'&.Mui-selected': { | |||||
backgroundColor: getSelectedBackgroundColor(theme.palette.warning.main, theme.palette.mode), | |||||
'&:hover': { | |||||
backgroundColor: getSelectedHoverBackgroundColor(theme.palette.warning.main, theme.palette.mode) | |||||
} | |||||
} | |||||
}, | }, | ||||
'& .super-app-theme--warning': { | |||||
backgroundColor: getBackgroundColor(theme.palette.error.main, theme.palette.mode), | |||||
'&:hover': { | |||||
backgroundColor: getHoverBackgroundColor(theme.palette.error.main, theme.palette.mode) | |||||
"& .super-app-theme--warning": { | |||||
backgroundColor: getBackgroundColor( | |||||
theme.palette.error.main, | |||||
theme.palette.mode, | |||||
), | |||||
"&:hover": { | |||||
backgroundColor: getHoverBackgroundColor( | |||||
theme.palette.error.main, | |||||
theme.palette.mode, | |||||
), | |||||
}, | }, | ||||
'&.Mui-selected': { | |||||
backgroundColor: getSelectedBackgroundColor(theme.palette.error.main, theme.palette.mode), | |||||
'&:hover': { | |||||
backgroundColor: getSelectedHoverBackgroundColor(theme.palette.error.main, theme.palette.mode) | |||||
} | |||||
} | |||||
} | |||||
"&.Mui-selected": { | |||||
backgroundColor: getSelectedBackgroundColor( | |||||
theme.palette.error.main, | |||||
theme.palette.mode, | |||||
), | |||||
"&:hover": { | |||||
backgroundColor: getSelectedHoverBackgroundColor( | |||||
theme.palette.error.main, | |||||
theme.palette.mode, | |||||
), | |||||
}, | |||||
}, | |||||
}, | |||||
})); | })); | ||||
return ( | return ( | ||||
<div className="mt-5 mb-5" style={{ height: dataGridHeight ?? 400, width: '100%'}}> | |||||
<div | |||||
className="mt-5 mb-5" | |||||
style={{ height: dataGridHeight ?? 400, width: "100%" }} | |||||
> | |||||
{Title ? ( | {Title ? ( | ||||
<Card style={{marginRight:10}}> | |||||
{Title && <CardHeader className="text-slate-500" title={Title} />} | |||||
<CardContent style={{ display: "flex", alignItems: "center", justifyContent: "center", marginTop:-20 }}> | |||||
{Style ? ( | |||||
<StyledDataGrid | |||||
rows={rowsWithDefaultValues} | |||||
columns={modifiedColumns} | |||||
editMode="row" | |||||
checkboxSelection={checkboxSelection} | |||||
onRowSelectionModelChange={onRowSelectionModelChange} | |||||
initialState={{ | |||||
pagination: { paginationModel: { pageSize: 10 } }, | |||||
}} | |||||
className="customDataGrid" | |||||
sx={{ | |||||
boxShadow: 1, | |||||
border: 0, | |||||
borderColor: 'primary.light', | |||||
'& .MuiDataGrid-cell:hover': { | |||||
color: 'primary.main' | |||||
}, | |||||
height: dataGridHeight ?? 400, | |||||
'& .MuiDataGrid-root': { | |||||
overflow: 'auto', | |||||
}, | |||||
'& .MuiDataGrid-columnHeaderTitle': { | |||||
fontWeight: 'bold', | |||||
}, | |||||
...sx | |||||
}} | |||||
{...props} | |||||
/> | |||||
) : ( | |||||
<DataGrid | |||||
rows={rowsWithDefaultValues} | |||||
columns={modifiedColumns} | |||||
editMode="row" | |||||
checkboxSelection={checkboxSelection} | |||||
onRowSelectionModelChange={onRowSelectionModelChange} | |||||
initialState={{ | |||||
pagination: { paginationModel: { pageSize: 10 } }, | |||||
}} | |||||
className="customDataGrid" | |||||
sx={{ | |||||
boxShadow: 2, | |||||
border: 2, | |||||
borderColor: 'primary.light', | |||||
'& .MuiDataGrid-cell:hover': { | |||||
color: 'primary.main' | |||||
}, | |||||
height: 300, | |||||
'& .MuiDataGrid-root': { | |||||
overflow: 'auto', | |||||
}, | |||||
...sx | |||||
}} | |||||
{...props} | |||||
/> | |||||
)} | |||||
<Card style={{ marginRight: 10 }}> | |||||
{Title && <CardHeader className="text-slate-500" title={Title} />} | |||||
<CardContent | |||||
style={{ | |||||
display: "flex", | |||||
alignItems: "center", | |||||
justifyContent: "center", | |||||
marginTop: -20, | |||||
}} | |||||
> | |||||
{Style ? ( | |||||
<StyledDataGrid | |||||
rows={rowsWithDefaultValues} | |||||
columns={modifiedColumns} | |||||
editMode="row" | |||||
checkboxSelection={checkboxSelection} | |||||
onRowSelectionModelChange={onRowSelectionModelChange} | |||||
initialState={{ | |||||
pagination: { paginationModel: { pageSize: 10 } }, | |||||
}} | |||||
className="customDataGrid" | |||||
sx={{ | |||||
boxShadow: 1, | |||||
border: 0, | |||||
borderColor: "primary.light", | |||||
"& .MuiDataGrid-cell:hover": { | |||||
color: "primary.main", | |||||
}, | |||||
height: dataGridHeight ?? 400, | |||||
"& .MuiDataGrid-root": { | |||||
overflow: "auto", | |||||
}, | |||||
"& .MuiDataGrid-columnHeaderTitle": { | |||||
fontWeight: "bold", | |||||
}, | |||||
...sx, | |||||
}} | |||||
{...props} | |||||
/> | |||||
) : ( | |||||
<DataGrid | |||||
rows={rowsWithDefaultValues} | |||||
columns={modifiedColumns} | |||||
editMode="row" | |||||
checkboxSelection={checkboxSelection} | |||||
onRowSelectionModelChange={onRowSelectionModelChange} | |||||
initialState={{ | |||||
pagination: { paginationModel: { pageSize: 10 } }, | |||||
}} | |||||
className="customDataGrid" | |||||
sx={{ | |||||
boxShadow: 2, | |||||
border: 2, | |||||
borderColor: "primary.light", | |||||
"& .MuiDataGrid-cell:hover": { | |||||
color: "primary.main", | |||||
}, | |||||
height: 300, | |||||
"& .MuiDataGrid-root": { | |||||
overflow: "auto", | |||||
}, | |||||
...sx, | |||||
}} | |||||
{...props} | |||||
/> | |||||
)} | |||||
</CardContent> | </CardContent> | ||||
</Card>) | |||||
: (Style ? ( | |||||
<StyledDataGrid | |||||
rows={rowsWithDefaultValues} | |||||
columns={modifiedColumns} | |||||
editMode="row" | |||||
checkboxSelection={checkboxSelection} | |||||
onRowSelectionModelChange={onRowSelectionModelChange} | |||||
style={{marginRight:20}} | |||||
initialState={{ | |||||
pagination: { paginationModel: { pageSize: 10 } }, | |||||
}} | |||||
className="customDataGrid" | |||||
sx={{ | |||||
boxShadow: 1, | |||||
border: 0, | |||||
borderColor: 'primary.light', | |||||
'& .MuiDataGrid-cell:hover': { | |||||
color: 'primary.main' | |||||
}, | |||||
height: dataGridHeight ?? 400, | |||||
'& .MuiDataGrid-root': { | |||||
overflow: 'auto', | |||||
}, | |||||
'& .MuiDataGrid-columnHeaderTitle': { | |||||
fontWeight: 'bold', | |||||
}, | |||||
...sx | |||||
}} | |||||
{...props} | |||||
/> | |||||
) : ( | |||||
<DataGrid | |||||
rows={rowsWithDefaultValues} | |||||
columns={modifiedColumns} | |||||
editMode="row" | |||||
style={{marginRight:0}} | |||||
checkboxSelection={checkboxSelection} | |||||
onRowSelectionModelChange={onRowSelectionModelChange} | |||||
initialState={{ | |||||
pagination: { paginationModel: { pageSize: 10 } }, | |||||
}} | |||||
className="customDataGrid" | |||||
sx={{ | |||||
boxShadow: 2, | |||||
border: 2, | |||||
borderColor: 'primary.light', | |||||
'& .MuiDataGrid-cell:hover': { | |||||
color: 'primary.main' | |||||
}, | |||||
height: 300, | |||||
'& .MuiDataGrid-root': { | |||||
overflow: 'auto', | |||||
}, | |||||
...sx | |||||
}} | |||||
{...props} | |||||
/> | |||||
))} | |||||
</Card> | |||||
) : Style ? ( | |||||
<StyledDataGrid | |||||
rows={rowsWithDefaultValues} | |||||
columns={modifiedColumns} | |||||
editMode="row" | |||||
checkboxSelection={checkboxSelection} | |||||
onRowSelectionModelChange={onRowSelectionModelChange} | |||||
style={{ marginRight: 20 }} | |||||
initialState={{ | |||||
pagination: { paginationModel: { pageSize: 10 } }, | |||||
}} | |||||
className="customDataGrid" | |||||
sx={{ | |||||
boxShadow: 1, | |||||
border: 0, | |||||
borderColor: "primary.light", | |||||
"& .MuiDataGrid-cell:hover": { | |||||
color: "primary.main", | |||||
}, | |||||
height: dataGridHeight ?? 400, | |||||
"& .MuiDataGrid-root": { | |||||
overflow: "auto", | |||||
}, | |||||
"& .MuiDataGrid-columnHeaderTitle": { | |||||
fontWeight: "bold", | |||||
}, | |||||
...sx, | |||||
}} | |||||
{...props} | |||||
/> | |||||
) : ( | |||||
<DataGrid | |||||
rows={rowsWithDefaultValues} | |||||
columns={modifiedColumns} | |||||
editMode="row" | |||||
style={{ marginRight: 0 }} | |||||
checkboxSelection={checkboxSelection} | |||||
onRowSelectionModelChange={onRowSelectionModelChange} | |||||
initialState={{ | |||||
pagination: { paginationModel: { pageSize: 10 } }, | |||||
}} | |||||
className="customDataGrid" | |||||
sx={{ | |||||
boxShadow: 2, | |||||
border: 2, | |||||
borderColor: "primary.light", | |||||
"& .MuiDataGrid-cell:hover": { | |||||
color: "primary.main", | |||||
}, | |||||
height: 300, | |||||
"& .MuiDataGrid-root": { | |||||
overflow: "auto", | |||||
}, | |||||
...sx, | |||||
}} | |||||
{...props} | |||||
/> | |||||
)} | |||||
</div> | </div> | ||||
); | ); | ||||
}; | }; | ||||
@@ -1,11 +1,21 @@ | |||||
import * as React from 'react'; | |||||
import { Card, CardHeader, CardContent, SxProps, Theme, Grid, Modal, Typography, Button } from '@mui/material'; | |||||
import { DataGrid, GridColDef } from '@mui/x-data-grid'; | |||||
import { darken, lighten, styled } from '@mui/material/styles'; | |||||
import { PROJECT_MODAL_STYLE } from '@/theme/colorConst'; | |||||
import { useRef, useEffect, useState } from 'react'; | |||||
import Swal from 'sweetalert2'; | |||||
import styledcmp from 'styled-components'; | |||||
import * as React from "react"; | |||||
import { | |||||
Card, | |||||
CardHeader, | |||||
CardContent, | |||||
SxProps, | |||||
Theme, | |||||
Grid, | |||||
Modal, | |||||
Typography, | |||||
Button, | |||||
} from "@mui/material"; | |||||
import { DataGrid, GridColDef } from "@mui/x-data-grid"; | |||||
import { darken, lighten, styled } from "@mui/material/styles"; | |||||
import { PROJECT_MODAL_STYLE } from "@/theme/colorConst"; | |||||
import { useRef, useEffect, useState } from "react"; | |||||
import Swal from "sweetalert2"; | |||||
import styledcmp from "styled-components"; | |||||
const CardWrapper = styledcmp.div` | const CardWrapper = styledcmp.div` | ||||
/* Styles for the card when not hovered */ | /* Styles for the card when not hovered */ | ||||
@@ -28,35 +38,44 @@ interface CustomModalProps { | |||||
} | } | ||||
const CustomModal: React.FC<CustomModalProps> = ({ ...props }) => { | const CustomModal: React.FC<CustomModalProps> = ({ ...props }) => { | ||||
const ModalContent = () => { | const ModalContent = () => { | ||||
return ( | return ( | ||||
// <Grid item sx={{ m: 3 }}> | // <Grid item sx={{ m: 3 }}> | ||||
<div > | |||||
<Typography variant="h6" id="modal-title"> | |||||
{props.title??"Modal Title"} | |||||
</Typography> | |||||
<Typography variant="h6" id="modal-title" style={{ alignSelf: 'flex-start', margin: '10px' }}> | |||||
Modal Content | |||||
</Typography> | |||||
<div style={{ display: 'flex', justifyContent: 'space-between', width: '100%' }}> | |||||
<Button variant="contained" onClick={props.onClose}> | |||||
Confirm | |||||
</Button> | |||||
<Button variant="contained" onClick={props.onClose}> | |||||
Cancel | |||||
</Button> | |||||
</div> | |||||
<div> | |||||
<Typography variant="h6" id="modal-title"> | |||||
{props.title ?? "Modal Title"} | |||||
</Typography> | |||||
<Typography | |||||
variant="h6" | |||||
id="modal-title" | |||||
style={{ alignSelf: "flex-start", margin: "10px" }} | |||||
> | |||||
Modal Content | |||||
</Typography> | |||||
<div | |||||
style={{ | |||||
display: "flex", | |||||
justifyContent: "space-between", | |||||
width: "100%", | |||||
}} | |||||
> | |||||
<Button variant="contained" onClick={props.onClose}> | |||||
Confirm | |||||
</Button> | |||||
<Button variant="contained" onClick={props.onClose}> | |||||
Cancel | |||||
</Button> | |||||
</div> | </div> | ||||
</div> | |||||
// </Grid> | // </Grid> | ||||
); | ); | ||||
}; | }; | ||||
return ( | return ( | ||||
<Modal open={props.isOpen} onClose={props.onClose}> | <Modal open={props.isOpen} onClose={props.onClose}> | ||||
{props.modalStyle? <props.modalStyle props={props}/> : <ModalContent/>} | |||||
{props.modalStyle ? <props.modalStyle props={props} /> : <ModalContent />} | |||||
</Modal> | </Modal> | ||||
); | ); | ||||
}; | }; | ||||
export default CustomModal; | |||||
export default CustomModal; |
@@ -1,5 +1,5 @@ | |||||
"use client"; | "use client"; | ||||
import React, { useState, FC } from 'react'; | |||||
import React, { useState, FC } from "react"; | |||||
import { | import { | ||||
Stack, | Stack, | ||||
Typography, | Typography, | ||||
@@ -15,16 +15,16 @@ import { | |||||
InputLabel, | InputLabel, | ||||
Select, | Select, | ||||
MenuItem, | MenuItem, | ||||
ThemeProvider | |||||
} from '@mui/material'; | |||||
import { useForm, Controller } from 'react-hook-form'; | |||||
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; | |||||
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; | |||||
import dayjs from 'dayjs'; | |||||
import SearchIcon from '@mui/icons-material/Search'; | |||||
import RefreshIcon from '@mui/icons-material/Refresh'; | |||||
import { DemoItem } from '@mui/x-date-pickers/internals/demo'; | |||||
import { DatePicker } from '@mui/x-date-pickers/DatePicker'; | |||||
ThemeProvider, | |||||
} from "@mui/material"; | |||||
import { useForm, Controller } from "react-hook-form"; | |||||
import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider"; | |||||
import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs"; | |||||
import dayjs from "dayjs"; | |||||
import SearchIcon from "@mui/icons-material/Search"; | |||||
import RefreshIcon from "@mui/icons-material/Refresh"; | |||||
import { DemoItem } from "@mui/x-date-pickers/internals/demo"; | |||||
import { DatePicker } from "@mui/x-date-pickers/DatePicker"; | |||||
interface Field { | interface Field { | ||||
id: any; | id: any; | ||||
@@ -50,29 +50,38 @@ interface SearchFormProps { | |||||
sx?: any; | sx?: any; | ||||
} | } | ||||
const FormComponent: FC<FormComponentProps> = ({ fields, onSubmit, resetForm, sx }) => { | |||||
const FormComponent: FC<FormComponentProps> = ({ | |||||
fields, | |||||
onSubmit, | |||||
resetForm, | |||||
sx, | |||||
}) => { | |||||
const { reset, register, handleSubmit, control } = useForm(); | const { reset, register, handleSubmit, control } = useForm(); | ||||
const [fromDate, setFromDate] = useState<dayjs.Dayjs | null>(null); | const [fromDate, setFromDate] = useState<dayjs.Dayjs | null>(null); | ||||
const [dayRangeFromDate, setDayRangeFromDate] = useState<dayjs.Dayjs | null>(null); | |||||
const [dayRangeToDate, setDayRangeToDate] = useState<dayjs.Dayjs | null>(null); | |||||
const [dayRangeFromDate, setDayRangeFromDate] = useState<dayjs.Dayjs | null>( | |||||
null, | |||||
); | |||||
const [dayRangeToDate, setDayRangeToDate] = useState<dayjs.Dayjs | null>( | |||||
null, | |||||
); | |||||
const [value, setValue] = useState<{ [key: string]: any }>({}); | const [value, setValue] = useState<{ [key: string]: any }>({}); | ||||
const [checkbox1, setCheckbox1] = useState(false); | const [checkbox1, setCheckbox1] = useState(false); | ||||
const handleFormSubmit = (data: any) => { | const handleFormSubmit = (data: any) => { | ||||
if (fromDate != null || fromDate != undefined) { | if (fromDate != null || fromDate != undefined) { | ||||
data.fromDate = dayjs(fromDate).format('YYYY-MM-DD'); | |||||
data.fromDate = dayjs(fromDate).format("YYYY-MM-DD"); | |||||
} | } | ||||
if (value !== null) { | if (value !== null) { | ||||
data.dropdownCombo = value | |||||
data.dropdownCombo = value; | |||||
} | } | ||||
if (value !== null) { | if (value !== null) { | ||||
data.checkbox = checkbox1; | data.checkbox = checkbox1; | ||||
} | } | ||||
if (dayRangeFromDate != null || dayRangeFromDate != undefined) { | if (dayRangeFromDate != null || dayRangeFromDate != undefined) { | ||||
data.dayRangeFromDate = dayjs(dayRangeFromDate).format('YYYY-MM-DD'); | |||||
data.dayRangeFromDate = dayjs(dayRangeFromDate).format("YYYY-MM-DD"); | |||||
} | } | ||||
if (dayRangeToDate != null || dayRangeToDate != undefined) { | if (dayRangeToDate != null || dayRangeToDate != undefined) { | ||||
data.dayRangeToDate = dayjs(dayRangeToDate).format('YYYY-MM-DD'); | |||||
data.dayRangeToDate = dayjs(dayRangeToDate).format("YYYY-MM-DD"); | |||||
} | } | ||||
onSubmit(data); | onSubmit(data); | ||||
}; | }; | ||||
@@ -82,8 +91,8 @@ const FormComponent: FC<FormComponentProps> = ({ fields, onSubmit, resetForm, sx | |||||
resetForm(); | resetForm(); | ||||
setFromDate(null); | setFromDate(null); | ||||
fields.forEach((field) => { | fields.forEach((field) => { | ||||
if (typeof(field.setValue) === "function") { | |||||
field.setValue(typeof (field.value) === "boolean" ? false : null); | |||||
if (typeof field.setValue === "function") { | |||||
field.setValue(typeof field.value === "boolean" ? false : null); | |||||
} else if (Array.isArray(field.setValue)) { | } else if (Array.isArray(field.setValue)) { | ||||
field.setValue.forEach((setFunc) => { | field.setValue.forEach((setFunc) => { | ||||
setFunc(null); | setFunc(null); | ||||
@@ -96,11 +105,21 @@ const FormComponent: FC<FormComponentProps> = ({ fields, onSubmit, resetForm, sx | |||||
<form onSubmit={handleSubmit(handleFormSubmit)}> | <form onSubmit={handleSubmit(handleFormSubmit)}> | ||||
<Grid container alignItems="center"> | <Grid container alignItems="center"> | ||||
{fields.map((field) => { | {fields.map((field) => { | ||||
if (field.type === 'dropdown') { | |||||
if (field.type === "dropdown") { | |||||
return ( | return ( | ||||
<Grid item xs={12} sm={5.5} md={5.5} lg={5.5} sx={{ ml: 3, mr: 3, mb: 3 }} key={field.id}> | |||||
<Grid | |||||
item | |||||
xs={12} | |||||
sm={5.5} | |||||
md={5.5} | |||||
lg={5.5} | |||||
sx={{ ml: 3, mr: 3, mb: 3 }} | |||||
key={field.id} | |||||
> | |||||
<FormControl fullWidth> | <FormControl fullWidth> | ||||
<InputLabel id={`${field.id}-label`}>{field.label}</InputLabel> | |||||
<InputLabel id={`${field.id}-label`}> | |||||
{field.label} | |||||
</InputLabel> | |||||
<Controller | <Controller | ||||
name={field.id} | name={field.id} | ||||
control={control} | control={control} | ||||
@@ -115,11 +134,13 @@ const FormComponent: FC<FormComponentProps> = ({ fields, onSubmit, resetForm, sx | |||||
}} | }} | ||||
> | > | ||||
{field.options?.map((option) => ( | {field.options?.map((option) => ( | ||||
<MenuItem | |||||
value={option.id ?? JSON.stringify(option)} | |||||
<MenuItem | |||||
value={option.id ?? JSON.stringify(option)} | |||||
key={option.id ?? JSON.stringify(option)} | key={option.id ?? JSON.stringify(option)} | ||||
> | > | ||||
{option.id !== undefined ? option.label : JSON.stringify(option)} | |||||
{option.id !== undefined | |||||
? option.label | |||||
: JSON.stringify(option)} | |||||
</MenuItem> | </MenuItem> | ||||
))} | ))} | ||||
</Select> | </Select> | ||||
@@ -128,19 +149,27 @@ const FormComponent: FC<FormComponentProps> = ({ fields, onSubmit, resetForm, sx | |||||
</FormControl> | </FormControl> | ||||
</Grid> | </Grid> | ||||
); | ); | ||||
} else if (field.type === 'date') { | |||||
} else if (field.type === "date") { | |||||
return ( | return ( | ||||
<Grid item xs={12} sm={5.5} md={5.5} lg={5.5} sx={{ ml: 3, mr: 3, mb: 3 }} key={field.id}> | |||||
<Grid | |||||
item | |||||
xs={12} | |||||
sm={5.5} | |||||
md={5.5} | |||||
lg={5.5} | |||||
sx={{ ml: 3, mr: 3, mb: 3 }} | |||||
key={field.id} | |||||
> | |||||
<LocalizationProvider dateAdapter={AdapterDayjs}> | <LocalizationProvider dateAdapter={AdapterDayjs}> | ||||
<DemoItem> | <DemoItem> | ||||
<DatePicker | <DatePicker | ||||
slotProps={{ | slotProps={{ | ||||
textField: { | textField: { | ||||
id:field.id, | |||||
id: field.id, | |||||
}, | }, | ||||
}} | }} | ||||
label={field.label} | label={field.label} | ||||
value={fromDate === null ? null : dayjs(fromDate)} | |||||
value={fromDate === null ? null : dayjs(fromDate)} | |||||
onChange={(newValue) => { | onChange={(newValue) => { | ||||
setFromDate(newValue); | setFromDate(newValue); | ||||
}} | }} | ||||
@@ -149,16 +178,24 @@ const FormComponent: FC<FormComponentProps> = ({ fields, onSubmit, resetForm, sx | |||||
</LocalizationProvider> | </LocalizationProvider> | ||||
</Grid> | </Grid> | ||||
); | ); | ||||
} else if (field.type === 'checkbox') { | |||||
} else if (field.type === "checkbox") { | |||||
return ( | return ( | ||||
<Grid item xs={12} sm={5.5} md={5.5} lg={5.5} sx={{ ml: 3, mr: 3, mb: 3 }} key={field.id}> | |||||
<Grid | |||||
item | |||||
xs={12} | |||||
sm={5.5} | |||||
md={5.5} | |||||
lg={5.5} | |||||
sx={{ ml: 3, mr: 3, mb: 3 }} | |||||
key={field.id} | |||||
> | |||||
<FormControlLabel | <FormControlLabel | ||||
control={ | control={ | ||||
<Checkbox | <Checkbox | ||||
id={field.id} | id={field.id} | ||||
checked={field.value} | checked={field.value} | ||||
onChange={(event) => { | onChange={(event) => { | ||||
if (typeof field.setValue === 'function') { | |||||
if (typeof field.setValue === "function") { | |||||
field.setValue(event.target.checked); | field.setValue(event.target.checked); | ||||
setCheckbox1(event.target.checked); | setCheckbox1(event.target.checked); | ||||
} | } | ||||
@@ -166,102 +203,176 @@ const FormComponent: FC<FormComponentProps> = ({ fields, onSubmit, resetForm, sx | |||||
color="primary" | color="primary" | ||||
/> | /> | ||||
} | } | ||||
label={<Typography style={{fontSize:"1.15em"}}>{field.label}</Typography>} | |||||
label={ | |||||
<Typography style={{ fontSize: "1.15em" }}> | |||||
{field.label} | |||||
</Typography> | |||||
} | |||||
/> | /> | ||||
</Grid> | </Grid> | ||||
) | |||||
} else if (field.type === 'dateRange') { | |||||
); | |||||
} else if (field.type === "dateRange") { | |||||
return ( | return ( | ||||
<Grid container key={field.id[0]}> | <Grid container key={field.id[0]}> | ||||
<Grid item xs={12} sm={7} md={7} lg={7} sx={{ ml: 3, mr: 3, mb: 3 }}> | |||||
<Grid | |||||
item | |||||
xs={12} | |||||
sm={7} | |||||
md={7} | |||||
lg={7} | |||||
sx={{ ml: 3, mr: 3, mb: 3 }} | |||||
> | |||||
<Grid container> | <Grid container> | ||||
<Grid> | <Grid> | ||||
<LocalizationProvider dateAdapter={AdapterDayjs}> | <LocalizationProvider dateAdapter={AdapterDayjs}> | ||||
<DatePicker | |||||
label={field.label[0]} | |||||
value={field.value[0]} | |||||
onChange={(newValue) => setDayRangeFromDate(newValue)} | |||||
/> | |||||
<DatePicker | |||||
label={field.label[0]} | |||||
value={field.value[0]} | |||||
onChange={(newValue) => setDayRangeFromDate(newValue)} | |||||
/> | |||||
</LocalizationProvider> | </LocalizationProvider> | ||||
</Grid> | </Grid> | ||||
<Grid item xs={1.5} sm={1.5} md={1.5} lg={1.5} sx={{ display: 'flex', justifyContent: "center", alignItems: 'center' }}> | |||||
To | |||||
</Grid> | |||||
<Grid | |||||
item | |||||
xs={1.5} | |||||
sm={1.5} | |||||
md={1.5} | |||||
lg={1.5} | |||||
sx={{ | |||||
display: "flex", | |||||
justifyContent: "center", | |||||
alignItems: "center", | |||||
}} | |||||
> | |||||
To | |||||
</Grid> | |||||
<Grid item xs={5.25} sm={5.25} md={5.25} lg={5.25}> | <Grid item xs={5.25} sm={5.25} md={5.25} lg={5.25}> | ||||
<LocalizationProvider dateAdapter={AdapterDayjs}> | <LocalizationProvider dateAdapter={AdapterDayjs}> | ||||
<DatePicker | |||||
label={field.label[1]} | |||||
value={field.value[1]} | |||||
onChange={(newValue) => setDayRangeToDate(newValue)} | |||||
/> | |||||
<DatePicker | |||||
label={field.label[1]} | |||||
value={field.value[1]} | |||||
onChange={(newValue) => setDayRangeToDate(newValue)} | |||||
/> | |||||
</LocalizationProvider> | </LocalizationProvider> | ||||
</Grid> | </Grid> | ||||
</Grid> | </Grid> | ||||
</Grid> | </Grid> | ||||
</Grid> | </Grid> | ||||
) | |||||
); | |||||
} | } | ||||
return ( | return ( | ||||
<Grid item xs={12} sm={5.5} md={5.5} lg={5.5} sx={{ ml: 3, mr: 3, mb: 3 }} key={field.id}> | |||||
<Grid | |||||
item | |||||
xs={12} | |||||
sm={5.5} | |||||
md={5.5} | |||||
lg={5.5} | |||||
sx={{ ml: 3, mr: 3, mb: 3 }} | |||||
key={field.id} | |||||
> | |||||
<TextField | <TextField | ||||
fullWidth | fullWidth | ||||
{...register(field.id)} | {...register(field.id)} | ||||
id={field.id} | id={field.id} | ||||
label={field.label} | label={field.label} | ||||
defaultValue={field.value !== undefined && field.value !== null ? `${field.value}` : ''} | |||||
defaultValue={ | |||||
field.value !== undefined && field.value !== null | |||||
? `${field.value}` | |||||
: "" | |||||
} | |||||
required={field.required === true ? field.required : false} | required={field.required === true ? field.required : false} | ||||
sx={{ ...sx }} | sx={{ ...sx }} | ||||
InputProps={{ | InputProps={{ | ||||
style: { | style: { | ||||
borderRadius: "10px", | borderRadius: "10px", | ||||
} | |||||
}, | |||||
}} | }} | ||||
/> | /> | ||||
</Grid> | </Grid> | ||||
); | ); | ||||
})} | })} | ||||
</Grid> | </Grid> | ||||
<Grid container maxWidth="lg" justifyContent="space-between" style={{marginTop:-20}}> | |||||
<Grid | |||||
container | |||||
maxWidth="lg" | |||||
justifyContent="space-between" | |||||
style={{ marginTop: -20 }} | |||||
> | |||||
<Stack direction="row"> | <Stack direction="row"> | ||||
<Grid item sx={{ ml: 3, mr: 3, mb: 3, mt: 3 }}> | <Grid item sx={{ ml: 3, mr: 3, mb: 3, mt: 3 }}> | ||||
<Button className="h-12 w-32" style={{backgroundColor:"#92c1e9",color:"white",fontSize:"1.15em",fontWeight:100,borderRadius:10}} type="submit"> | |||||
<SearchIcon/> Search | |||||
<Button | |||||
className="h-12 w-32" | |||||
style={{ | |||||
backgroundColor: "#92c1e9", | |||||
color: "white", | |||||
fontSize: "1.15em", | |||||
fontWeight: 100, | |||||
borderRadius: 10, | |||||
}} | |||||
type="submit" | |||||
> | |||||
<SearchIcon /> | |||||
Search | |||||
</Button> | </Button> | ||||
</Grid> | </Grid> | ||||
<Grid item sx={{ ml: 3, mr: 3, mb: 3, mt: 3 }}> | <Grid item sx={{ ml: 3, mr: 3, mb: 3, mt: 3 }}> | ||||
<Button className="h-12 w-32" style={{backgroundColor:"#f890a5",color:"white",fontSize:"1.15em",fontWeight:100,borderRadius:10}} onClick={handleFormReset}> | |||||
<RefreshIcon/> Reset | |||||
<Button | |||||
className="h-12 w-32" | |||||
style={{ | |||||
backgroundColor: "#f890a5", | |||||
color: "white", | |||||
fontSize: "1.15em", | |||||
fontWeight: 100, | |||||
borderRadius: 10, | |||||
}} | |||||
onClick={handleFormReset} | |||||
> | |||||
<RefreshIcon /> | |||||
Reset | |||||
</Button> | </Button> | ||||
</Grid> | </Grid> | ||||
</Stack> | </Stack> | ||||
</Grid> | |||||
</Grid> | |||||
</form> | </form> | ||||
); | ); | ||||
}; | }; | ||||
const CustomSearchForm: FC<SearchFormProps> = ({ applySearch, fields, title, sx }) => { | |||||
const CustomSearchForm: FC<SearchFormProps> = ({ | |||||
applySearch, | |||||
fields, | |||||
title, | |||||
sx, | |||||
}) => { | |||||
const Title = title || "Searching Criteria"; | const Title = title || "Searching Criteria"; | ||||
const handleSubmit = (data: any) => { | const handleSubmit = (data: any) => { | ||||
if (applySearch) { | if (applySearch) { | ||||
applySearch(data); | applySearch(data); | ||||
} else { | } else { | ||||
console.log('applySearch function is null'); | |||||
console.log("applySearch function is null"); | |||||
} | } | ||||
}; | }; | ||||
const handleFormReset = () => { | const handleFormReset = () => { | ||||
console.log('Form Reset'); | |||||
console.log("Form Reset"); | |||||
}; | }; | ||||
return ( | return ( | ||||
<Card style={{marginRight:20}}> | |||||
<CardHeader className="text-slate-500 " style={{marginTop:-5}} title={Title}></CardHeader> | |||||
<FormComponent fields={fields} onSubmit={handleSubmit} resetForm={handleFormReset} sx={sx} /> | |||||
</Card> | |||||
<Card style={{ marginRight: 20 }}> | |||||
<CardHeader | |||||
className="text-slate-500 " | |||||
style={{ marginTop: -5 }} | |||||
title={Title} | |||||
></CardHeader> | |||||
<FormComponent | |||||
fields={fields} | |||||
onSubmit={handleSubmit} | |||||
resetForm={handleFormReset} | |||||
sx={sx} | |||||
/> | |||||
</Card> | |||||
); | ); | ||||
}; | }; | ||||
@@ -1,12 +1,12 @@ | |||||
"use client" | |||||
"use client"; | |||||
import Grid from "@mui/material/Grid"; | import Grid from "@mui/material/Grid"; | ||||
import Paper from "@mui/material/Paper"; | import Paper from "@mui/material/Paper"; | ||||
import { TFunction } from "i18next"; | import { TFunction } from "i18next"; | ||||
import { useTranslation } from "react-i18next"; | import { useTranslation } from "react-i18next"; | ||||
import PageTitle from "../PageTitle/PageTitle"; | import PageTitle from "../PageTitle/PageTitle"; | ||||
import DashboardTabButton from "./DashboardTabButton"; | import DashboardTabButton from "./DashboardTabButton"; | ||||
import { ThemeProvider } from '@mui/material/styles'; | |||||
import theme from '../../theme'; | |||||
import { ThemeProvider } from "@mui/material/styles"; | |||||
import theme from "../../theme"; | |||||
import Tabs, { TabsProps } from "@mui/material/Tabs"; | import Tabs, { TabsProps } from "@mui/material/Tabs"; | ||||
import Tab from "@mui/material/Tab"; | import Tab from "@mui/material/Tab"; | ||||
import React, { useCallback, useState } from "react"; | import React, { useCallback, useState } from "react"; | ||||
@@ -38,7 +38,7 @@ const DashboardPage: React.FC = () => { | |||||
<Tab label="Staff Utilization" /> | <Tab label="Staff Utilization" /> | ||||
</Tabs> | </Tabs> | ||||
{tabIndex === 2 && <ProgressByClient />} | {tabIndex === 2 && <ProgressByClient />} | ||||
{/* <Grid container height="100vh" style={{ backgroundColor: theme.palette.background.default}}> | |||||
{/* <Grid container height="100vh" style={{ backgroundColor: theme.palette.background.default}}> | |||||
<Grid item sm> | <Grid item sm> | ||||
<PageTitle BigTitle={"Dashboards"}/> | <PageTitle BigTitle={"Dashboards"}/> | ||||
<DashboardTabButton/> | <DashboardTabButton/> | ||||
@@ -1,6 +1,6 @@ | |||||
"use client"; | "use client"; | ||||
import Grid from "@mui/material/Grid"; | import Grid from "@mui/material/Grid"; | ||||
import { useState,useCallback} from 'react' | |||||
import { useState, useCallback } from "react"; | |||||
import Paper from "@mui/material/Paper"; | import Paper from "@mui/material/Paper"; | ||||
import { TFunction } from "i18next"; | import { TFunction } from "i18next"; | ||||
import { useTranslation } from "react-i18next"; | import { useTranslation } from "react-i18next"; | ||||
@@ -8,22 +8,22 @@ import PageTitle from "../PageTitle/PageTitle"; | |||||
import ProgressByClient from "./ProgressByClient"; | import ProgressByClient from "./ProgressByClient"; | ||||
import Tabs, { TabsProps } from "@mui/material/Tabs"; | import Tabs, { TabsProps } from "@mui/material/Tabs"; | ||||
import Tab from "@mui/material/Tab"; | import Tab from "@mui/material/Tab"; | ||||
import '../../app/global.css'; | |||||
import "../../app/global.css"; | |||||
const DashboardTabButton: React.FC = () => { | const DashboardTabButton: React.FC = () => { | ||||
const [activeTab, setActiveTab] = useState('financialSummary'); | |||||
const [activeTab, setActiveTab] = useState("financialSummary"); | |||||
const { t } = useTranslation("dashboard"); | const { t } = useTranslation("dashboard"); | ||||
const renderContent = () => { | const renderContent = () => { | ||||
switch (activeTab) { | switch (activeTab) { | ||||
case 'financialSummary': | |||||
case "financialSummary": | |||||
return <div>Project Financial Summary</div>; | return <div>Project Financial Summary</div>; | ||||
case 'cashFlow': | |||||
case "cashFlow": | |||||
return <div>Project Cash Flow</div>; | return <div>Project Cash Flow</div>; | ||||
case 'progressByClient': | |||||
return <ProgressByClient/>; | |||||
case 'resourceUtilization': | |||||
case "progressByClient": | |||||
return <ProgressByClient />; | |||||
case "resourceUtilization": | |||||
return <div>Project Resource Utilization</div>; | return <div>Project Resource Utilization</div>; | ||||
case 'staffUtilization': | |||||
case "staffUtilization": | |||||
return <div>Staff Utilization</div>; | return <div>Staff Utilization</div>; | ||||
default: | default: | ||||
return <div>Project Financial Summary</div>; | return <div>Project Financial Summary</div>; | ||||
@@ -37,40 +37,40 @@ const DashboardTabButton: React.FC = () => { | |||||
[], | [], | ||||
); | ); | ||||
return ( | return ( | ||||
// <Grid item sm> | |||||
// <div style={{marginLeft:20}}> | |||||
// {activeTab !== 'financialSummary' ? | |||||
// <button onClick={() => setActiveTab('financialSummary')}className="hover:bg-sky-100 hover:cursor-pointer rounded-lg bg-transparent border-slate-400 border-solid text-slate-400 ml-0.5 mt-0.5" style={{height:40,width:250,fontSize:18}}>Project Financial Summary</button> : | |||||
// <button onClick={() => setActiveTab('financialSummary')}className="rounded-lg bg-sky-100 border-cyan-500 border-solid text-cyan-500 ml-0.5 mt-0.5" style={{height:40,width:250,fontSize:18}}>Project Financial Summary</button> | |||||
// } | |||||
// {activeTab !== 'cashFlow' ? | |||||
// <button onClick={() => setActiveTab('cashFlow')} className="hover:bg-sky-100 hover:cursor-pointer rounded-lg bg-transparent border-slate-400 border-solid text-slate-400 ml-0.5 mt-0.5" style={{height:39,width:250,fontSize:18}}>Project Cash Flow</button> : | |||||
// <button onClick={() => setActiveTab('cashFlow')} className="rounded-lg bg-sky-100 border-cyan-500 border-solid text-cyan-500 ml-0.5 mt-0.5" style={{height:39,width:250,fontSize:18}}>Project Cash Flow</button> | |||||
// } | |||||
// {activeTab !== 'progressByClient' ? | |||||
// <button onClick={() => setActiveTab('progressByClient')} className="hover:bg-sky-100 hover:cursor-pointer rounded-lg bg-transparent border-slate-400 border-solid text-slate-400 ml-0.5 mt-0.5" style={{height:39,width:250,fontSize:18}}>Project Progress by Client</button> : | |||||
// <button onClick={() => setActiveTab('progressByClient')} className="rounded-lg bg-sky-100 border-cyan-500 border-solid text-cyan-500 ml-0.5 mt-0.5" style={{height:39,width:250,fontSize:18}}>Project Progress by Client</button> | |||||
// } | |||||
// {activeTab !== 'resourceUtilization' ? | |||||
// <button onClick={() => setActiveTab('resourceUtilization')} className="hover:bg-sky-100 hover:cursor-pointer rounded-lg bg-transparent border-slate-400 border-solid text-slate-400 ml-0.5 mt-0.5" style={{height:39,width:250,fontSize:18}}>Project Resource Utilization</button> : | |||||
// <button onClick={() => setActiveTab('resourceUtilization')} className="rounded-lg bg-sky-100 border-cyan-500 border-solid text-cyan-500 ml-0.5 mt-0.5" style={{height:39,width:250,fontSize:18}}>Project Resource Utilization</button> | |||||
// } | |||||
// {activeTab !== 'staffUtilization' ? | |||||
// <button onClick={() => setActiveTab('staffUtilization')} className="hover:bg-sky-100 hover:cursor-pointer rounded-lg bg-transparent border-slate-400 border-solid text-slate-400 ml-0.5 mt-0.5" style={{height:39,width:250,fontSize:18}}>Staff Utilization</button> : | |||||
// <button onClick={() => setActiveTab('staffUtilization')} className="rounded-lg bg-sky-100 border-cyan-500 border-solid text-cyan-500 ml-0.5 mt-0.5" style={{height:39,width:250,fontSize:18}}>Staff Utilization</button> | |||||
// } | |||||
// </div> | |||||
// <div style={{marginLeft:20,marginTop:20}}> | |||||
// {renderContent()} | |||||
// </div> | |||||
// </Grid> | |||||
<Tabs value={tabIndex} onChange={handleTabChange} variant="scrollable"> | |||||
<Tab label="Project Financial Summary" /> | |||||
<Tab label="Project Cash Flow" /> | |||||
<Tab label="Project Progress by Client" /> | |||||
<Tab label="Project Resource Utilization" /> | |||||
<Tab label="Staff Utilization" /> | |||||
</Tabs> | |||||
// <Grid item sm> | |||||
// <div style={{marginLeft:20}}> | |||||
// {activeTab !== 'financialSummary' ? | |||||
// <button onClick={() => setActiveTab('financialSummary')}className="hover:bg-sky-100 hover:cursor-pointer rounded-lg bg-transparent border-slate-400 border-solid text-slate-400 ml-0.5 mt-0.5" style={{height:40,width:250,fontSize:18}}>Project Financial Summary</button> : | |||||
// <button onClick={() => setActiveTab('financialSummary')}className="rounded-lg bg-sky-100 border-cyan-500 border-solid text-cyan-500 ml-0.5 mt-0.5" style={{height:40,width:250,fontSize:18}}>Project Financial Summary</button> | |||||
// } | |||||
// {activeTab !== 'cashFlow' ? | |||||
// <button onClick={() => setActiveTab('cashFlow')} className="hover:bg-sky-100 hover:cursor-pointer rounded-lg bg-transparent border-slate-400 border-solid text-slate-400 ml-0.5 mt-0.5" style={{height:39,width:250,fontSize:18}}>Project Cash Flow</button> : | |||||
// <button onClick={() => setActiveTab('cashFlow')} className="rounded-lg bg-sky-100 border-cyan-500 border-solid text-cyan-500 ml-0.5 mt-0.5" style={{height:39,width:250,fontSize:18}}>Project Cash Flow</button> | |||||
// } | |||||
// {activeTab !== 'progressByClient' ? | |||||
// <button onClick={() => setActiveTab('progressByClient')} className="hover:bg-sky-100 hover:cursor-pointer rounded-lg bg-transparent border-slate-400 border-solid text-slate-400 ml-0.5 mt-0.5" style={{height:39,width:250,fontSize:18}}>Project Progress by Client</button> : | |||||
// <button onClick={() => setActiveTab('progressByClient')} className="rounded-lg bg-sky-100 border-cyan-500 border-solid text-cyan-500 ml-0.5 mt-0.5" style={{height:39,width:250,fontSize:18}}>Project Progress by Client</button> | |||||
// } | |||||
// {activeTab !== 'resourceUtilization' ? | |||||
// <button onClick={() => setActiveTab('resourceUtilization')} className="hover:bg-sky-100 hover:cursor-pointer rounded-lg bg-transparent border-slate-400 border-solid text-slate-400 ml-0.5 mt-0.5" style={{height:39,width:250,fontSize:18}}>Project Resource Utilization</button> : | |||||
// <button onClick={() => setActiveTab('resourceUtilization')} className="rounded-lg bg-sky-100 border-cyan-500 border-solid text-cyan-500 ml-0.5 mt-0.5" style={{height:39,width:250,fontSize:18}}>Project Resource Utilization</button> | |||||
// } | |||||
// {activeTab !== 'staffUtilization' ? | |||||
// <button onClick={() => setActiveTab('staffUtilization')} className="hover:bg-sky-100 hover:cursor-pointer rounded-lg bg-transparent border-slate-400 border-solid text-slate-400 ml-0.5 mt-0.5" style={{height:39,width:250,fontSize:18}}>Staff Utilization</button> : | |||||
// <button onClick={() => setActiveTab('staffUtilization')} className="rounded-lg bg-sky-100 border-cyan-500 border-solid text-cyan-500 ml-0.5 mt-0.5" style={{height:39,width:250,fontSize:18}}>Staff Utilization</button> | |||||
// } | |||||
// </div> | |||||
// <div style={{marginLeft:20,marginTop:20}}> | |||||
// {renderContent()} | |||||
// </div> | |||||
// </Grid> | |||||
<Tabs value={tabIndex} onChange={handleTabChange} variant="scrollable"> | |||||
<Tab label="Project Financial Summary" /> | |||||
<Tab label="Project Cash Flow" /> | |||||
<Tab label="Project Progress by Client" /> | |||||
<Tab label="Project Resource Utilization" /> | |||||
<Tab label="Staff Utilization" /> | |||||
</Tabs> | |||||
); | ); | ||||
}; | }; | ||||
@@ -1,76 +1,160 @@ | |||||
import * as React from "react"; | import * as React from "react"; | ||||
import Grid from "@mui/material/Grid"; | import Grid from "@mui/material/Grid"; | ||||
import { useState,useEffect, useMemo } from 'react' | |||||
import { useState, useEffect, useMemo } from "react"; | |||||
import Paper from "@mui/material/Paper"; | import Paper from "@mui/material/Paper"; | ||||
import { TFunction } from "i18next"; | import { TFunction } from "i18next"; | ||||
import { useTranslation } from "react-i18next"; | import { useTranslation } from "react-i18next"; | ||||
import {Card,CardHeader} from '@mui/material'; | |||||
import { Card, CardHeader } from "@mui/material"; | |||||
import CustomSearchForm from "../CustomSearchForm/CustomSearchForm"; | import CustomSearchForm from "../CustomSearchForm/CustomSearchForm"; | ||||
import CustomDatagrid from '../CustomDatagrid/CustomDatagrid'; | |||||
import ReactApexChart from 'react-apexcharts'; | |||||
import { ApexOptions } from 'apexcharts'; | |||||
import { GridColDef, GridRowSelectionModel} from '@mui/x-data-grid'; | |||||
import ReportProblemIcon from '@mui/icons-material/ReportProblem'; | |||||
import dynamic from 'next/dynamic'; | |||||
import '../../app/global.css'; | |||||
import CustomDatagrid from "../CustomDatagrid/CustomDatagrid"; | |||||
import ReactApexChart from "react-apexcharts"; | |||||
import { ApexOptions } from "apexcharts"; | |||||
import { GridColDef, GridRowSelectionModel } from "@mui/x-data-grid"; | |||||
import ReportProblemIcon from "@mui/icons-material/ReportProblem"; | |||||
import dynamic from "next/dynamic"; | |||||
import "../../app/global.css"; | |||||
import { AnyARecord } from "dns"; | import { AnyARecord } from "dns"; | ||||
import SearchBox, { Criterion } from "../SearchBox"; | import SearchBox, { Criterion } from "../SearchBox"; | ||||
import ProgressByClientSearch from "@/components/ProgressByClientSearch"; | import ProgressByClientSearch from "@/components/ProgressByClientSearch"; | ||||
import { Suspense } from "react"; | import { Suspense } from "react"; | ||||
const ProgressByClient: React.FC = () => { | const ProgressByClient: React.FC = () => { | ||||
const [activeTab, setActiveTab] = useState('financialSummary'); | |||||
const [SearchCriteria, setSearchCriteria] = React.useState({}) | |||||
const [activeTab, setActiveTab] = useState("financialSummary"); | |||||
const [SearchCriteria, setSearchCriteria] = React.useState({}); | |||||
const { t } = useTranslation("dashboard"); | const { t } = useTranslation("dashboard"); | ||||
const [clientCode, setClientCode] = useState(''); | |||||
const [clientName, setClientName] = useState(''); | |||||
const [subsidiaryClientCode, setSubsidiaryClientCode] = useState(''); | |||||
const [subsidiaryClientName, setSubsidiaryClientName] = useState(''); | |||||
const [projectArray, setProjectArray] : any[] = useState([]); | |||||
const [percentageArray, setPercentageArray] : any[] = useState([]); | |||||
const [selectionModel, setSelectionModel] : any[] = React.useState([]); | |||||
const [dropdownDemo, setDropdownDemo] = useState(''); | |||||
const [clientCode, setClientCode] = useState(""); | |||||
const [clientName, setClientName] = useState(""); | |||||
const [subsidiaryClientCode, setSubsidiaryClientCode] = useState(""); | |||||
const [subsidiaryClientName, setSubsidiaryClientName] = useState(""); | |||||
const [projectArray, setProjectArray]: any[] = useState([]); | |||||
const [percentageArray, setPercentageArray]: any[] = useState([]); | |||||
const [selectionModel, setSelectionModel]: any[] = React.useState([]); | |||||
const [dropdownDemo, setDropdownDemo] = useState(""); | |||||
const [dateDemo, setDateDemo] = useState(null); | const [dateDemo, setDateDemo] = useState(null); | ||||
const [checkboxDemo, setCheckboxDemo] = useState(false); | const [checkboxDemo, setCheckboxDemo] = useState(false); | ||||
const [receiptFromDate, setReceiptFromDate] = useState(null); | const [receiptFromDate, setReceiptFromDate] = useState(null); | ||||
const [receiptToDate, setReceiptToDate] = useState(null); | const [receiptToDate, setReceiptToDate] = useState(null); | ||||
const [selectedRows, setSelectedRows] = useState([]); | const [selectedRows, setSelectedRows] = useState([]); | ||||
const rows = [{id: 1,clientCode:"CUST-001",clientName:"Client A", clientSubsidiaryCode:"N/A", clientSubsidiaryName:"N/A", noOfProjects:"5"}, | |||||
{id: 2,clientCode:"CUST-001",clientName:"Client A", clientSubsidiaryCode:"SUBS-001", clientSubsidiaryName:"Subsidiary A", noOfProjects:"5"}, | |||||
{id: 3,clientCode:"CUST-001",clientName:"Client A", clientSubsidiaryCode:"SUBS-002", clientSubsidiaryName:"Subsidiary B", noOfProjects:"3"}, | |||||
{id: 4,clientCode:"CUST-001",clientName:"Client A", clientSubsidiaryCode:"SUBS-003", clientSubsidiaryName:"Subsidiary C", noOfProjects:"1"} | |||||
] | |||||
const rows2 = [{id: 1,project:"Consultancy Project 123",team:"XXX", teamLeader:"XXX", currentStage:"Contract Documentation", budgetedManhour:"200.00",spentManhour:"120.00",remainedManhour:"80.00",comingPaymentMilestone:"31/03/2024",alert:false}, | |||||
{id: 2,project:"Consultancy Project 456",team:"XXX", teamLeader:"XXX", currentStage:"Report Preparation", budgetedManhour:"400.00",spentManhour:"200.00",remainedManhour:"200.00",comingPaymentMilestone:"20/02/2024",alert:false}, | |||||
{id: 3,project:"Construction Project A",team:"YYY", teamLeader:"YYY", currentStage:"Construction", budgetedManhour:"187.50",spentManhour:"200.00",remainedManhour:"12.50",comingPaymentMilestone:"13/12/2023",alert:true}, | |||||
{id: 4,project:"Construction Project B",team:"XXX", teamLeader:"XXX", currentStage:"Post Construction", budgetedManhour:"100.00",spentManhour:"40.00",remainedManhour:"60.00",comingPaymentMilestone:"05/01/2024",alert:false}, | |||||
{id: 5,project:"Construction Project C",team:"YYY", teamLeader:"YYY", currentStage:"Construction", budgetedManhour:"300.00",spentManhour:"150.00",remainedManhour:"150.00",comingPaymentMilestone:"31/03/2024",alert:false}, | |||||
] | |||||
const rows = [ | |||||
{ | |||||
id: 1, | |||||
clientCode: "CUST-001", | |||||
clientName: "Client A", | |||||
clientSubsidiaryCode: "N/A", | |||||
clientSubsidiaryName: "N/A", | |||||
noOfProjects: "5", | |||||
}, | |||||
{ | |||||
id: 2, | |||||
clientCode: "CUST-001", | |||||
clientName: "Client A", | |||||
clientSubsidiaryCode: "SUBS-001", | |||||
clientSubsidiaryName: "Subsidiary A", | |||||
noOfProjects: "5", | |||||
}, | |||||
{ | |||||
id: 3, | |||||
clientCode: "CUST-001", | |||||
clientName: "Client A", | |||||
clientSubsidiaryCode: "SUBS-002", | |||||
clientSubsidiaryName: "Subsidiary B", | |||||
noOfProjects: "3", | |||||
}, | |||||
{ | |||||
id: 4, | |||||
clientCode: "CUST-001", | |||||
clientName: "Client A", | |||||
clientSubsidiaryCode: "SUBS-003", | |||||
clientSubsidiaryName: "Subsidiary C", | |||||
noOfProjects: "1", | |||||
}, | |||||
]; | |||||
const rows2 = [ | |||||
{ | |||||
id: 1, | |||||
project: "Consultancy Project 123", | |||||
team: "XXX", | |||||
teamLeader: "XXX", | |||||
currentStage: "Contract Documentation", | |||||
budgetedManhour: "200.00", | |||||
spentManhour: "120.00", | |||||
remainedManhour: "80.00", | |||||
comingPaymentMilestone: "31/03/2024", | |||||
alert: false, | |||||
}, | |||||
{ | |||||
id: 2, | |||||
project: "Consultancy Project 456", | |||||
team: "XXX", | |||||
teamLeader: "XXX", | |||||
currentStage: "Report Preparation", | |||||
budgetedManhour: "400.00", | |||||
spentManhour: "200.00", | |||||
remainedManhour: "200.00", | |||||
comingPaymentMilestone: "20/02/2024", | |||||
alert: false, | |||||
}, | |||||
{ | |||||
id: 3, | |||||
project: "Construction Project A", | |||||
team: "YYY", | |||||
teamLeader: "YYY", | |||||
currentStage: "Construction", | |||||
budgetedManhour: "187.50", | |||||
spentManhour: "200.00", | |||||
remainedManhour: "12.50", | |||||
comingPaymentMilestone: "13/12/2023", | |||||
alert: true, | |||||
}, | |||||
{ | |||||
id: 4, | |||||
project: "Construction Project B", | |||||
team: "XXX", | |||||
teamLeader: "XXX", | |||||
currentStage: "Post Construction", | |||||
budgetedManhour: "100.00", | |||||
spentManhour: "40.00", | |||||
remainedManhour: "60.00", | |||||
comingPaymentMilestone: "05/01/2024", | |||||
alert: false, | |||||
}, | |||||
{ | |||||
id: 5, | |||||
project: "Construction Project C", | |||||
team: "YYY", | |||||
teamLeader: "YYY", | |||||
currentStage: "Construction", | |||||
budgetedManhour: "300.00", | |||||
spentManhour: "150.00", | |||||
remainedManhour: "150.00", | |||||
comingPaymentMilestone: "31/03/2024", | |||||
alert: false, | |||||
}, | |||||
]; | |||||
const columns = [ | const columns = [ | ||||
{ | |||||
id: 'clientCode', | |||||
field: 'clientCode', | |||||
headerName: "Client Code", | |||||
flex: 1, | |||||
{ | |||||
id: "clientCode", | |||||
field: "clientCode", | |||||
headerName: "Client Code", | |||||
flex: 1, | |||||
}, | }, | ||||
{ | { | ||||
id: 'clientName', | |||||
field: 'clientName', | |||||
headerName: "Client Name", | |||||
flex: 1, | |||||
id: "clientName", | |||||
field: "clientName", | |||||
headerName: "Client Name", | |||||
flex: 1, | |||||
}, | }, | ||||
{ | { | ||||
id: 'clientSubsidiaryCode', | |||||
field: 'clientSubsidiaryCode', | |||||
id: "clientSubsidiaryCode", | |||||
field: "clientSubsidiaryCode", | |||||
headerName: "Client Subsidiary Code", | headerName: "Client Subsidiary Code", | ||||
flex: 1, | flex: 1, | ||||
}, | }, | ||||
{ | { | ||||
id: 'noOfProjects', | |||||
field: 'noOfProjects', | |||||
id: "noOfProjects", | |||||
field: "noOfProjects", | |||||
headerName: "No. of Projects", | headerName: "No. of Projects", | ||||
flex: 1, | flex: 1, | ||||
}, | }, | ||||
@@ -78,99 +162,119 @@ const ProgressByClient: React.FC = () => { | |||||
const columns2 = [ | const columns2 = [ | ||||
{ | { | ||||
id: 'project', | |||||
field: 'project', | |||||
id: "project", | |||||
field: "project", | |||||
headerName: "Project", | headerName: "Project", | ||||
flex: 1, | flex: 1, | ||||
}, | |||||
{ | |||||
id: 'team', | |||||
field: 'team', | |||||
}, | |||||
{ | |||||
id: "team", | |||||
field: "team", | |||||
headerName: "Team", | headerName: "Team", | ||||
flex: 1, | flex: 1, | ||||
}, | |||||
{ | |||||
id: 'teamLeader', | |||||
field: 'teamLeader', | |||||
headerName: "Team Leader", | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: 'currentStage', | |||||
field: 'currentStage', | |||||
headerName: "Current Stage", | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: 'budgetedManhour', | |||||
field: 'budgetedManhour', | |||||
headerName: "Budgeted Manhour", | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: 'spentManhour', | |||||
field: 'spentManhour', | |||||
headerName: "Spent Manhour", | |||||
renderCell: (params:any) => { | |||||
if (params.row.budgetedManhour - params.row.spentManhour <= 0) { | |||||
return( | |||||
<span className="text-red-300">{params.row.spentManhour}</span> | |||||
) | |||||
} else { | |||||
return ( | |||||
<span>{params.row.spentManhour}</span> | |||||
) | |||||
} | |||||
}, | }, | ||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: 'remainedManhour', | |||||
field: 'remainedManhour', | |||||
headerName: "Remained Manhour", | |||||
renderCell: (params:any) => { | |||||
if (params.row.budgetedManhour - params.row.spentManhour <= 0) { | |||||
return( | |||||
<span className="text-red-300">({params.row.remainedManhour})</span> | |||||
) | |||||
} else { | |||||
return ( | |||||
<span>{params.row.remainedManhour}</span> | |||||
) | |||||
} | |||||
{ | |||||
id: "teamLeader", | |||||
field: "teamLeader", | |||||
headerName: "Team Leader", | |||||
flex: 1, | |||||
}, | }, | ||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: 'comingPaymentMilestone', | |||||
field: 'comingPaymentMilestone', | |||||
headerName: "Coming Payment Milestone", | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: 'alert', | |||||
field: 'alert', | |||||
headerName: "Alert", | |||||
renderCell: (params:any) => { | |||||
if (params.row.alert === true) { | |||||
return ( | |||||
<span className="text-red-300 text-center"><ReportProblemIcon/></span> | |||||
) | |||||
} else { | |||||
return ( | |||||
<span></span> | |||||
) | |||||
} | |||||
{ | |||||
id: "currentStage", | |||||
field: "currentStage", | |||||
headerName: "Current Stage", | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: "budgetedManhour", | |||||
field: "budgetedManhour", | |||||
headerName: "Budgeted Manhour", | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: "spentManhour", | |||||
field: "spentManhour", | |||||
headerName: "Spent Manhour", | |||||
renderCell: (params: any) => { | |||||
if (params.row.budgetedManhour - params.row.spentManhour <= 0) { | |||||
return ( | |||||
<span className="text-red-300">{params.row.spentManhour}</span> | |||||
); | |||||
} else { | |||||
return <span>{params.row.spentManhour}</span>; | |||||
} | |||||
}, | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: "remainedManhour", | |||||
field: "remainedManhour", | |||||
headerName: "Remained Manhour", | |||||
renderCell: (params: any) => { | |||||
if (params.row.budgetedManhour - params.row.spentManhour <= 0) { | |||||
return ( | |||||
<span className="text-red-300">({params.row.remainedManhour})</span> | |||||
); | |||||
} else { | |||||
return <span>{params.row.remainedManhour}</span>; | |||||
} | |||||
}, | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: "comingPaymentMilestone", | |||||
field: "comingPaymentMilestone", | |||||
headerName: "Coming Payment Milestone", | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: "alert", | |||||
field: "alert", | |||||
headerName: "Alert", | |||||
renderCell: (params: any) => { | |||||
if (params.row.alert === true) { | |||||
return ( | |||||
<span className="text-red-300 text-center"> | |||||
<ReportProblemIcon /> | |||||
</span> | |||||
); | |||||
} else { | |||||
return <span></span>; | |||||
} | |||||
}, | |||||
flex: 1, | |||||
}, | }, | ||||
flex: 1, | |||||
}, | |||||
]; | |||||
]; | |||||
const InputFields = [ | const InputFields = [ | ||||
{ id: "clientCode", label: "Client Code", type: 'text', value: clientCode, setValue: setClientCode }, | |||||
{ id: "clientName", label: "Client Name", type: 'text', value: clientName, setValue: setClientName }, | |||||
{ id: "subsidiaryClientCode", label: "Subsidiary Client Code", type:'text', value:subsidiaryClientCode, setValue: setSubsidiaryClientCode}, | |||||
{ id: "subsidiaryClientName", label: "Subsidiary Client Name", type:'text', value:subsidiaryClientName, setValue: setSubsidiaryClientName}, | |||||
{ | |||||
id: "clientCode", | |||||
label: "Client Code", | |||||
type: "text", | |||||
value: clientCode, | |||||
setValue: setClientCode, | |||||
}, | |||||
{ | |||||
id: "clientName", | |||||
label: "Client Name", | |||||
type: "text", | |||||
value: clientName, | |||||
setValue: setClientName, | |||||
}, | |||||
{ | |||||
id: "subsidiaryClientCode", | |||||
label: "Subsidiary Client Code", | |||||
type: "text", | |||||
value: subsidiaryClientCode, | |||||
setValue: setSubsidiaryClientCode, | |||||
}, | |||||
{ | |||||
id: "subsidiaryClientName", | |||||
label: "Subsidiary Client Name", | |||||
type: "text", | |||||
value: subsidiaryClientName, | |||||
setValue: setSubsidiaryClientName, | |||||
}, | |||||
// { id: 'dropdownDemo', label: "dropdownDemo", type: 'dropdown', options: [{id:"1", label:"1"}], value: dropdownDemo, setValue: setDropdownDemo }, | // { id: 'dropdownDemo', label: "dropdownDemo", type: 'dropdown', options: [{id:"1", label:"1"}], value: dropdownDemo, setValue: setDropdownDemo }, | ||||
// { id: 'dateDemo', label:'dateDemo', type: 'date', value: dateDemo, setValue: setDateDemo }, | // { id: 'dateDemo', label:'dateDemo', type: 'date', value: dateDemo, setValue: setDateDemo }, | ||||
// { id: 'checkboxDemo', label:'checkboxDemo', type: 'checkbox', value: checkboxDemo, setValue: setCheckboxDemo }, | // { id: 'checkboxDemo', label:'checkboxDemo', type: 'checkbox', value: checkboxDemo, setValue: setCheckboxDemo }, | ||||
@@ -178,54 +282,66 @@ const ProgressByClient: React.FC = () => { | |||||
// setValue: [setReceiptFromDate, setReceiptToDate],type: 'dateRange' }, | // setValue: [setReceiptFromDate, setReceiptToDate],type: 'dateRange' }, | ||||
]; | ]; | ||||
const stageDeadline = ["31/03/2024","20/02/2024","01/12/2023","05/01/2024","31/03/2023"] | |||||
const stageDeadline = [ | |||||
"31/03/2024", | |||||
"20/02/2024", | |||||
"01/12/2023", | |||||
"05/01/2024", | |||||
"31/03/2023", | |||||
]; | |||||
const series2: ApexAxisChartSeries | ApexNonAxisChartSeries = [{ | |||||
data: [17.1, 28.6, 5.7, 48.6], | |||||
}]; | |||||
const series2: ApexAxisChartSeries | ApexNonAxisChartSeries = [ | |||||
{ | |||||
data: [17.1, 28.6, 5.7, 48.6], | |||||
}, | |||||
]; | |||||
const series: ApexAxisChartSeries | ApexNonAxisChartSeries = [{ | |||||
name: 'Current Stage Completion Percentage', | |||||
data: [80, 55, 40, 65, 70], | |||||
}]; | |||||
const options2 : ApexOptions = { | |||||
const series: ApexAxisChartSeries | ApexNonAxisChartSeries = [ | |||||
{ | |||||
name: "Current Stage Completion Percentage", | |||||
data: [80, 55, 40, 65, 70], | |||||
}, | |||||
]; | |||||
const options2: ApexOptions = { | |||||
chart: { | chart: { | ||||
type: 'donut', | |||||
type: "donut", | |||||
}, | }, | ||||
plotOptions: { | plotOptions: { | ||||
pie: { | pie: { | ||||
donut:{ | |||||
labels:{ | |||||
show:false, | |||||
} | |||||
} | |||||
donut: { | |||||
labels: { | |||||
show: false, | |||||
}, | |||||
}, | |||||
}, | }, | ||||
}, | }, | ||||
labels: [projectArray], | labels: [projectArray], | ||||
legend: { | legend: { | ||||
show: false, | show: false, | ||||
}, | }, | ||||
responsive: [{ | |||||
breakpoint: 480, | |||||
options: { | |||||
chart: { | |||||
width: 200 | |||||
responsive: [ | |||||
{ | |||||
breakpoint: 480, | |||||
options: { | |||||
chart: { | |||||
width: 200, | |||||
}, | |||||
legend: { | |||||
position: "bottom", | |||||
show: false, | |||||
}, | |||||
}, | }, | ||||
legend: { | |||||
position: 'bottom', | |||||
show:false | |||||
} | |||||
} | |||||
}] | |||||
} | |||||
}, | |||||
], | |||||
}; | |||||
const options: ApexOptions = { | const options: ApexOptions = { | ||||
chart: { | chart: { | ||||
type: 'bar', | |||||
height: 350 | |||||
type: "bar", | |||||
height: 350, | |||||
}, | }, | ||||
colors: ['#FF4560', '#00E396', '#008FFB', '#775DD0', '#FEB019'], | |||||
colors: ["#FF4560", "#00E396", "#008FFB", "#775DD0", "#FEB019"], | |||||
plotOptions: { | plotOptions: { | ||||
bar: { | bar: { | ||||
horizontal: true, | horizontal: true, | ||||
@@ -233,91 +349,93 @@ const ProgressByClient: React.FC = () => { | |||||
}, | }, | ||||
}, | }, | ||||
dataLabels: { | dataLabels: { | ||||
enabled: false | |||||
enabled: false, | |||||
}, | }, | ||||
xaxis: { | xaxis: { | ||||
categories: [ | categories: [ | ||||
'Consultancy Project 123', | |||||
'Consultancy Project 456', | |||||
'Construction Project A', | |||||
'Construction Project B', | |||||
'Construction Project C', | |||||
"Consultancy Project 123", | |||||
"Consultancy Project 456", | |||||
"Construction Project A", | |||||
"Construction Project B", | |||||
"Construction Project C", | |||||
], | ], | ||||
}, | }, | ||||
yaxis: { | yaxis: { | ||||
title: { | title: { | ||||
text: 'Projects' | |||||
text: "Projects", | |||||
}, | }, | ||||
labels: { | labels: { | ||||
maxWidth: 200, | |||||
maxWidth: 200, | |||||
style: { | style: { | ||||
cssClass: 'apexcharts-yaxis-label', | |||||
cssClass: "apexcharts-yaxis-label", | |||||
}, | }, | ||||
}, | }, | ||||
}, | }, | ||||
title: { | title: { | ||||
text: 'Current Stage Completion Percentage', | |||||
align: 'center' | |||||
text: "Current Stage Completion Percentage", | |||||
align: "center", | |||||
}, | }, | ||||
grid: { | grid: { | ||||
borderColor: '#f1f1f1', | |||||
borderColor: "#f1f1f1", | |||||
}, | }, | ||||
annotations: { | |||||
} | |||||
annotations: {}, | |||||
}; | }; | ||||
const handleSelectionChange = (newSelectionModel: GridRowSelectionModel) => { | const handleSelectionChange = (newSelectionModel: GridRowSelectionModel) => { | ||||
const selectedRowsData = rows2.filter((row) => | const selectedRowsData = rows2.filter((row) => | ||||
newSelectionModel.includes(row.id) | |||||
newSelectionModel.includes(row.id), | |||||
); | ); | ||||
console.log(selectedRowsData) | |||||
const projectArray:any[] = [] | |||||
let otherPercentage = 100 | |||||
let totalBudgetManhour = 0 | |||||
const percentageArray = [] | |||||
console.log(selectedRowsData); | |||||
const projectArray: any[] = []; | |||||
let otherPercentage = 100; | |||||
let totalBudgetManhour = 0; | |||||
const percentageArray = []; | |||||
for (let i = 0; i <= selectedRowsData.length; i++) { | for (let i = 0; i <= selectedRowsData.length; i++) { | ||||
if (i === selectedRowsData.length) { | if (i === selectedRowsData.length) { | ||||
projectArray.push("Other") | |||||
projectArray.push("Other"); | |||||
} else { | } else { | ||||
projectArray.push(selectedRowsData[i].project) | |||||
totalBudgetManhour += Number(selectedRowsData[i].budgetedManhour) | |||||
projectArray.push(selectedRowsData[i].project); | |||||
totalBudgetManhour += Number(selectedRowsData[i].budgetedManhour); | |||||
} | } | ||||
} | } | ||||
for (let i = 0; i <= selectedRowsData.length; i++) { | for (let i = 0; i <= selectedRowsData.length; i++) { | ||||
if (i === selectedRowsData.length) { | if (i === selectedRowsData.length) { | ||||
percentageArray.push(otherPercentage) | |||||
percentageArray.push(otherPercentage); | |||||
} else { | } else { | ||||
let percentage = ((Number(selectedRowsData[i].spentManhour) / totalBudgetManhour) * 100).toFixed(1) | |||||
percentageArray.push(Number(percentage)) | |||||
otherPercentage -= Number(percentage) | |||||
const percentage = ( | |||||
(Number(selectedRowsData[i].spentManhour) / totalBudgetManhour) * | |||||
100 | |||||
).toFixed(1); | |||||
percentageArray.push(Number(percentage)); | |||||
otherPercentage -= Number(percentage); | |||||
} | } | ||||
} | } | ||||
setSelectionModel(newSelectionModel) | |||||
setProjectArray(projectArray) | |||||
setPercentageArray(percentageArray) | |||||
setSelectionModel(newSelectionModel); | |||||
setProjectArray(projectArray); | |||||
setPercentageArray(percentageArray); | |||||
}; | }; | ||||
const applySearch = (data: any) => { | const applySearch = (data: any) => { | ||||
console.log(data) | |||||
setSearchCriteria(data) | |||||
} | |||||
console.log(data); | |||||
setSearchCriteria(data); | |||||
}; | |||||
return ( | return ( | ||||
<Grid item sm> | |||||
{/* <CustomSearchForm applySearch={applySearch} fields={InputFields}/> */} | |||||
{/* <CustomDatagrid rows={rows} columns={columns} columnWidth={200} dataGridHeight={300}/> */} | |||||
<div style={{display:"inline-block",width:"70%"}}> | |||||
<Grid item xs={12} md={12} lg={12}> | |||||
<Card> | |||||
<CardHeader className="text-slate-500" title="Project Progress"/> | |||||
<div style={{display:"inline-block",width:"99%"}}> | |||||
<ReactApexChart | |||||
options={options} | |||||
series={series} | |||||
type="bar" | |||||
height={350} | |||||
/> | |||||
</div> | |||||
{/* <div style={{display:"inline-block",width:"20%",verticalAlign:"top",textAlign:"center"}}> | |||||
<Grid item sm> | |||||
{/* <CustomSearchForm applySearch={applySearch} fields={InputFields}/> */} | |||||
{/* <CustomDatagrid rows={rows} columns={columns} columnWidth={200} dataGridHeight={300}/> */} | |||||
<div style={{ display: "inline-block", width: "70%" }}> | |||||
<Grid item xs={12} md={12} lg={12}> | |||||
<Card> | |||||
<CardHeader className="text-slate-500" title="Project Progress" /> | |||||
<div style={{ display: "inline-block", width: "99%" }}> | |||||
<ReactApexChart | |||||
options={options} | |||||
series={series} | |||||
type="bar" | |||||
height={350} | |||||
/> | |||||
</div> | |||||
{/* <div style={{display:"inline-block",width:"20%",verticalAlign:"top",textAlign:"center"}}> | |||||
<p><strong><u>Stage Deadline</u></strong></p> | <p><strong><u>Stage Deadline</u></strong></p> | ||||
{stageDeadline.map((date, index) => { | {stageDeadline.map((date, index) => { | ||||
const marginTop = index === 0 ? 25 : 20; | const marginTop = index === 0 ? 25 : 20; | ||||
@@ -326,26 +444,49 @@ const ProgressByClient: React.FC = () => { | |||||
); | ); | ||||
})} | })} | ||||
</div> */} | </div> */} | ||||
<CardHeader className="text-slate-500" title="Current Stage Due Date"/> | |||||
<div style={{display:"inline-block",width:"99%",marginLeft:10}}> | |||||
<CustomDatagrid rows={rows2} columns={columns2} columnWidth={200} dataGridHeight={300} checkboxSelection={true} onRowSelectionModelChange={handleSelectionChange} selectionModel={selectionModel}/> | |||||
</div> | |||||
</Card> | |||||
</Grid> | |||||
</div> | |||||
<div style={{display:"inline-block",width:"30%",verticalAlign:"top",marginLeft:0}}> | |||||
<Grid item xs={12} md={12} lg={12}> | |||||
<Card style={{marginLeft:15,marginRight:20}}> | |||||
<CardHeader className="text-slate-500" title="Overall Progress per Project"/> | |||||
<ReactApexChart | |||||
options={options2} | |||||
series={percentageArray} | |||||
type="donut" | |||||
/> | |||||
</Card> | |||||
</Grid> | |||||
<CardHeader | |||||
className="text-slate-500" | |||||
title="Current Stage Due Date" | |||||
/> | |||||
<div | |||||
style={{ display: "inline-block", width: "99%", marginLeft: 10 }} | |||||
> | |||||
<CustomDatagrid | |||||
rows={rows2} | |||||
columns={columns2} | |||||
columnWidth={200} | |||||
dataGridHeight={300} | |||||
checkboxSelection={true} | |||||
onRowSelectionModelChange={handleSelectionChange} | |||||
selectionModel={selectionModel} | |||||
/> | |||||
</div> | </div> | ||||
</Grid> | |||||
</Card> | |||||
</Grid> | |||||
</div> | |||||
<div | |||||
style={{ | |||||
display: "inline-block", | |||||
width: "30%", | |||||
verticalAlign: "top", | |||||
marginLeft: 0, | |||||
}} | |||||
> | |||||
<Grid item xs={12} md={12} lg={12}> | |||||
<Card style={{ marginLeft: 15, marginRight: 20 }}> | |||||
<CardHeader | |||||
className="text-slate-500" | |||||
title="Overall Progress per Project" | |||||
/> | |||||
<ReactApexChart | |||||
options={options2} | |||||
series={percentageArray} | |||||
type="donut" | |||||
/> | |||||
</Card> | |||||
</Grid> | |||||
</div> | |||||
</Grid> | |||||
); | ); | ||||
}; | }; | ||||
@@ -8,14 +8,14 @@ import PageTitle from "../PageTitle/PageTitle"; | |||||
import { Suspense } from "react"; | import { Suspense } from "react"; | ||||
import Button from "@mui/material/Button"; | import Button from "@mui/material/Button"; | ||||
import Stack from "@mui/material/Stack"; | import Stack from "@mui/material/Stack"; | ||||
import { Add } from '@mui/icons-material'; | |||||
import { Add } from "@mui/icons-material"; | |||||
import Link from "next/link"; | import Link from "next/link"; | ||||
import { t } from 'i18next'; | |||||
import { t } from "i18next"; | |||||
import { Card, Modal, Typography } from "@mui/material"; | import { Card, Modal, Typography } from "@mui/material"; | ||||
import CustomModal from "../CustomModal/CustomModal"; | import CustomModal from "../CustomModal/CustomModal"; | ||||
import { PROJECT_MODAL_STYLE } from "@/theme/colorConst"; | import { PROJECT_MODAL_STYLE } from "@/theme/colorConst"; | ||||
import CustomDatagrid from "../CustomDatagrid/CustomDatagrid"; | import CustomDatagrid from "../CustomDatagrid/CustomDatagrid"; | ||||
import { DataGrid } from '@mui/x-data-grid'; | |||||
import { DataGrid } from "@mui/x-data-grid"; | |||||
import TimesheetInputGrid from "./TimesheetInputGrid"; | import TimesheetInputGrid from "./TimesheetInputGrid"; | ||||
interface EnterTimesheetModalProps { | interface EnterTimesheetModalProps { | ||||
@@ -24,55 +24,75 @@ interface EnterTimesheetModalProps { | |||||
modalStyle?: any; | modalStyle?: any; | ||||
} | } | ||||
const EnterTimesheetModal: React.FC<EnterTimesheetModalProps> = ({ ...props }) => { | |||||
const EnterTimesheetModal: React.FC<EnterTimesheetModalProps> = ({ | |||||
...props | |||||
}) => { | |||||
const [lockConfirm, setLockConfirm] = useState(false); | const [lockConfirm, setLockConfirm] = useState(false); | ||||
const columns = [ | const columns = [ | ||||
{ | { | ||||
id: 'projectCode', | |||||
field: 'projectCode', | |||||
id: "projectCode", | |||||
field: "projectCode", | |||||
headerName: "Project Code and Name", | headerName: "Project Code and Name", | ||||
flex: 1, | flex: 1, | ||||
}, | }, | ||||
{ | { | ||||
id: 'task', | |||||
field: 'task', | |||||
headerName: "Task", | |||||
flex: 1, | |||||
id: "task", | |||||
field: "task", | |||||
headerName: "Task", | |||||
flex: 1, | |||||
}, | }, | ||||
]; | ]; | ||||
const rows = [{ | |||||
id: 1, projectCode: "M1001", task: "1.2" | |||||
const rows = [ | |||||
{ | |||||
id: 1, | |||||
projectCode: "M1001", | |||||
task: "1.2", | |||||
}, | }, | ||||
{ | { | ||||
id: 2, projectCode: "M1301", task: "1.1" | |||||
}]; | |||||
id: 2, | |||||
projectCode: "M1301", | |||||
task: "1.1", | |||||
}, | |||||
]; | |||||
return ( | return ( | ||||
<Modal open={props.isOpen} onClose={props.onClose}> | <Modal open={props.isOpen} onClose={props.onClose}> | ||||
<div> | |||||
{/* <Typography variant="h5" id="modal-title" sx={{flex:1}}> | |||||
<div> | |||||
{/* <Typography variant="h5" id="modal-title" sx={{flex:1}}> | |||||
<div style={{ display: 'flex', justifyContent: 'space-between', width: '100%' }}> | <div style={{ display: 'flex', justifyContent: 'space-between', width: '100%' }}> | ||||
Timesheet Input | Timesheet Input | ||||
</div> | </div> | ||||
</Typography> */} | </Typography> */} | ||||
<Card style={{flex: 10, marginBottom:'20px'}}> | |||||
{/* <TimesheetInputGrid setLockConfirm={setLockConfirm}/> */} | |||||
</Card> | |||||
<Card style={{ flex: 10, marginBottom: "20px" }}> | |||||
{/* <TimesheetInputGrid setLockConfirm={setLockConfirm}/> */} | |||||
</Card> | |||||
<div style={{ | |||||
display: 'flex', justifyContent: 'space-between', width: '100%', flex: 1 | |||||
}}> | |||||
<Button disabled={lockConfirm} variant="contained" onClick={props.onClose}> | |||||
Confirm | |||||
</Button> | |||||
<Button variant="contained" onClick={props.onClose} | |||||
sx={{"background-color":"#F890A5"}}> | |||||
Cancel | |||||
</Button> | |||||
</div> | |||||
<div | |||||
style={{ | |||||
display: "flex", | |||||
justifyContent: "space-between", | |||||
width: "100%", | |||||
flex: 1, | |||||
}} | |||||
> | |||||
<Button | |||||
disabled={lockConfirm} | |||||
variant="contained" | |||||
onClick={props.onClose} | |||||
> | |||||
Confirm | |||||
</Button> | |||||
<Button | |||||
variant="contained" | |||||
onClick={props.onClose} | |||||
sx={{ "background-color": "#F890A5" }} | |||||
> | |||||
Cancel | |||||
</Button> | |||||
</div> | </div> | ||||
</div> | |||||
</Modal> | </Modal> | ||||
); | ); | ||||
}; | }; | ||||
@@ -8,20 +8,27 @@ import { Suspense } from "react"; | |||||
import Button from "@mui/material/Button"; | import Button from "@mui/material/Button"; | ||||
import Stack from "@mui/material/Stack"; | import Stack from "@mui/material/Stack"; | ||||
import Link from "next/link"; | import Link from "next/link"; | ||||
import { t } from 'i18next'; | |||||
import { Box, Container, Modal, Select, SelectChangeEvent, Typography } from "@mui/material"; | |||||
import { Close } from '@mui/icons-material'; | |||||
import AddIcon from '@mui/icons-material/Add'; | |||||
import EditIcon from '@mui/icons-material/Edit'; | |||||
import DeleteIcon from '@mui/icons-material/DeleteOutlined'; | |||||
import SaveIcon from '@mui/icons-material/Save'; | |||||
import CancelIcon from '@mui/icons-material/Close'; | |||||
import ArrowForwardIcon from '@mui/icons-material/ArrowForward'; | |||||
import ArrowBackIcon from '@mui/icons-material/ArrowBack'; | |||||
import { t } from "i18next"; | |||||
import { | |||||
Box, | |||||
Container, | |||||
Modal, | |||||
Select, | |||||
SelectChangeEvent, | |||||
Typography, | |||||
} from "@mui/material"; | |||||
import { Close } from "@mui/icons-material"; | |||||
import AddIcon from "@mui/icons-material/Add"; | |||||
import EditIcon from "@mui/icons-material/Edit"; | |||||
import DeleteIcon from "@mui/icons-material/DeleteOutlined"; | |||||
import SaveIcon from "@mui/icons-material/Save"; | |||||
import CancelIcon from "@mui/icons-material/Close"; | |||||
import ArrowForwardIcon from "@mui/icons-material/ArrowForward"; | |||||
import ArrowBackIcon from "@mui/icons-material/ArrowBack"; | |||||
import Swal from "sweetalert2"; | import Swal from "sweetalert2"; | ||||
import { msg } from "../Swal/CustomAlerts"; | import { msg } from "../Swal/CustomAlerts"; | ||||
import React from "react"; | import React from "react"; | ||||
import { DatePicker } from '@mui/x-date-pickers/DatePicker'; | |||||
import { DatePicker } from "@mui/x-date-pickers/DatePicker"; | |||||
import { | import { | ||||
GridRowsProp, | GridRowsProp, | ||||
GridRowModesModel, | GridRowModesModel, | ||||
@@ -37,17 +44,17 @@ import { | |||||
GridRowEditStopReasons, | GridRowEditStopReasons, | ||||
GridEditInputCell, | GridEditInputCell, | ||||
GridValueSetterParams, | GridValueSetterParams, | ||||
} from '@mui/x-data-grid'; | |||||
} from "@mui/x-data-grid"; | |||||
import { LocalizationProvider } from "@mui/x-date-pickers"; | import { LocalizationProvider } from "@mui/x-date-pickers"; | ||||
import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs"; | import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs"; | ||||
import dayjs from "dayjs"; | import dayjs from "dayjs"; | ||||
import { Props } from "react-intl/src/components/relative"; | import { Props } from "react-intl/src/components/relative"; | ||||
const weekdays = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun']; | |||||
const weekdays = ["mon", "tue", "wed", "thu", "fri", "sat", "sun"]; | |||||
interface BottomBarProps { | interface BottomBarProps { | ||||
getHoursTotal: (column: string) => number; | getHoursTotal: (column: string) => number; | ||||
setLockConfirm: (newLock: (oldLock: Boolean) => Boolean) => void; | |||||
setLockConfirm: (newLock: (oldLock: boolean) => boolean) => void; | |||||
setRows: (newRows: (oldRows: GridRowsProp) => GridRowsProp) => void; | setRows: (newRows: (oldRows: GridRowsProp) => GridRowsProp) => void; | ||||
setRowModesModel: ( | setRowModesModel: ( | ||||
newModel: (oldModel: GridRowModesModel) => GridRowModesModel, | newModel: (oldModel: GridRowModesModel) => GridRowModesModel, | ||||
@@ -76,13 +83,16 @@ const EditToolbar = (props: EditToolbarProps) => { | |||||
const handleClickLeft = () => { | const handleClickLeft = () => { | ||||
if (selectedDate) { | if (selectedDate) { | ||||
const newDate = selectedDate.add(-7, 'day'); | |||||
const newDate = selectedDate.add(-7, "day"); | |||||
setSelectedDate(newDate); | setSelectedDate(newDate); | ||||
} | } | ||||
}; | }; | ||||
const handleClickRight = () => { | const handleClickRight = () => { | ||||
if (selectedDate) { | if (selectedDate) { | ||||
const newDate = selectedDate.add(7, 'day') > dayjs()? dayjs(): selectedDate.add(7, 'day'); | |||||
const newDate = | |||||
selectedDate.add(7, "day") > dayjs() | |||||
? dayjs() | |||||
: selectedDate.add(7, "day"); | |||||
setSelectedDate(newDate); | setSelectedDate(newDate); | ||||
} | } | ||||
}; | }; | ||||
@@ -98,24 +108,40 @@ const EditToolbar = (props: EditToolbarProps) => { | |||||
return ( | return ( | ||||
<LocalizationProvider dateAdapter={AdapterDayjs}> | <LocalizationProvider dateAdapter={AdapterDayjs}> | ||||
<div style={{ display: 'flex', justifyContent: 'flex-end', width: '100%', paddingBottom:'20px'}}> | |||||
<Typography variant="h5" id="modal-title" sx={{flex:1}}> | |||||
Timesheet Input | |||||
</Typography> | |||||
<Button sx={{"border-radius":"30%", marginRight:'20px'}} variant="contained" onClick={handleClickLeft}> | |||||
<ArrowBackIcon/> | |||||
<div | |||||
style={{ | |||||
display: "flex", | |||||
justifyContent: "flex-end", | |||||
width: "100%", | |||||
paddingBottom: "20px", | |||||
}} | |||||
> | |||||
<Typography variant="h5" id="modal-title" sx={{ flex: 1 }}> | |||||
Timesheet Input | |||||
</Typography> | |||||
<Button | |||||
sx={{ "border-radius": "30%", marginRight: "20px" }} | |||||
variant="contained" | |||||
onClick={handleClickLeft} | |||||
> | |||||
<ArrowBackIcon /> | |||||
</Button> | </Button> | ||||
<DatePicker | <DatePicker | ||||
value={selectedDate} | |||||
onChange={handleDateChange} | |||||
disableFuture={true}/> | |||||
<Button sx={{"border-radius":"30%", margin:'0px 20px 0px 20px'}} variant="contained" onClick={handleClickRight}> | |||||
<ArrowForwardIcon/> | |||||
value={selectedDate} | |||||
onChange={handleDateChange} | |||||
disableFuture={true} | |||||
/> | |||||
<Button | |||||
sx={{ "border-radius": "30%", margin: "0px 20px 0px 20px" }} | |||||
variant="contained" | |||||
onClick={handleClickRight} | |||||
> | |||||
<ArrowForwardIcon /> | |||||
</Button> | </Button> | ||||
</div> | </div> | ||||
</LocalizationProvider> | </LocalizationProvider> | ||||
); | ); | ||||
} | |||||
}; | |||||
const BottomBar = (props: BottomBarProps) => { | const BottomBar = (props: BottomBarProps) => { | ||||
const { setRows, setRowModesModel, getHoursTotal, setLockConfirm } = props; | const { setRows, setRowModesModel, getHoursTotal, setLockConfirm } = props; | ||||
@@ -126,75 +152,84 @@ const BottomBar = (props: BottomBarProps) => { | |||||
const handleAddClick = () => { | const handleAddClick = () => { | ||||
const id = newId; | const id = newId; | ||||
setNewId(newId - 1); | setNewId(newId - 1); | ||||
setRows((oldRows) => [...oldRows, { id, projectCode: '', task: '', isNew: true }]); | |||||
setRows((oldRows) => [ | |||||
...oldRows, | |||||
{ id, projectCode: "", task: "", isNew: true }, | |||||
]); | |||||
setRowModesModel((oldModel) => ({ | setRowModesModel((oldModel) => ({ | ||||
...oldModel, | ...oldModel, | ||||
[id]: { mode: GridRowModes.Edit, fieldToFocus: 'projectCode' }, | |||||
[id]: { mode: GridRowModes.Edit, fieldToFocus: "projectCode" }, | |||||
})); | })); | ||||
}; | }; | ||||
const totalColDef = { | const totalColDef = { | ||||
flex:1, | |||||
flex: 1, | |||||
// style: {color:getHoursTotal('mon')>24?"red":"black"} | // style: {color:getHoursTotal('mon')>24?"red":"black"} | ||||
}; | }; | ||||
const TotalCell = ({value}: Props) => { | |||||
const TotalCell = ({ value }: Props) => { | |||||
const [invalid, setInvalid] = useState(false); | const [invalid, setInvalid] = useState(false); | ||||
useEffect(()=> { | |||||
const newInvalid = (value??0)>24; | |||||
useEffect(() => { | |||||
const newInvalid = (value ?? 0) > 24; | |||||
setInvalid(newInvalid); | setInvalid(newInvalid); | ||||
}, [value]); | }, [value]); | ||||
return ( | return ( | ||||
<Box flex={1} style={{color: invalid?"red":"black"}}> | |||||
<Box flex={1} style={{ color: invalid ? "red" : "black" }}> | |||||
{value} | {value} | ||||
</Box> | </Box> | ||||
); | ); | ||||
} | |||||
}; | |||||
const checkUnlockConfirmBtn = () => { | const checkUnlockConfirmBtn = () => { | ||||
// setLockConfirm((oldLock)=> valid); | // setLockConfirm((oldLock)=> valid); | ||||
setLockConfirm((oldLock)=> weekdays.every(weekday => { | |||||
getHoursTotal(weekday) <= 24 | |||||
})); | |||||
} | |||||
setLockConfirm((oldLock) => | |||||
weekdays.every((weekday) => { | |||||
getHoursTotal(weekday) <= 24; | |||||
}), | |||||
); | |||||
}; | |||||
return ( | return ( | ||||
<div> | <div> | ||||
<div style={{ display: 'flex', justifyContent: 'flex', width: '100%' }}> | |||||
<Box flex={5.7} textAlign={'right'} marginRight='4rem'> | |||||
<div style={{ display: "flex", justifyContent: "flex", width: "100%" }}> | |||||
<Box flex={5.7} textAlign={"right"} marginRight="4rem"> | |||||
<b>Total:</b> | <b>Total:</b> | ||||
</Box> | </Box> | ||||
<TotalCell value={getHoursTotal('mon')}/> | |||||
<TotalCell value={getHoursTotal('tue')}/> | |||||
<TotalCell value={getHoursTotal('wed')}/> | |||||
<TotalCell value={getHoursTotal('thu')}/> | |||||
<TotalCell value={getHoursTotal('fri')}/> | |||||
<TotalCell value={getHoursTotal('sat')}/> | |||||
<TotalCell value={getHoursTotal('sun')}/> | |||||
<TotalCell value={getHoursTotal("mon")} /> | |||||
<TotalCell value={getHoursTotal("tue")} /> | |||||
<TotalCell value={getHoursTotal("wed")} /> | |||||
<TotalCell value={getHoursTotal("thu")} /> | |||||
<TotalCell value={getHoursTotal("fri")} /> | |||||
<TotalCell value={getHoursTotal("sat")} /> | |||||
<TotalCell value={getHoursTotal("sun")} /> | |||||
</div> | </div> | ||||
<Button variant="outlined" color="primary" startIcon={<AddIcon />} onClick={handleAddClick}> | |||||
<Button | |||||
variant="outlined" | |||||
color="primary" | |||||
startIcon={<AddIcon />} | |||||
onClick={handleAddClick} | |||||
> | |||||
Add record | Add record | ||||
</Button> | </Button> | ||||
</div> | </div> | ||||
); | ); | ||||
} | |||||
}; | |||||
const EditFooter = (props: EditFooterProps) => { | const EditFooter = (props: EditFooterProps) => { | ||||
return ( | return ( | ||||
<div style={{ display: 'flex', justifyContent: 'flex', width: '100%' }}> | |||||
<div style={{ display: "flex", justifyContent: "flex", width: "100%" }}> | |||||
<Box flex={1}> | <Box flex={1}> | ||||
<b>Total: </b> | <b>Total: </b> | ||||
</Box> | </Box> | ||||
<Box flex={2}>ssss</Box> | <Box flex={2}>ssss</Box> | ||||
</div> | </div> | ||||
); | ); | ||||
} | |||||
}; | |||||
interface TimesheetInputGridProps { | interface TimesheetInputGridProps { | ||||
setLockConfirm: (newLock: (oldLock: Boolean) => Boolean) => void; | |||||
setLockConfirm: (newLock: (oldLock: boolean) => boolean) => void; | |||||
onClose?: () => void; | onClose?: () => void; | ||||
} | } | ||||
@@ -213,30 +248,37 @@ const initialRows: GridRowsProp = [ | |||||
}, | }, | ||||
]; | ]; | ||||
const options=["M1001", "M1301", "M1354", "M1973"]; | |||||
const options2=[ | |||||
const options = ["M1001", "M1301", "M1354", "M1973"]; | |||||
const options2 = [ | |||||
"1.1 - Preparation of preliminary Cost Estimate / Cost Plan", | "1.1 - Preparation of preliminary Cost Estimate / Cost Plan", | ||||
"1.2 - Cash flow forecast", | "1.2 - Cash flow forecast", | ||||
"1.3 - Cost studies fo alterative design solutions", | "1.3 - Cost studies fo alterative design solutions", | ||||
"1.4 = Attend design co-ordination / project review meetings", | "1.4 = Attend design co-ordination / project review meetings", | ||||
"1.5 - Prepare / Review RIC"]; | |||||
"1.5 - Prepare / Review RIC", | |||||
]; | |||||
const getDateForHeader = (date : dayjs.Dayjs, weekday : number) => { | |||||
const getDateForHeader = (date: dayjs.Dayjs, weekday: number) => { | |||||
if (date.day() == 0) { | if (date.day() == 0) { | ||||
return date.add((weekday - date.day() - 7), 'day').format('DD MMM'); | |||||
return date.add(weekday - date.day() - 7, "day").format("DD MMM"); | |||||
} else { | } else { | ||||
return date.add(weekday - date.day(), 'day').format('DD MMM'); | |||||
return date.add(weekday - date.day(), "day").format("DD MMM"); | |||||
} | } | ||||
} | |||||
const TimesheetInputGrid: React.FC<TimesheetInputGridProps> = ({ ...props }) => { | |||||
}; | |||||
const TimesheetInputGrid: React.FC<TimesheetInputGridProps> = ({ | |||||
...props | |||||
}) => { | |||||
const [rows, setRows] = useState(initialRows); | const [rows, setRows] = useState(initialRows); | ||||
const [day, setDay] = useState(dayjs()); | const [day, setDay] = useState(dayjs()); | ||||
const [rowModesModel, setRowModesModel] = React.useState<GridRowModesModel>({}); | |||||
const [rowModesModel, setRowModesModel] = React.useState<GridRowModesModel>( | |||||
{}, | |||||
); | |||||
const { setLockConfirm } = props; | const { setLockConfirm } = props; | ||||
const handleRowEditStop: GridEventListener<'rowEditStop'> = (params, event) => { | |||||
const handleRowEditStop: GridEventListener<"rowEditStop"> = ( | |||||
params, | |||||
event, | |||||
) => { | |||||
if (params.reason === GridRowEditStopReasons.rowFocusOut) { | if (params.reason === GridRowEditStopReasons.rowFocusOut) { | ||||
event.defaultMuiPrevented = true; | event.defaultMuiPrevented = true; | ||||
} | } | ||||
@@ -247,7 +289,6 @@ const TimesheetInputGrid: React.FC<TimesheetInputGridProps> = ({ ...props }) => | |||||
}; | }; | ||||
const handleSaveClick = (id: GridRowId) => () => { | const handleSaveClick = (id: GridRowId) => () => { | ||||
setRowModesModel({ ...rowModesModel, [id]: { mode: GridRowModes.View } }); | setRowModesModel({ ...rowModesModel, [id]: { mode: GridRowModes.View } }); | ||||
}; | }; | ||||
@@ -277,23 +318,23 @@ const TimesheetInputGrid: React.FC<TimesheetInputGridProps> = ({ ...props }) => | |||||
setRowModesModel(newRowModesModel); | setRowModesModel(newRowModesModel); | ||||
}; | }; | ||||
const getHoursTotal = (column : any) => { | |||||
const getHoursTotal = (column: any) => { | |||||
let sum = 0; | let sum = 0; | ||||
rows.forEach((row) => { | rows.forEach((row) => { | ||||
sum += row[column]??0; | |||||
sum += row[column] ?? 0; | |||||
}); | }); | ||||
return sum; | return sum; | ||||
}; | }; | ||||
const weekdayColConfig : any = { | |||||
type: 'number', | |||||
const weekdayColConfig: any = { | |||||
type: "number", | |||||
// sortable: false, | // sortable: false, | ||||
//width: 100, | //width: 100, | ||||
flex: 1, | flex: 1, | ||||
align: 'left', | |||||
headerAlign: 'left', | |||||
align: "left", | |||||
headerAlign: "left", | |||||
editable: true, | editable: true, | ||||
renderEditCell: (value : any) => ( | |||||
renderEditCell: (value: any) => ( | |||||
<GridEditInputCell | <GridEditInputCell | ||||
{...value} | {...value} | ||||
inputProps={{ | inputProps={{ | ||||
@@ -307,26 +348,28 @@ const TimesheetInputGrid: React.FC<TimesheetInputGridProps> = ({ ...props }) => | |||||
const columns: GridColDef[] = [ | const columns: GridColDef[] = [ | ||||
{ | { | ||||
field: 'actions', | |||||
type: 'actions', | |||||
headerName: 'Actions', | |||||
field: "actions", | |||||
type: "actions", | |||||
headerName: "Actions", | |||||
width: 100, | width: 100, | ||||
cellClassName: 'actions', | |||||
cellClassName: "actions", | |||||
getActions: ({ id }) => { | getActions: ({ id }) => { | ||||
const isInEditMode = rowModesModel[id]?.mode === GridRowModes.Edit; | const isInEditMode = rowModesModel[id]?.mode === GridRowModes.Edit; | ||||
if (isInEditMode) { | if (isInEditMode) { | ||||
return [ | return [ | ||||
<GridActionsCellItem | <GridActionsCellItem | ||||
key={`actions-${id}-save`} | |||||
icon={<SaveIcon />} | icon={<SaveIcon />} | ||||
title="Save" | title="Save" | ||||
label="Save" | label="Save" | ||||
sx={{ | sx={{ | ||||
color: 'primary.main', | |||||
color: "primary.main", | |||||
}} | }} | ||||
onClick={handleSaveClick(id)} | onClick={handleSaveClick(id)} | ||||
/>, | />, | ||||
<GridActionsCellItem | <GridActionsCellItem | ||||
key={`actions-${id}-cancel`} | |||||
icon={<CancelIcon />} | icon={<CancelIcon />} | ||||
title="Cancel" | title="Cancel" | ||||
label="Cancel" | label="Cancel" | ||||
@@ -339,6 +382,7 @@ const TimesheetInputGrid: React.FC<TimesheetInputGridProps> = ({ ...props }) => | |||||
return [ | return [ | ||||
<GridActionsCellItem | <GridActionsCellItem | ||||
key={`actions-${id}-edit`} | |||||
icon={<EditIcon />} | icon={<EditIcon />} | ||||
title="Edit" | title="Edit" | ||||
label="Edit" | label="Edit" | ||||
@@ -347,100 +391,89 @@ const TimesheetInputGrid: React.FC<TimesheetInputGridProps> = ({ ...props }) => | |||||
color="inherit" | color="inherit" | ||||
/>, | />, | ||||
<GridActionsCellItem | <GridActionsCellItem | ||||
key={`actions-${id}-delete`} | |||||
title="Delete" | title="Delete" | ||||
label="Delete" | label="Delete" | ||||
icon={<DeleteIcon />} | icon={<DeleteIcon />} | ||||
onClick={handleDeleteClick(id)} | onClick={handleDeleteClick(id)} | ||||
sx={{color:"red"}} | |||||
sx={{ color: "red" }} | |||||
/>, | />, | ||||
]; | ]; | ||||
}, | }, | ||||
}, | }, | ||||
{ | { | ||||
field: 'projectCode', | |||||
headerName: 'Project Code', | |||||
field: "projectCode", | |||||
headerName: "Project Code", | |||||
// width: 220, | // width: 220, | ||||
flex: 2, | flex: 2, | ||||
editable: true, | editable: true, | ||||
type: 'singleSelect', | |||||
type: "singleSelect", | |||||
valueOptions: options, | valueOptions: options, | ||||
}, | }, | ||||
{ | { | ||||
field: 'task', | |||||
headerName: 'Task', | |||||
field: "task", | |||||
headerName: "Task", | |||||
// width: 220, | // width: 220, | ||||
flex: 3, | flex: 3, | ||||
editable: true, | editable: true, | ||||
type: 'singleSelect', | |||||
type: "singleSelect", | |||||
valueOptions: options2, | valueOptions: options2, | ||||
}, | }, | ||||
{ | { | ||||
// Mon | // Mon | ||||
field: 'mon', | |||||
field: "mon", | |||||
...weekdayColConfig, | ...weekdayColConfig, | ||||
renderHeader: () => { | renderHeader: () => { | ||||
return ( | |||||
<div>Mon - {getDateForHeader(day, 1)}</div> | |||||
); | |||||
return <div>Mon - {getDateForHeader(day, 1)}</div>; | |||||
}, | }, | ||||
}, | }, | ||||
{ | { | ||||
// Tue | // Tue | ||||
field: 'tue', | |||||
field: "tue", | |||||
...weekdayColConfig, | ...weekdayColConfig, | ||||
renderHeader: () => { | renderHeader: () => { | ||||
return ( | |||||
<div>Tue - {getDateForHeader(day, 2)}</div> | |||||
); | |||||
return <div>Tue - {getDateForHeader(day, 2)}</div>; | |||||
}, | }, | ||||
}, | }, | ||||
{ | { | ||||
// Wed | // Wed | ||||
field: 'wed', | |||||
field: "wed", | |||||
...weekdayColConfig, | ...weekdayColConfig, | ||||
renderHeader: () => { | renderHeader: () => { | ||||
return ( | |||||
<div>Wed - {getDateForHeader(day, 3)}</div> | |||||
); | |||||
return <div>Wed - {getDateForHeader(day, 3)}</div>; | |||||
}, | }, | ||||
}, | }, | ||||
{ | { | ||||
// Thu | // Thu | ||||
field: 'thu', | |||||
field: "thu", | |||||
...weekdayColConfig, | ...weekdayColConfig, | ||||
renderHeader: () => { | renderHeader: () => { | ||||
return ( | |||||
<div>Thu - {getDateForHeader(day, 4)}</div> | |||||
); | |||||
return <div>Thu - {getDateForHeader(day, 4)}</div>; | |||||
}, | }, | ||||
}, | }, | ||||
{ | { | ||||
// Fri | // Fri | ||||
field: 'fri', | |||||
field: "fri", | |||||
...weekdayColConfig, | ...weekdayColConfig, | ||||
renderHeader: () => { | renderHeader: () => { | ||||
return ( | |||||
<div>Fri - {getDateForHeader(day, 5)}</div> | |||||
); | |||||
return <div>Fri - {getDateForHeader(day, 5)}</div>; | |||||
}, | }, | ||||
}, | }, | ||||
{ | { | ||||
// Sat | // Sat | ||||
field: 'sat', | |||||
field: "sat", | |||||
...weekdayColConfig, | ...weekdayColConfig, | ||||
renderHeader: () => { | renderHeader: () => { | ||||
return ( | |||||
<div>Sat - {getDateForHeader(day, 6)}</div> | |||||
); | |||||
return <div>Sat - {getDateForHeader(day, 6)}</div>; | |||||
}, | }, | ||||
}, | }, | ||||
{ | { | ||||
// Sun | // Sun | ||||
field: 'sun', | |||||
field: "sun", | |||||
...weekdayColConfig, | ...weekdayColConfig, | ||||
renderHeader: () => { | renderHeader: () => { | ||||
return ( | return ( | ||||
<div style={{color:"red"}}>Sun - {getDateForHeader(day, 7)}</div> | |||||
<div style={{ color: "red" }}>Sun - {getDateForHeader(day, 7)}</div> | |||||
); | ); | ||||
}, | }, | ||||
}, | }, | ||||
@@ -457,22 +490,22 @@ const TimesheetInputGrid: React.FC<TimesheetInputGridProps> = ({ ...props }) => | |||||
<Box | <Box | ||||
sx={{ | sx={{ | ||||
// marginBottom: '-5px', | // marginBottom: '-5px', | ||||
display: 'flex', | |||||
'flex-direction': 'column', | |||||
display: "flex", | |||||
"flex-direction": "column", | |||||
// 'justify-content': 'flex-end', | // 'justify-content': 'flex-end', | ||||
padding: '20px', | |||||
height: '100%',//'30rem', | |||||
width: '100%', | |||||
'& .actions': { | |||||
color: 'text.secondary', | |||||
padding: "20px", | |||||
height: "100%", //'30rem', | |||||
width: "100%", | |||||
"& .actions": { | |||||
color: "text.secondary", | |||||
}, | }, | ||||
'& .header': { | |||||
"& .header": { | |||||
// border: 1, | // border: 1, | ||||
// 'border-width': '1px', | // 'border-width': '1px', | ||||
// 'border-color': 'grey', | // 'border-color': 'grey', | ||||
}, | }, | ||||
'& .textPrimary': { | |||||
color: 'text.primary', | |||||
"& .textPrimary": { | |||||
color: "text.primary", | |||||
}, | }, | ||||
}} | }} | ||||
> | > | ||||
@@ -498,14 +531,18 @@ const TimesheetInputGrid: React.FC<TimesheetInputGridProps> = ({ ...props }) => | |||||
initialState={{ | initialState={{ | ||||
pagination: { paginationModel: { pageSize: 100 } }, | pagination: { paginationModel: { pageSize: 100 } }, | ||||
}} | }} | ||||
sx={{flex:1}} | |||||
sx={{ flex: 1 }} | |||||
/> | /> | ||||
<BottomBar getHoursTotal={getHoursTotal} setRows={setRows} setRowModesModel={setRowModesModel} setLockConfirm={setLockConfirm} | |||||
// sx={{flex:3}} | |||||
<BottomBar | |||||
getHoursTotal={getHoursTotal} | |||||
setRows={setRows} | |||||
setRowModesModel={setRowModesModel} | |||||
setLockConfirm={setLockConfirm} | |||||
// sx={{flex:3}} | |||||
/> | /> | ||||
</Box> | </Box> | ||||
); | ); | ||||
} | |||||
}; | |||||
export default TimesheetInputGrid; | export default TimesheetInputGrid; |
@@ -7,11 +7,11 @@ import ListItemText from "@mui/material/ListItemText"; | |||||
import ListItemIcon from "@mui/material/ListItemIcon"; | import ListItemIcon from "@mui/material/ListItemIcon"; | ||||
import WorkHistory from "@mui/icons-material/WorkHistory"; | import WorkHistory from "@mui/icons-material/WorkHistory"; | ||||
import Dashboard from "@mui/icons-material/Dashboard"; | import Dashboard from "@mui/icons-material/Dashboard"; | ||||
import SummarizeIcon from '@mui/icons-material/Summarize'; | |||||
import PaymentsIcon from '@mui/icons-material/Payments'; | |||||
import AccountTreeIcon from '@mui/icons-material/AccountTree'; | |||||
import SummarizeIcon from "@mui/icons-material/Summarize"; | |||||
import PaymentsIcon from "@mui/icons-material/Payments"; | |||||
import AccountTreeIcon from "@mui/icons-material/AccountTree"; | |||||
import RequestQuote from "@mui/icons-material/RequestQuote"; | import RequestQuote from "@mui/icons-material/RequestQuote"; | ||||
import PeopleIcon from '@mui/icons-material/People'; | |||||
import PeopleIcon from "@mui/icons-material/People"; | |||||
import Task from "@mui/icons-material/Task"; | import Task from "@mui/icons-material/Task"; | ||||
import Assignment from "@mui/icons-material/Assignment"; | import Assignment from "@mui/icons-material/Assignment"; | ||||
import Settings from "@mui/icons-material/Settings"; | import Settings from "@mui/icons-material/Settings"; | ||||
@@ -22,8 +22,8 @@ import Typography from "@mui/material/Typography"; | |||||
import { usePathname } from "next/navigation"; | import { usePathname } from "next/navigation"; | ||||
import Link from "next/link"; | import Link from "next/link"; | ||||
import { NAVIGATION_CONTENT_WIDTH } from "@/config/uiConfig"; | import { NAVIGATION_CONTENT_WIDTH } from "@/config/uiConfig"; | ||||
import ArrowCircleLeftOutlinedIcon from '@mui/icons-material/ArrowCircleLeftOutlined'; | |||||
import ArrowCircleLeftRoundedIcon from '@mui/icons-material/ArrowCircleLeftRounded'; | |||||
import ArrowCircleLeftOutlinedIcon from "@mui/icons-material/ArrowCircleLeftOutlined"; | |||||
import ArrowCircleLeftRoundedIcon from "@mui/icons-material/ArrowCircleLeftRounded"; | |||||
interface NavigationItem { | interface NavigationItem { | ||||
icon: React.ReactNode; | icon: React.ReactNode; | ||||
@@ -34,17 +34,55 @@ interface NavigationItem { | |||||
const navigationItems: NavigationItem[] = [ | const navigationItems: NavigationItem[] = [ | ||||
{ icon: <WorkHistory />, label: "User Workspace", path: "/home" }, | { icon: <WorkHistory />, label: "User Workspace", path: "/home" }, | ||||
{ icon: <Dashboard />, label: "Dashboard", path: "", children: [ | |||||
{ icon: <SummarizeIcon />, label: "Project Financial Summary", path: "/dashboard/ProjectFinancialSummary" }, | |||||
{ icon: <PaymentsIcon />, label: "Company / Team Cash Flow", path: "/dashboard/CompanyTeamCashFlow" }, | |||||
{ icon: <PaymentsIcon />, label: "Project Cash Flow", path: "/dashboard/ProjectCashFlow" }, | |||||
{ icon: <AccountTreeIcon />, label: "Project Status by Client", path: "/dashboard/ProjectStatusByClient" }, | |||||
{ icon: <PeopleIcon />, label: "Staff Utilization", path: "/dashboard/StaffUtilization" }, | |||||
]}, | |||||
{ icon: <RequestQuote />, label: "Staff Reimbursement", path: "/staffReimbursement", children: [ | |||||
{ icon: <RequestQuote />, label: "ClaimApproval", path: "/staffReimbursement/ClaimApproval"}, | |||||
{ icon: <RequestQuote />, label: "ClaimSummary", path: "/staffReimbursement/ClaimSummary"} | |||||
] }, | |||||
{ | |||||
icon: <Dashboard />, | |||||
label: "Dashboard", | |||||
path: "", | |||||
children: [ | |||||
{ | |||||
icon: <SummarizeIcon />, | |||||
label: "Project Financial Summary", | |||||
path: "/dashboard/ProjectFinancialSummary", | |||||
}, | |||||
{ | |||||
icon: <PaymentsIcon />, | |||||
label: "Company / Team Cash Flow", | |||||
path: "/dashboard/CompanyTeamCashFlow", | |||||
}, | |||||
{ | |||||
icon: <PaymentsIcon />, | |||||
label: "Project Cash Flow", | |||||
path: "/dashboard/ProjectCashFlow", | |||||
}, | |||||
{ | |||||
icon: <AccountTreeIcon />, | |||||
label: "Project Status by Client", | |||||
path: "/dashboard/ProjectStatusByClient", | |||||
}, | |||||
{ | |||||
icon: <PeopleIcon />, | |||||
label: "Staff Utilization", | |||||
path: "/dashboard/StaffUtilization", | |||||
}, | |||||
], | |||||
}, | |||||
{ | |||||
icon: <RequestQuote />, | |||||
label: "Staff Reimbursement", | |||||
path: "/staffReimbursement", | |||||
children: [ | |||||
{ | |||||
icon: <RequestQuote />, | |||||
label: "ClaimApproval", | |||||
path: "/staffReimbursement/ClaimApproval", | |||||
}, | |||||
{ | |||||
icon: <RequestQuote />, | |||||
label: "ClaimSummary", | |||||
path: "/staffReimbursement/ClaimSummary", | |||||
}, | |||||
], | |||||
}, | |||||
{ icon: <Assignment />, label: "Project Management", path: "/projects" }, | { icon: <Assignment />, label: "Project Management", path: "/projects" }, | ||||
{ icon: <Task />, label: "Task Template", path: "/tasks" }, | { icon: <Task />, label: "Task Template", path: "/tasks" }, | ||||
{ icon: <Payments />, label: "Invoice", path: "/invoice" }, | { icon: <Payments />, label: "Invoice", path: "/invoice" }, | ||||
@@ -58,10 +96,10 @@ const NavigationContent: React.FC = () => { | |||||
const [openItems, setOpenItems] = React.useState<string[]>([]); | const [openItems, setOpenItems] = React.useState<string[]>([]); | ||||
const toggleItem = (path: string) => { | const toggleItem = (path: string) => { | ||||
setOpenItems(prevOpenItems => | |||||
setOpenItems((prevOpenItems) => | |||||
prevOpenItems.includes(path) | prevOpenItems.includes(path) | ||||
? prevOpenItems.filter(item => item !== path) | |||||
: [...prevOpenItems, path] | |||||
? prevOpenItems.filter((item) => item !== path) | |||||
: [...prevOpenItems, path], | |||||
); | ); | ||||
}; | }; | ||||
@@ -84,25 +122,27 @@ const NavigationContent: React.FC = () => { | |||||
</ListItemButton> | </ListItemButton> | ||||
{item.children && isOpen && ( | {item.children && isOpen && ( | ||||
<List sx={{ pl: 2 }}> | <List sx={{ pl: 2 }}> | ||||
{item.children.map(child => renderNavigationItem(child))} | |||||
{item.children.map((child) => renderNavigationItem(child))} | |||||
</List> | </List> | ||||
)} | )} | ||||
</Box> | </Box> | ||||
); | ); | ||||
}; | }; | ||||
return ( | return ( | ||||
<Box sx={{ width: NAVIGATION_CONTENT_WIDTH }}> | <Box sx={{ width: NAVIGATION_CONTENT_WIDTH }}> | ||||
<Box sx={{ p: "1.5rem" }}> | <Box sx={{ p: "1.5rem" }}> | ||||
{/* Replace this with company logo and/or name */} | {/* Replace this with company logo and/or name */} | ||||
<Typography style={{display:"inline-block"}}variant="h4">TSMS</Typography> | |||||
<Typography style={{ display: "inline-block" }} variant="h4"> | |||||
TSMS | |||||
</Typography> | |||||
{/* <button className="float-right bg-transparent border-transparent" > | {/* <button className="float-right bg-transparent border-transparent" > | ||||
<ArrowCircleLeftRoundedIcon className="text-slate-400 hover:text-blue-400 hover:cursor-pointer " style={{ fontSize: '35px' }} /> | <ArrowCircleLeftRoundedIcon className="text-slate-400 hover:text-blue-400 hover:cursor-pointer " style={{ fontSize: '35px' }} /> | ||||
</button> */} | </button> */} | ||||
</Box> | </Box> | ||||
<Divider /> | <Divider /> | ||||
<List component="nav"> | <List component="nav"> | ||||
{navigationItems.map(item => renderNavigationItem(item))} | |||||
{navigationItems.map((item) => renderNavigationItem(item))} | |||||
{/* {navigationItems.map(({ icon, label, path }, index) => { | {/* {navigationItems.map(({ icon, label, path }, index) => { | ||||
return ( | return ( | ||||
<Box | <Box | ||||
@@ -11,36 +11,155 @@ type PageTitleProps = { | |||||
FourthTitle?: string; | FourthTitle?: string; | ||||
}; | }; | ||||
const PageTitle: React.FC<PageTitleProps> = ({ BigTitle, SecondTitle = '', ThirdTitle = '', FourthTitle = ''}) => { | |||||
const PageTitle: React.FC<PageTitleProps> = ({ | |||||
BigTitle, | |||||
SecondTitle = "", | |||||
ThirdTitle = "", | |||||
FourthTitle = "", | |||||
}) => { | |||||
const { t } = useTranslation("dashboard"); | const { t } = useTranslation("dashboard"); | ||||
return ( | return ( | ||||
<Grid item sm> | |||||
<div style={{marginTop:20,marginLeft:20}}> | |||||
<h1 style={{display:"inline-block",color:"#636363",verticalAlign:"top"}}>{BigTitle}</h1> | |||||
<hr color="#D6DCE1" style={{display:"inline-block",width:1,height:35,marginTop:25}} /> | |||||
<h3 style={{display:"inline-block",color:"#6BAFD8",verticalAlign:"top",marginTop:32}}>Overview</h3> | |||||
<h3 style={{display:"inline-block",color:"#6E6B7B",verticalAlign:"top",marginTop:32}}>{">"}</h3> | |||||
<h3 style={{display:"inline-block",color:"#6E6B7B",verticalAlign:"top",marginTop:32}}>{BigTitle}</h3> | |||||
{SecondTitle !== '' ? | |||||
<h3 style={{display:"inline-block",color:"#6E6B7B",verticalAlign:"top",marginTop:32}}>{">"} </h3> | |||||
: ""} | |||||
{SecondTitle !== '' ? | |||||
<h3 style={{display:"inline-block",color:"#6E6B7B",verticalAlign:"top",marginTop:32}}>{SecondTitle} </h3> | |||||
: ""} | |||||
{ThirdTitle !== '' ? | |||||
<h3 style={{display:"inline-block",color:"#6E6B7B",verticalAlign:"top",marginTop:32}}>{">"} </h3> | |||||
: ""} | |||||
{ThirdTitle !== '' ? | |||||
<h3 style={{display:"inline-block",color:"#6E6B7B",verticalAlign:"top",marginTop:32}}>{ThirdTitle} </h3> | |||||
: ""} | |||||
{FourthTitle !== '' ? | |||||
<h3 style={{display:"inline-block",color:"#6E6B7B",verticalAlign:"top",marginTop:32}}>{">"} </h3> | |||||
: ""} | |||||
{FourthTitle !== '' ? | |||||
<h3 style={{display:"inline-block",color:"#6E6B7B",verticalAlign:"top",marginTop:32}}>{FourthTitle} </h3> | |||||
: ""} | |||||
</div> | |||||
</Grid> | |||||
<Grid item sm> | |||||
<div style={{ marginTop: 20, marginLeft: 20 }}> | |||||
<h1 | |||||
style={{ | |||||
display: "inline-block", | |||||
color: "#636363", | |||||
verticalAlign: "top", | |||||
}} | |||||
> | |||||
{BigTitle} | |||||
</h1> | |||||
| |||||
<hr | |||||
color="#D6DCE1" | |||||
style={{ | |||||
display: "inline-block", | |||||
width: 1, | |||||
height: 35, | |||||
marginTop: 25, | |||||
}} | |||||
/> | |||||
| |||||
<h3 | |||||
style={{ | |||||
display: "inline-block", | |||||
color: "#6BAFD8", | |||||
verticalAlign: "top", | |||||
marginTop: 32, | |||||
}} | |||||
> | |||||
Overview | |||||
</h3> | |||||
| |||||
<h3 | |||||
style={{ | |||||
display: "inline-block", | |||||
color: "#6E6B7B", | |||||
verticalAlign: "top", | |||||
marginTop: 32, | |||||
}} | |||||
> | |||||
{">"} | |||||
</h3> | |||||
| |||||
<h3 | |||||
style={{ | |||||
display: "inline-block", | |||||
color: "#6E6B7B", | |||||
verticalAlign: "top", | |||||
marginTop: 32, | |||||
}} | |||||
> | |||||
{BigTitle} | |||||
</h3> | |||||
| |||||
{SecondTitle !== "" ? ( | |||||
<h3 | |||||
style={{ | |||||
display: "inline-block", | |||||
color: "#6E6B7B", | |||||
verticalAlign: "top", | |||||
marginTop: 32, | |||||
}} | |||||
> | |||||
{">"} | |||||
</h3> | |||||
) : ( | |||||
"" | |||||
)} | |||||
{SecondTitle !== "" ? ( | |||||
<h3 | |||||
style={{ | |||||
display: "inline-block", | |||||
color: "#6E6B7B", | |||||
verticalAlign: "top", | |||||
marginTop: 32, | |||||
}} | |||||
> | |||||
{SecondTitle} | |||||
</h3> | |||||
) : ( | |||||
"" | |||||
)} | |||||
{ThirdTitle !== "" ? ( | |||||
<h3 | |||||
style={{ | |||||
display: "inline-block", | |||||
color: "#6E6B7B", | |||||
verticalAlign: "top", | |||||
marginTop: 32, | |||||
}} | |||||
> | |||||
{">"} | |||||
</h3> | |||||
) : ( | |||||
"" | |||||
)} | |||||
{ThirdTitle !== "" ? ( | |||||
<h3 | |||||
style={{ | |||||
display: "inline-block", | |||||
color: "#6E6B7B", | |||||
verticalAlign: "top", | |||||
marginTop: 32, | |||||
}} | |||||
> | |||||
{ThirdTitle} | |||||
</h3> | |||||
) : ( | |||||
"" | |||||
)} | |||||
{FourthTitle !== "" ? ( | |||||
<h3 | |||||
style={{ | |||||
display: "inline-block", | |||||
color: "#6E6B7B", | |||||
verticalAlign: "top", | |||||
marginTop: 32, | |||||
}} | |||||
> | |||||
{">"} | |||||
</h3> | |||||
) : ( | |||||
"" | |||||
)} | |||||
{FourthTitle !== "" ? ( | |||||
<h3 | |||||
style={{ | |||||
display: "inline-block", | |||||
color: "#6E6B7B", | |||||
verticalAlign: "top", | |||||
marginTop: 32, | |||||
}} | |||||
> | |||||
{FourthTitle} | |||||
</h3> | |||||
) : ( | |||||
"" | |||||
)} | |||||
</div> | |||||
</Grid> | |||||
); | ); | ||||
}; | }; | ||||
@@ -1,84 +1,175 @@ | |||||
"use client"; | "use client"; | ||||
import * as React from "react"; | import * as React from "react"; | ||||
import Grid from "@mui/material/Grid"; | import Grid from "@mui/material/Grid"; | ||||
import { useState,useEffect, useMemo } from 'react' | |||||
import { useState, useEffect, useMemo } from "react"; | |||||
import Paper from "@mui/material/Paper"; | import Paper from "@mui/material/Paper"; | ||||
import { TFunction } from "i18next"; | import { TFunction } from "i18next"; | ||||
import { useTranslation } from "react-i18next"; | import { useTranslation } from "react-i18next"; | ||||
import {Card,CardHeader} from '@mui/material'; | |||||
import { Card, CardHeader } from "@mui/material"; | |||||
import CustomSearchForm from "../CustomSearchForm/CustomSearchForm"; | import CustomSearchForm from "../CustomSearchForm/CustomSearchForm"; | ||||
import CustomDatagrid from '../CustomDatagrid/CustomDatagrid'; | |||||
import ReactApexChart from 'react-apexcharts'; | |||||
import { ApexOptions } from 'apexcharts'; | |||||
import { GridColDef, GridRowSelectionModel} from '@mui/x-data-grid'; | |||||
import ReportProblemIcon from '@mui/icons-material/ReportProblem'; | |||||
import dynamic from 'next/dynamic'; | |||||
import '../../app/global.css'; | |||||
import CustomDatagrid from "../CustomDatagrid/CustomDatagrid"; | |||||
import ReactApexChart from "react-apexcharts"; | |||||
import { ApexOptions } from "apexcharts"; | |||||
import { GridColDef, GridRowSelectionModel } from "@mui/x-data-grid"; | |||||
import ReportProblemIcon from "@mui/icons-material/ReportProblem"; | |||||
import dynamic from "next/dynamic"; | |||||
import "../../app/global.css"; | |||||
import { AnyARecord, AnyCnameRecord } from "dns"; | import { AnyARecord, AnyCnameRecord } from "dns"; | ||||
import SearchBox, { Criterion } from "../SearchBox"; | import SearchBox, { Criterion } from "../SearchBox"; | ||||
import ProgressByClientSearch from "@/components/ProgressByClientSearch"; | import ProgressByClientSearch from "@/components/ProgressByClientSearch"; | ||||
import { Suspense } from "react"; | import { Suspense } from "react"; | ||||
const ProgressByClient: React.FC = () => { | const ProgressByClient: React.FC = () => { | ||||
const [activeTab, setActiveTab] = useState('financialSummary'); | |||||
const [SearchCriteria, setSearchCriteria] = React.useState({}) | |||||
const [activeTab, setActiveTab] = useState("financialSummary"); | |||||
const [SearchCriteria, setSearchCriteria] = React.useState({}); | |||||
const { t } = useTranslation("dashboard"); | const { t } = useTranslation("dashboard"); | ||||
const [clientCode, setClientCode] = useState(''); | |||||
const [clientName, setClientName] = useState(''); | |||||
const [subsidiaryClientCode, setSubsidiaryClientCode] = useState(''); | |||||
const [subsidiaryClientName, setSubsidiaryClientName] = useState(''); | |||||
const [projectArray, setProjectArray] : any[] = useState([]); | |||||
const [percentageArray, setPercentageArray] : any[] = useState([]); | |||||
const [colorArray, setColorArray] : any[] = useState([]); | |||||
const [selectionModel, setSelectionModel] : any[] = React.useState([]); | |||||
const [pieChartColor, setPieChartColor] : any[] = React.useState([]); | |||||
const [totalSpentPercentage, setTotalSpentPercentage] : any = React.useState(); | |||||
const [projectBudgetManhour, setProjectBudgetManhour] :any = React.useState('-'); | |||||
const [actualManhourSpent, setActualManhourSpent] :any = React.useState('-'); | |||||
const [remainedManhour, setRemainedManhour] :any = React.useState('-'); | |||||
const [lastUpdate, setLastUpdate] :any = React.useState('-'); | |||||
const [dropdownDemo, setDropdownDemo] = useState(''); | |||||
const [clientCode, setClientCode] = useState(""); | |||||
const [clientName, setClientName] = useState(""); | |||||
const [subsidiaryClientCode, setSubsidiaryClientCode] = useState(""); | |||||
const [subsidiaryClientName, setSubsidiaryClientName] = useState(""); | |||||
const [projectArray, setProjectArray]: any[] = useState([]); | |||||
const [percentageArray, setPercentageArray]: any[] = useState([]); | |||||
const [colorArray, setColorArray]: any[] = useState([]); | |||||
const [selectionModel, setSelectionModel]: any[] = React.useState([]); | |||||
const [pieChartColor, setPieChartColor]: any[] = React.useState([]); | |||||
const [totalSpentPercentage, setTotalSpentPercentage]: any = React.useState(); | |||||
const [projectBudgetManhour, setProjectBudgetManhour]: any = | |||||
React.useState("-"); | |||||
const [actualManhourSpent, setActualManhourSpent]: any = React.useState("-"); | |||||
const [remainedManhour, setRemainedManhour]: any = React.useState("-"); | |||||
const [lastUpdate, setLastUpdate]: any = React.useState("-"); | |||||
const [dropdownDemo, setDropdownDemo] = useState(""); | |||||
const [dateDemo, setDateDemo] = useState(null); | const [dateDemo, setDateDemo] = useState(null); | ||||
const [checkboxDemo, setCheckboxDemo] = useState(false); | const [checkboxDemo, setCheckboxDemo] = useState(false); | ||||
const [receiptFromDate, setReceiptFromDate] = useState(null); | const [receiptFromDate, setReceiptFromDate] = useState(null); | ||||
const [receiptToDate, setReceiptToDate] = useState(null); | const [receiptToDate, setReceiptToDate] = useState(null); | ||||
const [selectedRows, setSelectedRows] = useState([]); | const [selectedRows, setSelectedRows] = useState([]); | ||||
const rows = [{id: 1,clientCode:"CUST-001",clientName:"Client A", clientSubsidiaryCode:"N/A", clientSubsidiaryName:"N/A", noOfProjects:"5"}, | |||||
{id: 2,clientCode:"CUST-001",clientName:"Client A", clientSubsidiaryCode:"SUBS-001", clientSubsidiaryName:"Subsidiary A", noOfProjects:"5"}, | |||||
{id: 3,clientCode:"CUST-001",clientName:"Client A", clientSubsidiaryCode:"SUBS-002", clientSubsidiaryName:"Subsidiary B", noOfProjects:"3"}, | |||||
{id: 4,clientCode:"CUST-001",clientName:"Client A", clientSubsidiaryCode:"SUBS-003", clientSubsidiaryName:"Subsidiary C", noOfProjects:"1"} | |||||
] | |||||
const rows = [ | |||||
{ | |||||
id: 1, | |||||
clientCode: "CUST-001", | |||||
clientName: "Client A", | |||||
clientSubsidiaryCode: "N/A", | |||||
clientSubsidiaryName: "N/A", | |||||
noOfProjects: "5", | |||||
}, | |||||
{ | |||||
id: 2, | |||||
clientCode: "CUST-001", | |||||
clientName: "Client A", | |||||
clientSubsidiaryCode: "SUBS-001", | |||||
clientSubsidiaryName: "Subsidiary A", | |||||
noOfProjects: "5", | |||||
}, | |||||
{ | |||||
id: 3, | |||||
clientCode: "CUST-001", | |||||
clientName: "Client A", | |||||
clientSubsidiaryCode: "SUBS-002", | |||||
clientSubsidiaryName: "Subsidiary B", | |||||
noOfProjects: "3", | |||||
}, | |||||
{ | |||||
id: 4, | |||||
clientCode: "CUST-001", | |||||
clientName: "Client A", | |||||
clientSubsidiaryCode: "SUBS-003", | |||||
clientSubsidiaryName: "Subsidiary C", | |||||
noOfProjects: "1", | |||||
}, | |||||
]; | |||||
//['#f57f90', '#94f7d6', '#87c5f5', '#ab95f5', '#fcd68b'] | //['#f57f90', '#94f7d6', '#87c5f5', '#ab95f5', '#fcd68b'] | ||||
const rows2 = [{id: 1,project:"Consultancy Project 123",team:"XXX", teamLeader:"XXX", currentStage:"Contract Documentation", budgetedManhour:"200.00",spentManhour:"120.00",remainedManhour:"80.00",comingPaymentMilestone:"31/03/2024",alert:false,color:"#f57f90"}, | |||||
{id: 2,project:"Consultancy Project 456",team:"XXX", teamLeader:"XXX", currentStage:"Report Preparation", budgetedManhour:"400.00",spentManhour:"200.00",remainedManhour:"200.00",comingPaymentMilestone:"20/02/2024",alert:false,color:"#94f7d6"}, | |||||
{id: 3,project:"Construction Project A",team:"YYY", teamLeader:"YYY", currentStage:"Construction", budgetedManhour:"187.50",spentManhour:"200.00",remainedManhour:"12.50",comingPaymentMilestone:"13/12/2023",alert:true,color:"#87c5f5"}, | |||||
{id: 4,project:"Construction Project B",team:"XXX", teamLeader:"XXX", currentStage:"Post Construction", budgetedManhour:"100.00",spentManhour:"40.00",remainedManhour:"60.00",comingPaymentMilestone:"05/01/2024",alert:false,color:"#ab95f5"}, | |||||
{id: 5,project:"Construction Project C",team:"YYY", teamLeader:"YYY", currentStage:"Construction", budgetedManhour:"300.00",spentManhour:"150.00",remainedManhour:"150.00",comingPaymentMilestone:"31/03/2024",alert:false,color:"#fcd68b"}, | |||||
] | |||||
const rows2 = [ | |||||
{ | |||||
id: 1, | |||||
project: "Consultancy Project 123", | |||||
team: "XXX", | |||||
teamLeader: "XXX", | |||||
currentStage: "Contract Documentation", | |||||
budgetedManhour: "200.00", | |||||
spentManhour: "120.00", | |||||
remainedManhour: "80.00", | |||||
comingPaymentMilestone: "31/03/2024", | |||||
alert: false, | |||||
color: "#f57f90", | |||||
}, | |||||
{ | |||||
id: 2, | |||||
project: "Consultancy Project 456", | |||||
team: "XXX", | |||||
teamLeader: "XXX", | |||||
currentStage: "Report Preparation", | |||||
budgetedManhour: "400.00", | |||||
spentManhour: "200.00", | |||||
remainedManhour: "200.00", | |||||
comingPaymentMilestone: "20/02/2024", | |||||
alert: false, | |||||
color: "#94f7d6", | |||||
}, | |||||
{ | |||||
id: 3, | |||||
project: "Construction Project A", | |||||
team: "YYY", | |||||
teamLeader: "YYY", | |||||
currentStage: "Construction", | |||||
budgetedManhour: "187.50", | |||||
spentManhour: "200.00", | |||||
remainedManhour: "12.50", | |||||
comingPaymentMilestone: "13/12/2023", | |||||
alert: true, | |||||
color: "#87c5f5", | |||||
}, | |||||
{ | |||||
id: 4, | |||||
project: "Construction Project B", | |||||
team: "XXX", | |||||
teamLeader: "XXX", | |||||
currentStage: "Post Construction", | |||||
budgetedManhour: "100.00", | |||||
spentManhour: "40.00", | |||||
remainedManhour: "60.00", | |||||
comingPaymentMilestone: "05/01/2024", | |||||
alert: false, | |||||
color: "#ab95f5", | |||||
}, | |||||
{ | |||||
id: 5, | |||||
project: "Construction Project C", | |||||
team: "YYY", | |||||
teamLeader: "YYY", | |||||
currentStage: "Construction", | |||||
budgetedManhour: "300.00", | |||||
spentManhour: "150.00", | |||||
remainedManhour: "150.00", | |||||
comingPaymentMilestone: "31/03/2024", | |||||
alert: false, | |||||
color: "#fcd68b", | |||||
}, | |||||
]; | |||||
const columns = [ | const columns = [ | ||||
{ | |||||
id: 'clientCode', | |||||
field: 'clientCode', | |||||
headerName: "Client Code", | |||||
flex: 1, | |||||
{ | |||||
id: "clientCode", | |||||
field: "clientCode", | |||||
headerName: "Client Code", | |||||
flex: 1, | |||||
}, | }, | ||||
{ | { | ||||
id: 'clientName', | |||||
field: 'clientName', | |||||
headerName: "Client Name", | |||||
flex: 1, | |||||
id: "clientName", | |||||
field: "clientName", | |||||
headerName: "Client Name", | |||||
flex: 1, | |||||
}, | }, | ||||
{ | { | ||||
id: 'clientSubsidiaryCode', | |||||
field: 'clientSubsidiaryCode', | |||||
id: "clientSubsidiaryCode", | |||||
field: "clientSubsidiaryCode", | |||||
headerName: "Client Subsidiary Code", | headerName: "Client Subsidiary Code", | ||||
flex: 1, | flex: 1, | ||||
}, | }, | ||||
{ | { | ||||
id: 'noOfProjects', | |||||
field: 'noOfProjects', | |||||
id: "noOfProjects", | |||||
field: "noOfProjects", | |||||
headerName: "No. of Projects", | headerName: "No. of Projects", | ||||
flex: 1, | flex: 1, | ||||
}, | }, | ||||
@@ -86,110 +177,139 @@ const ProgressByClient: React.FC = () => { | |||||
const columns2 = [ | const columns2 = [ | ||||
{ | { | ||||
id:"color", | |||||
field:'color', | |||||
headerName:'', | |||||
renderCell: (params:any) => { | |||||
id: "color", | |||||
field: "color", | |||||
headerName: "", | |||||
renderCell: (params: any) => { | |||||
return ( | return ( | ||||
<span className="dot" style={{height:"15px",width:"15px",borderRadius:"50%",backgroundColor:`${params.row.color}`,display:"inline-block"}}></span> | |||||
) | |||||
<span | |||||
className="dot" | |||||
style={{ | |||||
height: "15px", | |||||
width: "15px", | |||||
borderRadius: "50%", | |||||
backgroundColor: `${params.row.color}`, | |||||
display: "inline-block", | |||||
}} | |||||
></span> | |||||
); | |||||
}, | }, | ||||
flex:0.1, | |||||
flex: 0.1, | |||||
}, | }, | ||||
{ | { | ||||
id: 'project', | |||||
field: 'project', | |||||
id: "project", | |||||
field: "project", | |||||
headerName: "Project", | headerName: "Project", | ||||
flex: 1, | flex: 1, | ||||
}, | |||||
{ | |||||
id: 'team', | |||||
field: 'team', | |||||
}, | |||||
{ | |||||
id: "team", | |||||
field: "team", | |||||
headerName: "Team", | headerName: "Team", | ||||
flex: 0.8, | flex: 0.8, | ||||
}, | |||||
{ | |||||
id: 'teamLeader', | |||||
field: 'teamLeader', | |||||
headerName: "Team Leader", | |||||
flex: 0.8, | |||||
}, | |||||
{ | |||||
id: 'currentStage', | |||||
field: 'currentStage', | |||||
headerName: "Current Stage", | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: 'budgetedManhour', | |||||
field: 'budgetedManhour', | |||||
headerName: "Budgeted Manhour", | |||||
flex: 0.8, | |||||
}, | |||||
{ | |||||
id: 'spentManhour', | |||||
field: 'spentManhour', | |||||
headerName: "Spent Manhour", | |||||
renderCell: (params:any) => { | |||||
if (params.row.budgetedManhour - params.row.spentManhour <= 0) { | |||||
return( | |||||
<span className="text-red-300">{params.row.spentManhour}</span> | |||||
) | |||||
} else { | |||||
return ( | |||||
<span>{params.row.spentManhour}</span> | |||||
) | |||||
} | |||||
}, | }, | ||||
flex: 0.8, | |||||
}, | |||||
{ | |||||
id: 'remainedManhour', | |||||
field: 'remainedManhour', | |||||
headerName: "Remained Manhour", | |||||
renderCell: (params:any) => { | |||||
if (params.row.budgetedManhour - params.row.spentManhour <= 0) { | |||||
return( | |||||
<span className="text-red-300">({params.row.remainedManhour})</span> | |||||
) | |||||
} else { | |||||
return ( | |||||
<span>{params.row.remainedManhour}</span> | |||||
) | |||||
} | |||||
{ | |||||
id: "teamLeader", | |||||
field: "teamLeader", | |||||
headerName: "Team Leader", | |||||
flex: 0.8, | |||||
}, | }, | ||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: 'comingPaymentMilestone', | |||||
field: 'comingPaymentMilestone', | |||||
headerName: "Coming Payment Milestone", | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: 'alert', | |||||
field: 'alert', | |||||
headerName: "Alert", | |||||
renderCell: (params:any) => { | |||||
if (params.row.alert === true) { | |||||
return ( | |||||
<span className="text-red-300 text-center"><ReportProblemIcon/></span> | |||||
) | |||||
} else { | |||||
return ( | |||||
<span></span> | |||||
) | |||||
} | |||||
{ | |||||
id: "currentStage", | |||||
field: "currentStage", | |||||
headerName: "Current Stage", | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: "budgetedManhour", | |||||
field: "budgetedManhour", | |||||
headerName: "Budgeted Manhour", | |||||
flex: 0.8, | |||||
}, | }, | ||||
flex: 0.2, | |||||
}, | |||||
]; | |||||
{ | |||||
id: "spentManhour", | |||||
field: "spentManhour", | |||||
headerName: "Spent Manhour", | |||||
renderCell: (params: any) => { | |||||
if (params.row.budgetedManhour - params.row.spentManhour <= 0) { | |||||
return ( | |||||
<span className="text-red-300">{params.row.spentManhour}</span> | |||||
); | |||||
} else { | |||||
return <span>{params.row.spentManhour}</span>; | |||||
} | |||||
}, | |||||
flex: 0.8, | |||||
}, | |||||
{ | |||||
id: "remainedManhour", | |||||
field: "remainedManhour", | |||||
headerName: "Remained Manhour", | |||||
renderCell: (params: any) => { | |||||
if (params.row.budgetedManhour - params.row.spentManhour <= 0) { | |||||
return ( | |||||
<span className="text-red-300">({params.row.remainedManhour})</span> | |||||
); | |||||
} else { | |||||
return <span>{params.row.remainedManhour}</span>; | |||||
} | |||||
}, | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: "comingPaymentMilestone", | |||||
field: "comingPaymentMilestone", | |||||
headerName: "Coming Payment Milestone", | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: "alert", | |||||
field: "alert", | |||||
headerName: "Alert", | |||||
renderCell: (params: any) => { | |||||
if (params.row.alert === true) { | |||||
return ( | |||||
<span className="text-red-300 text-center"> | |||||
<ReportProblemIcon /> | |||||
</span> | |||||
); | |||||
} else { | |||||
return <span></span>; | |||||
} | |||||
}, | |||||
flex: 0.2, | |||||
}, | |||||
]; | |||||
const InputFields = [ | const InputFields = [ | ||||
{ id: "clientCode", label: "Client Code", type: 'text', value: clientCode, setValue: setClientCode }, | |||||
{ id: "clientName", label: "Client Name", type: 'text', value: clientName, setValue: setClientName }, | |||||
{ id: "subsidiaryClientCode", label: "Subsidiary Client Code", type:'text', value:subsidiaryClientCode, setValue: setSubsidiaryClientCode}, | |||||
{ id: "subsidiaryClientName", label: "Subsidiary Client Name", type:'text', value:subsidiaryClientName, setValue: setSubsidiaryClientName}, | |||||
{ | |||||
id: "clientCode", | |||||
label: "Client Code", | |||||
type: "text", | |||||
value: clientCode, | |||||
setValue: setClientCode, | |||||
}, | |||||
{ | |||||
id: "clientName", | |||||
label: "Client Name", | |||||
type: "text", | |||||
value: clientName, | |||||
setValue: setClientName, | |||||
}, | |||||
{ | |||||
id: "subsidiaryClientCode", | |||||
label: "Subsidiary Client Code", | |||||
type: "text", | |||||
value: subsidiaryClientCode, | |||||
setValue: setSubsidiaryClientCode, | |||||
}, | |||||
{ | |||||
id: "subsidiaryClientName", | |||||
label: "Subsidiary Client Name", | |||||
type: "text", | |||||
value: subsidiaryClientName, | |||||
setValue: setSubsidiaryClientName, | |||||
}, | |||||
// { id: 'dropdownDemo', label: "dropdownDemo", type: 'dropdown', options: [{id:"1", label:"1"}], value: dropdownDemo, setValue: setDropdownDemo }, | // { id: 'dropdownDemo', label: "dropdownDemo", type: 'dropdown', options: [{id:"1", label:"1"}], value: dropdownDemo, setValue: setDropdownDemo }, | ||||
// { id: 'dateDemo', label:'dateDemo', type: 'date', value: dateDemo, setValue: setDateDemo }, | // { id: 'dateDemo', label:'dateDemo', type: 'date', value: dateDemo, setValue: setDateDemo }, | ||||
// { id: 'checkboxDemo', label:'checkboxDemo', type: 'checkbox', value: checkboxDemo, setValue: setCheckboxDemo }, | // { id: 'checkboxDemo', label:'checkboxDemo', type: 'checkbox', value: checkboxDemo, setValue: setCheckboxDemo }, | ||||
@@ -197,73 +317,85 @@ const ProgressByClient: React.FC = () => { | |||||
// setValue: [setReceiptFromDate, setReceiptToDate],type: 'dateRange' }, | // setValue: [setReceiptFromDate, setReceiptToDate],type: 'dateRange' }, | ||||
]; | ]; | ||||
const stageDeadline = ["31/03/2024","20/02/2024","01/12/2023","05/01/2024","31/03/2023"] | |||||
const stageDeadline = [ | |||||
"31/03/2024", | |||||
"20/02/2024", | |||||
"01/12/2023", | |||||
"05/01/2024", | |||||
"31/03/2023", | |||||
]; | |||||
const series2: ApexAxisChartSeries | ApexNonAxisChartSeries = [ | |||||
{ | |||||
data: [17.1, 28.6, 5.7, 48.6], | |||||
}, | |||||
]; | |||||
const series2: ApexAxisChartSeries | ApexNonAxisChartSeries = [{ | |||||
data: [17.1, 28.6, 5.7, 48.6], | |||||
}]; | |||||
const series: ApexAxisChartSeries | ApexNonAxisChartSeries = [ | |||||
{ | |||||
name: "Current Stage Completion Percentage", | |||||
data: [80, 55, 40, 65, 70], | |||||
}, | |||||
]; | |||||
const series: ApexAxisChartSeries | ApexNonAxisChartSeries = [{ | |||||
name: 'Current Stage Completion Percentage', | |||||
data: [80, 55, 40, 65, 70], | |||||
}]; | |||||
const options2 : ApexOptions = { | |||||
const options2: ApexOptions = { | |||||
chart: { | chart: { | ||||
type: 'donut', | |||||
type: "donut", | |||||
}, | }, | ||||
colors: colorArray, | colors: colorArray, | ||||
plotOptions: { | plotOptions: { | ||||
pie: { | pie: { | ||||
donut:{ | |||||
labels:{ | |||||
show:true, | |||||
name:{ | |||||
show:true, | |||||
donut: { | |||||
labels: { | |||||
show: true, | |||||
name: { | |||||
show: true, | |||||
}, | }, | ||||
value:{ | |||||
show:true, | |||||
value: { | |||||
show: true, | |||||
fontWeight: 500, | fontWeight: 500, | ||||
fontSize: '30px', | |||||
fontSize: "30px", | |||||
color: "#3e98c7", | color: "#3e98c7", | ||||
}, | }, | ||||
total:{ | |||||
total: { | |||||
show: true, | show: true, | ||||
showAlways: true, | showAlways: true, | ||||
label: 'Spent', | |||||
fontFamily: 'sans-serif', | |||||
label: "Spent", | |||||
fontFamily: "sans-serif", | |||||
formatter: function (val) { | formatter: function (val) { | ||||
return totalSpentPercentage + "%" | |||||
} | |||||
} | |||||
} | |||||
} | |||||
return totalSpentPercentage + "%"; | |||||
}, | |||||
}, | |||||
}, | |||||
}, | |||||
}, | }, | ||||
}, | }, | ||||
labels: projectArray, | labels: projectArray, | ||||
legend: { | legend: { | ||||
show: false, | show: false, | ||||
}, | }, | ||||
responsive: [{ | |||||
breakpoint: 480, | |||||
options: { | |||||
chart: { | |||||
width: 200 | |||||
responsive: [ | |||||
{ | |||||
breakpoint: 480, | |||||
options: { | |||||
chart: { | |||||
width: 200, | |||||
}, | |||||
legend: { | |||||
position: "bottom", | |||||
show: false, | |||||
}, | |||||
}, | }, | ||||
legend: { | |||||
position: 'bottom', | |||||
show:false | |||||
} | |||||
} | |||||
}] | |||||
} | |||||
}, | |||||
], | |||||
}; | |||||
const options: ApexOptions = { | const options: ApexOptions = { | ||||
chart: { | chart: { | ||||
type: 'bar', | |||||
height: 350 | |||||
type: "bar", | |||||
height: 350, | |||||
}, | }, | ||||
colors: ['#f57f90', '#94f7d6', '#87c5f5', '#ab95f5', '#fcd68b'], | |||||
colors: ["#f57f90", "#94f7d6", "#87c5f5", "#ab95f5", "#fcd68b"], | |||||
plotOptions: { | plotOptions: { | ||||
bar: { | bar: { | ||||
horizontal: true, | horizontal: true, | ||||
@@ -271,107 +403,116 @@ const ProgressByClient: React.FC = () => { | |||||
}, | }, | ||||
}, | }, | ||||
dataLabels: { | dataLabels: { | ||||
enabled: false | |||||
enabled: false, | |||||
}, | }, | ||||
xaxis: { | xaxis: { | ||||
categories: [ | categories: [ | ||||
'Consultancy Project 123', | |||||
'Consultancy Project 456', | |||||
'Construction Project A', | |||||
'Construction Project B', | |||||
'Construction Project C', | |||||
"Consultancy Project 123", | |||||
"Consultancy Project 456", | |||||
"Construction Project A", | |||||
"Construction Project B", | |||||
"Construction Project C", | |||||
], | ], | ||||
}, | }, | ||||
yaxis: { | yaxis: { | ||||
title: { | title: { | ||||
text: 'Projects' | |||||
text: "Projects", | |||||
}, | }, | ||||
labels: { | labels: { | ||||
maxWidth: 200, | |||||
maxWidth: 200, | |||||
style: { | style: { | ||||
cssClass: 'apexcharts-yaxis-label', | |||||
cssClass: "apexcharts-yaxis-label", | |||||
}, | }, | ||||
}, | }, | ||||
}, | }, | ||||
title: { | title: { | ||||
text: 'Current Stage Completion Percentage', | |||||
align: 'center' | |||||
text: "Current Stage Completion Percentage", | |||||
align: "center", | |||||
}, | }, | ||||
grid: { | grid: { | ||||
borderColor: '#f1f1f1', | |||||
borderColor: "#f1f1f1", | |||||
}, | }, | ||||
annotations: { | |||||
} | |||||
annotations: {}, | |||||
}; | }; | ||||
const handleSelectionChange = (newSelectionModel: GridRowSelectionModel) => { | const handleSelectionChange = (newSelectionModel: GridRowSelectionModel) => { | ||||
const selectedRowsData = rows2.filter((row) => | const selectedRowsData = rows2.filter((row) => | ||||
newSelectionModel.includes(row.id) | |||||
newSelectionModel.includes(row.id), | |||||
); | ); | ||||
console.log(selectedRowsData) | |||||
const projectArray = [] | |||||
const pieChartColorArray = [] | |||||
let totalSpent = 0 | |||||
let totalBudgetManhour = 0 | |||||
const percentageArray = [] | |||||
console.log(selectedRowsData); | |||||
const projectArray = []; | |||||
const pieChartColorArray = []; | |||||
let totalSpent = 0; | |||||
let totalBudgetManhour = 0; | |||||
const percentageArray = []; | |||||
for (let i = 0; i <= selectedRowsData.length; i++) { | for (let i = 0; i <= selectedRowsData.length; i++) { | ||||
if (i === selectedRowsData.length && i > 0) { | if (i === selectedRowsData.length && i > 0) { | ||||
projectArray.push("Remained") | |||||
projectArray.push("Remained"); | |||||
} else if (selectedRowsData.length > 0) { | } else if (selectedRowsData.length > 0) { | ||||
projectArray.push(selectedRowsData[i].project) | |||||
totalBudgetManhour += Number(selectedRowsData[i].budgetedManhour) | |||||
totalSpent += Number(selectedRowsData[i].spentManhour) | |||||
pieChartColorArray.push(selectedRowsData[i].color) | |||||
projectArray.push(selectedRowsData[i].project); | |||||
totalBudgetManhour += Number(selectedRowsData[i].budgetedManhour); | |||||
totalSpent += Number(selectedRowsData[i].spentManhour); | |||||
pieChartColorArray.push(selectedRowsData[i].color); | |||||
} | } | ||||
} | } | ||||
for (let i = 0; i <= selectedRowsData.length; i++) { | for (let i = 0; i <= selectedRowsData.length; i++) { | ||||
if (i === selectedRowsData.length && i > 0) { | if (i === selectedRowsData.length && i > 0) { | ||||
const remainedManhour = (totalBudgetManhour - totalSpent) | |||||
percentageArray.push(Number(((remainedManhour / totalBudgetManhour) * 100).toFixed(1))) | |||||
const remainedManhour = totalBudgetManhour - totalSpent; | |||||
percentageArray.push( | |||||
Number(((remainedManhour / totalBudgetManhour) * 100).toFixed(1)), | |||||
); | |||||
} else if (selectedRowsData.length > 0) { | } else if (selectedRowsData.length > 0) { | ||||
let percentage = ((Number(selectedRowsData[i].spentManhour) / totalBudgetManhour) * 100).toFixed(1) | |||||
percentageArray.push(Number(percentage)) | |||||
const percentage = ( | |||||
(Number(selectedRowsData[i].spentManhour) / totalBudgetManhour) * | |||||
100 | |||||
).toFixed(1); | |||||
percentageArray.push(Number(percentage)); | |||||
} | } | ||||
} | } | ||||
setProjectBudgetManhour(totalBudgetManhour.toFixed(2)) | |||||
setActualManhourSpent(totalSpent.toFixed(2)) | |||||
setRemainedManhour((totalBudgetManhour - totalSpent).toFixed(2)) | |||||
setLastUpdate(new Date().toLocaleDateString('en-GB')) | |||||
setSelectionModel(newSelectionModel) | |||||
console.log(projectArray) | |||||
setProjectArray(projectArray) | |||||
setPercentageArray(percentageArray) | |||||
console.log(percentageArray) | |||||
setTotalSpentPercentage(((totalSpent/totalBudgetManhour)*100).toFixed(1)) | |||||
setProjectBudgetManhour(totalBudgetManhour.toFixed(2)); | |||||
setActualManhourSpent(totalSpent.toFixed(2)); | |||||
setRemainedManhour((totalBudgetManhour - totalSpent).toFixed(2)); | |||||
setLastUpdate(new Date().toLocaleDateString("en-GB")); | |||||
setSelectionModel(newSelectionModel); | |||||
console.log(projectArray); | |||||
setProjectArray(projectArray); | |||||
setPercentageArray(percentageArray); | |||||
console.log(percentageArray); | |||||
setTotalSpentPercentage( | |||||
((totalSpent / totalBudgetManhour) * 100).toFixed(1), | |||||
); | |||||
if (projectArray.length > 0 && projectArray.includes("Remained")) { | if (projectArray.length > 0 && projectArray.includes("Remained")) { | ||||
const nonLastRecordColors = pieChartColorArray; | const nonLastRecordColors = pieChartColorArray; | ||||
setColorArray([...nonLastRecordColors.slice(0, projectArray.length - 1), "#a3a3a3"]); | |||||
setColorArray([ | |||||
...nonLastRecordColors.slice(0, projectArray.length - 1), | |||||
"#a3a3a3", | |||||
]); | |||||
} else { | } else { | ||||
setColorArray(pieChartColorArray); | setColorArray(pieChartColorArray); | ||||
} | } | ||||
}; | }; | ||||
const applySearch = (data: any) => { | const applySearch = (data: any) => { | ||||
console.log(data) | |||||
setSearchCriteria(data) | |||||
} | |||||
console.log(data); | |||||
setSearchCriteria(data); | |||||
}; | |||||
return ( | return ( | ||||
<Grid item sm> | |||||
{/* <CustomSearchForm applySearch={applySearch} fields={InputFields}/> */} | |||||
{/* <CustomDatagrid rows={rows} columns={columns} columnWidth={200} dataGridHeight={300}/> */} | |||||
<div style={{display:"inline-block",width:"70%"}}> | |||||
<Grid item xs={12} md={12} lg={12}> | |||||
<Card> | |||||
<CardHeader className="text-slate-500" title="Project Progress"/> | |||||
<div style={{display:"inline-block",width:"99%"}}> | |||||
<ReactApexChart | |||||
options={options} | |||||
series={series} | |||||
type="bar" | |||||
height={350} | |||||
/> | |||||
</div> | |||||
{/* <div style={{display:"inline-block",width:"20%",verticalAlign:"top",textAlign:"center"}}> | |||||
<Grid item sm> | |||||
{/* <CustomSearchForm applySearch={applySearch} fields={InputFields}/> */} | |||||
{/* <CustomDatagrid rows={rows} columns={columns} columnWidth={200} dataGridHeight={300}/> */} | |||||
<div style={{ display: "inline-block", width: "70%" }}> | |||||
<Grid item xs={12} md={12} lg={12}> | |||||
<Card> | |||||
<CardHeader className="text-slate-500" title="Project Progress" /> | |||||
<div style={{ display: "inline-block", width: "99%" }}> | |||||
<ReactApexChart | |||||
options={options} | |||||
series={series} | |||||
type="bar" | |||||
height={350} | |||||
/> | |||||
</div> | |||||
{/* <div style={{display:"inline-block",width:"20%",verticalAlign:"top",textAlign:"center"}}> | |||||
<p><strong><u>Stage Deadline</u></strong></p> | <p><strong><u>Stage Deadline</u></strong></p> | ||||
{stageDeadline.map((date, index) => { | {stageDeadline.map((date, index) => { | ||||
const marginTop = index === 0 ? 25 : 20; | const marginTop = index === 0 ? 25 : 20; | ||||
@@ -380,54 +521,122 @@ const ProgressByClient: React.FC = () => { | |||||
); | ); | ||||
})} | })} | ||||
</div> */} | </div> */} | ||||
<CardHeader className="text-slate-500" title="Current Stage Due Date"/> | |||||
<div style={{display:"inline-block",width:"99%",marginLeft:10}}> | |||||
<CustomDatagrid rows={rows2} columns={columns2} columnWidth={200} dataGridHeight={300} checkboxSelection={true} onRowSelectionModelChange={handleSelectionChange} selectionModel={selectionModel}/> | |||||
</div> | |||||
</Card> | |||||
</Grid> | |||||
<CardHeader | |||||
className="text-slate-500" | |||||
title="Current Stage Due Date" | |||||
/> | |||||
<div | |||||
style={{ display: "inline-block", width: "99%", marginLeft: 10 }} | |||||
> | |||||
<CustomDatagrid | |||||
rows={rows2} | |||||
columns={columns2} | |||||
columnWidth={200} | |||||
dataGridHeight={300} | |||||
checkboxSelection={true} | |||||
onRowSelectionModelChange={handleSelectionChange} | |||||
selectionModel={selectionModel} | |||||
/> | |||||
</div> | |||||
</Card> | |||||
</Grid> | |||||
</div> | |||||
<div | |||||
style={{ | |||||
display: "inline-block", | |||||
width: "30%", | |||||
verticalAlign: "top", | |||||
marginLeft: 0, | |||||
}} | |||||
> | |||||
<Grid item xs={12} md={12} lg={12}> | |||||
<Card style={{ marginLeft: 15, marginRight: 20 }}> | |||||
<CardHeader | |||||
className="text-slate-500" | |||||
title="Overall Progress per Project" | |||||
/> | |||||
{percentageArray.length === 0 && ( | |||||
<div | |||||
className="mt-10 mb-10 ml-5 mr-5 text-lg font-medium text-center" | |||||
style={{ color: "#898d8d" }} | |||||
> | |||||
Please select the project you want to check. | |||||
</div> | |||||
)} | |||||
{percentageArray.length > 0 && ( | |||||
<ReactApexChart | |||||
options={options2} | |||||
series={percentageArray} | |||||
type="donut" | |||||
/> | |||||
)} | |||||
</Card> | |||||
</Grid> | |||||
<Grid item xs={12} md={12} lg={12}> | |||||
<Card style={{ marginLeft: 15, marginRight: 20, marginTop: 20 }}> | |||||
<div> | |||||
<div | |||||
className="mt-5 text-lg font-medium" | |||||
style={{ color: "#898d8d" }} | |||||
> | |||||
<span style={{ marginLeft: "5%" }}>Project Budget Manhour</span> | |||||
</div> | |||||
<div | |||||
className="mt-2 text-2xl font-extrabold" | |||||
style={{ color: "#6b87cf" }} | |||||
> | |||||
<span style={{ marginLeft: "5%" }}>{projectBudgetManhour}</span> | |||||
</div> | |||||
</div> | |||||
<hr /> | |||||
<div> | |||||
<div | |||||
className="mt-2 text-lg font-medium" | |||||
style={{ color: "#898d8d" }} | |||||
> | |||||
<span style={{ marginLeft: "5%" }}>Actual Manhour Spent</span> | |||||
</div> | |||||
<div | |||||
className="mt-2 text-2xl font-extrabold" | |||||
style={{ color: "#6b87cf" }} | |||||
> | |||||
<span style={{ marginLeft: "5%" }}>{actualManhourSpent}</span> | |||||
</div> | |||||
</div> | |||||
<hr /> | |||||
<div> | |||||
<div | |||||
className="mt-2 text-lg font-medium" | |||||
style={{ color: "#898d8d" }} | |||||
> | |||||
<span style={{ marginLeft: "5%" }}>Remained Manhour</span> | |||||
</div> | |||||
<div | |||||
className="mt-2 text-2xl font-extrabold" | |||||
style={{ color: "#6b87cf" }} | |||||
> | |||||
<span style={{ marginLeft: "5%" }}>{remainedManhour}</span> | |||||
</div> | |||||
</div> | </div> | ||||
<div style={{display:"inline-block",width:"30%",verticalAlign:"top",marginLeft:0}}> | |||||
<Grid item xs={12} md={12} lg={12}> | |||||
<Card style={{marginLeft:15,marginRight:20}}> | |||||
<CardHeader className="text-slate-500" title="Overall Progress per Project"/> | |||||
{percentageArray.length === 0 &&( | |||||
<div className="mt-10 mb-10 ml-5 mr-5 text-lg font-medium text-center" style={{color:"#898d8d"}}>Please select the project you want to check.</div> | |||||
)} | |||||
{percentageArray.length > 0 &&( | |||||
<ReactApexChart | |||||
options={options2} | |||||
series={percentageArray} | |||||
type="donut" | |||||
/> | |||||
)} | |||||
</Card> | |||||
</Grid> | |||||
<Grid item xs={12} md={12} lg={12}> | |||||
<Card style={{marginLeft:15,marginRight:20,marginTop:20}}> | |||||
<div> | |||||
<div className="mt-5 text-lg font-medium" style={{color:"#898d8d"}}><span style={{marginLeft:"5%"}}>Project Budget Manhour</span></div> | |||||
<div className="mt-2 text-2xl font-extrabold" style={{color:"#6b87cf"}}><span style={{marginLeft:"5%"}}>{projectBudgetManhour}</span></div> | |||||
</div> | |||||
<hr/> | |||||
<div> | |||||
<div className="mt-2 text-lg font-medium" style={{color:"#898d8d"}}><span style={{marginLeft:"5%"}}>Actual Manhour Spent</span></div> | |||||
<div className="mt-2 text-2xl font-extrabold" style={{color:"#6b87cf"}}><span style={{marginLeft:"5%"}}>{actualManhourSpent}</span></div> | |||||
</div> | |||||
<hr/> | |||||
<div> | |||||
<div className="mt-2 text-lg font-medium" style={{color:"#898d8d"}}><span style={{marginLeft:"5%"}}>Remained Manhour</span></div> | |||||
<div className="mt-2 text-2xl font-extrabold" style={{color:"#6b87cf"}}><span style={{marginLeft:"5%"}}>{remainedManhour}</span></div> | |||||
</div> | |||||
<hr/> | |||||
<div> | |||||
<div className="mt-2 text-lg font-medium" style={{color:"#898d8d"}}><span style={{marginLeft:"5%"}}>Last Update</span></div> | |||||
<div className="mt-2 mb-5 text-2xl font-extrabold" style={{color:"#6b87cf"}}><span style={{marginLeft:"5%"}}>{lastUpdate}</span></div> | |||||
</div> | |||||
</Card> | |||||
</Grid> | |||||
<hr /> | |||||
<div> | |||||
<div | |||||
className="mt-2 text-lg font-medium" | |||||
style={{ color: "#898d8d" }} | |||||
> | |||||
<span style={{ marginLeft: "5%" }}>Last Update</span> | |||||
</div> | |||||
<div | |||||
className="mt-2 mb-5 text-2xl font-extrabold" | |||||
style={{ color: "#6b87cf" }} | |||||
> | |||||
<span style={{ marginLeft: "5%" }}>{lastUpdate}</span> | |||||
</div> | |||||
</div> | </div> | ||||
</Grid> | |||||
</Card> | |||||
</Grid> | |||||
</div> | |||||
</Grid> | |||||
); | ); | ||||
}; | }; | ||||
@@ -6,9 +6,9 @@ import SearchBox, { Criterion } from "../SearchBox"; | |||||
import { useTranslation } from "react-i18next"; | import { useTranslation } from "react-i18next"; | ||||
import SearchResults, { Column } from "../SearchResults"; | import SearchResults, { Column } from "../SearchResults"; | ||||
import { CashFlow } from "@/app/api/cashflow"; | import { CashFlow } from "@/app/api/cashflow"; | ||||
import CustomDatagrid from '../CustomDatagrid/CustomDatagrid'; | |||||
import { GridColDef, GridRowSelectionModel} from '@mui/x-data-grid'; | |||||
import ProjectCashFlow from '../ProjectCashFlow' | |||||
import CustomDatagrid from "../CustomDatagrid/CustomDatagrid"; | |||||
import { GridColDef, GridRowSelectionModel } from "@mui/x-data-grid"; | |||||
import ProjectCashFlow from "../ProjectCashFlow"; | |||||
interface Props { | interface Props { | ||||
projects: CashFlow[]; | projects: CashFlow[]; | ||||
@@ -16,70 +16,101 @@ interface Props { | |||||
type SearchQuery = Partial<Omit<CashFlow, "id">>; | type SearchQuery = Partial<Omit<CashFlow, "id">>; | ||||
type SearchParamNames = keyof SearchQuery; | type SearchParamNames = keyof SearchQuery; | ||||
const ProgressByClientSearch: React.FC<Props> = ({ projects}) => { | |||||
const ProgressByClientSearch: React.FC<Props> = ({ projects }) => { | |||||
const { t } = useTranslation("projects"); | const { t } = useTranslation("projects"); | ||||
const [selectionModel, setSelectionModel] : any[] = React.useState([]); | |||||
const [selectionModel, setSelectionModel]: any[] = React.useState([]); | |||||
const columns = [ | const columns = [ | ||||
{ | { | ||||
id: 'projectCode', | |||||
field: 'projectCode', | |||||
id: "projectCode", | |||||
field: "projectCode", | |||||
headerName: "Project Code", | headerName: "Project Code", | ||||
flex: 1, | flex: 1, | ||||
}, | |||||
{ | |||||
id: 'projectName', | |||||
field: 'projectName', | |||||
}, | |||||
{ | |||||
id: "projectName", | |||||
field: "projectName", | |||||
headerName: "Project Name", | headerName: "Project Name", | ||||
flex: 1, | flex: 1, | ||||
}, | |||||
{ | |||||
id: 'team', | |||||
field: 'team', | |||||
headerName: "Team", | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: 'teamLeader', | |||||
field: 'teamLeader', | |||||
headerName: "Team Leader", | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: 'startDate', | |||||
field: 'startDate', | |||||
headerName: "Start Date", | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: 'targetEndDate', | |||||
field: 'targetEndDate', | |||||
headerName: "Target End Date", | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: 'client', | |||||
field: 'client', | |||||
headerName: "Client", | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: 'subsidiary', | |||||
field: 'subsidiary', | |||||
headerName: "Subsidiary", | |||||
flex: 1, | |||||
}, | |||||
]; | |||||
const rows = [{id: 1,projectCode:"M1001",projectName:"Consultancy Project A", team:"XXX", teamLeader:"XXX", startDate:"01/07/2022", targetEndDate: "01/04/2024", client:"Client B", subsidiary:"N/A"}, | |||||
{id: 2,projectCode:"M1301",projectName:"Consultancy Project AAAA", team:"XXX", teamLeader:"XXX", startDate:"01/09/2022", targetEndDate: "20/02/2024", client:"Client C", subsidiary:"Subsidiary A"}, | |||||
{id: 3,projectCode:"M1354",projectName:"Consultancy Project BBB", team:"YYY", teamLeader:"YYY", startDate:"01/02/2023", targetEndDate: "31/01/2024", client:"Client D", subsidiary:"Subsidiary C"} | |||||
] | |||||
const [selectedTeamData, setSelectedTeamData] : any[] = React.useState(rows); | |||||
}, | |||||
{ | |||||
id: "team", | |||||
field: "team", | |||||
headerName: "Team", | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: "teamLeader", | |||||
field: "teamLeader", | |||||
headerName: "Team Leader", | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: "startDate", | |||||
field: "startDate", | |||||
headerName: "Start Date", | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: "targetEndDate", | |||||
field: "targetEndDate", | |||||
headerName: "Target End Date", | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: "client", | |||||
field: "client", | |||||
headerName: "Client", | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: "subsidiary", | |||||
field: "subsidiary", | |||||
headerName: "Subsidiary", | |||||
flex: 1, | |||||
}, | |||||
]; | |||||
const rows = [ | |||||
{ | |||||
id: 1, | |||||
projectCode: "M1001", | |||||
projectName: "Consultancy Project A", | |||||
team: "XXX", | |||||
teamLeader: "XXX", | |||||
startDate: "01/07/2022", | |||||
targetEndDate: "01/04/2024", | |||||
client: "Client B", | |||||
subsidiary: "N/A", | |||||
}, | |||||
{ | |||||
id: 2, | |||||
projectCode: "M1301", | |||||
projectName: "Consultancy Project AAAA", | |||||
team: "XXX", | |||||
teamLeader: "XXX", | |||||
startDate: "01/09/2022", | |||||
targetEndDate: "20/02/2024", | |||||
client: "Client C", | |||||
subsidiary: "Subsidiary A", | |||||
}, | |||||
{ | |||||
id: 3, | |||||
projectCode: "M1354", | |||||
projectName: "Consultancy Project BBB", | |||||
team: "YYY", | |||||
teamLeader: "YYY", | |||||
startDate: "01/02/2023", | |||||
targetEndDate: "31/01/2024", | |||||
client: "Client D", | |||||
subsidiary: "Subsidiary C", | |||||
}, | |||||
]; | |||||
const [selectedTeamData, setSelectedTeamData]: any[] = React.useState(rows); | |||||
const handleSelectionChange = (newSelectionModel: GridRowSelectionModel) => { | const handleSelectionChange = (newSelectionModel: GridRowSelectionModel) => { | ||||
const selectedRowsData = selectedTeamData.filter((row:any) => | |||||
newSelectionModel.includes(row.id) | |||||
const selectedRowsData = selectedTeamData.filter((row: any) => | |||||
newSelectionModel.includes(row.id), | |||||
); | ); | ||||
console.log(selectedRowsData) | |||||
} | |||||
console.log(selectedRowsData); | |||||
}; | |||||
// If project searching is done on the server-side, then no need for this. | // If project searching is done on the server-side, then no need for this. | ||||
const [filteredProjects, setFilteredProjects] = useState(projects); | const [filteredProjects, setFilteredProjects] = useState(projects); | ||||
@@ -88,7 +119,12 @@ const ProgressByClientSearch: React.FC<Props> = ({ projects}) => { | |||||
() => [ | () => [ | ||||
{ label: "Project Code", paramName: "projectCode", type: "text" }, | { label: "Project Code", paramName: "projectCode", type: "text" }, | ||||
{ label: "Project Name", paramName: "projectName", type: "text" }, | { label: "Project Name", paramName: "projectName", type: "text" }, | ||||
{ label: "Start Date From",label2: "Start Date To", paramName: "startDateFrom", type: "dateRange" }, | |||||
{ | |||||
label: "Start Date From", | |||||
label2: "Start Date To", | |||||
paramName: "startDateFrom", | |||||
type: "dateRange", | |||||
}, | |||||
], | ], | ||||
[t], | [t], | ||||
); | ); | ||||
@@ -1,121 +1,123 @@ | |||||
"use client"; | "use client"; | ||||
import * as React from "react"; | import * as React from "react"; | ||||
import Grid from "@mui/material/Grid"; | import Grid from "@mui/material/Grid"; | ||||
import { useState,useEffect, useMemo } from 'react' | |||||
import { useState, useEffect, useMemo } from "react"; | |||||
import Paper from "@mui/material/Paper"; | import Paper from "@mui/material/Paper"; | ||||
import { TFunction } from "i18next"; | import { TFunction } from "i18next"; | ||||
import { useTranslation } from "react-i18next"; | import { useTranslation } from "react-i18next"; | ||||
import {Card,CardHeader} from '@mui/material'; | |||||
import { Card, CardHeader } from "@mui/material"; | |||||
import CustomSearchForm from "../CustomSearchForm/CustomSearchForm"; | import CustomSearchForm from "../CustomSearchForm/CustomSearchForm"; | ||||
import CustomDatagrid from '../CustomDatagrid/CustomDatagrid'; | |||||
import ReactApexChart from 'react-apexcharts'; | |||||
import { ApexOptions } from 'apexcharts'; | |||||
import { GridColDef, GridRowSelectionModel} from '@mui/x-data-grid'; | |||||
import ReportProblemIcon from '@mui/icons-material/ReportProblem'; | |||||
import dynamic from 'next/dynamic'; | |||||
import '../../app/global.css'; | |||||
import CustomDatagrid from "../CustomDatagrid/CustomDatagrid"; | |||||
import ReactApexChart from "react-apexcharts"; | |||||
import { ApexOptions } from "apexcharts"; | |||||
import { GridColDef, GridRowSelectionModel } from "@mui/x-data-grid"; | |||||
import ReportProblemIcon from "@mui/icons-material/ReportProblem"; | |||||
import dynamic from "next/dynamic"; | |||||
import "../../app/global.css"; | |||||
import { AnyARecord, AnyCnameRecord } from "dns"; | import { AnyARecord, AnyCnameRecord } from "dns"; | ||||
import SearchBox, { Criterion } from "../SearchBox"; | import SearchBox, { Criterion } from "../SearchBox"; | ||||
import ProgressByClientSearch from "@/components/ProgressByClientSearch"; | import ProgressByClientSearch from "@/components/ProgressByClientSearch"; | ||||
import { Suspense } from "react"; | import { Suspense } from "react"; | ||||
import ProgressCashFlowSearch from "@/components/ProgressCashFlowSearch"; | import ProgressCashFlowSearch from "@/components/ProgressCashFlowSearch"; | ||||
import {Input,Label} from "reactstrap"; | |||||
import { Input, Label } from "reactstrap"; | |||||
const ProjectCashFlow: React.FC = () => { | const ProjectCashFlow: React.FC = () => { | ||||
const todayDate = new Date; | |||||
const [selectionModel, setSelectionModel] : any[] = React.useState([]); | |||||
const [cashFlowYear, setCashFlowYear] : any[] = React.useState(todayDate.getFullYear()); | |||||
const todayDate = new Date(); | |||||
const [selectionModel, setSelectionModel]: any[] = React.useState([]); | |||||
const [cashFlowYear, setCashFlowYear]: any[] = React.useState( | |||||
todayDate.getFullYear(), | |||||
); | |||||
const columns = [ | const columns = [ | ||||
{ | { | ||||
id: 'projectCode', | |||||
field: 'projectCode', | |||||
id: "projectCode", | |||||
field: "projectCode", | |||||
headerName: "Project Code", | headerName: "Project Code", | ||||
flex: 1, | flex: 1, | ||||
}, | |||||
{ | |||||
id: 'projectName', | |||||
field: 'projectName', | |||||
}, | |||||
{ | |||||
id: "projectName", | |||||
field: "projectName", | |||||
headerName: "Project Name", | headerName: "Project Name", | ||||
flex: 1, | flex: 1, | ||||
}, | |||||
{ | |||||
id: 'team', | |||||
field: 'team', | |||||
headerName: "Team", | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: 'teamLeader', | |||||
field: 'teamLeader', | |||||
headerName: "Team Leader", | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: 'startDate', | |||||
field: 'startDate', | |||||
headerName: "Start Date", | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: 'targetEndDate', | |||||
field: 'targetEndDate', | |||||
headerName: "Target End Date", | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: 'client', | |||||
field: 'client', | |||||
headerName: "Client", | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: 'subsidiary', | |||||
field: 'subsidiary', | |||||
headerName: "Subsidiary", | |||||
flex: 1, | |||||
}, | |||||
}, | |||||
{ | |||||
id: "team", | |||||
field: "team", | |||||
headerName: "Team", | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: "teamLeader", | |||||
field: "teamLeader", | |||||
headerName: "Team Leader", | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: "startDate", | |||||
field: "startDate", | |||||
headerName: "Start Date", | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: "targetEndDate", | |||||
field: "targetEndDate", | |||||
headerName: "Target End Date", | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: "client", | |||||
field: "client", | |||||
headerName: "Client", | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: "subsidiary", | |||||
field: "subsidiary", | |||||
headerName: "Subsidiary", | |||||
flex: 1, | |||||
}, | |||||
]; | ]; | ||||
const ledgerColumns = [ | const ledgerColumns = [ | ||||
{ | { | ||||
id: 'date', | |||||
field: 'date', | |||||
id: "date", | |||||
field: "date", | |||||
headerName: "Date", | headerName: "Date", | ||||
flex: 0.5, | flex: 0.5, | ||||
}, | |||||
{ | |||||
id: 'expenditure', | |||||
field: 'expenditure', | |||||
}, | |||||
{ | |||||
id: "expenditure", | |||||
field: "expenditure", | |||||
headerName: "Expenditure (HKD)", | headerName: "Expenditure (HKD)", | ||||
flex: 0.6, | flex: 0.6, | ||||
}, | |||||
{ | |||||
id: 'income', | |||||
field: 'income', | |||||
headerName: "Income (HKD)", | |||||
flex: 0.6, | |||||
}, | |||||
{ | |||||
id: 'cashFlowBalance', | |||||
field: 'cashFlowBalance', | |||||
headerName: "Cash Flow Balance (HKD)", | |||||
flex: 0.6, | |||||
}, | |||||
{ | |||||
id: 'remarks', | |||||
field: 'remarks', | |||||
headerName: "Remarks", | |||||
flex: 1, | |||||
}, | |||||
}, | |||||
{ | |||||
id: "income", | |||||
field: "income", | |||||
headerName: "Income (HKD)", | |||||
flex: 0.6, | |||||
}, | |||||
{ | |||||
id: "cashFlowBalance", | |||||
field: "cashFlowBalance", | |||||
headerName: "Cash Flow Balance (HKD)", | |||||
flex: 0.6, | |||||
}, | |||||
{ | |||||
id: "remarks", | |||||
field: "remarks", | |||||
headerName: "Remarks", | |||||
flex: 1, | |||||
}, | |||||
]; | ]; | ||||
const options: ApexOptions = { | const options: ApexOptions = { | ||||
chart: { | chart: { | ||||
height: 350, | height: 350, | ||||
type: 'line', | |||||
type: "line", | |||||
}, | }, | ||||
stroke: { | stroke: { | ||||
width: [0, 0, 2, 2] | |||||
width: [0, 0, 2, 2], | |||||
}, | }, | ||||
plotOptions: { | plotOptions: { | ||||
bar: { | bar: { | ||||
@@ -124,160 +126,167 @@ const ProjectCashFlow: React.FC = () => { | |||||
}, | }, | ||||
}, | }, | ||||
dataLabels: { | dataLabels: { | ||||
enabled: false | |||||
enabled: false, | |||||
}, | }, | ||||
xaxis: { | xaxis: { | ||||
categories: [ | categories: [ | ||||
'Q1', | |||||
'Q2', | |||||
'Q3', | |||||
'Q4', | |||||
'Q5', | |||||
'Q6', | |||||
'Q7', | |||||
'Q8', | |||||
'Q9', | |||||
'Q10', | |||||
'Q11', | |||||
'Q12', | |||||
"Q1", | |||||
"Q2", | |||||
"Q3", | |||||
"Q4", | |||||
"Q5", | |||||
"Q6", | |||||
"Q7", | |||||
"Q8", | |||||
"Q9", | |||||
"Q10", | |||||
"Q11", | |||||
"Q12", | |||||
], | ], | ||||
}, | }, | ||||
yaxis: [ | yaxis: [ | ||||
{ | { | ||||
title: { | title: { | ||||
text: 'Monthly Income and Expenditure(HKD)' | |||||
text: "Monthly Income and Expenditure(HKD)", | |||||
}, | }, | ||||
min: 0, | min: 0, | ||||
max: 350000, | max: 350000, | ||||
tickAmount: 5 | |||||
tickAmount: 5, | |||||
}, | }, | ||||
{ | { | ||||
show:false, | |||||
seriesName: 'Monthly_Expenditure', | |||||
show: false, | |||||
seriesName: "Monthly_Expenditure", | |||||
title: { | title: { | ||||
text: 'Monthly Expenditure (HKD)' | |||||
text: "Monthly Expenditure (HKD)", | |||||
}, | }, | ||||
min: 0, | min: 0, | ||||
max: 350000, | max: 350000, | ||||
tickAmount: 5 | |||||
tickAmount: 5, | |||||
}, | }, | ||||
{ | { | ||||
seriesName: 'Cumulative_Income', | |||||
seriesName: "Cumulative_Income", | |||||
opposite: true, | opposite: true, | ||||
title: { | title: { | ||||
text: 'Cumulative Income and Expenditure(HKD)' | |||||
text: "Cumulative Income and Expenditure(HKD)", | |||||
}, | }, | ||||
min: 0, | min: 0, | ||||
max: 850000, | max: 850000, | ||||
tickAmount: 5 | |||||
tickAmount: 5, | |||||
}, | }, | ||||
{ | { | ||||
show:false, | |||||
seriesName: 'Cumulative_Expenditure', | |||||
show: false, | |||||
seriesName: "Cumulative_Expenditure", | |||||
opposite: true, | opposite: true, | ||||
title: { | title: { | ||||
text: 'Cumulative Expenditure (HKD)' | |||||
text: "Cumulative Expenditure (HKD)", | |||||
}, | }, | ||||
min: 0, | min: 0, | ||||
max: 850000, | max: 850000, | ||||
tickAmount: 5 | |||||
} | |||||
], | |||||
tickAmount: 5, | |||||
}, | |||||
], | |||||
grid: { | grid: { | ||||
borderColor: '#f1f1f1', | |||||
borderColor: "#f1f1f1", | |||||
}, | }, | ||||
annotations: { | |||||
}, | |||||
series:[ | |||||
annotations: {}, | |||||
series: [ | |||||
{ | { | ||||
name:"Monthly_Income", | |||||
type:"column", | |||||
name: "Monthly_Income", | |||||
type: "column", | |||||
color: "#ffde91", | color: "#ffde91", | ||||
data:[0,110000,0,0,185000,0,0,189000,0,0,300000,0], | |||||
data: [0, 110000, 0, 0, 185000, 0, 0, 189000, 0, 0, 300000, 0], | |||||
}, | }, | ||||
{ | { | ||||
name:"Monthly_Expenditure", | |||||
type:"column", | |||||
name: "Monthly_Expenditure", | |||||
type: "column", | |||||
color: "#82b59a", | color: "#82b59a", | ||||
data:[0,160000,120000,120000,55000,55000,55000,55000,55000,70000,55000,55000] | |||||
data: [ | |||||
0, 160000, 120000, 120000, 55000, 55000, 55000, 55000, 55000, 70000, | |||||
55000, 55000, | |||||
], | |||||
}, | }, | ||||
{ | { | ||||
name:"Cumulative_Income", | |||||
type:"line", | |||||
name: "Cumulative_Income", | |||||
type: "line", | |||||
color: "#EE6D7A", | color: "#EE6D7A", | ||||
data:[0,100000,100000,100000,300000,300000,300000,500000,500000,500000,800000,800000] | |||||
data: [ | |||||
0, 100000, 100000, 100000, 300000, 300000, 300000, 500000, 500000, | |||||
500000, 800000, 800000, | |||||
], | |||||
}, | }, | ||||
{ | { | ||||
name:"Cumulative_Expenditure", | |||||
type:"line", | |||||
name: "Cumulative_Expenditure", | |||||
type: "line", | |||||
color: "#7cd3f2", | color: "#7cd3f2", | ||||
data:[0,198000,240000,400000,410000,430000,510000,580000,600000,710000,730000,790000] | |||||
} | |||||
] | |||||
data: [ | |||||
0, 198000, 240000, 400000, 410000, 430000, 510000, 580000, 600000, | |||||
710000, 730000, 790000, | |||||
], | |||||
}, | |||||
], | |||||
}; | }; | ||||
const accountsReceivableOptions: ApexOptions = { | const accountsReceivableOptions: ApexOptions = { | ||||
colors: ["#20E647"], | |||||
series: [80], | |||||
chart: { | |||||
height: 350, | |||||
type: 'radialBar', | |||||
colors: ["#20E647"], | |||||
series: [80], | |||||
chart: { | |||||
height: 350, | |||||
type: "radialBar", | |||||
}, | |||||
plotOptions: { | |||||
radialBar: { | |||||
hollow: { | |||||
size: "70%", | |||||
background: "#ffffff", | |||||
}, | }, | ||||
plotOptions: { | |||||
radialBar: { | |||||
hollow: { | |||||
size: '70%', | |||||
background: "#ffffff" | |||||
}, | |||||
track: { | |||||
dropShadow: { | |||||
enabled: true, | |||||
top: 2, | |||||
left: 0, | |||||
blur: 4, | |||||
opacity: 0.15 | |||||
} | |||||
}, | |||||
dataLabels: { | |||||
name:{ | |||||
show:false, | |||||
}, | |||||
value: { | |||||
color: "#3e98c7", | |||||
fontSize: "3em", | |||||
show: true | |||||
} | |||||
}, | |||||
track: { | |||||
dropShadow: { | |||||
enabled: true, | |||||
top: 2, | |||||
left: 0, | |||||
blur: 4, | |||||
opacity: 0.15, | |||||
}, | }, | ||||
}, | }, | ||||
fill: { | |||||
type: "gradient", | |||||
gradient: { | |||||
shade: "dark", | |||||
type: "vertical", | |||||
gradientToColors: ["#87D4F9"], | |||||
stops: [0, 100] | |||||
} | |||||
}, | |||||
stroke: { | |||||
lineCap: "round" | |||||
dataLabels: { | |||||
name: { | |||||
show: false, | |||||
}, | |||||
value: { | |||||
color: "#3e98c7", | |||||
fontSize: "3em", | |||||
show: true, | |||||
}, | |||||
}, | }, | ||||
labels: ['AccountsReceivable'], | |||||
}, | |||||
}, | |||||
fill: { | |||||
type: "gradient", | |||||
gradient: { | |||||
shade: "dark", | |||||
type: "vertical", | |||||
gradientToColors: ["#87D4F9"], | |||||
stops: [0, 100], | |||||
}, | |||||
}, | |||||
stroke: { | |||||
lineCap: "round", | |||||
}, | |||||
labels: ["AccountsReceivable"], | |||||
}; | }; | ||||
const expenditureOptions: ApexOptions = { | const expenditureOptions: ApexOptions = { | ||||
colors: ["#20E647"], | colors: ["#20E647"], | ||||
series: [95], | series: [95], | ||||
chart: { | |||||
chart: { | |||||
height: 350, | height: 350, | ||||
type: 'radialBar', | |||||
type: "radialBar", | |||||
}, | }, | ||||
plotOptions: { | plotOptions: { | ||||
radialBar: { | radialBar: { | ||||
hollow: { | hollow: { | ||||
size: '70%', | |||||
background: "#ffffff" | |||||
size: "70%", | |||||
background: "#ffffff", | |||||
}, | }, | ||||
track: { | track: { | ||||
dropShadow: { | dropShadow: { | ||||
@@ -285,18 +294,18 @@ const ProjectCashFlow: React.FC = () => { | |||||
top: 2, | top: 2, | ||||
left: 0, | left: 0, | ||||
blur: 4, | blur: 4, | ||||
opacity: 0.15 | |||||
} | |||||
opacity: 0.15, | |||||
}, | |||||
}, | }, | ||||
dataLabels: { | dataLabels: { | ||||
name:{ | |||||
show:false, | |||||
name: { | |||||
show: false, | |||||
}, | }, | ||||
value: { | value: { | ||||
color: "#3e98c7", | color: "#3e98c7", | ||||
fontSize: "3em", | fontSize: "3em", | ||||
show: true | |||||
} | |||||
show: true, | |||||
}, | |||||
}, | }, | ||||
}, | }, | ||||
}, | }, | ||||
@@ -306,132 +315,322 @@ const ProjectCashFlow: React.FC = () => { | |||||
shade: "dark", | shade: "dark", | ||||
type: "vertical", | type: "vertical", | ||||
gradientToColors: ["#87D4F9"], | gradientToColors: ["#87D4F9"], | ||||
stops: [0, 100] | |||||
} | |||||
stops: [0, 100], | |||||
}, | |||||
}, | }, | ||||
stroke: { | stroke: { | ||||
lineCap: "round" | |||||
lineCap: "round", | |||||
}, | }, | ||||
labels: ['AccountsReceivable'], | |||||
}; | |||||
labels: ["AccountsReceivable"], | |||||
}; | |||||
const rows = [{id: 1,projectCode:"M1001",projectName:"Consultancy Project A", team:"XXX", teamLeader:"XXX", startDate:"01/07/2022", targetEndDate: "01/04/2024", client:"Client B", subsidiary:"N/A"}, | |||||
{id: 2,projectCode:"M1301",projectName:"Consultancy Project AAAA", team:"XXX", teamLeader:"XXX", startDate:"01/09/2022", targetEndDate: "20/02/2024", client:"Client C", subsidiary:"Subsidiary A"}, | |||||
{id: 3,projectCode:"M1354",projectName:"Consultancy Project BBB", team:"YYY", teamLeader:"YYY", startDate:"01/02/2023", targetEndDate: "31/01/2024", client:"Client D", subsidiary:"Subsidiary C"} | |||||
] | |||||
const rows = [ | |||||
{ | |||||
id: 1, | |||||
projectCode: "M1001", | |||||
projectName: "Consultancy Project A", | |||||
team: "XXX", | |||||
teamLeader: "XXX", | |||||
startDate: "01/07/2022", | |||||
targetEndDate: "01/04/2024", | |||||
client: "Client B", | |||||
subsidiary: "N/A", | |||||
}, | |||||
{ | |||||
id: 2, | |||||
projectCode: "M1301", | |||||
projectName: "Consultancy Project AAAA", | |||||
team: "XXX", | |||||
teamLeader: "XXX", | |||||
startDate: "01/09/2022", | |||||
targetEndDate: "20/02/2024", | |||||
client: "Client C", | |||||
subsidiary: "Subsidiary A", | |||||
}, | |||||
{ | |||||
id: 3, | |||||
projectCode: "M1354", | |||||
projectName: "Consultancy Project BBB", | |||||
team: "YYY", | |||||
teamLeader: "YYY", | |||||
startDate: "01/02/2023", | |||||
targetEndDate: "31/01/2024", | |||||
client: "Client D", | |||||
subsidiary: "Subsidiary C", | |||||
}, | |||||
]; | |||||
const ledgerRows = [{id: 1,date:"Feb 2023",expenditure:"-", income:"100,000.00", cashFlowBalance:"100,000.00", remarks:"Payment Milestone 1 (10%)"}, | |||||
{id: 2,date:"Feb 2023",expenditure:"160,000.00", income:"-", cashFlowBalance:"(60,000.00)", remarks:"Monthly Manpower Expenditure"}, | |||||
{id: 3,date:"Mar 2023",expenditure:"160,000.00", income:"-", cashFlowBalance:"(180,000.00)", remarks:"Monthly Manpower Expenditure"}, | |||||
{id: 4,date:"Apr 2023",expenditure:"120,000.00", income:"-", cashFlowBalance:"(300,000.00)", remarks:"Monthly Manpower Expenditure"}, | |||||
{id: 5,date:"May 2023",expenditure:"-", income:"200,000.00", cashFlowBalance:"(100,000.00)", remarks:"Payment Milestone 2 (20%)"}, | |||||
{id: 6,date:"May 2023",expenditure:"40,000.00", income:"-", cashFlowBalance:"(140,000.00)", remarks:"Monthly Manpower Expenditure"} | |||||
] | |||||
const ledgerRows = [ | |||||
{ | |||||
id: 1, | |||||
date: "Feb 2023", | |||||
expenditure: "-", | |||||
income: "100,000.00", | |||||
cashFlowBalance: "100,000.00", | |||||
remarks: "Payment Milestone 1 (10%)", | |||||
}, | |||||
{ | |||||
id: 2, | |||||
date: "Feb 2023", | |||||
expenditure: "160,000.00", | |||||
income: "-", | |||||
cashFlowBalance: "(60,000.00)", | |||||
remarks: "Monthly Manpower Expenditure", | |||||
}, | |||||
{ | |||||
id: 3, | |||||
date: "Mar 2023", | |||||
expenditure: "160,000.00", | |||||
income: "-", | |||||
cashFlowBalance: "(180,000.00)", | |||||
remarks: "Monthly Manpower Expenditure", | |||||
}, | |||||
{ | |||||
id: 4, | |||||
date: "Apr 2023", | |||||
expenditure: "120,000.00", | |||||
income: "-", | |||||
cashFlowBalance: "(300,000.00)", | |||||
remarks: "Monthly Manpower Expenditure", | |||||
}, | |||||
{ | |||||
id: 5, | |||||
date: "May 2023", | |||||
expenditure: "-", | |||||
income: "200,000.00", | |||||
cashFlowBalance: "(100,000.00)", | |||||
remarks: "Payment Milestone 2 (20%)", | |||||
}, | |||||
{ | |||||
id: 6, | |||||
date: "May 2023", | |||||
expenditure: "40,000.00", | |||||
income: "-", | |||||
cashFlowBalance: "(140,000.00)", | |||||
remarks: "Monthly Manpower Expenditure", | |||||
}, | |||||
]; | |||||
const [projectData, setProjectData] : any[] = React.useState(rows); | |||||
const [ledgerData, setLedgerData] : any[] = React.useState(ledgerRows); | |||||
const [projectData, setProjectData]: any[] = React.useState(rows); | |||||
const [ledgerData, setLedgerData]: any[] = React.useState(ledgerRows); | |||||
const handleSelectionChange = (newSelectionModel: GridRowSelectionModel) => { | const handleSelectionChange = (newSelectionModel: GridRowSelectionModel) => { | ||||
const selectedRowsData = projectData.filter((row:any) => | |||||
newSelectionModel.includes(row.id) | |||||
const selectedRowsData = projectData.filter((row: any) => | |||||
newSelectionModel.includes(row.id), | |||||
); | ); | ||||
console.log(selectedRowsData) | |||||
} | |||||
console.log(selectedRowsData); | |||||
}; | |||||
return ( | return ( | ||||
<> | <> | ||||
<Suspense fallback={<ProgressCashFlowSearch.Loading />}> | <Suspense fallback={<ProgressCashFlowSearch.Loading />}> | ||||
<ProgressCashFlowSearch/> | |||||
<ProgressCashFlowSearch /> | |||||
</Suspense> | </Suspense> | ||||
<CustomDatagrid rows={projectData} columns={columns} columnWidth={200} dataGridHeight={300} checkboxSelection={true} onRowSelectionModelChange={handleSelectionChange} selectionModel={selectionModel}/> | |||||
<Grid item sm> | |||||
<div style={{display:"inline-block",width:"50%"}}> | |||||
<Grid item xs={12} md={12} lg={12}> | |||||
<Card> | |||||
<CardHeader className="text-slate-500" title="Project Cash Flow by Month"/> | |||||
<div style={{display:"inline-block",width:"99%"}}> | |||||
<div className="inline-block"> | |||||
<Label className="text-slate-500 font-medium ml-6"> | |||||
Period: | |||||
</Label> | |||||
<Input | |||||
id={'cashFlowYear'} | |||||
value={cashFlowYear} | |||||
readOnly={true} | |||||
bsSize="lg" | |||||
className="rounded-md text-base w-12" | |||||
/> | |||||
</div> | |||||
<div className="inline-block ml-1"> | |||||
<button onClick={() => setCashFlowYear(cashFlowYear - 1)} className="hover:cursor-pointer hover:bg-slate-200 bg-transparent rounded-md w-8 h-8 text-base"> | |||||
< | |||||
</button> | |||||
</div> | |||||
<div className="inline-block ml-1"> | |||||
<button onClick={() => setCashFlowYear(cashFlowYear + 1)} className="hover:cursor-pointer hover:bg-slate-200 bg-transparent rounded-md w-8 h-8 text-base"> | |||||
> | |||||
</button> | |||||
</div> | |||||
<ReactApexChart | |||||
options={options} | |||||
series={options.series} | |||||
type="line" | |||||
height="auto" | |||||
/> | |||||
</div> | |||||
</Card> | |||||
</Grid> | |||||
</div> | |||||
<div style={{display:"inline-block",width:"24%", verticalAlign:"top", marginLeft:10}}> | |||||
<CustomDatagrid | |||||
rows={projectData} | |||||
columns={columns} | |||||
columnWidth={200} | |||||
dataGridHeight={300} | |||||
checkboxSelection={true} | |||||
onRowSelectionModelChange={handleSelectionChange} | |||||
selectionModel={selectionModel} | |||||
/> | |||||
<Grid item sm> | |||||
<div style={{ display: "inline-block", width: "50%" }}> | |||||
<Grid item xs={12} md={12} lg={12}> | <Grid item xs={12} md={12} lg={12}> | ||||
<Card> | |||||
<CardHeader className="text-slate-500" title="Accounts Receivable (HKD)"/> | |||||
<Card> | |||||
<CardHeader | |||||
className="text-slate-500" | |||||
title="Project Cash Flow by Month" | |||||
/> | |||||
<div style={{ display: "inline-block", width: "99%" }}> | |||||
<div className="inline-block"> | |||||
<Label className="text-slate-500 font-medium ml-6"> | |||||
Period: | |||||
</Label> | |||||
<Input | |||||
id={"cashFlowYear"} | |||||
value={cashFlowYear} | |||||
readOnly={true} | |||||
bsSize="lg" | |||||
className="rounded-md text-base w-12" | |||||
/> | |||||
</div> | |||||
<div className="inline-block ml-1"> | |||||
<button | |||||
onClick={() => setCashFlowYear(cashFlowYear - 1)} | |||||
className="hover:cursor-pointer hover:bg-slate-200 bg-transparent rounded-md w-8 h-8 text-base" | |||||
> | |||||
< | |||||
</button> | |||||
</div> | |||||
<div className="inline-block ml-1"> | |||||
<button | |||||
onClick={() => setCashFlowYear(cashFlowYear + 1)} | |||||
className="hover:cursor-pointer hover:bg-slate-200 bg-transparent rounded-md w-8 h-8 text-base" | |||||
> | |||||
> | |||||
</button> | |||||
</div> | |||||
<ReactApexChart | <ReactApexChart | ||||
options={accountsReceivableOptions} | |||||
series={accountsReceivableOptions.series} | |||||
type="radialBar" | |||||
/> | |||||
<Card className="ml-2 mr-2 mb-4 rounded-none border-solid border-slate-100"> | |||||
<div className="text-sm font-medium ml-5 mt-2" style={{color:"#898d8d"}}>Total A. Receivable</div> | |||||
<div className="text-lg font-medium ml-5" style={{color:"#6b87cf"}}>1,000,000.00</div><hr/> | |||||
<div className="text-sm font-medium ml-5" style={{color:"#898d8d"}}>Amount Received</div> | |||||
<div className="text-lg font-medium ml-5" style={{color:"#6b87cf"}}>800,000.00</div><hr/> | |||||
<div className="text-sm font-medium ml-5" style={{color:"#898d8d"}}>Remaining Balance</div> | |||||
<div className="text-lg font-medium ml-5 mb-2" style={{color:"#6b87cf"}}>200,000.00</div> | |||||
</Card> | |||||
</Card> | |||||
options={options} | |||||
series={options.series} | |||||
type="line" | |||||
height="auto" | |||||
/> | |||||
</div> | |||||
</Card> | |||||
</Grid> | </Grid> | ||||
</div> | |||||
<div style={{display:"inline-block",width:"24%", verticalAlign:"top", marginLeft:10}}> | |||||
</div> | |||||
<div | |||||
style={{ | |||||
display: "inline-block", | |||||
width: "24%", | |||||
verticalAlign: "top", | |||||
marginLeft: 10, | |||||
}} | |||||
> | |||||
<Grid item xs={12} md={12} lg={12}> | <Grid item xs={12} md={12} lg={12}> | ||||
<Card> | |||||
<CardHeader className="text-slate-500" title="Expenditure (HKD)"/> | |||||
<ReactApexChart | |||||
options={expenditureOptions} | |||||
series={expenditureOptions.series} | |||||
type="radialBar" | |||||
/> | |||||
<Card className="ml-2 mr-2 mb-4 rounded-none border-solid border-slate-100"> | |||||
<div className="text-sm font-medium ml-5 mt-2" style={{color:"#898d8d"}}>Budgeted Expenditure</div> | |||||
<div className="text-lg font-medium ml-5" style={{color:"#6b87cf"}}>800,000.00</div><hr/> | |||||
<div className="text-sm font-medium ml-5" style={{color:"#898d8d"}}>Actual Expenditure</div> | |||||
<div className="text-lg font-medium ml-5" style={{color:"#6b87cf"}}>760,000.00</div><hr/> | |||||
<div className="text-sm font-medium ml-5" style={{color:"#898d8d"}}>Remaining Balance</div> | |||||
<div className="text-lg font-medium ml-5 mb-2" style={{color:"#6b87cf"}}>40,000.00</div> | |||||
</Card> | |||||
<Card> | |||||
<CardHeader | |||||
className="text-slate-500" | |||||
title="Accounts Receivable (HKD)" | |||||
/> | |||||
<ReactApexChart | |||||
options={accountsReceivableOptions} | |||||
series={accountsReceivableOptions.series} | |||||
type="radialBar" | |||||
/> | |||||
<Card className="ml-2 mr-2 mb-4 rounded-none border-solid border-slate-100"> | |||||
<div | |||||
className="text-sm font-medium ml-5 mt-2" | |||||
style={{ color: "#898d8d" }} | |||||
> | |||||
Total A. Receivable | |||||
</div> | |||||
<div | |||||
className="text-lg font-medium ml-5" | |||||
style={{ color: "#6b87cf" }} | |||||
> | |||||
1,000,000.00 | |||||
</div> | |||||
<hr /> | |||||
<div | |||||
className="text-sm font-medium ml-5" | |||||
style={{ color: "#898d8d" }} | |||||
> | |||||
Amount Received | |||||
</div> | |||||
<div | |||||
className="text-lg font-medium ml-5" | |||||
style={{ color: "#6b87cf" }} | |||||
> | |||||
800,000.00 | |||||
</div> | |||||
<hr /> | |||||
<div | |||||
className="text-sm font-medium ml-5" | |||||
style={{ color: "#898d8d" }} | |||||
> | |||||
Remaining Balance | |||||
</div> | |||||
<div | |||||
className="text-lg font-medium ml-5 mb-2" | |||||
style={{ color: "#6b87cf" }} | |||||
> | |||||
200,000.00 | |||||
</div> | |||||
</Card> | </Card> | ||||
</Card> | |||||
</Grid> | </Grid> | ||||
</div> | |||||
<div className="mt-5" style={{display:"inline-block",width:"100%", verticalAlign:"top"}}> | |||||
<Grid item xs={12} md={12} lg={12}> | |||||
<Card> | |||||
<CardHeader className="text-slate-500" title="Cash Flow Ledger by Month"/> | |||||
<div className="ml-4 mr-4"> | |||||
<CustomDatagrid rows={ledgerData} columns={ledgerColumns} columnWidth={200} dataGridHeight={300}/> | |||||
</div> | |||||
<div | |||||
style={{ | |||||
display: "inline-block", | |||||
width: "24%", | |||||
verticalAlign: "top", | |||||
marginLeft: 10, | |||||
}} | |||||
> | |||||
<Grid item xs={12} md={12} lg={12}> | |||||
<Card> | |||||
<CardHeader | |||||
className="text-slate-500" | |||||
title="Expenditure (HKD)" | |||||
/> | |||||
<ReactApexChart | |||||
options={expenditureOptions} | |||||
series={expenditureOptions.series} | |||||
type="radialBar" | |||||
/> | |||||
<Card className="ml-2 mr-2 mb-4 rounded-none border-solid border-slate-100"> | |||||
<div | |||||
className="text-sm font-medium ml-5 mt-2" | |||||
style={{ color: "#898d8d" }} | |||||
> | |||||
Budgeted Expenditure | |||||
</div> | |||||
<div | |||||
className="text-lg font-medium ml-5" | |||||
style={{ color: "#6b87cf" }} | |||||
> | |||||
800,000.00 | |||||
</div> | |||||
<hr /> | |||||
<div | |||||
className="text-sm font-medium ml-5" | |||||
style={{ color: "#898d8d" }} | |||||
> | |||||
Actual Expenditure | |||||
</div> | |||||
<div | |||||
className="text-lg font-medium ml-5" | |||||
style={{ color: "#6b87cf" }} | |||||
> | |||||
760,000.00 | |||||
</div> | |||||
<hr /> | |||||
<div | |||||
className="text-sm font-medium ml-5" | |||||
style={{ color: "#898d8d" }} | |||||
> | |||||
Remaining Balance | |||||
</div> | |||||
<div | |||||
className="text-lg font-medium ml-5 mb-2" | |||||
style={{ color: "#6b87cf" }} | |||||
> | |||||
40,000.00 | |||||
</div> | </div> | ||||
</Card> | </Card> | ||||
</Grid> | |||||
</div> | |||||
</Grid> | |||||
</Card> | |||||
</Grid> | |||||
</div> | |||||
<div | |||||
className="mt-5" | |||||
style={{ | |||||
display: "inline-block", | |||||
width: "100%", | |||||
verticalAlign: "top", | |||||
}} | |||||
> | |||||
<Grid item xs={12} md={12} lg={12}> | |||||
<Card> | |||||
<CardHeader | |||||
className="text-slate-500" | |||||
title="Cash Flow Ledger by Month" | |||||
/> | |||||
<div className="ml-4 mr-4"> | |||||
<CustomDatagrid | |||||
rows={ledgerData} | |||||
columns={ledgerColumns} | |||||
columnWidth={200} | |||||
dataGridHeight={300} | |||||
/> | |||||
</div> | |||||
</Card> | |||||
</Grid> | |||||
</div> | |||||
</Grid> | |||||
</> | </> | ||||
); | ); | ||||
}; | }; | ||||
@@ -1,75 +1,173 @@ | |||||
import * as React from "react"; | import * as React from "react"; | ||||
import Grid from "@mui/material/Grid"; | import Grid from "@mui/material/Grid"; | ||||
import { useState,useEffect, useMemo } from 'react' | |||||
import { useState, useEffect, useMemo } from "react"; | |||||
import Paper from "@mui/material/Paper"; | import Paper from "@mui/material/Paper"; | ||||
import { TFunction } from "i18next"; | import { TFunction } from "i18next"; | ||||
import { useTranslation } from "react-i18next"; | import { useTranslation } from "react-i18next"; | ||||
import {Card,CardHeader} from '@mui/material'; | |||||
import { Card, CardHeader } from "@mui/material"; | |||||
import CustomSearchForm from "../CustomSearchForm/CustomSearchForm"; | import CustomSearchForm from "../CustomSearchForm/CustomSearchForm"; | ||||
import CustomDatagrid from '../CustomDatagrid/CustomDatagrid'; | |||||
import ReactApexChart from 'react-apexcharts'; | |||||
import { ApexOptions } from 'apexcharts'; | |||||
import { GridColDef, GridRowSelectionModel} from '@mui/x-data-grid'; | |||||
import ReportProblemIcon from '@mui/icons-material/ReportProblem'; | |||||
import dynamic from 'next/dynamic'; | |||||
import '../../app/global.css'; | |||||
import CustomDatagrid from "../CustomDatagrid/CustomDatagrid"; | |||||
import ReactApexChart from "react-apexcharts"; | |||||
import { ApexOptions } from "apexcharts"; | |||||
import { GridColDef, GridRowSelectionModel } from "@mui/x-data-grid"; | |||||
import ReportProblemIcon from "@mui/icons-material/ReportProblem"; | |||||
import dynamic from "next/dynamic"; | |||||
import "../../app/global.css"; | |||||
import { AnyARecord, AnyCnameRecord } from "dns"; | import { AnyARecord, AnyCnameRecord } from "dns"; | ||||
import SearchBox, { Criterion } from "../SearchBox"; | import SearchBox, { Criterion } from "../SearchBox"; | ||||
import ProgressByClientSearch from "@/components/ProgressByClientSearch"; | import ProgressByClientSearch from "@/components/ProgressByClientSearch"; | ||||
import { Suspense } from "react"; | import { Suspense } from "react"; | ||||
interface Props { | interface Props { | ||||
Title: string; | |||||
TotalActiveProjectNumber: string; | |||||
TotalFees: string; | |||||
TotalBudget: string; | |||||
TotalCumulative: string; | |||||
TotalInvoicedAmount: string; | |||||
TotalReceivedAmount: string; | |||||
CashFlowStatus: string; | |||||
CostPerformanceIndex: string; | |||||
ClickedIndex: number; | |||||
Index: number; | |||||
} | |||||
Title: string; | |||||
TotalActiveProjectNumber: string; | |||||
TotalFees: string; | |||||
TotalBudget: string; | |||||
TotalCumulative: string; | |||||
TotalInvoicedAmount: string; | |||||
TotalReceivedAmount: string; | |||||
CashFlowStatus: string; | |||||
CostPerformanceIndex: string; | |||||
ClickedIndex: number; | |||||
Index: number; | |||||
} | |||||
const ProjectFinancialCard: React.FC<Props> = ({Title,TotalActiveProjectNumber,TotalFees,TotalBudget,TotalCumulative,TotalInvoicedAmount,TotalReceivedAmount,CashFlowStatus,CostPerformanceIndex,ClickedIndex,Index}) => { | |||||
const [SearchCriteria, setSearchCriteria] = React.useState({}) | |||||
const { t } = useTranslation("dashboard"); | |||||
const borderColor = CashFlowStatus === "Negative" ? "border-red-300 border-solid" : "border-green-200 border-solid" | |||||
const selectedBackgroundColor = ClickedIndex === Index ? "rgb(235 235 235)" : "rgb(255 255 255)" | |||||
console.log(ClickedIndex) | |||||
console.log(Index) | |||||
return ( | |||||
<Card style={{maxWidth:"25%",minWidth:"280px",boxShadow:"0 0px 10px 0 rgba(0, 0, 0, 0.08), 0 0px 10px 0 rgba(0, 0, 0, 0.08)", backgroundColor:selectedBackgroundColor}} className={`${borderColor}`}> | |||||
<div className="text-xl mt-2 font-medium" style={{width:"100%",textAlign:"center",color:"#898d8d"}}>{Title}</div><hr/> | |||||
<div className="text-sm font-medium ml-5" style={{color:"#898d8d"}}>Total Active Project</div> | |||||
<div className="text-lg font-medium ml-5" style={{color:"#6b87cf"}}>{TotalActiveProjectNumber}</div><hr/> | |||||
<div className="text-sm font-medium ml-5" style={{color:"#898d8d"}}>Total Fees</div> | |||||
<div className="text-lg font-medium ml-5" style={{color:"#6b87cf"}}>{TotalFees}</div><hr/> | |||||
<div className="text-sm font-medium ml-5" style={{color:"#898d8d"}}>Total Budget</div> | |||||
<div className="text-lg font-medium ml-5" style={{color:"#6b87cf"}}>{TotalBudget}</div><hr/> | |||||
<div className="text-sm font-medium ml-5" style={{color:"#898d8d"}}>Total Cumulative Expenditure</div> | |||||
<div className="text-lg font-medium ml-5" style={{color:"#6b87cf"}}>{TotalCumulative}</div><hr/> | |||||
<div className="text-sm font-medium ml-5" style={{color:"#898d8d"}}>Total Invoiced Amount</div> | |||||
<div className="text-lg font-medium ml-5" style={{color:"#6b87cf"}}>{TotalInvoicedAmount}</div><hr/> | |||||
<div className="text-sm font-medium ml-5" style={{color:"#898d8d"}}>Total Received Amount</div> | |||||
<div className="text-lg font-medium ml-5" style={{color:"#6b87cf"}}>{TotalReceivedAmount}</div><hr/> | |||||
<div className="text-sm font-medium ml-5" style={{color:"#898d8d"}}>Cash Flow Status</div> | |||||
{CashFlowStatus === "Negative" && ( | |||||
<><div className="text-lg font-medium ml-5" style={{color:"#f896aa"}}>{CashFlowStatus}</div><hr/></> | |||||
)} | |||||
{CashFlowStatus === "Positive" && ( | |||||
<><div className="text-lg font-medium ml-5" style={{color:"#71d19e"}}>{CashFlowStatus}</div><hr/></> | |||||
)} | |||||
<div className="text-sm mt-2 font-medium ml-5" style={{color:"#898d8d"}}>Cost Performance Index (CPI)</div> | |||||
{Number(CostPerformanceIndex) < 1 && ( | |||||
<><div className="text-lg font-medium ml-5 mb-2" style={{color:"#f896aa"}}>{CostPerformanceIndex}</div></> | |||||
)} | |||||
{Number(CostPerformanceIndex) >= 1 && ( | |||||
<><div className="text-lg font-medium ml-5 mb-2" style={{color:"#71d19e"}}>{CostPerformanceIndex}</div></> | |||||
)} | |||||
</Card> | |||||
); | |||||
}; | |||||
export default ProjectFinancialCard; | |||||
const ProjectFinancialCard: React.FC<Props> = ({ | |||||
Title, | |||||
TotalActiveProjectNumber, | |||||
TotalFees, | |||||
TotalBudget, | |||||
TotalCumulative, | |||||
TotalInvoicedAmount, | |||||
TotalReceivedAmount, | |||||
CashFlowStatus, | |||||
CostPerformanceIndex, | |||||
ClickedIndex, | |||||
Index, | |||||
}) => { | |||||
const [SearchCriteria, setSearchCriteria] = React.useState({}); | |||||
const { t } = useTranslation("dashboard"); | |||||
const borderColor = | |||||
CashFlowStatus === "Negative" | |||||
? "border-red-300 border-solid" | |||||
: "border-green-200 border-solid"; | |||||
const selectedBackgroundColor = | |||||
ClickedIndex === Index ? "rgb(235 235 235)" : "rgb(255 255 255)"; | |||||
console.log(ClickedIndex); | |||||
console.log(Index); | |||||
return ( | |||||
<Card | |||||
style={{ | |||||
maxWidth: "25%", | |||||
minWidth: "280px", | |||||
boxShadow: | |||||
"0 0px 10px 0 rgba(0, 0, 0, 0.08), 0 0px 10px 0 rgba(0, 0, 0, 0.08)", | |||||
backgroundColor: selectedBackgroundColor, | |||||
}} | |||||
className={`${borderColor}`} | |||||
> | |||||
<div | |||||
className="text-xl mt-2 font-medium" | |||||
style={{ width: "100%", textAlign: "center", color: "#898d8d" }} | |||||
> | |||||
{Title} | |||||
</div> | |||||
<hr /> | |||||
<div className="text-sm font-medium ml-5" style={{ color: "#898d8d" }}> | |||||
Total Active Project | |||||
</div> | |||||
<div className="text-lg font-medium ml-5" style={{ color: "#6b87cf" }}> | |||||
{TotalActiveProjectNumber} | |||||
</div> | |||||
<hr /> | |||||
<div className="text-sm font-medium ml-5" style={{ color: "#898d8d" }}> | |||||
Total Fees | |||||
</div> | |||||
<div className="text-lg font-medium ml-5" style={{ color: "#6b87cf" }}> | |||||
{TotalFees} | |||||
</div> | |||||
<hr /> | |||||
<div className="text-sm font-medium ml-5" style={{ color: "#898d8d" }}> | |||||
Total Budget | |||||
</div> | |||||
<div className="text-lg font-medium ml-5" style={{ color: "#6b87cf" }}> | |||||
{TotalBudget} | |||||
</div> | |||||
<hr /> | |||||
<div className="text-sm font-medium ml-5" style={{ color: "#898d8d" }}> | |||||
Total Cumulative Expenditure | |||||
</div> | |||||
<div className="text-lg font-medium ml-5" style={{ color: "#6b87cf" }}> | |||||
{TotalCumulative} | |||||
</div> | |||||
<hr /> | |||||
<div className="text-sm font-medium ml-5" style={{ color: "#898d8d" }}> | |||||
Total Invoiced Amount | |||||
</div> | |||||
<div className="text-lg font-medium ml-5" style={{ color: "#6b87cf" }}> | |||||
{TotalInvoicedAmount} | |||||
</div> | |||||
<hr /> | |||||
<div className="text-sm font-medium ml-5" style={{ color: "#898d8d" }}> | |||||
Total Received Amount | |||||
</div> | |||||
<div className="text-lg font-medium ml-5" style={{ color: "#6b87cf" }}> | |||||
{TotalReceivedAmount} | |||||
</div> | |||||
<hr /> | |||||
<div className="text-sm font-medium ml-5" style={{ color: "#898d8d" }}> | |||||
Cash Flow Status | |||||
</div> | |||||
{CashFlowStatus === "Negative" && ( | |||||
<> | |||||
<div | |||||
className="text-lg font-medium ml-5" | |||||
style={{ color: "#f896aa" }} | |||||
> | |||||
{CashFlowStatus} | |||||
</div> | |||||
<hr /> | |||||
</> | |||||
)} | |||||
{CashFlowStatus === "Positive" && ( | |||||
<> | |||||
<div | |||||
className="text-lg font-medium ml-5" | |||||
style={{ color: "#71d19e" }} | |||||
> | |||||
{CashFlowStatus} | |||||
</div> | |||||
<hr /> | |||||
</> | |||||
)} | |||||
<div | |||||
className="text-sm mt-2 font-medium ml-5" | |||||
style={{ color: "#898d8d" }} | |||||
> | |||||
Cost Performance Index (CPI) | |||||
</div> | |||||
{Number(CostPerformanceIndex) < 1 && ( | |||||
<> | |||||
<div | |||||
className="text-lg font-medium ml-5 mb-2" | |||||
style={{ color: "#f896aa" }} | |||||
> | |||||
{CostPerformanceIndex} | |||||
</div> | |||||
</> | |||||
)} | |||||
{Number(CostPerformanceIndex) >= 1 && ( | |||||
<> | |||||
<div | |||||
className="text-lg font-medium ml-5 mb-2" | |||||
style={{ color: "#71d19e" }} | |||||
> | |||||
{CostPerformanceIndex} | |||||
</div> | |||||
</> | |||||
)} | |||||
</Card> | |||||
); | |||||
}; | |||||
export default ProjectFinancialCard; |
@@ -1,19 +1,19 @@ | |||||
"use client"; | "use client"; | ||||
import * as React from "react"; | import * as React from "react"; | ||||
import Grid from "@mui/material/Grid"; | import Grid from "@mui/material/Grid"; | ||||
import { useState,useEffect, useMemo } from 'react' | |||||
import { useState, useEffect, useMemo } from "react"; | |||||
import Paper from "@mui/material/Paper"; | import Paper from "@mui/material/Paper"; | ||||
import { TFunction } from "i18next"; | import { TFunction } from "i18next"; | ||||
import { useTranslation } from "react-i18next"; | import { useTranslation } from "react-i18next"; | ||||
import {Card,CardHeader} from '@mui/material'; | |||||
import { Card, CardHeader } from "@mui/material"; | |||||
import CustomSearchForm from "../CustomSearchForm/CustomSearchForm"; | import CustomSearchForm from "../CustomSearchForm/CustomSearchForm"; | ||||
import CustomDatagrid from '../CustomDatagrid/CustomDatagrid'; | |||||
import ReactApexChart from 'react-apexcharts'; | |||||
import { ApexOptions } from 'apexcharts'; | |||||
import { GridColDef, GridRowSelectionModel} from '@mui/x-data-grid'; | |||||
import ReportProblemIcon from '@mui/icons-material/ReportProblem'; | |||||
import dynamic from 'next/dynamic'; | |||||
import '../../app/global.css'; | |||||
import CustomDatagrid from "../CustomDatagrid/CustomDatagrid"; | |||||
import ReactApexChart from "react-apexcharts"; | |||||
import { ApexOptions } from "apexcharts"; | |||||
import { GridColDef, GridRowSelectionModel } from "@mui/x-data-grid"; | |||||
import ReportProblemIcon from "@mui/icons-material/ReportProblem"; | |||||
import dynamic from "next/dynamic"; | |||||
import "../../app/global.css"; | |||||
import { AnyARecord, AnyCnameRecord } from "dns"; | import { AnyARecord, AnyCnameRecord } from "dns"; | ||||
import SearchBox, { Criterion } from "../SearchBox"; | import SearchBox, { Criterion } from "../SearchBox"; | ||||
import ProgressByClientSearch from "@/components/ProgressByClientSearch"; | import ProgressByClientSearch from "@/components/ProgressByClientSearch"; | ||||
@@ -21,251 +21,453 @@ import { Suspense } from "react"; | |||||
import ProjectFinancialCard from "./ProjectFinancialCard"; | import ProjectFinancialCard from "./ProjectFinancialCard"; | ||||
const ProjectFinancialSummary: React.FC = () => { | const ProjectFinancialSummary: React.FC = () => { | ||||
const [SearchCriteria, setSearchCriteria] = React.useState({}) | |||||
const [SearchCriteria, setSearchCriteria] = React.useState({}); | |||||
const { t } = useTranslation("dashboard"); | const { t } = useTranslation("dashboard"); | ||||
const [selectionModel, setSelectionModel] : any[] = React.useState([]); | |||||
const [selectionModel, setSelectionModel]: any[] = React.useState([]); | |||||
const projectFinancialData = [ | const projectFinancialData = [ | ||||
{id:1,title:"All Teams",activeProject:"147",fees:"22,800,000.00",budget:"18,240,000.00",cumulativeExpenditure:"17,950,000.00",invoicedAmount:"18,240,000.00",receivedAmount:"10,900,000.00",cashFlowStatus:"Negative",CPI:"0.69"}, | |||||
{id:2,title:"XXX Team",activeProject:"25",fees:"1,500,000.00",budget:"1,200,000.00",cumulativeExpenditure:"1,250,000.00",invoicedAmount:"900,000.00",receivedAmount:"650,000.00",cashFlowStatus:"Negative",CPI:"0.72"}, | |||||
{id:3,title:"YYY Team",activeProject:"35",fees:"5,000,000.00",budget:"4,000,000.00",cumulativeExpenditure:"3,200,000.00",invoicedAmount:"3,500,000.00",receivedAmount:"3,500,000.00",cashFlowStatus:"Positive",CPI:"1.09"}, | |||||
{id:4,title:"ZZZ Team",activeProject:"50",fees:"3,500,000.00",budget:"2,800,000.00",cumulativeExpenditure:"5,600,000.00",invoicedAmount:"2,500,000.00",receivedAmount:"2,200,000.00",cashFlowStatus:"Negative",CPI:"0.45"}, | |||||
{id:5,title:"AAA Team",activeProject:"15",fees:"4,800,000.00",budget:"3,840,000.00",cumulativeExpenditure:"2,500,000.00",invoicedAmount:"1,500,000.00",receivedAmount:"750,000.00",cashFlowStatus:"Negative",CPI:"0.60"}, | |||||
{id:6,title:"BBB Team",activeProject:"22",fees:"8,000,000.00",budget:"6,400,000.00",cumulativeExpenditure:"5,400,000.00",invoicedAmount:"4,000,000.00",receivedAmount:"3,800,000.00",cashFlowStatus:"Negative",CPI:"0.74"} | |||||
] | |||||
{ | |||||
id: 1, | |||||
title: "All Teams", | |||||
activeProject: "147", | |||||
fees: "22,800,000.00", | |||||
budget: "18,240,000.00", | |||||
cumulativeExpenditure: "17,950,000.00", | |||||
invoicedAmount: "18,240,000.00", | |||||
receivedAmount: "10,900,000.00", | |||||
cashFlowStatus: "Negative", | |||||
CPI: "0.69", | |||||
}, | |||||
{ | |||||
id: 2, | |||||
title: "XXX Team", | |||||
activeProject: "25", | |||||
fees: "1,500,000.00", | |||||
budget: "1,200,000.00", | |||||
cumulativeExpenditure: "1,250,000.00", | |||||
invoicedAmount: "900,000.00", | |||||
receivedAmount: "650,000.00", | |||||
cashFlowStatus: "Negative", | |||||
CPI: "0.72", | |||||
}, | |||||
{ | |||||
id: 3, | |||||
title: "YYY Team", | |||||
activeProject: "35", | |||||
fees: "5,000,000.00", | |||||
budget: "4,000,000.00", | |||||
cumulativeExpenditure: "3,200,000.00", | |||||
invoicedAmount: "3,500,000.00", | |||||
receivedAmount: "3,500,000.00", | |||||
cashFlowStatus: "Positive", | |||||
CPI: "1.09", | |||||
}, | |||||
{ | |||||
id: 4, | |||||
title: "ZZZ Team", | |||||
activeProject: "50", | |||||
fees: "3,500,000.00", | |||||
budget: "2,800,000.00", | |||||
cumulativeExpenditure: "5,600,000.00", | |||||
invoicedAmount: "2,500,000.00", | |||||
receivedAmount: "2,200,000.00", | |||||
cashFlowStatus: "Negative", | |||||
CPI: "0.45", | |||||
}, | |||||
{ | |||||
id: 5, | |||||
title: "AAA Team", | |||||
activeProject: "15", | |||||
fees: "4,800,000.00", | |||||
budget: "3,840,000.00", | |||||
cumulativeExpenditure: "2,500,000.00", | |||||
invoicedAmount: "1,500,000.00", | |||||
receivedAmount: "750,000.00", | |||||
cashFlowStatus: "Negative", | |||||
CPI: "0.60", | |||||
}, | |||||
{ | |||||
id: 6, | |||||
title: "BBB Team", | |||||
activeProject: "22", | |||||
fees: "8,000,000.00", | |||||
budget: "6,400,000.00", | |||||
cumulativeExpenditure: "5,400,000.00", | |||||
invoicedAmount: "4,000,000.00", | |||||
receivedAmount: "3,800,000.00", | |||||
cashFlowStatus: "Negative", | |||||
CPI: "0.74", | |||||
}, | |||||
]; | |||||
const rows0 = [{id: 1,projectCode:"M1201",projectName:"Consultancy Project C", team:"XXX", teamLeader:"XXX", startDate:"01/08/2022", targetEndDate: "01/05/2024", client:"Client A", subsidiary:"N/A"}, | |||||
{id: 2,projectCode:"M1321",projectName:"Consultancy Project CCC", team:"XXX", teamLeader:"XXX", startDate:"01/08/2022", targetEndDate: "20/01/2024", client:"Client E", subsidiary:"Subsidiary B"}, | |||||
{id: 3,projectCode:"M1001",projectName:"Consultancy Project A", team:"YYY", teamLeader:"YYY", startDate:"01/07/2022", targetEndDate: "01/04/2024", client:"Client B", subsidiary:"N/A"}, | |||||
{id: 4,projectCode:"M1301",projectName:"Consultancy Project AAAA", team:"YYY", teamLeader:"YYY", startDate:"01/09/2022", targetEndDate: "20/02/2024", client:"Client C", subsidiary:"Subsidiary A"}, | |||||
{id: 5,projectCode:"M1354",projectName:"Consultancy Project BBB", team:"YYY", teamLeader:"YYY", startDate:"01/02/2023", targetEndDate: "31/01/2024", client:"Client D", subsidiary:"Subsidiary C"} | |||||
] | |||||
const rows0 = [ | |||||
{ | |||||
id: 1, | |||||
projectCode: "M1201", | |||||
projectName: "Consultancy Project C", | |||||
team: "XXX", | |||||
teamLeader: "XXX", | |||||
startDate: "01/08/2022", | |||||
targetEndDate: "01/05/2024", | |||||
client: "Client A", | |||||
subsidiary: "N/A", | |||||
}, | |||||
{ | |||||
id: 2, | |||||
projectCode: "M1321", | |||||
projectName: "Consultancy Project CCC", | |||||
team: "XXX", | |||||
teamLeader: "XXX", | |||||
startDate: "01/08/2022", | |||||
targetEndDate: "20/01/2024", | |||||
client: "Client E", | |||||
subsidiary: "Subsidiary B", | |||||
}, | |||||
{ | |||||
id: 3, | |||||
projectCode: "M1001", | |||||
projectName: "Consultancy Project A", | |||||
team: "YYY", | |||||
teamLeader: "YYY", | |||||
startDate: "01/07/2022", | |||||
targetEndDate: "01/04/2024", | |||||
client: "Client B", | |||||
subsidiary: "N/A", | |||||
}, | |||||
{ | |||||
id: 4, | |||||
projectCode: "M1301", | |||||
projectName: "Consultancy Project AAAA", | |||||
team: "YYY", | |||||
teamLeader: "YYY", | |||||
startDate: "01/09/2022", | |||||
targetEndDate: "20/02/2024", | |||||
client: "Client C", | |||||
subsidiary: "Subsidiary A", | |||||
}, | |||||
{ | |||||
id: 5, | |||||
projectCode: "M1354", | |||||
projectName: "Consultancy Project BBB", | |||||
team: "YYY", | |||||
teamLeader: "YYY", | |||||
startDate: "01/02/2023", | |||||
targetEndDate: "31/01/2024", | |||||
client: "Client D", | |||||
subsidiary: "Subsidiary C", | |||||
}, | |||||
]; | |||||
const rows1 = [{id: 1,projectCode:"M1201",projectName:"Consultancy Project C", team:"XXX", teamLeader:"XXX", startDate:"01/08/2022", targetEndDate: "01/05/2024", client:"Client A", subsidiary:"N/A"}, | |||||
{id: 2,projectCode:"M1321",projectName:"Consultancy Project CCC", team:"XXX", teamLeader:"XXX", startDate:"01/08/2022", targetEndDate: "20/01/2024", client:"Client E", subsidiary:"Subsidiary B"}, | |||||
] | |||||
const rows1 = [ | |||||
{ | |||||
id: 1, | |||||
projectCode: "M1201", | |||||
projectName: "Consultancy Project C", | |||||
team: "XXX", | |||||
teamLeader: "XXX", | |||||
startDate: "01/08/2022", | |||||
targetEndDate: "01/05/2024", | |||||
client: "Client A", | |||||
subsidiary: "N/A", | |||||
}, | |||||
{ | |||||
id: 2, | |||||
projectCode: "M1321", | |||||
projectName: "Consultancy Project CCC", | |||||
team: "XXX", | |||||
teamLeader: "XXX", | |||||
startDate: "01/08/2022", | |||||
targetEndDate: "20/01/2024", | |||||
client: "Client E", | |||||
subsidiary: "Subsidiary B", | |||||
}, | |||||
]; | |||||
const rows2 = [{id: 3,projectCode:"M1001",projectName:"Consultancy Project A", team:"YYY", teamLeader:"YYY", startDate:"01/07/2022", targetEndDate: "01/04/2024", client:"Client B", subsidiary:"N/A"}, | |||||
{id: 4,projectCode:"M1301",projectName:"Consultancy Project AAAA", team:"YYY", teamLeader:"YYY", startDate:"01/09/2022", targetEndDate: "20/02/2024", client:"Client C", subsidiary:"Subsidiary A"}, | |||||
{id: 5,projectCode:"M1354",projectName:"Consultancy Project BBB", team:"YYY", teamLeader:"YYY", startDate:"01/02/2023", targetEndDate: "31/01/2024", client:"Client D", subsidiary:"Subsidiary C"} | |||||
] | |||||
const rows2 = [ | |||||
{ | |||||
id: 3, | |||||
projectCode: "M1001", | |||||
projectName: "Consultancy Project A", | |||||
team: "YYY", | |||||
teamLeader: "YYY", | |||||
startDate: "01/07/2022", | |||||
targetEndDate: "01/04/2024", | |||||
client: "Client B", | |||||
subsidiary: "N/A", | |||||
}, | |||||
{ | |||||
id: 4, | |||||
projectCode: "M1301", | |||||
projectName: "Consultancy Project AAAA", | |||||
team: "YYY", | |||||
teamLeader: "YYY", | |||||
startDate: "01/09/2022", | |||||
targetEndDate: "20/02/2024", | |||||
client: "Client C", | |||||
subsidiary: "Subsidiary A", | |||||
}, | |||||
{ | |||||
id: 5, | |||||
projectCode: "M1354", | |||||
projectName: "Consultancy Project BBB", | |||||
team: "YYY", | |||||
teamLeader: "YYY", | |||||
startDate: "01/02/2023", | |||||
targetEndDate: "31/01/2024", | |||||
client: "Client D", | |||||
subsidiary: "Subsidiary C", | |||||
}, | |||||
]; | |||||
const projectFinancialRows = [{id: 1,cashFlowStatus:"Positive",cpi:"1.25", totalFees:"500,000.00", totalBudget:"400,000.00", totalCumulativeExpenditure:"280,000.00", totalInvoicedAmount: "350,000.00", totalUnInvoicedAmount:"150,000.00", totalReceivedAmount:"350,000.00", totalUnReceivedAmount:"0.00"} | |||||
] | |||||
const projectFinancialRows = [ | |||||
{ | |||||
id: 1, | |||||
cashFlowStatus: "Positive", | |||||
cpi: "1.25", | |||||
totalFees: "500,000.00", | |||||
totalBudget: "400,000.00", | |||||
totalCumulativeExpenditure: "280,000.00", | |||||
totalInvoicedAmount: "350,000.00", | |||||
totalUnInvoicedAmount: "150,000.00", | |||||
totalReceivedAmount: "350,000.00", | |||||
totalUnReceivedAmount: "0.00", | |||||
}, | |||||
]; | |||||
const [isCardClickedIndex, setIsCardClickedIndex] = React.useState(0); | const [isCardClickedIndex, setIsCardClickedIndex] = React.useState(0); | ||||
const [selectedTeamData, setSelectedTeamData] : any[] = React.useState(rows0); | |||||
const [selectedTeamData, setSelectedTeamData]: any[] = React.useState(rows0); | |||||
const handleCardClick = (r:any) => { | |||||
setIsCardClickedIndex(r) | |||||
if (r === 0) { | |||||
setSelectedTeamData(rows0) | |||||
} else if (r === 1) { | |||||
setSelectedTeamData(rows1) | |||||
} else if (r === 2) { | |||||
setSelectedTeamData(rows2) | |||||
} | |||||
const handleCardClick = (r: any) => { | |||||
setIsCardClickedIndex(r); | |||||
if (r === 0) { | |||||
setSelectedTeamData(rows0); | |||||
} else if (r === 1) { | |||||
setSelectedTeamData(rows1); | |||||
} else if (r === 2) { | |||||
setSelectedTeamData(rows2); | |||||
} | |||||
}; | }; | ||||
const columns = [ | const columns = [ | ||||
{ | { | ||||
id: 'projectCode', | |||||
field: 'projectCode', | |||||
id: "projectCode", | |||||
field: "projectCode", | |||||
headerName: "Project Code", | headerName: "Project Code", | ||||
flex: 1, | flex: 1, | ||||
}, | |||||
{ | |||||
id: 'projectName', | |||||
field: 'projectName', | |||||
}, | |||||
{ | |||||
id: "projectName", | |||||
field: "projectName", | |||||
headerName: "Project Name", | headerName: "Project Name", | ||||
flex: 1, | flex: 1, | ||||
}, | |||||
{ | |||||
id: 'team', | |||||
field: 'team', | |||||
headerName: "Team", | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: 'teamLeader', | |||||
field: 'teamLeader', | |||||
headerName: "Team Leader", | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: 'startDate', | |||||
field: 'startDate', | |||||
headerName: "Start Date", | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: 'targetEndDate', | |||||
field: 'targetEndDate', | |||||
headerName: "Target End Date", | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: 'client', | |||||
field: 'client', | |||||
headerName: "Client", | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: 'subsidiary', | |||||
field: 'subsidiary', | |||||
headerName: "Subsidiary", | |||||
flex: 1, | |||||
}, | |||||
]; | |||||
}, | |||||
{ | |||||
id: "team", | |||||
field: "team", | |||||
headerName: "Team", | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: "teamLeader", | |||||
field: "teamLeader", | |||||
headerName: "Team Leader", | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: "startDate", | |||||
field: "startDate", | |||||
headerName: "Start Date", | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: "targetEndDate", | |||||
field: "targetEndDate", | |||||
headerName: "Target End Date", | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: "client", | |||||
field: "client", | |||||
headerName: "Client", | |||||
flex: 1, | |||||
}, | |||||
{ | |||||
id: "subsidiary", | |||||
field: "subsidiary", | |||||
headerName: "Subsidiary", | |||||
flex: 1, | |||||
}, | |||||
]; | |||||
const columns2 = [ | |||||
{ | |||||
id: 'cashFlowStatus', | |||||
field: 'cashFlowStatus', | |||||
headerName: "Cash Flow Status", | |||||
flex: 1, | |||||
renderCell: (params:any) => { | |||||
if (params.row.cashFlowStatus === "Positive") { | |||||
return ( | |||||
<span className="text-lime-500">{params.row.cashFlowStatus}</span> | |||||
) | |||||
} else if (params.row.cashFlowStatus === "Negative") { | |||||
return ( | |||||
<span className="text-red-500">{params.row.cashFlowStatus}</span> | |||||
) | |||||
} | |||||
}, | |||||
}, | |||||
{ | |||||
id: 'cpi', | |||||
field: 'cpi', | |||||
headerName: "CPI", | |||||
flex: 0.7, | |||||
renderCell: (params:any) => { | |||||
if (params.row.cpi >= 1) { | |||||
return ( | |||||
<span className="text-lime-500">{params.row.cpi}</span> | |||||
) | |||||
} else if (params.row.cpi < 1) { | |||||
return ( | |||||
<span className="text-red-500">{params.row.cpi}</span> | |||||
) | |||||
} | |||||
}, | |||||
}, | |||||
{ | |||||
id: 'totalFees', | |||||
field: 'totalFees', | |||||
headerName: "Total Fees (HKD)", | |||||
flex: 1, | |||||
renderCell: (params:any) => { | |||||
return ( | |||||
<span>${params.row.totalFees}</span> | |||||
) | |||||
}, | |||||
}, | |||||
{ | |||||
id: 'totalBudget', | |||||
field: 'totalBudget', | |||||
headerName: "Total Budget (HKD)", | |||||
flex: 1, | |||||
renderCell: (params:any) => { | |||||
return ( | |||||
<span>${params.row.totalBudget}</span> | |||||
) | |||||
}, | |||||
}, | |||||
{ | |||||
id: 'totalCumulativeExpenditure', | |||||
field: 'totalCumulativeExpenditure', | |||||
headerName: "Total Cumulative Expenditure (HKD)", | |||||
flex: 1, | |||||
renderCell: (params:any) => { | |||||
return ( | |||||
<span>${params.row.totalCumulativeExpenditure}</span> | |||||
) | |||||
}, | |||||
}, | |||||
{ | |||||
id: 'totalInvoicedAmount', | |||||
field: 'totalInvoicedAmount', | |||||
headerName: "Total Invoiced Amount (HKD)", | |||||
flex: 1, | |||||
renderCell: (params:any) => { | |||||
return ( | |||||
<span>${params.row.totalInvoicedAmount}</span> | |||||
) | |||||
}, | |||||
}, | |||||
{ | |||||
id: 'totalUnInvoicedAmount', | |||||
field: 'totalUnInvoicedAmount', | |||||
headerName: "Total Un-invoiced Amount (HKD)", | |||||
flex: 1, | |||||
renderCell: (params:any) => { | |||||
return ( | |||||
<span>${params.row.totalUnInvoicedAmount}</span> | |||||
) | |||||
}, | |||||
}, | |||||
{ | |||||
id: 'totalReceivedAmount', | |||||
field: 'totalReceivedAmount', | |||||
headerName: "Total Received Amount (HKD)", | |||||
flex: 1, | |||||
renderCell: (params:any) => { | |||||
return ( | |||||
<span>${params.row.totalReceivedAmount}</span> | |||||
) | |||||
}, | |||||
}, | |||||
{ | |||||
id: 'totalUnReceivedAmount', | |||||
field: 'totalUnReceivedAmount', | |||||
headerName: "Total Un-received Amount (HKD)", | |||||
flex: 1, | |||||
renderCell: (params:any) => { | |||||
return ( | |||||
<span>${params.row.totalUnReceivedAmount}</span> | |||||
) | |||||
}, | |||||
}, | |||||
]; | |||||
const columns2 = [ | |||||
{ | |||||
id: "cashFlowStatus", | |||||
field: "cashFlowStatus", | |||||
headerName: "Cash Flow Status", | |||||
flex: 1, | |||||
renderCell: (params: any) => { | |||||
if (params.row.cashFlowStatus === "Positive") { | |||||
return ( | |||||
<span className="text-lime-500">{params.row.cashFlowStatus}</span> | |||||
); | |||||
} else if (params.row.cashFlowStatus === "Negative") { | |||||
return ( | |||||
<span className="text-red-500">{params.row.cashFlowStatus}</span> | |||||
); | |||||
} | |||||
}, | |||||
}, | |||||
{ | |||||
id: "cpi", | |||||
field: "cpi", | |||||
headerName: "CPI", | |||||
flex: 0.7, | |||||
renderCell: (params: any) => { | |||||
if (params.row.cpi >= 1) { | |||||
return <span className="text-lime-500">{params.row.cpi}</span>; | |||||
} else if (params.row.cpi < 1) { | |||||
return <span className="text-red-500">{params.row.cpi}</span>; | |||||
} | |||||
}, | |||||
}, | |||||
{ | |||||
id: "totalFees", | |||||
field: "totalFees", | |||||
headerName: "Total Fees (HKD)", | |||||
flex: 1, | |||||
renderCell: (params: any) => { | |||||
return <span>${params.row.totalFees}</span>; | |||||
}, | |||||
}, | |||||
{ | |||||
id: "totalBudget", | |||||
field: "totalBudget", | |||||
headerName: "Total Budget (HKD)", | |||||
flex: 1, | |||||
renderCell: (params: any) => { | |||||
return <span>${params.row.totalBudget}</span>; | |||||
}, | |||||
}, | |||||
{ | |||||
id: "totalCumulativeExpenditure", | |||||
field: "totalCumulativeExpenditure", | |||||
headerName: "Total Cumulative Expenditure (HKD)", | |||||
flex: 1, | |||||
renderCell: (params: any) => { | |||||
return <span>${params.row.totalCumulativeExpenditure}</span>; | |||||
}, | |||||
}, | |||||
{ | |||||
id: "totalInvoicedAmount", | |||||
field: "totalInvoicedAmount", | |||||
headerName: "Total Invoiced Amount (HKD)", | |||||
flex: 1, | |||||
renderCell: (params: any) => { | |||||
return <span>${params.row.totalInvoicedAmount}</span>; | |||||
}, | |||||
}, | |||||
{ | |||||
id: "totalUnInvoicedAmount", | |||||
field: "totalUnInvoicedAmount", | |||||
headerName: "Total Un-invoiced Amount (HKD)", | |||||
flex: 1, | |||||
renderCell: (params: any) => { | |||||
return <span>${params.row.totalUnInvoicedAmount}</span>; | |||||
}, | |||||
}, | |||||
{ | |||||
id: "totalReceivedAmount", | |||||
field: "totalReceivedAmount", | |||||
headerName: "Total Received Amount (HKD)", | |||||
flex: 1, | |||||
renderCell: (params: any) => { | |||||
return <span>${params.row.totalReceivedAmount}</span>; | |||||
}, | |||||
}, | |||||
{ | |||||
id: "totalUnReceivedAmount", | |||||
field: "totalUnReceivedAmount", | |||||
headerName: "Total Un-received Amount (HKD)", | |||||
flex: 1, | |||||
renderCell: (params: any) => { | |||||
return <span>${params.row.totalUnReceivedAmount}</span>; | |||||
}, | |||||
}, | |||||
]; | |||||
const handleSelectionChange = (newSelectionModel: GridRowSelectionModel) => { | const handleSelectionChange = (newSelectionModel: GridRowSelectionModel) => { | ||||
const selectedRowsData = selectedTeamData.filter((row:any) => | |||||
newSelectionModel.includes(row.id) | |||||
const selectedRowsData = selectedTeamData.filter((row: any) => | |||||
newSelectionModel.includes(row.id), | |||||
); | ); | ||||
console.log(selectedRowsData) | |||||
} | |||||
console.log(selectedRowsData); | |||||
}; | |||||
return ( | return ( | ||||
<Grid item sm> | |||||
<Card> | |||||
<CardHeader className="text-slate-500" title="Active Project Financial Status"/> | |||||
<div className="ml-10 mr-10" style={{ display: 'flex', flexWrap: 'wrap', justifyContent: 'start'}}> | |||||
{projectFinancialData.map((record, index) => ( | |||||
<div className="hover:cursor-pointer ml-4 mt-5 mb-4 inline-block" key={index} onClick={(r) => handleCardClick(index)}> | |||||
<ProjectFinancialCard Title={record.title} TotalActiveProjectNumber={record.activeProject} TotalFees={record.fees} TotalBudget={record.budget} TotalCumulative={record.cumulativeExpenditure} TotalInvoicedAmount={record.invoicedAmount} TotalReceivedAmount={record.receivedAmount} CashFlowStatus={record.cashFlowStatus} CostPerformanceIndex={record.CPI} ClickedIndex={isCardClickedIndex} Index={index}/> | |||||
</div> | |||||
))} | |||||
</div> | |||||
</Card> | |||||
<Card className="mt-5"> | |||||
<CardHeader className="text-slate-500" title="Selected Team's Project"/> | |||||
<div style={{display:"inline-block",width:"99%",marginLeft:10}}> | |||||
<CustomDatagrid rows={selectedTeamData} columns={columns} columnWidth={200} dataGridHeight={300} checkboxSelection={true} onRowSelectionModelChange={handleSelectionChange} selectionModel={selectionModel}/> | |||||
</div> | |||||
</Card> | |||||
<Card className="mt-5"> | |||||
<CardHeader className="text-slate-500" title="Individual Project Financial Status"/> | |||||
<div style={{display:"inline-block",width:"99%",marginLeft:10}}> | |||||
<CustomDatagrid rows={projectFinancialRows} columns={columns2} columnWidth={200} dataGridHeight={300}/> | |||||
</div> | |||||
</Card> | |||||
</Grid> | |||||
<Grid item sm> | |||||
<Card> | |||||
<CardHeader | |||||
className="text-slate-500" | |||||
title="Active Project Financial Status" | |||||
/> | |||||
<div | |||||
className="ml-10 mr-10" | |||||
style={{ display: "flex", flexWrap: "wrap", justifyContent: "start" }} | |||||
> | |||||
{projectFinancialData.map((record, index) => ( | |||||
<div | |||||
className="hover:cursor-pointer ml-4 mt-5 mb-4 inline-block" | |||||
key={index} | |||||
onClick={(r) => handleCardClick(index)} | |||||
> | |||||
<ProjectFinancialCard | |||||
Title={record.title} | |||||
TotalActiveProjectNumber={record.activeProject} | |||||
TotalFees={record.fees} | |||||
TotalBudget={record.budget} | |||||
TotalCumulative={record.cumulativeExpenditure} | |||||
TotalInvoicedAmount={record.invoicedAmount} | |||||
TotalReceivedAmount={record.receivedAmount} | |||||
CashFlowStatus={record.cashFlowStatus} | |||||
CostPerformanceIndex={record.CPI} | |||||
ClickedIndex={isCardClickedIndex} | |||||
Index={index} | |||||
/> | |||||
</div> | |||||
))} | |||||
</div> | |||||
</Card> | |||||
<Card className="mt-5"> | |||||
<CardHeader | |||||
className="text-slate-500" | |||||
title="Selected Team's Project" | |||||
/> | |||||
<div style={{ display: "inline-block", width: "99%", marginLeft: 10 }}> | |||||
<CustomDatagrid | |||||
rows={selectedTeamData} | |||||
columns={columns} | |||||
columnWidth={200} | |||||
dataGridHeight={300} | |||||
checkboxSelection={true} | |||||
onRowSelectionModelChange={handleSelectionChange} | |||||
selectionModel={selectionModel} | |||||
/> | |||||
</div> | |||||
</Card> | |||||
<Card className="mt-5"> | |||||
<CardHeader | |||||
className="text-slate-500" | |||||
title="Individual Project Financial Status" | |||||
/> | |||||
<div style={{ display: "inline-block", width: "99%", marginLeft: 10 }}> | |||||
<CustomDatagrid | |||||
rows={projectFinancialRows} | |||||
columns={columns2} | |||||
columnWidth={200} | |||||
dataGridHeight={300} | |||||
/> | |||||
</div> | |||||
</Card> | |||||
</Grid> | |||||
); | ); | ||||
}; | }; | ||||
@@ -1,23 +1,22 @@ | |||||
import Swal from "sweetalert2"; | import Swal from "sweetalert2"; | ||||
export const msg = (text) => { | export const msg = (text) => { | ||||
Swal.mixin({ | |||||
toast: true, | |||||
position: "bottom-end", | |||||
showConfirmButton: false, | |||||
timer: 3000, | |||||
timerProgressBar: true, | |||||
didOpen: (toast) => { | |||||
toast.onmouseenter = Swal.stopTimer; | |||||
toast.onmouseleave = Swal.resumeTimer; | |||||
} | |||||
}).fire({ | |||||
icon: "Success", | |||||
title: text | |||||
}); | |||||
} | |||||
Swal.mixin({ | |||||
toast: true, | |||||
position: "bottom-end", | |||||
showConfirmButton: false, | |||||
timer: 3000, | |||||
timerProgressBar: true, | |||||
didOpen: (toast) => { | |||||
toast.onmouseenter = Swal.stopTimer; | |||||
toast.onmouseleave = Swal.resumeTimer; | |||||
}, | |||||
}).fire({ | |||||
icon: "Success", | |||||
title: text, | |||||
}); | |||||
}; | |||||
export const popup = (text) => { | export const popup = (text) => { | ||||
Swal.fire(text); | |||||
} | |||||
Swal.fire(text); | |||||
}; |
@@ -1,44 +1,78 @@ | |||||
"use client"; | "use client"; | ||||
import * as React from "react"; | import * as React from "react"; | ||||
import Grid from "@mui/material/Grid"; | import Grid from "@mui/material/Grid"; | ||||
import { useEffect, useState } from 'react' | |||||
import { TFunction } from "i18next"; | |||||
import { useTranslation } from "react-i18next"; | |||||
import {Card,CardContent,CardHeader} from '@mui/material'; | |||||
import CustomCardGrid from '../CustomCardGrid/CustomCardGrid'; | |||||
import '../../app/global.css'; | |||||
import { useEffect } from "react"; | |||||
import { Card, CardContent, CardHeader } from "@mui/material"; | |||||
import CustomCardGrid from "../CustomCardGrid/CustomCardGrid"; | |||||
import "../../app/global.css"; | |||||
import { PROJECT_CARD_STYLE } from "@/theme/colorConst"; | import { PROJECT_CARD_STYLE } from "@/theme/colorConst"; | ||||
interface ProjectGridProps { | interface ProjectGridProps { | ||||
tab: number; | tab: number; | ||||
} | } | ||||
const cards = [ | |||||
{ | |||||
code: "M1001 (C)", | |||||
name: "Consultancy Project A", | |||||
hr_spent: 12.75, | |||||
hr_spent_normal: 0.0, | |||||
hr_alloc: 150.0, | |||||
hr_alloc_normal: 30.0, | |||||
}, | |||||
{ | |||||
code: "M1301 (C)", | |||||
name: "Consultancy Project AAA", | |||||
hr_spent: 4.25, | |||||
hr_spent_normal: 0.25, | |||||
hr_alloc: 30.0, | |||||
hr_alloc_normal: 0.0, | |||||
}, | |||||
{ | |||||
code: "M1354 (C)", | |||||
name: "Consultancy Project BBB", | |||||
hr_spent: 57.0, | |||||
hr_spent_normal: 6.5, | |||||
hr_alloc: 100.0, | |||||
hr_alloc_normal: 20.0, | |||||
}, | |||||
{ | |||||
code: "M1973 (C)", | |||||
name: "Construction Project CCC", | |||||
hr_spent: 12.75, | |||||
hr_spent_normal: 0.0, | |||||
hr_alloc: 150.0, | |||||
hr_alloc_normal: 30.0, | |||||
}, | |||||
{ | |||||
code: "M2014 (T)", | |||||
name: "Consultancy Project DDD", | |||||
hr_spent: 1.0, | |||||
hr_spent_normal: 0.0, | |||||
hr_alloc: 10.0, | |||||
hr_alloc_normal: 0.0, | |||||
}, | |||||
]; | |||||
const ProjectGrid: React.FC<ProjectGridProps> = (props) => { | const ProjectGrid: React.FC<ProjectGridProps> = (props) => { | ||||
const [items, setItems] = React.useState<Object[]>([]) | |||||
const [items, setItems] = React.useState<typeof cards>([]); | |||||
useEffect(() => { | useEffect(() => { | ||||
if (props.tab == 0) { | if (props.tab == 0) { | ||||
setItems(cards) | |||||
} | |||||
else { | |||||
const filteredItems = cards;//cards.filter(item => (item.track == props.tab)); | |||||
setItems(cards); | |||||
} else { | |||||
const filteredItems = cards; //cards.filter(item => (item.track == props.tab)); | |||||
setItems(filteredItems); | setItems(filteredItems); | ||||
} | } | ||||
}, [props.tab]); | }, [props.tab]); | ||||
const cards = [ | |||||
{code: 'M1001 (C)', name: 'Consultancy Project A', hr_spent: 12.75, hr_spent_normal: 0.00, hr_alloc: 150.00, hr_alloc_normal: 30.00}, | |||||
{code: 'M1301 (C)', name: 'Consultancy Project AAA', hr_spent: 4.25, hr_spent_normal: 0.25, hr_alloc: 30.00, hr_alloc_normal: 0.00}, | |||||
{code: 'M1354 (C)', name: 'Consultancy Project BBB', hr_spent: 57.00, hr_spent_normal: 6.50, hr_alloc: 100.00, hr_alloc_normal: 20.00}, | |||||
{code: 'M1973 (C)', name: 'Construction Project CCC', hr_spent: 12.75, hr_spent_normal: 0.00, hr_alloc: 150.00, hr_alloc_normal: 30.00}, | |||||
{code: 'M2014 (T)', name: 'Consultancy Project DDD', hr_spent: 1.00, hr_spent_normal: 0.00, hr_alloc: 10.00, hr_alloc_normal: 0.00}, | |||||
]; | |||||
const cardLayout = (item: Record<string, string>) => { | const cardLayout = (item: Record<string, string>) => { | ||||
return ( | return ( | ||||
<Card style={PROJECT_CARD_STYLE}> | <Card style={PROJECT_CARD_STYLE}> | ||||
<CardHeader style={{backgroundColor:'pink'}} title={item.code + '\u000A' + item.name}/> | |||||
<CardHeader | |||||
style={{ backgroundColor: "pink" }} | |||||
title={item.code + "\u000A" + item.name} | |||||
/> | |||||
<CardContent> | <CardContent> | ||||
<p>Hours Spent: {item.hr_spent}</p> | <p>Hours Spent: {item.hr_spent}</p> | ||||
<p>Normal (Others): {item.hr_spent_normal}</p> | <p>Normal (Others): {item.hr_spent_normal}</p> | ||||
@@ -47,15 +81,19 @@ const ProjectGrid: React.FC<ProjectGridProps> = (props) => { | |||||
</CardContent> | </CardContent> | ||||
</Card> | </Card> | ||||
); | ); | ||||
} | |||||
}; | |||||
// Apply the preset style to the cards in child, if not specified // | // Apply the preset style to the cards in child, if not specified // | ||||
return ( | return ( | ||||
<Grid container md={12}> | <Grid container md={12}> | ||||
{/* <CustomSearchForm applySearch={applySearch} fields={InputFields}/> */} | |||||
{/* item count = {items?.length??"idk"} , track/tab = {props.tab} */} | |||||
<CustomCardGrid Title={props.tab.toString()} items={items} cardStyle={cardLayout}/> | |||||
{/* <CustomCardGrid Title={props.tab.toString()} rows={rows} columns={columns} columnWidth={200} items={items}/> */} | |||||
</Grid> | |||||
{/* <CustomSearchForm applySearch={applySearch} fields={InputFields}/> */} | |||||
{/* item count = {items?.length??"idk"} , track/tab = {props.tab} */} | |||||
<CustomCardGrid | |||||
Title={props.tab.toString()} | |||||
items={items} | |||||
cardStyle={cardLayout} | |||||
/> | |||||
{/* <CustomCardGrid Title={props.tab.toString()} rows={rows} columns={columns} columnWidth={200} items={items}/> */} | |||||
</Grid> | |||||
); | ); | ||||
}; | }; | ||||
@@ -8,9 +8,9 @@ import PageTitle from "../PageTitle/PageTitle"; | |||||
import { Suspense } from "react"; | import { Suspense } from "react"; | ||||
import Button from "@mui/material/Button"; | import Button from "@mui/material/Button"; | ||||
import Stack from "@mui/material/Stack"; | import Stack from "@mui/material/Stack"; | ||||
import { Add } from '@mui/icons-material'; | |||||
import { Add } from "@mui/icons-material"; | |||||
import Link from "next/link"; | import Link from "next/link"; | ||||
import { t } from 'i18next'; | |||||
import { t } from "i18next"; | |||||
import { Modal } from "@mui/material"; | import { Modal } from "@mui/material"; | ||||
import CustomModal from "../CustomModal/CustomModal"; | import CustomModal from "../CustomModal/CustomModal"; | ||||
import EnterTimesheetModal from "../EnterTimesheet/EnterTimesheetModal"; | import EnterTimesheetModal from "../EnterTimesheet/EnterTimesheetModal"; | ||||
@@ -18,7 +18,6 @@ import EnterTimesheetModal from "../EnterTimesheet/EnterTimesheetModal"; | |||||
const UserWorkspacePage: React.FC = () => { | const UserWorkspacePage: React.FC = () => { | ||||
const [isModalVisible, setModalVisible] = useState(false); | const [isModalVisible, setModalVisible] = useState(false); | ||||
const { t } = useTranslation("home"); | const { t } = useTranslation("home"); | ||||
const handleButtonClick = () => { | const handleButtonClick = () => { | ||||
setModalVisible(true); | setModalVisible(true); | ||||
@@ -29,38 +28,36 @@ const UserWorkspacePage: React.FC = () => { | |||||
}; | }; | ||||
return ( | return ( | ||||
<Grid container height="100vh" > | |||||
<Grid container height="100vh"> | |||||
<Grid item sm> | <Grid item sm> | ||||
<PageTitle BigTitle={"User Workspace"}/> | |||||
<div><Stack | |||||
direction="row" | |||||
justifyContent="right" | |||||
flexWrap="wrap" | |||||
> | |||||
<Button | |||||
variant="contained" | |||||
startIcon={<Add />} | |||||
onClick={handleButtonClick} | |||||
sx={{marginRight:"2rem"}} | |||||
> | |||||
Enter Timesheet | |||||
</Button> | |||||
<Button | |||||
variant="contained" | |||||
startIcon={<Add />} | |||||
sx={{marginRight:"2rem"}} | |||||
LinkComponent={Link} | |||||
href="/projects/create" | |||||
> | |||||
Record Leave | |||||
</Button> | |||||
</Stack> | |||||
<Suspense> {/*fallback={<ProjectSearch.Loading />}>*/} | |||||
</Suspense> | |||||
</div> | |||||
<EnterTimesheetModal isOpen={isModalVisible} onClose={handleCloseModal}/> | |||||
<AssignedProjectGrid Title="Assigned Project"/> | |||||
<PageTitle BigTitle={"User Workspace"} /> | |||||
<div> | |||||
<Stack direction="row" justifyContent="right" flexWrap="wrap"> | |||||
<Button | |||||
variant="contained" | |||||
startIcon={<Add />} | |||||
onClick={handleButtonClick} | |||||
sx={{ marginRight: "2rem" }} | |||||
> | |||||
Enter Timesheet | |||||
</Button> | |||||
<Button | |||||
variant="contained" | |||||
startIcon={<Add />} | |||||
sx={{ marginRight: "2rem" }} | |||||
LinkComponent={Link} | |||||
href="/projects/create" | |||||
> | |||||
Record Leave | |||||
</Button> | |||||
</Stack> | |||||
<Suspense> {/*fallback={<ProjectSearch.Loading />}>*/}</Suspense> | |||||
</div> | |||||
<EnterTimesheetModal | |||||
isOpen={isModalVisible} | |||||
onClose={handleCloseModal} | |||||
/> | |||||
<AssignedProjectGrid Title="Assigned Project" /> | |||||
</Grid> | </Grid> | ||||
</Grid> | </Grid> | ||||
); | ); | ||||
@@ -1,12 +1,11 @@ | |||||
import { createTheme } from '@mui/material/styles'; | |||||
import { createTheme } from "@mui/material/styles"; | |||||
const theme = createTheme({ | const theme = createTheme({ | ||||
palette: { | palette: { | ||||
background: { | background: { | ||||
default: '#fcfcfc' | |||||
} | |||||
} | |||||
default: "#fcfcfc", | |||||
}, | |||||
}, | |||||
}); | }); | ||||
export default theme; | |||||
export default theme; |
@@ -4,51 +4,85 @@ import { aborted } from "util"; | |||||
// - - - - - - WORK IN PROGRESS - - - - - - // | // - - - - - - WORK IN PROGRESS - - - - - - // | ||||
export const chartColor = [ | export const chartColor = [ | ||||
'#CB4047', '#ED3A41', '#F47B50', '#FBA647', | |||||
'#FDB64C', '#CCBB32', '#9ACC59', '#57B962', | |||||
'#1E83C5', '#7C4A9D' | |||||
"#CB4047", | |||||
"#ED3A41", | |||||
"#F47B50", | |||||
"#FBA647", | |||||
"#FDB64C", | |||||
"#CCBB32", | |||||
"#9ACC59", | |||||
"#57B962", | |||||
"#1E83C5", | |||||
"#7C4A9D", | |||||
]; | ]; | ||||
export const chartSingleColor = [ | export const chartSingleColor = [ | ||||
'#f2969a', '#fc9599', '#faa789', '#f7ae94', | |||||
'#ffd491', '#ede5a1', '#d1f5a2', '#9de0a4', | |||||
'#a2d4f5', '#b685d6' | |||||
"#f2969a", | |||||
"#fc9599", | |||||
"#faa789", | |||||
"#f7ae94", | |||||
"#ffd491", | |||||
"#ede5a1", | |||||
"#d1f5a2", | |||||
"#9de0a4", | |||||
"#a2d4f5", | |||||
"#b685d6", | |||||
]; | ]; | ||||
export const rankColor = [ | export const rankColor = [ | ||||
'#FFD700', '#C0C0C0', '#CD853F', '#57B962', '#57B962', | |||||
'#57B962', '#57B962', '#57B962', '#57B962', '#57B962' | |||||
"#FFD700", | |||||
"#C0C0C0", | |||||
"#CD853F", | |||||
"#57B962", | |||||
"#57B962", | |||||
"#57B962", | |||||
"#57B962", | |||||
"#57B962", | |||||
"#57B962", | |||||
"#57B962", | |||||
]; | ]; | ||||
export const piechartColor1 = [ | export const piechartColor1 = [ | ||||
'#E84A3E', '#F2883C', '#FDCD4D', '#CE478A', '#B63D2A', | |||||
'#6A8B9E', '#60667E', '#58865F', '#2F763E', '#7D80B5', | |||||
"#E84A3E", | |||||
"#F2883C", | |||||
"#FDCD4D", | |||||
"#CE478A", | |||||
"#B63D2A", | |||||
"#6A8B9E", | |||||
"#60667E", | |||||
"#58865F", | |||||
"#2F763E", | |||||
"#7D80B5", | |||||
]; | ]; | ||||
export const piechartColor2 = [ | export const piechartColor2 = [ | ||||
'#6A8B9E', '#60667E', '#58865F', '#2F763E', '#7D80B5', | |||||
'#E84A3E', '#F2883C', '#FDCD4D', '#CE478A', '#B63D2A', | |||||
"#6A8B9E", | |||||
"#60667E", | |||||
"#58865F", | |||||
"#2F763E", | |||||
"#7D80B5", | |||||
"#E84A3E", | |||||
"#F2883C", | |||||
"#FDCD4D", | |||||
"#CE478A", | |||||
"#B63D2A", | |||||
]; | ]; | ||||
export const cardBorderColor = [ | |||||
'#efb142', '#4bb641', '#448df2', '#e03c04' | |||||
]; | |||||
export const cardBorderColor = ["#efb142", "#4bb641", "#448df2", "#e03c04"]; | |||||
export const chartLineColor = [ | |||||
'#FFFFFF', '#D9D9D9' | |||||
]; | |||||
export const chartLineColor = ["#FFFFFF", "#D9D9D9"]; | |||||
export const GENERAL_RED_COLOR = '#e03c04'; | |||||
export const GENERAL_RED_COLOR = "#e03c04"; | |||||
export const TABLE_HEADER_TEXT_COLOR = "#3367D1"; | export const TABLE_HEADER_TEXT_COLOR = "#3367D1"; | ||||
export const GENERAL_INFO_COLOR = '#448df2'; | |||||
export const GENERAL_INFO_COLOR = "#448df2"; | |||||
export const GENERAL_SETTING_COLOR = '#666666'; | |||||
export const GENERAL_SETTING_COLOR = "#666666"; | |||||
export const GENERAL_BORDER_COLOR = '#e6ebf1'; | |||||
export const GENERAL_BORDER_COLOR = "#e6ebf1"; | |||||
export const GENERAL_TEXT_COLOR = '#262626'; | |||||
export const GENERAL_TEXT_COLOR = "#262626"; | |||||
export const FONT_SIZE_L = "1.875rem"; | export const FONT_SIZE_L = "1.875rem"; | ||||
@@ -57,327 +91,327 @@ export const FONT_SIZE_M = "1.5rem"; | |||||
export const FONT_SIZE_S = "1.25rem"; | export const FONT_SIZE_S = "1.25rem"; | ||||
export const PROJECT_CARD_STYLE = { | export const PROJECT_CARD_STYLE = { | ||||
borderRadius: '10px', | |||||
//border: '10px dotted #ccc', | |||||
width: '20rem', | |||||
margin: '20px', | |||||
//backgroundColor:"pink" | |||||
borderRadius: "10px", | |||||
//border: '10px dotted #ccc', | |||||
width: "20rem", | |||||
margin: "20px", | |||||
//backgroundColor:"pink" | |||||
}; | }; | ||||
export const PROJECT_MODAL_STYLE = { | export const PROJECT_MODAL_STYLE = { | ||||
position: 'absolute', | |||||
width: '85%', | |||||
borderRadius: '10px', | |||||
height: '75%', | |||||
// top: '50%', | |||||
// left: '50%', | |||||
transform: 'translate(10%, 15%)', | |||||
backgroundColor: 'white', | |||||
padding: '20px', | |||||
display: 'flex', | |||||
flexDirection: 'column', | |||||
}; | |||||
position: "absolute", | |||||
width: "85%", | |||||
borderRadius: "10px", | |||||
height: "75%", | |||||
// top: '50%', | |||||
// left: '50%', | |||||
transform: "translate(10%, 15%)", | |||||
backgroundColor: "white", | |||||
padding: "20px", | |||||
display: "flex", | |||||
flexDirection: "column", | |||||
}; | |||||
export const DATAGRID_STYLE = { | export const DATAGRID_STYLE = { | ||||
boxShadow: 2, | |||||
border: 2, | |||||
borderColor: 'primary.light', | |||||
'& .MuiDataGrid-cell:hover': { | |||||
color: 'primary.main' | |||||
}, | |||||
'& .MuiDataGrid-root': { | |||||
overflow: 'auto', | |||||
} | |||||
boxShadow: 2, | |||||
border: 2, | |||||
borderColor: "primary.light", | |||||
"& .MuiDataGrid-cell:hover": { | |||||
color: "primary.main", | |||||
}, | |||||
"& .MuiDataGrid-root": { | |||||
overflow: "auto", | |||||
}, | |||||
}; | }; | ||||
export const TAB_THEME = { | export const TAB_THEME = { | ||||
components: { | |||||
MuiTab: { | |||||
styleOverrides: { | |||||
root: { | |||||
// fontSize: '1.0rem', | |||||
fontSize: '1.25rem'//'20px', | |||||
// height: '40px', | |||||
// width: '40vw', // Default width for xs screen sizes | |||||
// '@media (min-width: 600px)': { // sm breakpoint | |||||
// width: '20vw', | |||||
// }, | |||||
// '@media (min-width: 960px)': { // md breakpoint | |||||
// width: '15vw', | |||||
// }, | |||||
// '@media (min-width: 1280px)': { // lg breakpoint | |||||
// width: '7vw', | |||||
// }, | |||||
// textTransform: "none", | |||||
// alignItems: 'center' | |||||
}, | |||||
}, | |||||
}, | |||||
} | |||||
}; | |||||
components: { | |||||
MuiTab: { | |||||
styleOverrides: { | |||||
root: { | |||||
// fontSize: '1.0rem', | |||||
fontSize: "1.25rem", //'20px', | |||||
// height: '40px', | |||||
// width: '40vw', // Default width for xs screen sizes | |||||
// '@media (min-width: 600px)': { // sm breakpoint | |||||
// width: '20vw', | |||||
// }, | |||||
// '@media (min-width: 960px)': { // md breakpoint | |||||
// width: '15vw', | |||||
// }, | |||||
// '@media (min-width: 1280px)': { // lg breakpoint | |||||
// width: '7vw', | |||||
// }, | |||||
// textTransform: "none", | |||||
// alignItems: 'center' | |||||
}, | |||||
}, | |||||
}, | |||||
}, | |||||
}; | |||||
// copy from MTMS | // copy from MTMS | ||||
export const TSMS_BUTTON_THEME = createTheme({ | export const TSMS_BUTTON_THEME = createTheme({ | ||||
palette: { | |||||
primary: { | |||||
main: '#92C1E9', | |||||
contrastText: '#FFFFFF', | |||||
}, | |||||
secondary: { | |||||
main: '#898D8D', | |||||
contrastText: '#FFFFFF', | |||||
}, | |||||
success: { | |||||
main: '#ADCAB8', | |||||
contrastText: '#FFFFFF', | |||||
}, | |||||
danger: { | |||||
main: '#F890A5', | |||||
contrastText: '#FFFFFF', | |||||
}, | |||||
warning: { | |||||
main: '#EFBE7D', | |||||
contrastText: '#FFFFFF', | |||||
}, | |||||
disable: { | |||||
main: '#B2B4B2', | |||||
contrastText: '#FFFFFF', | |||||
}, | |||||
create: { | |||||
// main: '#57B962', | |||||
main: '#ADCAB8', | |||||
// light: will be calculated from palette.primary.main, | |||||
// dark: will be calculated from palette.primary.main, | |||||
// contrastText: will be calculated to contrast with palette.primary.main | |||||
contrastText: '#FFFFFF', | |||||
}, | |||||
delete: { | |||||
// main: '#E03C04', | |||||
main: '#F890A5', | |||||
contrastText: '#FFFFFF', | |||||
}, | |||||
cancel: { | |||||
// main: '#999999', | |||||
main: '#F890A5', | |||||
contrastText: '#FFFFFF', | |||||
}, | |||||
back: { | |||||
// main: '#999999', | |||||
main: '#898D8D', | |||||
contrastText: '#FFFFFF', | |||||
}, | |||||
reset: { | |||||
main: '#EFBE7D', | |||||
contrastText: '#FFFFFF', | |||||
}, | |||||
save: { | |||||
// main: '#448DF2', | |||||
main: '#92C1E9', | |||||
contrastText: '#FFFFFF', | |||||
}, | |||||
export: { | |||||
main: '#8C52FF', | |||||
contrastText: '#FFFFFF', | |||||
}, | |||||
import: { | |||||
main: '#92C1E9', | |||||
contrastText: '#FFFFFF', | |||||
}, | |||||
saveAs: { | |||||
main: '#FFBD59', | |||||
contrastText: '#FFFFFF', | |||||
} | |||||
}, | |||||
components: { | |||||
MuiButton: { | |||||
styleOverrides: { | |||||
root: { | |||||
'& .MuiButtonBase-root-MuiButton-root': { | |||||
fontSize: FONT_SIZE_S | |||||
}, | |||||
} | |||||
} | |||||
}, | |||||
MuiButtonBase: { | |||||
styleOverrides: { | |||||
root: { | |||||
'&.MuiChip-root.Mui-disabled': { | |||||
opacity: 0.75, | |||||
}, | |||||
'&.MuiButton-root': { | |||||
fontSize: FONT_SIZE_S | |||||
}, | |||||
} | |||||
} | |||||
}, | |||||
} | |||||
palette: { | |||||
primary: { | |||||
main: "#92C1E9", | |||||
contrastText: "#FFFFFF", | |||||
}, | |||||
secondary: { | |||||
main: "#898D8D", | |||||
contrastText: "#FFFFFF", | |||||
}, | |||||
success: { | |||||
main: "#ADCAB8", | |||||
contrastText: "#FFFFFF", | |||||
}, | |||||
danger: { | |||||
main: "#F890A5", | |||||
contrastText: "#FFFFFF", | |||||
}, | |||||
warning: { | |||||
main: "#EFBE7D", | |||||
contrastText: "#FFFFFF", | |||||
}, | |||||
disable: { | |||||
main: "#B2B4B2", | |||||
contrastText: "#FFFFFF", | |||||
}, | |||||
create: { | |||||
// main: '#57B962', | |||||
main: "#ADCAB8", | |||||
// light: will be calculated from palette.primary.main, | |||||
// dark: will be calculated from palette.primary.main, | |||||
// contrastText: will be calculated to contrast with palette.primary.main | |||||
contrastText: "#FFFFFF", | |||||
}, | |||||
delete: { | |||||
// main: '#E03C04', | |||||
main: "#F890A5", | |||||
contrastText: "#FFFFFF", | |||||
}, | |||||
cancel: { | |||||
// main: '#999999', | |||||
main: "#F890A5", | |||||
contrastText: "#FFFFFF", | |||||
}, | |||||
back: { | |||||
// main: '#999999', | |||||
main: "#898D8D", | |||||
contrastText: "#FFFFFF", | |||||
}, | |||||
reset: { | |||||
main: "#EFBE7D", | |||||
contrastText: "#FFFFFF", | |||||
}, | |||||
save: { | |||||
// main: '#448DF2', | |||||
main: "#92C1E9", | |||||
contrastText: "#FFFFFF", | |||||
}, | |||||
export: { | |||||
main: "#8C52FF", | |||||
contrastText: "#FFFFFF", | |||||
}, | |||||
import: { | |||||
main: "#92C1E9", | |||||
contrastText: "#FFFFFF", | |||||
}, | |||||
saveAs: { | |||||
main: "#FFBD59", | |||||
contrastText: "#FFFFFF", | |||||
}, | |||||
}, | |||||
components: { | |||||
MuiButton: { | |||||
styleOverrides: { | |||||
root: { | |||||
"& .MuiButtonBase-root-MuiButton-root": { | |||||
fontSize: FONT_SIZE_S, | |||||
}, | |||||
}, | |||||
}, | |||||
}, | |||||
MuiButtonBase: { | |||||
styleOverrides: { | |||||
root: { | |||||
"&.MuiChip-root.Mui-disabled": { | |||||
opacity: 0.75, | |||||
}, | |||||
"&.MuiButton-root": { | |||||
fontSize: FONT_SIZE_S, | |||||
}, | |||||
}, | |||||
}, | |||||
}, | |||||
}, | |||||
}); | }); | ||||
export const formTheme = createTheme({ | export const formTheme = createTheme({ | ||||
components: { | |||||
MuiFormLabel: { | |||||
root: { // Name of the rule | |||||
color: "rgba(0, 0, 0, 1)", | |||||
}, | |||||
styleOverrides: { | |||||
asterisk: { | |||||
color: "#db3131", | |||||
"&$error": { | |||||
color: "#db3131", | |||||
}, | |||||
}, | |||||
}, | |||||
}, | |||||
components: { | |||||
MuiFormLabel: { | |||||
root: { | |||||
// Name of the rule | |||||
color: "rgba(0, 0, 0, 1)", | |||||
}, | |||||
styleOverrides: { | |||||
asterisk: { | |||||
color: "#db3131", | |||||
"&$error": { | |||||
color: "#db3131", | |||||
}, | |||||
}, | |||||
}, | |||||
}, | }, | ||||
}, | |||||
}); | }); | ||||
export const ARS_BUTTON_THEME = createTheme({ | export const ARS_BUTTON_THEME = createTheme({ | ||||
palette: { | |||||
create: { | |||||
main: '#57B962', | |||||
// light: will be calculated from palette.primary.main, | |||||
// dark: will be calculated from palette.primary.main, | |||||
// contrastText: will be calculated to contrast with palette.primary.main | |||||
contrastText: '#FFFFFF', | |||||
}, | |||||
delete: { | |||||
main: '#E03C04', | |||||
contrastText: '#FFFFFF', | |||||
}, | |||||
cancel: { | |||||
main: '#999999', | |||||
contrastText: '#FFFFFF', | |||||
}, | |||||
save: { | |||||
main: '#448DF2', | |||||
contrastText: '#FFFFFF', | |||||
}, | |||||
export: { | |||||
main: '#8C52FF', | |||||
contrastText: '#FFFFFF', | |||||
}, | |||||
saveAs: { | |||||
main: '#FFBD59', | |||||
contrastText: '#FFFFFF', | |||||
}, | |||||
edit: { | |||||
main: '#F3AF2B', | |||||
contrastText: '#FFFFFF', | |||||
}, | |||||
exportExcel: { | |||||
main: '#6A8B9E', | |||||
contrastText: '#FFFFFF', | |||||
} | |||||
}, | |||||
components: { | |||||
MuiDataGrid: { | |||||
styleOverrides: { | |||||
actionsCell: { | |||||
'& .MuiDataGrid-actionsContainer .MuiIconButton-root': { | |||||
fontSize: '80px', // Set the desired icon size here | |||||
}, | |||||
}, | |||||
}, | |||||
}, | |||||
MuiButton: { | |||||
styleOverrides: { | |||||
root: { | |||||
// fontSize: '1.0rem', | |||||
fontSize: '1.25rem', | |||||
height: '40px', | |||||
width: '40vw', // Default width for xs screen sizes | |||||
'@media (min-width: 600px)': { // sm breakpoint | |||||
width: '20vw', | |||||
}, | |||||
'@media (min-width: 960px)': { // md breakpoint | |||||
width: '15vw', | |||||
}, | |||||
'@media (min-width: 1280px)': { // lg breakpoint | |||||
width: '7vw', | |||||
}, | |||||
textTransform: "none", | |||||
alignItems: 'center' | |||||
}, | |||||
}, | |||||
}, | |||||
} | |||||
palette: { | |||||
create: { | |||||
main: "#57B962", | |||||
// light: will be calculated from palette.primary.main, | |||||
// dark: will be calculated from palette.primary.main, | |||||
// contrastText: will be calculated to contrast with palette.primary.main | |||||
contrastText: "#FFFFFF", | |||||
}, | |||||
delete: { | |||||
main: "#E03C04", | |||||
contrastText: "#FFFFFF", | |||||
}, | |||||
cancel: { | |||||
main: "#999999", | |||||
contrastText: "#FFFFFF", | |||||
}, | |||||
save: { | |||||
main: "#448DF2", | |||||
contrastText: "#FFFFFF", | |||||
}, | |||||
export: { | |||||
main: "#8C52FF", | |||||
contrastText: "#FFFFFF", | |||||
}, | |||||
saveAs: { | |||||
main: "#FFBD59", | |||||
contrastText: "#FFFFFF", | |||||
}, | |||||
edit: { | |||||
main: "#F3AF2B", | |||||
contrastText: "#FFFFFF", | |||||
}, | |||||
exportExcel: { | |||||
main: "#6A8B9E", | |||||
contrastText: "#FFFFFF", | |||||
}, | |||||
}, | |||||
components: { | |||||
MuiDataGrid: { | |||||
styleOverrides: { | |||||
actionsCell: { | |||||
"& .MuiDataGrid-actionsContainer .MuiIconButton-root": { | |||||
fontSize: "80px", // Set the desired icon size here | |||||
}, | |||||
}, | |||||
}, | |||||
}, | |||||
MuiButton: { | |||||
styleOverrides: { | |||||
root: { | |||||
// fontSize: '1.0rem', | |||||
fontSize: "1.25rem", | |||||
height: "40px", | |||||
width: "40vw", // Default width for xs screen sizes | |||||
"@media (min-width: 600px)": { | |||||
// sm breakpoint | |||||
width: "20vw", | |||||
}, | |||||
"@media (min-width: 960px)": { | |||||
// md breakpoint | |||||
width: "15vw", | |||||
}, | |||||
"@media (min-width: 1280px)": { | |||||
// lg breakpoint | |||||
width: "7vw", | |||||
}, | |||||
textTransform: "none", | |||||
alignItems: "center", | |||||
}, | |||||
}, | |||||
}, | |||||
}, | |||||
}); | }); | ||||
//from ARS | //from ARS | ||||
export const TSMS_LONG_BUTTON_THEME = createTheme({ | export const TSMS_LONG_BUTTON_THEME = createTheme({ | ||||
palette: { | |||||
create: { | |||||
main: '#57B962', | |||||
// light: will be calculated from palette.primary.main, | |||||
// dark: will be calculated from palette.primary.main, | |||||
// contrastText: will be calculated to contrast with palette.primary.main | |||||
contrastText: '#FFFFFF', | |||||
}, | |||||
delete: { | |||||
main: '#E03C04', | |||||
contrastText: '#FFFFFF', | |||||
}, | |||||
cancel: { | |||||
main: '#999999', | |||||
contrastText: '#FFFFFF', | |||||
}, | |||||
save: { | |||||
main: '#448DF2', | |||||
contrastText: '#FFFFFF', | |||||
}, | |||||
export: { | |||||
main: '#8C52FF', | |||||
contrastText: '#FFFFFF', | |||||
}, | |||||
saveAs: { | |||||
main: '#FFBD59', | |||||
contrastText: '#FFFFFF', | |||||
}, | |||||
edit: { | |||||
main: '#F3AF2B', | |||||
contrastText: '#FFFFFF', | |||||
}, | |||||
exportExcel: { | |||||
main: '#60667E', | |||||
contrastText: '#FFFFFF', | |||||
} | |||||
}, | |||||
components: { | |||||
MuiDataGrid: { | |||||
styleOverrides: { | |||||
actionsCell: { | |||||
'& .MuiDataGrid-actionsContainer .MuiIconButton-root': { | |||||
fontSize: '80px', // Set the desired icon size here | |||||
}, | |||||
}, | |||||
}, | |||||
}, | |||||
MuiButton: { | |||||
styleOverrides: { | |||||
root: { | |||||
fontSize: '1.25rem', | |||||
height: '40px', | |||||
width: '40vw', // Default width for xs screen sizes | |||||
'@media (min-width: 600px)': { // sm breakpoint | |||||
width: '30vw', | |||||
}, | |||||
'@media (min-width: 960px)': { // md breakpoint | |||||
width: '25vw', | |||||
}, | |||||
'@media (min-width: 1280px)': { // lg breakpoint | |||||
width: '14vw', | |||||
}, | |||||
textTransform: "none", | |||||
alignItems: 'center' | |||||
}, | |||||
}, | |||||
}, | |||||
} | |||||
}); | |||||
palette: { | |||||
create: { | |||||
main: "#57B962", | |||||
// light: will be calculated from palette.primary.main, | |||||
// dark: will be calculated from palette.primary.main, | |||||
// contrastText: will be calculated to contrast with palette.primary.main | |||||
contrastText: "#FFFFFF", | |||||
}, | |||||
delete: { | |||||
main: "#E03C04", | |||||
contrastText: "#FFFFFF", | |||||
}, | |||||
cancel: { | |||||
main: "#999999", | |||||
contrastText: "#FFFFFF", | |||||
}, | |||||
save: { | |||||
main: "#448DF2", | |||||
contrastText: "#FFFFFF", | |||||
}, | |||||
export: { | |||||
main: "#8C52FF", | |||||
contrastText: "#FFFFFF", | |||||
}, | |||||
saveAs: { | |||||
main: "#FFBD59", | |||||
contrastText: "#FFFFFF", | |||||
}, | |||||
edit: { | |||||
main: "#F3AF2B", | |||||
contrastText: "#FFFFFF", | |||||
}, | |||||
exportExcel: { | |||||
main: "#60667E", | |||||
contrastText: "#FFFFFF", | |||||
}, | |||||
}, | |||||
components: { | |||||
MuiDataGrid: { | |||||
styleOverrides: { | |||||
actionsCell: { | |||||
"& .MuiDataGrid-actionsContainer .MuiIconButton-root": { | |||||
fontSize: "80px", // Set the desired icon size here | |||||
}, | |||||
}, | |||||
}, | |||||
}, | |||||
MuiButton: { | |||||
styleOverrides: { | |||||
root: { | |||||
fontSize: "1.25rem", | |||||
height: "40px", | |||||
width: "40vw", // Default width for xs screen sizes | |||||
"@media (min-width: 600px)": { | |||||
// sm breakpoint | |||||
width: "30vw", | |||||
}, | |||||
"@media (min-width: 960px)": { | |||||
// md breakpoint | |||||
width: "25vw", | |||||
}, | |||||
"@media (min-width: 1280px)": { | |||||
// lg breakpoint | |||||
width: "14vw", | |||||
}, | |||||
textTransform: "none", | |||||
alignItems: "center", | |||||
}, | |||||
}, | |||||
}, | |||||
}, | |||||
}); |