Polish marketplace UX
This commit is contained in:
@@ -7,35 +7,80 @@
|
||||
</x-slot>
|
||||
|
||||
<div class="mx-auto max-w-7xl space-y-4 px-4 py-8 sm:px-6 lg:px-8">
|
||||
@forelse ($orders as $order)
|
||||
@php($progress = $order->checklistProgress())
|
||||
<a href="{{ route('work-orders.show', $order) }}" class="tse-panel block p-5 transition hover:border-sky-300 hover:shadow-md dark:hover:border-sky-700">
|
||||
<div class="flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between">
|
||||
<div>
|
||||
<h3 class="font-semibold text-slate-950 dark:text-white">{{ $order->jobPost->title }}</h3>
|
||||
<p class="mt-1 text-sm text-slate-600 dark:text-slate-400">
|
||||
Buyer: {{ $order->buyer->buyerProfile?->company_name ?? $order->buyer->name }}
|
||||
| Provider: {{ $order->provider->providerProfile?->business_name ?? $order->provider->name }}
|
||||
</p>
|
||||
<div class="hidden overflow-hidden rounded border bg-white shadow-sm dark:border-slate-800 dark:bg-slate-900 lg:block">
|
||||
<table class="min-w-full divide-y divide-slate-200 text-sm dark:divide-slate-800">
|
||||
<thead class="bg-slate-50 text-left text-xs uppercase text-slate-500 dark:bg-slate-950 dark:text-slate-400">
|
||||
<tr>
|
||||
<th class="px-4 py-3">Work order</th>
|
||||
<th class="px-4 py-3">Buyer</th>
|
||||
<th class="px-4 py-3">Provider</th>
|
||||
<th class="px-4 py-3">Schedule</th>
|
||||
<th class="px-4 py-3">Status</th>
|
||||
<th class="px-4 py-3">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-slate-100 dark:divide-slate-800">
|
||||
@forelse ($orders as $order)
|
||||
@php($progress = $order->checklistProgress())
|
||||
<tr class="align-top">
|
||||
<td class="px-4 py-4">
|
||||
<a href="{{ route('work-orders.show', $order) }}" class="font-semibold text-slate-950 hover:text-sky-700 dark:text-white dark:hover:text-sky-300">{{ $order->jobPost->title }}</a>
|
||||
<p class="mt-1 text-xs text-slate-500">#{{ $order->id }}</p>
|
||||
</td>
|
||||
<td class="px-4 py-4">{{ $order->buyer->buyerProfile?->company_name ?? $order->buyer->name }}</td>
|
||||
<td class="px-4 py-4">{{ $order->provider->providerProfile?->business_name ?? $order->provider->name }}</td>
|
||||
<td class="px-4 py-4">
|
||||
<p>{{ $order->scheduled_at?->format('M j, Y g:i A') ?? 'No scheduled time' }}</p>
|
||||
<p class="text-xs text-slate-500">{{ $order->appointment_window ?: 'No appointment window' }}</p>
|
||||
</td>
|
||||
<td class="px-4 py-4">
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<x-badge tone="sky">{{ str_replace('_', ' ', $order->status) }}</x-badge>
|
||||
<x-badge tone="slate">Checklist {{ $progress['done'] }}/{{ $progress['total'] }}</x-badge>
|
||||
</div>
|
||||
</td>
|
||||
<td class="px-4 py-4">
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<a href="{{ route('work-orders.show', $order) }}" class="text-sm font-semibold text-sky-700 hover:text-sky-900 dark:text-sky-300">Open</a>
|
||||
<a href="{{ route('work-orders.print', $order) }}" class="text-sm font-semibold text-sky-700 hover:text-sky-900 dark:text-sky-300">Print</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr><td colspan="6" class="px-4 py-8 text-center text-slate-500">No work orders yet.</td></tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="grid gap-4 lg:hidden">
|
||||
@forelse ($orders as $order)
|
||||
@php($progress = $order->checklistProgress())
|
||||
<a href="{{ route('work-orders.show', $order) }}" class="tse-panel block p-5 transition hover:border-sky-300 hover:shadow-md dark:hover:border-sky-700">
|
||||
<div class="flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between">
|
||||
<div>
|
||||
<h3 class="font-semibold text-slate-950 dark:text-white">{{ $order->jobPost->title }}</h3>
|
||||
<p class="mt-1 text-sm text-slate-600 dark:text-slate-400">
|
||||
Buyer: {{ $order->buyer->buyerProfile?->company_name ?? $order->buyer->name }}
|
||||
| Provider: {{ $order->provider->providerProfile?->business_name ?? $order->provider->name }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex flex-wrap gap-2 sm:justify-end">
|
||||
<x-badge tone="sky">{{ str_replace('_', ' ', $order->status) }}</x-badge>
|
||||
<x-badge tone="slate">Checklist {{ $progress['done'] }}/{{ $progress['total'] }}</x-badge>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-wrap gap-2 sm:justify-end">
|
||||
<x-badge tone="sky">{{ str_replace('_', ' ', $order->status) }}</x-badge>
|
||||
<x-badge tone="slate">Checklist {{ $progress['done'] }}/{{ $progress['total'] }}</x-badge>
|
||||
</div>
|
||||
</div>
|
||||
<p class="mt-3 text-sm text-slate-600 dark:text-slate-400">
|
||||
{{ $order->scheduled_at?->format('M j, Y g:i A') ?? 'No scheduled time' }}
|
||||
@if ($order->appointment_window)
|
||||
| {{ $order->appointment_window }}
|
||||
@endif
|
||||
</p>
|
||||
</a>
|
||||
@empty
|
||||
<div class="tse-panel p-8 text-center">
|
||||
<h3 class="text-base font-semibold text-slate-950 dark:text-white">No work orders yet.</h3>
|
||||
<p class="mt-2 text-sm text-slate-600 dark:text-slate-400">Accepted quotes will appear here.</p>
|
||||
</div>
|
||||
@endforelse
|
||||
<p class="mt-3 text-sm text-slate-600 dark:text-slate-400">
|
||||
{{ $order->scheduled_at?->format('M j, Y g:i A') ?? 'No scheduled time' }}
|
||||
@if ($order->appointment_window)
|
||||
| {{ $order->appointment_window }}
|
||||
@endif
|
||||
</p>
|
||||
</a>
|
||||
@empty
|
||||
<x-empty-state title="No work orders yet." description="Accepted quotes will appear here." />
|
||||
@endforelse
|
||||
</div>
|
||||
|
||||
{{ $orders->links() }}
|
||||
</div>
|
||||
|
||||
@@ -5,16 +5,28 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Work Order {{ $workOrder->id }} - {{ $workOrder->jobPost->title }}</title>
|
||||
<style>
|
||||
body { font-family: Arial, sans-serif; color: #111827; margin: 32px; }
|
||||
h1, h2 { margin-bottom: 8px; }
|
||||
body { font-family: Arial, sans-serif; color: #111827; margin: 32px; line-height: 1.45; }
|
||||
h1, h2, h3 { margin-bottom: 8px; }
|
||||
h1 { font-size: 26px; }
|
||||
h2 { font-size: 18px; }
|
||||
h3 { font-size: 14px; }
|
||||
section { border-top: 1px solid #d1d5db; padding-top: 16px; margin-top: 20px; }
|
||||
.muted { color: #4b5563; }
|
||||
.small { font-size: 12px; }
|
||||
.grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
|
||||
.box { border: 1px solid #d1d5db; padding: 12px; border-radius: 6px; }
|
||||
.summary { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; margin-top: 18px; }
|
||||
.summary div { border: 1px solid #d1d5db; border-radius: 6px; padding: 10px; }
|
||||
.label { display: block; color: #4b5563; font-size: 11px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; }
|
||||
.value { display: block; margin-top: 3px; font-weight: 700; }
|
||||
.notice { background: #f8fafc; border: 1px solid #cbd5e1; border-radius: 6px; padding: 12px; }
|
||||
ul { padding-left: 20px; }
|
||||
li { margin-bottom: 4px; }
|
||||
@media print {
|
||||
body { margin: 18mm; }
|
||||
button { display: none; }
|
||||
section { break-inside: avoid; }
|
||||
.page-break { break-before: page; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
@@ -22,6 +34,26 @@
|
||||
<button onclick="window.print()">Print</button>
|
||||
<h1>{{ $workOrder->jobPost->title }}</h1>
|
||||
<p class="muted">Work Order #{{ $workOrder->id }} | {{ str_replace('_', ' ', $workOrder->status) }}</p>
|
||||
<p class="muted small">Packet generated {{ now()->format('M j, Y g:i A') }}</p>
|
||||
|
||||
<div class="summary">
|
||||
<div>
|
||||
<span class="label">Schedule</span>
|
||||
<span class="value">{{ $workOrder->scheduled_at?->format('M j, Y g:i A') ?? 'Not set' }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="label">Window</span>
|
||||
<span class="value">{{ $workOrder->appointment_window ?: 'Not set' }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="label">Scope</span>
|
||||
<span class="value">{{ str_replace('_', ' ', $workOrder->scope_clarity_status) }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="label">Level</span>
|
||||
<span class="value">{{ $workOrder->technicianLevel()['short_name'] }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section class="grid">
|
||||
<div class="box">
|
||||
@@ -41,6 +73,7 @@
|
||||
|
||||
<section>
|
||||
<h2>Scope Safeguards</h2>
|
||||
<p class="notice small">Supplemental instructions are reference material only. They do not override the structured scope, excluded work, change-request path, or agreed terms in this packet.</p>
|
||||
<p class="muted">Scope clarity: {{ str_replace('_', ' ', $workOrder->scope_clarity_status) }}</p>
|
||||
<p class="muted">Technician level: {{ $workOrder->technicianLevel()['name'] }}</p>
|
||||
@if (is_array($workOrder->risk_flags) && $workOrder->risk_flags)
|
||||
@@ -66,7 +99,7 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<section class="page-break">
|
||||
<h2>Contact And Support</h2>
|
||||
<p class="muted">Certified: {{ $workOrder->contactSnapshotValue('contact_certified') ? 'Yes' : 'No' }}</p>
|
||||
<div class="grid">
|
||||
|
||||
Reference in New Issue
Block a user