@@ -1,4 +1,3 @@ | |||||
"use client"; | |||||
import { fetchProjectCategories } from "@/app/api/projects"; | import { fetchProjectCategories } from "@/app/api/projects"; | ||||
import { preloadStaff } from "@/app/api/staff"; | import { preloadStaff } from "@/app/api/staff"; | ||||
import { fetchAllTasks, fetchTaskTemplates } from "@/app/api/tasks"; | import { fetchAllTasks, fetchTaskTemplates } from "@/app/api/tasks"; | ||||
@@ -17,7 +17,7 @@ export default async function RootLayout({ | |||||
return ( | return ( | ||||
<html lang={lang}> | <html lang={lang}> | ||||
<body> | <body> | ||||
<ThemeRegistry>{children}</ThemeRegistry> | |||||
<ThemeRegistry lang={lang}>{children}</ThemeRegistry> | |||||
</body> | </body> | ||||
</html> | </html> | ||||
); | ); | ||||
@@ -8,6 +8,7 @@ import { | |||||
ListItemButton, | ListItemButton, | ||||
ListItemText, | ListItemText, | ||||
TextField, | TextField, | ||||
Alert, | |||||
} from "@mui/material"; | } from "@mui/material"; | ||||
import { useState, useCallback, useEffect, useMemo } from "react"; | import { useState, useCallback, useEffect, useMemo } from "react"; | ||||
import { useTranslation } from "react-i18next"; | import { useTranslation } from "react-i18next"; | ||||
@@ -230,4 +231,28 @@ const ResourceAllocation: React.FC<Props> = ({ | |||||
); | ); | ||||
}; | }; | ||||
export default ResourceAllocation; | |||||
const NoTaskState: React.FC = () => { | |||||
const { t } = useTranslation(); | |||||
return ( | |||||
<> | |||||
<Typography variant="overline" display="block" marginBlockEnd={1}> | |||||
{t("Task Breakdown")} | |||||
</Typography> | |||||
<Alert severity="warning"> | |||||
{t('Please add some tasks in "Project Task Setup" first!')} | |||||
</Alert> | |||||
</> | |||||
); | |||||
}; | |||||
const ResourceAllocationWrapper: React.FC<Props> = (props) => { | |||||
const { getValues } = useFormContext<CreateProjectInputs>(); | |||||
if (Object.keys(getValues("tasks")).length === 0) { | |||||
return <NoTaskState />; | |||||
} | |||||
return <ResourceAllocation {...props} />; | |||||
}; | |||||
export default ResourceAllocationWrapper; |
@@ -12,8 +12,6 @@ import TablePagination, { | |||||
} from "@mui/material/TablePagination"; | } from "@mui/material/TablePagination"; | ||||
import TableRow from "@mui/material/TableRow"; | import TableRow from "@mui/material/TableRow"; | ||||
import IconButton from "@mui/material/IconButton"; | import IconButton from "@mui/material/IconButton"; | ||||
import { ThemeProvider, createTheme } from "@mui/material"; | |||||
import { zhTW, enUS } from '@mui/material/locale'; | |||||
export interface ResultWithId { | export interface ResultWithId { | ||||
id: string | number; | id: string | number; | ||||
@@ -67,18 +65,8 @@ function SearchResults<T extends ResultWithId>({ | |||||
setPage(0); | setPage(0); | ||||
}; | }; | ||||
const theme = createTheme( | |||||
// locale | |||||
//TODO: May need to know what locale the client is using | |||||
// localStorage.getItem("locale")?.includes("zh") ? zhTW : enUS | |||||
zhTW | |||||
); | |||||
const table = ( | const table = ( | ||||
<> | <> | ||||
<ThemeProvider theme={theme}> | |||||
<TableContainer sx={{ maxHeight: 440 }}> | <TableContainer sx={{ maxHeight: 440 }}> | ||||
<Table stickyHeader> | <Table stickyHeader> | ||||
<TableHead> | <TableHead> | ||||
@@ -129,7 +117,6 @@ function SearchResults<T extends ResultWithId>({ | |||||
onPageChange={handleChangePage} | onPageChange={handleChangePage} | ||||
onRowsPerPageChange={handleChangeRowsPerPage} | onRowsPerPageChange={handleChangeRowsPerPage} | ||||
/> | /> | ||||
</ThemeProvider> | |||||
</> | </> | ||||
); | ); | ||||
@@ -1,19 +1,36 @@ | |||||
"use client"; | "use client"; | ||||
import * as React from "react"; | import * as React from "react"; | ||||
import { ThemeProvider } from "@mui/material/styles"; | |||||
import { ThemeProvider, createTheme } from "@mui/material/styles"; | |||||
import CssBaseline from "@mui/material/CssBaseline"; | import CssBaseline from "@mui/material/CssBaseline"; | ||||
import NextAppDirEmotionCacheProvider from "./EmotionCache"; | import NextAppDirEmotionCacheProvider from "./EmotionCache"; | ||||
import theme from "./devias-material-kit"; | import theme from "./devias-material-kit"; | ||||
import { zhHK, enUS } from "@mui/material/locale"; | |||||
const getLocalizationFromLang = (lang: string) => { | |||||
switch (lang) { | |||||
case "zh": | |||||
return zhHK; | |||||
default: | |||||
return enUS; | |||||
} | |||||
}; | |||||
// Copied from https://github.com/mui/material-ui/blob/master/examples/material-ui-nextjs-ts/src/components/ThemeRegistry/ThemeRegistry.tsx | // Copied from https://github.com/mui/material-ui/blob/master/examples/material-ui-nextjs-ts/src/components/ThemeRegistry/ThemeRegistry.tsx | ||||
export default function ThemeRegistry({ | export default function ThemeRegistry({ | ||||
children, | children, | ||||
lang, | |||||
}: { | }: { | ||||
children: React.ReactNode; | children: React.ReactNode; | ||||
lang: string; | |||||
}) { | }) { | ||||
const themeWithLocale = React.useMemo( | |||||
() => createTheme(theme, getLocalizationFromLang(lang)), | |||||
[lang], | |||||
); | |||||
return ( | return ( | ||||
<NextAppDirEmotionCacheProvider options={{ key: "mui" }}> | <NextAppDirEmotionCacheProvider options={{ key: "mui" }}> | ||||
<ThemeProvider theme={theme}> | |||||
<ThemeProvider theme={themeWithLocale}> | |||||
<CssBaseline /> | <CssBaseline /> | ||||
{children} | {children} | ||||
</ThemeProvider> | </ThemeProvider> | ||||