{{-- ── Toast ─────────────────────────────────────────────────────────── --}}
@php $csLabels = \App\Models\Batch::COLOR_STATUS_LABELS; $csClasses = [ 'PENDING' => 'bg-gray-100 text-gray-600', 'APPROVED' => 'bg-green-100 text-green-700', 'OUT_OF_STANDARD' => 'bg-orange-100 text-orange-700', 'MATIZ' => 'bg-blue-100 text-blue-700', 'REJECTED' => 'bg-red-100 text-red-700', 'REJECTED_DISPATCHED' => 'bg-red-100 text-red-700 ring-1 ring-green-400', ]; $procesoLabels = \App\Models\Batch::PROCESO_LABELS; $statusColors = [ 'PLAN' => 'transparent', 'PROCESO' => 'rgba(245,158,11,0.22)', 'TERMINADO' => 'rgba(34,197,94,0.18)', 'CANCELADO' => 'rgba(156,163,175,0.28)', ]; // Helper: is a hex color light (determines fg text color) $isLightHex = function(string $hex): bool { $hex = ltrim($hex, '#'); if (strlen($hex) < 6) return false; $r = hexdec(substr($hex, 0, 2)); $g = hexdec(substr($hex, 2, 2)); $b = hexdec(substr($hex, 4, 2)); return (0.299 * $r + 0.587 * $g + 0.114 * $b) / 255 > 0.60; }; @endphp {{-- ══ TOP BAR ════════════════════════════════════════════════════════ --}}

📊 Planning Board

{{ $windowLabel }} · {{ $machines->count() }} máquinas

{{-- Date navigation --}}
{{-- View toggle --}}
⚙ Ajustes
{{-- ══ SIN MÁQUINA QUEUE ═══════════════════════════════════════════════ --}}
📋 Sin Máquina
@forelse($unassignedBatches as $b)
{{ $b->batch_number }} @if($b->lote_greige_id) @php $bgs = $b->greigeStatus ?? ['color'=>'#9ca3af','label'=>'Greige']; @endphp @endif @if($b->dyeColor) {{ $b->dyeColor->code }} @endif @if($b->derived_article) Art: {{ $b->derived_article }} @endif @if($b->derived_customer) {{ $b->derived_customer }} @endif
@empty Vacío — arrastre un batch aquí para quitarlo de su máquina @endforelse
{{-- ══ GANTT (HORIZONTAL) VIEW ════════════════════════════════════════ --}}
{{-- Fixed left column --}}
Máquina
@foreach ($machines as $machine)
{{ $machine->code }}
{{ $machine->name }}
@if($machine->allowed_ropes)
{{ implode('/', $machine->allowed_ropes) }} cuerdas
@endif
@endforeach
{{-- Scrollable grid --}}
{{-- Day header --}}
@foreach ($days as $day)
{{ $day['dt']->format('d') }}
{{ $day['dt']->isoFormat('ddd') }} {{ $day['dt']->format('M') }}
@if($day['is_today'])
hoy
@endif
@endforeach @foreach ($shiftLines as $sl)
{{ $sl['label'] }}
@endforeach
{{-- Machine rows --}} @foreach ($machines as $machine) @php $maxRopeForMachine = $machine->allowed_ropes ? max($machine->allowed_ropes) : 1; @endphp
{{-- Day backgrounds --}} @foreach ($days as $day)
@endforeach {{-- Shift dividers --}} @foreach ($shiftLines as $sl) @if(!$sl['is_day_start'])
@endif @endforeach {{-- NOW line --}} @if($nowVisible)
@if($loop->first)
AHORA {{ now()->format('H:i') }}
@endif
@endif {{-- Batch blocks --}} @foreach ($machine->orderedBatches as $idx => $batch) @if($batch->col_left !== null) @php $bStatus = $batch->status ?? 'PLAN'; $bStatusBg = $statusColors[$bStatus] ?? 'transparent'; $cs = $batch->color_status ?? 'PENDING'; $csDot = match($cs) { 'APPROVED' => '#22c55e', 'OUT_OF_STANDARD' => '#f97316', 'MATIZ' => '#3b82f6', 'REJECTED', 'REJECTED_DISPATCHED' => '#ef4444', default => '#9ca3af', }; $light = $isLightHex($batch->color); $fg = $light ? '#1F2937' : '#ffffff'; $fgSm = $light ? 'rgba(31,41,55,.55)' : 'rgba(255,255,255,.70)'; $stBorder = match($bStatus) { 'TERMINADO' => '#16A34A', 'PROCESO' => '#F59E0B', default => 'transparent', }; $w = $batch->col_width; // Rope data $ropesByNum = $batch->loteGreige?->ropes?->keyBy('rope_number') ?? collect(); @endphp
{{-- Status tint overlay --}}
{{-- Row 1: batch number + symbols --}}
{{ $batch->batch_number }} {!! $batch->labTestStatus === 'APPROVED' ? '🧪' : ($batch->labTestStatus === 'TESTING' ? '⏳' : '⚠️') !!} @if($batch->lote_greige_id) @php $bgs = $batch->greigeStatus ?? ['color'=>'#9ca3af','label'=>'Greige']; @endphp @endif {!! $bStatus === 'TERMINADO' ? '✅' : ($bStatus === 'PROCESO' ? '▶️' : '📅') !!}
{{-- Row 2: Color --}}
{{ $batch->dyeColor->code ?? 'Sin Color' }}
{{-- Row 3: Articulo --}}
Art: {{ $batch->derived_article ?? '--' }}
{{-- Row 4: FPO --}}
FPO: {{ $batch->derived_fpo ?? '--' }}
{{-- Row 5: Customer | Total time --}}
{{ $batch->derived_customer ?? '--' }} {{ $batch->duration_hours }}h
{{-- Row 6: End date/time --}}
Fin: {{ $batch->calculated_end?->format('d/m H:i') }}
@if($w >= 100) {{-- Row 6: rope badges --}}
@for ($r = 1; $r <= $maxRopeForMachine; $r++) @php $rope = $ropesByNum->get($r); $rolls = $rope?->rolls ?? collect(); $hasRolls = $rolls->isNotEmpty(); @endphp
C{{ $r }}
@foreach($rolls->take(2) as $rr) {{ substr($rr->etiqueta, -4) }} @endforeach @if($rolls->count() > 2) +{{ $rolls->count()-2 }} @endif
@endfor
@endif
@endif @endforeach
@endforeach
{{-- ══ VERTICAL DYE VIEW ══════════════════════════════════════════════ --}}
{{-- Machine header row (sticky top) --}}
@foreach ($machines as $machine)
{{ $machine->code }}
{{ $machine->orderedBatches->count() }} en cola @if($machine->allowed_ropes) · {{ implode('/', $machine->allowed_ropes) }}C @endif
@endforeach
{{-- Scrollable body --}}
{{-- Time axis --}}
@foreach($dyeTimeMarks as $mark)
{{ $mark['label'] }}
@endforeach
{{-- Machine columns --}} @foreach ($machines as $machine) @php $maxRopeForDyeCol = $machine->allowed_ropes ? max($machine->allowed_ropes) : 1; @endphp
{{-- Grid lines --}} @foreach($dyeTimeMarks as $mark)
@endforeach {{-- NOW line --}} @if($dyeNowPx >= 0 && $dyeNowPx <= $dyeTotalPx)
@if($loop->first) NOW {{ now()->format('H:i') }} @endif
@endif {{-- Batch blocks (vertical) --}} @foreach ($machine->orderedBatches as $idx => $batch) @if($batch->dye_top_px !== null) @php $bStatus = $batch->status ?? 'PLAN'; $bStatusBg = $statusColors[$bStatus] ?? 'transparent'; $cs = $batch->color_status ?? 'PENDING'; $csDot = match($cs) { 'APPROVED' => '#22c55e', 'OUT_OF_STANDARD' => '#f97316', 'MATIZ' => '#3b82f6', 'REJECTED','REJECTED_DISPATCHED' => '#ef4444', default => '#9ca3af', }; $light = $isLightHex($batch->color); $fg = $light ? '#1F2937' : '#ffffff'; $fgSm = $light ? 'rgba(31,41,55,.55)' : 'rgba(255,255,255,.70)'; $stBorder = match($bStatus) { 'TERMINADO' => '#16A34A', 'PROCESO' => '#F59E0B', default => 'transparent', }; $ropesByNum = $batch->loteGreige?->ropes?->keyBy('rope_number') ?? collect(); $compact = $batch->dye_height_px < 100; @endphp
{{-- Batch number + symbols --}}
{{ $batch->batch_number }} {!! $batch->labTestStatus === 'APPROVED' ? '🧪' : ($batch->labTestStatus === 'TESTING' ? '⏳' : '⚠️') !!} @if($batch->lote_greige_id) @php $bgs = $batch->greigeStatus ?? ['color'=>'#9ca3af','label'=>'Greige']; @endphp @endif {!! $bStatus === 'TERMINADO' ? '✅' : ($bStatus === 'PROCESO' ? '▶️' : '📅') !!}
@if(!$compact) {{-- Row 2: Color --}}
{{ $batch->dyeColor->code ?? 'Sin Color' }}
{{-- Row 3: Articulo --}}
Art: {{ $batch->derived_article ?? '--' }}
{{-- Row 4: FPO --}}
FPO: {{ $batch->derived_fpo ?? '--' }}
{{-- Row 5: Customer | Total time --}}
{{ $batch->derived_customer ?? '--' }} {{ $batch->duration_hours }}h
{{-- Row 6: End date/time --}}
Fin: {{ $batch->calculated_end?->format('d/m H:i') }}
{{-- Rope badges --}}
@for ($r = 1; $r <= $maxRopeForDyeCol; $r++) @php $rope = $ropesByNum->get($r); $rolls = $rope?->rolls ?? collect(); $hasRolls = $rolls->isNotEmpty(); @endphp
C{{ $r }}
@foreach($rolls->take(2) as $rr) {{ substr($rr->etiqueta, -4) }} @endforeach
@endfor
@endif
@endif @endforeach
@endforeach
{{-- ══ ÓRDENES DE TRABAJO PENDIENTES ════════════════════════════════════ --}} @if(isset($pendingWorkOrders) && $pendingWorkOrders->isNotEmpty())

📋 Órdenes de Trabajo — Pendientes de asignar

@foreach($pendingWorkOrders as $wo)
{{ $wo->articulo_id }}
{{ $wo->dye_color?->code ?? 'Sin Color' }}
Pedido: {{ number_format($wo->total_m, 0) }}m | Pendiente: {{ number_format($wo->pending_m, 0) }}m
Cap: {{ number_format($wo->batch_cap_m, 0) }}m/batch (3 ropes)
{{ $wo->batches }} Batches
Cola
@endforeach
@endif {{-- ══════════════════════════ MODALS ══════════════════════════════════ --}} {{-- ── Batch Create / Edit Modal ────────────────────────────────────── --}} @if ($showBatchModal) @php $editBatch = $editingBatch ? \App\Models\Batch::find($batchId) : null; @endphp

{{ $editingBatch ? 'Lote ' . ($editBatch?->batch_number ?? '') : '+ Nuevo Batch' }}

{{-- ── Status section (edit only) ──────────────────────────── --}} @if($editingBatch && $editBatch) @php $bStatus = $editBatch->status ?? 'PLAN'; $cs = $editBatch->color_status ?? 'PENDING'; @endphp
{{-- Status + color status badges --}}
Proceso:
@foreach(['PLAN' => '○ Plan', 'PROCESO' => '▶ Proceso', 'TERMINADO' => '✓ Terminado', 'CANCELADO' => '✕ Cancelado'] as $sv => $sl) {{ $sl }} @endforeach
{{-- Color status --}}
Color:
@foreach(['PENDING' => '? Pendiente', 'APPROVED' => '✓ Aprobado', 'OUT_OF_STANDARD' => '⚠ Fuera std', 'REJECTED' => '✗ Rechazado'] as $csv => $csl) @endforeach
{{-- Action buttons --}}
@if($bStatus === 'PLAN') @endif @if($bStatus === 'PROCESO') @endif @if(in_array($bStatus, ['PLAN','PROCESO'])) @endif @if(in_array($cs, ['OUT_OF_STANDARD','MATIZ'])) @endif
{{-- Greige assignment --}}
@if($editBatchGreigeStatus) @php $egs = $editBatchGreigeStatus; @endphp {{ $egs['label'] }} @endif
{{-- Reschedule row — only for first batch in queue --}} @if($editBatchIsFirst && $editBatch->machine_id)
⏱ Reprogramar inicio de cola
Los lotes siguientes se recalculan automáticamente.
@endif
@endif {{-- ── Form fields ─────────────────────────────────────────── --}} {{-- Machine --}}
@error('modalMachineId')

{{ $message }}

@enderror
{{-- Queue insert position (new batches with machine only) --}} @if(!$editingBatch && $modalMachineId && $modalQueue->isNotEmpty())
Los lotes siguientes se recalculan automáticamente.
@endif {{-- Batch # --}}
@error('batchNumber')

{{ $message }}

@enderror
{{-- Receta / Production Formula --}}
@if($selectedFormula?->dyeCurve)

🌡 {{ $selectedFormula->dyeCurve->nombre }}  ·  ⏱ {{ $selectedFormula->dyeCurve->total_min }} min ({{ round($selectedFormula->dyeCurve->total_min / 60, 1) }} h)  ·  máx {{ $selectedFormula->dyeCurve->max_temp }}°C

@endif
{{-- Color --}}
@error('colorId')

{{ $message }}

@enderror
{{-- Proceso --}}
{{-- Duration --}}
@error('durationHours')

{{ $message }}

@enderror
{{-- Manual start --}}
{{-- Notes --}}
@if($editingBatch) 🖨️ Fórmula @endif
@endif {{-- ── Finish / Action Modal ─────────────────────────────────────────── --}} @if($showActionModal)

✓ Finalizar Batch

@if($actionBatch)
{{ $actionBatch->batch_number }}
@if($actionBatch->dyeColor)
{{ $actionBatch->dyeColor->code }} — {{ $actionBatch->dyeColor->name }}
@endif
@endif
@foreach($csLabels as $csVal => $csLbl) @endforeach
@if(in_array($newColorStatus, ['OUT_OF_STANDARD','MATIZ']))
💡 Después de finalizar podrá crear un batch de Matiz desde la edición del lote.
@endif
@endif {{-- ── Delete Confirm ────────────────────────────────────────────────── --}} @if ($confirmingDelete)

¿Eliminar batch?

La cola se recalculará automáticamente.

@endif {{-- ── Roll Detail Modal ─────────────────────────────────────────────── --}} @if($showRollModal)

🔍 Historial Color — {{ $rollEtiqueta }}

@if($rollDetail)
Rollo / Clave
{{ $rollDetail->etiqueta }}
@if($rollDetail->etiqueta !== (string)$rollDetail->clave_id)
Segmento de {{ $rollDetail->clave_id }}
@endif
Artículo
{{ $rollDetail->articulo_id }}
Partida
{{ $rollDetail->partida_id ?? '—' }}
Metros · Kg
{{ number_format($rollDetail->greigeInventory?->metros ?? $rollDetail->metros ?? 0, 1) }} m @if($rollDetail->greigeInventory?->peso_kg) · {{ number_format($rollDetail->greigeInventory->peso_kg, 1) }} kg @endif
@if($rollColorTests->isEmpty())
🧪
Sin pruebas de laboratorio para esta partida
@else

Pruebas de color — Partida {{ $rollDetail->partida_id }}

@foreach($rollColorTests as $colorId => $tests) @php $dColor = $tests->first()->dyeColor; @endphp
@if($dColor) {{ $dColor->code }} {{ $dColor->name }} @if($dColor->client)({{ $dColor->client }})@endif @endif
@foreach($tests as $test) @php $tBadge = match($test->status ?? '') { 'APPROVED' => 'bg-green-100 text-green-700', 'REJECTED' => 'bg-red-100 text-red-700', 'OUT_OF_STANDARD' => 'bg-orange-100 text-orange-700', 'TESTING','PENDING'=> 'bg-amber-100 text-amber-700', default => 'bg-gray-100 text-gray-600', }; @endphp
Lote: {{ $test->lote_greige_id ?? 'NPS' }} @if($test->tester_name) · {{ $test->tester_name }}@endif
{{ $test->status ?? 'PENDING' }}
@endforeach
@endforeach
@endif @else
Rollo no encontrado
@endif
@endif {{-- ── Greige Assignment Modal ────────────────────────────────────────── --}} @if($showGreigeModal && $greigeModalBatch) @php $gBatch = $greigeModalBatch; $gRopesByNum = $gBatch->loteGreige?->ropes?->keyBy('rope_number') ?? collect(); $gBatchGs = $gBatch->greigeStatus ?? ['status'=>'empty','color'=>'#9ca3af','label'=>'Sin greige']; // Existing partidas already in this lote (for roll color-coding) $gLotePartidas = collect(); foreach ($gBatch->loteGreige?->ropes ?? [] as $gr) { foreach ($gr->rolls as $grr) { if ($grr->division?->partida_id) $gLotePartidas->push($grr->division->partida_id); } } $gLotePartidas = $gLotePartidas->unique()->values(); @endphp
{{-- Header --}}

📦 Greige — {{ $gBatch->batch_number }}

● {{ $gBatchGs['label'] }}
{{-- Body --}}
{{-- Current rope assignments --}}

Cuerdas actuales

@forelse($gRopesByNum as $rNum => $grRope)
Cuerda {{ $rNum }} @if($grRope->metros_total > 0) · {{ number_format($grRope->metros_total, 0) }}m · {{ number_format($grRope->peso_kg_total, 1) }}kg @endif
@forelse($grRope->rolls as $grRoll)
@php $grDiv = $grRoll->division; @endphp {{ $grRoll->etiqueta }} @if($grDiv) {{ $grDiv->articulo_id }} @if($grDiv->partida_id) P:{{ $grDiv->partida_id }} @endif @if($grDiv->greigeInventory) {{ number_format($grDiv->greigeInventory->metros ?? 0, 0) }}m @endif @endif
@empty Vacía @endforelse
@empty

No hay cuerdas asignadas aún.

@endforelse
{{-- Assign rolls section --}}

Asignar rollo

{{-- Rope selector --}}
Asignar a cuerda: @foreach([1, 2, 3] as $rn) @endforeach
{{-- Roll search --}}
{{-- Greige status legend --}}
● Verde = OK ● Ámbar = Sin receta ● Rojo = Partida distinta (bloqueado)
{{-- Available rolls list --}} @if(strlen($greigeSearch) < 2)
🔍
Escriba artículo, partida o etiqueta para buscar rollos disponibles
@elseif($greigeModalRolls->isEmpty())
Sin resultados para "{{ $greigeSearch }}"
@else
@foreach($greigeModalRolls as $grRollAvail) @php $grPid = $grRollAvail->partida_id; if (!$grPid) { $grFlag = 'gray'; $grFlagLabel = 'Sin partida'; } elseif ($gLotePartidas->isNotEmpty() && !$gLotePartidas->contains($grPid)) { $grFlag = 'red'; $grFlagLabel = "Partida {$grPid} distinta de las existentes"; } elseif (!isset($formulaPartidas[$grPid])) { $grFlag = 'amber'; $grFlagLabel = "Sin receta para partida {$grPid}"; } else { $grFlag = 'green'; $grFlagLabel = "OK · Partida {$grPid}"; } $grFlagColors = ['gray'=>'#9ca3af','red'=>'#ef4444','amber'=>'#f59e0b','green'=>'#22c55e']; $grFlagColor = $grFlagColors[$grFlag]; @endphp
{{ $grRollAvail->etiqueta }} {{ $grRollAvail->articulo_id }} @if($grRollAvail->partida_id) P:{{ $grRollAvail->partida_id }} @else Sin partida @endif {{ number_format($grRollAvail->greigeInventory?->metros ?? $grRollAvail->metros ?? 0, 0) }}m
@endforeach
@endif
{{-- Footer --}}
@endif
{{-- /root --}}