- {/* avatar with XP level ring */}
- {/* XP progress to next level */}
{t.profileToNextLevel}
@@ -219,7 +216,6 @@ export default async function ProfilePage({ params }: Args) {
- {/* courses in progress */}
{t.profileMyCourses}
{inProgress.length === 0 && completed.length === 0 ? (
@@ -277,7 +273,6 @@ export default async function ProfilePage({ params }: Args) {
)}
- {/* certificates */}
{completed.length > 0 && (
<>
{t.profileCertificates}
@@ -323,7 +318,6 @@ export default async function ProfilePage({ params }: Args) {
>
)}
- {/* recent quiz attempts */}
{recentAttempts.docs.length > 0 && (
<>
{t.profileRecentQuizzes}
@@ -370,7 +364,6 @@ export default async function ProfilePage({ params }: Args) {
>
)}
- {/* account info */}
diff --git a/src/app/(frontend)/[locale]/register/page.tsx b/src/app/(frontend)/[locale]/register/page.tsx
index 8dec18d..5ec9591 100644
--- a/src/app/(frontend)/[locale]/register/page.tsx
+++ b/src/app/(frontend)/[locale]/register/page.tsx
@@ -16,7 +16,6 @@ export default async function RegisterPage({ params, searchParams }: Args) {
const { redirect: redirectParam } = await searchParams
const home = locale === defaultLocale ? '/' : `/${locale}`
- // sanitized return path; undefined keeps each form's own default
const redirectTo = redirectParam ? safeRedirectPath(redirectParam, home) : undefined
const session = await getSession()
diff --git a/src/app/(frontend)/[locale]/users/[id]/page.tsx b/src/app/(frontend)/[locale]/users/[id]/page.tsx
index b8264c4..8b17c68 100644
--- a/src/app/(frontend)/[locale]/users/[id]/page.tsx
+++ b/src/app/(frontend)/[locale]/users/[id]/page.tsx
@@ -76,7 +76,6 @@ export default async function PublicProfilePage({ params }: Args) {
depth: 1,
})
- // Same XP math as the private profile page.
let stepsDone = 0
let quizzesPassed = 0
for (const enrollment of enrollments.docs) {
@@ -102,7 +101,6 @@ export default async function PublicProfilePage({ params }: Args) {
return (
- {/* avatar with XP level ring */}
- {/* stats */}
@@ -182,7 +179,6 @@ export default async function PublicProfilePage({ params }: Args) {
- {/* completed courses — no scores, no certificate downloads */}
{completed.length > 0 && (
<>
@@ -218,14 +214,12 @@ export default async function PublicProfilePage({ params }: Args) {
>
)}
- {/* latest comments — streamed after first paint so they never block the page */}
{user.hideProfileComments !== true && (
}>
)}
- {/* joined date */}
{joinedDate && (
diff --git a/src/app/(frontend)/next/preview/route.ts b/src/app/(frontend)/next/preview/route.ts
index ce2fb55..6d6b55f 100644
--- a/src/app/(frontend)/next/preview/route.ts
+++ b/src/app/(frontend)/next/preview/route.ts
@@ -48,8 +48,6 @@ export async function GET(req: NextRequest): Promise
{
return new Response('You are not allowed to preview this page', { status: 403 })
}
- // You can add additional checks here to see if the user is allowed to preview this page
-
draft.enable()
redirect(path)
diff --git a/src/app/api/auth/verify-registration/route.ts b/src/app/api/auth/verify-registration/route.ts
index c255e8b..764c19a 100644
--- a/src/app/api/auth/verify-registration/route.ts
+++ b/src/app/api/auth/verify-registration/route.ts
@@ -56,7 +56,6 @@ async function handleSendOtp(request: Request, body: { email?: string }) {
body: { email, type: 'email-verification' },
})
- // Send the OTP email via Resend (skipped when API key is not configured, e.g. in CI/tests)
if (process.env.RESEND_API_KEY) {
const resend = new Resend(process.env.RESEND_API_KEY)
await resend.emails.send({
@@ -94,7 +93,6 @@ async function handleVerifyOtp(request: Request, body: { email?: string; otp?: s
const identifier = `email-verification-otp-${email}`
- // Find the verification record
const records = await payload.find({
collection: 'verifications',
where: { identifier: { equals: identifier } },
@@ -123,7 +121,6 @@ async function handleVerifyOtp(request: Request, body: { email?: string; otp?: s
}
if (storedOtp !== otp) {
- // Increment attempt counter
await payload.update({
collection: 'verifications',
id: record.id,
@@ -132,7 +129,6 @@ async function handleVerifyOtp(request: Request, body: { email?: string; otp?: s
return NextResponse.json({ error: 'Invalid OTP' }, { status: 400 })
}
- // OTP valid — mark email as pre-verified and clean up
markPreVerified(email)
await payload.delete({ collection: 'verifications', id: record.id })
diff --git a/src/app/api/courses/[id]/completions/route.ts b/src/app/api/courses/[id]/completions/route.ts
index 0be1058..9e41f43 100644
--- a/src/app/api/courses/[id]/completions/route.ts
+++ b/src/app/api/courses/[id]/completions/route.ts
@@ -1,9 +1,7 @@
import { getCachedCourseCompletions } from '@/utilities/leaderboard'
-/**
- * Public projection of who completed a course (name/avatar only), consumed by
- * the course-page ticker. Enrollment docs themselves stay admin-or-own.
- */
+// Public projection of who completed a course (name/avatar only) — enrollment docs
+// themselves stay admin-or-own.
export async function GET(
_req: Request,
{ params }: { params: Promise<{ id: string }> },
diff --git a/src/app/api/dev-login/route.ts b/src/app/api/dev-login/route.ts
index 6847724..31a3f16 100644
--- a/src/app/api/dev-login/route.ts
+++ b/src/app/api/dev-login/route.ts
@@ -3,19 +3,6 @@ import { getPayload } from '@/lib/payload'
import { DEV_ADMIN } from '@/lib/auth/dev-credentials'
import { seedDevAdmin } from '@/lib/auth/seed-dev-admin'
-/**
- * Dev-only auto-login: signs in as the dev admin and sets the Better Auth
- * session cookies, then redirects. One request logs a browser in —
- * `open http://localhost:3000/api/dev-login`.
- *
- * Self-healing: when sign-in fails (fresh/wiped database without the account),
- * it runs the dev-admin seed and retries — so the first login on any dev
- * branch works without a manual seeding step. The account normally pre-exists
- * via the seeded dev parent Neon branch, making the fast path seed-free.
- *
- * Never available on Vercel. Local production builds (pnpm dev:prod) must
- * opt in with ALLOW_DEV_LOGIN=1. See docs/dev-admin-login.md.
- */
function devLoginEnabled(): boolean {
if (process.env.VERCEL) return false
return process.env.NODE_ENV !== 'production' || process.env.ALLOW_DEV_LOGIN === '1'
@@ -38,7 +25,6 @@ export async function GET(request: Request) {
let authResponse = await signIn(payload)
if (!authResponse.ok) {
- // Account missing (or stale password) — seed it, then retry once.
payload.logger.info('dev-login: sign-in failed, running dev-admin seed')
try {
pendingSeed ??= seedDevAdmin(payload).finally(() => {
diff --git a/src/blocks/Form/Component.tsx b/src/blocks/Form/Component.tsx
index 1e50ecd..3729ffd 100644
--- a/src/blocks/Form/Component.tsx
+++ b/src/blocks/Form/Component.tsx
@@ -60,7 +60,6 @@ export const FormBlock: React.FC<
value,
}))
- // delay loading indicator by 1s
loadingTimerID = setTimeout(() => {
setIsLoading(true)
}, 1000)
diff --git a/src/collections/Courses.ts b/src/collections/Courses.ts
index 3819d75..5f1ed4c 100644
--- a/src/collections/Courses.ts
+++ b/src/collections/Courses.ts
@@ -7,7 +7,6 @@ import { cyrillicSlugify } from '../utilities/cyrillicSlugify'
import { syncCourseCompletions } from '../hooks/syncCourseCompletions'
import { revalidateCourse, revalidateCourseDelete } from '../hooks/revalidateCourse'
-// Орієнтовна тривалість кроку — показується учням у списках кроків («Відео · 8 хв»).
const stepDurationField: Field = {
name: 'duration',
type: 'number',
diff --git a/src/collections/Media.ts b/src/collections/Media.ts
index 67130a7..5301972 100644
--- a/src/collections/Media.ts
+++ b/src/collections/Media.ts
@@ -45,7 +45,6 @@ export const Media: CollectionConfig = {
},
],
upload: {
- // Upload to the public/media directory in Next.js making them publicly accessible even outside of Payload
staticDir: path.resolve(dirname, '../../public/media'),
adminThumbnail: 'thumbnail',
focalPoint: true,
diff --git a/src/collections/Pages/hooks/revalidatePage.ts b/src/collections/Pages/hooks/revalidatePage.ts
index 2a19809..b0aee9e 100644
--- a/src/collections/Pages/hooks/revalidatePage.ts
+++ b/src/collections/Pages/hooks/revalidatePage.ts
@@ -19,7 +19,6 @@ export const revalidatePage: CollectionAfterChangeHook = ({
revalidateTag('pages-sitemap')
}
- // If the page was previously published, we need to revalidate the old path
if (previousDoc?._status === 'published' && doc._status !== 'published') {
const oldPath = previousDoc.slug === 'home' ? '/' : `/${previousDoc.slug}`
diff --git a/src/collections/Pages/index.ts b/src/collections/Pages/index.ts
index 6cc65a5..36d6657 100644
--- a/src/collections/Pages/index.ts
+++ b/src/collections/Pages/index.ts
@@ -31,9 +31,6 @@ export const Pages: CollectionConfig<'pages'> = {
read: authenticatedOrPublished,
update: admin,
},
- // This config controls what's populated by default when a page is referenced
- // https://payloadcms.com/docs/queries/select#defaultpopulate-collection-config-property
- // Type safe if the collection slug generic is passed to `CollectionConfig` - `CollectionConfig<'pages'>
defaultPopulate: {
title: true,
slug: true,
@@ -109,10 +106,8 @@ export const Pages: CollectionConfig<'pages'> = {
overrides: { label: 'Мета-опис' },
}),
PreviewField({
- // if the `generateUrl` function is configured
hasGenerateFn: true,
- // field paths to match the target field for data
titlePath: 'meta.title',
descriptionPath: 'meta.description',
}),
diff --git a/src/collections/Posts/hooks/populateAuthors.ts b/src/collections/Posts/hooks/populateAuthors.ts
index 746ebfd..17e139d 100644
--- a/src/collections/Posts/hooks/populateAuthors.ts
+++ b/src/collections/Posts/hooks/populateAuthors.ts
@@ -2,8 +2,6 @@ import type { CollectionAfterReadHook } from 'payload'
// The `user` collection has access control locked so that users are not publicly accessible
// This means that we need to populate the authors manually here to protect user privacy
-// GraphQL will not return mutated user data that differs from the underlying schema
-// So we use an alternative `populatedAuthors` field to populate the user data, hidden from the admin UI
export const populateAuthors: CollectionAfterReadHook = async ({ doc, req, req: { payload } }) => {
if (doc?.authors && doc?.authors?.length > 0) {
const authorIds: number[] = doc.authors.map((author: { id: number } | number) =>
diff --git a/src/collections/Posts/hooks/revalidatePost.ts b/src/collections/Posts/hooks/revalidatePost.ts
index ff43752..ccff28c 100644
--- a/src/collections/Posts/hooks/revalidatePost.ts
+++ b/src/collections/Posts/hooks/revalidatePost.ts
@@ -19,7 +19,6 @@ export const revalidatePost: CollectionAfterChangeHook = ({
revalidateTag('posts-sitemap')
}
- // If the post was previously published, we need to revalidate the old path
if (previousDoc._status === 'published' && doc._status !== 'published') {
const oldPath = `/posts/${previousDoc.slug}`
diff --git a/src/collections/Posts/index.ts b/src/collections/Posts/index.ts
index d87cafb..a41644b 100644
--- a/src/collections/Posts/index.ts
+++ b/src/collections/Posts/index.ts
@@ -39,9 +39,6 @@ export const Posts: CollectionConfig<'posts'> = {
read: authenticatedOrPublished,
update: admin,
},
- // This config controls what's populated by default when a post is referenced
- // https://payloadcms.com/docs/queries/select#defaultpopulate-collection-config-property
- // Type safe if the collection slug generic is passed to `CollectionConfig` - `CollectionConfig<'posts'>
defaultPopulate: {
title: true,
slug: true,
@@ -165,10 +162,8 @@ export const Posts: CollectionConfig<'posts'> = {
overrides: { label: 'Мета-опис' },
}),
PreviewField({
- // if the `generateUrl` function is configured
hasGenerateFn: true,
- // field paths to match the target field for data
titlePath: 'meta.title',
descriptionPath: 'meta.description',
}),
@@ -207,9 +202,6 @@ export const Posts: CollectionConfig<'posts'> = {
hasMany: true,
relationTo: 'users',
},
- // This field is only used to populate the user data via the `populateAuthors` hook
- // This is because the `user` collection has access control locked to protect user privacy
- // GraphQL will also not return mutated user data that differs from the underlying schema
{
name: 'populatedAuthors',
type: 'array',
diff --git a/src/collections/XpEvents.ts b/src/collections/XpEvents.ts
index 3e2a363..b717367 100644
--- a/src/collections/XpEvents.ts
+++ b/src/collections/XpEvents.ts
@@ -2,13 +2,9 @@ import type { CollectionConfig } from 'payload'
import { admin } from '../access/admin'
-/**
- * Append-only log of XP awards (step completed, final quiz passed).
- *
- * Total XP stays derived from enrollments (see src/utilities/xp.ts); this log
- * exists so period leaderboards («XP за день/тиждень/місяць») can be computed —
- * enrollments store which steps are done but not when.
- */
+// Append-only log of XP awards. Total XP stays derived from enrollments (src/utilities/xp.ts);
+// this log exists only so period leaderboards can be computed — enrollments store which
+// steps are done but not when.
export const XpEvents: CollectionConfig = {
slug: 'xp-events',
labels: { singular: 'Подія XP', plural: 'Події XP' },
diff --git a/src/components/AccountSettings/AvatarForm.tsx b/src/components/AccountSettings/AvatarForm.tsx
index b402656..1fdd0cf 100644
--- a/src/components/AccountSettings/AvatarForm.tsx
+++ b/src/components/AccountSettings/AvatarForm.tsx
@@ -31,13 +31,10 @@ const fileType = (file: File): string =>
file.type || EXTENSION_TYPES[file.name.split('.').pop()?.toLowerCase() ?? ''] || ''
/**
- * Re-encodes the picked image to a modest JPEG before it ever reaches the
- * server action. A phone photo is routinely 2–5 MB, which blows past the
- * server action body limit and fails as an opaque rejection — this keeps the
- * upload at a couple hundred KB and normalises the type on the way.
- *
- * Returns the untouched file when re-encoding is not worth it or not possible;
- * the caller still validates size, so a passthrough is always safe.
+ * A phone photo is routinely 2–5 MB, which blows past the server action body limit and
+ * fails as an opaque rejection, so re-encode to a modest JPEG first. Returns the
+ * untouched file when that is not worth it or not possible — the caller still validates
+ * size, so a passthrough is always safe.
*/
async function shrinkForUpload(file: File): Promise {
const type = fileType(file)
@@ -74,10 +71,8 @@ async function shrinkForUpload(file: File): Promise {
}
}
-/** The server action updates the user in the DB, but two caches still hold the
- * old snapshot: the session cookie cache (5 min) and the header's myXp cache,
- * whose payload carries `image`. Clear both so the header avatar changes with
- * the rest of the page instead of lagging behind it by up to 5 minutes. */
+// Two caches still hold the old snapshot after the server action writes: the session
+// cookie cache (5 min) and the header's myXp cache, whose payload carries `image`.
const refreshAndReload = async () => {
clearMyXpCache()
await authClient.getSession({ query: { disableCookieCache: true } })
@@ -143,8 +138,6 @@ export const AvatarForm: React.FC<{
: t.settingsErrorGeneric,
)
} catch {
- // A rejected server action (body too large, network drop, cold start
- // timeout) used to leave the button stuck on "saving" with no message.
setError(t.settingsErrorGeneric)
}
setBusy(false)
diff --git a/src/components/AccountSettings/ConnectedProviders.tsx b/src/components/AccountSettings/ConnectedProviders.tsx
index 92cc4c3..4885de6 100644
--- a/src/components/AccountSettings/ConnectedProviders.tsx
+++ b/src/components/AccountSettings/ConnectedProviders.tsx
@@ -60,7 +60,6 @@ export const ConnectedProviders: React.FC<{
setError(t.settingsErrorGeneric)
setBusy(false)
}
- // On success the browser redirects to Google.
}
const handleDisconnectGoogle = async () => {
diff --git a/src/components/AdminBar/index.tsx b/src/components/AdminBar/index.tsx
index 46aeaa1..7f6b7ac 100644
--- a/src/components/AdminBar/index.tsx
+++ b/src/components/AdminBar/index.tsx
@@ -14,7 +14,6 @@ import './index.scss'
const baseClass = 'admin-bar'
-/** Collections an admin touches daily; `create` adds a quick «+» link. */
const quickLinks = [
{ create: true, icon: GraduationCap, label: 'Курси', slug: 'courses' },
{ create: true, icon: Newspaper, label: 'Публікації', slug: 'posts' },
@@ -33,10 +32,6 @@ type MeUser = {
role?: ('admin' | 'learner')[] | null
}
-/**
- * Slim bar shown above the site header to logged-in admins only: quick links
- * into the CMS (courses, posts, pages, users) plus create shortcuts.
- */
export const AdminBar: React.FC = ({ adminBarProps }) => {
const preview = adminBarProps?.preview ?? false
const [isAdmin, setIsAdmin] = useState(false)
diff --git a/src/components/Auth/ForgotPasswordForm.tsx b/src/components/Auth/ForgotPasswordForm.tsx
index a7f5e9c..942164c 100644
--- a/src/components/Auth/ForgotPasswordForm.tsx
+++ b/src/components/Auth/ForgotPasswordForm.tsx
@@ -26,7 +26,6 @@ export const ForgotPasswordForm: React.FC<{
const loginHref = `/${locale === 'uk' ? '' : locale + '/'}login`
- // Resend cooldown timer
useEffect(() => {
if (resendCooldown <= 0) return
const timer = setTimeout(() => setResendCooldown((c) => c - 1), 1000)
@@ -88,7 +87,6 @@ export const ForgotPasswordForm: React.FC<{
router.refresh()
}
- // Step 2: OTP + new password
if (step === 'reset') {
return (
@@ -159,7 +157,6 @@ export const ForgotPasswordForm: React.FC<{
)
}
- // Step 1: Email entry
return (
{t.forgotTitle}
diff --git a/src/components/Auth/PasswordInput.tsx b/src/components/Auth/PasswordInput.tsx
index 23af3ed..aa8699b 100644
--- a/src/components/Auth/PasswordInput.tsx
+++ b/src/components/Auth/PasswordInput.tsx
@@ -4,12 +4,10 @@ import React, { useState } from 'react'
import { Eye, EyeOff } from 'lucide-react'
type Props = Omit
, 'type'> & {
- /** aria-labels for the toggle button */
showLabel: string
hideLabel: string
}
-/** Password field with a show/hide toggle. Keeps the same id/name/autofill contract as a plain input. */
export const PasswordInput: React.FC = ({ showLabel, hideLabel, className, ...props }) => {
const [visible, setVisible] = useState(false)
diff --git a/src/components/Auth/RegisterForm.tsx b/src/components/Auth/RegisterForm.tsx
index 56d90a3..23dc38d 100644
--- a/src/components/Auth/RegisterForm.tsx
+++ b/src/components/Auth/RegisterForm.tsx
@@ -31,7 +31,6 @@ export const RegisterForm: React.FC<{
// fragment (e.g. #comments) only rides on the client-side navigation below.
const serverCallbackURL = callbackURL.split('#')[0] || '/'
- // Resend cooldown timer
useEffect(() => {
if (resendCooldown <= 0) return
const timer = setTimeout(() => setResendCooldown((c) => c - 1), 1000)
@@ -94,7 +93,6 @@ export const RegisterForm: React.FC<{
return
}
- // OTP verified — create the account
setStep('creating')
const { error: signUpError } = await authClient.signUp.email({
name,
@@ -142,7 +140,6 @@ export const RegisterForm: React.FC<{
? `/${locale === 'uk' ? '' : locale + '/'}login?redirect=${encodeURIComponent(redirectTo)}`
: `/${locale === 'uk' ? '' : locale + '/'}login`
- // Step 3: Creating account (loading screen)
if (step === 'creating') {
return (
@@ -151,7 +148,6 @@ export const RegisterForm: React.FC<{
)
}
- // Step 2: OTP verification
if (step === 'otp') {
return (
@@ -206,7 +202,6 @@ export const RegisterForm: React.FC<{
)
}
- // Step 1: Credentials form
return (
{t.registerTitle}
diff --git a/src/components/BeforeDashboard/index.tsx b/src/components/BeforeDashboard/index.tsx
index 4f768d5..99c03b9 100644
--- a/src/components/BeforeDashboard/index.tsx
+++ b/src/components/BeforeDashboard/index.tsx
@@ -5,7 +5,6 @@ import './index.scss'
const baseClass = 'before-dashboard'
-/** Quick links into the collections admins touch daily, plus live counts. */
const quickStats = [
{ slug: 'courses', label: 'Курси' },
{ slug: 'users', label: 'Користувачі' },
diff --git a/src/components/Card/index.tsx b/src/components/Card/index.tsx
index b1d9a1e..6153d87 100644
--- a/src/components/Card/index.tsx
+++ b/src/components/Card/index.tsx
@@ -18,11 +18,9 @@ export type CardRelationTo = 'posts' | 'courses' | 'course-categories' | 'pages'
export type CardPostData = Pick
& {
collectionType?: string | null
publishedAt?: string | null
- /** Id of the underlying document (search results only) — used for category deep links. */
docId?: number | null
}
-// Fallback covers extracted from the approved design prototype.
const FALLBACK_COVERS = [
'/illustrations/post-shift-recap.svg',
'/illustrations/post-enrollment.svg',
diff --git a/src/components/CollectionArchive/index.tsx b/src/components/CollectionArchive/index.tsx
index 84bd677..be19f1a 100644
--- a/src/components/CollectionArchive/index.tsx
+++ b/src/components/CollectionArchive/index.tsx
@@ -9,7 +9,6 @@ export type Props = {
posts: CardPostData[]
likesCountMap?: Record
commentsCountMap?: Record
- /** Optional label per collection type, shown as a chip on each card (used on search results). */
typeLabels?: Partial>
}
diff --git a/src/components/CommentsAndLikes/CommentItem.tsx b/src/components/CommentsAndLikes/CommentItem.tsx
index 2d30c75..0ae7d32 100644
--- a/src/components/CommentsAndLikes/CommentItem.tsx
+++ b/src/components/CommentsAndLikes/CommentItem.tsx
@@ -30,7 +30,6 @@ interface CommentItemProps {
onDelete: (commentId: number) => Promise
depth?: number
loginUrl?: string
- /** Locale-aware base path for public profiles, e.g. "/users" or "/en/users". */
userProfileBase?: string
}
diff --git a/src/components/CommentsAndLikes/CommentsSection.tsx b/src/components/CommentsAndLikes/CommentsSection.tsx
index 3ac8c6f..1eeb3a2 100644
--- a/src/components/CommentsAndLikes/CommentsSection.tsx
+++ b/src/components/CommentsAndLikes/CommentsSection.tsx
@@ -34,11 +34,9 @@ interface CommentsSectionProps {
isAuthenticated: boolean
currentUserId: number | null
isAdmin: boolean
- /** When false, loading the comment list is deferred (e.g. until scrolled into view). */
active?: boolean
labels: Labels
loginUrl: string
- /** Locale-aware base path for public profiles, e.g. "/users" or "/en/users". */
userProfileBase: string
}
diff --git a/src/components/CommentsAndLikes/InteractionClient.tsx b/src/components/CommentsAndLikes/InteractionClient.tsx
index 27ff21b..4a08a82 100644
--- a/src/components/CommentsAndLikes/InteractionClient.tsx
+++ b/src/components/CommentsAndLikes/InteractionClient.tsx
@@ -25,7 +25,6 @@ interface InteractionClientProps {
targetCollection: 'posts' | 'courses'
targetId: number
loginUrl: string
- /** Locale-aware base path for public profiles, e.g. "/users" or "/en/users". */
userProfileBase: string
labels: Labels
}
@@ -37,8 +36,6 @@ export function InteractionClient({
userProfileBase,
labels,
}: InteractionClientProps) {
- // Auth state comes from the client session so the embedding page can stay
- // statically cached for guests and members alike.
const { data: session } = useSession()
const user = session?.user
const isAuthenticated = Boolean(user)
@@ -47,8 +44,6 @@ export function InteractionClient({
user && 'role' in user && (user as { role?: string[] }).role?.includes('admin'),
)
- // Comments/likes only load once the section is near the viewport — page
- // views that never scroll down here don't pay for the data requests.
const rootRef = useRef(null)
const [active, setActive] = useState(false)
useEffect(() => {
@@ -65,7 +60,6 @@ export function InteractionClient({
}, [active])
return (
- // #comments — post-login redirects land here so the user resumes the action in place