user workspace enter timesheet input added Custom Alert for unificationtags/Baseline_30082024_FRONTEND_UAT
| @@ -1,11 +1,17 @@ | |||
| import { Metadata } from "next"; | |||
| import { I18nProvider } from "@/i18n"; | |||
| import UserWorkspacePage from "@/components/UserWorkspacePage/UserWorkspacePage"; | |||
| export const metadata: Metadata = { | |||
| title: "Home", | |||
| title: "User Workspace", | |||
| }; | |||
| const Home: React.FC = async () => { | |||
| return "Home"; | |||
| return ( | |||
| <I18nProvider namespaces={["home"]}> | |||
| <UserWorkspacePage/> | |||
| </I18nProvider> | |||
| ); | |||
| }; | |||
| export default Home; | |||
| @@ -0,0 +1,176 @@ | |||
| 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 { | |||
| Title?: string; | |||
| // rows: any[]; | |||
| // columns: any[]; | |||
| columnWidth?: number; | |||
| Style?: boolean; | |||
| sx?: SxProps<Theme>; | |||
| height?: number; | |||
| [key: string]: any; | |||
| } | |||
| interface TabPanelProps { | |||
| children?: React.ReactNode; | |||
| index: number; | |||
| value: number; | |||
| } | |||
| function CustomTabPanel(props: TabPanelProps) { | |||
| const { children, value, index, ...other } = props; | |||
| return ( | |||
| <div | |||
| role="tabpanel" | |||
| hidden={value !== index} | |||
| id={`simple-tabpanel-${index}`} | |||
| aria-labelledby={`simple-tab-${index}`} | |||
| {...other} | |||
| > | |||
| {value === index && ( | |||
| <Box sx={{ p: 3 }}> | |||
| <Typography>{children}</Typography> | |||
| </Box> | |||
| )} | |||
| </div> | |||
| ); | |||
| } | |||
| function a11yProps(index: number) { | |||
| return { | |||
| id: `simple-tab-${index}`, | |||
| 'aria-controls': `simple-tabpanel-${index}`, | |||
| }; | |||
| } | |||
| const AssignedProjectGrid: React.FC<AssignedProjectGridProps> = ({ | |||
| Title, | |||
| rows, | |||
| columns, | |||
| columnWidth, | |||
| Style = true, | |||
| sx, | |||
| height, | |||
| ...props | |||
| }) => { | |||
| // const modifiedColumns = columns.map((column) => { | |||
| // return { | |||
| // ...column, | |||
| // width: columnWidth ?? 150, | |||
| // }; | |||
| // }); | |||
| // const rowsWithDefaultValues = rows.map((row) => { | |||
| // return { ...row }; | |||
| // }); | |||
| 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 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 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) | |||
| }, | |||
| '&.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) | |||
| }, | |||
| '&.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) | |||
| }, | |||
| '&.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) | |||
| }, | |||
| '&.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 handleChange = (event: React.SyntheticEvent, newValue: number) => { | |||
| setValue(newValue); | |||
| }; | |||
| 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}> | |||
| Item {value} | |||
| </CustomTabPanel> | |||
| <CustomTabPanel value={value} index={1}> | |||
| Item {value} | |||
| </CustomTabPanel> | |||
| <CustomTabPanel value={value} index={2}> | |||
| Item {value} | |||
| </CustomTabPanel> */} | |||
| </ThemeProvider> | |||
| </div> | |||
| </CardContent> | |||
| <AllProjectGrid tab={value} /> | |||
| </Card> | |||
| </div> | |||
| ); | |||
| }; | |||
| export default AssignedProjectGrid; | |||
| @@ -0,0 +1 @@ | |||
| export { default } from "./AssignedProjectGrid"; | |||
| @@ -0,0 +1,171 @@ | |||
| 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` | |||
| /* Styles for the card when not hovered */ | |||
| background-color: #f0f0f0; | |||
| padding: 10px; | |||
| /* ...other styles... */ | |||
| &:hover { | |||
| /* Styles for the card when hovered */ | |||
| background-color: #c0c0c0; | |||
| /* ...other hover styles... */ | |||
| } | |||
| `; | |||
| interface CustomCardGridProps { | |||
| Title?: string; | |||
| cardsPerRow?: number; | |||
| rows?: any[]; | |||
| columns?: any[]; | |||
| items: any[]; | |||
| columnWidth?: number; | |||
| Style?: boolean; | |||
| sx?: SxProps<Theme>; | |||
| dataGridHeight?: number; | |||
| cardStyle?: any; | |||
| [key: string]: any; | |||
| } | |||
| const CustomCardGrid: React.FC<CustomCardGridProps> = ({ | |||
| Title, | |||
| rows, | |||
| items, | |||
| columns, | |||
| columnWidth, | |||
| cardsPerRow = 4, | |||
| Style = true, | |||
| sx, | |||
| dataGridHeight, | |||
| ...props | |||
| }) => { | |||
| 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 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 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) | |||
| }, | |||
| '&.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) | |||
| }, | |||
| '&.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) | |||
| }, | |||
| '&.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) | |||
| }, | |||
| '&.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.item as Record<string, string>; | |||
| return props.cardStyle?? ( | |||
| // <Grid item sx={{ m: 3 }}> | |||
| <StyledCard style={PROJECT_CARD_STYLE}> | |||
| <CardContent> | |||
| {Object.keys(cardItem).map((key) => ( | |||
| <p key={key}> | |||
| {key}: {cardItem[key]} | |||
| </p> | |||
| ))} | |||
| </CardContent> | |||
| </StyledCard> | |||
| // </Grid> | |||
| ); | |||
| }; | |||
| const containerRef = useRef<HTMLDivElement>(null!); | |||
| const [cardMargin, setCardMargin] = useState(1.5); | |||
| useEffect(() => { | |||
| console.log(CardItem); | |||
| const resizeHandler = () => { | |||
| const containerWidth = containerRef.current.offsetWidth; | |||
| 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)); | |||
| // Set the cardMargin value using style={{margin: `${cardMargin}px`, ...PROJECT_CARD_STYLE}} | |||
| }; | |||
| window.addEventListener('resize', resizeHandler); | |||
| resizeHandler(); // Initial calculation | |||
| // Swal.fire({ | |||
| // title: 'Error! ', | |||
| // text: `Card Count is ${items.length}`, | |||
| // icon: 'success', | |||
| // confirmButtonText: 'Jus Cool' | |||
| // }) | |||
| return () => { | |||
| window.removeEventListener('resize', resizeHandler); | |||
| }; | |||
| }, [items]); | |||
| return ( | |||
| <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> */} | |||
| {items.map((item, index) => ( | |||
| <div key={index}> | |||
| {props.cardStyle? props.cardStyle(item) : <CardItem item={item}/>} | |||
| </div> | |||
| ))} | |||
| </div> | |||
| ); | |||
| }; | |||
| export default CustomCardGrid; | |||
| @@ -0,0 +1 @@ | |||
| export { default } from "./CustomCardGrid"; | |||
| @@ -0,0 +1,62 @@ | |||
| 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` | |||
| /* Styles for the card when not hovered */ | |||
| background-color: #f0f0f0, | |||
| padding: 10px, | |||
| /* ...other styles... */ | |||
| &:hover { | |||
| /* Styles for the card when hovered */ | |||
| background-color: #c0c0c0, | |||
| /* ...other hover styles... */ | |||
| } | |||
| `; | |||
| interface CustomModalProps { | |||
| title?: string; | |||
| isOpen: boolean; | |||
| onClose: () => void; | |||
| modalStyle?: any; | |||
| } | |||
| const CustomModal: React.FC<CustomModalProps> = ({ ...props }) => { | |||
| const ModalContent = () => { | |||
| return ( | |||
| // <Grid item sx={{ m: 3 }}> | |||
| <div style={PROJECT_MODAL_STYLE}> | |||
| <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> | |||
| // </Grid> | |||
| ); | |||
| }; | |||
| return ( | |||
| <Modal open={props.isOpen} onClose={props.onClose}> | |||
| {props.modalStyle? <props.modalStyle props={props}/> : <ModalContent/>} | |||
| </Modal> | |||
| ); | |||
| }; | |||
| export default CustomModal; | |||
| @@ -0,0 +1 @@ | |||
| export { default } from "./CustomModal"; | |||
| @@ -0,0 +1,80 @@ | |||
| "use client"; | |||
| import Grid from "@mui/material/Grid"; | |||
| import Paper from "@mui/material/Paper"; | |||
| import { useState } from "react"; | |||
| import { useTranslation } from "react-i18next"; | |||
| import AssignedProjectGrid from "../AssignedProjectGrid/AssignedProjectGrid"; | |||
| import PageTitle from "../PageTitle/PageTitle"; | |||
| import { Suspense } from "react"; | |||
| import Button from "@mui/material/Button"; | |||
| import Stack from "@mui/material/Stack"; | |||
| import { Add } from '@mui/icons-material'; | |||
| import Link from "next/link"; | |||
| import { t } from 'i18next'; | |||
| import { Modal, Typography } from "@mui/material"; | |||
| import CustomModal from "../CustomModal/CustomModal"; | |||
| import { PROJECT_MODAL_STYLE } from "@/theme/colorConst"; | |||
| import CustomDatagrid from "../CustomDatagrid/CustomDatagrid"; | |||
| import { DataGrid } from '@mui/x-data-grid'; | |||
| import TimesheetInputGrid from "./TimesheetInputGrid"; | |||
| interface EnterTimesheetModalProps { | |||
| isOpen: boolean; | |||
| onClose: () => void; | |||
| modalStyle?: any; | |||
| } | |||
| const EnterTimesheetModal: React.FC<EnterTimesheetModalProps> = ({ ...props }) => { | |||
| const [lockConfirm, setLockConfirm] = useState(false); | |||
| const columns = [ | |||
| { | |||
| id: 'projectCode', | |||
| field: 'projectCode', | |||
| headerName: "Project Code and Name", | |||
| flex: 1, | |||
| }, | |||
| { | |||
| id: 'task', | |||
| field: 'task', | |||
| headerName: "Task", | |||
| flex: 1, | |||
| }, | |||
| ]; | |||
| const rows = [{ | |||
| id: 1, projectCode: "M1001", task: "1.2" | |||
| }, | |||
| { | |||
| id: 2, projectCode: "M1301", task: "1.1" | |||
| }]; | |||
| return ( | |||
| <Modal open={props.isOpen} onClose={props.onClose}> | |||
| <div style={PROJECT_MODAL_STYLE}> | |||
| <Typography variant="h6" id="modal-title" sx={{flex:1}}> | |||
| <div style={{ display: 'flex', justifyContent: 'space-between', width: '100%' }}> | |||
| Timesheet Input | |||
| </div> | |||
| </Typography> | |||
| <div style={{flex: 10}}> | |||
| <TimesheetInputGrid setLockConfirm={setLockConfirm}/> | |||
| </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> | |||
| </Modal> | |||
| ); | |||
| }; | |||
| export default EnterTimesheetModal; | |||
| @@ -0,0 +1,62 @@ | |||
| "use client"; | |||
| import * as React from "react"; | |||
| 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 { PROJECT_CARD_STYLE } from "@/theme/colorConst"; | |||
| interface ProjectGridProps { | |||
| tab: number; | |||
| } | |||
| const ProjectGrid: React.FC<ProjectGridProps> = (props) => { | |||
| const [items, setItems] = React.useState<Object[]>([]) | |||
| useEffect(() => { | |||
| if (props.tab == 0) { | |||
| setItems(cards) | |||
| } | |||
| else { | |||
| const filteredItems = cards;//cards.filter(item => (item.track == props.tab)); | |||
| setItems(filteredItems); | |||
| } | |||
| }, [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>) => { | |||
| return ( | |||
| <Card style={PROJECT_CARD_STYLE}> | |||
| <CardHeader style={{backgroundColor:'red'}} title={item.code + '\u000A' + item.name}/> | |||
| <CardContent> | |||
| <p>Hours Spent: {item.hr_spent}</p> | |||
| <p>Normal (Others): {item.hr_spent_normal}</p> | |||
| <p>Hours Allocated: {item.hr_alloc}</p> | |||
| <p>Normal (Others): {item.hr_alloc_normal}</p> | |||
| </CardContent> | |||
| </Card> | |||
| ); | |||
| } | |||
| // Apply the preset style to the cards in child, if not specified // | |||
| return ( | |||
| <Grid container md={12} style={{backgroundColor:"yellow"}}> | |||
| {/* <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> | |||
| ); | |||
| }; | |||
| export default ProjectGrid; | |||
| @@ -0,0 +1,502 @@ | |||
| "use client"; | |||
| import Grid from "@mui/material/Grid"; | |||
| import Paper from "@mui/material/Paper"; | |||
| import { useState, useEffect } from "react"; | |||
| import { useTranslation } from "react-i18next"; | |||
| import PageTitle from "../PageTitle/PageTitle"; | |||
| import { Suspense } from "react"; | |||
| import Button from "@mui/material/Button"; | |||
| import Stack from "@mui/material/Stack"; | |||
| import { Add, SettingsEthernet } from '@mui/icons-material'; | |||
| 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 Swal from "sweetalert2"; | |||
| import { msg } from "../Swal/CustomAlerts"; | |||
| import ComboEditor from "../ComboEditor/ComboEditor"; | |||
| import React from "react"; | |||
| import { DatePicker } from '@mui/x-date-pickers/DatePicker'; | |||
| import { | |||
| GridRowsProp, | |||
| GridRowModesModel, | |||
| GridRowModes, | |||
| DataGrid, | |||
| GridColDef, | |||
| GridToolbarContainer, | |||
| GridFooterContainer, | |||
| GridActionsCellItem, | |||
| GridEventListener, | |||
| GridRowId, | |||
| GridRowModel, | |||
| GridRowEditStopReasons, | |||
| GridEditInputCell, | |||
| GridValueSetterParams, | |||
| } from '@mui/x-data-grid'; | |||
| import { LocalizationProvider } from "@mui/x-date-pickers"; | |||
| import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs"; | |||
| import dayjs from "dayjs"; | |||
| import { Props } from "react-intl/src/components/relative"; | |||
| const weekdays = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun']; | |||
| interface BottomBarProps { | |||
| getHoursTotal: (column: string) => number; | |||
| setLockConfirm: (newLock: (oldLock: Boolean) => Boolean) => void; | |||
| setRows: (newRows: (oldRows: GridRowsProp) => GridRowsProp) => void; | |||
| setRowModesModel: ( | |||
| newModel: (oldModel: GridRowModesModel) => GridRowModesModel, | |||
| ) => void; | |||
| } | |||
| interface EditToolbarProps { | |||
| // setDay: (newDay : dayjs.Dayjs) => void; | |||
| setDay: (newDay: (oldDay: dayjs.Dayjs) => dayjs.Dayjs) => void; | |||
| setRows: (newRows: (oldRows: GridRowsProp) => GridRowsProp) => void; | |||
| setRowModesModel: ( | |||
| newModel: (oldModel: GridRowModesModel) => GridRowModesModel, | |||
| ) => void; | |||
| } | |||
| interface EditFooterProps { | |||
| setRows: (newRows: (oldRows: GridRowsProp) => GridRowsProp) => void; | |||
| setRowModesModel: ( | |||
| newModel: (oldModel: GridRowModesModel) => GridRowModesModel, | |||
| ) => void; | |||
| } | |||
| const BottomBar = (props: BottomBarProps) => { | |||
| const { setRows, setRowModesModel, getHoursTotal, setLockConfirm } = props; | |||
| // const getHoursTotal = props.getHoursTotal; | |||
| const [newId, setNewId] = useState(-1); | |||
| const [invalidDays, setInvalidDays] = useState(0); | |||
| const handleAddClick = () => { | |||
| const id = newId; | |||
| setNewId(newId - 1); | |||
| setRows((oldRows) => [...oldRows, { id, projectCode: '', task: '', isNew: true }]); | |||
| setRowModesModel((oldModel) => ({ | |||
| ...oldModel, | |||
| [id]: { mode: GridRowModes.Edit, fieldToFocus: 'projectCode' }, | |||
| })); | |||
| }; | |||
| const totalColDef = { | |||
| flex:1, | |||
| // style: {color:getHoursTotal('mon')>24?"red":"black"} | |||
| }; | |||
| const TotalCell = ({value}: Props) => { | |||
| const [invalid, setInvalid] = useState(false); | |||
| useEffect(()=> { | |||
| const newInvalid = (value??0)>24; | |||
| setInvalid(newInvalid); | |||
| }, [value]); | |||
| return ( | |||
| <Box flex={1} style={{color: invalid?"red":"black"}}> | |||
| {value} | |||
| </Box> | |||
| ); | |||
| } | |||
| const checkUnlockConfirmBtn = () => { | |||
| // setLockConfirm((oldLock)=> valid); | |||
| setLockConfirm((oldLock)=> weekdays.every(weekday => { | |||
| getHoursTotal(weekday) <= 24 | |||
| })); | |||
| } | |||
| return ( | |||
| <div> | |||
| <div style={{ display: 'flex', justifyContent: 'flex', width: '100%' }}> | |||
| <Box flex={5.7} textAlign={'right'} marginRight='4rem'> | |||
| <b>Total:</b> | |||
| </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')}/> | |||
| </div> | |||
| <Button variant="outlined" color="primary" startIcon={<AddIcon />} onClick={handleAddClick}> | |||
| Add record | |||
| </Button> | |||
| </div> | |||
| ); | |||
| } | |||
| const EditToolbar = (props: EditToolbarProps) => { | |||
| const { setDay } = props; | |||
| const [selectedDate, setSelectedDate] = useState<dayjs.Dayjs>(dayjs()); | |||
| const handleClickLeft = () => { | |||
| if (selectedDate) { | |||
| const newDate = selectedDate.add(-7, 'day'); | |||
| setSelectedDate(newDate); | |||
| } | |||
| }; | |||
| const handleClickRight = () => { | |||
| if (selectedDate) { | |||
| const newDate = selectedDate.add(7, 'day') > dayjs()? dayjs(): selectedDate.add(7, 'day'); | |||
| setSelectedDate(newDate); | |||
| } | |||
| }; | |||
| const handleDateChange = (date: dayjs.Dayjs | Date | null) => { | |||
| const newDate = dayjs(date); | |||
| setSelectedDate(newDate); | |||
| }; | |||
| useEffect(() => { | |||
| setDay((oldDay) => selectedDate); | |||
| }, [selectedDate]); | |||
| return ( | |||
| <LocalizationProvider dateAdapter={AdapterDayjs}> | |||
| <div style={{ display: 'flex', justifyContent: 'flex-end', width: '100%' }}> | |||
| <Button sx={{"border-radius":"30%", marginRight:'20px'}} variant="contained" onClick={handleClickLeft}> | |||
| <ArrowBackIcon/> | |||
| </Button> | |||
| <DatePicker | |||
| value={selectedDate} | |||
| onChange={handleDateChange} | |||
| disableFuture={true}/> | |||
| <Button sx={{"border-radius":"30%", margin:'0px 20px 0px 20px'}} variant="contained" onClick={handleClickRight}> | |||
| <ArrowForwardIcon/> | |||
| </Button> | |||
| </div> | |||
| </LocalizationProvider> | |||
| ); | |||
| } | |||
| const EditFooter = (props: EditFooterProps) => { | |||
| return ( | |||
| <div style={{ display: 'flex', justifyContent: 'flex', width: '100%' }}> | |||
| <Box flex={1}> | |||
| <b>Total: </b> | |||
| </Box> | |||
| <Box flex={2}>ssss</Box> | |||
| </div> | |||
| ); | |||
| } | |||
| interface TimesheetInputGridProps { | |||
| setLockConfirm: (newLock: (oldLock: Boolean) => Boolean) => void; | |||
| onClose?: () => void; | |||
| } | |||
| const initialRows: GridRowsProp = [ | |||
| { | |||
| id: 1, | |||
| projectCode: "M1001", | |||
| task: "1.2", | |||
| mon: 2.5, | |||
| }, | |||
| { | |||
| id: 2, | |||
| projectCode: "M1002", | |||
| task: "1.3", | |||
| mon: 3.25, | |||
| }, | |||
| ]; | |||
| const options=["M1001", "M1301", "M1354", "M1973"]; | |||
| const options2=[ | |||
| "1.1 - Preparation of preliminary Cost Estimate / Cost Plan", | |||
| "1.2 - Cash flow forecast", | |||
| "1.3 - Cost studies fo alterative design solutions", | |||
| "1.4 = Attend design co-ordination / project review meetings", | |||
| "1.5 - Prepare / Review RIC"]; | |||
| const getDateForHeader = (date : dayjs.Dayjs, weekday : number) => { | |||
| if (date.day() == 0) { | |||
| return date.add((weekday - date.day() - 7), 'day').format('DD MMM'); | |||
| } else { | |||
| return date.add(weekday - date.day(), 'day').format('DD MMM'); | |||
| } | |||
| } | |||
| const TimesheetInputGrid: React.FC<TimesheetInputGridProps> = ({ ...props }) => { | |||
| const [rows, setRows] = useState(initialRows); | |||
| const [day, setDay] = useState(dayjs()); | |||
| const [rowModesModel, setRowModesModel] = React.useState<GridRowModesModel>({}); | |||
| const { setLockConfirm } = props; | |||
| const handleRowEditStop: GridEventListener<'rowEditStop'> = (params, event) => { | |||
| if (params.reason === GridRowEditStopReasons.rowFocusOut) { | |||
| event.defaultMuiPrevented = true; | |||
| } | |||
| }; | |||
| const handleEditClick = (id: GridRowId) => () => { | |||
| setRowModesModel({ ...rowModesModel, [id]: { mode: GridRowModes.Edit } }); | |||
| }; | |||
| const handleSaveClick = (id: GridRowId) => () => { | |||
| setRowModesModel({ ...rowModesModel, [id]: { mode: GridRowModes.View } }); | |||
| }; | |||
| const handleDeleteClick = (id: GridRowId) => () => { | |||
| setRows(rows.filter((row) => row.id !== id)); | |||
| }; | |||
| const handleCancelClick = (id: GridRowId) => () => { | |||
| setRowModesModel({ | |||
| ...rowModesModel, | |||
| [id]: { mode: GridRowModes.View, ignoreModifications: true }, | |||
| }); | |||
| const editedRow = rows.find((row) => row.id === id); | |||
| if (editedRow!.isNew) { | |||
| setRows(rows.filter((row) => row.id !== id)); | |||
| } | |||
| }; | |||
| const processRowUpdate = (newRow: GridRowModel) => { | |||
| const updatedRow = { ...newRow, isNew: false }; | |||
| setRows(rows.map((row) => (row.id === newRow.id ? updatedRow : row))); | |||
| return updatedRow; | |||
| }; | |||
| const handleRowModesModelChange = (newRowModesModel: GridRowModesModel) => { | |||
| setRowModesModel(newRowModesModel); | |||
| }; | |||
| const getHoursTotal = (column : any) => { | |||
| let sum = 0; | |||
| rows.forEach((row) => { | |||
| sum += row[column]??0; | |||
| }); | |||
| return sum; | |||
| }; | |||
| const weekdayColConfig : any = { | |||
| type: 'number', | |||
| // sortable: false, | |||
| //width: 100, | |||
| flex: 1, | |||
| align: 'left', | |||
| headerAlign: 'left', | |||
| editable: true, | |||
| renderEditCell: (value : any) => ( | |||
| <GridEditInputCell | |||
| {...value} | |||
| inputProps={{ | |||
| max: 24, | |||
| min: 0, | |||
| step: 0.25, | |||
| }} | |||
| /> | |||
| ), | |||
| }; | |||
| const columns: GridColDef[] = [ | |||
| { | |||
| field: 'actions', | |||
| type: 'actions', | |||
| headerName: '', | |||
| width: 100, | |||
| cellClassName: 'actions', | |||
| getActions: ({ id }) => { | |||
| const isInEditMode = rowModesModel[id]?.mode === GridRowModes.Edit; | |||
| if (isInEditMode) { | |||
| return [ | |||
| <GridActionsCellItem | |||
| icon={<SaveIcon />} | |||
| title="Save" | |||
| label="Save" | |||
| sx={{ | |||
| color: 'primary.main', | |||
| }} | |||
| onClick={handleSaveClick(id)} | |||
| />, | |||
| <GridActionsCellItem | |||
| icon={<CancelIcon />} | |||
| title="Cancel" | |||
| label="Cancel" | |||
| className="textPrimary" | |||
| onClick={handleCancelClick(id)} | |||
| color="inherit" | |||
| />, | |||
| ]; | |||
| } | |||
| return [ | |||
| <GridActionsCellItem | |||
| icon={<EditIcon />} | |||
| title="Edit" | |||
| label="Edit" | |||
| className="textPrimary" | |||
| onClick={handleEditClick(id)} | |||
| color="inherit" | |||
| />, | |||
| <GridActionsCellItem | |||
| title="Delete" | |||
| label="Delete" | |||
| icon={<DeleteIcon />} | |||
| onClick={handleDeleteClick(id)} | |||
| sx={{color:"red"}} | |||
| />, | |||
| ]; | |||
| }, | |||
| }, | |||
| { | |||
| field: 'projectCode', | |||
| headerName: 'Project Code', | |||
| // width: 220, | |||
| flex: 2, | |||
| editable: true, | |||
| type: 'singleSelect', | |||
| valueOptions: options, | |||
| }, | |||
| { | |||
| field: 'task', | |||
| headerName: 'Task', | |||
| // width: 220, | |||
| flex: 3, | |||
| editable: true, | |||
| type: 'singleSelect', | |||
| valueOptions: options2, | |||
| }, | |||
| { | |||
| // Mon | |||
| field: 'mon', | |||
| ...weekdayColConfig, | |||
| renderHeader: () => { | |||
| return ( | |||
| <div>Mon - {getDateForHeader(day, 1)}</div> | |||
| ); | |||
| }, | |||
| }, | |||
| { | |||
| // Tue | |||
| field: 'tue', | |||
| ...weekdayColConfig, | |||
| renderHeader: () => { | |||
| return ( | |||
| <div>Tue - {getDateForHeader(day, 2)}</div> | |||
| ); | |||
| }, | |||
| }, | |||
| { | |||
| // Wed | |||
| field: 'wed', | |||
| ...weekdayColConfig, | |||
| renderHeader: () => { | |||
| return ( | |||
| <div>Wed - {getDateForHeader(day, 3)}</div> | |||
| ); | |||
| }, | |||
| }, | |||
| { | |||
| // Thu | |||
| field: 'thu', | |||
| ...weekdayColConfig, | |||
| renderHeader: () => { | |||
| return ( | |||
| <div>Thu - {getDateForHeader(day, 4)}</div> | |||
| ); | |||
| }, | |||
| }, | |||
| { | |||
| // Fri | |||
| field: 'fri', | |||
| ...weekdayColConfig, | |||
| renderHeader: () => { | |||
| return ( | |||
| <div>Fri - {getDateForHeader(day, 5)}</div> | |||
| ); | |||
| }, | |||
| }, | |||
| { | |||
| // Sat | |||
| field: 'sat', | |||
| ...weekdayColConfig, | |||
| renderHeader: () => { | |||
| return ( | |||
| <div>Sat - {getDateForHeader(day, 6)}</div> | |||
| ); | |||
| }, | |||
| }, | |||
| { | |||
| // Sun | |||
| field: 'sun', | |||
| ...weekdayColConfig, | |||
| renderHeader: () => { | |||
| return ( | |||
| <div style={{color:"red"}}>Sun - {getDateForHeader(day, 7)}</div> | |||
| ); | |||
| }, | |||
| }, | |||
| // { | |||
| // field: 'joinDate', | |||
| // headerName: 'Join date', | |||
| // type: 'date', | |||
| // width: 180, | |||
| // editable: true, | |||
| // }, | |||
| ]; | |||
| return ( | |||
| <Box | |||
| sx={{ | |||
| // marginBottom: '-5px', | |||
| height: '30rem', | |||
| width: '100%', | |||
| '& .actions': { | |||
| color: 'text.secondary', | |||
| }, | |||
| '& .header': { | |||
| // border: 1, | |||
| // 'border-width': '1px', | |||
| // 'border-color': 'grey', | |||
| }, | |||
| '& .textPrimary': { | |||
| color: 'text.primary', | |||
| }, | |||
| }} | |||
| > | |||
| <DataGrid | |||
| rows={rows} | |||
| columns={columns} | |||
| editMode="row" | |||
| rowModesModel={rowModesModel} | |||
| onRowModesModelChange={handleRowModesModelChange} | |||
| onRowEditStop={handleRowEditStop} | |||
| processRowUpdate={processRowUpdate} | |||
| disableRowSelectionOnClick={true} | |||
| disableColumnMenu={true} | |||
| hideFooterPagination={true} | |||
| slots={{ | |||
| toolbar: EditToolbar, | |||
| // footer: EditFooter, | |||
| }} | |||
| slotProps={{ | |||
| toolbar: { setDay, setRows, setRowModesModel }, | |||
| // footer: { setDay, setRows, setRowModesModel }, | |||
| }} | |||
| initialState={{ | |||
| pagination: { paginationModel: { pageSize: 100 } }, | |||
| }} | |||
| /> | |||
| <BottomBar getHoursTotal={getHoursTotal} setRows={setRows} setRowModesModel={setRowModesModel} setLockConfirm={setLockConfirm}/> | |||
| </Box> | |||
| ); | |||
| } | |||
| export default TimesheetInputGrid; | |||
| @@ -0,0 +1 @@ | |||
| export { default } from "./EnterTimesheetModal"; | |||
| @@ -0,0 +1,23 @@ | |||
| import Swal from "sweetalert2"; | |||
| 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 | |||
| }); | |||
| } | |||
| export const popup = (text) => { | |||
| Swal.fire(text); | |||
| } | |||
| @@ -0,0 +1,62 @@ | |||
| "use client"; | |||
| import * as React from "react"; | |||
| 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 { PROJECT_CARD_STYLE } from "@/theme/colorConst"; | |||
| interface ProjectGridProps { | |||
| tab: number; | |||
| } | |||
| const ProjectGrid: React.FC<ProjectGridProps> = (props) => { | |||
| const [items, setItems] = React.useState<Object[]>([]) | |||
| useEffect(() => { | |||
| if (props.tab == 0) { | |||
| setItems(cards) | |||
| } | |||
| else { | |||
| const filteredItems = cards;//cards.filter(item => (item.track == props.tab)); | |||
| setItems(filteredItems); | |||
| } | |||
| }, [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>) => { | |||
| return ( | |||
| <Card style={PROJECT_CARD_STYLE}> | |||
| <CardHeader style={{backgroundColor:'red'}} title={item.code + '\u000A' + item.name}/> | |||
| <CardContent> | |||
| <p>Hours Spent: {item.hr_spent}</p> | |||
| <p>Normal (Others): {item.hr_spent_normal}</p> | |||
| <p>Hours Allocated: {item.hr_alloc}</p> | |||
| <p>Normal (Others): {item.hr_alloc_normal}</p> | |||
| </CardContent> | |||
| </Card> | |||
| ); | |||
| } | |||
| // Apply the preset style to the cards in child, if not specified // | |||
| return ( | |||
| <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> | |||
| ); | |||
| }; | |||
| export default ProjectGrid; | |||
| @@ -0,0 +1,69 @@ | |||
| "use client"; | |||
| import Grid from "@mui/material/Grid"; | |||
| import Paper from "@mui/material/Paper"; | |||
| import { useState } from "react"; | |||
| import { useTranslation } from "react-i18next"; | |||
| import AssignedProjectGrid from "../AssignedProjectGrid/AssignedProjectGrid"; | |||
| import PageTitle from "../PageTitle/PageTitle"; | |||
| import { Suspense } from "react"; | |||
| import Button from "@mui/material/Button"; | |||
| import Stack from "@mui/material/Stack"; | |||
| import { Add } from '@mui/icons-material'; | |||
| import Link from "next/link"; | |||
| import { t } from 'i18next'; | |||
| import { Modal } from "@mui/material"; | |||
| import CustomModal from "../CustomModal/CustomModal"; | |||
| import EnterTimesheetModal from "../EnterTimesheet/EnterTimesheetModal"; | |||
| const UserWorkspacePage: React.FC = () => { | |||
| const [isModalVisible, setModalVisible] = useState(false); | |||
| const { t } = useTranslation("home"); | |||
| const handleButtonClick = () => { | |||
| setModalVisible(true); | |||
| }; | |||
| const handleCloseModal = () => { | |||
| setModalVisible(false); | |||
| }; | |||
| return ( | |||
| <Grid container height="100vh" > | |||
| <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"/> | |||
| </Grid> | |||
| </Grid> | |||
| ); | |||
| }; | |||
| export default UserWorkspacePage; | |||
| @@ -0,0 +1 @@ | |||
| export { default } from "./UserWorkspacePage"; | |||
| @@ -0,0 +1,371 @@ | |||
| import { createTheme } from "@mui/material"; | |||
| import { aborted } from "util"; | |||
| // - - - - - - WORK IN PROGRESS - - - - - - // | |||
| export const chartColor = [ | |||
| '#CB4047', '#ED3A41', '#F47B50', '#FBA647', | |||
| '#FDB64C', '#CCBB32', '#9ACC59', '#57B962', | |||
| '#1E83C5', '#7C4A9D' | |||
| ]; | |||
| export const chartSingleColor = [ | |||
| '#f2969a', '#fc9599', '#faa789', '#f7ae94', | |||
| '#ffd491', '#ede5a1', '#d1f5a2', '#9de0a4', | |||
| '#a2d4f5', '#b685d6' | |||
| ]; | |||
| export const rankColor = [ | |||
| '#FFD700', '#C0C0C0', '#CD853F', '#57B962', '#57B962', | |||
| '#57B962', '#57B962', '#57B962', '#57B962', '#57B962' | |||
| ]; | |||
| export const piechartColor1 = [ | |||
| '#E84A3E', '#F2883C', '#FDCD4D', '#CE478A', '#B63D2A', | |||
| '#6A8B9E', '#60667E', '#58865F', '#2F763E', '#7D80B5', | |||
| ]; | |||
| export const piechartColor2 = [ | |||
| '#6A8B9E', '#60667E', '#58865F', '#2F763E', '#7D80B5', | |||
| '#E84A3E', '#F2883C', '#FDCD4D', '#CE478A', '#B63D2A', | |||
| ]; | |||
| export const cardBorderColor = [ | |||
| '#efb142', '#4bb641', '#448df2', '#e03c04' | |||
| ]; | |||
| export const chartLineColor = [ | |||
| '#FFFFFF', '#D9D9D9' | |||
| ]; | |||
| export const GENERAL_RED_COLOR = '#e03c04'; | |||
| export const TABLE_HEADER_TEXT_COLOR = "#3367D1"; | |||
| export const GENERAL_INFO_COLOR = '#448df2'; | |||
| export const GENERAL_SETTING_COLOR = '#666666'; | |||
| export const GENERAL_BORDER_COLOR = '#e6ebf1'; | |||
| export const GENERAL_TEXT_COLOR = '#262626'; | |||
| export const FONT_SIZE_L = "1.875rem"; | |||
| export const FONT_SIZE_M = "1.5rem"; | |||
| export const FONT_SIZE_S = "1.25rem"; | |||
| export const PROJECT_CARD_STYLE = { | |||
| borderRadius: '10px', | |||
| //border: '10px dotted #ccc', | |||
| width: '20rem', | |||
| margin: '20px', | |||
| //backgroundColor:"pink" | |||
| }; | |||
| 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', | |||
| }; | |||
| 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' | |||
| }, | |||
| }, | |||
| }, | |||
| } | |||
| }; | |||
| // copy from MTMS | |||
| 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 | |||
| }, | |||
| } | |||
| } | |||
| }, | |||
| } | |||
| }); | |||
| export const formTheme = createTheme({ | |||
| 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({ | |||
| 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 | |||
| 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' | |||
| }, | |||
| }, | |||
| }, | |||
| } | |||
| }); | |||