user workspace enter timesheet input added Custom Alert for unificationtags/Baseline_30082024_FRONTEND_UAT
@@ -1,11 +1,17 @@ | |||||
import { Metadata } from "next"; | import { Metadata } from "next"; | ||||
import { I18nProvider } from "@/i18n"; | |||||
import UserWorkspacePage from "@/components/UserWorkspacePage/UserWorkspacePage"; | |||||
export const metadata: Metadata = { | export const metadata: Metadata = { | ||||
title: "Home", | |||||
title: "User Workspace", | |||||
}; | }; | ||||
const Home: React.FC = async () => { | const Home: React.FC = async () => { | ||||
return "Home"; | |||||
return ( | |||||
<I18nProvider namespaces={["home"]}> | |||||
<UserWorkspacePage/> | |||||
</I18nProvider> | |||||
); | |||||
}; | }; | ||||
export default Home; | 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' | |||||
}, | |||||
}, | |||||
}, | |||||
} | |||||
}); |