@php /** * One unit of work on the products board: a product, a compiled unit, or one * piece of a product that has been split. * * Rendered in two settings, because a piece IS a unit of work and reading * differently would suggest otherwise: * * $compact = false a product standing on its own, in its own card on the * page. * $compact = true a piece, in its own card on its parent product's * surface. Tighter, with a status bar across the top and * its secondary actions reduced to icons — a piece is * read three or four at a time, so the same seven text * links that are fine once become noise. */ $meta = $statusMeta[$unit['status']] ?? $statusMeta['pending']; $overdue = $unit['due_date'] && $unit['status'] !== 'done' && $unit['due_date']->isPast(); $marginTone = $unit['revenue'] <= 0 ? 'slate' : ($unit['margin'] >= 30 ? 'emerald' : ($unit['margin'] >= 10 ? 'amber' : 'rose')); $marginPill = [ 'emerald' => 'bg-emerald-50 text-emerald-700 ring-emerald-200', 'amber' => 'bg-amber-50 text-amber-700 ring-amber-200', 'rose' => 'bg-rose-50 text-rose-700 ring-rose-200', 'slate' => 'bg-slate-100 text-slate-500 ring-slate-200', ][$marginTone]; $noteCount = $unit['part_id'] ? ($partNoteCounts[$unit['part_id']] ?? 0) : 0; $fileCount = $unit['part_id'] ? ($partFileCounts[$unit['part_id']] ?? 0) : 0; $canTick = $canUpdate && count($units) > 1 && ! $unit['is_group'] && ! $unit['is_part']; $pad = $compact ? 'px-3.5' : 'px-4 sm:px-5'; @endphp
@if ($compact) {{-- Where this piece has got to, readable before anything is read. --}} @endif {{-- Head --}}
@if ($canTick) @endif
@if ($compact) {{ $unit['part_index'] }} @endif

{{ $unit['label'] }}

@if ($unit['is_group']) {{ trans_choice('[2,*] :count products', count($unit['line_ids']), ['count' => count($unit['line_ids'])]) }} @endif {{ $meta['label'] }} {{-- On a hybrid job every product says where it is made; on any other job the job itself already answers for all of them. --}} @if ($isHybrid) @if ($unit['is_outsourced']) {{ $unit['partner']?->name ?: __('Outsourced') }} @else {{ __('In-house') }} @endif @endif
{{ rtrim(rtrim(number_format($unit['qty'], 2), '0'), '.') }} {{ __('units') }} @if ($unit['due_date']) {{ $unit['due_date']->format('j M Y') }}{{ $overdue ? ' · '.__('overdue') : '' }} @endif @if ($unit['assignee']) {{ $initials($unit['assignee']->name) }} {{ $unit['assignee']->name }} @endif @if ($unit['hours'] > 0) {{ number_format($unit['hours'], 2) }} h @endif @if ($unit['cost_rows'] > 0) {{ trans_choice('{1} :count cost|[2,*] :count costs', $unit['cost_rows'], ['count' => $unit['cost_rows']]) }} @endif
{{-- Body --}}
{{-- Progress --}}
{{ __('Progress') }} {{ $unit['progress'] }}%
{{-- Members of a compiled unit --}} @if ($unit['is_group'])
@foreach ($unit['lines'] as $member) {{ $member['line']->name }} @endforeach
@endif {{-- Money --}} @if ($canSeeMoney)
{{ __('Rev') }} {{ number_format($unit['revenue'], 2) }} {{ __('Cost') }} {{ $unit['has_cost'] ? number_format($unit['cost'], 2) : __('none') }} {{ __('GP') }} {{ number_format($unit['profit'], 2) }}
{{ $unit['revenue'] > 0 ? number_format($unit['margin'], 1).'%' : '—' }} @if ($unit['is_estimated']) @endif
@endif {{-- Notes --}} @if ($unit['notes'])

{{ $unit['notes'] }}

@endif
{{-- Actions --}} @if ($canUpdate) @php // Everything that is not "move this along" is an icon on a piece and // a word on a product. Same actions, same order, either way. $tools = []; if (! $unit['is_group']) { $tools[] = ['icon' => 'paper-clip', 'label' => __('Files'), 'count' => $fileCount, 'wire' => "openFiles('".$unit['key']."')", 'tone' => $fileCount ? 'text-indigo-600' : 'text-slate-400']; $tools[] = ['icon' => 'sticky-note', 'label' => __('Notes'), 'count' => $noteCount, 'wire' => "openNotes('".$unit['key']."')", 'tone' => $noteCount ? 'text-amber-500' : 'text-slate-400']; } if ($canAddCost) { $tools[] = ['icon' => 'banknotes', 'label' => __('Add cost'), 'count' => 0, 'tone' => 'text-slate-400', 'click' => "tab = 'financials'; \$dispatch('add-cost-for-product', { lineItem: ".$unit['line_ids'][0].", part: ".($unit['part_id'] ?? 'null')." })"]; } if (! $unit['is_group']) { $tools[] = ['icon' => 'clock', 'label' => __('Track time'), 'count' => 0, 'tone' => 'text-slate-400', 'click' => "tab = 'time'; \$dispatch('track-time-for-product', { lineItem: ".$unit['line_ids'][0].", part: ".($unit['part_id'] ?? 'null')." })"]; } $tools[] = ['icon' => 'pencil-square', 'label' => __('Edit'), 'count' => 0, 'tone' => 'text-slate-400', 'wire' => "edit('".$unit['key']."')"]; @endphp
@if ($unit['status'] !== 'in_production' && $unit['status'] !== 'done') @endif @if ($unit['status'] !== 'done') @else @endif
@foreach ($tools as $tool) @if ($compact) @else @endif @endforeach @if ($unit['is_group']) @elseif (! $unit['is_part']) @endif
@endif