@extends('layouts.app') @section('title', $proposal->title) @section('content')
@php $sv = $proposal->status instanceof \App\Enums\ProposalStatus ? $proposal->status->value : $proposal->status; $currencyValue = $proposal->currency instanceof \App\Enums\Currency ? $proposal->currency->value : $proposal->currency; $isOverdue = $proposal->valid_until->isPast() && in_array($sv, ['draft','sent']); $daysRemaining = now()->diffInDays($proposal->valid_until, false); $pSv = $proposal->project?->status instanceof \App\Enums\ProjectStatus ? $proposal->project->status->value : $proposal->project?->status; $badgeClass = match($sv) { 'draft' => 'bg-slate-100 text-slate-600', 'sent' => 'bg-sky-50 text-sky-700', 'approved' => 'bg-emerald-50 text-emerald-700', 'rejected' => 'bg-red-50 text-red-600', 'expired' => 'bg-amber-50 text-amber-700', default => 'bg-slate-100 text-slate-600', }; $currencySymbol = $proposal->currency instanceof \App\Enums\Currency ? $proposal->currency->symbol() : (string) $proposal->currency; @endphp {{-- Flash messages --}} @if (session('success'))
{{ session('success') }}
@endif @if (session('error'))
{{ session('error') }}
@endif {{-- Back link --}} Proposals {{-- Page header --}}

{{ $proposal->title }}

{{ $proposal->client->name }} · {{ $proposal->project?->title }}

@can('proposals.edit') Edit @endcan Download PDF @can('proposals.delete')
@csrf @method('DELETE')
@endcan
{{-- 3-column grid --}}
{{-- LEFT: Main content (2/3) --}}
{{-- PRIORITY 1 — Hero value card --}}
{{-- Amount + currency + status --}}
{{ $currencySymbol }} {{ number_format((float) $proposal->amount, 2) }} {{ $currencyValue }}
{{ ucfirst($sv) }}
{{-- Validity countdown --}}
Valid until {{ $proposal->valid_until->format('d M Y') }} @if ($isOverdue) Expired {{ abs((int) $daysRemaining) }} {{ Str::plural('day', abs((int) $daysRemaining)) }} ago @elseif ($daysRemaining >= 0) {{ (int) $daysRemaining }} {{ Str::plural('day', (int) $daysRemaining) }} remaining @endif
{{-- PRIORITY 2 — Scope of work card --}}

Scope of work

{{ $proposal->scope }}

@if ($proposal->notes)

Notes

{{ $proposal->notes }}

@endif
{{-- RIGHT: Sidebar (1/3) --}}
{{-- Card A — Client & project --}}

Client & project

Client

{{ $proposal->client->name }}

{{ $proposal->client->email }}

Project

{{ $proposal->project?->title }}

@if($pSv) {{ ucfirst(str_replace('_', ' ', $pSv)) }} @endif
{{-- Card B — Update status --}} @can('proposals.edit')

Update status

Current status

{{ ucfirst($sv) }}
@csrf @method('PATCH')
@endcan {{-- Card C — Invoice --}} @if ($proposal->invoice) @php $inv = $proposal->invoice; $invSv = $inv->status instanceof \App\Enums\InvoiceStatus ? $inv->status->value : $inv->status; $invSymbol = $inv->currency instanceof \App\Enums\Currency ? $inv->currency->symbol() : (string) $inv->currency; $invBadge = match($invSv) { 'paid' => 'bg-emerald-50 text-emerald-700', 'partial' => 'bg-sky-50 text-sky-700', default => 'bg-amber-50 text-amber-700', }; @endphp

Invoice

{{ $inv->invoice_number }} {{ ucfirst($invSv) }}

{{ $invSymbol }} {{ number_format((float) $inv->amount, 2) }}

Due {{ $inv->due_date->format('d M Y') }}

View Invoice →
@else

Invoice

Invoice appears once the proposal is approved

@endif {{-- Card E — Client Deck --}}

Client Deck

@if ($deckUrl) {{-- Deck link exists --}}
{{-- Copyable URL --}}
{{-- Deck status --}}
@if ($proposal->deck_approved_at) Approved {{ $proposal->deck_approved_at->diffForHumans() }} @elseif ($proposal->deck_rejected_at)
Declined {{ $proposal->deck_rejected_at->diffForHumans() }} @if ($proposal->deck_rejection_reason)

"{{ Str::limit($proposal->deck_rejection_reason, 60) }}"

@endif
@elseif ($proposal->deck_viewed_at) Viewed {{ $proposal->deck_viewed_at->diffForHumans() }} @else Not yet viewed @endif
{{-- Action links --}}
Preview → @can('proposals.edit')
@csrf
@endcan
@else {{-- No deck link yet --}} @can('proposals.edit')
@csrf

Share a professional proposal page with your client — no login required.

@else

No deck link generated yet.

@endcan @endif
{{-- Card D — Metadata --}}

Details

Created {{ $proposal->created_at->format('d M Y') }}
Updated {{ $proposal->updated_at->format('d M Y') }}
Proposal ID #{{ $proposal->id }}
{{-- Card F — Payment Milestones --}}

Payment Milestones

@if ($proposal->milestones->count()) @php $milestoneTotal = $proposal->milestones->reduce(fn($carry, $m) => bcadd($carry, (string) $m->amount, 2), '0.00'); $proposalAmount = number_format((float) $proposal->amount, 2, '.', ''); $milestoneMismatch = bccomp($milestoneTotal, $proposalAmount, 2) !== 0; @endphp {{ $currencySymbol }}{{ number_format((float) $milestoneTotal, 2) }} / {{ $currencySymbol }}{{ number_format((float) $proposal->amount, 2) }} @endif
@forelse ($proposal->milestones as $milestone) @php $mStatus = $milestone->status; $mBadge = match($mStatus) { 'paid' => 'bg-emerald-50 text-emerald-700', 'invoiced' => 'bg-sky-50 text-sky-700', default => 'bg-amber-50 text-amber-700', }; $mTriggerLabel = match($milestone->due_trigger) { 'on_signing' => 'On signing', 'on_milestone' => 'On milestone', 'on_delivery' => 'On delivery', 'custom_date' => $milestone->due_date?->format('d M Y') ?? 'Custom date', default => $milestone->due_trigger, }; @endphp

{{ $milestone->title }}

@if ($milestone->description)

{{ $milestone->description }}

@endif

{{ $mTriggerLabel }}

{{ $currencySymbol }}{{ number_format((float) $milestone->amount, 2) }}

@if ($milestone->percentage)

{{ number_format((float) $milestone->percentage, 1) }}%

@endif {{ ucfirst($mStatus) }}
@can('proposals.edit') @if ($mStatus === 'pending')
@csrf @method('DELETE')
@endif @endcan
@empty

No milestones added yet.

@endforelse {{-- Add Milestone form --}} @can('proposals.edit')
@csrf
@endcan
{{-- Card G — Signature Status --}}

Signature

@if ($proposal->signature)
Signed

{{ $proposal->signature->signatory_name }}

{{ $proposal->signature->signatory_email }}

{{ $proposal->signature->signed_at->format('d M Y, H:i') }}

{{ substr(hash('sha256', $proposal->signature->signatory_email . '|' . $proposal->signature->signed_at), 0, 8) }}...

@else

Awaiting client signature

@if ($deckUrl ?? null) Open deck → @endif
@endif
@endsection