@@ -1,18 +1,23 @@ | |||||
import { Metadata } from "next"; | import { Metadata } from "next"; | ||||
import { Suspense } from "react"; | import { Suspense } from "react"; | ||||
import { I18nProvider } from "@/i18n"; | |||||
import { I18nProvider, getServerI18n } from "@/i18n"; | |||||
import { fetchProjects } from "@/app/api/projects"; | import { fetchProjects } from "@/app/api/projects"; | ||||
import GenerateProjectCashFlowReport from "@/components/GenerateProjectCashFlowReport"; | import GenerateProjectCashFlowReport from "@/components/GenerateProjectCashFlowReport"; | ||||
import { Typography } from "@mui/material"; | |||||
export const metadata: Metadata = { | export const metadata: Metadata = { | ||||
title: "Project Cash Flow Report", | title: "Project Cash Flow Report", | ||||
}; | }; | ||||
const ProjectCashFlowReport: React.FC = async () => { | const ProjectCashFlowReport: React.FC = async () => { | ||||
const { t } = await getServerI18n("reports"); | |||||
fetchProjects(); | fetchProjects(); | ||||
return ( | return ( | ||||
<> | <> | ||||
<Typography variant="h4" marginInlineEnd={2}> | |||||
{t("Project Cash Flow Report")} | |||||
</Typography> | |||||
<I18nProvider namespaces={["report", "common"]}> | <I18nProvider namespaces={["report", "common"]}> | ||||
<Suspense fallback={<GenerateProjectCashFlowReport.Loading />}> | <Suspense fallback={<GenerateProjectCashFlowReport.Loading />}> | ||||
<GenerateProjectCashFlowReport /> | <GenerateProjectCashFlowReport /> | ||||
@@ -41,6 +41,7 @@ const GenerateProjectCashFlowReport: React.FC<Props> = ({ projects }) => { | |||||
} | } | ||||
} | } | ||||
}} | }} | ||||
formType={"download"} | |||||
/> | /> | ||||
</> | </> | ||||
); | ); | ||||
@@ -15,6 +15,7 @@ import CardActions from "@mui/material/CardActions"; | |||||
import Button from "@mui/material/Button"; | import Button from "@mui/material/Button"; | ||||
import RestartAlt from "@mui/icons-material/RestartAlt"; | import RestartAlt from "@mui/icons-material/RestartAlt"; | ||||
import Search from "@mui/icons-material/Search"; | import Search from "@mui/icons-material/Search"; | ||||
import FileDownload from '@mui/icons-material/FileDownload'; | |||||
import dayjs from "dayjs"; | import dayjs from "dayjs"; | ||||
import "dayjs/locale/zh-hk"; | import "dayjs/locale/zh-hk"; | ||||
import { DatePicker } from "@mui/x-date-pickers/DatePicker"; | import { DatePicker } from "@mui/x-date-pickers/DatePicker"; | ||||
@@ -58,12 +59,14 @@ interface Props<T extends string> { | |||||
criteria: Criterion<T>[]; | criteria: Criterion<T>[]; | ||||
onSearch: (inputs: Record<T, string>) => void; | onSearch: (inputs: Record<T, string>) => void; | ||||
onReset?: () => void; | onReset?: () => void; | ||||
formType?: String, | |||||
} | } | ||||
function SearchBox<T extends string>({ | function SearchBox<T extends string>({ | ||||
criteria, | criteria, | ||||
onSearch, | onSearch, | ||||
onReset, | onReset, | ||||
formType, | |||||
}: Props<T>) { | }: Props<T>) { | ||||
const { t } = useTranslation("common"); | const { t } = useTranslation("common"); | ||||
const defaultInputs = useMemo( | const defaultInputs = useMemo( | ||||
@@ -223,22 +226,22 @@ function SearchBox<T extends string>({ | |||||
); | ); | ||||
})} | })} | ||||
</Grid> | </Grid> | ||||
<CardActions sx={{ justifyContent: "flex-end" }}> | |||||
<Button | |||||
variant="text" | |||||
startIcon={<RestartAlt />} | |||||
onClick={handleReset} | |||||
> | |||||
{t("Reset")} | |||||
</Button> | |||||
<Button | |||||
variant="outlined" | |||||
startIcon={<Search />} | |||||
onClick={handleSearch} | |||||
> | |||||
{t("Search")} | |||||
</Button> | |||||
</CardActions> | |||||
<CardActions sx={{ justifyContent: "flex-end" }}> | |||||
<Button | |||||
variant="text" | |||||
startIcon={<RestartAlt />} | |||||
onClick={handleReset} | |||||
> | |||||
{t("Reset")} | |||||
</Button> | |||||
<Button | |||||
variant="outlined" | |||||
startIcon={(formType === "download" && <FileDownload />) || <Search />} | |||||
onClick={handleSearch} | |||||
> | |||||
{(formType === "download" && t("Download")) || t("Search")} | |||||
</Button> | |||||
</CardActions> | |||||
</CardContent> | </CardContent> | ||||
</Card> | </Card> | ||||
); | ); | ||||
@@ -19,6 +19,7 @@ | |||||
"Details": "Details", | "Details": "Details", | ||||
"Delete": "Delete", | "Delete": "Delete", | ||||
"Download": "Download", | |||||
"Search": "Search", | "Search": "Search", | ||||
"Search Criteria": "Search Criteria", | "Search Criteria": "Search Criteria", | ||||
"Cancel": "Cancel", | "Cancel": "Cancel", | ||||
@@ -17,6 +17,7 @@ | |||||
"Details": "詳情", | "Details": "詳情", | ||||
"Delete": "刪除", | "Delete": "刪除", | ||||
"Download": "下載", | |||||
"Search": "搜尋", | "Search": "搜尋", | ||||
"Search Criteria": "搜尋條件", | "Search Criteria": "搜尋條件", | ||||
"Cancel": "取消", | "Cancel": "取消", | ||||