femto-webapp/src/app/feed/components/PostTimeline.tsx
2025-08-10 21:18:06 +02:00

67 lines
2 KiB
TypeScript

import { PostComment, PostReaction } from '../posts/posts.ts'
import { Temporal } from '@js-temporal/polyfill'
interface PostTimelineProps {
reactions: PostReaction[]
comments: PostComment[]
}
export function PostTimeline({ reactions, comments }: PostTimelineProps) {
const items = [
...reactions.map((reaction) => ({
timestamp: reaction.reactedOn,
component: (
<ReactionItem
key={'reaction-' + reaction.authorName + reaction.reactedOn.toString()}
reaction={reaction}
/>
),
})),
...comments.map((comment) => ({
timestamp: comment.postedOn,
component: (
<CommentItem
key={'comment-' + comment.author + comment.postedOn.toString()}
comment={comment}
/>
),
})),
].toSorted((a, b) => Temporal.Instant.compare(a.timestamp, b.timestamp))
return (
<div className={`flex flex-col gap-4 mb-4 px-4`}>{items.map((item) => item.component)}</div>
)
}
function ReactionItem({ reaction }: { reaction: PostReaction }) {
return (
<div className={`flex flex-col`}>
<div className={`text-gray-400 text-xs -mb-1`}>{formatItemDate(reaction.reactedOn)}</div>
<div className={`flex flex-row items-baseline text-gray-400`}>
<span>@{reaction.authorName}</span>&nbsp;
<span>clicked</span>&nbsp;
<span>{reaction.emoji}</span>
</div>
</div>
)
}
function CommentItem({ comment }: { comment: PostComment }) {
return (
<div className={`flex flex-col`}>
<div className={`text-gray-400 text-xs -mb-1`}>{formatItemDate(comment.postedOn)}</div>
<div className={`flex flex-row items-baseline text-gray-500`}>
<span className={`text-gray-400`}>@{comment.author}</span>&nbsp;
</div>
<div className={`ml-1 text-gray-600`}>{comment.content}</div>
</div>
)
}
function formatItemDate(date: Temporal.Instant) {
return date.toLocaleString('en-AU', {
year: 'numeric',
month: 'numeric',
day: 'numeric',
})
}