@@ -5,15 +5,28 @@ import { Button, Container, Form, Header, Message } from 'semantic-ui-react';
55
66import { useEnvironment } from '../../hooks' ;
77
8+ type RowValidationError = {
9+ row : number ;
10+ code : string ;
11+ message : string ;
12+ column ?: string ;
13+ } ;
14+
15+ type ImportErrorResponse = {
16+ success : false ;
17+ type : string ;
18+ message ?: string ;
19+ errors ?: RowValidationError [ ] ;
20+ } ;
21+
822export const MyOpenCRE = ( ) => {
923 const { apiUrl } = useEnvironment ( ) ;
1024
11- // Upload enabled only for local/dev
1225 const isUploadEnabled = apiUrl !== '/rest/v1' ;
1326
1427 const [ selectedFile , setSelectedFile ] = useState < File | null > ( null ) ;
1528 const [ loading , setLoading ] = useState ( false ) ;
16- const [ error , setError ] = useState < string | null > ( null ) ;
29+ const [ error , setError ] = useState < ImportErrorResponse | null > ( null ) ;
1730 const [ success , setSuccess ] = useState < any | null > ( null ) ;
1831
1932 /* ------------------ CSV DOWNLOAD ------------------ */
@@ -57,7 +70,11 @@ export const MyOpenCRE = () => {
5770 const file = e . target . files [ 0 ] ;
5871
5972 if ( ! file . name . toLowerCase ( ) . endsWith ( '.csv' ) ) {
60- setError ( 'Please upload a valid CSV file.' ) ;
73+ setError ( {
74+ success : false ,
75+ type : 'FILE_ERROR' ,
76+ message : 'Please upload a valid CSV file.' ,
77+ } ) ;
6178 e . target . value = '' ;
6279 setSelectedFile ( null ) ;
6380 return ;
@@ -90,21 +107,49 @@ export const MyOpenCRE = () => {
90107 ) ;
91108 }
92109
110+ const payload = await response . json ( ) ;
111+
93112 if ( ! response . ok ) {
94- const text = await response . text ( ) ;
95- throw new Error ( text || 'CSV import failed' ) ;
113+ setError ( payload ) ;
114+ return ;
96115 }
97116
98- const result = await response . json ( ) ;
99- setSuccess ( result ) ;
117+ setSuccess ( payload ) ;
100118 setSelectedFile ( null ) ;
101119 } catch ( err : any ) {
102- setError ( err . message || 'Unexpected error during import' ) ;
120+ setError ( {
121+ success : false ,
122+ type : 'CLIENT_ERROR' ,
123+ message : err . message || 'Unexpected error during import' ,
124+ } ) ;
103125 } finally {
104126 setLoading ( false ) ;
105127 }
106128 } ;
107129
130+ /* ------------------ ERROR RENDERING ------------------ */
131+
132+ const renderErrorMessage = ( ) => {
133+ if ( ! error ) return null ;
134+
135+ if ( error . errors && error . errors . length > 0 ) {
136+ return (
137+ < Message negative >
138+ < strong > Import failed due to validation errors</ strong >
139+ < ul >
140+ { error . errors . map ( ( e , idx ) => (
141+ < li key = { idx } >
142+ < strong > Row { e . row } :</ strong > { e . message }
143+ </ li >
144+ ) ) }
145+ </ ul >
146+ </ Message >
147+ ) ;
148+ }
149+
150+ return < Message negative > { error . message || 'Import failed' } </ Message > ;
151+ } ;
152+
108153 /* ------------------ UI ------------------ */
109154
110155 return (
@@ -140,7 +185,7 @@ export const MyOpenCRE = () => {
140185 </ Message >
141186 ) }
142187
143- { error && < Message negative > { error } </ Message > }
188+ { renderErrorMessage ( ) }
144189
145190 { success && (
146191 < Message positive >
0 commit comments