File size: 5,943 Bytes
25f22bf |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
import postService from '../../services/postService';
// Initial state
const initialState = {
items: [],
loading: false,
error: null
};
// Async thunks
export const fetchPosts = createAsyncThunk(
'posts/fetchPosts',
async (params = {}, { rejectWithValue }) => {
try {
const response = await postService.getAll(params);
return response.data.posts;
} catch (error) {
return rejectWithValue(error.response.data);
}
}
);
export const generatePost = createAsyncThunk(
'posts/generatePost',
async (_, { rejectWithValue }) => {
try {
const response = await postService.generate();
return response.data;
} catch (error) {
// Check if it's a network error or timeout
if (error.code === 'ECONNABORTED' || error.message.includes('timeout') || error.message.includes('polling timed out')) {
return rejectWithValue({
message: 'The post generation is taking longer than expected. Please check back in a few minutes as the post may still be processing on the server.'
});
}
return rejectWithValue(error.response?.data || { message: error.message });
}
}
);
export const createPost = createAsyncThunk(
'posts/createPost',
async (postData, { rejectWithValue }) => {
try {
console.log('π [PostsSlice] Creating post with data:', postData);
const response = await postService.create(postData);
console.log('π [PostsSlice] Post created successfully:', response.data);
return response.data.post;
} catch (error) {
console.error('π [PostsSlice] Failed to create post:', error.response?.data || error.message);
return rejectWithValue(error.response.data);
}
}
);
export const publishPostDirect = createAsyncThunk(
'posts/publishPostDirect',
async (publishData, { rejectWithValue }) => {
try {
console.log('π [PostsSlice] Publishing post directly to LinkedIn with data:', publishData);
const response = await postService.publishDirect(publishData);
console.log('π [PostsSlice] Post published directly to LinkedIn successfully:', response.data);
return response.data;
} catch (error) {
console.error('π [PostsSlice] Failed to publish post directly to LinkedIn:', error.response?.data || error.message);
return rejectWithValue(error.response.data);
}
}
);
export const deletePost = createAsyncThunk(
'posts/deletePost',
async (postId, { rejectWithValue }) => {
try {
const response = await postService.delete(postId);
return { ...response.data, postId };
} catch (error) {
return rejectWithValue(error.response.data);
}
}
);
// Posts slice
const postsSlice = createSlice({
name: 'posts',
initialState,
reducers: {
clearError: (state) => {
state.error = null;
},
updatePostContent: (state, action) => {
// This reducer can be used to update post content in the store
const { postId, content } = action.payload;
const postIndex = state.items.findIndex(item => item.id === postId);
if (postIndex !== -1) {
state.items[postIndex] = { ...state.items[postIndex], Text_content: content };
}
}
},
extraReducers: (builder) => {
// Fetch posts
builder
.addCase(fetchPosts.pending, (state) => {
state.loading = true;
state.error = null;
})
.addCase(fetchPosts.fulfilled, (state, action) => {
state.loading = false;
state.items = action.payload;
})
.addCase(fetchPosts.rejected, (state, action) => {
state.loading = false;
state.error = action.payload?.message || 'Failed to fetch posts';
})
// Generate post
.addCase(generatePost.pending, (state) => {
state.loading = true;
state.error = null;
})
.addCase(generatePost.fulfilled, (state, action) => {
state.loading = false;
// We don't add generated content to the list, it's just for the form
})
.addCase(generatePost.rejected, (state, action) => {
state.loading = false;
state.error = action.payload?.message || 'Failed to generate post';
})
// Create post
.addCase(createPost.pending, (state) => {
state.loading = true;
state.error = null;
})
.addCase(createPost.fulfilled, (state, action) => {
state.loading = false;
// Add the new post to the list
state.items = [...state.items, action.payload];
})
.addCase(createPost.rejected, (state, action) => {
state.loading = false;
state.error = action.payload?.message || 'Failed to create post';
})
// Publish post directly
.addCase(publishPostDirect.pending, (state) => {
state.loading = true;
state.error = null;
})
.addCase(publishPostDirect.fulfilled, (state, action) => {
state.loading = false;
// We don't need to update the state here as we'll create the post separately
})
.addCase(publishPostDirect.rejected, (state, action) => {
state.loading = false;
state.error = action.payload?.message || 'Failed to publish post';
})
// Delete post
.addCase(deletePost.pending, (state) => {
state.loading = true;
state.error = null;
})
.addCase(deletePost.fulfilled, (state, action) => {
state.loading = false;
// Remove the deleted post from the list
state.items = state.items.filter(post => post.id !== action.payload.postId);
})
.addCase(deletePost.rejected, (state, action) => {
state.loading = false;
state.error = action.payload?.message || 'Failed to delete post';
});
}
});
export const { clearError, updatePostContent } = postsSlice.actions;
export default postsSlice.reducer; |