diff --git a/frontend/src/templates/ContentViewTemplate.tsx b/frontend/src/templates/ContentViewTemplate.tsx
index 4defd704..8e54e8a5 100644
--- a/frontend/src/templates/ContentViewTemplate.tsx
+++ b/frontend/src/templates/ContentViewTemplate.tsx
@@ -21,6 +21,7 @@ import { ArrowLeftIcon, CalendarIcon, TagIcon, FileTextIcon, CheckCircleIcon, XC
import { useNavigate } from 'react-router-dom';
import Button from '../components/ui/button/Button';
import { useToast } from '../components/ui/toast/ToastContainer';
+import { formatDateTime, formatDateTimeLocal, getDatePartsInAccountTimezone, toUtcISOStringFromLocal } from '../utils/date';
interface ContentViewTemplateProps {
content: Content | null;
@@ -632,16 +633,17 @@ export default function ContentViewTemplate({ content, loading, onBack }: Conten
// Initialize schedule datetime when content loads
useEffect(() => {
if (content?.scheduled_publish_at) {
- // Convert ISO string to datetime-local format (YYYY-MM-DDTHH:mm)
- const date = new Date(content.scheduled_publish_at);
- const localDateTime = date.toISOString().slice(0, 16);
+ const localDateTime = formatDateTimeLocal(content.scheduled_publish_at);
setScheduleDateTime(localDateTime);
} else if (content?.site_status === 'failed') {
- // Default to tomorrow at 9 AM for failed items without a schedule
- const tomorrow = new Date();
- tomorrow.setDate(tomorrow.getDate() + 1);
- tomorrow.setHours(9, 0, 0, 0);
- setScheduleDateTime(tomorrow.toISOString().slice(0, 16));
+ // Default to tomorrow at 9 AM (account timezone) for failed items without a schedule
+ const todayParts = getDatePartsInAccountTimezone(new Date());
+ const baseDate = new Date(Date.UTC(todayParts.year, todayParts.month - 1, todayParts.day));
+ baseDate.setUTCDate(baseDate.getUTCDate() + 1);
+ const year = baseDate.getUTCFullYear();
+ const month = String(baseDate.getUTCMonth() + 1).padStart(2, '0');
+ const day = String(baseDate.getUTCDate()).padStart(2, '0');
+ setScheduleDateTime(`${year}-${month}-${day}T09:00`);
}
}, [content?.scheduled_publish_at, content?.site_status]);
@@ -651,7 +653,11 @@ export default function ContentViewTemplate({ content, loading, onBack }: Conten
setIsUpdatingSchedule(true);
try {
- const isoDateTime = new Date(scheduleDateTime).toISOString();
+ const isoDateTime = toUtcISOStringFromLocal(scheduleDateTime);
+ if (!isoDateTime) {
+ toast.error('Invalid schedule date/time.');
+ return;
+ }
// Use reschedule endpoint for failed items, schedule endpoint for scheduled items
const endpoint = content.site_status === 'failed'
@@ -875,20 +881,6 @@ export default function ContentViewTemplate({ content, loading, onBack }: Conten
);
}
- const formatDate = (dateString: string) => {
- try {
- return new Date(dateString).toLocaleDateString('en-US', {
- year: 'numeric',
- month: 'long',
- day: 'numeric',
- hour: '2-digit',
- minute: '2-digit',
- });
- } catch {
- return dateString;
- }
- };
-
const getStatusColor = (status: string) => {
const statusLower = status.toLowerCase();
if (statusLower === 'generated' || statusLower === 'published' || statusLower === 'complete') {
@@ -974,7 +966,7 @@ export default function ContentViewTemplate({ content, loading, onBack }: Conten
Generated
- {formatDate(content.generated_at)}
+ {formatDateTime(content.generated_at)}
@@ -984,7 +976,7 @@ export default function ContentViewTemplate({ content, loading, onBack }: Conten
Last Updated
- {formatDate(content.updated_at)}
+ {formatDateTime(content.updated_at)}
@@ -1225,14 +1217,16 @@ export default function ContentViewTemplate({ content, loading, onBack }: Conten
setIsEditingSchedule(false);
// Reset to original value or tomorrow if failed
if (content.scheduled_publish_at) {
- const date = new Date(content.scheduled_publish_at);
- setScheduleDateTime(date.toISOString().slice(0, 16));
+ setScheduleDateTime(formatDateTimeLocal(content.scheduled_publish_at));
} else if (content.site_status === 'failed') {
// Default to tomorrow for failed items
- const tomorrow = new Date();
- tomorrow.setDate(tomorrow.getDate() + 1);
- tomorrow.setHours(9, 0, 0, 0);
- setScheduleDateTime(tomorrow.toISOString().slice(0, 16));
+ const todayParts = getDatePartsInAccountTimezone(new Date());
+ const baseDate = new Date(Date.UTC(todayParts.year, todayParts.month - 1, todayParts.day));
+ baseDate.setUTCDate(baseDate.getUTCDate() + 1);
+ const year = baseDate.getUTCFullYear();
+ const month = String(baseDate.getUTCMonth() + 1).padStart(2, '0');
+ const day = String(baseDate.getUTCDate()).padStart(2, '0');
+ setScheduleDateTime(`${year}-${month}-${day}T09:00`);
}
}}
>
@@ -1243,10 +1237,10 @@ export default function ContentViewTemplate({ content, loading, onBack }: Conten
<>
{content.site_status === 'failed' && (
- content.scheduled_publish_at ? `Was scheduled: ${formatDate(content.scheduled_publish_at)}` : 'Not scheduled'
+ content.scheduled_publish_at ? `Was scheduled: ${formatDateTime(content.scheduled_publish_at)}` : 'Not scheduled'
)}
{content.site_status === 'scheduled' && (
- content.scheduled_publish_at ? formatDate(content.scheduled_publish_at) : ''
+ content.scheduled_publish_at ? formatDateTime(content.scheduled_publish_at) : ''
)}