trypost/resources/js/composables/usePostStatus.ts
Paulo Castellano d336f79059 feat(social): reschedule publish on PlatformUnavailable instead of failing
Before: a scheduled post hitting a platform outage was marked Failed —
user had to manually retry. Now the job reschedules itself for 10
minutes later and the PostPlatform shows status "Retrying". Loops
indefinitely until the platform accepts the post.

- Adds PostPlatformStatus::Retrying (existing string column, no migration)
- PublishToSocialPlatform: PlatformUnavailable catch now calls
  rescheduleForRetry() which (a) updates the row to Retrying with
  retry_count + next_attempt_at in error_context, and (b) dispatches
  itself with a 10-minute delay. updatePostStatus() naturally leaves
  the parent Post in Publishing because Retrying is neither Published
  nor Failed.
- Same treatment for the retry-refresh edge case (publisher throws
  TokenExpired, refresh subsequently fails with PlatformUnavailable).
- i18n + frontend status config updated (en, pt-BR, es) for both
  posts.status.retrying and posts.edit.status.retrying.
- Tests: 3 new tests covering the dispatched job, the edge case path,
  and retry_count increment across attempts.
2026-05-19 10:03:30 -03:00

44 lines
1.5 KiB
TypeScript

import {
IconAlertCircle,
IconCircleCheck,
IconClock,
IconFileText,
IconLoader2,
} from '@tabler/icons-vue';
import { trans } from 'laravel-vue-i18n';
type BadgeVariant = 'default' | 'secondary' | 'destructive' | 'success' | 'warning' | 'outline';
interface StatusConfig {
variant: BadgeVariant;
icon: typeof IconFileText;
label: string;
}
const CONFIGS: Record<string, Pick<StatusConfig, 'variant' | 'icon'>> = {
draft: { variant: 'outline', icon: IconFileText },
scheduled: { variant: 'default', icon: IconClock },
publishing: { variant: 'warning', icon: IconLoader2 },
retrying: { variant: 'warning', icon: IconLoader2 },
published: { variant: 'success', icon: IconCircleCheck },
partially_published: { variant: 'warning', icon: IconAlertCircle },
failed: { variant: 'destructive', icon: IconAlertCircle },
};
export const getPostStatusConfig = (status: string): StatusConfig => {
const config = CONFIGS[status] ?? CONFIGS.draft;
return { ...config, label: trans(`posts.status.${status}`) };
};
export const getPlatformStatusConfig = (status: string): StatusConfig => {
const map: Record<string, string> = {
pending: 'draft',
publishing: 'publishing',
retrying: 'retrying',
published: 'published',
failed: 'failed',
};
const key = map[status] ?? 'draft';
const config = CONFIGS[key];
return { ...config, label: trans(`posts.edit.status.${status}`) };
};