Create SelectingTable, improve EditingTable functionality

This commit is contained in:
ShootingStar91
2024-05-22 14:54:18 +03:00
committed by arttu
parent 23d3816875
commit 8ded817dc4
5 changed files with 81 additions and 88 deletions
@@ -31,9 +31,14 @@ export const EditableTable = <T extends Editable<MRT_RowData>, ParentType extend
// TODO: Using static index - need to use some id, probably sorting breaks this
const rowClicked = (index: number | undefined) => {
if (index === undefined) return
const museums = [...editData[field]]
museums[index].rowState = getNewState(state)
setEditData({ ...editData, museums })
const items = [...editData[field]]
if (items[index].rowState === 'new') {
items.splice(index, 1)
setEditData({ ...editData, [field]: items })
return
}
items[index].rowState = getNewState(state)
setEditData({ ...editData, items })
}
const getIcon = () => {
@@ -0,0 +1,49 @@
import { MRT_ColumnDef, MRT_RowData } from 'material-react-table'
import { EditingModal } from './FormComponents'
import { TableView } from '@/components/TableView/TableView'
import { useDetailContext } from '../hooks'
import { useMemo } from 'react'
export const SelectingTable = <T extends MRT_RowData, ParentType>({
buttonText,
data,
columns,
editingAction,
fieldName,
idFieldName,
}: {
buttonText: string
data: T[]
columns: MRT_ColumnDef<T>[]
editingAction?: (object: T) => void
fieldName: keyof ParentType
idFieldName: keyof T
}) => {
const { editData, setEditData } = useDetailContext<ParentType>()
const selectedItems = editData[fieldName] as T[]
const defaultEditingAction = (newObject: T) => {
if (selectedItems.find(item => item[idFieldName] === newObject[idFieldName])) return
setEditData({ ...editData, [fieldName]: [...selectedItems, { ...newObject, rowState: 'new' }] })
}
const idSet = useMemo(() => {
return new Set(selectedItems.map(item => item[idFieldName] as T))
}, [selectedItems, idFieldName])
const filteredMuseums = useMemo(() => {
return data.filter(row => !idSet.has(row[idFieldName]))
}, [data, idSet, idFieldName])
return (
<EditingModal buttonText={buttonText}>
<TableView<T>
data={filteredMuseums}
columns={columns}
selectorFn={editingAction ?? defaultEditingAction}
idFieldName={idFieldName}
/>
</EditingModal>
)
}
@@ -1,63 +1,19 @@
import { Editable, LocalityDetails, Museum } from '@/backendTypes'
import { EditableTable } from '@/components/DetailView/common/EditableTable'
import { EditingForm } from '@/components/DetailView/common/EditingForm'
import { EditingModal, Grouped } from '@/components/DetailView/common/FormComponents'
import { Grouped } from '@/components/DetailView/common/FormComponents'
import { SelectingTable } from '@/components/DetailView/common/SelectingTable'
import { useDetailContext } from '@/components/DetailView/hooks'
import { TableView } from '@/components/TableView/TableView'
import { useGetAllMuseumsQuery } from '@/redux/museumReducer'
import { Box, CircularProgress } from '@mui/material'
import { MRT_ColumnDef } from 'material-react-table'
import { useState } from 'react'
const MuseumSelectingTable = () => {
const { data, isError } = useGetAllMuseumsQuery()
const [selected, setSelected] = useState<string[]>([])
if (isError) return 'Error loading museums.'
if (!data) return <CircularProgress />
const selectId = (id: string) => {
const index = selected.indexOf(id)
if (index < 0) {
setSelected([...selected, id])
} else {
const newSelected = [...selected]
newSelected.splice(index, 1)
setSelected(newSelected)
}
}
const columns: MRT_ColumnDef<Museum>[] = [
{
accessorKey: 'museum',
header: 'Code',
},
{
accessorKey: 'institution',
header: 'Museum',
},
{
accessorKey: 'city',
header: 'City',
},
{
accessorKey: 'country',
header: 'Country',
},
]
return (
<TableView<Museum>
data={data}
columns={columns}
selectorFn={selectId}
selectedList={selected}
idFieldName="museum"
/>
)
}
export const MuseumTab = () => {
const { editData, mode } = useDetailContext<LocalityDetails>()
const { data: museumData, isError } = useGetAllMuseumsQuery()
if (isError) return 'Error loading museums.'
if (!museumData) return <CircularProgress />
const columns: MRT_ColumnDef<Museum>[] = [
{
@@ -78,12 +34,6 @@ export const MuseumTab = () => {
},
]
const selectingTable = (
<EditingModal buttonText="Add existing museum">
<MuseumSelectingTable />
</EditingModal>
)
const formFields: { name: string; label: string; required?: boolean }[] = [
{ name: 'code', label: 'Code', required: true },
{ name: 'museum', label: 'Museum', required: true },
@@ -94,19 +44,22 @@ export const MuseumTab = () => {
{ name: 'country', label: 'Country', required: true },
]
const editingModal = (
<EditingForm<Museum, LocalityDetails>
buttonText="Add new museum"
formFields={formFields}
arrayFieldName="museums"
/>
)
return (
<Grouped title="Museums">
{mode === 'edit' && (
<Box display="flex" gap={1}>
{editingModal} {selectingTable}
<EditingForm<Museum, LocalityDetails>
buttonText="Add new museum"
formFields={formFields}
arrayFieldName="museums"
/>
<SelectingTable<Museum, LocalityDetails>
buttonText="Add existing museum"
data={museumData}
columns={columns}
fieldName="museums"
idFieldName="museum"
/>
</Box>
)}
<EditableTable<Editable<Museum>, LocalityDetails>
@@ -5,34 +5,29 @@ import { useNavigate } from 'react-router-dom'
import ManageSearchIcon from '@mui/icons-material/ManageSearch'
import PolicyIcon from '@mui/icons-material/Policy'
import AddCircleOutlineIcon from '@mui/icons-material/AddCircleOutline'
import CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline'
export const ActionComponent = <T extends MRT_RowData>({
row,
idFieldName,
selectorFn,
selectedList,
checkRowRestriction,
url,
selectorFn,
}: {
row: MRT_Row<T>
idFieldName: keyof T
selectorFn?: (id: string) => void
selectedList?: string[]
checkRowRestriction: ((row: T) => boolean) | undefined
url: string | undefined
selectorFn?: (id: T) => void
}) => {
const navigate = useNavigate()
const id = row.original[idFieldName]
const currentSelected = selectedList && selectedList.find(sel => sel === id)
const getIconToShow = () => {
if (currentSelected) return <CheckCircleOutlineIcon color="success" />
if (selectorFn) return <AddCircleOutlineIcon />
return <ManageSearchIcon />
}
const onClick = () => {
if (selectorFn) {
selectorFn(id)
selectorFn(row.original)
} else {
navigate(`/${url}/${id}`)
}
@@ -30,15 +30,13 @@ export const TableView = <T extends MRT_RowData>({
idFieldName,
checkRowRestriction,
selectorFn,
selectedList,
url,
}: {
data: T[] | undefined
columns: MRT_ColumnDef<T>[]
idFieldName: keyof MRT_RowData
idFieldName: keyof T
checkRowRestriction?: (row: T) => boolean
selectorFn?: (id: string) => void
selectedList?: string[]
selectorFn?: (id: T) => void
url?: string
}) => {
const navigate = useNavigate()
@@ -92,14 +90,7 @@ export const TableView = <T extends MRT_RowData>({
}}
onColumnFiltersChange={setColumnFilters}
renderRowActions={({ row }) => (
<ActionComponent
row={row}
idFieldName={idFieldName}
selectorFn={selectorFn}
selectedList={selectedList}
checkRowRestriction={checkRowRestriction}
url={url}
/>
<ActionComponent {...{ selectorFn, url, checkRowRestriction, row, idFieldName }} />
)}
displayColumnDefOptions={{ 'mrt-row-actions': { size: 50, header: '' } }}
enableRowActions