Files
storkit/frontend/src/components/UpcomingPanel.tsx
2026-02-19 18:05:21 +00:00

191 lines
3.9 KiB
TypeScript

import type { UpcomingStory } from "../api/workflow";
interface UpcomingPanelProps {
stories: UpcomingStory[];
isLoading: boolean;
error: string | null;
lastRefresh: Date | null;
onRefresh: () => void;
}
const formatTimestamp = (value: Date | null): string => {
if (!value) return "—";
return value.toLocaleTimeString([], {
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
});
};
export function UpcomingPanel({
stories,
isLoading,
error,
lastRefresh,
onRefresh,
}: UpcomingPanelProps) {
return (
<div
style={{
border: "1px solid #333",
borderRadius: "10px",
padding: "12px 16px",
background: "#1f1f1f",
display: "flex",
flexDirection: "column",
gap: "8px",
}}
>
<div
style={{
display: "flex",
alignItems: "center",
justifyContent: "space-between",
gap: "12px",
}}
>
<div
style={{
display: "flex",
alignItems: "center",
gap: "8px",
}}
>
<div style={{ fontWeight: 600 }}>Upcoming Stories</div>
<button
type="button"
onClick={onRefresh}
disabled={isLoading}
style={{
padding: "4px 10px",
borderRadius: "999px",
border: "1px solid #333",
background: isLoading ? "#2a2a2a" : "#2f2f2f",
color: isLoading ? "#777" : "#aaa",
cursor: isLoading ? "not-allowed" : "pointer",
fontSize: "0.75em",
fontWeight: 600,
}}
>
Refresh
</button>
</div>
<div
style={{
display: "flex",
flexDirection: "column",
alignItems: "flex-end",
gap: "2px",
fontSize: "0.85em",
color: "#aaa",
}}
>
<div>{stories.length} stories</div>
<div style={{ fontSize: "0.8em", color: "#777" }}>
Updated {formatTimestamp(lastRefresh)}
</div>
</div>
</div>
{isLoading ? (
<div style={{ fontSize: "0.85em", color: "#aaa" }}>
Loading upcoming stories...
</div>
) : error ? (
<div
style={{
fontSize: "0.85em",
color: "#ff7b72",
display: "flex",
alignItems: "center",
gap: "8px",
flexWrap: "wrap",
}}
>
<span>{error} Use Refresh to try again.</span>
<button
type="button"
onClick={onRefresh}
disabled={isLoading}
style={{
padding: "4px 10px",
borderRadius: "999px",
border: "1px solid #333",
background: "#2f2f2f",
color: "#aaa",
cursor: "pointer",
fontSize: "0.75em",
fontWeight: 600,
}}
>
Retry
</button>
</div>
) : stories.length === 0 ? (
<div style={{ fontSize: "0.85em", color: "#aaa" }}>
No upcoming stories.
</div>
) : (
<div
style={{
display: "flex",
flexDirection: "column",
gap: "6px",
}}
>
{stories.map((story) => (
<div
key={`upcoming-${story.story_id}`}
style={{
border: "1px solid #2a2a2a",
borderRadius: "8px",
padding: "8px 12px",
background: "#191919",
display: "flex",
alignItems: "center",
gap: "8px",
}}
>
<div style={{ flex: 1 }}>
<div
style={{
display: "flex",
alignItems: "center",
gap: "8px",
}}
>
<div style={{ fontWeight: 600, fontSize: "0.9em" }}>
{story.name ?? story.story_id}
</div>
{story.name && (
<div
style={{
fontSize: "0.75em",
color: "#777",
fontFamily: "monospace",
}}
>
{story.story_id}
</div>
)}
</div>
{story.error && (
<div
style={{
fontSize: "0.8em",
color: "#ff7b72",
marginTop: "4px",
}}
>
{story.error}
</div>
)}
</div>
</div>
))}
</div>
)}
</div>
);
}