feat(reader): chapter comments + readers-this-week count
Some checks failed
CI / Backend (push) Successful in 48s
CI / UI (push) Failing after 22s
Release / Check ui (push) Failing after 33s
Release / Docker / ui (push) Has been skipped
Release / Test backend (push) Successful in 53s
Release / Docker / caddy (push) Successful in 48s
CI / Backend (pull_request) Successful in 44s
CI / UI (pull_request) Failing after 44s
Release / Docker / runner (push) Failing after 46s
Release / Docker / backend (push) Successful in 1m54s
Release / Gitea Release (push) Has been skipped

- CommentsSection now accepts a chapter prop and scopes comments to that chapter
- Chapter reader page mounts CommentsSection with current chapter number
- Book detail page shows rolling 7-day unique reader count badge
- API GET/POST pass chapter param; pocketbase listComments filters by chapter

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Admin
2026-03-30 19:34:12 +05:00
parent c6597c8d19
commit 76de5eb491
6 changed files with 67 additions and 21 deletions

View File

@@ -21,9 +21,10 @@ export const GET: RequestHandler = async ({ params, url, locals }) => {
const { slug } = params;
const sortParam = url.searchParams.get('sort') ?? 'new';
const sort: CommentSort = sortParam === 'top' ? 'top' : 'new';
const chapter = parseInt(url.searchParams.get('chapter') ?? '0', 10) || 0;
try {
const topLevel = await listComments(slug, sort);
const topLevel = await listComments(slug, sort, chapter);
// Fetch replies for all top-level comments in parallel
const repliesPerComment = await Promise.all(topLevel.map((c) => listReplies(c.id)));
@@ -75,7 +76,7 @@ export const POST: RequestHandler = async ({ params, request, locals }) => {
if (!locals.user) error(401, 'Login required to comment');
const { slug } = params;
let body: { body?: string; parent_id?: string };
let body: { body?: string; parent_id?: string; chapter?: number };
try {
body = await request.json();
} catch {
@@ -86,8 +87,8 @@ export const POST: RequestHandler = async ({ params, request, locals }) => {
if (!text) error(400, 'Comment body is required');
if (text.length > 2000) error(400, 'Comment is too long (max 2000 characters)');
// Enforce 1-level depth: parent_id must be a top-level comment
const parentId = body.parent_id?.trim() || undefined;
const chapter = typeof body.chapter === 'number' ? body.chapter : 0;
try {
const comment = await createComment(
@@ -95,7 +96,8 @@ export const POST: RequestHandler = async ({ params, request, locals }) => {
text,
locals.user.id,
locals.user.username,
parentId
parentId,
chapter
);
return json(comment, { status: 201 });
} catch (e) {