@@ -16,12 +16,15 @@ import {
1616 ApplyComplianceUnitsFormData ,
1717 BccrUnit ,
1818} from "@/compliance/src/app/types" ;
19- import FormAlerts from "@bciers/components/form/FormAlerts" ;
2019import { ApplyComplianceUnitsAlertNote } from "./ApplyComplianceUnitsAlertNote" ;
2120import { IChangeEvent } from "@rjsf/core" ;
2221import { actionHandler } from "@bciers/actions" ;
2322import SubmitButton from "@bciers/components/button/SubmitButton" ;
2423import getReportOperationByComplianceReportVersionId from "@/compliance/src/app/utils/getReportOperationByComplianceReportVersionId" ;
24+ import {
25+ useValidationErrors ,
26+ handleApiResponse ,
27+ } from "@bciers/components/validationErrors" ;
2528
2629interface ApplyComplianceUnitsComponentProps {
2730 complianceReportVersionId : number ;
@@ -44,14 +47,15 @@ export default function ApplyComplianceUnitsComponent({
4447 const [ currentPhase , setCurrentPhase ] = useState <
4548 "initial" | "confirmation" | "compliance_data"
4649 > ( "initial" ) ;
47- const [ errors , setErrors ] = useState < string [ ] | undefined > ( ) ;
4850 const [ status , setStatus ] = useState < Status > ( "idle" ) ;
4951 // Keep track of the remaining cap from the API (what's left to apply)
5052 const [ remainingCap , setRemainingCap ] = useState < number > ( 0 ) ;
5153 // Legacy / fallback outstanding balance (not used for limit enforcement)
5254 const [ initialOutstandingBalance , setInitialOutstandingBalance ] =
5355 useState < number > ( 0 ) ;
5456
57+ const { setErrors, renderedErrors } = useValidationErrors ( ) ;
58+
5559 useEffect ( ( ) => {
5660 const fetchOperationName = async ( ) => {
5761 const operation = await getReportOperationByComplianceReportVersionId (
@@ -107,6 +111,7 @@ export default function ApplyComplianceUnitsComponent({
107111 setFormData ( {
108112 bccr_holding_account_id : newAccountId ,
109113 } ) ;
114+ setErrors ( undefined ) ;
110115 setStatus ( "idle" ) ;
111116 setCurrentPhase ( "initial" ) ;
112117 return ;
@@ -162,51 +167,47 @@ export default function ApplyComplianceUnitsComponent({
162167 e : IChangeEvent < ApplyComplianceUnitsFormData > ,
163168 ) => {
164169 setStatus ( "submitting" ) ;
165- try {
166- const response = await actionHandler (
167- `compliance/bccr/accounts/${ e . formData ?. bccr_holding_account_id } /compliance-report-versions/${ complianceReportVersionId } /compliance-units` ,
168- "GET" ,
169- "" ,
170- ) ;
170+ setErrors ( undefined ) ;
171171
172- if ( ! response || response . error ) {
173- setStatus ( "idle" ) ;
174- setErrors ( [ response ?. error || "Failed to get compliance units data." ] ) ;
175- } else {
176- // Set the remaining cap from the response (what’s left to apply)
177- setRemainingCap ( Number ( response . compliance_unit_cap_remaining ) ) ;
178-
179- // Set the outstanding balance from the response
180- setInitialOutstandingBalance ( response . outstanding_balance || 0 ) ;
181-
182- // Update form data with the full compliance data from the response
183- setFormData ( ( prev : Partial < ApplyComplianceUnitsFormData > ) => {
184- // Create a clean data object for the compliance phase
185- const cleanFormData = {
186- bccr_holding_account_id : prev . bccr_holding_account_id ,
187- bccr_trading_name : prev . bccr_trading_name ,
188- ...response ,
189- } ;
190-
191- setCurrentPhase ( "compliance_data" ) ;
192- return cleanFormData ;
193- } ) ;
194-
195- setStatus ( "submitted" ) ;
196- setErrors ( undefined ) ;
197- }
198- } catch ( err : any ) {
199- // Catch uncaught server errors
200- setErrors ( [
201- err ?. message ||
202- "An internal server error has occurred. Please contact support." ,
203- ] ) ;
172+ const response = await actionHandler (
173+ `compliance/bccr/accounts/${ e . formData ?. bccr_holding_account_id } /compliance-report-versions/${ complianceReportVersionId } /compliance-units` ,
174+ "GET" ,
175+ "" ,
176+ ) ;
177+
178+ const isSuccess = handleApiResponse ( response , setErrors ) ;
179+ if ( ! isSuccess ) {
180+ setStatus ( "idle" ) ;
181+ return ;
204182 }
183+
184+ // Set the remaining cap from the response (what’s left to apply)
185+ setRemainingCap ( Number ( response . compliance_unit_cap_remaining ) ) ;
186+
187+ // Set the outstanding balance from the response
188+ setInitialOutstandingBalance ( response . outstanding_balance || 0 ) ;
189+
190+ // Update form data with the full compliance data from the response
191+ setFormData ( ( prev : Partial < ApplyComplianceUnitsFormData > ) => {
192+ // Create a clean data object for the compliance phase
193+ const cleanFormData = {
194+ bccr_holding_account_id : prev . bccr_holding_account_id ,
195+ bccr_trading_name : prev . bccr_trading_name ,
196+ ...response ,
197+ } ;
198+
199+ setCurrentPhase ( "compliance_data" ) ;
200+ return cleanFormData ;
201+ } ) ;
202+
203+ setStatus ( "submitted" ) ;
205204 } ;
206205
207206 // Second submission: Apply the compliance units
208207 const handleApply = async ( ) => {
209208 setStatus ( "applying" ) ;
209+ setErrors ( undefined ) ;
210+
210211 const response = await actionHandler (
211212 `compliance/bccr/accounts/${
212213 ( formData as ApplyComplianceUnitsFormData ) ?. bccr_holding_account_id
@@ -217,13 +218,14 @@ export default function ApplyComplianceUnitsComponent({
217218 body : JSON . stringify ( formData ) ,
218219 } ,
219220 ) ;
220- if ( ! response || response . error ) {
221+
222+ const isSuccess = handleApiResponse ( response , setErrors ) ;
223+ if ( ! isSuccess ) {
221224 setStatus ( "submitted" ) ;
222- setErrors ( [ response . error || "Failed to apply compliance units." ] ) ;
223- } else {
224- setStatus ( "applied" ) ;
225- setErrors ( undefined ) ;
225+ return ;
226226 }
227+
228+ setStatus ( "applied" ) ;
227229 } ;
228230
229231 // Check if we should show the Submit button (when trading name is received)
@@ -318,11 +320,37 @@ export default function ApplyComplianceUnitsComponent({
318320 ...response ,
319321 } ) ) ;
320322 setCurrentPhase ( "confirmation" ) ;
323+ setErrors ( undefined ) ;
321324 } else {
322325 setCurrentPhase ( "initial" ) ;
323326 }
324327 } ,
325- onError : setErrors ,
328+ onError : ( errs ?: any ) => {
329+ if ( ! errs || ( Array . isArray ( errs ) && errs . length === 0 ) ) {
330+ setErrors ( undefined ) ;
331+ return ;
332+ }
333+ const rawErrors = Array . isArray ( errs ) ? errs : [ errs ] ;
334+ const formatted = rawErrors . map ( ( err ) => {
335+ if ( typeof err === "string" ) {
336+ return {
337+ key : err ,
338+ error : { severity : "Error" , message : err } ,
339+ } ;
340+ }
341+ if ( err && ! err . error ) {
342+ return {
343+ key : err . key || "error" ,
344+ error : {
345+ severity : "Error" ,
346+ message : err . message || String ( err ) ,
347+ } ,
348+ } ;
349+ }
350+ return err ;
351+ } ) ;
352+ setErrors ( formatted as any ) ;
353+ } ,
326354 complianceLimitStatus,
327355 isApplied : status === "applied" ,
328356 maxCreditUsagePercentage : ( formData as ApplyComplianceUnitsFormData )
@@ -336,7 +364,7 @@ export default function ApplyComplianceUnitsComponent({
336364 < ApplyComplianceUnitsAlertNote />
337365 </ div >
338366 ) }
339- < FormAlerts errors = { errors } />
367+ { renderedErrors }
340368 < ComplianceStepButtons
341369 backButtonText = { status === "applied" ? "Back" : "Cancel" }
342370 onBackClick = { ( ) =>
0 commit comments