# `MishkaBlogWeb.Templates.CommentCard`
[🔗](https://github.com/mishka-group/mishka_blog/blob/v0.0.1/lib/mishka_blog_web/templates/comment_card.ex#L5)

The comments list: one full-width row per comment, stacked.

Declared only by `MishkaBlog.Comment`, and it reads that record directly rather than by column
position. It is `MishkaBlogWeb.Templates.PostCard` for a different record — same row shape, same
chrome, same breakpoints — because a comment queue and a post queue are read the same way: who,
where, what they said, and what you can do about it.

## Which post a comment is on

Only one of `:post` and `:master_post` is ever loaded — the resource preloads the tenant
relationship for a tenant admin and the tenancy-bypassing one for a master. The other comes back
as `%Ash.NotLoaded{}`, which is truthy, so `post/1` picks whichever is actually a record rather
than testing for nil.

## Features
- `:filter` - the labelled filter row: search, site, status, post, with Pinned as a switch
- `:select` - per-row selection for bulk operations
- `:bulk_actions` - bulk actions on the selected rows
- `:paginate` - the page-size picker and Load more under the list

The furniture is `MishkaCmsCoreWeb.Templates.CardChrome` and the controls are
`MishkaCmsCoreWeb.UIAdapters.Admin`, both shared with every other admin card page.

# `author`

```elixir
@spec author(map()) :: String.t()
```

Who wrote the comment, for the reader whose read loaded it.

The author's email when the reader may see it. For a master, the name of its blogger profile on
the comment's site, else "Master". "Guest" for a comment written signed out, "Unknown" for an
author the reader's read did not return. Load `:author`, `:author_profile` and `:author_master?`.

# `icon`

The switcher draws the grid-of-squares glyph, identical to every other blog card page.

# `initials`

```elixir
@spec initials(map()) :: String.t()
```

The two letters the avatar tile shows for an author.

# `post_title`

```elixir
@spec post_title(map()) :: String.t() | nil
```

The title of the post a comment sits under.

Only one of `:post` and `:master_post` is loaded, so this finds whichever came back as a record —
an unloaded relationship is a `%Ash.NotLoaded{}` struct, which is truthy and would otherwise win.

# `render_bulk_actions`

# `render_empty`

# `render_error`

# `render_filters`

# `render_header`

# `render_item`

One comment row.

The comment's text is the row's subject, so it gets two lines rather than the one a post excerpt
gets — a moderator decides from the words, not from the metadata around them.

# `render_pagination`

# `render_template_switcher`

# `status_badge`

```elixir
@spec status_badge(map()) :: %{
  label: String.t(),
  chip: String.t(),
  mark: String.t(),
  mark_tone: String.t()
}
```

How a comment's moderation status reads and what colour it wears.

One entry per value of the `status` attribute, falling back to `:pending` — the attribute's own
default, and the state an unrecognised comment should be treated as.

# `tint`

```elixir
@spec tint(map()) :: String.t()
```

The avatar tint, picked from the record's id so it never flickers between renders.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
