@@ -1,11 +1,11 @@ | |||
import { preloadExpense } from "@/app/api/expenses" | |||
import { preloadProjectExpenses } from "@/app/api/projectExpenses" | |||
import ExpenseSearch from "@/components/ExpenseSearch" | |||
import { getServerI18n, I18nProvider } from "@/i18n" | |||
import { Stack, Typography } from "@mui/material" | |||
import { Suspense } from "react" | |||
const Expense: React.FC = async () => { | |||
preloadExpense() | |||
preloadProjectExpenses() | |||
const { t } = await getServerI18n("expense") | |||
return( | |||
@@ -1,28 +0,0 @@ | |||
"use server"; | |||
import { cache } from "react"; | |||
import { serverFetchJson } from "@/app/utils/fetchUtil"; | |||
import { BASE_API_URL } from "@/config/api"; | |||
export type ExpensesResult = { | |||
id: number | |||
projectCode: string | |||
projectName: string | |||
staffCode: string | |||
staffName: string | |||
description: string | |||
amount: number | |||
approvedAmount: number | |||
verifiedDatetime: number[] | |||
remark: string | |||
} | |||
export const preloadExpense = () => { | |||
fetchExpenses() | |||
}; | |||
export const fetchExpenses = cache(async () => { | |||
return serverFetchJson<ExpensesResult[]>(`${BASE_API_URL}/expense`, { | |||
next: { tags: ["expense"] }, | |||
}); | |||
}); |
@@ -0,0 +1,25 @@ | |||
"use server" | |||
import { serverFetchJson, serverFetchWithNoContent } from "@/app/utils/fetchUtil"; | |||
import { BASE_API_URL } from "@/config/api"; | |||
import { cache } from "react"; | |||
import { revalidateTag } from "next/cache"; | |||
export type CreateNewExpense = { | |||
expenseNo: string | undefined, | |||
projectCode: string | undefined, | |||
issueDate: Date | |||
issuedAmount: number, | |||
receiptDate: Date | |||
receivedAmount: number | |||
} | |||
export type PostExpenseData = { | |||
expenseNo?: string | |||
projectId: number | |||
projectCode: string, | |||
amount: number | |||
issueDate: string | |||
receiptDate?: string | |||
} |
@@ -0,0 +1,31 @@ | |||
"use server"; | |||
import { cache } from "react"; | |||
import { serverFetchJson } from "@/app/utils/fetchUtil"; | |||
import { BASE_API_URL } from "@/config/api"; | |||
export type ProjectExpensesResult = { | |||
id: number | |||
expenseNo?: string | |||
projectCode: string | |||
projectName: string | |||
teamCode: string | |||
teamName: string | |||
amount: number | |||
issueDate: number[] | |||
receiptDate: number[] | |||
} | |||
export type ProjectExpensesResultFormatted = Omit<ProjectExpensesResult, 'issueDate' | 'receiptDate'> & { | |||
issueDate: string; | |||
receiptDate: string; | |||
}; | |||
export const preloadProjectExpenses = () => { | |||
fetchProjectExpenses() | |||
}; | |||
export const fetchProjectExpenses = cache(async () => { | |||
return serverFetchJson<ProjectExpensesResult[]>(`${BASE_API_URL}/project-expense`, { | |||
next: { tags: ["projectExpenses"] }, | |||
}); | |||
}); |
@@ -12,8 +12,11 @@ import { | |||
import { useTranslation } from 'react-i18next'; | |||
import { FormProvider, SubmitHandler, useForm } from 'react-hook-form'; | |||
import { Check, Close } from "@mui/icons-material"; | |||
import InvoiceTable from './ExpenseTable'; | |||
import { ProjectResult } from '@/app/api/projects'; | |||
import { CreateNewExpense, PostExpenseData } from '@/app/api/projectExpenses/actions'; | |||
import ExpenseTable from './ExpenseTable'; | |||
import dayjs from 'dayjs'; | |||
import { INPUT_DATE_FORMAT } from '@/app/utils/formatUtil'; | |||
interface Props { | |||
isOpen: boolean, | |||
@@ -32,13 +35,30 @@ const modalSx: SxProps= { | |||
bgcolor: 'background.paper', | |||
}; | |||
const CreateInvoiceModal: React.FC<Props> = ({isOpen, onClose, projects}) => { | |||
type postData = { | |||
data: PostExpenseData[] | |||
} | |||
const CreateExpenseModal: React.FC<Props> = ({isOpen, onClose, projects}) => { | |||
const { t } = useTranslation() | |||
const formProps = useForm<any>(); | |||
const formProps = useForm<postData>(); | |||
const onSubmit = useCallback<SubmitHandler<any>>( | |||
const onSubmit = useCallback<SubmitHandler<postData>>( | |||
(data) => { | |||
console.log(data) | |||
const _data = data.data | |||
console.log(_data[0]) | |||
console.log(_data[0].issueDate) | |||
console.log(_data[1].issueDate) | |||
const postData: PostExpenseData[] = _data.map(item => { | |||
console.log(item.issueDate) | |||
return ({ | |||
expenseNo: item.expenseNo, | |||
issueDate: dayjs(item.issueDate).format(INPUT_DATE_FORMAT), | |||
amount: item.amount, | |||
projectId: projects.find(p => p.code === item.projectCode)!.id, | |||
projectCode: item.projectCode, | |||
})} | |||
) | |||
console.log(postData) | |||
} | |||
, []) | |||
@@ -63,7 +83,7 @@ const CreateInvoiceModal: React.FC<Props> = ({isOpen, onClose, projects}) => { | |||
marginBlock: 2, | |||
}} | |||
> | |||
<InvoiceTable projects={projects}/> | |||
<ExpenseTable projects={projects}/> | |||
</Box> | |||
<CardActions sx={{ justifyContent: "flex-end" }}> | |||
<Button | |||
@@ -84,4 +104,4 @@ const CreateInvoiceModal: React.FC<Props> = ({isOpen, onClose, projects}) => { | |||
); | |||
}; | |||
export default CreateInvoiceModal; | |||
export default CreateExpenseModal; |
@@ -1,6 +1,6 @@ | |||
"use client"; | |||
import { ExpensesResult } from "@/app/api/expenses"; | |||
import { useCallback, useMemo, useState } from "react"; | |||
import { ProjectExpensesResult, ProjectExpensesResultFormatted } from "@/app/api/projectExpenses"; | |||
import { useCallback, useEffect, useMemo, useState } from "react"; | |||
import { useTranslation } from "react-i18next"; | |||
import SearchBox, { Criterion } from "../SearchBox"; | |||
import SearchResults, { Column } from "../SearchResults"; | |||
@@ -18,41 +18,55 @@ import { | |||
import { moneyFormatter } from "@/app/utils/formatUtil"; | |||
import { EditNote } from "@mui/icons-material"; | |||
import AddIcon from '@mui/icons-material/Add'; | |||
import { uniq } from "lodash"; | |||
import CreateExpenseModal from "./CreateExpenseModal"; | |||
import { ProjectResult } from "@/app/api/projects"; | |||
interface Props { | |||
expenses: ExpensesResult[] | |||
expenses: ProjectExpensesResultFormatted[] | |||
projects: ProjectResult[]; | |||
} | |||
type SearchQuery = Partial<Omit<ExpensesResult, "id">>; | |||
type SearchQuery = Partial<Omit<ProjectExpensesResultFormatted, "id">>; | |||
type SearchParamNames = keyof SearchQuery; | |||
const ExpenseSearch: React.FC<Props> = ({ expenses }) => { | |||
console.log(expenses) | |||
type Modals = { | |||
createInvoiceModal: boolean | |||
} | |||
const initState: Modals = { | |||
createInvoiceModal: false, | |||
} | |||
const ExpenseSearch: React.FC<Props> = ({ expenses, projects }) => { | |||
const router = useRouter(); | |||
const { t } = useTranslation("expenses"); | |||
const [filteredExpenses, setFilteredExpenses] = useState(expenses); | |||
const [modalsOpen, setModalsOpen] = useState(initState) | |||
const toggleModals = useCallback((key: keyof Modals) => { | |||
setModalsOpen((prev) => ({...prev, [key]: !prev[key]})) | |||
}, [modalsOpen]); | |||
const searchCriteria: Criterion<SearchParamNames>[] = useMemo( | |||
() => [ | |||
// { label: t("Expense No"), paramName: "ExpenseNo", type: "text" }, | |||
{ label: t("Project Code"), paramName: "projectCode", type: "text" }, | |||
{ label: t("Project Name"), paramName: "projectName", type: "text" }, | |||
{ | |||
label: t("Verified Date"), | |||
label2: t("Verified Date To"), | |||
paramName: "verifiedDatetime", | |||
type: "dateRange", | |||
}, | |||
// { | |||
// label: t("Team"), | |||
// paramName: "team", | |||
// type: "select", | |||
// options: uniq(expenses.map((expenses) => expenses.teamCode)), | |||
// }, | |||
], | |||
[] | |||
); | |||
const onExpenseClick = useCallback( | |||
(expenses?: ExpensesResult) => {}, | |||
(expenses?: ProjectExpensesResultFormatted) => {}, | |||
[router] | |||
); | |||
const columns = useMemo<Column<ExpensesResult>[]>( | |||
const columns = useMemo<Column<ProjectExpensesResultFormatted>[]>( | |||
() => [ | |||
{ | |||
name: "id", | |||
@@ -63,7 +77,9 @@ const ExpenseSearch: React.FC<Props> = ({ expenses }) => { | |||
}, | |||
{ name: "projectCode", label: t("Project Code") }, | |||
{ name: "projectName", label: t("Project Name") }, | |||
{ name: "verifiedDatetime", label: t("verifiedDatetime") }, | |||
{ name: "amount", label: t("Amount") }, | |||
{ name: "teamCode", label: t("Team") }, | |||
{ name: "issueDate", label: t("Issue Date") }, | |||
], | |||
[t, onExpenseClick] | |||
); | |||
@@ -72,6 +88,7 @@ const ExpenseSearch: React.FC<Props> = ({ expenses }) => { | |||
}, []); | |||
return ( | |||
<> | |||
<Stack | |||
spacing={2} | |||
> | |||
@@ -87,7 +104,7 @@ const ExpenseSearch: React.FC<Props> = ({ expenses }) => { | |||
startIcon={<AddIcon />} | |||
variant="outlined" | |||
component="label" | |||
onClick={() => console.log()} | |||
onClick={() => toggleModals("createInvoiceModal")} | |||
> | |||
{t("Create expense")} | |||
</Button> | |||
@@ -134,11 +151,17 @@ const ExpenseSearch: React.FC<Props> = ({ expenses }) => { | |||
</CardContent> | |||
</Card> | |||
<Divider sx={{ paddingBlockEnd: 2 }} /> | |||
<SearchResults<ExpensesResult> | |||
<SearchResults<ProjectExpensesResultFormatted> | |||
items={filteredExpenses} | |||
columns={columns} | |||
/> | |||
</Stack> | |||
<CreateExpenseModal | |||
isOpen={modalsOpen.createInvoiceModal} | |||
onClose={() => toggleModals("createInvoiceModal")} | |||
projects={projects} | |||
/> | |||
</> | |||
); | |||
}; | |||
export default ExpenseSearch; |
@@ -1,10 +1,12 @@ | |||
import React from "react"; | |||
import ExpenseSearch from "./ExpenseSearch"; | |||
import ExpenseSearchLoading from "./ExpenseSearchLoading"; | |||
import { fetchExpenses } from "@/app/api/expenses"; | |||
import { fetchProjectExpenses } from "@/app/api/projectExpenses"; | |||
import dayjs from "dayjs"; | |||
import arraySupport from "dayjs/plugin/arraySupport"; | |||
import { OUTPUT_DATE_FORMAT, OUTPUT_TIME_FORMAT } from "@/app/utils/formatUtil"; | |||
import { fetchUserStaff } from "@/app/utils/fetchUtil"; | |||
import { fetchProjects } from "@/app/api/projects"; | |||
interface SubComponents { | |||
@@ -14,20 +16,31 @@ dayjs.extend(arraySupport) | |||
const ExpenseSearchWrapper: React.FC & SubComponents = async () => { | |||
const [ | |||
Expenses | |||
expenses, | |||
projects | |||
] = await Promise.all([ | |||
fetchExpenses(), | |||
fetchProjectExpenses(), | |||
fetchProjects(), | |||
]); | |||
const _expenses = Expenses.map((e) => { | |||
const date: number[] = e.verifiedDatetime as number[]; | |||
const formattedDate = dayjs([date[0], date[1], date[2]].join()).format(OUTPUT_DATE_FORMAT) | |||
// const userStaff = await fetchUserStaff() | |||
// const teamId = userStaff?.teamId | |||
// const _projects = projects | |||
console.log(expenses) | |||
const _expenses = expenses.map((e) => { | |||
const issueDate = e.issueDate; | |||
const receiptDate = e.receiptDate; | |||
const formattedIssueDate = dayjs([issueDate[0], issueDate[1], issueDate[2]].join()).format(OUTPUT_DATE_FORMAT) | |||
const formattedReceiptDate = dayjs([receiptDate[0], receiptDate[1], receiptDate[2]].join()).format(OUTPUT_DATE_FORMAT) | |||
return ({ | |||
...e, | |||
verifiedDatetime: formattedDate | |||
issueDate: formattedIssueDate, | |||
receiptDate: formattedReceiptDate | |||
}) | |||
}) | |||
return <ExpenseSearch | |||
expenses={_expenses} | |||
projects={projects} | |||
/> | |||
}; | |||
@@ -7,8 +7,6 @@ import { moneyFormatter } from "@/app/utils/formatUtil" | |||
import { Button, ButtonGroup, Stack, Tab, Tabs, TabsProps, Dialog, DialogTitle, DialogContent, DialogContentText, DialogActions, TextField, CardContent, Typography, Divider, Card, Box, Autocomplete, MenuItem } from "@mui/material"; | |||
import FileUploadIcon from '@mui/icons-material/FileUpload'; | |||
import { Add, Check, Close, Delete } from "@mui/icons-material"; | |||
import { deleteInvoice, importIssuedInovice, importReceivedInovice, updateInvoice } from "@/app/api/invoices/actions"; | |||
import { deleteDialog, errorDialogWithContent, successDialog } from "../Swal/CustomAlerts"; | |||
import { invoiceList, issuedInvoiceList, issuedInvoiceSearchForm, receivedInvoiceList, receivedInvoiceSearchForm } from "@/app/api/invoices"; | |||
import EditOutlinedIcon from '@mui/icons-material/EditOutlined'; | |||
import { | |||
@@ -19,7 +17,8 @@ import { | |||
GridRowModel, | |||
GridRowModes, | |||
GridRowModesModel, | |||
GridRenderEditCellParams, | |||
GridRenderEditCellParams, | |||
useGridApiContext, | |||
} from "@mui/x-data-grid"; | |||
import { useGridApiRef } from "@mui/x-data-grid"; | |||
import StyledDataGrid from "../StyledDataGrid"; | |||
@@ -32,15 +31,17 @@ import { th } from "@faker-js/faker"; | |||
import { GridRowIdGetter } from "@mui/x-data-grid"; | |||
import { useFormContext } from "react-hook-form"; | |||
import { ProjectResult } from "@/app/api/projects"; | |||
import { ProjectExpensesResultFormatted } from "@/app/api/projectExpenses"; | |||
import { GridRenderCellParams } from "@mui/x-data-grid"; | |||
type InvoiceListError = { | |||
[field in keyof invoiceList]?: string; | |||
type ExpenseListError = { | |||
[field in keyof ProjectExpensesResultFormatted]?: string; | |||
}; | |||
type invoiceListRow = Partial< | |||
invoiceList & { | |||
type ExpenseListRow = Partial< | |||
ProjectExpensesResultFormatted & { | |||
_isNew: boolean; | |||
_error: InvoiceListError; | |||
_error: ExpenseListError; | |||
} | |||
>; | |||
@@ -49,12 +50,12 @@ interface Props { | |||
} | |||
class ProcessRowUpdateError extends Error { | |||
public readonly row: invoiceListRow; | |||
public readonly errors: InvoiceListError | undefined; | |||
public readonly row: ExpenseListRow; | |||
public readonly errors: ExpenseListError | undefined; | |||
constructor( | |||
row: invoiceListRow, | |||
row: ExpenseListRow, | |||
message?: string, | |||
errors?: InvoiceListError, | |||
errors?: ExpenseListError, | |||
) { | |||
super(message); | |||
this.row = row; | |||
@@ -67,34 +68,25 @@ type project = { | |||
label: string; | |||
value: number; | |||
} | |||
const InvoiceTable: React.FC<Props> = ({ projects }) => { | |||
const ExpenseTable: React.FC<Props> = ({ projects }) => { | |||
console.log(projects) | |||
const projectCombos = projects.map(item => item.code) | |||
const { t } = useTranslation() | |||
const [rowModesModel, setRowModesModel] = useState<GridRowModesModel>({}); | |||
const [selectedRow, setSelectedRow] = useState<invoiceListRow[] | []>([]); | |||
const [selectedRow, setSelectedRow] = useState<ExpenseListRow[] | []>([]); | |||
const { getValues, setValue, clearErrors, setError } = | |||
useFormContext<any>(); | |||
const apiRef = useGridApiRef(); | |||
const [projectCode, setProjectCode] = useState<project>({label: "", value: 0}) | |||
const validateInvoiceEntry = ( | |||
entry: Partial<invoiceList>, | |||
): InvoiceListError | undefined => { | |||
const validateExpenseEntry = ( | |||
entry: Partial<ProjectExpensesResultFormatted>, | |||
): ExpenseListError | undefined => { | |||
// Test for errors | |||
const error: any = {}; | |||
console.log(entry) | |||
if (!entry.issuedAmount) { | |||
error.issuedAmount = "Please input issued amount "; | |||
} else if (!entry.issuedAmount) { | |||
error.receivedAmount = "Please input received amount"; | |||
} else if (entry.invoiceNo === "") { | |||
error.invoiceNo = "Please input invoice number"; | |||
} else if (!entry.issuedDate) { | |||
error.issuedDate = "Please input issue date"; | |||
} else if (!entry.receiptDate){ | |||
} | |||
const error: ExpenseListError = {}; | |||
if (!entry.issueDate) error.issueDate = "Please input issued date"; | |||
if (!entry.amount) error.amount = "Please input amount"; | |||
if (!entry.projectCode) error.projectCode = "Please input project code"; | |||
console.log(error) | |||
return Object.keys(error).length > 0 ? error : undefined; | |||
} | |||
@@ -105,8 +97,8 @@ const InvoiceTable: React.FC<Props> = ({ projects }) => { | |||
"", | |||
) | |||
const error = validateInvoiceEntry(row); | |||
// console.log(error) | |||
const error = validateExpenseEntry(row); | |||
console.log(error) | |||
// Test for warnings | |||
// apiRef.current.updateRows([{ id, _error: error }]); | |||
@@ -159,8 +151,8 @@ const InvoiceTable: React.FC<Props> = ({ projects }) => { | |||
const processRowUpdate = useCallback( | |||
( | |||
newRow: GridRowModel<invoiceListRow>, | |||
originalRow: GridRowModel<invoiceListRow>, | |||
newRow: GridRowModel<ExpenseListRow>, | |||
originalRow: GridRowModel<ExpenseListRow>, | |||
) => { | |||
const errors = validateRow(newRow.id!!); | |||
if (errors) { | |||
@@ -178,7 +170,7 @@ const InvoiceTable: React.FC<Props> = ({ projects }) => { | |||
const rowToSave = { | |||
...updatedRow, | |||
} satisfies invoiceListRow; | |||
} satisfies ExpenseListRow; | |||
console.log(newRow) | |||
@@ -198,7 +190,7 @@ const InvoiceTable: React.FC<Props> = ({ projects }) => { | |||
(updateError: ProcessRowUpdateError) => { | |||
const errors = updateError.errors; | |||
const oldRow = updateError.row; | |||
// console.log(errors) | |||
console.log(errors) | |||
apiRef.current.updateRows([{ ...oldRow, _error: errors }]); | |||
}, | |||
[apiRef] | |||
@@ -209,38 +201,64 @@ const InvoiceTable: React.FC<Props> = ({ projects }) => { | |||
setValue("data", selectedRow) | |||
}, [selectedRow, setValue]); | |||
function renderAutocomplete(params: GridRenderCellParams<any, number>) { | |||
return( | |||
<Box sx={{ display: 'flex', alignItems: 'center', pr: 2 }}> | |||
<Autocomplete | |||
readOnly | |||
sx={{ width: 300 }} | |||
value={params.row.projectCode} | |||
options={projectCombos} | |||
renderInput={(params) => <TextField {...params} />} | |||
/> | |||
</Box> | |||
) | |||
} | |||
function AutocompleteInput(props: GridRenderCellParams<any, number>) { | |||
const { id, value, field, hasFocus } = props; | |||
const apiRef = useGridApiContext(); | |||
const ref = React.useRef<HTMLElement>(null); | |||
const handleValueChange = useCallback((newValue: any) => { | |||
console.log(newValue) | |||
apiRef.current.setEditCellValue({ id, field, value: newValue }) | |||
}, []); | |||
return ( | |||
<Box sx={{ display: 'flex', alignItems: 'center', pr: 2 }}> | |||
<Autocomplete | |||
disablePortal | |||
options={projectCombos} | |||
sx={{ width: 300 }} | |||
onChange={(event: React.SyntheticEvent<Element, Event>, value: string | null, ) => handleValueChange(value)} | |||
renderInput={(params) => <TextField {...params} />} | |||
/> | |||
</Box> | |||
); | |||
} | |||
const renderAutocompleteInput: GridColDef['renderCell'] = (params) => { | |||
return <AutocompleteInput {...params} />; | |||
}; | |||
const editCombinedColumns = useMemo<GridColDef[]>( | |||
() => [ | |||
{ field: "invoiceNo", headerName: t("Invoice No"), editable: true, flex: 0.5 }, | |||
{ field: "expenseNo", headerName: t("Expense No"), editable: true, flex: 0.5 }, | |||
{ field: "projectCode", | |||
headerName: t("Project Code"), | |||
editable: true, | |||
flex: 0.3, | |||
renderEditCell(params: GridRenderEditCellParams<invoiceListRow, number>){ | |||
return( | |||
<Autocomplete | |||
disablePortal | |||
options={[]} | |||
sx={{width: '100%'}} | |||
renderInput={(params) => <TextField {...params} />} | |||
/> | |||
) | |||
} | |||
renderCell: renderAutocomplete, | |||
renderEditCell: renderAutocompleteInput | |||
}, | |||
{ field: "issuedDate", | |||
{ field: "issueDate", | |||
headerName: t("Issue Date"), | |||
editable: true, | |||
flex: 0.4, | |||
// type: 'date', | |||
// valueGetter: (params) => { | |||
// // console.log(params.row.issuedDate) | |||
// return new Date(params.row.issuedDate) | |||
// }, | |||
type: 'date', | |||
}, | |||
{ field: "issuedAmount", | |||
{ field: "amount", | |||
headerName: t("Amount (HKD)"), | |||
editable: true, | |||
flex: 0.5, | |||
@@ -251,13 +269,8 @@ const editCombinedColumns = useMemo<GridColDef[]>( | |||
headerName: t("Settle Date"), | |||
editable: true, | |||
flex: 0.4, | |||
}, | |||
{ field: "receivedAmount", | |||
headerName: t("Actual Received Amount (HKD)"), | |||
editable: true, | |||
flex: 0.5, | |||
type: 'number' | |||
}, | |||
type: 'date', | |||
}, | |||
], | |||
[t] | |||
) | |||
@@ -271,7 +284,7 @@ const footer = ( | |||
onClick={addRow} | |||
size="small" | |||
> | |||
{t("Create Invoice")} | |||
{t("Create Expense")} | |||
</Button> | |||
</Box> | |||
); | |||
@@ -301,9 +314,9 @@ const footer = ( | |||
columns={editCombinedColumns} | |||
processRowUpdate={processRowUpdate} | |||
onProcessRowUpdateError={onProcessRowUpdateError} | |||
getCellClassName={(params: GridCellParams<invoiceListRow>) => { | |||
getCellClassName={(params: GridCellParams<ExpenseListRow>) => { | |||
let classname = ""; | |||
if (params.row._error?.[params.field as keyof invoiceList]) { | |||
if (params.row._error?.[params.field as keyof ProjectExpensesResultFormatted]) { | |||
classname = "hasError"; | |||
} | |||
return classname; | |||
@@ -320,7 +333,7 @@ const footer = ( | |||
) | |||
} | |||
export default InvoiceTable | |||
export default ExpenseTable | |||
const NoRowsOverlay: React.FC = () => { | |||
const { t } = useTranslation("home"); | |||
@@ -19,18 +19,18 @@ interface SubComponents { | |||
// } | |||
const InvoiceSearchWrapper: React.FC & SubComponents = async () => { | |||
const userStaff = await fetchUserStaff() | |||
const teamId = userStaff?.teamId | |||
// const userStaff = await fetchUserStaff() | |||
// const teamId = userStaff?.teamId | |||
const invoices = await fetchInvoicesV3() | |||
const projects = await fetchProjects() | |||
const filteredProjects = projects.filter(project => project.teamId === teamId) | |||
// const filteredProjects = projects.filter(project => project.teamId === teamId) | |||
let filteredInvoice = invoices | |||
if (teamId) { | |||
filteredInvoice = invoices.filter(invoice => invoice.teamId === teamId) | |||
} | |||
// let filteredInvoice = invoices | |||
// if (teamId) { | |||
// filteredInvoice = invoices.filter(invoice => invoice.teamId === teamId) | |||
// } | |||
const convertedInvoices = filteredInvoice.map((invoice)=>{ | |||
const convertedInvoices = invoices.map((invoice)=>{ | |||
return{ | |||
id: invoice.id, | |||
invoiceNo: invoice.invoiceNo, | |||
@@ -47,7 +47,7 @@ const InvoiceSearchWrapper: React.FC & SubComponents = async () => { | |||
return <InvoiceSearch | |||
invoices={convertedInvoices} | |||
projects={filteredProjects} | |||
projects={projects} | |||
/> | |||
}; | |||