tiemzone udpate on all pages that requrie timezone updating
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
*/
|
||||
import React from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { formatDateTime } from '../../../utils/date';
|
||||
|
||||
interface StageOutput {
|
||||
stage: number;
|
||||
@@ -99,19 +100,7 @@ const MeaningfulRunHistory: React.FC<MeaningfulRunHistoryProps> = ({
|
||||
return `${minutes}m`;
|
||||
};
|
||||
|
||||
const formatDate = (dateStr: string) => {
|
||||
try {
|
||||
const date = new Date(dateStr);
|
||||
return date.toLocaleDateString('en-US', {
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit'
|
||||
});
|
||||
} catch {
|
||||
return dateStr;
|
||||
}
|
||||
};
|
||||
const formatDate = (dateStr: string) => formatDateTime(dateStr);
|
||||
|
||||
const getStatusColor = (status: string) => {
|
||||
switch (status) {
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { automationService, RunHistoryItem } from '../../services/automationService';
|
||||
import ComponentCard from '../common/ComponentCard';
|
||||
import { formatDateTime } from '../../utils/date';
|
||||
|
||||
interface RunHistoryProps {
|
||||
siteId: number;
|
||||
@@ -98,11 +99,11 @@ const RunHistory: React.FC<RunHistoryProps> = ({ siteId }) => {
|
||||
</td>
|
||||
<td className="px-4 py-3 text-sm text-gray-900 dark:text-gray-100 capitalize">{run.trigger_type || 'manual'}</td>
|
||||
<td className="px-4 py-3 text-sm text-gray-900 dark:text-gray-100">
|
||||
{run.started_at ? new Date(run.started_at).toLocaleString() : '-'}
|
||||
{run.started_at ? formatDateTime(run.started_at) : '-'}
|
||||
</td>
|
||||
<td className="px-4 py-3 text-sm text-gray-900 dark:text-gray-100">
|
||||
{run.completed_at
|
||||
? new Date(run.completed_at).toLocaleString()
|
||||
? formatDateTime(run.completed_at)
|
||||
: '-'}
|
||||
</td>
|
||||
<td className="px-4 py-3 text-sm text-gray-900 dark:text-gray-100">{run.total_credits_used || 0}</td>
|
||||
|
||||
@@ -6,6 +6,7 @@ import Input from "../form/input/InputField";
|
||||
import Checkbox from "../form/input/Checkbox";
|
||||
import Button from "../ui/button/Button";
|
||||
import { useAuthStore } from "../../store/authStore";
|
||||
import { formatDateTime } from "../../utils/date";
|
||||
|
||||
interface LogoutReason {
|
||||
code: string;
|
||||
@@ -158,7 +159,7 @@ export default function SignInForm() {
|
||||
<div className="space-y-1 text-xs font-mono text-warning-700 dark:text-warning-400">
|
||||
<div><span className="font-bold">Code:</span> {logoutReason.code}</div>
|
||||
<div><span className="font-bold">Source:</span> {logoutReason.source}</div>
|
||||
<div><span className="font-bold">Time:</span> {new Date(logoutReason.timestamp).toLocaleString()}</div>
|
||||
<div><span className="font-bold">Time:</span> {formatDateTime(logoutReason.timestamp)}</div>
|
||||
{logoutReason.context && Object.keys(logoutReason.context).length > 0 && (
|
||||
<div className="mt-2">
|
||||
<span className="font-bold">Context:</span>
|
||||
|
||||
@@ -3,6 +3,7 @@ import ComponentCard from '../../components/common/ComponentCard';
|
||||
import Badge from '../../components/ui/badge/Badge';
|
||||
import { useToast } from '../../components/ui/toast/ToastContainer';
|
||||
import { getCreditTransactions, type CreditTransaction } from '../../services/billing.api';
|
||||
import { formatDateTime } from '../../utils/date';
|
||||
|
||||
type Variant = 'card' | 'plain';
|
||||
|
||||
@@ -57,7 +58,7 @@ export default function BillingRecentTransactions({ limit = 10, variant = 'card'
|
||||
</span>
|
||||
</div>
|
||||
<div className="text-xs text-gray-500 dark:text-gray-400 mt-1">
|
||||
{new Date(transaction.created_at).toLocaleString()}
|
||||
{formatDateTime(transaction.created_at)}
|
||||
{transaction.reference_id && ` • Ref: ${transaction.reference_id}`}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -5,6 +5,7 @@ import { useBillingStore } from '../../store/billingStore';
|
||||
import { Card } from '../../components/ui/card';
|
||||
import Badge from '../../components/ui/badge/Badge';
|
||||
import { CompactPagination } from '../ui/pagination';
|
||||
import { formatDateTime } from '../../utils/date';
|
||||
|
||||
// Credit costs per operation (copied from Billing usage page)
|
||||
const CREDIT_COSTS: Record<string, { cost: number | string; description: string }> = {
|
||||
@@ -85,7 +86,7 @@ export default function BillingUsagePanel({ showOnlyActivity = false }: BillingU
|
||||
<tbody>
|
||||
{paginated.map((txn) => (
|
||||
<tr key={txn.id} className="border-b border-gray-100 dark:border-gray-800">
|
||||
<td className="py-3 px-4 text-sm text-gray-900 dark:text-white">{new Date(txn.created_at).toLocaleString()}</td>
|
||||
<td className="py-3 px-4 text-sm text-gray-900 dark:text-white">{formatDateTime(txn.created_at)}</td>
|
||||
<td className="py-3 px-4">
|
||||
<Badge variant="soft" tone={txn.amount >= 0 ? 'success' : 'danger'}>{txn.transaction_type}</Badge>
|
||||
</td>
|
||||
@@ -232,7 +233,7 @@ export default function BillingUsagePanel({ showOnlyActivity = false }: BillingU
|
||||
<tbody>
|
||||
{paginated.map((txn) => (
|
||||
<tr key={txn.id} className="border-b border-gray-100 dark:border-gray-800">
|
||||
<td className="py-3 px-4 text-sm text-gray-900 dark:text-white">{new Date(txn.created_at).toLocaleString()}</td>
|
||||
<td className="py-3 px-4 text-sm text-gray-900 dark:text-white">{formatDateTime(txn.created_at)}</td>
|
||||
<td className="py-3 px-4">
|
||||
<Badge variant="light" color={txn.amount >= 0 ? 'success' : 'error'}>{txn.transaction_type}</Badge>
|
||||
</td>
|
||||
|
||||
@@ -3,6 +3,7 @@ import { useAuthStore } from '../../store/authStore';
|
||||
import { API_BASE_URL } from '../../services/api';
|
||||
import Button from '../ui/button/Button';
|
||||
import { CheckCircleIcon, XCircleIcon, ClockIcon, RefreshCwIcon } from '../../icons';
|
||||
import { formatDateTime } from '../../utils/date';
|
||||
|
||||
interface Payment {
|
||||
id: number;
|
||||
@@ -73,15 +74,7 @@ export default function PaymentHistory() {
|
||||
return badges[status as keyof typeof badges] || badges.pending_approval;
|
||||
};
|
||||
|
||||
const formatDate = (dateString: string) => {
|
||||
return new Date(dateString).toLocaleDateString('en-US', {
|
||||
year: 'numeric',
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
});
|
||||
};
|
||||
const formatDate = (dateString: string) => formatDateTime(dateString);
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
|
||||
@@ -2,6 +2,7 @@ import React from 'react';
|
||||
import { Modal } from '../ui/modal';
|
||||
import Button from '../ui/button/Button';
|
||||
import { ErrorIcon, CalendarIcon, BoltIcon, ExternalLinkIcon } from '../../icons';
|
||||
import { formatDateTime } from '../../utils/date';
|
||||
|
||||
interface Content {
|
||||
id: number;
|
||||
@@ -42,15 +43,7 @@ const ErrorDetailsModal: React.FC<ErrorDetailsModalProps> = ({
|
||||
const formatDate = (isoString: string | null) => {
|
||||
if (!isoString) return 'N/A';
|
||||
try {
|
||||
const date = new Date(isoString);
|
||||
return date.toLocaleString('en-US', {
|
||||
month: 'long',
|
||||
day: 'numeric',
|
||||
year: 'numeric',
|
||||
hour: 'numeric',
|
||||
minute: '2-digit',
|
||||
hour12: true
|
||||
});
|
||||
return formatDateTime(isoString);
|
||||
} catch (error) {
|
||||
return isoString;
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import ComponentCard from '../common/ComponentCard';
|
||||
import Button from '../ui/button/Button';
|
||||
import Badge from '../ui/badge/Badge';
|
||||
import { CreditBalance, Subscription, Plan } from '../../services/billing.api';
|
||||
import { formatDate } from '../../utils/date';
|
||||
import {
|
||||
CalendarIcon,
|
||||
CreditCardIcon,
|
||||
@@ -29,18 +30,9 @@ interface AccountInfoWidgetProps {
|
||||
}
|
||||
|
||||
// Helper to format dates
|
||||
function formatDate(dateStr: string | undefined): string {
|
||||
function formatAccountDate(dateStr: string | undefined): string {
|
||||
if (!dateStr) return '—';
|
||||
try {
|
||||
const date = new Date(dateStr);
|
||||
return date.toLocaleDateString('en-US', {
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
year: 'numeric'
|
||||
});
|
||||
} catch {
|
||||
return '—';
|
||||
}
|
||||
return formatDate(dateStr);
|
||||
}
|
||||
|
||||
// Helper to get days until date
|
||||
@@ -162,7 +154,7 @@ export default function AccountInfoWidget({
|
||||
</p>
|
||||
</div>
|
||||
<p className="text-base font-semibold text-gray-900 dark:text-white">
|
||||
{formatDate(periodEnd)}
|
||||
{formatAccountDate(periodEnd)}
|
||||
</p>
|
||||
{daysUntilReset !== null && daysUntilReset > 0 && (
|
||||
<p className="text-sm text-gray-400 dark:text-gray-500">
|
||||
@@ -180,7 +172,7 @@ export default function AccountInfoWidget({
|
||||
</p>
|
||||
</div>
|
||||
<p className="text-base font-semibold text-gray-900 dark:text-white">
|
||||
{formatDate(periodEnd)}
|
||||
{formatAccountDate(periodEnd)}
|
||||
</p>
|
||||
{currentPlan?.price && (
|
||||
<p className="text-sm text-gray-400 dark:text-gray-500">
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
AlertIcon,
|
||||
ClockIcon,
|
||||
} from '../../icons';
|
||||
import { formatDateTime } from '../../utils/date';
|
||||
|
||||
export interface AutomationData {
|
||||
status: 'active' | 'paused' | 'failed' | 'not_configured';
|
||||
@@ -61,16 +62,6 @@ const statusConfig = {
|
||||
},
|
||||
};
|
||||
|
||||
function formatDateTime(date: Date): string {
|
||||
return date.toLocaleDateString('en-US', {
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
hour: 'numeric',
|
||||
minute: '2-digit',
|
||||
hour12: true,
|
||||
});
|
||||
}
|
||||
|
||||
export default function AutomationStatusWidget({ data, onRunNow, loading }: AutomationStatusWidgetProps) {
|
||||
const config = statusConfig[data.status];
|
||||
const StatusIcon = config.icon;
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
AlertIcon,
|
||||
CheckCircleIcon,
|
||||
} from '../../icons';
|
||||
import { formatDate } from '../../utils/date';
|
||||
|
||||
export interface ActivityItem {
|
||||
id: string;
|
||||
@@ -68,7 +69,7 @@ function formatRelativeTime(date: Date): string {
|
||||
if (diffDays === 1) return 'Yesterday';
|
||||
if (diffDays < 7) return `${diffDays}d ago`;
|
||||
|
||||
return date.toLocaleDateString();
|
||||
return formatDate(date);
|
||||
}
|
||||
|
||||
export default function RecentActivityWidget({ activities, loading }: RecentActivityWidgetProps) {
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
*/
|
||||
import React from 'react';
|
||||
import { CheckCircleIcon, XCircleIcon, ClockIcon, RefreshCwIcon } from '../../icons';
|
||||
import { formatDateTime } from '../../utils/date';
|
||||
|
||||
interface IntegrationStatusProps {
|
||||
syncEnabled: boolean;
|
||||
@@ -47,8 +48,7 @@ export default function IntegrationStatus({
|
||||
const formatDate = (dateString: string | null) => {
|
||||
if (!dateString) return 'Never';
|
||||
try {
|
||||
const date = new Date(dateString);
|
||||
return date.toLocaleString();
|
||||
return formatDateTime(dateString);
|
||||
} catch {
|
||||
return 'Invalid Date';
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import { Card } from '../ui/card';
|
||||
import Button from '../ui/button/Button';
|
||||
import IconButton from '../ui/button/IconButton';
|
||||
import Badge from '../ui/badge/Badge';
|
||||
import { formatDate } from '../../utils/date';
|
||||
|
||||
interface WordPressIntegration {
|
||||
id: number;
|
||||
@@ -122,7 +123,7 @@ export default function WordPressIntegrationCard({
|
||||
<p className="text-xs text-gray-500 dark:text-gray-400 mb-1">Last Sync</p>
|
||||
<p className="text-sm text-gray-900 dark:text-white">
|
||||
{integration.last_sync_at
|
||||
? new Date(integration.last_sync_at).toLocaleDateString()
|
||||
? formatDate(integration.last_sync_at)
|
||||
: 'Never'}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
*/
|
||||
import React, { ReactNode } from 'react';
|
||||
import { EnhancedTooltip } from './EnhancedTooltip';
|
||||
import { formatDateTime } from '../../../utils/date';
|
||||
|
||||
interface CalendarItemTooltipProps {
|
||||
children: ReactNode;
|
||||
@@ -63,7 +64,7 @@ export const CalendarItemTooltip: React.FC<CalendarItemTooltipProps> = ({
|
||||
{contentType && <div>Type: {contentType}</div>}
|
||||
{date && (
|
||||
<div>
|
||||
{dateLabel}: {new Date(date).toLocaleString()}
|
||||
{dateLabel}: {formatDateTime(date)}
|
||||
</div>
|
||||
)}
|
||||
{wordCount !== undefined && <div>Words: {wordCount}</div>}
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
import { useSiteStore } from '../../store/siteStore';
|
||||
import { useToast } from '../../components/ui/toast/ToastContainer';
|
||||
import { API_BASE_URL, fetchAPI } from '../../services/api';
|
||||
import { formatTime } from '../../utils/date';
|
||||
|
||||
// Types for WordPress integration debugging
|
||||
interface IntegrationHealth {
|
||||
@@ -498,7 +499,7 @@ export default function WordPressIntegrationDebug() {
|
||||
</div>
|
||||
<p className="text-xs text-gray-600 dark:text-gray-400">{integrationHealth.api_message}</p>
|
||||
<div className="text-xs text-gray-500 mt-1">
|
||||
Last: {new Date(integrationHealth.last_api_check).toLocaleTimeString()}
|
||||
Last: {formatTime(integrationHealth.last_api_check)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -533,7 +534,7 @@ export default function WordPressIntegrationDebug() {
|
||||
</p>
|
||||
<div className="text-xs text-gray-500 mt-1">
|
||||
Last: {integrationHealth.last_sync ?
|
||||
new Date(integrationHealth.last_sync).toLocaleTimeString() : 'Never'}
|
||||
formatTime(integrationHealth.last_sync) : 'Never'}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -579,7 +580,7 @@ export default function WordPressIntegrationDebug() {
|
||||
)}
|
||||
</div>
|
||||
<div className="text-xs text-gray-500 whitespace-nowrap ml-4">
|
||||
{new Date(event.timestamp).toLocaleTimeString()}
|
||||
{formatTime(event.timestamp)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -22,6 +22,7 @@ import { useNotificationStore } from '../../store/notificationStore';
|
||||
import { usePageLoading } from '../../context/PageLoadingContext';
|
||||
import type { NotificationAPI } from '../../services/notifications.api';
|
||||
import { deleteNotification as deleteNotificationAPI } from '../../services/notifications.api';
|
||||
import { formatDateTime } from '../../utils/date';
|
||||
|
||||
interface FilterState {
|
||||
severity: string;
|
||||
@@ -101,13 +102,7 @@ export default function NotificationsPage() {
|
||||
const days = Math.floor(hours / 24);
|
||||
|
||||
if (days > 7) {
|
||||
return date.toLocaleDateString('en-US', {
|
||||
month: 'short',
|
||||
day: 'numeric',
|
||||
year: 'numeric',
|
||||
hour: 'numeric',
|
||||
minute: '2-digit'
|
||||
});
|
||||
return formatDateTime(date);
|
||||
} else if (days > 0) {
|
||||
return `${days} day${days !== 1 ? 's' : ''} ago`;
|
||||
} else if (hours > 0) {
|
||||
|
||||
@@ -142,3 +142,23 @@ export function formatDateTime(
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Format time in account timezone
|
||||
* @param dateString - ISO date string or Date object
|
||||
* @param options - Intl.DateTimeFormat options override
|
||||
*/
|
||||
export function formatTime(
|
||||
dateString: string | Date | null | undefined,
|
||||
options: Intl.DateTimeFormatOptions = { hour: 'numeric', minute: '2-digit', second: '2-digit' }
|
||||
): string {
|
||||
if (!dateString) return '-';
|
||||
|
||||
const date = typeof dateString === 'string' ? new Date(dateString) : dateString;
|
||||
if (isNaN(date.getTime())) return '-';
|
||||
|
||||
return date.toLocaleTimeString('en-US', {
|
||||
...options,
|
||||
timeZone: getAccountTimezone(),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user