@@ -36,7 +36,7 @@ import {
36
36
import { useFetcher , useLoaderData } from '@remix-run/react' ;
37
37
import { useForm } from '@tanstack/react-form' ;
38
38
import { decode as formDataToObject } from 'decode-formdata' ;
39
- import { type Namespace } from 'i18next' ;
39
+ import { type Namespace , t as rawT } from 'i18next' ;
40
40
import { serialize as objectToFormData } from 'object-to-formdata' ;
41
41
import { Trans , useTranslation } from 'react-i18next' ;
42
42
import { difference } from 'remeda' ;
@@ -133,8 +133,22 @@ const editSanctionFormSchema = z.object({
133
133
z . literal ( 'block_and_review' ) ,
134
134
] ) ,
135
135
triggerRule : z . any ( ) . nullish ( ) ,
136
- counterPartyName : z . any ( ) . nullish ( ) ,
137
- counterPartyLabel : z . any ( ) . nullish ( ) ,
136
+ query : z
137
+ . object ( {
138
+ name : z . any ( ) . nullish ( ) ,
139
+ label : z . any ( ) . nullish ( ) ,
140
+ } )
141
+ . superRefine ( ( arg , ctx ) => {
142
+ if ( ! arg . name && ! arg . label ) {
143
+ ctx . addIssue ( {
144
+ code : 'invalid_arguments' ,
145
+ path : [ 'label' ] ,
146
+ message : rawT ( 'scenarios:sanction.match_settings.no_empty' ) ,
147
+ argumentsError : rawT ( 'scenarios:sanction.match_settings.no_empty' ) ,
148
+ } ) ;
149
+ }
150
+ return true ;
151
+ } ) ,
138
152
counterPartyId : z . any ( ) . nullish ( ) ,
139
153
datasets : z . array ( z . string ( ) ) ,
140
154
} ) ;
@@ -161,22 +175,27 @@ export async function action({ request, params }: ActionFunctionArgs) {
161
175
arrays : [ 'datasets' ] ,
162
176
} ) ;
163
177
164
- try {
165
- console . log ( 'Form Data' , formDataDecoded ) ;
166
-
167
- const data = editSanctionFormSchema . parse ( formDataDecoded ) ;
178
+ const result = editSanctionFormSchema . safeParse ( formDataDecoded ) ;
168
179
169
- console . log ( 'Data' , formDataDecoded ) ;
180
+ if ( ! result . success ) {
181
+ return json (
182
+ { status : 'error' , errors : result . error . flatten ( ) } ,
183
+ {
184
+ headers : { 'Set-Cookie' : await commitSession ( session ) } ,
185
+ } ,
186
+ ) ;
187
+ }
170
188
189
+ try {
171
190
await scenarioIterationSanctionRepository . upsertSanctionCheckConfig ( {
172
191
iterationId,
173
192
changes : {
174
- ...data ,
175
- counterPartyId : data . counterPartyId as AstNode | undefined ,
176
- triggerRule : data . triggerRule as AstNode | undefined ,
193
+ ...result . data ,
194
+ counterPartyId : result . data . counterPartyId as AstNode | undefined ,
195
+ triggerRule : result . data . triggerRule as AstNode | undefined ,
177
196
query : {
178
- name : data . counterPartyName as AstNode | undefined ,
179
- label : data . counterPartyLabel as AstNode | undefined ,
197
+ name : result . data . query ?. name as AstNode | undefined ,
198
+ label : result . data . query ?. label as AstNode | undefined ,
180
199
} ,
181
200
} ,
182
201
} ) ;
@@ -187,21 +206,19 @@ export async function action({ request, params }: ActionFunctionArgs) {
187
206
} ) ;
188
207
189
208
return json (
190
- { status : 'success' } ,
209
+ { status : 'success' , errors : [ ] } ,
191
210
{
192
211
headers : { 'Set-Cookie' : await commitSession ( session ) } ,
193
212
} ,
194
213
) ;
195
214
} catch ( error ) {
196
- console . log ( 'Error' , error ) ;
197
-
198
215
setToastMessage ( session , {
199
216
type : 'error' ,
200
217
messageKey : 'common:errors.unknown' ,
201
218
} ) ;
202
219
203
220
return json (
204
- { status : 'error' } ,
221
+ { status : 'error' , errors : [ ] } ,
205
222
{
206
223
headers : { 'Set-Cookie' : await commitSession ( session ) } ,
207
224
} ,
@@ -251,8 +268,10 @@ export default function SanctionDetail() {
251
268
( sanctionCheckConfig ?. forcedOutcome as SanctionOutcome ) ??
252
269
'block_and_review' ,
253
270
triggerRule : sanctionCheckConfig ?. triggerRule ,
254
- counterPartyName : sanctionCheckConfig ?. query ?. name ,
255
- counterPartyLabel : sanctionCheckConfig ?. query ?. label ,
271
+ query : {
272
+ name : sanctionCheckConfig ?. query ?. name ,
273
+ label : sanctionCheckConfig ?. query ?. label ,
274
+ } ,
256
275
counterPartyId : sanctionCheckConfig ?. counterPartyId ,
257
276
} ,
258
277
} ) ;
@@ -307,8 +326,8 @@ export default function SanctionDetail() {
307
326
type = "text"
308
327
name = { field . name }
309
328
onBlur = { field . handleBlur }
310
- onChange = { ( e ) =>
311
- field . handleChange ( e . currentTarget . value )
329
+ onChange = { ( { currentTarget : { value } } ) =>
330
+ field . handleChange ( value )
312
331
}
313
332
placeholder = { t (
314
333
'scenarios:edit_rule.name_placeholder' ,
@@ -439,6 +458,43 @@ export default function SanctionDetail() {
439
458
</ Collapsible . Content >
440
459
</ Collapsible . Container >
441
460
461
+ < Collapsible . Container className = "bg-grey-100 max-w-3xl" >
462
+ < Collapsible . Title className = "mb-2" >
463
+ { t ( 'scenarios:sanction_counterparty_id' ) }
464
+ </ Collapsible . Title >
465
+ < Collapsible . Content >
466
+ < form . Field name = "counterPartyId" >
467
+ { ( field ) => (
468
+ < div className = "flex flex-col gap-4" >
469
+ < FormLabel
470
+ className = "inline-flex items-center gap-1"
471
+ name = { field . name }
472
+ >
473
+ { t ( 'scenarios:sanction_counterparty_id' ) }
474
+ < FieldToolTip >
475
+ { t ( 'scenarios:sanction_counterparty_id.tooltip' ) }
476
+ </ FieldToolTip >
477
+ </ FormLabel >
478
+ < OptionsProvider { ...options } >
479
+ < FieldNode
480
+ viewOnly = { editor === 'view' }
481
+ value = { field . state . value }
482
+ onChange = { field . handleChange }
483
+ onBlur = { field . handleBlur }
484
+ placeholder = { t (
485
+ 'scenarios:sanction_counterparty_id_placeholder' ,
486
+ ) }
487
+ />
488
+ </ OptionsProvider >
489
+ < FormErrorOrDescription
490
+ errors = { field . state . meta . errors }
491
+ />
492
+ </ div >
493
+ ) }
494
+ </ form . Field >
495
+ </ Collapsible . Content >
496
+ </ Collapsible . Container >
497
+
442
498
< Collapsible . Container className = "bg-grey-100 max-w-3xl" >
443
499
< Collapsible . Title >
444
500
{ t ( 'scenarios:sanction.match_settings.title' ) }
@@ -450,36 +506,7 @@ export default function SanctionDetail() {
450
506
</ p >
451
507
</ Callout >
452
508
< div className = "flex flex-col gap-6" >
453
- < form . Field name = "counterPartyId" >
454
- { ( field ) => (
455
- < div className = "flex flex-col gap-4" >
456
- < FormLabel
457
- className = "inline-flex items-center gap-1"
458
- name = { field . name }
459
- >
460
- { t ( 'scenarios:sanction_counterparty_id' ) }
461
- < FieldToolTip >
462
- { t ( 'scenarios:sanction_counterparty_id.tooltip' ) }
463
- </ FieldToolTip >
464
- </ FormLabel >
465
- < OptionsProvider { ...options } >
466
- < FieldNode
467
- viewOnly = { editor === 'view' }
468
- value = { field . state . value }
469
- onChange = { field . handleChange }
470
- onBlur = { field . handleBlur }
471
- placeholder = { t (
472
- 'scenarios:sanction_counterparty_id_placeholder' ,
473
- ) }
474
- />
475
- </ OptionsProvider >
476
- < FormErrorOrDescription
477
- errors = { field . state . meta . errors }
478
- />
479
- </ div >
480
- ) }
481
- </ form . Field >
482
- < form . Field name = "counterPartyName" >
509
+ < form . Field name = "query.name" >
483
510
{ ( field ) => (
484
511
< div className = "flex flex-col gap-4" >
485
512
< FormLabel
@@ -494,7 +521,7 @@ export default function SanctionDetail() {
494
521
< OptionsProvider { ...options } >
495
522
< FieldNodeConcat
496
523
viewOnly = { editor === 'view' }
497
- value = { field . state . value }
524
+ value = { sanctionCheckConfig ?. query ?. name }
498
525
onChange = { field . handleChange }
499
526
onBlur = { field . handleBlur }
500
527
placeholder = "Select the First name or Full Name"
@@ -507,7 +534,7 @@ export default function SanctionDetail() {
507
534
</ div >
508
535
) }
509
536
</ form . Field >
510
- < form . Field name = "counterPartyLabel " >
537
+ < form . Field name = "query.label " >
511
538
{ ( field ) => (
512
539
< div className = "flex flex-col gap-4" >
513
540
< FormLabel name = { field . name } >
0 commit comments