Skip to content

Commit f17e15d

Browse files
committed
chore: refactor redundant filter helper function
1 parent b87a79d commit f17e15d

File tree

5 files changed

+76
-153
lines changed

5 files changed

+76
-153
lines changed

examples/erp/genseki/collections/posts.client.tsx

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -72,19 +72,6 @@ export function PostClientToolbar() {
7272
return (
7373
<div>
7474
<CollectionListToolbar actions={context.actions} />
75-
{/* <CollectionListToolbar
76-
filterOptions={Object.values(listViewProps.fieldsClient.shape).map((field) => {
77-
return {
78-
fieldShape: field,
79-
optionsName: optionsFetchPathName(field),
80-
}
81-
})}
82-
allowedFilters={listViewProps.listConfiguration?.filterBy || []}
83-
actions={listViewProps.actions}
84-
slug={listViewProps.slug}
85-
isShowDeleteButton={isShowDeleteButton}
86-
onDelete={handleBulkDelete}
87-
/> */}
8875
</div>
8976
)
9077
}

packages/react/src/react/views/collections/list/toolbar/components/filter/filter-helper.ts

Lines changed: 66 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -21,126 +21,97 @@ export const isThisFilterAllowed = (target: string, allowedList: string[]) => {
2121
return allowedList.includes(target)
2222
}
2323

24-
export const whatFilterChoiceToChoose = (item: FieldShapeClient): FilterChoiceComponent => {
25-
switch (item.type) {
26-
case 'richText':
27-
case 'text':
28-
case 'password':
29-
case 'email':
30-
case 'number':
31-
case 'comboboxNumber':
32-
case 'comboboxText':
33-
case 'media':
34-
case 'create':
35-
return null
36-
37-
case 'time':
38-
case 'date':
39-
return 'datetime' // as range
40-
41-
case 'checkbox':
42-
case 'switch':
43-
return 'toggle' // as toggle ?
44-
45-
case 'selectNumber':
46-
case 'selectText':
47-
case 'connect':
48-
case 'connectOrCreate': {
49-
if (!item.options || (Array.isArray(item.options) && item.options.length === 0)) {
50-
throw new Error('Missing options for select/connect field')
51-
}
52-
return 'singleselect'
53-
}
54-
55-
default:
56-
return null
24+
export function getLabelFromFieldShape(fieldShape: FieldShapeClient, userFriendlyText: boolean) {
25+
const isRelational = isRelationFieldShapeClient(fieldShape)
26+
let columnOrRelationName = ''
27+
if (isRelational) {
28+
columnOrRelationName = fieldShape.$client.relation.name
29+
} else {
30+
columnOrRelationName = fieldShape.$client.column.name
5731
}
32+
if (userFriendlyText) {
33+
return `${fieldShape.label || fieldShape.$client.fieldName} (${columnOrRelationName})`
34+
}
35+
return `${columnOrRelationName}`
5836
}
5937

60-
export const isThisTypeFilterable = (item: FieldShapeClient) => {
61-
switch (item.type) {
62-
case 'richText':
63-
case 'text':
64-
case 'password':
65-
case 'email':
66-
case 'number':
67-
case 'comboboxNumber':
68-
case 'comboboxText':
69-
case 'media':
70-
case 'create':
71-
return false
38+
export function mapFieldShapeClient(fieldShape: FieldShapeClient): {
39+
filterChoice: FilterChoiceComponent
40+
optionsFetchPathName: string
41+
} {
42+
switch (fieldShape.type) {
43+
// case 'richText':
44+
// case 'text':
45+
// case 'password':
46+
// case 'email':
47+
// case 'number':
48+
// case 'comboboxNumber':
49+
// case 'comboboxText':
50+
// case 'media':
51+
// case 'create':
7252

7353
case 'time':
7454
case 'date':
75-
return true
55+
return {
56+
filterChoice: 'datetime',
57+
optionsFetchPathName: '',
58+
}
7659

7760
case 'checkbox':
7861
case 'switch':
79-
return false // not ready
62+
// this component is not ready yet
63+
return {
64+
filterChoice: 'toggle',
65+
optionsFetchPathName: '',
66+
}
8067

8168
case 'selectNumber':
8269
case 'selectText':
8370
case 'connect':
8471
case 'connectOrCreate': {
85-
if (!item.options) throw new Error('Missing optionsFetchPath')
86-
return true
72+
if (
73+
!fieldShape.options ||
74+
(Array.isArray(fieldShape.options) && fieldShape.options.length === 0)
75+
) {
76+
// `optionsFetchPathName` will not be completed without `options`, won't be able to fetch for choices
77+
// Act as if it is non-filterable
78+
return {
79+
filterChoice: null,
80+
optionsFetchPathName: '',
81+
}
82+
}
83+
return {
84+
filterChoice: 'singleselect',
85+
optionsFetchPathName: fieldShape.options,
86+
}
8787
}
8888

8989
default:
90-
throw new Error(`Unsupported field type: ${JSON.stringify(item)}`)
90+
return {
91+
filterChoice: null,
92+
optionsFetchPathName: '',
93+
}
9194
}
9295
}
9396

94-
export const optionsFetchPathName = (item: FieldShapeClient) => {
95-
switch (item.type) {
96-
case 'richText':
97-
return undefined
98-
case 'text':
99-
return undefined
100-
case 'password':
101-
return undefined
102-
case 'email':
103-
return undefined
104-
case 'number':
105-
return undefined
106-
case 'time':
107-
return undefined
108-
case 'date':
109-
return undefined
110-
case 'checkbox':
111-
return undefined
112-
case 'switch':
113-
return undefined
97+
export function selectFilterChoiceWithFieldShape(
98+
fieldShape: FieldShapeClient
99+
): FilterChoiceComponent {
100+
return mapFieldShapeClient(fieldShape).filterChoice
101+
}
114102

115-
case 'selectNumber':
116-
case 'selectText': {
117-
if (!item.options) throw new Error('Missing optionsFetchPath')
118-
return item.options
119-
}
120-
case 'comboboxNumber':
121-
case 'comboboxText': {
122-
return undefined
123-
}
124-
case 'media': {
125-
return undefined
126-
}
127-
case 'create': {
128-
return undefined
129-
}
130-
case 'connect':
131-
case 'connectOrCreate': {
132-
if (!item.options) throw new Error('Missing optionsFetchPath')
133-
return item.options
134-
}
135-
default:
136-
throw new Error(`Unsupported field type: ${JSON.stringify(item)}`)
137-
}
103+
export function isThisFieldShapeFilterable(fieldShape: FieldShapeClient): boolean {
104+
return !!mapFieldShapeClient(fieldShape).filterChoice
105+
}
106+
107+
export function getOptionsFetchPathNameWithFieldShape(fieldShape: FieldShapeClient): string {
108+
return mapFieldShapeClient(fieldShape).optionsFetchPathName
138109
}
139110

140111
export const transformFilterToPrismaString = (filters: MinimalFilter[]) => {
141112
// In case false data gets in, filter it out
142113
const filteredFilters = filters.filter((f) => {
143-
const targetType = whatFilterChoiceToChoose(f.fieldShape)
114+
const targetType = selectFilterChoiceWithFieldShape(f.fieldShape)
144115
switch (targetType) {
145116
case 'datetime':
146117
return !!f.value.filterValue && !!f.value.endFilterValue
@@ -173,7 +144,7 @@ export const transformFilterToPrismaString = (filters: MinimalFilter[]) => {
173144
}
174145

175146
const selfPrismaObjectGenerator = (sItem: MinimalFilter) => {
176-
const targetType = whatFilterChoiceToChoose(sItem.fieldShape)
147+
const targetType = selectFilterChoiceWithFieldShape(sItem.fieldShape)
177148
switch (targetType) {
178149
case 'datetime':
179150
return { gte: sItem.value.filterValue, lte: sItem.value.endFilterValue }

packages/react/src/react/views/collections/list/toolbar/components/filter/panel-content.tsx

Lines changed: 6 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ import { useState } from 'react'
33
import { FilterDate } from './components/filter-date'
44
import { FilterOptions } from './components/filter-options'
55
import {
6+
getLabelFromFieldShape,
67
type MinimalFilter,
8+
selectFilterChoiceWithFieldShape,
79
transformFilterToPrismaString,
8-
whatFilterChoiceToChoose,
910
} from './filter-helper'
1011

1112
import type { FieldShapeClient } from '../../../../../../../core'
12-
import { isRelationFieldShapeClient } from '../../../../../../../core/utils'
1313
import {
1414
Button,
1515
Select,
@@ -35,35 +35,18 @@ interface CollectionListFilterPanelProps {
3535
}
3636

3737
export function CollectionListFilterPanel(props: CollectionListFilterPanelProps) {
38-
const generateLabel = (target: FieldShapeClient, userFriendlyText: boolean) => {
39-
const isRelational = isRelationFieldShapeClient(target)
40-
41-
let columnOrRelationName = ''
42-
43-
if (isRelational) {
44-
columnOrRelationName = target.$client.relation.name
45-
} else {
46-
columnOrRelationName = target.$client.column.name
47-
}
48-
49-
if (userFriendlyText) {
50-
return `${target.label || target.$client.fieldName} (${columnOrRelationName})`
51-
}
52-
return `${columnOrRelationName}`
53-
}
54-
5538
const availableFields = [
5639
...props.fetchList.map((e) => {
5740
return {
5841
field: e.fieldShape,
59-
label: generateLabel(e.fieldShape, true),
42+
label: getLabelFromFieldShape(e.fieldShape, true),
6043
options: e.optionsName,
6144
}
6245
}),
6346
...props.formulateList.map((e) => {
6447
return {
6548
field: e.fieldShape,
66-
label: generateLabel(e.fieldShape, true),
49+
label: getLabelFromFieldShape(e.fieldShape, true),
6750
options: e.optionsName,
6851
}
6952
}),
@@ -180,8 +163,8 @@ export function CollectionListFilterPanel(props: CollectionListFilterPanelProps)
180163
{chosenFilter.length > 0 && (
181164
<div className="space-y-2">
182165
{chosenFilter.map((filterField) => {
183-
const fieldLabel = generateLabel(filterField.fieldShape, true)
184-
const choiceType = whatFilterChoiceToChoose(filterField.fieldShape)
166+
const fieldLabel = getLabelFromFieldShape(filterField.fieldShape, true)
167+
const choiceType = selectFilterChoiceWithFieldShape(filterField.fieldShape)
185168
switch (choiceType) {
186169
case 'datetime':
187170
return (

packages/react/src/react/views/collections/list/toolbar/filter.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use client'
22

3-
import { isThisFilterAllowed, isThisTypeFilterable } from './components/filter/filter-helper'
3+
import { isThisFieldShapeFilterable, isThisFilterAllowed } from './components/filter/filter-helper'
44
import {
55
CollectionListFilterPanel,
66
type FilterFieldOptions,
@@ -30,7 +30,7 @@ export interface CollectionListFilterProps
3030
export function CollectionListFilter(props: CollectionListFilterProps) {
3131
const { setFilter } = useFilter({ debounce: 500 })
3232

33-
const filterable = props.filterOptions.filter((e) => isThisTypeFilterable(e.fieldShape))
33+
const filterable = props.filterOptions.filter((e) => isThisFieldShapeFilterable(e.fieldShape))
3434

3535
const whatFilterCanIFetch = [] // use this to fetch for optionsName
3636
const whatFilterCanIFormulate = [] // these you will have to create a component to handle the filter value(s) yourself

packages/react/src/react/views/collections/list/toolbar/index.tsx

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,13 @@ import { useState } from 'react'
55
import { CaretLeftIcon } from '@phosphor-icons/react/dist/ssr'
66
import { useQueryClient } from '@tanstack/react-query'
77

8-
import { optionsFetchPathName } from './components/filter/filter-helper'
8+
import { getOptionsFetchPathNameWithFieldShape } from './components/filter/filter-helper'
99
import { FilterToggle } from './components/filter/filter-toggle'
1010
import { CollectionListCreate } from './create'
1111
import { CollectionListDelete } from './delete'
1212
import { CollectionListFilter } from './filter'
1313
import { CollectionListSearch } from './search'
1414

15-
// import { CollectionListCreate, type MinimalCollectionListCreateProps } from './create'
16-
// import { CollectionListDelete, type MinimalCollectionListDeleteProps } from './delete'
17-
// import { CollectionListFilter } from './filter'
18-
// import { CollectionListSearch, type CollectionListSearchProps } from './search'
1915
import type { CollectionListActions } from '../../../../../core/collection'
2016
import { toast } from '../../../..'
2117
import { BaseIcon, ButtonLink } from '../../../../components'
@@ -27,20 +23,6 @@ import { useCollectionDeleteMutation } from '../hooks/use-collection-delete'
2723
export interface CollectionListToolbarProps {
2824
actions?: Partial<CollectionListActions>
2925
}
30-
// import { cn } from '../../../../utils/cn'
31-
// import type { ListActions } from '../../types'
32-
33-
// export interface CollectionListToolbarProps
34-
// extends CollectionListSearchProps,
35-
// MinimalCollectionListDeleteProps,
36-
// MinimalCollectionListFilterProps,
37-
// MinimalCollectionListCreateProps {
38-
// isShowDeleteButton?: boolean
39-
// actions?: ListActions
40-
// filterOptions: FilterFieldOptions[]
41-
// allowedFilters: string[]
42-
// onFilterChange?: (value: string) => void
43-
// }
4426

4527
export function CollectionListToolbar(props: CollectionListToolbarProps) {
4628
const context = useCollectionList()
@@ -108,7 +90,7 @@ export function CollectionListToolbar(props: CollectionListToolbarProps) {
10890
filterOptions={Object.values(context.fields.shape).map((fieldShape) => {
10991
return {
11092
fieldShape,
111-
optionsName: optionsFetchPathName(fieldShape),
93+
optionsName: getOptionsFetchPathNameWithFieldShape(fieldShape),
11294
}
11395
})}
11496
allowedFilters={context.filter || []}

0 commit comments

Comments
 (0)