feat: forum rich-text editor, emoji picker, mentions, discover nav, feed, uploads, profile
Forum: - TipTap WYSIWYG editor with full toolbar - @emoji-mart/react emoji picker (consistent with tweets) - @mention autocomplete with user search API - Fix PHP 8.4 parse errors in Blade templates - Fix thread data display (paginator items) - Align forum page widths to max-w-5xl Discover: - Extract shared _nav.blade.php partial - Add missing nav links to for-you page - Add Following link for authenticated users Feed/Posts: - Post model, controllers, policies, migrations - Feed page components (PostComposer, FeedCard, etc) - Post reactions, comments, saves, reports, sharing - Scheduled publishing support - Link preview controller Profile: - Profile page components (ProfileHero, ProfileTabs) - Profile API controller Uploads: - Upload wizard enhancements - Scheduled publish picker - Studio status bar and readiness checklist
This commit is contained in:
91
resources/js/Pages/Forum/ForumNewThread.jsx
Normal file
91
resources/js/Pages/Forum/ForumNewThread.jsx
Normal file
@@ -0,0 +1,91 @@
|
||||
import React, { useState, useCallback } from 'react'
|
||||
import Breadcrumbs from '../../components/forum/Breadcrumbs'
|
||||
import Button from '../../components/ui/Button'
|
||||
import TextInput from '../../components/ui/TextInput'
|
||||
import RichTextEditor from '../../components/forum/RichTextEditor'
|
||||
|
||||
export default function ForumNewThread({ category, csrfToken, errors = {}, oldValues = {} }) {
|
||||
const [title, setTitle] = useState(oldValues.title ?? '')
|
||||
const [content, setContent] = useState(oldValues.content ?? '')
|
||||
const [submitting, setSubmitting] = useState(false)
|
||||
|
||||
const slug = category?.slug
|
||||
const categoryName = category?.name ?? 'Category'
|
||||
|
||||
const breadcrumbs = [
|
||||
{ label: 'Home', href: '/' },
|
||||
{ label: 'Forum', href: '/forum' },
|
||||
{ label: categoryName, href: slug ? `/forum/${slug}` : '/forum' },
|
||||
{ label: 'New thread' },
|
||||
]
|
||||
|
||||
const handleSubmit = useCallback(async (e) => {
|
||||
e.preventDefault()
|
||||
if (submitting) return
|
||||
setSubmitting(true)
|
||||
|
||||
// Standard form submission to keep server-side validation + redirect
|
||||
e.target.submit()
|
||||
}, [submitting])
|
||||
|
||||
return (
|
||||
<div className="px-4 pt-10 pb-20 sm:px-6 lg:px-8 max-w-3xl mx-auto">
|
||||
<Breadcrumbs items={breadcrumbs} />
|
||||
|
||||
{/* Header */}
|
||||
<div className="mt-5 mb-6">
|
||||
<p className="text-xs font-semibold uppercase tracking-widest text-white/30 mb-1">New thread</p>
|
||||
<h1 className="text-2xl font-bold text-white leading-tight">
|
||||
Create thread in {categoryName}
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
{/* Form */}
|
||||
<form
|
||||
method="POST"
|
||||
action={`/forum/${slug}/new`}
|
||||
onSubmit={handleSubmit}
|
||||
className="space-y-5 rounded-2xl border border-white/[0.06] bg-nova-800/50 p-6 backdrop-blur"
|
||||
>
|
||||
<input type="hidden" name="_token" value={csrfToken} />
|
||||
|
||||
<TextInput
|
||||
label="Title"
|
||||
name="title"
|
||||
value={title}
|
||||
onChange={(e) => setTitle(e.target.value)}
|
||||
required
|
||||
maxLength={255}
|
||||
placeholder="Thread title…"
|
||||
error={errors.title}
|
||||
/>
|
||||
|
||||
{/* Rich text editor */}
|
||||
<div>
|
||||
<label className="mb-1.5 block text-sm font-medium text-white/85">
|
||||
Content <span className="text-red-400 ml-1">*</span>
|
||||
</label>
|
||||
<RichTextEditor
|
||||
content={content}
|
||||
onChange={setContent}
|
||||
placeholder="Write your post…"
|
||||
error={errors.content}
|
||||
minHeight={14}
|
||||
autofocus={false}
|
||||
/>
|
||||
<input type="hidden" name="content" value={content} />
|
||||
</div>
|
||||
|
||||
{/* Submit */}
|
||||
<div className="flex items-center justify-between pt-2">
|
||||
<a href={`/forum/${slug}`} className="text-sm text-zinc-500 hover:text-zinc-300 transition-colors">
|
||||
← Cancel
|
||||
</a>
|
||||
<Button type="submit" variant="primary" size="md" loading={submitting}>
|
||||
Publish thread
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user