Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 41 additions & 33 deletions src/components/StoryCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { Storyline } from "../../lib/supabase";
import { AgentBadge } from "./AgentBadge";
import { WriterIdentityClient } from "./WriterIdentityClient";
import { RatingSummary } from "./RatingSummary";
import { StoryCardStats } from "./StoryCardStats";
import { StoryCardTVL } from "./StoryCardStats";

export function StoryCard({
storyline,
Expand All @@ -16,51 +16,59 @@ export function StoryCard({

return (
<div className="flex flex-col">
{/* Book cover */}
{/* Book cover with spine */}
<Link
href={`/story/${storyline.storyline_id}`}
className="border-border hover:border-accent-dim flex aspect-[2/3] flex-col justify-between rounded border px-5 py-6 transition-colors"
className="border-border hover:border-accent-dim relative flex aspect-[2/3] flex-col justify-between overflow-hidden rounded border transition-colors"
>
{/* Top: genre tag + completion badge */}
<div className="flex items-start justify-between gap-2">
<span className="text-muted text-[10px] uppercase tracking-widest">
{displayGenre || "Uncategorized"}
</span>
{storyline.sunset && (
<span className="text-muted border-border shrink-0 rounded border px-1.5 py-0.5 text-[10px]">
complete
</span>
)}
</div>
{/* Spine edge — thin line on left */}
<div className="bg-border absolute inset-y-0 left-0 w-[3px]" />

{/* Center: title */}
<div className="flex flex-1 flex-col items-center justify-center px-2 text-center">
<h3 className="text-foreground text-base font-bold leading-tight tracking-tight sm:text-lg">
{storyline.title}
</h3>
{storyline.language && storyline.language !== "English" && (
<span className="text-muted mt-2 text-[10px]">
{storyline.language}
<div className="flex flex-1 flex-col justify-between py-6 pl-6 pr-5">
{/* Top: genre tag + completion badge */}
<div className="flex items-start justify-between gap-2">
<span className="text-muted text-[10px] uppercase tracking-widest">
{displayGenre || "Uncategorized"}
</span>
)}
</div>
{storyline.sunset && (
<span className="text-muted border-border shrink-0 rounded border px-1.5 py-0.5 text-[10px]">
complete
</span>
)}
</div>

{/* Bottom: author */}
<div className="text-muted flex items-center justify-center gap-1 text-xs">
<WriterIdentityClient address={storyline.writer_address} linkProfile={false} />
{storyline.writer_type === 1 && <AgentBadge />}
{/* Center: title */}
<div className="flex flex-1 flex-col items-center justify-center px-2 text-center">
<h3 className="text-foreground text-base font-bold leading-tight tracking-tight sm:text-lg">
{storyline.title}
</h3>
{storyline.language && storyline.language !== "English" && (
<span className="text-muted mt-2 text-[10px]">
{storyline.language}
</span>
)}
</div>

{/* Bottom: author */}
<div className="text-muted flex items-center justify-center gap-1 text-xs">
<WriterIdentityClient address={storyline.writer_address} linkProfile={false} />
{storyline.writer_type === 1 && <AgentBadge />}
</div>
</div>
</Link>

{/* Metadata row below card */}
<div className="text-muted mt-2 flex flex-wrap items-center justify-between gap-x-2 gap-y-1 px-1 text-[10px]">
<div className="flex items-center gap-2">
<span>
{storyline.plot_count} {storyline.plot_count === 1 ? "plot" : "plots"}
</span>
<div className="flex items-center gap-1">
{storyline.token_address && (
<StoryCardStats tokenAddress={storyline.token_address} />
<>
<StoryCardTVL tokenAddress={storyline.token_address} />
<span>|</span>
</>
)}
<span>
{storyline.plot_count} {storyline.plot_count === 1 ? "plot" : "plots"} linked
</span>
</div>
<RatingSummary storylineId={storyline.storyline_id} />
</div>
Expand Down
18 changes: 18 additions & 0 deletions src/components/StoryCardStats.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ function formatCompact(value: string): string {
return num.toFixed(2);
}

/** Full stats row with price + TVL (used on detail pages) */
export function StoryCardStats({ tokenAddress }: { tokenAddress: string }) {
const addr = tokenAddress as Address;

Expand Down Expand Up @@ -45,3 +46,20 @@ export function StoryCardStats({ tokenAddress }: { tokenAddress: string }) {
</div>
);
}

/** TVL-only display for home page book cards */
export function StoryCardTVL({ tokenAddress }: { tokenAddress: string }) {
const addr = tokenAddress as Address;

const { data: tvlData } = useQuery({
queryKey: ["card-tvl", tokenAddress],
queryFn: () => getTokenTVL(addr),
staleTime: 60000,
});

const tvl = tvlData ? formatCompact(tvlData.tvl) : "—";

return (
<span>TVL: <span className="text-foreground">{tvl} {reserveLabel}</span></span>
);
}
Loading