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:
213
resources/views/categories/index.blade.php
Normal file
213
resources/views/categories/index.blade.php
Normal file
@@ -0,0 +1,213 @@
|
||||
@extends('layouts.app')
|
||||
@section('title', 'Categories')
|
||||
@section('page-title', '🏷️ Category Management')
|
||||
@section('page-subtitle', 'Organise clients, schedules & content by category')
|
||||
|
||||
@section('content')
|
||||
<div class="max-w-4xl mx-auto space-y-5">
|
||||
|
||||
@if(session('success'))
|
||||
<div x-data="{ show: true }" x-show="show" x-init="setTimeout(() => show = false, 4000)"
|
||||
class="flex items-center justify-between gap-3 bg-green-50 border border-green-200 rounded-2xl px-4 py-3 text-sm text-green-700">
|
||||
<span>{{ session('success') }}</span>
|
||||
<button @click="show = false" class="text-green-500 hover:text-green-700 text-lg leading-none">✕</button>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
{{-- Add form --}}
|
||||
<div class="cat-card overflow-hidden">
|
||||
<div class="flex items-center gap-3 px-5 py-4 border-b border-pink-50">
|
||||
<span class="text-xl">➕</span>
|
||||
<h2 class="font-bold text-gray-700">Add New Category</h2>
|
||||
</div>
|
||||
<form action="{{ route('client-categories.store') }}" method="POST"
|
||||
class="p-5 grid grid-cols-2 sm:grid-cols-4 gap-3 items-end">
|
||||
@csrf
|
||||
<div>
|
||||
<label class="block text-xs font-semibold text-gray-600 mb-1">Name <span class="text-pink-400">*</span></label>
|
||||
<input type="text" name="name" required maxlength="100"
|
||||
placeholder="e.g. Energy Drinks"
|
||||
class="input-soft" value="{{ old('name') }}">
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs font-semibold text-gray-600 mb-1">Parent (optional)</label>
|
||||
<select name="parent_id" class="input-soft">
|
||||
<option value="">— Root category —</option>
|
||||
@foreach($parents as $p)
|
||||
<option value="{{ $p->id }}" {{ old('parent_id') == $p->id ? 'selected' : '' }}>
|
||||
{{ $p->icon }} {{ $p->name }}
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs font-semibold text-gray-600 mb-1">Icon (emoji)</label>
|
||||
<input type="text" name="icon" maxlength="10" placeholder="🏷️"
|
||||
class="input-soft" value="{{ old('icon') }}">
|
||||
</div>
|
||||
<div class="flex items-end gap-2">
|
||||
<div class="flex-1">
|
||||
<label class="block text-xs font-semibold text-gray-600 mb-1">Color</label>
|
||||
<input type="color" name="color" value="{{ old('color', '#FFB7C5') }}"
|
||||
class="w-full h-[42px] rounded-2xl border border-pink-200 cursor-pointer p-1 bg-white">
|
||||
</div>
|
||||
<button type="submit" class="btn-sakura px-4 py-2.5 shrink-0 text-sm">Add</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{{-- List --}}
|
||||
<div class="cat-card overflow-hidden">
|
||||
<div class="flex items-center gap-3 px-5 py-4 border-b border-pink-50">
|
||||
<span class="text-xl">🗂️</span>
|
||||
<h2 class="font-bold text-gray-700">All Categories</h2>
|
||||
<span class="ml-auto text-xs bg-pink-100 text-pink-600 font-semibold px-2.5 py-0.5 rounded-full">
|
||||
{{ $categories->count() }} total
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@php $roots = $categories->whereNull('parent_id'); @endphp
|
||||
|
||||
@forelse($roots as $root)
|
||||
<div x-data="{ editing: false }" class="border-b border-pink-50 last:border-0">
|
||||
{{-- Root row --}}
|
||||
<div class="flex items-center gap-3 px-5 py-3 hover:bg-pink-50/40 transition-colors">
|
||||
<span class="text-xl w-7 text-center shrink-0">{{ $root->icon ?: '🏷️' }}</span>
|
||||
@if($root->color)
|
||||
<span class="w-3 h-3 rounded-full shrink-0" style="background:{{ $root->color }}"></span>
|
||||
@endif
|
||||
<div class="flex-1 min-w-0">
|
||||
<div class="font-semibold text-gray-700 text-sm">{{ $root->name }}</div>
|
||||
<div class="text-xs text-gray-400">{{ $root->children->count() }} sub · {{ $root->clients_count }} client(s)</div>
|
||||
</div>
|
||||
<div class="flex gap-2 shrink-0">
|
||||
<button @click="editing = !editing"
|
||||
class="text-xs px-3 py-1.5 rounded-full border border-blue-200 text-blue-500 hover:bg-blue-50">
|
||||
✏️ Edit
|
||||
</button>
|
||||
@unless($root->is_system)
|
||||
<form action="{{ route('client-categories.destroy', $root) }}" method="POST"
|
||||
onsubmit="return confirm('Remove this category? Its children will be promoted.')">
|
||||
@csrf @method('DELETE')
|
||||
<button class="text-xs px-3 py-1.5 rounded-full border border-red-100 text-red-400 hover:bg-red-50">
|
||||
🗑️
|
||||
</button>
|
||||
</form>
|
||||
@endunless
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Edit form --}}
|
||||
<div x-show="editing" x-transition style="display:none"
|
||||
class="px-5 py-4 bg-pink-50/30 border-t border-pink-50">
|
||||
<form action="{{ route('client-categories.update', $root) }}" method="POST"
|
||||
class="grid grid-cols-2 sm:grid-cols-4 gap-3 items-end">
|
||||
@csrf @method('PUT')
|
||||
<div>
|
||||
<label class="block text-xs font-semibold text-gray-600 mb-1">Name</label>
|
||||
<input type="text" name="name" required value="{{ $root->name }}" class="input-soft">
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs font-semibold text-gray-600 mb-1">Parent</label>
|
||||
<select name="parent_id" class="input-soft">
|
||||
<option value="">— Root —</option>
|
||||
@foreach($parents as $p)
|
||||
@if($p->id !== $root->id)
|
||||
<option value="{{ $p->id }}" {{ $root->parent_id == $p->id ? 'selected' : '' }}>
|
||||
{{ $p->icon }} {{ $p->name }}
|
||||
</option>
|
||||
@endif
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs font-semibold text-gray-600 mb-1">Icon</label>
|
||||
<input type="text" name="icon" value="{{ $root->icon }}" maxlength="10" class="input-soft">
|
||||
</div>
|
||||
<div class="flex items-end gap-2">
|
||||
<div class="flex-1">
|
||||
<label class="block text-xs font-semibold text-gray-600 mb-1">Color</label>
|
||||
<input type="color" name="color" value="{{ $root->color ?: '#FFB7C5' }}"
|
||||
class="w-full h-[42px] rounded-2xl border border-pink-200 cursor-pointer p-1 bg-white">
|
||||
</div>
|
||||
<button type="submit" class="btn-sakura px-3 py-2.5 text-sm shrink-0">Save</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{{-- Children --}}
|
||||
@foreach($root->children as $child)
|
||||
<div x-data="{ editingC: false }">
|
||||
<div class="flex items-center gap-3 px-5 py-2.5 pl-12 border-t border-pink-50/60 hover:bg-pink-50/20 transition-colors">
|
||||
<span class="text-base w-6 text-center shrink-0">{{ $child->icon ?: '↳' }}</span>
|
||||
@if($child->color)
|
||||
<span class="w-2.5 h-2.5 rounded-full shrink-0" style="background:{{ $child->color }}"></span>
|
||||
@endif
|
||||
<div class="flex-1 min-w-0">
|
||||
<div class="text-sm font-medium text-gray-600">↳ {{ $child->name }}</div>
|
||||
<div class="text-xs text-gray-400">{{ $child->clients_count }} client(s)</div>
|
||||
</div>
|
||||
<div class="flex gap-2 shrink-0">
|
||||
<button @click="editingC = !editingC"
|
||||
class="text-xs px-2.5 py-1 rounded-full border border-blue-200 text-blue-500 hover:bg-blue-50">
|
||||
✏️
|
||||
</button>
|
||||
@unless($child->is_system)
|
||||
<form action="{{ route('client-categories.destroy', $child) }}" method="POST"
|
||||
onsubmit="return confirm('Remove subcategory?')">
|
||||
@csrf @method('DELETE')
|
||||
<button class="text-xs px-2.5 py-1 rounded-full border border-red-100 text-red-400 hover:bg-red-50">
|
||||
🗑️
|
||||
</button>
|
||||
</form>
|
||||
@endunless
|
||||
</div>
|
||||
</div>
|
||||
<div x-show="editingC" x-transition style="display:none"
|
||||
class="px-5 py-4 pl-12 bg-pink-50/20 border-t border-pink-50/60">
|
||||
<form action="{{ route('client-categories.update', $child) }}" method="POST"
|
||||
class="grid grid-cols-2 sm:grid-cols-4 gap-3 items-end">
|
||||
@csrf @method('PUT')
|
||||
<div>
|
||||
<label class="block text-xs font-semibold text-gray-600 mb-1">Name</label>
|
||||
<input type="text" name="name" required value="{{ $child->name }}" class="input-soft">
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs font-semibold text-gray-600 mb-1">Parent</label>
|
||||
<select name="parent_id" class="input-soft">
|
||||
<option value="">— Root —</option>
|
||||
@foreach($parents as $p)
|
||||
@if($p->id !== $child->id)
|
||||
<option value="{{ $p->id }}" {{ $child->parent_id == $p->id ? 'selected' : '' }}>
|
||||
{{ $p->icon }} {{ $p->name }}
|
||||
</option>
|
||||
@endif
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs font-semibold text-gray-600 mb-1">Icon</label>
|
||||
<input type="text" name="icon" value="{{ $child->icon }}" maxlength="10" class="input-soft">
|
||||
</div>
|
||||
<div class="flex items-end gap-2">
|
||||
<div class="flex-1">
|
||||
<label class="block text-xs font-semibold text-gray-600 mb-1">Color</label>
|
||||
<input type="color" name="color" value="{{ $child->color ?: '#FFB7C5' }}"
|
||||
class="w-full h-[42px] rounded-2xl border border-pink-200 cursor-pointer p-1 bg-white">
|
||||
</div>
|
||||
<button type="submit" class="btn-sakura px-3 py-2.5 text-sm shrink-0">Save</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
@empty
|
||||
<div class="text-center py-14 text-gray-400">
|
||||
<div class="text-4xl mb-2">🏷️</div>
|
||||
<p class="text-sm">No categories yet. Add your first one above.</p>
|
||||
</div>
|
||||
@endforelse
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
Reference in New Issue
Block a user