'use client';
import { useRouter } from 'next/navigation';
import { Calendar, ExternalLink, AlertCircle, CheckCircle, Hourglass, Activity, History } from 'lucide-react';
import TimeAgo from '@/components/common/TimeAgo';
import { useLanguage } from '@/lib/i18n/LanguageContext';
export interface SlotSnapshot {
id: number;
country: string;
city: string;
visa_type: string;
availability_status: 'None' | 'Available' | 'Waitlist';
earliest_date: string | null;
snapshot_at: string;
website?: string;
last_check_at?: string | null;
routing_key?: string;
slot_snapshot?: {
routing_key?: string;
[key: string]: any;
};
}
export default function CitySlotCard({ data, isBlacklisted = false }: { data: SlotSnapshot; isBlacklisted?: boolean }) {
const { t, lang } = useLanguage();
const router = useRouter();
// === 1. 时间计算与解析 ===
const now = new Date().getTime();
const THRESHOLD = 6 * 60 * 1000; // 5分钟阈值
const parseTime = (timeStr: string | null | undefined): number => {
if (!timeStr) return 0;
let t = timeStr;
if (!t.endsWith('Z') && !t.includes('+')) t += 'Z';
return new Date(t).getTime();
};
const lastCheckTime = parseTime(data.last_check_at);
const snapshotTime = parseTime(data.snapshot_at);
// === 2. 状态判定逻辑 ===
const isMonitorStale = (now - lastCheckTime) > THRESHOLD;
const isSnapshotStale = (now - snapshotTime) > THRESHOLD;
const isDataStale = isMonitorStale || isSnapshotStale; // 统称数据过期
const rawStatus = data.availability_status;
// 定义“有号”:包括具体的 Available 和 Waitlist
const hasSlot = rawStatus === 'Available' || rawStatus === 'Waitlist';
// 1. 真正的有号 (Live Slots) -> 数据新鲜且有号
const isLiveSlot = hasSlot && !isDataStale;
// 2. 历史记录 (History) -> 曾经有号,但数据旧了
const isHistorySlot = hasSlot && isDataStale;
// 格式化日期
const formatDate = (dateStr: string | null) => {
if (!dateStr) return 'N/A';
const d = new Date(dateStr);
return d.toLocaleDateString(lang === 'zh' ? 'zh-CN' : 'en-US', {
month: 'short', day: 'numeric', weekday: 'long'
});
};
// === 3. 动态样式配置 ===
const getStyleConfig = () => {
// 情况 A: 历史快照 (有号但过期) -> 橙色
if (isHistorySlot) {
return {
bg: 'bg-orange-50/40 border-orange-200',
badgeBg: 'bg-orange-100 text-orange-700',
icon:
{/* 这里文案也统一,如果是 Waitlist 也可以算作 Slot Info */} {rawStatus === 'Waitlist' ? 'Slot Status' : (t('slots.earliest_date') || 'Earliest Slot')}
{t('slots.subscribe_unavailable') || 'Routing info unavailable'}
)}