Files
Kol-Manager/resources/views/clients/show.blade.php

234 lines
12 KiB
PHP

@extends('layouts.app')
@section('title', $client->name)
@section('page-title', $client->name)
@section('page-subtitle', $client->company ?? $client->email ?? 'Client Profile')
@section('content')
<div class="max-w-5xl mx-auto">
{{-- Profile Header --}}
<div class="cat-card p-4 mb-4"
x-data="{
avatarUrl: '{{ $client->avatar ? asset('storage/' . $client->avatar) : '' }}',
uploading: false,
async pickAvatar(input) {
if (!input.files.length) return;
this.uploading = true;
const fd = new FormData();
fd.append('avatar', input.files[0]);
fd.append('_token', document.querySelector('meta[name=csrf-token]').content);
try {
const res = await fetch('{{ route('clients.upload-avatar', $client->id, false) }}', {
method: 'POST',
body: fd,
headers: { 'Accept': 'application/json' }
});
const data = await res.json();
if (res.ok) {
this.avatarUrl = data.url + '?t=' + Date.now();
} else {
alert(data.message || 'Upload failed');
}
} catch (err) {
console.error('Avatar upload error:', err);
alert('Network Error. Could not upload.');
}
this.uploading = false;
input.value = '';
},
async removeAvatar() {
if (!confirm('Remove profile picture?')) return;
const fd = new FormData();
fd.append('_token', document.querySelector('meta[name=csrf-token]').content);
fd.append('_method', 'DELETE');
try {
await fetch('{{ route('clients.delete-avatar', $client->id, false) }}', {
method: 'POST',
body: fd,
headers: { 'Accept': 'application/json' }
});
this.avatarUrl = '';
} catch (err) {
console.error(err);
}
}
}">
<div class="flex items-start gap-4">
{{-- Avatar with upload overlay --}}
<div class="relative shrink-0 group">
<template x-if="avatarUrl">
<img :src="avatarUrl" alt="{{ $client->name }}"
class="w-16 h-16 rounded-3xl object-cover shadow border border-pink-100">
</template>
<template x-if="!avatarUrl">
<div class="w-16 h-16 rounded-3xl flex items-center justify-center text-white font-bold text-xl shadow"
style="background: linear-gradient(135deg, #FFB7C5, #E8D5F5);">
{{ $client->initials }}
</div>
</template>
{{-- Upload overlay --}}
<label class="absolute inset-0 rounded-3xl bg-black/30 flex items-center justify-center
opacity-0 group-hover:opacity-100 transition-opacity cursor-pointer"
:class="{ 'opacity-100': uploading }"
title="Change photo">
<span x-show="!uploading" class="text-white text-lg">📷</span>
<span x-show="uploading" class="text-white text-xs">…</span>
<input type="file" accept="image/*" class="hidden" @change="pickAvatar($event.target)">
</label>
{{-- Remove Photo Button (Top Left) --}}
<button x-show="avatarUrl" @click.prevent="removeAvatar()"
class="absolute -top-2 -left-2 bg-red-100 text-red-500 rounded-full w-6 h-6 flex items-center justify-center hover:bg-red-200 shadow text-xs z-10 border border-white"
title="Remove Photo">
✕
</button>
</div>
<div class="flex-1 min-w-0">
<h2 class="text-lg font-bold text-gray-800 leading-tight">{{ $client->name }}</h2>
@if($client->company) <p class="text-sm text-gray-500">{{ $client->company }}</p> @endif
<div class="flex gap-2 mt-2 flex-wrap">
<span class="badge {{ $client->status->badgeClass() }}">{{ $client->status->label() }}</span>
@if($client->ig_handle)
<span class="text-xs bg-pink-50 text-pink-600 px-2 py-1 rounded-full">📸 {{ $client->ig_handle }}</span>
@endif
@if($client->tiktok_handle)
<span class="text-xs bg-purple-50 text-purple-600 px-2 py-1 rounded-full">🎵 {{ $client->tiktok_handle }}</span>
@endif
@if($client->youtube_handle)
<span class="text-xs bg-red-50 text-red-600 px-2 py-1 rounded-full">▶️ {{ $client->youtube_handle }}</span>
@endif
</div>
</div>
</div>
<div class="flex gap-2 mt-3 flex-wrap">
<a href="{{ route('clients.edit', $client) }}" class="btn-sakura text-sm px-4 py-2">Edit</a>
<a href="{{ route('invoices.create') }}?client={{ $client->id }}"
class="text-sm px-4 py-2 rounded-full border border-pink-200 text-gray-600 hover:bg-pink-50 font-semibold">
🧾 New Invoice
</a>
</div>
</div>
<div class="grid grid-cols-1 lg:grid-cols-3 gap-4">
{{-- Contact Info --}}
<div class="cat-card p-4">
<h3 class="font-bold text-gray-700 mb-3 text-sm flex items-center gap-2">📋 Contact Info</h3>
<div class="space-y-2 text-sm">
@if($client->email)
<div class="flex gap-2 items-start">
<span class="text-gray-400 shrink-0">✉️</span>
<a href="mailto:{{ $client->email }}" class="text-pink-500 hover:underline break-all">{{ $client->email }}</a>
</div>
@endif
@if($client->phone)
<div class="flex gap-2 items-start">
<span class="text-gray-400 shrink-0">📞</span>
<span>{{ $client->phone }}</span>
</div>
@endif
@if($client->full_address)
<div class="flex gap-2 items-start">
<span class="text-gray-400 shrink-0">📍</span>
<span class="text-gray-600">{{ $client->full_address }}</span>
</div>
@endif
@if($client->notes)
<div class="mt-3 pt-3 border-t border-pink-50">
<p class="text-xs font-semibold text-gray-500 mb-1">Notes</p>
<p class="text-gray-600 text-xs">{{ $client->notes }}</p>
</div>
@endif
@if(!$client->email && !$client->phone && !$client->full_address && !$client->notes)
<p class="text-xs text-gray-400">No contact info yet.</p>
@endif
</div>
</div>
{{-- Recent Events --}}
<div class="cat-card p-4">
<div class="flex items-center justify-between mb-3">
<h3 class="font-bold text-gray-700 text-sm flex items-center gap-2">📅 Events</h3>
<a href="{{ route('schedule.index') }}" class="text-xs text-pink-500">All →</a>
</div>
@forelse($client->events as $event)
<div class="py-2 border-b border-pink-50 last:border-0 text-sm">
<div class="font-medium text-gray-700 truncate">{{ $event->title }}</div>
<div class="text-xs text-gray-400">{{ $event->start_time->format('d M Y, H:i') }}</div>
</div>
@empty
<p class="text-xs text-gray-400">No events yet.</p>
@endforelse
</div>
{{-- Recent Invoices --}}
<div class="cat-card p-4">
<div class="flex items-center justify-between mb-3">
<h3 class="font-bold text-gray-700 text-sm flex items-center gap-2">🧾 Invoices</h3>
<a href="{{ route('invoices.index') }}" class="text-xs text-pink-500">All →</a>
</div>
@forelse($client->invoices as $invoice)
<div class="py-2 border-b border-pink-50 last:border-0 text-sm flex justify-between gap-2">
<div class="min-w-0">
<div class="font-medium text-gray-700 truncate">{{ $invoice->invoice_number }}</div>
<div class="text-xs text-gray-400">Due {{ $invoice->due_date->format('d M Y') }}</div>
</div>
<div class="text-right shrink-0">
<div class="font-bold text-gray-700 text-xs">{{ $invoice->formatted_total }}</div>
<span class="badge {{ $invoice->status->badgeClass() }} badge-xs">{{ $invoice->status->label() }}</span>
</div>
</div>
@empty
<p class="text-xs text-gray-400">No invoices yet.</p>
@endforelse
</div>
</div>
{{-- Content Briefs --}}
@if($client->contentBriefs->isNotEmpty())
<div class="cat-card p-4 mt-4">
<h3 class="font-bold text-gray-700 mb-3 text-sm flex items-center gap-2">🎬 Content Briefs</h3>
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3">
@foreach($client->contentBriefs as $brief)
<a href="{{ route('content.show', $brief) }}"
class="bg-pink-50 rounded-2xl p-3 hover:bg-pink-100 transition-colors block">
<div class="text-xs font-bold text-pink-600 flex items-center gap-1">
{{ $brief->platform_icon }} {{ ucfirst($brief->platform) }}
</div>
<div class="font-semibold text-gray-700 text-sm truncate mt-1">{{ $brief->title }}</div>
<div class="text-xs text-gray-400 mt-0.5">{{ $brief->status->label() }}</div>
</a>
@endforeach
</div>
</div>
@endif
{{-- Uploaded Files --}}
@if($client->mediaFiles->isNotEmpty())
<div class="cat-card p-4 mt-4">
<div class="flex items-center justify-between mb-3">
<h3 class="font-bold text-gray-700 text-sm flex items-center gap-2">📁 Files</h3>
<a href="{{ route('files.index') }}?client_id={{ $client->id }}" class="text-xs text-pink-500">All Files →</a>
</div>
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3">
@foreach($client->mediaFiles as $file)
<a href="{{ route('files.serve', $file) }}" target="_blank"
class="bg-blue-50 rounded-2xl p-3 hover:bg-blue-100 transition-colors flex items-center gap-3">
<div class="shrink-0 text-xl border border-blue-200 rounded-lg w-10 h-10 flex items-center justify-center bg-white">
📄
</div>
<div class="min-w-0 flex-1">
<div class="font-semibold text-gray-700 text-sm truncate" title="{{ $file->name }}">{{ $file->name }}</div>
<div class="text-xs text-gray-400 mt-0.5">{{ number_format($file->size / 1024, 1) }} KB</div>
</div>
</a>
@endforeach
</div>
</div>
@endif
</div>
@endsection