trypost/app/Http/Controllers/PostController.php

331 lines
11 KiB
PHP
Raw Normal View History

2026-01-15 01:13:44 +00:00
<?php
namespace App\Http\Controllers;
use App\Enums\PostPlatform\ContentType;
2026-01-15 01:13:44 +00:00
use App\Enums\PostStatus;
use App\Http\Requests\StorePostRequest;
use App\Http\Requests\UpdatePostRequest;
2026-01-15 17:24:39 +00:00
use App\Jobs\PublishPost;
2026-01-15 01:13:44 +00:00
use App\Models\Post;
use Carbon\Carbon;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Inertia\Inertia;
use Inertia\Response;
class PostController extends Controller
{
public function index(Request $request): Response|RedirectResponse
2026-01-15 01:13:44 +00:00
{
$workspace = $request->user()->currentWorkspace;
if (! $workspace) {
return redirect()->route('workspaces.create');
}
2026-01-15 01:13:44 +00:00
$this->authorize('view', $workspace);
$posts = $workspace->posts()
->with(['postPlatforms.socialAccount', 'user'])
->latest('scheduled_at')
->paginate(20);
return Inertia::render('posts/Index', [
'workspace' => $workspace,
'posts' => $posts,
]);
}
public function calendar(Request $request): Response|RedirectResponse
2026-01-15 01:13:44 +00:00
{
$workspace = $request->user()->currentWorkspace;
if (! $workspace) {
return redirect()->route('workspaces.create');
}
2026-01-15 01:13:44 +00:00
$this->authorize('view', $workspace);
2026-01-15 17:24:39 +00:00
$tz = $workspace->timezone;
2026-01-15 01:13:44 +00:00
2026-01-15 17:24:39 +00:00
$weekStart = $request->input('week')
? Carbon::parse($request->input('week'), $tz)->startOfWeek()
: Carbon::now($tz)->startOfWeek();
$weekEnd = $weekStart->copy()->endOfWeek();
// Convert to UTC for database query
$weekStartUtc = $weekStart->copy()->utc();
$weekEndUtc = $weekEnd->copy()->utc();
2026-01-15 01:13:44 +00:00
$posts = $workspace->posts()
->with(['postPlatforms.socialAccount'])
2026-01-15 17:24:39 +00:00
->whereBetween('scheduled_at', [$weekStartUtc, $weekEndUtc])
2026-01-15 01:13:44 +00:00
->orderBy('scheduled_at')
->get()
2026-01-15 17:24:39 +00:00
->groupBy(fn ($post) => $post->scheduled_at?->setTimezone($tz)->format('Y-m-d'));
2026-01-15 01:13:44 +00:00
return Inertia::render('posts/Calendar', [
'workspace' => $workspace,
'posts' => $posts,
2026-01-15 17:24:39 +00:00
'currentWeekStart' => $weekStart->format('Y-m-d'),
2026-01-15 01:13:44 +00:00
]);
}
public function create(Request $request): RedirectResponse
2026-01-15 01:13:44 +00:00
{
$workspace = $request->user()->currentWorkspace;
if (! $workspace) {
return redirect()->route('workspaces.create');
}
2026-01-15 01:13:44 +00:00
$this->authorize('view', $workspace);
$socialAccounts = $workspace->socialAccounts;
if ($socialAccounts->isEmpty()) {
2026-01-15 17:24:39 +00:00
session()->flash('flash.banner', 'Connect at least one social network before creating a post.');
session()->flash('flash.bannerStyle', 'danger');
return redirect()->route('accounts');
2026-01-15 01:13:44 +00:00
}
2026-01-15 17:24:39 +00:00
// Create a draft post - default to today if no date provided
$date = $request->input('date') ?: Carbon::now($workspace->timezone)->format('Y-m-d');
$scheduledAt = Carbon::parse($date, $workspace->timezone)
->setTime(9, 0)
->utc();
$post = $workspace->posts()->create([
'user_id' => $request->user()->id,
'status' => PostStatus::Draft,
'synced' => true,
2026-01-15 17:24:39 +00:00
'scheduled_at' => $scheduledAt,
2026-01-15 01:13:44 +00:00
]);
2026-01-15 17:24:39 +00:00
// Create post_platforms for each connected account
foreach ($socialAccounts as $account) {
$post->postPlatforms()->create([
'social_account_id' => $account->id,
'platform' => $account->platform->value,
'content' => '',
'content_type' => ContentType::defaultFor($account->platform),
2026-01-15 17:24:39 +00:00
'status' => 'pending',
'enabled' => true,
2026-01-15 17:24:39 +00:00
]);
}
return redirect()->route('posts.edit', $post);
2026-01-15 01:13:44 +00:00
}
public function store(StorePostRequest $request): RedirectResponse
2026-01-15 01:13:44 +00:00
{
$workspace = $request->user()->currentWorkspace;
if (! $workspace) {
return redirect()->route('workspaces.create');
}
2026-01-15 01:13:44 +00:00
$this->authorize('view', $workspace);
$post = $workspace->posts()->create([
'user_id' => $request->user()->id,
'status' => $request->input('status', PostStatus::Draft),
'synced' => $request->input('synced', true),
2026-01-15 01:13:44 +00:00
'scheduled_at' => $request->input('scheduled_at'),
]);
foreach ($request->input('platforms', []) as $platformData) {
$postPlatform = $post->postPlatforms()->create([
'social_account_id' => $platformData['social_account_id'],
'platform' => $platformData['platform'],
'content' => $platformData['content'],
'content_type' => $platformData['content_type'] ?? null,
2026-01-15 01:13:44 +00:00
'status' => 'pending',
'enabled' => $platformData['enabled'] ?? true,
2026-01-15 01:13:44 +00:00
]);
if (! empty($platformData['media_ids'])) {
$postPlatform->media()->whereIn('id', $platformData['media_ids'])->update([
'post_platform_id' => $postPlatform->id,
]);
}
}
$route = $request->input('status') === PostStatus::Scheduled->value
? 'calendar'
: 'posts.index';
2026-01-15 01:13:44 +00:00
2026-01-15 17:24:39 +00:00
session()->flash('flash.banner', 'Post created successfully!');
session()->flash('flash.bannerStyle', 'success');
return redirect()->route($route);
2026-01-15 01:13:44 +00:00
}
public function show(Request $request, Post $post): Response|RedirectResponse
2026-01-15 01:13:44 +00:00
{
$workspace = $request->user()->currentWorkspace;
if (! $workspace) {
return redirect()->route('workspaces.create');
}
2026-01-15 01:13:44 +00:00
$this->authorize('view', $workspace);
if ($post->workspace_id !== $workspace->id) {
abort(404);
}
$post->load(['postPlatforms.socialAccount', 'postPlatforms.media', 'user']);
return Inertia::render('posts/Show', [
'workspace' => $workspace,
'post' => $post,
]);
}
public function edit(Request $request, Post $post): Response|RedirectResponse
2026-01-15 01:13:44 +00:00
{
$workspace = $request->user()->currentWorkspace;
if (! $workspace) {
return redirect()->route('workspaces.create');
}
2026-01-15 01:13:44 +00:00
$this->authorize('view', $workspace);
if ($post->workspace_id !== $workspace->id) {
abort(404);
}
if ($post->status === PostStatus::Published) {
2026-01-15 17:24:39 +00:00
session()->flash('flash.banner', 'Published posts cannot be edited.');
session()->flash('flash.bannerStyle', 'danger');
return redirect()->route('posts.show', $post);
2026-01-15 01:13:44 +00:00
}
$post->load(['postPlatforms.socialAccount', 'postPlatforms.media']);
$socialAccounts = $workspace->socialAccounts;
2026-01-15 17:24:39 +00:00
$platformConfigs = $socialAccounts->mapWithKeys(function ($account) {
$platform = $account->platform;
return [
$account->id => [
'maxContentLength' => $platform->maxContentLength(),
'maxImages' => $platform->maxImages(),
'allowedMediaTypes' => array_map(fn ($type) => $type->value, $platform->allowedMediaTypes()),
'supportsTextOnly' => $platform->supportsTextOnly(),
],
];
});
2026-01-15 01:13:44 +00:00
return Inertia::render('posts/Edit', [
'workspace' => $workspace,
'post' => $post,
'socialAccounts' => $socialAccounts,
2026-01-15 17:24:39 +00:00
'platformConfigs' => $platformConfigs,
2026-01-15 01:13:44 +00:00
]);
}
public function update(UpdatePostRequest $request, Post $post): RedirectResponse
2026-01-15 01:13:44 +00:00
{
$workspace = $request->user()->currentWorkspace;
if (! $workspace) {
return redirect()->route('workspaces.create');
}
2026-01-15 01:13:44 +00:00
$this->authorize('view', $workspace);
if ($post->workspace_id !== $workspace->id) {
abort(404);
}
if ($post->status === PostStatus::Published) {
2026-01-15 17:24:39 +00:00
session()->flash('flash.banner', 'Published posts cannot be edited.');
session()->flash('flash.bannerStyle', 'danger');
return back();
}
$scheduledAt = $post->scheduled_at;
if ($request->has('scheduled_at') && $request->input('scheduled_at')) {
$scheduledAt = Carbon::parse($request->input('scheduled_at'), $workspace->timezone)->utc();
2026-01-15 01:13:44 +00:00
}
2026-01-15 17:24:39 +00:00
$status = $request->input('status', $post->status);
2026-01-15 01:13:44 +00:00
$post->update([
2026-01-15 17:24:39 +00:00
'status' => $status === 'publishing' ? PostStatus::Publishing : $status,
'synced' => $request->input('synced', $post->synced),
2026-01-15 17:24:39 +00:00
'scheduled_at' => $scheduledAt,
2026-01-15 01:13:44 +00:00
]);
2026-01-15 17:24:39 +00:00
// Get selected platform IDs
$selectedPlatformIds = collect($request->input('platforms', []))->pluck('id')->toArray();
// Update all platforms - disable those not selected, update content for selected ones
$post->postPlatforms()->update(['enabled' => false]);
2026-01-15 01:13:44 +00:00
foreach ($request->input('platforms', []) as $platformData) {
$post->postPlatforms()
->where('id', $platformData['id'])
->update([
2026-01-15 17:24:39 +00:00
'enabled' => true,
2026-01-15 01:13:44 +00:00
'content' => $platformData['content'],
'content_type' => $platformData['content_type'] ?? null,
2026-01-15 01:13:44 +00:00
]);
}
2026-01-15 17:24:39 +00:00
// Dispatch publish job if publishing now
if ($status === 'publishing') {
PublishPost::dispatch($post);
session()->flash('flash.banner', 'Post is being published!');
session()->flash('flash.bannerStyle', 'success');
return redirect()->route('posts.show', $post);
2026-01-15 17:24:39 +00:00
}
// Redirect to show page for schedule action
if ($status === 'scheduled') {
session()->flash('flash.banner', 'Post scheduled successfully!');
session()->flash('flash.bannerStyle', 'success');
return redirect()->route('posts.show', $post);
}
// Stay on edit page for save action
session()->flash('flash.banner', 'Post saved!');
2026-01-15 17:24:39 +00:00
session()->flash('flash.bannerStyle', 'success');
return back();
2026-01-15 01:13:44 +00:00
}
public function destroy(Request $request, Post $post): RedirectResponse
2026-01-15 01:13:44 +00:00
{
$workspace = $request->user()->currentWorkspace;
if (! $workspace) {
return redirect()->route('workspaces.create');
}
2026-01-15 01:13:44 +00:00
$this->authorize('view', $workspace);
if ($post->workspace_id !== $workspace->id) {
abort(404);
}
$post->delete();
2026-01-15 17:24:39 +00:00
session()->flash('flash.banner', 'Post deleted successfully!');
session()->flash('flash.bannerStyle', 'success');
return redirect()->route('calendar');
2026-01-15 01:13:44 +00:00
}
}