@extends('layouts.dashboard') @section('content') @php /** * @var array $comments rows joined with post title/slug * @var string $filter active status filter ('' = all) * @var array $counts [status => count] * @var array $statuses allowed statuses * @var array $pager pagination metadata * @var array $replies [comment id => number of replies already under it] */ $replies = $replies ?? []; $tabs = array_merge(['' => t_raw('common.all')], array_combine($statuses, array_map(static fn ($s) => t_raw("status.comment.{$s}"), $statuses))); $pillClass = ['approved' => 'qm-pill-green', 'pending' => 'qm-pill-amber', 'spam' => 'qm-pill-red']; @endphp @php /* .qm-d2: the dashboard density standard (app.css §35) */ @endphp

{{ t_raw('admin.comments.title') }}

@if (!empty($counts['pending'])){{ t_raw('admin.comments.pending_badge', [':count' => (int) $counts['pending']]) }}@endif
@php /* Comment body is free text (not meaningfully sortable), so that th carries no data-sort; Received renders via fmt_datetime(), which Date.parse() can't read, so that cell carries a data-sort-value instead. */ @endphp @if ($comments) @foreach ($comments as $c) @endforeach @else @partial('table-empty', ['colspan' => 6, 'icon' => 'fa-comments', 'msg' => $filter !== '' ? t('admin.comments.empty_filtered') : t('admin.comments.empty_all')]) @endif
{{ t_raw('admin.comments.col_author') }}{{ t_raw('admin.comments.col_comment') }}{{ t_raw('admin.comments.col_on_post') }}{{ t_raw('common.status') }}{{ t_raw('admin.comments.col_received') }}{{ t_raw('common.actions') }}
{!! brandmark_html($c['avatar'] ?? null, (string) ($c['name'] ?? t_raw('common.anonymous')), 'md', 'qm-brandmark--round') !!}
{{ $c['name'] }}@if (!empty($c['parent_id'])){{ t_raw('admin.comments.reply_badge') }}@endif @if (!empty($c['email'])){{ $c['email'] }}@endif
{{ $c['body'] }}
@php $replyCount = (int) ($replies[(int) $c['id']] ?? 0); @endphp @if ($replyCount > 0) {{ t_raw('admin.comments.badge_replies', [':count' => $replyCount]) }} @endif
@if (!empty($c['post_slug'])) {{ $c['post_title'] }} @else {{ t_raw('admin.comments.deleted_post') }} @endif {{ status_label('comment', $c['status']) }} {!! fmt_datetime($c['created_at']) !!} @partial('row-actions', ['actions' => [ [ 'label' => t_raw('admin.comments.action_reply'), 'icon' => 'fa-reply', 'primary' => true, 'attrs' => [ 'data-bs-toggle' => 'modal', 'data-bs-target' => '#commentReplyModal', 'data-creply-open' => '1', 'data-id' => (string) (int) $c['id'], 'data-name' => (string) ($c['name'] ?? ''), 'data-body' => (string) $c['body'], 'data-post' => (string) ($c['post_title'] ?? ''), ], ], $c['status'] !== 'approved' ? [ 'label' => t_raw('admin.campaigns.approve'), 'icon' => 'fa-check', 'form' => ['action' => '/admin/comments/status', 'fields' => ['id' => (int) $c['id'], 'status' => 'approved', 'filter' => $filter]], ] : null, $c['status'] !== 'spam' ? [ 'label' => t_raw('admin.comments.mark_spam_btn'), 'icon' => 'fa-ban', 'form' => ['action' => '/admin/comments/status', 'fields' => ['id' => (int) $c['id'], 'status' => 'spam', 'filter' => $filter]], ] : null, [ 'label' => t_raw('common.delete'), 'icon' => 'fa-trash-alt', 'danger' => true, 'form' => ['action' => '/admin/comments/delete', 'fields' => ['id' => (int) $c['id'], 'filter' => $filter], 'confirm' => t_raw('admin.comments.confirm_delete')], ], ]])
@partial('table-toolbar', ['pager' => $pager, 'base' => '/admin/comments'])
@if ($comments) @php // Reply composer. A reply is a published comment filed under the one it answers, so // it appears under the original on the post itself — not a private note. @endphp @endif
@php /* /.qm-d2 */ @endphp @endsection