نظر (Comment)

یک نظر از مدل SocialComment در ردیف، کارت یا رشته؛ نویسنده، زمان، پسند، پاسخ، برچسب با اطمینان، احساس و ترجمه

معرفی

Comment تنها کامپوننت نمایش یک نظر است. دادهٔ آن یک SocialComment است و همان محتوایی را دارد که آیتم نظر کشوی جزئیات پست داشت: نویسنده (یا «کاربر ناشناس» وقتی نویسنده‌ای نیست)، زمان، پسند و پاسخ، برچسب‌های تحلیل با اطمینانشان، احساس، ترجمه، و وضعیت‌های منبع: سنجاق‌شده، ویرایش‌شده، پاسخ نویسندهٔ پست، پنهان‌شده توسط مدیر منبع و پرچم محتوای آزارنده.

چیدمانکجاقاعده
rowفهرست نظرها برای مرور سریعخط نویسنده، دو خط متن (یک خط در حالت فشرده)، شاخص‌ها و برچسب‌ها در یک خط
cardشبکهٔ نظرها و صفحهٔ تحلیل نظرهاکارت با حاشیه، چهار خط متن که باز می‌شود، برچسب‌ها، احساس و ترجمه
threadبحث زیر یک پستنظر با پاسخ‌هایش زیر آن، با تورفتگی و دکمهٔ «نمایش n پاسخ»

چه زمانی استفاده کنیم:

  • هر جا نظرهای یک پست نمایش داده می‌شوند: صفحهٔ جزئیات پست، صفحهٔ تحلیل نظرها، فهرست نظرهای یک حساب.
  • برای فهرست نظرها، از جمله بحث زیر یک پست، Comment را داخل EntityCollection با entity="comment" بگذارید (پیش‌فرض آن رشتهٔ thread است، بدون دکمهٔ چیدمان)؛ فهرست نظرها را با map نسازید. برای شبکهٔ صفحهٔ تحلیل نظرها layouts={['card', 'row']} بدهید.

چه زمانی استفاده نکنیم:

  • برای پیام گفت‌وگو یا اعلان: این‌ها نظرِ کاربر روی پست نیستند.
thread
سارا@sara_1402
بسته‌بندی جدید خیلی بهتر شده، ولی هزینهٔ ارسال بالاست. کاش ارسال رایگان هم داشتید. @sample_shop
قیمت91٪ارسال64٪
ترکیبی
  • پسند24
  • پاسخ2
فروشگاه نمونه@sample_shopپاسخ نویسنده
ممنون از نظرتان؛ ارسال رایگان از هفتهٔ بعد فعال می‌شود.
  • پسند5
کاربر ناشناس
موافقم.
  • پسندنامعلوم
card
@brand.fan
Love the new packaging!
مثبت
  • پسند3
row
سارا@sara_1402
بسته‌بندی جدید خیلی بهتر شده، ولی هزینهٔ ارسال بالاست. کاش ارسال رایگان هم داشتید. @sample_shop
  • پسند24
  • پاسخ2
ترکیبی
قیمت91٪ارسال64٪
علی@ali_rپرچم‌خورده (امتیاز آزارندگی 72٪)
این چه وضع ارسال است؟
  • پسند0
منفی

آناتومی

Comment یک کامپوننت ترکیبی است؛ تکه‌هایش در همین صفحه مستند شده‌اند و جدول API هر تکه در بخش Props است.

سارا@sara_1402
بسته‌بندی جدید خیلی بهتر شده، ولی هزینهٔ ارسال بالاست. کاش ارسال رایگان هم داشتید. @sample_shop
قیمت91٪ارسال64٪
  • پسند24
  • پاسخ2
  1. 1Comment.Author — نویسنده و زمان
  2. 2Comment.Text — متن نظر
  3. 3Comment.Labels — برچسب‌های تحلیلی با توضیح روی hover
  4. 4Comment.Stats — پسند و پاسخ

استفاده

بحث زیر یک پست یک EntityCollection از نظرهای thread است (همان الگوی «جزئیات پست همراه با نظرها» در صفحهٔ Post):

'use client'

import { Comment, EntityCollection, type SocialComment } from '@partodata/ui/social'

interface DiscussionProps {
  comments: SocialComment[]
  loading: boolean
  error?: unknown
  onRetry: () => void
  onLoadReplies: (comment: SocialComment) => Promise<void>
}

export function Discussion({ comments, loading, error, onRetry, onLoadReplies }: DiscussionProps) {
  return (
    <EntityCollection
      entity="comment"
      items={comments}
      getId={(comment) => comment.id}
      label="نظرها"
      loading={loading}
      error={error}
      onRetry={onRetry}
      renderItem={(comment, item) => <Comment comment={comment} {...item} onLoadReplies={onLoadReplies} />}
    />
  )
}

دادهٔ نظرها را یک بار به مدل تبدیل کنید: نظرهای کشوی جزئیات (PostComment) با fromPostComment و برچسب‌های نظر با احتمال 0 تا 100 با fromCommentTag، هر دو از @partodata/ui/social/adapters. اطمینان برچسب در مدل همیشه کسر است و فقط یک بار، در همین کامپوننت، درصد نمایش داده می‌شود.

حالت‌ها و انواع

  • نویسنده: نام، نشان تأیید فقط وقتی منبع آن را گفته، شناسه به‌صورت جزیرهٔ چپ‌به‌راست. بدون نویسنده: «کاربر ناشناس». با onActorClick نام دکمه می‌شود.
  • شاخص‌ها: پسند و تعداد پاسخ با همان قاعدهٔ مدل؛ نامعلوم «—» و شمارنده‌ای که منبع ندارد نمایش داده نمی‌شود.
  • پاسخ‌ها (thread): دکمهٔ «نمایش n پاسخ» دقیقاً همان پاسخ‌هایی را وعده می‌دهد که باز می‌کند. بدون onLoadReplies، n تعداد پاسخ‌های بارگذاری‌شده است. با onLoadReplies، n از metrics.replies می‌آید: دکمه حتی پیش از بارگذاری هر پاسخی نمایش داده می‌شود، با باز شدن تابع را صدا می‌زند و تا رسیدن پاسخ‌ها «در حال بارگذاری پاسخ‌ها» است؛ پس از پاسخ‌های بارگذاری‌شده، تا وقتی تعدادشان از metrics.replies کمتر است، «نمایش n پاسخ دیگر» می‌آید و فوکوس را به اولین پاسخی می‌برد که بارگذاری کرد. تابع باید promise برگرداند: پاسخ‌های تازه را به comment.replies اضافه کنید و بعد promise را تمام کنید؛ خطا «تلاش دوباره» می‌دهد و بارگذاری‌ای که پاسخی اضافه نکند (شمار کهنه، پاسخ حذف‌شده در منبع) پس از مکثی کوتاه «پاسخی در دسترس نیست» می‌گوید، نه یک فهرست باز و خالی. پاسخ‌هایی که کمی پس از تمام شدن promise برسند (مخزنی که React را دیرتر خبر می‌کند) هم باز می‌شوند و فوکوس را می‌گیرند. با defaultRepliesExpanded و بدون پاسخ بارگذاری‌شده، پاسخ‌ها هنگام نمایش نظر بارگذاری می‌شوند. پاسخ‌های تودرتو همین تابع را به ارث می‌برند.
  • سیگنال‌ها: احساس و نوع نویسندهٔ استنباط‌شده (مرد، زن، حساب غیرشخصی) فقط برای نظری که تحلیل شده است. امتیاز آزارندگی از 0.6 به بالا نشان «پرچم‌خورده» می‌گیرد.
  • ترجمه: وقتی زبان نظر (lang) زبان خواننده نیست، ترجمهٔ آماده (translation) یا onTranslate یک دکمهٔ «ترجمه» می‌دهد.
  • پنهان‌شده: نظری که مدیر منبع پنهان کرده به‌جای متنش یک اطلاع دارد (نام دسترس‌پذیرش همین اطلاع است)، ولی چک‌باکس، اقدامات و پاسخ‌هایش می‌مانند تا محصول نظارت بتواند روی آن کار کند.
  • ترکیب: بدون children ترکیب پیش‌فرض هر چیدمان؛ برای ترکیب دیگر Comment.Select، Comment.Author، Comment.Aside، Comment.Text، Comment.Labels، Comment.Signals، Comment.Stats، Comment.Actions و Comment.Replies را بچینید. فقط جایگاه‌های چیده‌شده نمایش داده می‌شوند؛ aside فقط در ترکیب پیش‌فرض است (در ترکیب دلخواه Comment.Aside).
  • وضعیت‌ها: state مثل پست؛ loading اسکلت همان چیدمان است.

راهنمای استفاده

بکنید

  • برچسب‌ها را با اطمینان کسری (0.91) در مدل نگه دارید و اجازه دهید کامپوننت آن را درصد کند.
  • برای بحث زیر پست layout="thread" و برای شبکهٔ صفحهٔ تحلیل layout="card" را به کار ببرید؛ چیدمان پیش‌فرض card است.
  • وقتی API پاسخ‌ها را جدا و صفحه‌به‌صفحه می‌دهد، onLoadReplies بدهید؛ دکمهٔ پاسخ‌ها را خودتان کنار نظر نسازید.

نکنید

  • وقتی نویسنده را نمی‌دانید، نام نسازید؛ author را خالی بگذارید تا «کاربر ناشناس» نمایش داده شود.
  • پسند نامعلوم را 0 نکنید.
  • ردیف نظر را خودتان از نشان‌ها و متن نسازید.

Props

Comment

Prop

Type

CommentAiDraft

Prop

Type

<Comment
  comment={draft}
  aiDraft={{
    onRegenerate: regenerate,
    tones: [{ id: 'formal', label: 'رسمی' }, { id: 'friendly', label: 'صمیمی' }],
    onTone: rewrite,
  }}
  actions={[{ id: 'send', label: 'ارسال پاسخ', icon: <Send />, onSelect: send }]}
/>

Comment.Text / CommentTextProps

Prop

Type

Comment.Stats / CommentStatsProps

Prop

Type

Comment.Actions / CommentActionsProps

Prop

Type

دسترسی‌پذیری

  • هر نظر یک article است که با نام نویسنده نام‌گذاری می‌شود؛ پاسخ‌های رشته یک فهرست تودرتو هستند.
  • هر نظر حلقهٔ فوکوس دیدنی دارد؛ نام نویسنده جزیرهٔ جهت خودش است و نام لاتین ارقام لاتین می‌گیرد («Agent 47»).
  • دکمهٔ «نمایش n پاسخ» aria-expanded و aria-controls دارد و هنگام بارگذاری پاسخ‌ها فوکوس را نگه می‌دارد (aria-busy، هرگز disabled). «نمایش n پاسخ دیگر» فوکوس را به اولین پاسخی می‌برد که بارگذاری کرد (خواندن از همان‌جا ادامه می‌یابد و دکمه با صفحهٔ آخر می‌رود)؛ «تلاش دوباره» فوکوس را به دکمه‌ای برمی‌گرداند که بارگذاری‌اش ناموفق بود. «پاسخی در دسترس نیست» در یک ناحیهٔ role="status" اعلام می‌شود.
  • امتیاز آزارندگی نظر پرچم‌خورده برای صفحه‌خوان هم خوانده می‌شود، نه فقط در راهنمای شناور.
  • برچسب‌ها متن دارند (نام و درصد)، نه فقط رنگ؛ احساس نشان با آیکون و متن است.

کامپوننت‌های مرتبط

  • Post — پستی که نظرها زیر آن‌اند (layout="details").
  • EntityCollection — فهرست نظرها با اسکلت، حالت‌ها و انتخاب.