feat: add website field to CommentUser and update comment components

- Introduced an optional `website` field in the `CommentUser` interface to allow users to provide their website links.
- Updated `CommentCard` and `CommentHeader` components to utilize the new `website` field, enabling clickable links for user websites in the comment header.
- Refactored user data fetching in `CommentService` to include the website information when retrieving user profiles.

Signed-off-by: Innei <tukon479@gmail.com>
This commit is contained in:
Innei
2025-12-03 21:16:35 +08:00
parent ced9e747aa
commit 9fb7f5525f
5 changed files with 169 additions and 133 deletions

View File

@@ -32,6 +32,7 @@ export interface CommentUser {
id: string
name: string
image: string | null
website?: string | null
}
export interface CommentListResult {
@@ -62,6 +63,7 @@ interface CommentUserDto {
id: string
name: string
image: string | null
website?: string | null
}
interface CommentListResponseDto {

View File

@@ -34,6 +34,9 @@ export const CommentItem = memo(({ comment, reacted, locale }: CommentItemProps)
[atoms.usersAtom, comment.userId],
),
)
const user = useAtomValue(
useMemo(() => selectAtom(atoms.usersAtom, (users) => users[comment.userId]), [atoms.usersAtom, comment.userId]),
)
const userName = useAtomValue(
useMemo(
() => selectAtom(atoms.usersAtom, (users) => users[comment.userId]?.name),
@@ -67,7 +70,7 @@ export const CommentItem = memo(({ comment, reacted, locale }: CommentItemProps)
<div className="relative z-10 flex min-w-0 flex-row gap-3">
<UserAvatar image={userImage} name={userName ?? comment.userId} fallback="?" size={36} />
<div className="flex min-w-0 flex-1 flex-col space-y-2">
<CommentHeader comment={comment} author={authorName(comment)} locale={locale} />
<CommentHeader comment={comment} author={authorName(comment)} locale={locale} user={user} />
<CommentContent comment={comment} parentId={comment.parentId} authorName={authorName} />
<CommentActionBar reacted={reacted} reactionCount={comment.reactionCounts.like ?? 0} comment={comment} />
</div>

View File

@@ -1,14 +1,37 @@
import { useTranslation } from 'react-i18next'
import type { Comment } from '~/lib/api/comments'
import type { Comment, CommentUser } from '~/lib/api/comments'
import { RelativeTime } from './RelativeTime'
export const CommentHeader = ({ comment, author, locale }: { comment: Comment; author: string; locale: string }) => {
export const CommentHeader = ({
comment,
author,
locale,
user,
}: {
comment: Comment
author: string
locale: string
user?: CommentUser | null
}) => {
const { t } = useTranslation()
return (
<div className="flex flex-wrap items-baseline gap-2">
<span className="text-sm font-medium text-white/90">{author}</span>
<span className="text-sm font-medium text-white/90">
{user?.website ? (
<a
href={user.website}
target="_blank"
rel="noopener noreferrer"
className="decoration-white/20 hover:underline hover:decoration-white/40"
>
{author}
</a>
) : (
author
)}
</span>
<RelativeTime timestamp={comment.createdAt} locale={locale} className="text-xs text-white/45" />
{comment.status === 'pending' && (
<span className="rounded-full bg-amber-500/10 px-2 py-0.5 text-[10px] text-amber-200/80 uppercase">