feat: real user avatars in reviews, conditional product link

This commit is contained in:
Kirill
2026-05-21 21:10:49 +05:00
parent 7e7bade80c
commit 57da755ea1
4 changed files with 57 additions and 25 deletions
+12 -2
View File
@@ -26,8 +26,15 @@ export type PublicReviewFeedItem = {
imageUrl: string | null
createdAt: string
authorDisplay: string
productId: string
productTitle: string
authorAvatar?: string | null
authorAvatarType?: string | null
authorAvatarStyle?: string | null
product: {
id: string
title: string
published: boolean
slug: string
}
}
export type PublicReviewsLatestResponse = {
@@ -48,6 +55,9 @@ export type PublicProductReviewItem = {
imageUrl: string | null
createdAt: string
authorDisplay: string
authorAvatar?: string | null
authorAvatarType?: string | null
authorAvatarStyle?: string | null
}
export type PublicProductReviewsResponse = {
@@ -19,7 +19,13 @@ function ReviewItem({ rv }: { rv: PublicProductReviewItem }) {
<Paper variant="outlined" sx={{ p: 1.5, borderRadius: 2 }}>
<Stack spacing={0.75}>
<Stack direction="row" spacing={1.5} sx={{ alignItems: 'center' }}>
<UserAvatar userId={rv.authorDisplay} avatarUrl={null} avatarType={null} avatarStyle={null} size={32} />
<UserAvatar
userId={rv.authorDisplay}
avatarUrl={rv.authorAvatar}
avatarType={rv.authorAvatarType}
avatarStyle={rv.authorAvatarStyle}
size={32}
/>
<Box sx={{ flexGrow: 1 }}>
<Typography sx={{ fontWeight: 700 }}>{rv.authorDisplay}</Typography>
</Box>
@@ -103,9 +103,9 @@ export function ReviewsBlock() {
<Stack direction="row" spacing={1.5} sx={{ minWidth: { sm: 200 }, alignItems: 'center' }}>
<UserAvatar
userId={r.authorDisplay}
avatarUrl={null}
avatarType={null}
avatarStyle={null}
avatarUrl={r.authorAvatar}
avatarType={r.authorAvatarType}
avatarStyle={r.authorAvatarStyle}
size={40}
/>
<Box>
@@ -122,20 +122,26 @@ export function ReviewsBlock() {
{formatReviewDate(r.createdAt)}
</Typography>
</Stack>
<Typography
variant="caption"
component={RouterLink}
to={`/products/${r.productId}`}
sx={{
display: 'block',
mt: 0.25,
color: 'primary.main',
textDecoration: 'none',
'&:hover': { textDecoration: 'underline' },
}}
>
{r.productTitle}
</Typography>
{r.product.published ? (
<Typography
variant="caption"
component={RouterLink}
to={`/products/${r.product.slug || r.product.id}`}
sx={{
display: 'block',
mt: 0.25,
color: 'primary.main',
textDecoration: 'none',
'&:hover': { textDecoration: 'underline' },
}}
>
{r.product.title}
</Typography>
) : (
<Typography variant="caption" color="text.secondary" sx={{ display: 'block', mt: 0.25 }}>
{r.product.title}
</Typography>
)}
</Box>
</Stack>
+15 -5
View File
@@ -40,8 +40,8 @@ export async function registerPublicReviewRoutes(fastify) {
const rows = await prisma.review.findMany({
where: { status: 'approved', product: { published: true } },
include: {
user: { select: { email: true, displayName: true } },
product: { select: { id: true, title: true } },
user: { select: { email: true, displayName: true, avatar: true, avatarType: true, avatarStyle: true } },
product: { select: { id: true, title: true, published: true, slug: true } },
},
orderBy: { createdAt: 'desc' },
take,
@@ -54,8 +54,15 @@ export async function registerPublicReviewRoutes(fastify) {
imageUrl: r.imageUrl,
createdAt: r.createdAt,
authorDisplay: publicReviewAuthorDisplay(r.user),
productId: r.productId,
productTitle: r.product?.title ?? '',
authorAvatar: r.user?.avatar ?? null,
authorAvatarType: r.user?.avatarType ?? null,
authorAvatarStyle: r.user?.avatarStyle ?? null,
product: {
id: r.product?.id ?? r.productId,
title: r.product?.title ?? '',
published: r.product?.published ?? false,
slug: r.product?.slug ?? '',
},
}))
return { items }
@@ -80,7 +87,7 @@ export async function registerPublicReviewRoutes(fastify) {
const total = await prisma.review.count({ where })
const rawItems = await prisma.review.findMany({
where,
include: { user: { select: { email: true, displayName: true } } },
include: { user: { select: { email: true, displayName: true, avatar: true, avatarType: true, avatarStyle: true } } },
orderBy: { createdAt: 'desc' },
skip: (page - 1) * pageSize,
take: pageSize,
@@ -93,6 +100,9 @@ export async function registerPublicReviewRoutes(fastify) {
imageUrl: r.imageUrl,
createdAt: r.createdAt,
authorDisplay: publicReviewAuthorDisplay(r.user),
authorAvatar: r.user?.avatar ?? null,
authorAvatarType: r.user?.avatarType ?? null,
authorAvatarStyle: r.user?.avatarStyle ?? null,
}))
return { items, total, page, pageSize }