11import {
22 useCallback ,
33 useMemo ,
4+ useState ,
45} from 'react' ;
56import {
67 Container ,
78 DateInput ,
89 Pager ,
910 Table ,
11+ TextInput ,
1012} from '@ifrc-go/ui' ;
1113import { SortContext } from '@ifrc-go/ui/contexts' ;
1214import { useTranslation } from '@ifrc-go/ui/hooks' ;
@@ -23,11 +25,15 @@ import {
2325import { saveAs } from 'file-saver' ;
2426import Papa from 'papaparse' ;
2527
28+ import CountrySelectInput from '#components/domain/CountrySelectInput' ;
29+ import EventSearchSelectInput from '#components/domain/EventSearchSelectInput' ;
2630import ExportButton from '#components/domain/ExportButton' ;
31+ import NationalSocietySelectInput from '#components/domain/NationalSocietySelectInput' ;
2732import Page from '#components/Page' ;
2833import useAlert from '#hooks/useAlert' ;
2934import useFilterState from '#hooks/useFilterState' ;
3035import useRecursiveCsvExport from '#hooks/useRecursiveCsvRequest' ;
36+ import useUrlSearchState from '#hooks/useUrlSearchState' ;
3137import { COUNTRY_RECORD_TYPE_REGION } from '#utils/constants' ;
3238import { countryIdToRegionIdMap } from '#utils/domain/country' ;
3339import { createLinkColumn } from '#utils/domain/tableHelpers' ;
@@ -61,6 +67,7 @@ export function Component() {
6167 } = useFilterState < {
6268 startDateAfter ?: string ,
6369 startDateBefore ?: string ,
70+ type ?: string ,
6471 } > ( {
6572 filter : { } ,
6673 pageSize : 10 ,
@@ -92,18 +99,113 @@ export function Component() {
9299 return [ ordering , defaultOrdering ] . join ( ',' ) ;
93100 } , [ ordering ] ) ;
94101
102+ const [ nationalSocietyFilter , setNationalSocietyFilter ] = useUrlSearchState < number | undefined > (
103+ 'country' ,
104+ ( searchValue ) => {
105+ const potentialValue = isDefined ( searchValue ) ? Number ( searchValue ) : undefined ;
106+ if ( potentialValue ) {
107+ setPage ( 0 ) ;
108+ }
109+ return potentialValue ;
110+ } ,
111+ ( country ) => country ,
112+ ) ;
113+
114+ const [ countryToFilter , setCountryToFilter ] = useUrlSearchState < number | undefined > (
115+ 'country2' ,
116+ ( searchValue ) => {
117+ const potentialValue = isDefined ( searchValue ) ? Number ( searchValue ) : undefined ;
118+ if ( potentialValue ) {
119+ setPage ( 0 ) ;
120+ }
121+ return potentialValue ;
122+ } ,
123+ ( country ) => country ,
124+ ) ;
125+
126+ const [ eventFilter , setEventFilter ] = useUrlSearchState < number | undefined > (
127+ 'event' ,
128+ ( searchValue ) => {
129+ const potentialValue = isDefined ( searchValue ) ? Number ( searchValue ) : undefined ;
130+ if ( potentialValue ) {
131+ setPage ( 0 ) ;
132+ }
133+ return potentialValue ;
134+ } ,
135+ ( country ) => country ,
136+ ) ;
137+
138+ const [ positionFilter , setPositionFilter ] = useUrlSearchState < string > (
139+ 'role' ,
140+ ( searchValue ) => searchValue ?? '' ,
141+ ( value ) => value ,
142+ ) ;
143+
144+ const [ eventOptions , setEventOptions ] = useState <
145+ EventItem [ ] | undefined | null
146+ > ( [ ] ) ;
147+
148+ useRequest ( {
149+ skip : isNotDefined ( eventFilter )
150+ || ( ! ! eventOptions ?. find ( ( event ) => event . id === eventFilter ) ) ,
151+ url : '/api/v2/event/{id}/' ,
152+ pathVariables : isDefined ( eventFilter ) ? {
153+ id : eventFilter ,
154+ } : undefined ,
155+ onSuccess : ( response ) => {
156+ if ( isNotDefined ( response ) ) {
157+ return ;
158+ }
159+
160+ const {
161+ id,
162+ dtype,
163+ name,
164+ } = response ;
165+
166+ if ( isNotDefined ( id ) || isNotDefined ( dtype ) || isNotDefined ( name ) ) {
167+ return ;
168+ }
169+
170+ const newOption = {
171+ id,
172+ dtype : {
173+ id : dtype ,
174+ translation_module_original_language : 'en' as const ,
175+ name : undefined ,
176+ summary : undefined ,
177+ } ,
178+ name,
179+ } ;
180+
181+ setEventOptions ( ( prevOptions ) => ( [
182+ ...prevOptions ?? [ ] ,
183+ newOption ,
184+ ] ) ) ;
185+ } ,
186+ } ) ;
187+
95188 const query = useMemo ( ( ) => ( {
96189 limit,
97190 offset,
98191 ordering : orderingWithFallback ,
99192 // FIXME: The server does not support date string
100193 start_date__gte : toDateTimeString ( filter . startDateAfter ) ,
101194 start_date__lte : toDateTimeString ( filter . startDateBefore ) ,
195+ type : filter . type ,
196+ role__icontains : positionFilter ,
197+ country_from : nationalSocietyFilter ,
198+ country_to : countryToFilter ,
199+ event_deployed_to : eventFilter ,
102200 } ) , [
103201 limit ,
104202 offset ,
105203 orderingWithFallback ,
106204 filter ,
205+ positionFilter ,
206+ nationalSocietyFilter ,
207+ countryToFilter ,
208+ eventFilter ,
107209 ] ) ;
108210
109211 const {
@@ -191,7 +293,7 @@ export function Component() {
191293 { sortable : true } ,
192294 ) ,
193295 createLinkColumn < PersonnelTableItem , number > (
194- 'event_deployed_to ' ,
296+ 'deployment__event_deployed_to ' ,
195297 strings . personnelTableEmergency ,
196298 ( item ) => item . deployment ?. event_deployed_to ?. name ,
197299 ( item ) => ( {
@@ -288,6 +390,36 @@ export function Component() {
288390 onChange = { setFilterField }
289391 value = { rawFilter . startDateBefore }
290392 />
393+ < TextInput
394+ label = { strings . personnelTablePosition }
395+ name = "role"
396+ value = { positionFilter }
397+ onChange = { setPositionFilter }
398+ placeholder = { strings . defaultPlaceholder }
399+ />
400+ < NationalSocietySelectInput
401+ label = { strings . personnelTableDeployingParty }
402+ name = "deploying_party"
403+ placeholder = { strings . defaultPlaceholder }
404+ value = { nationalSocietyFilter }
405+ onChange = { setNationalSocietyFilter }
406+ />
407+ < CountrySelectInput
408+ label = { strings . personnelTableDeployedTo }
409+ name = "deployed_to"
410+ placeholder = { strings . defaultPlaceholder }
411+ value = { countryToFilter }
412+ onChange = { setCountryToFilter }
413+ />
414+ < EventSearchSelectInput
415+ name = "event"
416+ label = { strings . personnelTableEmergency }
417+ placeholder = { strings . defaultPlaceholder }
418+ value = { eventFilter }
419+ onChange = { setEventFilter }
420+ options = { eventOptions }
421+ onOptionsChange = { setEventOptions }
422+ />
291423 </ >
292424 ) }
293425 footerActions = { (
0 commit comments