| @@ -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] | ||||
| ) | ) | ||||