add error toasts

This commit is contained in:
Виталий Лавшонок
2025-12-10 01:33:16 +03:00
parent 02de330034
commit d1a46435c4
17 changed files with 508 additions and 278 deletions

View File

@@ -1,5 +1,6 @@
import { createSlice, createAsyncThunk, PayloadAction } from '@reduxjs/toolkit';
import axios from '../../axios';
import { toastError } from '../../lib/toastNotification';
// =====================
// Типы
@@ -280,10 +281,7 @@ export const fetchParticipatingContests = createAsyncThunk(
);
return response.data;
} catch (err: any) {
return rejectWithValue(
err.response?.data?.message ||
'Failed to fetch participating contests',
);
return rejectWithValue(err.response?.data);
}
},
);
@@ -297,9 +295,7 @@ export const fetchMySubmissions = createAsyncThunk(
);
return response.data;
} catch (err: any) {
return rejectWithValue(
err.response?.data?.message || 'Failed to fetch my submissions',
);
return rejectWithValue(err.response?.data);
}
},
);
@@ -321,9 +317,7 @@ export const fetchContests = createAsyncThunk(
});
return response.data;
} catch (err: any) {
return rejectWithValue(
err.response?.data?.message || 'Failed to fetch contests',
);
return rejectWithValue(err.response?.data);
}
},
);
@@ -335,9 +329,7 @@ export const fetchContestById = createAsyncThunk(
const response = await axios.get<Contest>(`/contests/${id}`);
return response.data;
} catch (err: any) {
return rejectWithValue(
err.response?.data?.message || 'Failed to fetch contest',
);
return rejectWithValue(err.response?.data);
}
},
);
@@ -352,9 +344,7 @@ export const createContest = createAsyncThunk(
);
return response.data;
} catch (err: any) {
return rejectWithValue(
err.response?.data?.message || 'Failed to create contest',
);
return rejectWithValue(err.response?.data);
}
},
);
@@ -375,9 +365,7 @@ export const updateContest = createAsyncThunk(
);
return response.data;
} catch (err: any) {
return rejectWithValue(
err.response?.data?.message || 'Failed to update contest',
);
return rejectWithValue(err.response?.data);
}
},
);
@@ -389,9 +377,7 @@ export const deleteContest = createAsyncThunk(
await axios.delete(`/contests/${contestId}`);
return contestId;
} catch (err: any) {
return rejectWithValue(
err.response?.data?.message || 'Failed to delete contest',
);
return rejectWithValue(err.response?.data);
}
},
);
@@ -403,9 +389,7 @@ export const fetchMyContests = createAsyncThunk(
const response = await axios.get<Contest[]>('/contests/my');
return response.data;
} catch (err: any) {
return rejectWithValue(
err.response?.data?.message || 'Failed to fetch my contests',
);
return rejectWithValue(err.response?.data);
}
},
);
@@ -424,10 +408,7 @@ export const fetchRegisteredContests = createAsyncThunk(
);
return response.data;
} catch (err: any) {
return rejectWithValue(
err.response?.data?.message ||
'Failed to fetch registered contests',
);
return rejectWithValue(err.response?.data);
}
},
);
@@ -451,10 +432,7 @@ export const addOrUpdateContestMember = createAsyncThunk(
);
return { contestId, members: response.data };
} catch (err: any) {
return rejectWithValue(
err.response?.data?.message ||
'Failed to add or update contest member',
);
return rejectWithValue(err.response?.data);
}
},
);
@@ -470,10 +448,7 @@ export const deleteContestMember = createAsyncThunk(
await axios.delete(`/contests/${contestId}/members/${memberId}`);
return { contestId, memberId };
} catch (err: any) {
return rejectWithValue(
err.response?.data?.message ||
'Failed to delete contest member',
);
return rejectWithValue(err.response?.data);
}
},
);
@@ -488,10 +463,7 @@ export const startContestAttempt = createAsyncThunk(
);
return response.data;
} catch (err: any) {
return rejectWithValue(
err.response?.data?.message ||
'Failed to start contest attempt',
);
return rejectWithValue(err.response?.data);
}
},
);
@@ -506,9 +478,7 @@ export const fetchMyAttemptsInContest = createAsyncThunk(
);
return response.data;
} catch (err: any) {
return rejectWithValue(
err.response?.data?.message || 'Failed to fetch my attempts',
);
return rejectWithValue(err.response?.data);
}
},
);
@@ -531,10 +501,7 @@ export const fetchContestMembers = createAsyncThunk(
);
return { contestId, ...response.data };
} catch (err: any) {
return rejectWithValue(
err.response?.data?.message ||
'Failed to fetch contest members',
);
return rejectWithValue(err.response?.data);
}
},
);
@@ -549,9 +516,7 @@ export const checkContestRegistration = createAsyncThunk(
);
return { contestId, registered: response.data.registered };
} catch (err: any) {
return rejectWithValue(
err.response?.data?.message || 'Failed to check registration',
);
return rejectWithValue(err.response?.data);
}
},
);
@@ -566,10 +531,7 @@ export const fetchUpcomingEligibleContests = createAsyncThunk(
);
return response.data;
} catch (err: any) {
return rejectWithValue(
err.response?.data?.message ||
'Failed to fetch upcoming eligible contests',
);
return rejectWithValue(err.response?.data);
}
},
);
@@ -584,9 +546,7 @@ export const fetchMyAllAttempts = createAsyncThunk(
);
return response.data;
} catch (err: any) {
return rejectWithValue(
err.response?.data?.message || 'Failed to fetch my attempts',
);
return rejectWithValue(err.response?.data);
}
},
);
@@ -601,9 +561,7 @@ export const fetchMyActiveAttempt = createAsyncThunk(
);
return { contestId, attempt: response.data };
} catch (err: any) {
return rejectWithValue(
err.response?.data?.message || 'Failed to fetch active attempt',
);
return rejectWithValue(err.response?.data);
}
},
);
@@ -642,7 +600,13 @@ const contestsSlice = createSlice({
);
builder.addCase(fetchMySubmissions.rejected, (state, action: any) => {
state.fetchMySubmissions.status = 'failed';
state.fetchMySubmissions.error = action.payload;
const errors = action.payload.errors as Record<string, string[]>;
Object.values(errors).forEach((messages) => {
messages.forEach((msg) => {
toastError(msg);
});
});
});
builder.addCase(fetchContests.pending, (state) => {
@@ -658,7 +622,13 @@ const contestsSlice = createSlice({
);
builder.addCase(fetchContests.rejected, (state, action: any) => {
state.fetchContests.status = 'failed';
state.fetchContests.error = action.payload;
const errors = action.payload.errors as Record<string, string[]>;
Object.values(errors).forEach((messages) => {
messages.forEach((msg) => {
toastError(msg);
});
});
});
builder.addCase(fetchContestById.pending, (state) => {
@@ -673,7 +643,13 @@ const contestsSlice = createSlice({
);
builder.addCase(fetchContestById.rejected, (state, action: any) => {
state.fetchContestById.status = 'failed';
state.fetchContestById.error = action.payload;
const errors = action.payload.errors as Record<string, string[]>;
Object.values(errors).forEach((messages) => {
messages.forEach((msg) => {
toastError(msg);
});
});
});
builder.addCase(createContest.pending, (state) => {
@@ -688,7 +664,13 @@ const contestsSlice = createSlice({
);
builder.addCase(createContest.rejected, (state, action: any) => {
state.createContest.status = 'failed';
state.createContest.error = action.payload;
const errors = action.payload.errors as Record<string, string[]>;
Object.values(errors).forEach((messages) => {
messages.forEach((msg) => {
toastError(msg);
});
});
});
builder.addCase(updateContest.pending, (state) => {
@@ -703,7 +685,13 @@ const contestsSlice = createSlice({
);
builder.addCase(updateContest.rejected, (state, action: any) => {
state.updateContest.status = 'failed';
state.updateContest.error = action.payload;
const errors = action.payload.errors as Record<string, string[]>;
Object.values(errors).forEach((messages) => {
messages.forEach((msg) => {
toastError(msg);
});
});
});
builder.addCase(deleteContest.pending, (state) => {
@@ -725,7 +713,13 @@ const contestsSlice = createSlice({
);
builder.addCase(deleteContest.rejected, (state, action: any) => {
state.deleteContest.status = 'failed';
state.deleteContest.error = action.payload;
const errors = action.payload.errors as Record<string, string[]>;
Object.values(errors).forEach((messages) => {
messages.forEach((msg) => {
toastError(msg);
});
});
});
builder.addCase(fetchMyContests.pending, (state) => {
@@ -740,7 +734,13 @@ const contestsSlice = createSlice({
);
builder.addCase(fetchMyContests.rejected, (state, action: any) => {
state.fetchMyContests.status = 'failed';
state.fetchMyContests.error = action.payload;
const errors = action.payload.errors as Record<string, string[]>;
Object.values(errors).forEach((messages) => {
messages.forEach((msg) => {
toastError(msg);
});
});
});
builder.addCase(fetchRegisteredContests.pending, (state) => {
@@ -760,7 +760,15 @@ const contestsSlice = createSlice({
fetchRegisteredContests.rejected,
(state, action: any) => {
state.fetchRegisteredContests.status = 'failed';
state.fetchRegisteredContests.error = action.payload;
const errors = action.payload.errors as Record<
string,
string[]
>;
Object.values(errors).forEach((messages) => {
messages.forEach((msg) => {
toastError(msg);
});
});
},
);
@@ -787,7 +795,13 @@ const contestsSlice = createSlice({
);
builder.addCase(fetchContestMembers.rejected, (state, action: any) => {
state.fetchContestMembers.status = 'failed';
state.fetchContestMembers.error = action.payload;
const errors = action.payload.errors as Record<string, string[]>;
Object.values(errors).forEach((messages) => {
messages.forEach((msg) => {
toastError(msg);
});
});
});
builder.addCase(addOrUpdateContestMember.pending, (state) => {
@@ -800,7 +814,15 @@ const contestsSlice = createSlice({
addOrUpdateContestMember.rejected,
(state, action: any) => {
state.addOrUpdateMember.status = 'failed';
state.addOrUpdateMember.error = action.payload;
const errors = action.payload.errors as Record<
string,
string[]
>;
Object.values(errors).forEach((messages) => {
messages.forEach((msg) => {
toastError(msg);
});
});
},
);
@@ -812,7 +834,13 @@ const contestsSlice = createSlice({
});
builder.addCase(deleteContestMember.rejected, (state, action: any) => {
state.deleteContestMember.status = 'failed';
state.deleteContestMember.error = action.payload;
const errors = action.payload.errors as Record<string, string[]>;
Object.values(errors).forEach((messages) => {
messages.forEach((msg) => {
toastError(msg);
});
});
});
builder.addCase(startContestAttempt.pending, (state) => {
@@ -827,7 +855,13 @@ const contestsSlice = createSlice({
);
builder.addCase(startContestAttempt.rejected, (state, action: any) => {
state.startAttempt.status = 'failed';
state.startAttempt.error = action.payload;
const errors = action.payload.errors as Record<string, string[]>;
Object.values(errors).forEach((messages) => {
messages.forEach((msg) => {
toastError(msg);
});
});
});
builder.addCase(fetchMyAttemptsInContest.pending, (state) => {
@@ -844,7 +878,15 @@ const contestsSlice = createSlice({
fetchMyAttemptsInContest.rejected,
(state, action: any) => {
state.fetchMyAttemptsInContest.status = 'failed';
state.fetchMyAttemptsInContest.error = action.payload;
const errors = action.payload.errors as Record<
string,
string[]
>;
Object.values(errors).forEach((messages) => {
messages.forEach((msg) => {
toastError(msg);
});
});
},
);
@@ -860,7 +902,13 @@ const contestsSlice = createSlice({
);
builder.addCase(fetchMyAllAttempts.rejected, (state, action: any) => {
state.fetchMyAllAttempts.status = 'failed';
state.fetchMyAllAttempts.error = action.payload;
const errors = action.payload.errors as Record<string, string[]>;
Object.values(errors).forEach((messages) => {
messages.forEach((msg) => {
toastError(msg);
});
});
});
builder.addCase(fetchMyActiveAttempt.pending, (state) => {
@@ -881,7 +929,13 @@ const contestsSlice = createSlice({
);
builder.addCase(fetchMyActiveAttempt.rejected, (state, action: any) => {
state.fetchMyActiveAttempt.status = 'failed';
state.fetchMyActiveAttempt.error = action.payload;
const errors = action.payload.errors as Record<string, string[]>;
Object.values(errors).forEach((messages) => {
messages.forEach((msg) => {
toastError(msg);
});
});
});
builder.addCase(checkContestRegistration.pending, (state) => {
@@ -904,7 +958,15 @@ const contestsSlice = createSlice({
checkContestRegistration.rejected,
(state, action: any) => {
state.checkRegistration.status = 'failed';
state.checkRegistration.error = action.payload;
const errors = action.payload.errors as Record<
string,
string[]
>;
Object.values(errors).forEach((messages) => {
messages.forEach((msg) => {
toastError(msg);
});
});
},
);
@@ -922,7 +984,15 @@ const contestsSlice = createSlice({
fetchUpcomingEligibleContests.rejected,
(state, action: any) => {
state.fetchUpcomingEligible.status = 'failed';
state.fetchUpcomingEligible.error = action.payload;
const errors = action.payload.errors as Record<
string,
string[]
>;
Object.values(errors).forEach((messages) => {
messages.forEach((msg) => {
toastError(msg);
});
});
},
);
@@ -944,7 +1014,15 @@ const contestsSlice = createSlice({
fetchParticipatingContests.rejected,
(state, action: any) => {
state.fetchParticipating.status = 'failed';
state.fetchParticipating.error = action.payload;
const errors = action.payload.errors as Record<
string,
string[]
>;
Object.values(errors).forEach((messages) => {
messages.forEach((msg) => {
toastError(msg);
});
});
},
);
},