public() ->orderBy('created_at', 'desc') ->paginate(10); return view('presence.index', [ 'user' => $user, 'posts' => $posts, ]); } /** * Single post with comments */ public function show($id) { $post = Writing::posts()->public()->findOrFail($id); $comments = $post->comments()->approved()->orderBy('created_at', 'asc')->get(); return view('presence.show', [ 'post' => $post, 'comments' => $comments, ]); } /** * Admin dashboard for posting/managing */ public function admin() { $user = Auth::user(); $posts = Writing::posts() ->where('user_id', $user->id) ->orderBy('created_at', 'desc') ->paginate(20); $pendingComments = Comment::where('is_approved', false)->count(); $recentComments = Comment::orderBy('created_at', 'desc')->limit(10)->get(); return view('presence.admin', [ 'user' => $user, 'posts' => $posts, 'pendingComments' => $pendingComments, 'recentComments' => $recentComments, ]); } /** * Update current status */ public function updateStatus(Request $request) { $validated = $request->validate([ 'statushtml' => 'nullable|string|max:500', ]); $user = Auth::user(); $user->statushtml = $validated['statushtml']; $user->status_updated_at = now(); $user->save(); return redirect()->back()->with('success', 'Status updated!'); } /** * Create new post */ public function storePost(Request $request) { $validated = $request->validate([ 'title' => 'nullable|string|max:255', 'content' => 'required|string|min:1', 'is_public' => 'boolean', ]); Writing::create([ 'title' => $validated['title'] ?? '', 'content' => $validated['content'], 'user_id' => Auth::id(), 'type' => 'post', 'is_public' => $validated['is_public'] ?? true, ]); return redirect()->back()->with('success', 'Post created!'); } /** * Edit post */ public function updatePost(Request $request, $id) { $post = Writing::posts()->where('user_id', Auth::id())->findOrFail($id); $validated = $request->validate([ 'title' => 'nullable|string|max:255', 'content' => 'required|string|min:1', 'is_public' => 'boolean', ]); $post->update([ 'title' => $validated['title'] ?? '', 'content' => $validated['content'], 'is_public' => $validated['is_public'] ?? true, ]); return redirect()->back()->with('success', 'Post updated!'); } /** * Remove post */ public function deletePost($id) { $post = Writing::posts()->where('user_id', Auth::id())->findOrFail($id); $post->delete(); return redirect()->back()->with('success', 'Post deleted.'); } /** * Add comment to post */ public function storeComment(Request $request, $id) { $post = Writing::posts()->public()->findOrFail($id); $key = 'comment:' . $request->ip(); if (RateLimiter::tooManyAttempts($key, 5)) { return redirect()->back()->with('error', 'Too many comments. Please wait a moment.'); } RateLimiter::hit($key, 60); $validated = $request->validate([ 'author_name' => 'required|string|max:100', 'author_email' => 'required|email|max:255', 'content' => 'required|string|min:1|max:2000', ]); Comment::create([ 'writing_id' => $post->id, 'author_name' => $validated['author_name'], 'author_email' => $validated['author_email'], 'content' => $validated['content'], 'is_approved' => true, ]); return redirect()->back()->with('success', 'Comment added!'); } /** * Remove comment (moderation) */ public function deleteComment($id) { $comment = Comment::findOrFail($id); $comment->delete(); return redirect()->back()->with('success', 'Comment removed.'); } /** * Handle contact form submission */ public function contact(Request $request) { $key = 'contact:' . $request->ip(); if (RateLimiter::tooManyAttempts($key, 3)) { return redirect()->back()->with('error', 'Too many messages. Please wait a few minutes.'); } RateLimiter::hit($key, 300); $validated = $request->validate([ 'name' => 'required|string|max:100', 'email' => 'required|email|max:255', 'message' => 'required|string|min:10|max:5000', ]); $owner = User::first(); if ($owner && $owner->email && config('mail.default') !== 'log') { Mail::to($owner->email)->send(new ContactMessage( $validated['name'], $validated['email'], $validated['message'] )); } return redirect()->back()->with('success', 'Message sent! Thank you for reaching out.'); } }