11import { createSlice , createAsyncThunk } from '@reduxjs/toolkit' ;
2- import { HttpClient , getDataAPIUrl } from '../../utils/httpClient' ;
2+ import { HttpClient } from '../../utils/httpClient' ;
33import SearchState from './SearchState' ;
44import Sample from '../../types/Sample' ;
5+ import { RootState } from '../store' ;
56
67// Define the delay function
78const delay = ( ms : number | undefined ) => new Promise ( resolve => setTimeout ( resolve , ms ) ) ;
89
910// async search total samples
1011export const getTotalSamplesAsync = createAsyncThunk < number > ( 'search/getTotalSamples' , async ( ) => {
11- const response = await HttpClient . get ( `${ getDataAPIUrl ( ) } countSamples` , {
12- withCredentials : false ,
12+ const response = await HttpClient . get ( `./api/countSamples` , {
1313 headers : {
1414 'Content-Type' : 'application/json' ,
1515 'Accept' : 'application/json' ,
@@ -20,8 +20,7 @@ export const getTotalSamplesAsync = createAsyncThunk<number>('search/getTotalSam
2020
2121// async list all samples
2222export const getAllSamplesAsync = createAsyncThunk < Sample [ ] > ( 'search/getAllSamplesAsync' , async ( ) => {
23- const response = await HttpClient . get ( `${ getDataAPIUrl ( ) } samples` , {
24- withCredentials : false ,
23+ const response = await HttpClient . get ( `./api/samples` , {
2524 headers : {
2625 'Content-Type' : 'application/json' ,
2726 'Accept' : 'application/json' ,
@@ -32,8 +31,7 @@ export const getAllSamplesAsync = createAsyncThunk<Sample[]>('search/getAllSampl
3231
3332// async list latest samples
3433export const getLatestSamplesAsync = createAsyncThunk < Sample [ ] > ( 'search/getLatestSamples' , async ( ) => {
35- const response = await HttpClient . get ( `${ getDataAPIUrl ( ) } latestSamples` , {
36- withCredentials : false ,
34+ const response = await HttpClient . get ( `./api/latestSamples` , {
3735 headers : {
3836 'Content-Type' : 'application/json' ,
3937 'Accept' : 'application/json' ,
@@ -44,8 +42,7 @@ export const getLatestSamplesAsync = createAsyncThunk<Sample[]>('search/getLates
4442
4543// async search specific samples
4644export const searchSamplesAsync = createAsyncThunk < Sample [ ] , string > ( 'search/searchSamplesAsync' , async ( query : string ) => {
47- const response = await HttpClient . get ( `${ getDataAPIUrl ( ) } findSamples?text=${ query } ` , {
48- withCredentials : false ,
45+ const response = await HttpClient . get ( `./api/findSamples?text=${ query } ` , {
4946 headers : {
5047 'Content-Type' : 'application/json' ,
5148 'Accept' : 'application/json' ,
@@ -55,15 +52,23 @@ export const searchSamplesAsync = createAsyncThunk<Sample[], string>('search/sea
5552} ) ;
5653
5754// delete a sample
58- export const deleteSampleAsync = createAsyncThunk < number , string > ( 'search/deleteSampleAsync' , async ( id : string ) => {
55+ export const deleteSampleAsync = createAsyncThunk < number , string , { state : RootState } > ( 'search/deleteSampleAsync' , async ( id : string , { getState } ) => {
56+ const state = getState ( ) ;
57+ const isAdmin = state . user . isAdmin ;
58+
59+ const headers : Record < string , string > = {
60+ 'Content-Type' : 'application/json' ,
61+ 'Accept' : 'application/json' ,
62+ } ;
63+
64+ if ( isAdmin ) {
65+ headers [ 'X-MS-API-ROLE' ] = 'admin' ;
66+ }
67+
5968 await delay ( 1000 ) . then ( async ( ) => { // for better user experience
60- await HttpClient . delete ( `${ getDataAPIUrl ( ) } deleteSample` , {
69+ await HttpClient . delete ( `./api/ deleteSample` , {
6170 data : { id : id , url : null } ,
62- withCredentials : false ,
63- headers : {
64- 'Content-Type' : 'application/json' ,
65- 'Accept' : 'application/json' ,
66- }
71+ headers
6772 } ) ;
6873
6974 } ) ;
@@ -72,8 +77,7 @@ export const deleteSampleAsync = createAsyncThunk<number, string>('search/delete
7277
7378// get the details
7479export const getSampleDetailsAsync = createAsyncThunk < Sample , string > ( 'search/getSampleDetailsAsync' , async ( id : string ) => {
75- const response = await HttpClient . post ( `${ getDataAPIUrl ( ) } sampleDetails` , { id : id , url : null } , {
76- // withCredentials: false,
80+ const response = await HttpClient . post ( `./api/sampleDetails` , { id : id , url : null } , {
7781 headers : {
7882 'Content-Type' : 'application/json' ,
7983 'Accept' : 'application/json' ,
@@ -83,28 +87,28 @@ export const getSampleDetailsAsync = createAsyncThunk<Sample, string>('search/ge
8387 return JSON . parse ( sample ) ;
8488} ) ;
8589
86- // create a sample
87- export const createSampleAsync = createAsyncThunk < number , string > ( 'search/createSampleAsync' , async ( payload : string ) => {
88- const response = await HttpClient . post ( `${ getDataAPIUrl ( ) } createSample` , { payload : payload } , {
89- // withCredentials: false,
90- headers : {
91- 'Content-Type' : 'application/json' ,
92- 'Accept' : 'application/json' ,
93- }
94- } ) ;
95- return response . data ;
96- } ) ;
90+ // upsert a sample (create or update)
91+ export const upsertSampleAsync = createAsyncThunk <
92+ { id : number ; isCreate : boolean } ,
93+ { payload : string ; isCreate : boolean } ,
94+ { state : RootState }
95+ > ( 'search/upsertSampleAsync' , async ( { payload, isCreate } , { getState } ) => {
96+ const state = getState ( ) ;
97+ const isAdmin = state . user . isAdmin ;
98+
99+ const headers : Record < string , string > = {
100+ 'Content-Type' : 'application/json' ,
101+ 'Accept' : 'application/json' ,
102+ } ;
103+
104+ if ( isAdmin ) {
105+ headers [ 'X-MS-API-ROLE' ] = 'admin' ;
106+ }
97107
98- // update a sample
99- export const updateSampleAsync = createAsyncThunk < number , string > ( 'search/updateSampleAsync' , async ( payload :string ) => {
100- const response = await HttpClient . post ( `${ getDataAPIUrl ( ) } createSample` , { payload : payload } , {
101- // withCredentials: false,
102- headers : {
103- 'Content-Type' : 'application/json' ,
104- 'Accept' : 'application/json' ,
105- }
108+ const response = await HttpClient . post ( `./api/upsertSample` , { payload : payload } , {
109+ headers
106110 } ) ;
107- return response . data ;
111+ return { id : response . data , isCreate } ;
108112} ) ;
109113
110114
@@ -128,15 +132,11 @@ const initialState: SearchState = {
128132 error : undefined ,
129133 sample : undefined
130134 } ,
131- createSample : {
132- status : 'idle' ,
133- error : undefined ,
134- id : 0
135- } ,
136- updateSample : {
135+ upsertSample : {
137136 status : 'idle' ,
138137 error : undefined ,
139- id : 0
138+ id : 0 ,
139+ isCreate : false
140140 }
141141} ;
142142
@@ -150,11 +150,8 @@ const SearchSlice = createSlice({
150150 resetDeleteState : ( state ) => {
151151 state . delete = initialState . delete ;
152152 } ,
153- resetUpdateState : ( state ) => {
154- state . updateSample = initialState . updateSample ;
155- } ,
156- resetCreateState : ( state ) => {
157- state . createSample = initialState . createSample ;
153+ resetUpsertState : ( state ) => {
154+ state . upsertSample = initialState . upsertSample ;
158155 } ,
159156 resetSampleDetailsState : ( state ) => {
160157 state . sampleDetails = initialState . sampleDetails ;
@@ -238,35 +235,33 @@ const SearchSlice = createSlice({
238235 state . sampleDetails . status = 'failed' ;
239236 state . sampleDetails . error = action . error . message ;
240237 } )
241- // create sample
242- . addCase ( createSampleAsync . pending , ( state ) => {
243- state . createSample . status = 'loading'
238+ // upsert sample (create or update)
239+ . addCase ( upsertSampleAsync . pending , ( state ) => {
240+ state . upsertSample . status = 'loading' ;
244241 } )
245- . addCase ( createSampleAsync . fulfilled , ( state , action ) => {
246- state . createSample . status = 'succeeded' ;
247- state . createSample . id = action . payload ;
248- // recount the total samples
249- state . totalSamples . total = state . totalSamples . total + 1 ;
242+ . addCase ( upsertSampleAsync . fulfilled , ( state , action ) => {
243+ state . upsertSample . status = 'succeeded' ;
244+ state . upsertSample . id = action . payload . id ;
245+ state . upsertSample . isCreate = action . payload . isCreate ;
246+ // increment total samples count only if it's a create operation
247+ if ( action . payload . isCreate ) {
248+ state . totalSamples . total = state . totalSamples . total + 1 ;
249+ }
250250 } )
251- . addCase ( createSampleAsync . rejected , ( state , action ) => {
252- state . createSample . status = 'failed' ;
253- state . createSample . error = action . error . message ;
254- } )
255- // update sample
256- . addCase ( updateSampleAsync . pending , ( state ) => {
257- state . updateSample . status = 'loading' ;
258- } )
259- . addCase ( updateSampleAsync . fulfilled , ( state , action ) => {
260- state . updateSample . status = 'succeeded' ;
261- state . updateSample . id = action . payload ;
262- } )
263- . addCase ( updateSampleAsync . rejected , ( state , action ) => {
264- state . updateSample . status = 'failed' ;
265- state . updateSample . error = action . error . message ;
251+ . addCase ( upsertSampleAsync . rejected , ( state , action ) => {
252+ state . upsertSample . status = 'failed' ;
253+ state . upsertSample . error = action . error . message ;
266254 } )
267255 ;
268256 }
269257} ) ;
270258
271- export const { resetSearchState, resetDeleteState, resetUpdateState, resetCreateState, resetSampleDetailsState } = SearchSlice . actions ;
259+ export const { resetSearchState, resetDeleteState, resetUpsertState, resetSampleDetailsState } = SearchSlice . actions ;
260+
261+ // Backward compatibility exports
262+ export const createSampleAsync = ( payload : string ) => upsertSampleAsync ( { payload, isCreate : true } ) ;
263+ export const updateSampleAsync = ( payload : string ) => upsertSampleAsync ( { payload, isCreate : false } ) ;
264+ export const resetCreateState = resetUpsertState ;
265+ export const resetUpdateState = resetUpsertState ;
266+
272267export default SearchSlice ;
0 commit comments