86 lines
2.4 KiB
TypeScript
86 lines
2.4 KiB
TypeScript
import { Fragment, useMemo } from "react";
|
|
import { t } from "@lingui/core/macro";
|
|
import { Trans } from "@lingui/react/macro";
|
|
import { ErrorCard } from "../../components/ui/ErrorCard.tsx";
|
|
import { JournalCard } from "../../components/dump/JournalCard.tsx";
|
|
import { composeJournal } from "../../utils/journalLayout.ts";
|
|
import type { MainFeedProps } from "./types.ts";
|
|
|
|
export function JournalFeed(
|
|
{
|
|
dumps,
|
|
loading,
|
|
error,
|
|
hasMore,
|
|
loadingMore,
|
|
sentinelRef,
|
|
voteCounts,
|
|
myVotes,
|
|
user,
|
|
castVote,
|
|
removeVote,
|
|
}: MainFeedProps,
|
|
) {
|
|
const blocks = useMemo(() => composeJournal(dumps), [dumps]);
|
|
|
|
if (loading) {
|
|
return (
|
|
<p className="index-status">
|
|
<Trans>Loading…</Trans>
|
|
</p>
|
|
);
|
|
}
|
|
if (error) return <ErrorCard title={t`Failed to load`} message={error} />;
|
|
if (blocks.length === 0) {
|
|
return (
|
|
<p className="index-status">
|
|
<Trans>No dumps yet. Be the first!</Trans>
|
|
</p>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<>
|
|
{
|
|
/* Each sub-block is its own grid, with a themable <hr> between them.
|
|
A break sits between two grids rather than inside one because a grid
|
|
item would be stretched to the 9rem row track — out here its height
|
|
is its own, down to nothing for a theme that wants no separation. */
|
|
}
|
|
<div className="journal-feed">
|
|
{blocks.map((block, index) => (
|
|
<Fragment key={block.key}>
|
|
{index > 0 && <hr className="journal-break" />}
|
|
<ul className="journal-grid">
|
|
{block.entries.map(({ dump, shape }) => (
|
|
<JournalCard
|
|
key={dump.id}
|
|
dump={dump}
|
|
shape={shape}
|
|
voteCount={voteCounts[dump.id] ?? dump.voteCount}
|
|
voted={myVotes.has(dump.id)}
|
|
canVote={!!user}
|
|
castVote={castVote}
|
|
removeVote={removeVote}
|
|
isOwner={user?.id === dump.userId}
|
|
/>
|
|
))}
|
|
</ul>
|
|
</Fragment>
|
|
))}
|
|
</div>
|
|
<div ref={sentinelRef} />
|
|
{loadingMore && (
|
|
<p className="feed-loading-more">
|
|
<Trans>Loading more…</Trans>
|
|
</p>
|
|
)}
|
|
{!hasMore && blocks.length > 0 && (
|
|
<p className="feed-end">
|
|
<Trans>You've reached the end.</Trans>
|
|
</p>
|
|
)}
|
|
</>
|
|
);
|
|
}
|