@php
// Step type configuration — mirrors ColorManagement::STEP_TYPES
$stepCfg = \App\Livewire\Planning\ColorManagement::STEP_TYPES;
// Helper: render step badge inline
$stepBadge = fn(string $tipo) => sprintf(
'%s ',
$stepCfg[$tipo]['bg'] ?? '#f1f5f9',
$stepCfg[$tipo]['fg'] ?? '#475569',
$stepCfg[$tipo]['code'] ?? substr($tipo,0,3)
);
$stepLabel = fn(string $tipo) => $stepCfg[$tipo]['label'] ?? $tipo;
$stepIsHeat = fn(string $tipo) => $stepCfg[$tipo]['is_heat'] ?? false;
$stepHasTemp = fn(string $tipo) => $stepCfg[$tipo]['has_temp'] ?? true;
@endphp
{{-- ── PAGE HEADER ─────────────────────────────────── --}}
@if($section === 'curves')
{{-- ══════════════════════════════════════════════════════════════
CURVES SECTION
══════════════════════════════════════════════════════════════ --}}
@if($curvas->isEmpty())
📈
Sin curvas de tintura
Clic para crear la primera curva
@else
{{ $curvas->count() }} curva(s) · ● = paso con dosificación de químicos
@foreach($curvas as $curve)
@php
$dosingCount = $curve->steps->where('ventana_adicion', true)->count();
$totalMin = $curve->steps->sum(fn($s) => in_array($s->tipo,['CALENTAMIENTO','ENFRIAMIENTO']) && $s->gradiente_c_min > 0
? abs($s->temp_final_c-$s->temp_inicio_c)/$s->gradiente_c_min : $s->tiempo_min ?? 0);
$maxTemp = $curve->steps->max('temp_final_c');
$recipeCount = \App\Models\ProductionFormula::where('dye_curve_id', $curve->id)->count();
@endphp
@if($curve->descripcion)
{{ $curve->descripcion }}
@endif
@foreach($curve->steps->sortBy('orden') as $step)
@php
$prefix = substr($step->tipo,0,3);
$isHeat = in_array($step->tipo,['CALENTAMIENTO','ENFRIAMIENTO']);
$dur = $isHeat && $step->gradiente_c_min>0 ? round(abs($step->temp_final_c-$step->temp_inicio_c)/$step->gradiente_c_min).'min' : ($step->tiempo_min.'min');
@endphp
{{ $step->orden }}
{{ $prefix }}
@if($step->ventana_adicion)
@else
@endif
{{ $step->temp_inicio_c }}°→{{ $step->temp_final_c }}°C
@if($isHeat && $step->gradiente_c_min) · {{ $step->gradiente_c_min }}°/min @endif
· {{ $dur }}
@if($step->descripcion) — {{ $step->descripcion }} @endif
@endforeach
@endforeach
@endif
@elseif(!$selectedColorId)
{{-- ══════════════════════════════════════════════════════════════
COLORS LIST / GRID
══════════════════════════════════════════════════════════════ --}}
Buscar
Temporada
Todas
@foreach($seasons as $s){{ $s }} @endforeach
Cliente
Todos
@foreach($clients as $c){{ $c }} @endforeach
{{ $colors->total() }}
Total colores
{{ $colors->where('active',true)->count() }}
Activos
{{ $colors->filter(fn($c)=>$c->labFormulas->where('status','Approved_in_Lab')->isNotEmpty())->count() }}
Lab aprobado
@if($viewMode === 'grid')
@forelse($colors as $color)
@php
$hex = $color->fallback_hex ?? $color->color_hex ?? '#6B7280';
$hA = $color->labFormulas->where('status','Approved_in_Lab')->isNotEmpty();
@endphp
{{ $color->code }}
{{ $color->name }}
@if($color->client)
{{ $color->client }}
@endif
@empty
No se encontraron colores.
@endforelse
@else
@forelse($colors as $color)
@php $hex = $color->fallback_hex ?? $color->color_hex ?? '#6B7280'; @endphp
{{ $color->code }}
{{ $color->name }}
{{ $color->client ?: '—' }}
@if($color->season)
{{ $color->season }} @else
@endif
{{ $color->articulo_id ?: '—' }}
@if($color->labFormulas->where('status','Approved_in_Lab')->isNotEmpty())
✓ Lab
@elseif($color->labFormulas->isNotEmpty())
Borrador
@else
Sin fórmula @endif
@empty
No se encontraron colores.
@endforelse
@endif
{{ $colors->links() }}
@else
{{-- ══════════════════════════════════════════════════════════════
COLOR DETAIL — 4-TAB VIEW
══════════════════════════════════════════════════════════════ --}}
@php
$ref = $color->reference_data ?? [];
$hex = $color->fallback_hex ?? $color->color_hex ?? '#6B7280';
$hasRef = !empty($ref['l_star']);
$activeRecipe = $recipes->firstWhere('status','Approved');
@endphp
{{-- Color banner --}}
{{-- Tabs --}}
📋 Información
🔬 Lab Trials {{ $trials->count() }}
🧪 Fórmula Producción
@if($activeRecipe)✓ Activa @endif
📊 Análisis {{ count($measurements) }}
{{-- ── TAB 1: INFO ─────────────────────────────────── --}}
@if($activeTab === 'info')
Identificación
Referencia de Color
Guardar Cambios
@endif
{{-- ── TAB 2: LAB TRIALS ───────────────────────────── --}}
@if($activeTab === 'trials')
Intentos de laboratorio · ΔE automático
@if(!$hasRef) ⚠ Sin L*a*b* de referencia @endif
+ Nuevo Trial
@forelse($trials as $trial)
@php $pf=$trial->pass_fail; $deCls=match($pf){'PASS'=>'pass','MARGINAL'=>'marginal','FAIL'=>'fail',default=>'nodata'}; $mx=$trial->items->max('concentration_owf')?:1; @endphp
{{ $trial->version_name }}
{{ $trial->status==='Approved_in_Lab'?'✓ Aprobado Lab':'Borrador' }}
{{ $trial->delta_e!==null?'ΔE '.number_format($trial->delta_e,2):'—' }}
{{ $pf==='PASS'?'DENTRO DEL ESTÁNDAR':($pf==='MARGINAL'?'MARGINAL':($pf==='FAIL'?'FUERA':'Sin medición')) }}
@if($trial->read_l!==null)
L* {{ number_format($trial->read_l,2) }}
a* {{ number_format($trial->read_a,2) }}
b* {{ number_format($trial->read_b,2) }}
@endif
@foreach($trial->items as $fi)
{{ $fi->dyestuff?->name ?? '—' }}
{{ number_format($fi->concentration_owf,4) }}%
@endforeach
@if($trial->trial_notes)
{{ $trial->trial_notes }}
@endif
✏️
@if($trial->status!=='Approved_in_Lab')✓ Aprobar
@else↩ @endif
✕
@empty
🧫
Sin trials — clic para crear el primero
@endforelse
@if($trials->isNotEmpty())
@endif
@endif
{{-- ── TAB 3: PRODUCTION FORMULA ───────────────────── --}}
@if($activeTab === 'production')
Versiones de fórmula con curva de tintura · Una versión activa a la vez
+ Nueva Versión
@if($recipes->isEmpty())
🧪
Sin fórmulas de producción
@else
@foreach($recipes as $r)
{{ $r->nombre }} @if($r->status==='Approved') ✓@elseif($r->status==='Superseded') 🗄@endif
@endforeach
@php $viewing = $recipes->firstWhere('id',$viewingRecipeId) ?? $recipes->first(); @endphp
@if($viewing)
@php
$pf = $viewing->productionFormula;
$lf = $pf?->labFormula;
$cur = $viewing->dyeCurve;
// Group step chemicals by curve_step_id
$chemByStep = $viewing->items->groupBy('curve_step_id');
@endphp
{{ $viewing->nombre }}
{{ $viewing->status==='Approved'?'✓ Activa':($viewing->status==='Superseded'?'Archivada':'Borrador') }}
✏️ Editar
@if($viewing->status!=='Approved')
✓ Aprobar @endif
@if($viewing->status!=='Superseded')
🗄 @endif
🖨
Trial base: {{ $lf?->version_name ?? '—' }}
Partida: {{ $pf?->partida ?? '—' }}
Versión: V.{{ $pf?->version_number ?? '—' }}
Curva: {{ $cur?->nombre ?? '—' }}
Rel. Baño: {{ $viewing->water_ratio }}:1
Emitido por: {{ $viewing->emitido_por ?: '—' }}
{{-- Full process: curve steps with chemicals interleaved --}}
@if($cur && $cur->steps->isNotEmpty())
Proceso Completo — {{ $cur->nombre }} ({{ $cur->tipo_fibra }})
@foreach($cur->steps->sortBy('orden') as $step)
@php
$prefix = substr($step->tipo,0,3);
$isHeat = in_array($step->tipo,['CALENTAMIENTO','ENFRIAMIENTO']);
$dur = $isHeat && $step->gradiente_c_min>0 ? round(abs($step->temp_final_c-$step->temp_inicio_c)/$step->gradiente_c_min).'min ('.($step->gradiente_c_min.'°/min)') : ($step->tiempo_min.'min');
$chems = $chemByStep->get($step->id, collect());
@endphp
{{ $step->orden }}
{{ $step->tipo }}
{{ $step->temp_inicio_c }}° → {{ $step->temp_final_c }}°C
{{ $dur }}
@if($step->ventana_adicion)● Dosificación @endif
@if($step->descripcion)— {{ $step->descripcion }} @endif
@foreach($chems->sortBy('order_in_step') as $chem)
{{ $loop->iteration }}.
{{ $chem->dyestuff?->name ?? '—' }}
{{ number_format($chem->concentration,4) }}
{{ $chem->uom==='g_l'?'g/L':'% owf' }}
@if($chem->notes)— {{ $chem->notes }} @endif
@endforeach
@endforeach
@elseif($viewing->items->isNotEmpty())
Químicos (sin curva asignada)
@foreach($viewing->items as $chem)
{{ $chem->dyestuff?->name ?? '—' }}
{{ number_format($chem->concentration,4) }}
{{ $chem->uom==='g_l'?'g/L':'% owf' }}
@endforeach
@endif
@if($viewing->notes)
{{ $viewing->notes }}
@endif
@endif
@endif
@endif
{{-- ── TAB 4: ANALYSIS ─────────────────────────────── --}}
@if($activeTab === 'analysis')
{{-- ── Filter bar ── --}}
{{-- ── Stats cards ── --}}
@if(!empty($analysisStats) && $analysisStats['n'] > 0)
@php
$tol = $color->customer_tolerance_de ?? 1.0;
$pct = $analysisStats['pass_pct'] ?? null;
$pctCol = $pct===null?'var(--text-sm)':($pct>=90?'var(--green)':($pct>=70?'var(--amber)':'var(--red)'));
$deCol = isset($analysisStats['mean_de'])?($analysisStats['mean_de']<=$tol?'var(--green)':($analysisStats['mean_de']<=$tol*1.5?'var(--amber)':'var(--red)')):'var(--text-sm)';
@endphp
{{ $analysisStats['n'] }}
Mediciones
{{ $analysisStats['mean_de']!==null?number_format($analysisStats['mean_de'],3):'—' }}
ΔE Promedio
{{ $analysisStats['max_de']!==null?number_format($analysisStats['max_de'],3):'—' }}
ΔE Máximo
{{ $pct!==null?$pct.'%':'—' }}
Tasa Aprobado
{{ $analysisStats['sigma']!==null?number_format($analysisStats['sigma'],3):'—' }}
σ (Sigma)
@endif
@if(empty($measurements))
Sin mediciones registradas para este color con los filtros activos.
@else
{{-- ── Charts grid: scatter (left, tall) + trend/L* stacked (right) ── --}}
{{-- a*/b* scatter ── --}}
● Batch
▲ Lab Trial
■ Aprobado
■ Marginal
■ Rechazado
— Tolerancia ·· Marginal
{{-- ΔE trend + L* trend stacked ── --}}
@if($color->target_l !== null)
— verde = L* objetivo ({{ number_format($color->target_l,2) }})
@endif
{{-- ── Formula suggestions ── --}}
@if(!empty($formulaSuggestions))
@foreach($formulaSuggestions as $tip)
@if($tip['axis'])
{{ $tip['axis'] }}
{{ $tip['value']>=0?'+':'' }}{{ number_format($tip['value'],2) }}
@else
⚠
@endif
{{ $tip['msg'] }}
@endforeach
Basado en el promedio de {{ count($measurements) }} lectura(s) seleccionadas.
Confirmar ajuste en Lab Dip antes de aplicar en producción.
@endif
{{-- ── Measurement table ── --}}
@endif
@endif
@endif {{-- end $selectedColorId --}}
{{-- ══════════════════════════════════════════════════════════════
MODALS
══════════════════════════════════════════════════════════════ --}}
{{-- Color Modal --}}
@if($showColorModal)
{{ $colorForm['id']?'Editar Color':'Nuevo Color' }}
@endif
{{-- Trial Modal --}}
@if($showTrialModal)
{{ $trialId?'Editar Trial':'Nuevo Lab Trial' }}
Colorantes (% owf)
@foreach($trialItems as $i => $item)
— Colorante — @foreach($dyestuffs as $d){{ $d->name }}@if($d->supplier) ({{ $d->supplier }})@endif @endforeach
% owf
×
@endforeach
+ Colorante
Lectura Espectrofotométrica (opcional)
@if($hasRef ?? false)
Ref: L*{{ number_format($ref['l_star'] ?? 0,2) }} a*{{ number_format($ref['a_star'] ?? 0,2) }} b*{{ number_format($ref['b_star'] ?? 0,2) }} — ΔE calculado al guardar.
@endif
Notas
@endif
{{-- Recipe Modal (step-based chemicals) --}}
@if($showRecipeModal)
{{ $recipeId?'Editar Fórmula de Producción':'Nueva Fórmula de Producción' }}
{{-- Dosing step chemical groups --}}
@if(!empty($dosingSteps))
Dosificación de Químicos por Paso
Cada paso marcado con ● requiere definir qué químicos se agregan.
% owf = % del peso de tela · g/L = gramos por litro de agua (auxiliares)
@foreach($dosingSteps as $step)
● Paso {{ $step['orden'] }}
{{ $step['tipo'] }}
{{ $step['temp_inicio_c'] }}°→{{ $step['temp_final_c'] }}°C
@if($step['descripcion'])— {{ $step['descripcion'] }} @endif
@endforeach
@elseif($recipeForm['dye_curve_id'])
Esta curva no tiene pasos de dosificación definidos. Edita la curva y marca los pasos con "Dosif." para poder asignar químicos.
@else
Selecciona una curva de tintura para ver y configurar los pasos de dosificación de químicos.
@endif
{{-- /if dosingSteps --}}
Notas generales
@endif
{{-- Curve Modal (step builder) --}}
@if($showCurveModal)
{{ $curveId?'Editar Curva':'Nueva Curva de Tintura' }}
Pasos del Proceso
● = Dosificación de químicos (aparecerá en el formulario de receta)
+ Paso
@foreach($curveSteps as $i => $paso)
@php $isHeat=in_array($paso['tipo'],['CALENTAMIENTO','ENFRIAMIENTO']); @endphp
@endforeach
@endif
{{-- ══ Chart.js ══ --}}
@push('scripts')
@endpush