|
@@ -1,7 +1,7 @@ |
|
|
import React, { useCallback, useMemo, useState, useEffect, SyntheticEvent } from "react"; |
|
|
import React, { useCallback, useMemo, useState, useEffect, SyntheticEvent } from "react"; |
|
|
import { useTranslation } from "react-i18next"; |
|
|
import { useTranslation } from "react-i18next"; |
|
|
import { Button, TextField, CardContent, Typography, Divider, Card, Box, Autocomplete, MenuItem, AutocompleteChangeReason, AutocompleteChangeDetails } from "@mui/material"; |
|
|
import { Button, TextField, CardContent, Typography, Divider, Card, Box, Autocomplete, MenuItem, AutocompleteChangeReason, AutocompleteChangeDetails } from "@mui/material"; |
|
|
import { Add, } from "@mui/icons-material"; |
|
|
|
|
|
|
|
|
import { Add, Check, Close, Delete} from "@mui/icons-material"; |
|
|
import { invoiceList } from "@/app/api/invoices"; |
|
|
import { invoiceList } from "@/app/api/invoices"; |
|
|
import { |
|
|
import { |
|
|
GridCellParams, |
|
|
GridCellParams, |
|
@@ -13,7 +13,9 @@ import { |
|
|
GridRowModesModel, |
|
|
GridRowModesModel, |
|
|
GridRenderEditCellParams, |
|
|
GridRenderEditCellParams, |
|
|
GridRenderCellParams, |
|
|
GridRenderCellParams, |
|
|
useGridApiContext, |
|
|
|
|
|
|
|
|
useGridApiContext, |
|
|
|
|
|
GridActionsCellItem, |
|
|
|
|
|
GridRowIdGetter, |
|
|
} from "@mui/x-data-grid"; |
|
|
} from "@mui/x-data-grid"; |
|
|
import { useGridApiRef } from "@mui/x-data-grid"; |
|
|
import { useGridApiRef } from "@mui/x-data-grid"; |
|
|
import StyledDataGrid from "../StyledDataGrid"; |
|
|
import StyledDataGrid from "../StyledDataGrid"; |
|
@@ -70,6 +72,10 @@ const InvoiceTable: React.FC<Props> = ({ projects, invoices }) => { |
|
|
const { getValues, setValue, clearErrors, setError } = useFormContext<any>(); |
|
|
const { getValues, setValue, clearErrors, setError } = useFormContext<any>(); |
|
|
const apiRef = useGridApiRef(); |
|
|
const apiRef = useGridApiRef(); |
|
|
// const [projectCode, setProjectCode] = useState<project>({label: "", value: 0}) |
|
|
// const [projectCode, setProjectCode] = useState<project>({label: "", value: 0}) |
|
|
|
|
|
const getRowId = useCallback<GridRowIdGetter<invoiceListRow>>( |
|
|
|
|
|
(row) => row.id != undefined ? row.id : 0, |
|
|
|
|
|
[], |
|
|
|
|
|
); |
|
|
const validateInvoiceEntry = ( |
|
|
const validateInvoiceEntry = ( |
|
|
entry: Partial<invoiceList>, |
|
|
entry: Partial<invoiceList>, |
|
|
): InvoiceListError | undefined => { |
|
|
): InvoiceListError | undefined => { |
|
@@ -159,13 +165,40 @@ const InvoiceTable: React.FC<Props> = ({ projects, invoices }) => { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const addRow = useCallback(() => { |
|
|
const addRow = useCallback(() => { |
|
|
const id = Date.now(); |
|
|
|
|
|
setSelectedRow((e) => [...e, { id, _isNew: true }]); |
|
|
|
|
|
|
|
|
const newEntry = { id: Date.now(), _isNew: true }; |
|
|
|
|
|
setSelectedRow((e) => [...e, newEntry]); |
|
|
setRowModesModel((model) => ({ |
|
|
setRowModesModel((model) => ({ |
|
|
...model, |
|
|
...model, |
|
|
[id]: { mode: GridRowModes.Edit }, |
|
|
|
|
|
|
|
|
[getRowId(newEntry)]: { mode: GridRowModes.Edit }, |
|
|
})); |
|
|
})); |
|
|
}, []); |
|
|
|
|
|
|
|
|
}, [getRowId]); |
|
|
|
|
|
|
|
|
|
|
|
const handleSave = useCallback( |
|
|
|
|
|
(id: GridRowId) => () => { |
|
|
|
|
|
setRowModesModel((model) => ({ |
|
|
|
|
|
...model, |
|
|
|
|
|
[id]: { mode: GridRowModes.View }, |
|
|
|
|
|
})); |
|
|
|
|
|
}, |
|
|
|
|
|
[], |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
const handleCancel = useCallback( |
|
|
|
|
|
(id: GridRowId) => () => { |
|
|
|
|
|
setRowModesModel((model) => ({ |
|
|
|
|
|
...model, |
|
|
|
|
|
[id]: { mode: GridRowModes.View, ignoreModifications: true }, |
|
|
|
|
|
})); |
|
|
|
|
|
}, |
|
|
|
|
|
[], |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
const handleDelete = useCallback( |
|
|
|
|
|
(id: GridRowId) => () => { |
|
|
|
|
|
setSelectedRow((row => row.filter(r => getRowId(r) !== id))) |
|
|
|
|
|
}, |
|
|
|
|
|
[getRowId], |
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
const processRowUpdate = useCallback( |
|
|
const processRowUpdate = useCallback( |
|
|
( |
|
|
( |
|
@@ -235,19 +268,10 @@ const InvoiceTable: React.FC<Props> = ({ projects, invoices }) => { |
|
|
</Box> |
|
|
</Box> |
|
|
) |
|
|
) |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
function AutocompleteInput(props: GridRenderCellParams<any, number>) { |
|
|
function AutocompleteInput(props: GridRenderCellParams<any, number>) { |
|
|
const { id, value, field, hasFocus } = props; |
|
|
const { id, value, field, hasFocus } = props; |
|
|
const apiRef = useGridApiContext(); |
|
|
const apiRef = useGridApiContext(); |
|
|
const ref = React.useRef<HTMLElement>(null); |
|
|
|
|
|
|
|
|
|
|
|
// useEnhancedEffect(() => { |
|
|
|
|
|
// if (hasFocus && ref.current) { |
|
|
|
|
|
// const input = ref.current.querySelector<HTMLInputElement>( |
|
|
|
|
|
// `input[value="${value}"]`, |
|
|
|
|
|
// ); |
|
|
|
|
|
// input?.focus(); |
|
|
|
|
|
// } |
|
|
|
|
|
// }, [hasFocus, value]); |
|
|
|
|
|
|
|
|
|
|
|
const handleValueChange = useCallback((newValue: any) => { |
|
|
const handleValueChange = useCallback((newValue: any) => { |
|
|
console.log(newValue) |
|
|
console.log(newValue) |
|
@@ -304,12 +328,46 @@ const editCombinedColumns = useMemo<GridColDef[]>( |
|
|
flex: 1, |
|
|
flex: 1, |
|
|
type: 'date', |
|
|
type: 'date', |
|
|
}, |
|
|
}, |
|
|
{ field: "receivedAmount", |
|
|
|
|
|
|
|
|
{ |
|
|
|
|
|
field: "receivedAmount", |
|
|
headerName: t("Actual Received Amount (HKD)"), |
|
|
headerName: t("Actual Received Amount (HKD)"), |
|
|
editable: true, |
|
|
editable: true, |
|
|
flex: 1, |
|
|
flex: 1, |
|
|
type: 'number' |
|
|
type: 'number' |
|
|
}, |
|
|
}, |
|
|
|
|
|
{ |
|
|
|
|
|
type: "actions", |
|
|
|
|
|
field: "actions", |
|
|
|
|
|
headerName: t("Actions"), |
|
|
|
|
|
getActions: ({ id }) => { |
|
|
|
|
|
console.log(rowModesModel[id]?.mode === GridRowModes.Edit) |
|
|
|
|
|
if (rowModesModel[id]?.mode === GridRowModes.Edit) { |
|
|
|
|
|
return [ |
|
|
|
|
|
<GridActionsCellItem |
|
|
|
|
|
key="accpet-action" |
|
|
|
|
|
icon={<Check />} |
|
|
|
|
|
label={t("Save")} |
|
|
|
|
|
onClick={handleSave(id)} |
|
|
|
|
|
/>, |
|
|
|
|
|
<GridActionsCellItem |
|
|
|
|
|
key="cancel-action" |
|
|
|
|
|
icon={<Close />} |
|
|
|
|
|
label={t("Cancel")} |
|
|
|
|
|
onClick={handleCancel(id)} |
|
|
|
|
|
/>, |
|
|
|
|
|
]; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return [ |
|
|
|
|
|
<GridActionsCellItem |
|
|
|
|
|
key="delete-action" |
|
|
|
|
|
icon={<Delete />} |
|
|
|
|
|
label={t("Remove")} |
|
|
|
|
|
onClick={handleDelete(id)} |
|
|
|
|
|
/>, |
|
|
|
|
|
]; |
|
|
|
|
|
}, |
|
|
|
|
|
}, |
|
|
], |
|
|
], |
|
|
[t] |
|
|
[t] |
|
|
) |
|
|
) |
|
|