diff --git a/src/app/(main)/settings/company/create/page.tsx b/src/app/(main)/settings/company/create/page.tsx new file mode 100644 index 0000000..1702f2d --- /dev/null +++ b/src/app/(main)/settings/company/create/page.tsx @@ -0,0 +1,22 @@ +import { fetchProjectCategories } from "@/app/api/projects"; +import { preloadStaff } from "@/app/api/staff"; +import { fetchAllTasks, fetchTaskTemplates } from "@/app/api/tasks"; +import CreateProject from "@/components/CreateProject"; +import { I18nProvider, getServerI18n } from "@/i18n"; +import Typography from "@mui/material/Typography"; +import { Metadata } from "next"; + +export const metadata: Metadata = { + title: "Create Project", + }; + +const Companys: React.FC = async () => { + const { t } = await getServerI18n("projects"); + + return( + <>AAAA + ) + +} + +export default Companys; \ No newline at end of file diff --git a/src/app/(main)/settings/company/page.tsx b/src/app/(main)/settings/company/page.tsx new file mode 100644 index 0000000..26332c1 --- /dev/null +++ b/src/app/(main)/settings/company/page.tsx @@ -0,0 +1,50 @@ +import CompanySearch from "@/components/CompanySearch"; +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 { fetchCompanys, preloadCompanys } from "@/app/api/companys"; + +export const metadata: Metadata = { + title: "Company", +}; + +const Company: React.FC = async () => { + const { t } = await getServerI18n("companys"); + + // Preload necessary dependencies + fetchCompanys(); + preloadCompanys(); + + return ( + <> + + + {t("Company")} + + + + }> + + + + ) +}; + +export default Company; diff --git a/src/app/api/companys/index.ts b/src/app/api/companys/index.ts new file mode 100644 index 0000000..3211d1c --- /dev/null +++ b/src/app/api/companys/index.ts @@ -0,0 +1,24 @@ +import { serverFetchJson } from "@/app/utils/fetchUtil"; +import { BASE_API_URL } from "@/config/api"; +import { cache } from "react"; +import "server-only"; + +export interface CompanyResult { + id: number; + companyCode: string; + name: string; + brNo: string; + contactName: string; + phone: string + email: string; +} + +export const preloadCompanys = () => { + fetchCompanys(); +}; + +export const fetchCompanys = cache(async () => { + return serverFetchJson(`${BASE_API_URL}/companys`, { + next: { tags: ["companys"] }, + }); +}); \ No newline at end of file diff --git a/src/components/Breadcrumb/Breadcrumb.tsx b/src/components/Breadcrumb/Breadcrumb.tsx index fbb68e2..44b16a8 100644 --- a/src/components/Breadcrumb/Breadcrumb.tsx +++ b/src/components/Breadcrumb/Breadcrumb.tsx @@ -15,6 +15,7 @@ const pathToLabelMap: { [path: string]: string } = { "/tasks/create": "Create Task Template", "/customer": "Customer", "/customer/create": "Create Customer", + "/company": "Company", }; const Breadcrumb = () => { diff --git a/src/components/CompanySearch/CompanySearch.tsx b/src/components/CompanySearch/CompanySearch.tsx new file mode 100644 index 0000000..27a9635 --- /dev/null +++ b/src/components/CompanySearch/CompanySearch.tsx @@ -0,0 +1,87 @@ +"use client"; + +import { CompanyResult } from "@/app/api/companys"; +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 uniq from "lodash/uniq"; + +interface Props { + companys: CompanyResult[]; +} + +type SearchQuery = Partial>; +type SearchParamNames = keyof SearchQuery; + +const CompanySearch: React.FC = ({ companys }) => { + const { t } = useTranslation("companys"); + + const [filteredCompanys, setFilteredCompanys] = useState(companys); + + const searchCriteria: Criterion[] = useMemo( + () => [ + { label: t("Company code"), paramName: "companyCode", type: "text" }, + { label: t("Company name"), paramName: "name", type: "text" }, + { label: t("Contact Name"), paramName: "contactName", type: "text" }, + { label: t("Contact Number"), paramName: "phone", type: "text" }, + ], + [t, companys], + ); + + const onReset = useCallback(() => { + setFilteredCompanys(companys); + }, [companys]); + + const onProjectClick = useCallback((project: CompanyResult) => { + console.log(project); + }, []); + + const columns = useMemo[]>( + () => [ + { + name: "id", + label: t("Details"), + onClick: onProjectClick, + buttonIcon: , + }, + { name: "companyCode", label: t("Company Code") }, + { name: "name", label: t("Company Name") }, + { name: "brNo", label: t("brNo") }, + { name: "contactName", label: t("Contact Name") }, + { name: "phone", label: t("Contact No.") }, + { name: "email", label: t("Contact Email") } + ], + [t, onProjectClick], + ); + + return ( + <> + { + setFilteredCompanys( + companys.filter( + (p) => + p.companyCode.toLowerCase().includes(query.companyCode.toLowerCase()) && + p.name.toLowerCase().includes(query.name.toLowerCase()) && + p.contactName.toLowerCase().includes(query.contactName.toLowerCase()) && + p.phone.toLowerCase().includes(query.phone.toLowerCase()) && + {/*(query.client === "All" || p.client === query.client) && + (query.category === "All" || p.category === query.category) && + (query.team === "All" || p.team === query.team), **/} + ), + ); + }} + onReset={onReset} + /> + + items={filteredCompanys} + columns={columns} + /> + + ); +}; + +export default CompanySearch; diff --git a/src/components/CompanySearch/CompanySearchLoading.tsx b/src/components/CompanySearch/CompanySearchLoading.tsx new file mode 100644 index 0000000..68eb7a6 --- /dev/null +++ b/src/components/CompanySearch/CompanySearchLoading.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 CompanySearchLoading: React.FC = () => { + return ( + <> + + + + + + + + + + + + + + + + + + + + + + ); +}; + +export default CompanySearchLoading; diff --git a/src/components/CompanySearch/CompanySearchWrapper.tsx b/src/components/CompanySearch/CompanySearchWrapper.tsx new file mode 100644 index 0000000..f7e61a0 --- /dev/null +++ b/src/components/CompanySearch/CompanySearchWrapper.tsx @@ -0,0 +1,20 @@ +// import { fetchCompanyCategories, fetchCompanys } from "@/app/api/companys"; +import React from "react"; +import CompanySearch from "./CompanySearch"; +import CompanySearchLoading from "./CompanySearchLoading"; +import { fetchCompanys } from "@/app/api/companys"; + +interface SubComponents { + Loading: typeof CompanySearchLoading; +} + +const CompanySearchWrapper: React.FC & SubComponents = async () => { + // const Companys = await fetchCompanys(); + const Companys = await fetchCompanys(); + + return ; +}; + +CompanySearchWrapper.Loading = CompanySearchLoading; + +export default CompanySearchWrapper; diff --git a/src/components/CompanySearch/index.ts b/src/components/CompanySearch/index.ts new file mode 100644 index 0000000..69bd2a2 --- /dev/null +++ b/src/components/CompanySearch/index.ts @@ -0,0 +1 @@ +export { default } from "./CompanySearchWrapper"; diff --git a/src/components/NavigationContent/NavigationContent.tsx b/src/components/NavigationContent/NavigationContent.tsx index 1bb497e..9eb5ebc 100644 --- a/src/components/NavigationContent/NavigationContent.tsx +++ b/src/components/NavigationContent/NavigationContent.tsx @@ -91,7 +91,8 @@ const navigationItems: NavigationItem[] = [ icon: , label: "Setting", path: "", children: [ { icon: , label: "Customer", path: "/customer" }, - { icon: , label: "Staff", path: "/staff" } + { icon: , label: "Staff", path: "/staff" }, + { icon: , label: "Company", path: "/settings/company" } ], }, ];