Add contract management and invoice settings pages

- Created a new Blade view for managing brand contracts with forms for adding and editing contracts, including client and category selection.
- Implemented success message notifications for contract actions.
- Added a new Blade view for invoice settings, allowing customization of invoice number format, header branding, and default values for new invoices.
- Introduced a new PDF view for generating rate cards with customizable styles based on user profile settings.
- Developed a profile management page for rate cards, enabling users to update their identity, appearance, and visibility settings.
This commit is contained in:
I-Fun
2026-04-01 21:47:34 +07:00
parent d3c35ad730
commit 22f03ccca7
48 changed files with 2415 additions and 296 deletions

View File

@@ -6,6 +6,7 @@ namespace App\Http\Controllers;
use App\Enums\ContentStatus;
use App\Models\Client;
use App\Models\ClientCategory;
use App\Models\ContentBrief;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
@@ -14,6 +15,14 @@ use Illuminate\View\View;
class ContentBriefController extends Controller
{
private function categoryTree(): \Illuminate\Support\Collection
{
return ClientCategory::with('children')
->whereNull('parent_id')
->orderBy('sort_order')
->get();
}
public function index(): View
{
$clients = Client::where('status', 'active')->orderBy('name')->get();
@@ -32,9 +41,10 @@ class ContentBriefController extends Controller
public function create(): View
{
$clients = Client::where('status', 'active')->orderBy('name')->get();
$statuses = ContentStatus::cases();
return view('content.create', compact('clients', 'statuses'));
$clients = Client::where('status', 'active')->orderBy('name')->get();
$statuses = ContentStatus::cases();
$categoryTree = $this->categoryTree();
return view('content.create', compact('clients', 'statuses', 'categoryTree'));
}
public function store(Request $request): RedirectResponse
@@ -42,6 +52,7 @@ class ContentBriefController extends Controller
$validated = $request->validate([
'title' => 'required|string|max:255',
'client_id' => 'nullable|exists:clients,id',
'category_id' => 'nullable|exists:client_categories,id',
'platform' => 'required|in:instagram,tiktok,youtube',
'content_type' => 'required|string|max:50',
'status' => 'required|in:drafting,filming,editing,review,posted,archived',
@@ -69,10 +80,16 @@ class ContentBriefController extends Controller
public function edit(ContentBrief $contentBrief): View
{
$clients = Client::where('status', 'active')->orderBy('name')->get();
$statuses = ContentStatus::cases();
$clients = Client::where('status', 'active')->orderBy('name')->get();
$statuses = ContentStatus::cases();
$categoryTree = $this->categoryTree();
$contentBrief->load('client');
return view('content.edit', ['brief' => $contentBrief, 'clients' => $clients, 'statuses' => $statuses]);
return view('content.edit', [
'brief' => $contentBrief,
'clients' => $clients,
'statuses' => $statuses,
'categoryTree' => $categoryTree,
]);
}
public function update(Request $request, ContentBrief $contentBrief): RedirectResponse
@@ -80,6 +97,7 @@ class ContentBriefController extends Controller
$validated = $request->validate([
'title' => 'required|string|max:255',
'client_id' => 'nullable|exists:clients,id',
'category_id' => 'nullable|exists:client_categories,id',
'platform' => 'required|in:instagram,tiktok,youtube',
'content_type' => 'required|string|max:50',
'status' => 'required|in:drafting,filming,editing,review,posted,archived',