diff --git a/web-next/app/[locale]/forum/[forumId]/page.tsx b/web-next/app/[locale]/forum/[forumId]/page.tsx index 5fded4f..9f89299 100644 --- a/web-next/app/[locale]/forum/[forumId]/page.tsx +++ b/web-next/app/[locale]/forum/[forumId]/page.tsx @@ -2,6 +2,8 @@ import { notFound } from 'next/navigation' import { getTranslations, setRequestLocale } from 'next-intl/server' import { Link } from '@/i18n/navigation' import { getForum, getTopics } from '@/lib/forum' +import { getSession } from '@/lib/session' +import { NewTopicForm } from '@/components/NewTopicForm' export const dynamic = 'force-dynamic' @@ -18,6 +20,8 @@ export default async function ForumPage({ const forum = await getForum(id) if (!forum) notFound() const topics = await getTopics(id) + const session = await getSession() + const canPost = Boolean(session.username) return (
@@ -52,6 +56,12 @@ export default async function ForumPage({ ))} )} + + {canPost ? ( + + ) : ( +

{t('loginToPost')}

+ )}
) } diff --git a/web-next/app/[locale]/forum/topic/[topicId]/page.tsx b/web-next/app/[locale]/forum/topic/[topicId]/page.tsx index e24fe31..d1f00ff 100644 --- a/web-next/app/[locale]/forum/topic/[topicId]/page.tsx +++ b/web-next/app/[locale]/forum/topic/[topicId]/page.tsx @@ -2,6 +2,8 @@ import { notFound } from 'next/navigation' import { getTranslations, setRequestLocale } from 'next-intl/server' import { Link } from '@/i18n/navigation' import { getTopic, getPosts } from '@/lib/forum' +import { getSession } from '@/lib/session' +import { ReplyForm } from '@/components/ReplyForm' export const dynamic = 'force-dynamic' @@ -18,6 +20,8 @@ export default async function TopicPage({ const topic = await getTopic(id) if (!topic) notFound() const posts = await getPosts(id) + const session = await getSession() + const canReply = Boolean(session.username) && !topic!.locked return (
@@ -47,6 +51,12 @@ export default async function TopicPage({ ))} + + {canReply ? ( + + ) : ( + !session.username &&

{t('loginToPost')}

+ )}
) } diff --git a/web-next/app/api/forum/reply/route.ts b/web-next/app/api/forum/reply/route.ts new file mode 100644 index 0000000..04aef94 --- /dev/null +++ b/web-next/app/api/forum/reply/route.ts @@ -0,0 +1,15 @@ +import { getSession } from '@/lib/session' +import { createPost, topicIsReplyable } from '@/lib/forum-write' + +export async function POST(request: Request) { + const session = await getSession() + if (!session.accountId || !session.username) return Response.json({ success: false, error: 'notAuthenticated' }, { status: 401 }) + let b: Record = {} + try { b = await request.json() } catch { return Response.json({ success: false, error: 'invalidRequest' }, { status: 400 }) } + const topicId = Number(b.topicId) + const text = String(b.text ?? '').trim() + if (!topicId || !text) return Response.json({ success: false, error: 'emptyError' }) + if (!(await topicIsReplyable(topicId))) return Response.json({ success: false, error: 'topicLocked' }) + await createPost(topicId, session.username, session.accountId, text) + return Response.json({ success: true }) +} diff --git a/web-next/app/api/forum/topic/route.ts b/web-next/app/api/forum/topic/route.ts new file mode 100644 index 0000000..38b9353 --- /dev/null +++ b/web-next/app/api/forum/topic/route.ts @@ -0,0 +1,16 @@ +import { getSession } from '@/lib/session' +import { createTopic, forumIsPostable } from '@/lib/forum-write' + +export async function POST(request: Request) { + const session = await getSession() + if (!session.accountId || !session.username) return Response.json({ success: false, error: 'notAuthenticated' }, { status: 401 }) + let b: Record = {} + try { b = await request.json() } catch { return Response.json({ success: false, error: 'invalidRequest' }, { status: 400 }) } + const forumId = Number(b.forumId) + const name = String(b.name ?? '').trim() + const text = String(b.text ?? '').trim() + if (!forumId || !name || !text) return Response.json({ success: false, error: 'emptyError' }) + if (!(await forumIsPostable(forumId))) return Response.json({ success: false, error: 'invalidForum' }) + const topicId = await createTopic(forumId, name, session.username, session.accountId, text) + return Response.json({ success: true, topicId }) +} diff --git a/web-next/components/NewTopicForm.tsx b/web-next/components/NewTopicForm.tsx new file mode 100644 index 0000000..9fcadc9 --- /dev/null +++ b/web-next/components/NewTopicForm.tsx @@ -0,0 +1,51 @@ +'use client' + +import { useState } from 'react' +import { useTranslations } from 'next-intl' +import { useRouter } from '@/i18n/navigation' + +export function NewTopicForm({ forumId }: { forumId: number }) { + const t = useTranslations('Forum') + const router = useRouter() + const [name, setName] = useState('') + const [text, setText] = useState('') + const [busy, setBusy] = useState(false) + const [error, setError] = useState(null) + + async function handleSubmit(e: React.FormEvent) { + e.preventDefault() + if (busy || !name.trim() || !text.trim()) return + setBusy(true) + setError(null) + try { + const res = await fetch('/api/forum/topic', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + credentials: 'same-origin', + body: JSON.stringify({ forumId, name, text }), + }) + const data: { success?: boolean; topicId?: number } = await res.json() + if (data.success && data.topicId) router.push(`/forum/topic/${data.topicId}`) + else { + setError(t('genericError')) + setBusy(false) + } + } catch { + setError(t('genericError')) + setBusy(false) + } + } + + const field = 'w-full rounded border border-amber-900/60 bg-[#2c1e14] px-3 py-2' + return ( +
+

{t('newTopic')}

+ setName(e.target.value)} placeholder={t('newTopicName')} maxLength={200} className={field} /> +