From 8d50d437263f30342bedae0394e18b57ca0c6928 Mon Sep 17 00:00:00 2001 From: "MSI\\2Fi" Date: Wed, 10 Apr 2024 10:42:42 +0800 Subject: [PATCH] Salary page --- src/app/(main)/settings/salary/page.tsx | 50 ++++++++++++ src/app/api/salarys/index.ts | 22 ++++++ src/components/Breadcrumb/Breadcrumb.tsx | 1 + .../NavigationContent/NavigationContent.tsx | 2 + src/components/SalarySearch/SalarySearch.tsx | 77 +++++++++++++++++++ .../SalarySearch/SalarySearchLoading.tsx | 40 ++++++++++ .../SalarySearch/SalarySearchWrapper.tsx | 20 +++++ src/components/SalarySearch/index.ts | 1 + 8 files changed, 213 insertions(+) create mode 100644 src/app/(main)/settings/salary/page.tsx create mode 100644 src/app/api/salarys/index.ts create mode 100644 src/components/SalarySearch/SalarySearch.tsx create mode 100644 src/components/SalarySearch/SalarySearchLoading.tsx create mode 100644 src/components/SalarySearch/SalarySearchWrapper.tsx create mode 100644 src/components/SalarySearch/index.ts diff --git a/src/app/(main)/settings/salary/page.tsx b/src/app/(main)/settings/salary/page.tsx new file mode 100644 index 0000000..d1c1d63 --- /dev/null +++ b/src/app/(main)/settings/salary/page.tsx @@ -0,0 +1,50 @@ +import SalarySearch from "@/components/SalarySearch"; +import { Metadata } from "next"; +import { getServerI18n } from "@/i18n"; +import Add from "@mui/icons-material/Add"; +import Button from "@mui/material/Button"; +import Stack from "@mui/material/Stack"; +import Typography from "@mui/material/Typography"; +import Link from "next/link"; +import { Suspense } from "react"; +import { fetchSalarys, preloadSalarys } from "@/app/api/salarys"; + +export const metadata: Metadata = { + title: "Salary", +}; + +const Salary: React.FC = async () => { + const { t } = await getServerI18n("Salary"); + + // Preload necessary dependencies + // fetchSalarys(); + // preloadSalarys(); + + return ( + <> + + + {t("Salary")} + + + + }> + + + + ) +}; + +export default Salary; diff --git a/src/app/api/salarys/index.ts b/src/app/api/salarys/index.ts new file mode 100644 index 0000000..02fcf55 --- /dev/null +++ b/src/app/api/salarys/index.ts @@ -0,0 +1,22 @@ +import { serverFetchJson } from "@/app/utils/fetchUtil"; +import { BASE_API_URL } from "@/config/api"; +import { cache } from "react"; +import "server-only"; + +export interface SalaryResult { + id: number; + lowerLimit: number; + upperLimit: number; + salaryPoint: number; + salary: number; +} + +export const preloadSalarys = () => { + fetchSalarys(); +}; + +export const fetchSalarys = cache(async () => { + return serverFetchJson(`${BASE_API_URL}/salarys`, { + next: { tags: ["salarys"] }, + }); +}); diff --git a/src/components/Breadcrumb/Breadcrumb.tsx b/src/components/Breadcrumb/Breadcrumb.tsx index 9439cc8..55ce53d 100644 --- a/src/components/Breadcrumb/Breadcrumb.tsx +++ b/src/components/Breadcrumb/Breadcrumb.tsx @@ -22,6 +22,7 @@ const pathToLabelMap: { [path: string]: string } = { "/settings/department/new": "Create Department", "/settings/position": "Position", "/settings/position/new": "Create Position", + "/settings/salarys": "Salary", }; const Breadcrumb = () => { diff --git a/src/components/NavigationContent/NavigationContent.tsx b/src/components/NavigationContent/NavigationContent.tsx index fbb1aa5..5817dde 100644 --- a/src/components/NavigationContent/NavigationContent.tsx +++ b/src/components/NavigationContent/NavigationContent.tsx @@ -21,6 +21,7 @@ import Staff from "@mui/icons-material/PeopleAlt"; import Company from '@mui/icons-material/Store'; import Department from '@mui/icons-material/Diversity3'; import Position from '@mui/icons-material/Paragliding'; +import Salary from '@mui/icons-material/AttachMoney'; import { useTranslation } from "react-i18next"; import Typography from "@mui/material/Typography"; import { usePathname } from "next/navigation"; @@ -98,6 +99,7 @@ const navigationItems: NavigationItem[] = [ { icon: , label: "Company", path: "/settings/company" }, { icon: , label: "Department", path: "/settings/department" }, { icon: , label: "Position", path: "/settings/position" }, + { icon: , label: "Salary", path: "/settings/salary" }, ], }, ]; diff --git a/src/components/SalarySearch/SalarySearch.tsx b/src/components/SalarySearch/SalarySearch.tsx new file mode 100644 index 0000000..8513fca --- /dev/null +++ b/src/components/SalarySearch/SalarySearch.tsx @@ -0,0 +1,77 @@ +"use client"; + +import React, { useCallback, useMemo, useState } from "react"; +import SearchBox, { Criterion } from "../SearchBox"; +import { useTranslation } from "react-i18next"; +import SearchResults, { Column } from "../SearchResults"; +import EditNote from "@mui/icons-material/EditNote"; +import { SalaryResult } from "@/app/api/salarys"; + +interface Props { + salarys: SalaryResult[]; +} + +type SearchQuery = Partial>; +type SearchParamNames = keyof SearchQuery; + +const SalarySearch: React.FC = ({ salarys }) => { + const { t } = useTranslation("salarys"); + + const [filteredSalarys, setFilteredSalarys] = useState(salarys); + + const searchCriteria: Criterion[] = useMemo( + () => [ + { label: t("Salary"), paramName: "salary", type: "text" }, + { label: t("Salary Point"), paramName: "salaryPoint", type: "text" }, + ], + [t, salarys], + ); + + const onReset = useCallback(() => { + setFilteredSalarys(salarys); + }, [salarys]); + + const onSalaryClick = useCallback((project: SalaryResult) => { + console.log(project); + }, []); + + const columns = useMemo[]>( + () => [ + { + name: "id", + label: t("Details"), + onClick: onSalaryClick, + buttonIcon: , + }, + { name: "salaryPoint", label: t("Salary Point") }, + { name: "lowerLimit", label: t("Lower Limit") }, + { name: "upperLimit", label: t("Upper Limit") }, + ], + [t, onSalaryClick], + ); + + return ( + <> + { + setFilteredSalarys( + salarys.filter( + (s) => + ((s.lowerLimit <= Number(query.salary))&& + (s.upperLimit >= Number(query.salary)))|| + (s.salaryPoint === Number(query.salaryPoint)) + ), + ); + }} + onReset={onReset} + /> + + items={filteredSalarys} + columns={columns} + /> + + ); +}; + +export default SalarySearch; diff --git a/src/components/SalarySearch/SalarySearchLoading.tsx b/src/components/SalarySearch/SalarySearchLoading.tsx new file mode 100644 index 0000000..e2cc58d --- /dev/null +++ b/src/components/SalarySearch/SalarySearchLoading.tsx @@ -0,0 +1,40 @@ +import Card from "@mui/material/Card"; +import CardContent from "@mui/material/CardContent"; +import Skeleton from "@mui/material/Skeleton"; +import Stack from "@mui/material/Stack"; +import React from "react"; + +// Can make this nicer +export const SalarySearchLoading: React.FC = () => { + return ( + <> + + + + + + + + + + + Salary + + + + + + + + + + + ); +}; + +export default SalarySearchLoading; diff --git a/src/components/SalarySearch/SalarySearchWrapper.tsx b/src/components/SalarySearch/SalarySearchWrapper.tsx new file mode 100644 index 0000000..4687c17 --- /dev/null +++ b/src/components/SalarySearch/SalarySearchWrapper.tsx @@ -0,0 +1,20 @@ +// import { fetchSalaryCategories, fetchSalarys } from "@/app/api/companys"; +import React from "react"; +import SalarySearch from "./SalarySearch"; +import SalarySearchLoading from "./SalarySearchLoading"; +import { fetchSalarys } from "@/app/api/salarys"; + +interface SubComponents { + Loading: typeof SalarySearchLoading; +} + +const SalarySearchWrapper: React.FC & SubComponents = async () => { + const Salarys = await fetchSalarys(); + // const Salarys:any[] = [] + + return ; +}; + +SalarySearchWrapper.Loading = SalarySearchLoading; + +export default SalarySearchWrapper; diff --git a/src/components/SalarySearch/index.ts b/src/components/SalarySearch/index.ts new file mode 100644 index 0000000..9134949 --- /dev/null +++ b/src/components/SalarySearch/index.ts @@ -0,0 +1 @@ +export { default } from "./SalarySearchWrapper";