From d2ed0abc0432fbd4dd956b277c540715aa0bdb57 Mon Sep 17 00:00:00 2001 From: "MSI\\2Fi" Date: Mon, 13 May 2024 18:29:31 +0800 Subject: [PATCH] Edit Company Type import Inovice --- src/app/(main)/settings/company/edit/page.tsx | 30 ++++ src/app/api/companys/actions.ts | 32 +++- src/app/api/companys/index.ts | 10 ++ src/app/utils/formatUtil.ts | 19 ++ .../CompanySearch/CompanySearch.tsx | 32 +++- .../CreateCompany/CompanyDetails.tsx | 165 ++++++++++-------- .../CreateCompany/CreateCompany.tsx | 49 ++++-- .../CreateCompany/CreateCompanyWrapper.tsx | 20 ++- .../InvoiceSearch/InvoiceSearch.tsx | 4 +- 9 files changed, 262 insertions(+), 99 deletions(-) create mode 100644 src/app/(main)/settings/company/edit/page.tsx diff --git a/src/app/(main)/settings/company/edit/page.tsx b/src/app/(main)/settings/company/edit/page.tsx new file mode 100644 index 0000000..3ff9e17 --- /dev/null +++ b/src/app/(main)/settings/company/edit/page.tsx @@ -0,0 +1,30 @@ +import CreateCompany from "@/components/CreateCompany"; +import { I18nProvider, getServerI18n } from "@/i18n"; +import Typography from "@mui/material/Typography"; +import { Metadata } from "next"; + +export const metadata: Metadata = { + title: "Create Comapny", +}; + +interface Props { + searchParams: { [key: string]: string | undefined }; +} + +const Companys: React.FC = async ({searchParams}) => { + const { t } = await getServerI18n("companys"); + + const companyId = searchParams["id"]; + + return( + <> + {t("Create Company")} + + + + + ) + +} + +export default Companys; \ No newline at end of file diff --git a/src/app/api/companys/actions.ts b/src/app/api/companys/actions.ts index f342177..9afc9c7 100644 --- a/src/app/api/companys/actions.ts +++ b/src/app/api/companys/actions.ts @@ -1,6 +1,6 @@ "use server"; -import { serverFetchJson } from "@/app/utils/fetchUtil"; +import { serverFetchJson, serverFetchWithNoContent } from "@/app/utils/fetchUtil"; import { BASE_API_URL } from "@/config/api"; import { Dayjs } from "dayjs"; import { cache } from "react"; @@ -15,6 +15,7 @@ export interface combo { } export interface CreateCompanyInputs { + id?: number; companyCode: string; companyName: string; brNo: string; @@ -30,6 +31,23 @@ export interface CreateCompanyInputs { email: string; } +export interface EditCompanyInputs { + id?: number; + companyCode: string; + name: string; + brNo: string; + contactName: string; + phone: string; + otHourTo: number[]; + otHourFrom: number[]; + normalHourTo: number[]; + normalHourFrom: number[]; + currency: string; + address: string; + district: string; + email: string; +} + export const saveCompany = async (data: CreateCompanyInputs) => { return serverFetchJson(`${BASE_API_URL}/companys/new`, { method: "POST", @@ -43,3 +61,15 @@ export const fetchCompanyCombo = cache(async () => { next: { tags: ["company"] }, }); }); + +export const deleteCompany = async (id: number) => { + const department = await serverFetchWithNoContent( + `${BASE_API_URL}/companys/${id}`, + { + method: "DELETE", + headers: { "Content-Type": "application/json" }, + }, + ); + + return department +}; diff --git a/src/app/api/companys/index.ts b/src/app/api/companys/index.ts index 3211d1c..a517f38 100644 --- a/src/app/api/companys/index.ts +++ b/src/app/api/companys/index.ts @@ -2,6 +2,7 @@ import { serverFetchJson } from "@/app/utils/fetchUtil"; import { BASE_API_URL } from "@/config/api"; import { cache } from "react"; import "server-only"; +import { CreateCompanyInputs, EditCompanyInputs } from "./actions"; export interface CompanyResult { id: number; @@ -21,4 +22,13 @@ export const fetchCompanys = cache(async () => { return serverFetchJson(`${BASE_API_URL}/companys`, { next: { tags: ["companys"] }, }); +}); + +export const fetchCompanyDetails = cache(async (companyId: string) => { + return serverFetchJson( + `${BASE_API_URL}/companys/companyDetails/${companyId}`, + { + next: { tags: [`departmentDetail${companyId}`] }, + }, + ); }); \ No newline at end of file diff --git a/src/app/utils/formatUtil.ts b/src/app/utils/formatUtil.ts index 899c1cd..4d773e9 100644 --- a/src/app/utils/formatUtil.ts +++ b/src/app/utils/formatUtil.ts @@ -19,6 +19,8 @@ export const INPUT_DATE_FORMAT = "YYYY-MM-DD"; export const OUTPUT_DATE_FORMAT = "YYYY/MM/DD"; +export const OUTPUT_TIME_FORMAT = "HH:mm:ss"; + export const convertDateToString = (date: Date, format: string = OUTPUT_DATE_FORMAT) => { return dayjs(date).format(format) } @@ -38,6 +40,23 @@ export const convertDateArrayToString = (dateArray: number[], format: string = O } } +export const convertTimeArrayToString = (timeArray: number[], format: string = OUTPUT_TIME_FORMAT, needTime: boolean = false) => { + let timeString = ''; + + if (timeArray !== null && timeArray !== undefined) { + const hour = timeArray[0] || 0; + const minute = timeArray[1] || 0; + + timeString = dayjs() + .set('hour', hour) + .set('minute', minute) + .set('second', 0) + .format('HH:mm:ss'); + } + + return timeString +} + const shortDateFormatter_en = new Intl.DateTimeFormat("en-HK", { weekday: "short", year: "numeric", diff --git a/src/components/CompanySearch/CompanySearch.tsx b/src/components/CompanySearch/CompanySearch.tsx index 27a9635..297366d 100644 --- a/src/components/CompanySearch/CompanySearch.tsx +++ b/src/components/CompanySearch/CompanySearch.tsx @@ -6,7 +6,10 @@ 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"; +import { useRouter } from "next/navigation"; +import { deleteDialog, successDialog } from "../Swal/CustomAlerts"; +import { deleteCompany } from "@/app/api/companys/actions"; +import DeleteIcon from '@mui/icons-material/Delete'; interface Props { companys: CompanyResult[]; @@ -18,6 +21,8 @@ type SearchParamNames = keyof SearchQuery; const CompanySearch: React.FC = ({ companys }) => { const { t } = useTranslation("companys"); + const router = useRouter() + const [filteredCompanys, setFilteredCompanys] = useState(companys); const searchCriteria: Criterion[] = useMemo( @@ -34,10 +39,22 @@ const CompanySearch: React.FC = ({ companys }) => { setFilteredCompanys(companys); }, [companys]); - const onProjectClick = useCallback((project: CompanyResult) => { - console.log(project); + const onProjectClick = useCallback((company: CompanyResult) => { + console.log(company); + router.push(`/settings/company/edit?id=${company.id}`); }, []); + const onDeleteClick = useCallback((company: CompanyResult) => { + + deleteDialog(async() => { + await deleteCompany(company.id) + + successDialog("Delete Success", t) + + setFilteredCompanys((prev) => prev.filter((obj) => obj.id !== company.id)) + }, t) + }, []); + const columns = useMemo[]>( () => [ { @@ -51,7 +68,14 @@ const CompanySearch: React.FC = ({ companys }) => { { name: "brNo", label: t("brNo") }, { name: "contactName", label: t("Contact Name") }, { name: "phone", label: t("Contact No.") }, - { name: "email", label: t("Contact Email") } + { name: "email", label: t("Contact Email") }, + { + name: "id", + label: t("Delete"), + onClick: onDeleteClick, + buttonIcon: , + color: "error" + }, ], [t, onProjectClick], ); diff --git a/src/components/CreateCompany/CompanyDetails.tsx b/src/components/CreateCompany/CompanyDetails.tsx index ccef906..c1599f5 100644 --- a/src/components/CreateCompany/CompanyDetails.tsx +++ b/src/components/CreateCompany/CompanyDetails.tsx @@ -19,18 +19,39 @@ import { Controller, UseFormRegister, useFormContext } from "react-hook-form"; import { CreateCompanyInputs } from "@/app/api/companys/actions"; import { TimePicker } from "@mui/x-date-pickers"; import dayjs from 'dayjs'; +import { useEffect } from "react"; +import { convertTimeArrayToString } from "@/app/utils/formatUtil"; -const CompanyDetails: React.FC = ({ +interface Props{ + content : Content; +} + +interface Content { + normalHourFrom: number[]; + normalHourTo: number[]; + otHourFrom: number[]; + otHourTo: number[]; +} + +const CompanyDetails: React.FC = ({ + content, }) => { const { t } = useTranslation(); const { register, formState: { errors }, - control, setValue, getValues, } = useFormContext(); + console.log(content) + + useEffect(() => { + setValue("normalHourFrom", convertTimeArrayToString(content.normalHourFrom, "HH:mm:ss", false)); + setValue("normalHourTo", convertTimeArrayToString(content.normalHourTo, "HH:mm:ss", false)); + setValue("otHourFrom", convertTimeArrayToString(content.otHourFrom, "HH:mm:ss", false)); + setValue("otHourTo", convertTimeArrayToString(content.otHourTo, "HH:mm:ss", false)); + }, [content]) return ( @@ -101,84 +122,80 @@ const CompanyDetails: React.FC = ({ /> - { - return ( - { - const formattedTime = time ? dayjs(time as string).format('HH:mm:ss') : ''; - field.onChange(formattedTime); - }} - sx={{ width: '100%' }} - /> - ); - }} - /> + + { + if (!time) return; + setValue("normalHourFrom", time.format("HH:mm:ss")); + }} + slotProps={{ + textField: { + helperText: 'HH:mm:ss', + }, + }} + /> + - { - return ( - { - const formattedTime = time ? dayjs(time as string).format('HH:mm:ss') : ''; - field.onChange(formattedTime); - }} - sx={{ width: '100%' }} - /> - ); - }} - /> + + { + if (!time) return; + setValue("normalHourTo", time.format("HH:mm:ss")); + }} + slotProps={{ + textField: { + helperText: 'HH:mm:ss', + }, + }} + /> + - { - return ( - { - const formattedTime = time ? dayjs(time as string).format('HH:mm:ss') : ''; - field.onChange(formattedTime); - }} - sx={{ width: '100%' }} - /> - ); - }} - /> + + { + if (!time) return; + setValue("otHourFrom", time.format("HH:mm:ss")); + }} + slotProps={{ + textField: { + helperText: 'HH:mm:ss', + }, + }} + /> + - { - return ( - { - const formattedTime = time ? dayjs(time as string).format('HH:mm:ss') : ''; - field.onChange(formattedTime); - }} - sx={{ width: '100%' }} - /> - ); - }} - /> + + { + if (!time) return; + setValue("otHourTo", time.format("HH:mm:ss")); + }} + slotProps={{ + textField: { + helperText: 'HH:mm:ss', + }, + }} + /> + = ({ + isEdit, + company, }) => { const [serverError, setServerError] = useState(""); const { t } = useTranslation(); @@ -55,23 +62,24 @@ const CreateCompany: React.FC = ({ const formProps = useForm({ defaultValues: { - companyCode: "", - companyName: "", - brNo: "", - contactName: "", - phone: "", + id: company?.id, + companyCode: company?.companyCode, + companyName: company?.name, + brNo: company?.brNo, + contactName: company?.contactName, + phone: company?.phone, otHourTo: "", otHourFrom: "", - normalHourTo: dayjs().format('HH:mm:ss'), - normalHourFrom: dayjs().format('HH:mm:ss'), - currency: "", - address: "", - district: "", - email: "", + normalHourTo: "", + normalHourFrom: "", + currency: company?.currency, + address: company?.address, + district: company?.district, + email: company?.email, }, }); - const errors = formProps.formState.errors; + const errors = formProps.formState.errors; return( @@ -82,7 +90,16 @@ const CreateCompany: React.FC = ({ > { - + } diff --git a/src/components/CreateCompany/CreateCompanyWrapper.tsx b/src/components/CreateCompany/CreateCompanyWrapper.tsx index 1becfc6..fa26f45 100644 --- a/src/components/CreateCompany/CreateCompanyWrapper.tsx +++ b/src/components/CreateCompany/CreateCompanyWrapper.tsx @@ -1,8 +1,24 @@ +import { fetchCompanyDetails } from "@/app/api/companys"; import CreateCompany from "./CreateCompany"; -const CreateCompanyWrapper: React.FC = async () => { +type CreateCompanyProps = {isEdit: false} +interface EditCompanyProps { + isEdit: true; + companyId?: string; +} + +type Props = CreateCompanyProps | EditCompanyProps; + +const CreateCompanyWrapper: React.FC = async (props) => { + + console.log(props) + + const companyDetails = props.isEdit + ? await fetchCompanyDetails(props.companyId!) + : undefined; + return ( - ) } diff --git a/src/components/InvoiceSearch/InvoiceSearch.tsx b/src/components/InvoiceSearch/InvoiceSearch.tsx index 6d2a244..dfe10a5 100644 --- a/src/components/InvoiceSearch/InvoiceSearch.tsx +++ b/src/components/InvoiceSearch/InvoiceSearch.tsx @@ -208,7 +208,7 @@ const InvoiceSearch: React.FC = ({ issuedInvoice, receivedInvoice }) => { { name: "paymentMilestone", label: t("Payment Milestone") }, { name: "invoiceDate", label: t("Invocie Date") }, { name: "dueDate", label: t("Due Date") }, - { name: "issuedAmount", label: t("Amount (HKD") }, + { name: "issuedAmount", label: t("Amount (HKD)") }, ], [t], ); @@ -316,7 +316,7 @@ const InvoiceSearch: React.FC = ({ issuedInvoice, receivedInvoice }) => { } - + { tabIndex == 0 &&