diff --git a/app/Http/Controllers/Api/PostController.php b/app/Http/Controllers/Api/PostController.php
index c662d53d..bddaa328 100644
--- a/app/Http/Controllers/Api/PostController.php
+++ b/app/Http/Controllers/Api/PostController.php
@@ -69,7 +69,7 @@ public function update(UpdatePostRequest $request, Post $post): PostResource|Jso
if (data_get($result, 'action') === PostAction::Finalized) {
return response()->json(
- ['message' => 'Cannot edit a published post.'],
+ ['message' => 'Cannot edit a post in a terminal state.'],
Response::HTTP_UNPROCESSABLE_ENTITY
);
}
diff --git a/app/Mcp/Tools/Post/UpdatePostTool.php b/app/Mcp/Tools/Post/UpdatePostTool.php
index 6062a722..d855c1b0 100644
--- a/app/Mcp/Tools/Post/UpdatePostTool.php
+++ b/app/Mcp/Tools/Post/UpdatePostTool.php
@@ -55,7 +55,7 @@ public function handle(Request $request): Response|ResponseFactory
$result = UpdatePost::execute($workspace, $post, $payload);
if (data_get($result, 'action') === PostAction::Finalized) {
- return Response::error('Cannot edit a published post.');
+ return Response::error('Cannot edit a post in a terminal state.');
}
/** @var Post $updated */
diff --git a/app/Services/Social/FacebookPublisher.php b/app/Services/Social/FacebookPublisher.php
index fdb7519b..51e351ef 100644
--- a/app/Services/Social/FacebookPublisher.php
+++ b/app/Services/Social/FacebookPublisher.php
@@ -49,7 +49,7 @@ private function publishPost(string $pageId, string $accessToken, ?string $conte
{
// Text only post
if ($media->isEmpty()) {
- if (empty($content)) {
+ if ($content === null || $content === '') {
throw new \Exception('Facebook text posts require content. Please add text to your post.');
}
@@ -107,7 +107,7 @@ private function publishSingleImagePost(string $pageId, string $accessToken, ?st
'access_token' => $accessToken,
];
- if (! empty($content)) {
+ if ($content !== null && $content !== '') {
$payload['message'] = $content;
}
@@ -167,7 +167,7 @@ private function publishMultiImagePost(string $pageId, string $accessToken, ?str
'access_token' => $accessToken,
];
- if (! empty($content)) {
+ if ($content !== null && $content !== '') {
$postData['message'] = $content;
}
@@ -201,7 +201,7 @@ private function publishVideoPost(string $pageId, string $accessToken, ?string $
'access_token' => $accessToken,
];
- if (! empty($content)) {
+ if ($content !== null && $content !== '') {
$payload['description'] = $content;
}
@@ -306,7 +306,7 @@ private function publishReel(string $pageId, string $accessToken, ?string $conte
'access_token' => $accessToken,
];
- if (! empty($content)) {
+ if ($content !== null && $content !== '') {
$finishPayload['description'] = $content;
}
diff --git a/resources/js/pages/posts/Edit.vue b/resources/js/pages/posts/Edit.vue
index d312cab1..1582bdda 100644
--- a/resources/js/pages/posts/Edit.vue
+++ b/resources/js/pages/posts/Edit.vue
@@ -20,7 +20,7 @@ import { ContentType } from '@/enums/content-type';
import { Platform } from '@/enums/platform';
import { PostStatus } from '@/types/post';
import AppLayout from '@/layouts/AppLayout.vue';
-import { destroy as destroyPost, update as updatePost } from '@/routes/app/posts';
+import { destroy as destroyPost, show as showPost, update as updatePost } from '@/routes/app/posts';
import type { PinterestBoard } from '@/types';
interface MediaItem {
@@ -514,12 +514,15 @@ const unschedulePost = () => {
submit(PostStatus.Draft);
};
-// Echo: listen for real-time platform status updates.
-// Event fires when any post_platform completes publishing (success or fail).
-// Full reload of the post prop so the new status + post_platforms propagate and
-// the overlay dismisses.
usePostEcho(post.value.id, '.post.platform.status.updated', () => {
- router.reload({ only: ['post'] });
+ router.reload({
+ only: ['post'],
+ onSuccess: () => {
+ if (READONLY_STATUSES.includes(post.value.status)) {
+ router.visit(showPost.url(post.value.id));
+ }
+ },
+ });
});
diff --git a/resources/js/pages/posts/Index.vue b/resources/js/pages/posts/Index.vue
index ad70d20b..f99ac13a 100644
--- a/resources/js/pages/posts/Index.vue
+++ b/resources/js/pages/posts/Index.vue
@@ -138,7 +138,9 @@ const getPostPreview = (post: Post): string =>
post.content?.trim() || trans('calendar.no_content');
const EDITABLE_STATUSES: readonly string[] = [PostStatus.Draft, PostStatus.Scheduled];
+const DELETABLE_STATUSES: readonly string[] = [PostStatus.Draft, PostStatus.Scheduled, PostStatus.Failed];
const canEdit = (post: Post): boolean => EDITABLE_STATUSES.includes(post.status);
+const canDelete = (post: Post): boolean => DELETABLE_STATUSES.includes(post.status);
const postUrl = (post: Post): string =>
canEdit(post) ? editPost.url(post.id) : showPost.url(post.id);
@@ -303,7 +305,7 @@ useWorkspaceEcho(
{{ $t('posts.actions.copy_id') }}
-
+
user)
->tool(UpdatePostTool::class, ['post_id' => $post->id, 'content' => 'x']);
- $response->assertHasErrors(['Cannot edit a published post.']);
+ $response->assertHasErrors(['Cannot edit a post in a terminal state.']);
})->with([
PostStatus::Published,
PostStatus::PartiallyPublished,