beherbergung/frontend/search/components/ngo/HostOfferLookupTable.tsx

225 lines
5.1 KiB
TypeScript
Raw Normal View History

2022-03-09 21:58:51 +01:00
import React, {ReactNode} from 'react'
2022-03-09 18:23:27 +01:00
2022-03-10 12:41:20 +01:00
import {CheckBoxOutlineBlank, CheckBox} from '@mui/icons-material';
2022-03-09 18:23:27 +01:00
2022-03-09 17:01:05 +01:00
import '@inovua/reactdatagrid-community/index.css'
import DataGrid from '@inovua/reactdatagrid-community'
import DateFilter from '@inovua/reactdatagrid-community/DateFilter'
import StringFilter from '@inovua/reactdatagrid-community/StringFilter'
import BoolFilter from '@inovua/reactdatagrid-community/BoolFilter'
2022-03-09 15:39:15 +01:00
import {GetOffersQuery} from "../../codegen/generates";
2022-03-09 17:01:05 +01:00
import {TypeColumn, TypeFilterValue, TypeSingleFilterValue} from "@inovua/reactdatagrid-community/types";
import NumberFilter from "@inovua/reactdatagrid-community/NumberFilter";
2022-03-09 17:19:45 +01:00
import moment from "moment";
2022-03-09 22:51:30 +01:00
import {useTranslation} from "react-i18next";
2022-03-10 12:41:20 +01:00
import {resources} from '../../i18n/config';
import {Box} from "@mui/material";
2022-03-09 22:51:30 +01:00
2022-03-09 17:19:45 +01:00
global.moment = moment
2022-03-09 15:39:15 +01:00
type HostOfferLookupTableProps = {
data: GetOffersQuery
}
interface ColumnRaw {
name: string;
header: string;
type: string;
defaultWidth: number;
}
2022-03-09 18:23:27 +01:00
2022-03-09 21:58:51 +01:00
/**
* you can generate an inital raw column json by running the following
* function
*/
2022-03-10 12:41:20 +01:00
const makeColumnDefinition = (data: any) => Object.keys(data)
2022-03-09 21:58:51 +01:00
.map(k => ({
name: k,
header: k.replace(/_/g, ' '),
2022-03-10 12:41:20 +01:00
type: typeof data[k]
}))
2022-03-09 21:58:51 +01:00
const columnsRaw: Partial<ColumnRaw>[] = [
2022-03-09 17:01:05 +01:00
{
2022-03-10 11:28:40 +01:00
"name": "place_country",
"header": "Country",
"type": "string",
"defaultWidth": 10
2022-03-09 17:01:05 +01:00
},
{
2022-03-10 11:28:40 +01:00
"name": "place_city",
"header": "City",
2022-03-09 17:01:05 +01:00
"type": "string"
},
{
2022-03-10 11:28:40 +01:00
"name": "beds",
"header": "Beds",
2022-03-10 11:28:40 +01:00
"type": "number"
2022-03-09 17:01:05 +01:00
},
{
2022-03-10 11:28:40 +01:00
"name": "time_from_str",
"header": "From",
"type": "date",
"defaultWidth": 90
2022-03-09 17:01:05 +01:00
},
{
"name": "time_duration_str",
"header": "Duration",
2022-03-09 17:01:05 +01:00
"type": "string"
},
{
2022-03-10 11:28:40 +01:00
"name": "languages",
"header": "languages",
"type": "object",
"defaultWidth": 200
2022-03-09 17:01:05 +01:00
},
{
2022-03-10 11:28:40 +01:00
"name": "accessible",
"header": "accessible",
"type": "boolean",
"defaultWidth": 80
2022-03-09 17:01:05 +01:00
},
{
2022-03-10 11:28:40 +01:00
"name": "animals_allowed",
"header": "allows animals",
"type": "boolean",
"defaultWidth": 80
2022-03-09 17:01:05 +01:00
},
{
2022-03-10 11:28:40 +01:00
"name": "animals_present",
"header": "has animals",
"type": "boolean",
"defaultWidth": 80
2022-03-09 17:01:05 +01:00
},
{
2022-03-10 11:28:40 +01:00
"name": "note",
"header": "Note",
"type": "string",
"defaultWidth": 400
2022-03-09 17:01:05 +01:00
},
{
2022-03-10 11:28:40 +01:00
"name": "contact_name_full",
"header": "Name",
2022-03-10 11:28:40 +01:00
"type": "string"
2022-03-09 17:01:05 +01:00
},
{
2022-03-10 11:28:40 +01:00
"name": "contact_phone",
"header": "Phone",
2022-03-09 17:01:05 +01:00
"type": "string"
},
{
2022-03-10 11:28:40 +01:00
"name": "contact_email",
"header": "EMail",
2022-03-10 11:28:40 +01:00
"type": "string"
2022-03-09 17:01:05 +01:00
},
{
2022-03-10 11:28:40 +01:00
"name": "place_street",
"header": "Street",
2022-03-10 11:28:40 +01:00
"type": "string"
2022-03-09 17:01:05 +01:00
},
{
2022-03-10 11:28:40 +01:00
"name": "place_street_number",
"header": "Street number",
"type": "string",
"defaultWidth": 80
2022-03-09 17:01:05 +01:00
},
{
2022-03-10 11:28:40 +01:00
"name": "place_zip",
"header": "Zip",
"type": "string",
"defaultWidth": 80
2022-03-10 11:28:40 +01:00
},
2022-03-09 17:01:05 +01:00
]
const filterMappings = {
string: StringFilter,
boolean: BoolFilter,
number: NumberFilter,
date: DateFilter,
2022-03-09 17:01:05 +01:00
}
const operatorsForType = {
number: 'gte',
string: 'contains',
date: 'beforeOrOn',
boolean: 'eq',
2022-03-09 18:23:27 +01:00
}
2022-03-09 17:01:05 +01:00
2022-03-09 21:58:51 +01:00
type CustomRendererMatcher = {
match: { [key: string]: any }
render: (...args: any[]) => ReactNode
}
const customRendererForType: CustomRendererMatcher[] = [
2022-03-09 18:23:27 +01:00
{
match: {type: 'boolean'},
2022-03-10 12:41:20 +01:00
render: ({value}) => !!value ? <CheckBox/> : <CheckBoxOutlineBlank/>
2022-03-09 18:23:27 +01:00
},
{
match: {type: 'string', name: 'contact_email'},
2022-03-10 12:41:20 +01:00
render: ({value}) => (<a href={`mailto:${value}`}>{value}</a>)
2022-03-09 18:23:27 +01:00
}
]
const findMatchingRenderer = (c: Partial<ColumnRaw>) => {
2022-03-09 18:23:27 +01:00
const customRenderer = customRendererForType.find(d => {
// @ts-ignore
2022-03-10 12:41:20 +01:00
return Object.keys(d.match).reduce((prev, cur) => prev && c[cur] === d.match[cur], true)
2022-03-09 18:23:27 +01:00
})
return customRenderer?.render
}
2022-03-09 17:01:05 +01:00
const columns: TypeColumn[] = columnsRaw
.map(c => ({
...c,
2022-03-09 21:58:51 +01:00
render: findMatchingRenderer(c) || undefined,
2022-03-09 17:19:45 +01:00
filterEditor: filterMappings[c.type as 'string' | 'number' | 'boolean' | 'date']
2022-03-09 17:01:05 +01:00
}))
const defaultFilterValue: TypeFilterValue = columns
2022-03-10 12:41:20 +01:00
.filter(({type}) => type && ['string', 'number', 'date', 'boolean'].includes(type))
.map(({name, type}) => {
2022-03-09 17:01:05 +01:00
return {
name,
type,
2022-03-09 18:23:27 +01:00
value: null,
operator: operatorsForType[type as 'string' | 'number' | 'date' | 'boolean']
2022-03-09 17:01:05 +01:00
} as unknown as TypeSingleFilterValue
2022-03-10 12:41:20 +01:00
})
2022-03-09 17:01:05 +01:00
2022-03-10 12:41:20 +01:00
const HostOfferLookupTable = ({data}: HostOfferLookupTableProps) => {
2022-03-09 17:19:45 +01:00
const dataSource = data.get_offers || []
2022-03-09 22:51:30 +01:00
2022-03-10 12:41:20 +01:00
const {i18n: {language}} = useTranslation()
2022-03-09 22:51:30 +01:00
// @ts-ignore
const reactdatagridi18n = resources[language]?.translation?.reactdatagrid
2022-03-10 12:59:51 +01:00
return <Box sx={{
display: 'flex',
alignItems: 'stretch',
flexDirection: 'column',
height: '100%'}}>
2022-03-10 12:41:20 +01:00
<div
2022-03-10 12:59:51 +01:00
style={{flex: '1 1', height: '100%'}}>
2022-03-10 12:41:20 +01:00
<DataGrid
idProperty="id"
filterable
showColumnMenuFilterOptions={true}
showFilteringMenuItems={true}
defaultFilterValue={defaultFilterValue}
rowIndexColumn
enableSelection
enableColumnAutosize={false}
columns={columns}
dataSource={dataSource}
i18n={reactdatagridi18n || undefined}
2022-03-10 12:41:20 +01:00
style={{height: '100%'}}
2022-03-10 12:41:20 +01:00
/>
</div>
</Box>
2022-03-09 15:39:15 +01:00
}
export default HostOfferLookupTable