85 lines
2.2 KiB
TypeScript
85 lines
2.2 KiB
TypeScript
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
|
|
|
|
import { createPostRecord, listPosts, type PostRecord } from './postsService';
|
|
|
|
type CreatePostInput = {
|
|
title: string;
|
|
content: string;
|
|
};
|
|
|
|
type PostsState = {
|
|
items: PostRecord[];
|
|
fetchStatus: 'idle' | 'loading' | 'failed';
|
|
createStatus: 'idle' | 'loading' | 'failed';
|
|
message: string | null;
|
|
error: string | null;
|
|
};
|
|
|
|
const initialState: PostsState = {
|
|
items: [],
|
|
fetchStatus: 'idle',
|
|
createStatus: 'idle',
|
|
message: null,
|
|
error: null,
|
|
};
|
|
|
|
export const fetchPosts = createAsyncThunk('posts/fetchPosts', async () => listPosts());
|
|
|
|
export const createPost = createAsyncThunk<
|
|
PostRecord,
|
|
CreatePostInput,
|
|
{ rejectValue: string }
|
|
>('posts/createPost', async (payload, { rejectWithValue }) => {
|
|
try {
|
|
return await createPostRecord(payload);
|
|
} catch (error) {
|
|
const message = error instanceof Error ? error.message : 'Unable to create post';
|
|
return rejectWithValue(message);
|
|
}
|
|
});
|
|
|
|
const postsSlice = createSlice({
|
|
name: 'posts',
|
|
initialState,
|
|
reducers: {
|
|
clearPostMessage(state) {
|
|
state.message = null;
|
|
state.error = null;
|
|
state.createStatus = 'idle';
|
|
},
|
|
},
|
|
extraReducers: (builder) => {
|
|
builder
|
|
.addCase(fetchPosts.pending, (state) => {
|
|
state.fetchStatus = 'loading';
|
|
state.error = null;
|
|
})
|
|
.addCase(fetchPosts.fulfilled, (state, action) => {
|
|
state.fetchStatus = 'idle';
|
|
state.items = action.payload;
|
|
})
|
|
.addCase(fetchPosts.rejected, (state) => {
|
|
state.fetchStatus = 'failed';
|
|
state.error = 'Unable to load posts';
|
|
})
|
|
.addCase(createPost.pending, (state) => {
|
|
state.createStatus = 'loading';
|
|
state.message = null;
|
|
state.error = null;
|
|
})
|
|
.addCase(createPost.fulfilled, (state, action) => {
|
|
state.createStatus = 'idle';
|
|
state.items = [action.payload, ...state.items];
|
|
state.message = 'Post created successfully';
|
|
})
|
|
.addCase(createPost.rejected, (state, action) => {
|
|
state.createStatus = 'failed';
|
|
state.error = action.payload ?? 'Unable to create post';
|
|
});
|
|
},
|
|
});
|
|
|
|
export const { clearPostMessage } = postsSlice.actions;
|
|
|
|
export default postsSlice.reducer;
|