|
1 | 1 | import { useTasksTranslation } from '@/i18n/useTasksTranslation' |
2 | 2 | import { Button, FilterBasePopUp, type FilterListPopUpBuilderProps } from '@helpwave/hightide' |
3 | | -import { useId, useMemo, useState } from 'react' |
| 3 | +import { useId, useMemo, useState, type ReactNode } from 'react' |
4 | 4 | import { MapPin } from 'lucide-react' |
5 | | -import type { LocationNodeType } from '@/api/gql/generated' |
| 5 | +import type { LocationNodeType, LocationType } from '@/api/gql/generated' |
6 | 6 | import { LocationSelectionDialog } from '@/components/locations/LocationSelectionDialog' |
7 | 7 | import { useLocations } from '@/data' |
| 8 | +import { FilterPreviewLocationChips } from '@/components/tables/FilterPreviewMedia' |
| 9 | + |
| 10 | +function nodeToPreviewLocation(node: { id: string, title: string, kind: LocationType }) { |
| 11 | + return { id: node.id, title: node.title, kind: node.kind } |
| 12 | +} |
8 | 13 |
|
9 | 14 | export const LocationSubtreeFilterPopUp = ({ value, onValueChange, onRemove, name }: FilterListPopUpBuilderProps) => { |
10 | 15 | const translation = useTasksTranslation() |
@@ -51,20 +56,72 @@ export const LocationSubtreeFilterPopUp = ({ value, onValueChange, onRemove, nam |
51 | 56 | setDialogOpen(false) |
52 | 57 | } |
53 | 58 |
|
54 | | - const summary = useMemo(() => { |
55 | | - const nodes = locationsData?.locationNodes |
| 59 | + const summaryContent = useMemo((): ReactNode => { |
| 60 | + const locationNodes = locationsData?.locationNodes |
56 | 61 | if (isMulti) { |
57 | | - const n = (uuidValues as string[] | undefined)?.length ?? 0 |
58 | | - return n === 0 ? translation('selectLocation') : `${n} ${translation('location')}` |
| 62 | + const ids = (uuidValues as string[] | undefined) ?? [] |
| 63 | + const n = ids.length |
| 64 | + if (n === 0) { |
| 65 | + return ( |
| 66 | + <> |
| 67 | + <MapPin className="size-4 shrink-0 opacity-60" /> |
| 68 | + <span className="truncate">{translation('selectLocation')}</span> |
| 69 | + </> |
| 70 | + ) |
| 71 | + } |
| 72 | + if (n > 2) { |
| 73 | + return ( |
| 74 | + <> |
| 75 | + <MapPin className="size-4 shrink-0 opacity-60" /> |
| 76 | + <span className="truncate text-sm"> |
| 77 | + {n} {translation('location')} |
| 78 | + </span> |
| 79 | + </> |
| 80 | + ) |
| 81 | + } |
| 82 | + return ( |
| 83 | + <span className="flex flex-wrap items-center gap-1 min-w-0"> |
| 84 | + {ids.map(locId => { |
| 85 | + const node = locationNodes?.find(x => x.id === locId) |
| 86 | + return node ? ( |
| 87 | + <FilterPreviewLocationChips |
| 88 | + key={locId} |
| 89 | + className="max-w-[min(100%,9.5rem)]" |
| 90 | + locations={[nodeToPreviewLocation(node)]} |
| 91 | + /> |
| 92 | + ) : ( |
| 93 | + <span key={locId} className="text-sm truncate"> |
| 94 | + {locId} |
| 95 | + </span> |
| 96 | + ) |
| 97 | + })} |
| 98 | + </span> |
| 99 | + ) |
59 | 100 | } |
60 | 101 | const uid = uuidValue != null && String(uuidValue) !== '' |
61 | 102 | ? String(uuidValue) |
62 | 103 | : undefined |
63 | 104 | if (!uid) { |
64 | | - return translation('selectLocation') |
| 105 | + return ( |
| 106 | + <> |
| 107 | + <MapPin className="size-4 shrink-0 opacity-60" /> |
| 108 | + <span className="truncate">{translation('selectLocation')}</span> |
| 109 | + </> |
| 110 | + ) |
65 | 111 | } |
66 | | - const node = nodes?.find(n => n.id === uid) |
67 | | - return node?.title ?? translation('selectLocation') |
| 112 | + const node = locationNodes?.find(n => n.id === uid) |
| 113 | + const label = node?.title ?? translation('selectLocation') |
| 114 | + return node ? ( |
| 115 | + <FilterPreviewLocationChips |
| 116 | + className="max-w-[min(100%,14rem)]" |
| 117 | + locations={[nodeToPreviewLocation(node)]} |
| 118 | + /> |
| 119 | + ) : ( |
| 120 | + <> |
| 121 | + <MapPin className="size-4 shrink-0 opacity-60" /> |
| 122 | + <span className="truncate text-sm">{label}</span> |
| 123 | + </> |
| 124 | + ) |
68 | 125 | }, [isMulti, locationsData?.locationNodes, uuidValue, uuidValues, translation]) |
69 | 126 |
|
70 | 127 | return ( |
@@ -109,11 +166,10 @@ export const LocationSubtreeFilterPopUp = ({ value, onValueChange, onRemove, nam |
109 | 166 | type="button" |
110 | 167 | color="neutral" |
111 | 168 | coloringStyle="outline" |
112 | | - className="inline-flex items-center gap-2" |
| 169 | + className="inline-flex items-center gap-2 min-w-0 max-w-full h-auto py-1.5" |
113 | 170 | onClick={() => setDialogOpen(true)} |
114 | 171 | > |
115 | | - <MapPin className="size-4" /> |
116 | | - {summary} |
| 172 | + {summaryContent} |
117 | 173 | </Button> |
118 | 174 | </div> |
119 | 175 | </div> |
|
0 commit comments