mirror of
https://github.com/m1ngsama/php.git
synced 2025-12-24 16:01:19 +00:00
Add post creation and display features
Implemented post creation form with multiple content types. Added detailed post view with nested comment threading.
This commit is contained in:
parent
d0f10e0590
commit
2e3a97c09d
3 changed files with 257 additions and 0 deletions
80
resources/views/partials/comment.blade.php
Normal file
80
resources/views/partials/comment.blade.php
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
<div class="mb-4" style="margin-left: {{ $depth * 20 }}px;">
|
||||
<div class="border-l-2 border-gray-200 pl-4">
|
||||
<div class="flex items-start mb-2">
|
||||
<div class="flex flex-col items-center mr-2">
|
||||
@auth
|
||||
<form action="{{ route('comments.vote', $comment) }}" method="POST">
|
||||
@csrf
|
||||
<input type="hidden" name="vote" value="1">
|
||||
<button type="submit" class="text-gray-400 hover:text-orange-600 text-xs">▲</button>
|
||||
</form>
|
||||
@else
|
||||
<span class="text-gray-400 text-xs">▲</span>
|
||||
@endauth
|
||||
|
||||
<span class="text-xs font-bold {{ $comment->votes > 0 ? 'text-orange-600' : ($comment->votes < 0 ? 'text-blue-600' : 'text-gray-600') }}">
|
||||
{{ $comment->votes }}
|
||||
</span>
|
||||
|
||||
@auth
|
||||
<form action="{{ route('comments.vote', $comment) }}" method="POST">
|
||||
@csrf
|
||||
<input type="hidden" name="vote" value="-1">
|
||||
<button type="submit" class="text-gray-400 hover:text-blue-600 text-xs">▼</button>
|
||||
</form>
|
||||
@else
|
||||
<span class="text-gray-400 text-xs">▼</span>
|
||||
@endauth
|
||||
</div>
|
||||
|
||||
<div class="flex-1">
|
||||
<div class="text-sm text-gray-600 mb-1">
|
||||
<a href="{{ route('users.show', $comment->user) }}" class="font-bold hover:underline">u/{{ $comment->user->name }}</a>
|
||||
• {{ $comment->created_at->diffForHumans() }}
|
||||
</div>
|
||||
<p class="text-gray-800 whitespace-pre-wrap">{{ $comment->content }}</p>
|
||||
|
||||
@auth
|
||||
<div class="mt-2 text-sm">
|
||||
<button onclick="toggleReplyForm({{ $comment->id }})" class="text-gray-600 hover:underline">Reply</button>
|
||||
@if($comment->user_id === auth()->id())
|
||||
<form action="{{ route('comments.destroy', $comment) }}" method="POST" class="inline ml-2">
|
||||
@csrf
|
||||
@method('DELETE')
|
||||
<button type="submit" class="text-red-600 hover:underline" onclick="return confirm('Are you sure?')">Delete</button>
|
||||
</form>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div id="reply-form-{{ $comment->id }}" class="hidden mt-2">
|
||||
<form action="{{ route('comments.store', $comment->post) }}" method="POST">
|
||||
@csrf
|
||||
<input type="hidden" name="parent_id" value="{{ $comment->id }}">
|
||||
<textarea name="content" rows="3" required
|
||||
class="w-full px-3 py-2 border rounded focus:outline-none focus:border-orange-500"></textarea>
|
||||
<button type="submit" class="mt-2 bg-orange-600 text-white px-4 py-2 rounded hover:bg-orange-700 text-sm">
|
||||
Reply
|
||||
</button>
|
||||
<button type="button" onclick="toggleReplyForm({{ $comment->id }})" class="mt-2 text-gray-600 hover:underline text-sm ml-2">
|
||||
Cancel
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
@endauth
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@foreach($comment->replies as $reply)
|
||||
@include('partials.comment', ['comment' => $reply, 'depth' => $depth + 1])
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if($depth === 0)
|
||||
<script>
|
||||
function toggleReplyForm(commentId) {
|
||||
const form = document.getElementById('reply-form-' + commentId);
|
||||
form.classList.toggle('hidden');
|
||||
}
|
||||
</script>
|
||||
@endif
|
||||
88
resources/views/posts/create.blade.php
Normal file
88
resources/views/posts/create.blade.php
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
@extends('layout')
|
||||
|
||||
@section('title', 'Create Post')
|
||||
|
||||
@section('content')
|
||||
<div class="max-w-2xl mx-auto bg-white rounded-lg shadow p-8">
|
||||
<h1 class="text-2xl font-bold mb-6">Create a Post</h1>
|
||||
|
||||
<form action="{{ route('posts.store') }}" method="POST">
|
||||
@csrf
|
||||
|
||||
<div class="mb-4">
|
||||
<label for="community_id" class="block text-gray-700 font-bold mb-2">Community</label>
|
||||
<select id="community_id" name="community_id" required
|
||||
class="w-full px-3 py-2 border rounded focus:outline-none focus:border-orange-500">
|
||||
<option value="">Select a community</option>
|
||||
@foreach($communities as $community)
|
||||
<option value="{{ $community->id }}" {{ old('community_id') == $community->id ? 'selected' : '' }}>
|
||||
r/{{ $community->name }}
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
@error('community_id')
|
||||
<p class="text-red-500 text-sm mt-1">{{ $message }}</p>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<label for="type" class="block text-gray-700 font-bold mb-2">Post Type</label>
|
||||
<select id="type" name="type" required
|
||||
class="w-full px-3 py-2 border rounded focus:outline-none focus:border-orange-500">
|
||||
<option value="text" {{ old('type') == 'text' ? 'selected' : '' }}>Text</option>
|
||||
<option value="link" {{ old('type') == 'link' ? 'selected' : '' }}>Link</option>
|
||||
<option value="image" {{ old('type') == 'image' ? 'selected' : '' }}>Image</option>
|
||||
</select>
|
||||
@error('type')
|
||||
<p class="text-red-500 text-sm mt-1">{{ $message }}</p>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<label for="title" class="block text-gray-700 font-bold mb-2">Title</label>
|
||||
<input type="text" id="title" name="title" value="{{ old('title') }}" required
|
||||
class="w-full px-3 py-2 border rounded focus:outline-none focus:border-orange-500">
|
||||
@error('title')
|
||||
<p class="text-red-500 text-sm mt-1">{{ $message }}</p>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="mb-4" id="content-field">
|
||||
<label for="content" class="block text-gray-700 font-bold mb-2">Content</label>
|
||||
<textarea id="content" name="content" rows="6"
|
||||
class="w-full px-3 py-2 border rounded focus:outline-none focus:border-orange-500">{{ old('content') }}</textarea>
|
||||
@error('content')
|
||||
<p class="text-red-500 text-sm mt-1">{{ $message }}</p>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="mb-6 hidden" id="url-field">
|
||||
<label for="url" class="block text-gray-700 font-bold mb-2">URL</label>
|
||||
<input type="url" id="url" name="url" value="{{ old('url') }}"
|
||||
class="w-full px-3 py-2 border rounded focus:outline-none focus:border-orange-500">
|
||||
@error('url')
|
||||
<p class="text-red-500 text-sm mt-1">{{ $message }}</p>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<button type="submit" class="bg-orange-600 text-white px-6 py-2 rounded hover:bg-orange-700 font-bold">
|
||||
Create Post
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.getElementById('type').addEventListener('change', function() {
|
||||
const contentField = document.getElementById('content-field');
|
||||
const urlField = document.getElementById('url-field');
|
||||
|
||||
if (this.value === 'text') {
|
||||
contentField.classList.remove('hidden');
|
||||
urlField.classList.add('hidden');
|
||||
} else {
|
||||
contentField.classList.add('hidden');
|
||||
urlField.classList.remove('hidden');
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@endsection
|
||||
89
resources/views/posts/show.blade.php
Normal file
89
resources/views/posts/show.blade.php
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
@extends('layout')
|
||||
|
||||
@section('title', $post->title)
|
||||
|
||||
@section('content')
|
||||
<div class="max-w-4xl mx-auto">
|
||||
<div class="bg-white rounded-lg shadow p-6 mb-6">
|
||||
<div class="flex">
|
||||
<div class="flex flex-col items-center mr-4">
|
||||
@auth
|
||||
<form action="{{ route('posts.vote', $post) }}" method="POST">
|
||||
@csrf
|
||||
<input type="hidden" name="vote" value="1">
|
||||
<button type="submit" class="text-gray-400 hover:text-orange-600">▲</button>
|
||||
</form>
|
||||
@else
|
||||
<span class="text-gray-400">▲</span>
|
||||
@endauth
|
||||
|
||||
<span class="font-bold text-lg {{ $post->votes > 0 ? 'text-orange-600' : ($post->votes < 0 ? 'text-blue-600' : 'text-gray-600') }}">
|
||||
{{ $post->votes }}
|
||||
</span>
|
||||
|
||||
@auth
|
||||
<form action="{{ route('posts.vote', $post) }}" method="POST">
|
||||
@csrf
|
||||
<input type="hidden" name="vote" value="-1">
|
||||
<button type="submit" class="text-gray-400 hover:text-blue-600">▼</button>
|
||||
</form>
|
||||
@else
|
||||
<span class="text-gray-400">▼</span>
|
||||
@endauth
|
||||
</div>
|
||||
|
||||
<div class="flex-1">
|
||||
<div class="text-sm text-gray-600 mb-2">
|
||||
<a href="{{ route('communities.show', $post->community) }}" class="font-bold hover:underline">r/{{ $post->community->name }}</a>
|
||||
• Posted by <a href="{{ route('users.show', $post->user) }}" class="hover:underline">u/{{ $post->user->name }}</a>
|
||||
• {{ $post->created_at->diffForHumans() }}
|
||||
</div>
|
||||
<h1 class="text-2xl font-bold mb-4">{{ $post->title }}</h1>
|
||||
@if($post->content)
|
||||
<p class="text-gray-700 mb-4 whitespace-pre-wrap">{{ $post->content }}</p>
|
||||
@endif
|
||||
@if($post->url)
|
||||
<a href="{{ $post->url }}" target="_blank" class="text-blue-600 hover:underline">{{ $post->url }}</a>
|
||||
@endif
|
||||
|
||||
@auth
|
||||
@if($post->user_id === auth()->id())
|
||||
<form action="{{ route('posts.destroy', $post) }}" method="POST" class="mt-4">
|
||||
@csrf
|
||||
@method('DELETE')
|
||||
<button type="submit" class="text-red-600 hover:underline" onclick="return confirm('Are you sure?')">Delete Post</button>
|
||||
</form>
|
||||
@endif
|
||||
@endauth
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@auth
|
||||
<div class="bg-white rounded-lg shadow p-6 mb-6">
|
||||
<h2 class="text-xl font-bold mb-4">Add a Comment</h2>
|
||||
<form action="{{ route('comments.store', $post) }}" method="POST">
|
||||
@csrf
|
||||
<textarea name="content" rows="4" required
|
||||
class="w-full px-3 py-2 border rounded focus:outline-none focus:border-orange-500"></textarea>
|
||||
@error('content')
|
||||
<p class="text-red-500 text-sm mt-1">{{ $message }}</p>
|
||||
@enderror
|
||||
<button type="submit" class="mt-2 bg-orange-600 text-white px-4 py-2 rounded hover:bg-orange-700">
|
||||
Comment
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
@endauth
|
||||
|
||||
<div class="bg-white rounded-lg shadow p-6">
|
||||
<h2 class="text-xl font-bold mb-4">Comments ({{ $post->comments->count() }})</h2>
|
||||
|
||||
@forelse($post->comments->whereNull('parent_id') as $comment)
|
||||
@include('partials.comment', ['comment' => $comment, 'depth' => 0])
|
||||
@empty
|
||||
<p class="text-gray-600">No comments yet. Be the first to comment!</p>
|
||||
@endforelse
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
Loading…
Reference in a new issue