"use client"; import Link from "next/link"; import { useEffect, useState } from "react"; import { loadStoryList, deleteStory } from "@/lib/clientStoryPersistence"; import type { StoryMeta } from "@/lib/persistence/types"; import { coerceEpoch } from "@/lib/persistence/types"; import { useLocalePath } from "@/lib/i18n/hooks"; import { useI18n } from "@/lib/i18n/client"; export default function StoriesPage() { const lp = useLocalePath(); const { t, locale } = useI18n(); const [stories, setStories] = useState([]); const [loading, setLoading] = useState(true); const [deletingId, setDeletingId] = useState(null); useEffect(() => { loadStoryList() .then(setStories) .catch(() => setStories([])) .finally(() => setLoading(false)); }, []); const handleDelete = async (storyId: string) => { if (!confirm(t("stories.deleteConfirm"))) return; setDeletingId(storyId); const success = await deleteStory(storyId); if (success) { setStories((prev) => prev.filter((s) => s.id !== storyId)); } else { alert(t("stories.deleteFailed")); } setDeletingId(null); }; // Story timestamps cross the storage boundary as epoch ms (the local store // coerces them); coerceEpoch is the shared guard for any legacy string/Date. const formatDate = (value: Date | string | number) => { const ms = coerceEpoch(value, NaN); if (Number.isNaN(ms)) return ""; const date = new Date(ms); const now = new Date(); const diff = now.getTime() - date.getTime(); const days = Math.floor(diff / (1000 * 60 * 60 * 24)); if (days === 0) return t("stories.today"); if (days === 1) return t("stories.yesterday"); if (days < 7) return t("stories.daysAgo", { days }); return date.toLocaleDateString(locale, { year: "numeric", month: "2-digit", day: "2-digit", }); }; return (
{/* ================== HEADER ================== */}
InfiPlot {t("stories.title")}
{/* ================== CONTENT ================== */}
{loading ? (

{t("stories.loading")}

) : stories.length === 0 ? (

{t("stories.emptyTitle")}

{t("stories.emptyBack")}
) : (
{stories.map((story) => (

{story.worldSetting.slice(0, 60)} {story.worldSetting.length > 60 ? "..." : ""}

{story.styleGuide}

{t("stories.scenes", { count: story.sceneCount })} {formatDate(story.updatedAt)}
{/* Delete button */}
))}
)}
{/* ================== FOOTER ================== */}
MMXXVI {t("stories.storiesCount", { count: stories.length })}
); }