diff --git a/src/app/api/invoices/index.ts b/src/app/api/invoices/index.ts index 6036051..d20e0cf 100644 --- a/src/app/api/invoices/index.ts +++ b/src/app/api/invoices/index.ts @@ -7,7 +7,7 @@ export interface InvoiceResult { id: number; projectCode: string; projectName: string; - stage: String; + stage: string; comingPaymentMileStone: string; paymentMilestoneDate: string; resourceUsage: number; diff --git a/src/components/ClaimSearch/ClaimSearch.tsx b/src/components/ClaimSearch/ClaimSearch.tsx index e8fab2d..cafdec5 100644 --- a/src/components/ClaimSearch/ClaimSearch.tsx +++ b/src/components/ClaimSearch/ClaimSearch.tsx @@ -26,7 +26,7 @@ const ClaimSearch: React.FC = ({ claims }) => { const searchCriteria: Criterion[] = useMemo( () => [ { label: t("Creation Date From"), label2: t("Creation Date To"), paramName: "created", type: "dateRange" }, - { label: t("Related Project Name"), paramName: "name", type: "text" }, + // { label: t("Related Project Name"), paramName: "name", type: "text" }, { label: t("Expense Type"), paramName: "type", @@ -57,7 +57,7 @@ const ClaimSearch: React.FC = ({ claims }) => { // }, { name: "created", label: t("Creation Date"), type: "date" }, { name: "code", label: t("Claim Code") }, - { name: "project", label: t("Related Project Name") }, + // { name: "project", label: t("Related Project Name") }, { name: "amount", label: t("Amount (HKD)") }, { name: "type", label: t("Expense Type"), needTranslation: true }, { name: "status", label: t("Status"), needTranslation: true }, diff --git a/src/components/CreateInvoice/CreateInvoice.tsx b/src/components/CreateInvoice/CreateInvoice.tsx index f42dd74..e85d249 100644 --- a/src/components/CreateInvoice/CreateInvoice.tsx +++ b/src/components/CreateInvoice/CreateInvoice.tsx @@ -6,7 +6,7 @@ import Stack from "@mui/material/Stack"; import Print from '@mui/icons-material/Print'; // import { CreateInvoiceInputs, saveInvoice } from "@/app/api/companys/actions"; import { useRouter } from "next/navigation"; -import React, { useCallback, useState, useLayoutEffect } from "react"; +import React, { useCallback, useState, useLayoutEffect, useEffect } from "react"; import { useTranslation } from "react-i18next"; import { FieldErrors, @@ -23,6 +23,7 @@ import ProjectDetails from "./ProjectDetails"; import ProjectTotalFee from "./ProjectTotalFee"; import { timestampToDateString } from "@/app/utils/formatUtil"; import dayjs from "dayjs"; +import { getSession } from "next-auth/react" const CreateInvoice: React.FC = ({ }) => { @@ -34,7 +35,7 @@ const CreateInvoice: React.FC = ({ const [invoiceDetail, setInvoiceDetail] = useState() const [serverError, setServerError] = useState(""); - // const { getValues } = useForm(); + const [accessToken, setAccessToken] = useState(''); const fetchProjectDetails = async () =>{ const projectId = searchParams.get("id") @@ -78,13 +79,84 @@ const CreateInvoice: React.FC = ({ fetchInvoiceDetails() }, []) + // useEffect(() => { + // const fetchData = async () => { + // try { + // const session = await getSession(); + + // if (session?.accessToken) { + // const accessToken = session.accessToken; + // // Use the access token as needed + // setAccessToken(accessToken) + // console.log(accessToken); + // } else { + // throw new Error('Access token not found in the session.'); + // } + // } catch (error) { + // console.error(error); + // } + // }; + + // fetchData(); + // }, []); + + const handleCancel = () => { router.back(); }; - const handlePrintout = () => { - // const formData = getValues(); - console.log("Printing in Progress") + + const handlePrintout = async () => { + const formData = formProps.getValues() + const projectId = searchParams.get("id") + // console.log(formData, projectId) + const tempData = { + ...formData, + id: projectId + } + try { + // Make an API request to generate the JasperReport + + const response = await fetch(`http://localhost:8090/api/invoices/pdf`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${accessToken}` + }, + + body: JSON.stringify(tempData), + }); + + // Check if the request was successful + if (response.ok) { + // Extract the filename from the response headers + const contentDisposition = response.headers.get('content-disposition'); + console.log(contentDisposition) + const fileName = contentDisposition + ? contentDisposition.split('filename=')[1] + : 'invoice.pdf'; + + // Convert the response data to a Blob object + const blob = await response.blob(); + + // Create a temporary URL for the Blob object + const url = URL.createObjectURL(blob); + + // Create a link element to trigger the file download + const link = document.createElement('a'); + link.href = url; + link.download = fileName; + link.click(); + + // Clean up the temporary URL + URL.revokeObjectURL(url); + } else { + throw new Error('Failed to generate the JasperReport.'); + } + } catch (error) { + console.error(error); + // Handle any errors that occurred during the process + } } const onSubmit = useCallback>( diff --git a/src/components/InvoiceSearch/InvoiceSearchWrapper.tsx b/src/components/InvoiceSearch/InvoiceSearchWrapper.tsx index 420736f..ba05baf 100644 --- a/src/components/InvoiceSearch/InvoiceSearchWrapper.tsx +++ b/src/components/InvoiceSearch/InvoiceSearchWrapper.tsx @@ -3,6 +3,8 @@ import React from "react"; import InvoiceSearch from "./InvoiceSearch"; import InvoiceSearchLoading from "./InvoiceSearchLoading"; import { fetchInvoices } from "@/app/api/invoices"; +import { timestampToDateString } from "@/app/utils/formatUtil"; + interface SubComponents { Loading: typeof InvoiceSearchLoading; @@ -11,7 +13,12 @@ interface SubComponents { const InvoiceSearchWrapper: React.FC & SubComponents = async () => { const Invoices = await fetchInvoices(); - return ; + const temp = Invoices.map((invoice) => ({ + ...invoice, + paymentMilestoneDate: timestampToDateString(invoice.paymentMilestoneDate) + })) + + return ; }; InvoiceSearchWrapper.Loading = InvoiceSearchLoading;