diff --git a/src/app/api/tasks/index.ts b/src/app/api/tasks/index.ts index a9dae82..ffc15f2 100644 --- a/src/app/api/tasks/index.ts +++ b/src/app/api/tasks/index.ts @@ -12,7 +12,7 @@ export interface Task { id: number; name: string; description: string | null; - taskGroup: TaskGroup | null; + taskGroup: TaskGroup; } export interface TaskTemplate { diff --git a/src/app/utils/formatUtil.ts b/src/app/utils/formatUtil.ts new file mode 100644 index 0000000..c2e38ea --- /dev/null +++ b/src/app/utils/formatUtil.ts @@ -0,0 +1,9 @@ +export const manhourFormatter = new Intl.NumberFormat("en-HK", { + minimumFractionDigits: 2, + maximumFractionDigits: 2, +}); + +export const moneyFormatter = new Intl.NumberFormat("en-HK", { + style: "currency", + currency: "HKD", +}); diff --git a/src/components/CreateProject/CreateProject.tsx b/src/components/CreateProject/CreateProject.tsx index e118304..622205e 100644 --- a/src/components/CreateProject/CreateProject.tsx +++ b/src/components/CreateProject/CreateProject.tsx @@ -13,8 +13,13 @@ import ProjectClientDetails from "./ProjectClientDetails"; import TaskSetup from "./TaskSetup"; import StaffAllocation from "./StaffAllocation"; import ResourceMilestone from "./ResourceMilestone"; +import { Task } from "@/app/api/tasks"; -const CreateProject: React.FC = () => { +export interface Props { + mockTasks: Task[]; +} + +const CreateProject: React.FC = ({ mockTasks }) => { const [tabIndex, setTabIndex] = useState(0); const { t } = useTranslation(); const router = useRouter(); @@ -41,7 +46,7 @@ const CreateProject: React.FC = () => { {tabIndex === 0 && } {tabIndex === 1 && } {tabIndex === 2 && } - {tabIndex === 3 && } + {tabIndex === 3 && } + + + + + + + {t("Project Total Fee")} + {moneyFormatter.format(80000)} + + + + + ); +}; + +const NoTaskState: React.FC = () => { + const { t } = useTranslation(); return ( - - - {t("Resource and Milestone")} - - - - + + + {t('Please add some tasks in "Project Task Setup" first!')} + ); }; -export default ResourceMilestone; +const ResourceMilestoneWrapper: React.FC = (props) => { + if (props.tasks.length === 0) { + return ; + } + + return ; +}; + +export default ResourceMilestoneWrapper; diff --git a/src/components/CreateProject/StaffAllocation.tsx b/src/components/CreateProject/StaffAllocation.tsx index 7c5b806..f025749 100644 --- a/src/components/CreateProject/StaffAllocation.tsx +++ b/src/components/CreateProject/StaffAllocation.tsx @@ -28,6 +28,7 @@ import { } from "@mui/material"; import differenceBy from "lodash/differenceBy"; import uniq from "lodash/uniq"; +import ResourceCapacity from "./ResourceCapacity"; interface StaffResult { id: string; @@ -222,87 +223,90 @@ const StaffAllocation: React.FC = ({ }, [clearQueryInput, clearStaff, defaultFilterValues]); return ( - - - - - {t("Staff Allocation")} - - - - - - - - - - ), - }} - /> - - {columnFilters.map((filter, idx) => { - const label = staffPoolColumns.find( - (c) => c.name === filter, - )!.label; + <> + + + + + {t("Staff Allocation")} + + + + + + + + + + ), + }} + /> + + {columnFilters.map((filter, idx) => { + const label = staffPoolColumns.find( + (c) => c.name === filter, + )!.label; - return ( - - - {label} - - - - ); - })} - - - - - - - {tabIndex === 0 && ( - - )} - {tabIndex === 1 && ( - - )} - - - - - - - + return ( + + + {label} + + + + ); + })} + + + + + + + {tabIndex === 0 && ( + + )} + {tabIndex === 1 && ( + + )} + + + + + + + + + ); }; diff --git a/src/components/CreateProject/TaskSetup.tsx b/src/components/CreateProject/TaskSetup.tsx index 020d625..177110c 100644 --- a/src/components/CreateProject/TaskSetup.tsx +++ b/src/components/CreateProject/TaskSetup.tsx @@ -46,11 +46,11 @@ const TaskSetup = () => { {}} diff --git a/src/components/CreateProject/index.ts b/src/components/CreateProject/index.ts index 054f07a..6332185 100644 --- a/src/components/CreateProject/index.ts +++ b/src/components/CreateProject/index.ts @@ -1 +1 @@ -export { default } from "./CreateProject"; +export { default } from "./CreateProjectWrapper"; diff --git a/src/components/SearchBox/SearchBox.tsx b/src/components/SearchBox/SearchBox.tsx index 7606037..56c9b13 100644 --- a/src/components/SearchBox/SearchBox.tsx +++ b/src/components/SearchBox/SearchBox.tsx @@ -15,10 +15,12 @@ import CardActions from "@mui/material/CardActions"; import Button from "@mui/material/Button"; import RestartAlt from "@mui/icons-material/RestartAlt"; import Search from "@mui/icons-material/Search"; -import dayjs from 'dayjs'; -import { DatePicker } from '@mui/x-date-pickers/DatePicker'; -import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; -import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; +import dayjs from "dayjs"; +import "dayjs/locale/zh-hk"; +import { DatePicker } from "@mui/x-date-pickers/DatePicker"; +import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider"; +import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs"; +import { Box } from "@mui/material"; interface BaseCriterion { label: string; @@ -40,7 +42,10 @@ interface DateRangeCriterion extends BaseCriterion { type: "dateRange"; } -export type Criterion = TextCriterion | SelectCriterion | DateRangeCriterion; +export type Criterion = + | TextCriterion + | SelectCriterion + | DateRangeCriterion; interface Props { criteria: Criterion[]; @@ -54,7 +59,6 @@ function SearchBox({ onReset, }: Props) { const { t } = useTranslation("common"); - const [dayRangeFromDate, setDayRangeFromDate] :any = useState(""); const defaultInputs = useMemo( () => criteria.reduce>( @@ -82,23 +86,20 @@ function SearchBox({ }; }, []); - const makeDateChangeHandler = useCallback( - (paramName: T) => { - return (e:any) => { - setInputs((i) => ({ ...i, [paramName]: dayjs(e).format('YYYY-MM-DD') })); + const makeDateChangeHandler = useCallback((paramName: T) => { + return (e: any) => { + setInputs((i) => ({ ...i, [paramName]: dayjs(e).format("YYYY-MM-DD") })); }; - }, - [], - ); + }, []); - const makeDateToChangeHandler = useCallback( - (paramName: T) => { - return (e:any) => { - setInputs((i) => ({ ...i, [paramName + "To"]: dayjs(e).format('YYYY-MM-DD') })); + const makeDateToChangeHandler = useCallback((paramName: T) => { + return (e: any) => { + setInputs((i) => ({ + ...i, + [paramName + "To"]: dayjs(e).format("YYYY-MM-DD"), + })); }; - }, - [], - ); + }, []); const handleReset = () => { setInputs(defaultInputs); @@ -143,33 +144,34 @@ function SearchBox({ )} {c.type === "dateRange" && ( - - - - - - - - - - - - - - - - - - - - - - + + + + + + + {"-"} + + + + + + )} ); diff --git a/src/theme/devias-material-kit/components.ts b/src/theme/devias-material-kit/components.ts index ee432e8..2fe5b46 100644 --- a/src/theme/devias-material-kit/components.ts +++ b/src/theme/devias-material-kit/components.ts @@ -47,6 +47,13 @@ const components: ThemeOptions["components"] = { }, }, }, + MuiAlert: { + styleOverrides: { + root: { + borderRadius: 8, + }, + }, + }, MuiPaper: { styleOverrides: { rounded: {