|
|
|
@@ -2,13 +2,15 @@
|
|
|
|
|
|
|
|
|
|
<x-section-header subtitle="Taller" title="Nueva " highlight="Orden de Reparación" />
|
|
|
|
|
|
|
|
|
|
<div class="max-w-4xl mx-auto bg-panel-bg border border-neutral-800 rounded-xl p-8 shadow-lg">
|
|
|
|
|
<form action="{{ route('taller.store') }}" method="POST" class="space-y-6">
|
|
|
|
|
<div class="max-w-5xl mx-auto bg-panel-bg border border-neutral-800 rounded-xl p-8 shadow-lg">
|
|
|
|
|
<form action="{{ route('taller.store') }}" method="POST" class="space-y-8" id="taller-form">
|
|
|
|
|
@csrf
|
|
|
|
|
|
|
|
|
|
<!-- 1. Datos del Cliente y Contacto -->
|
|
|
|
|
<!-- 1. Datos del Cliente -->
|
|
|
|
|
<div class="border-b border-neutral-800 pb-6">
|
|
|
|
|
<h3 class="text-white font-bold uppercase tracking-wider text-sm mb-4">1. Cliente y Contacto</h3>
|
|
|
|
|
<h3 class="text-white font-bold uppercase tracking-wider text-sm mb-4 flex items-center gap-2">
|
|
|
|
|
<span class="bg-neutral-800 text-neon-lime px-2 py-0.5 rounded text-xs">1</span> Cliente
|
|
|
|
|
</h3>
|
|
|
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
|
|
|
<div>
|
|
|
|
|
<label class="block text-xs font-bold text-gray-400 uppercase mb-2">Propietario</label>
|
|
|
|
@@ -26,47 +28,181 @@
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- 2. La Bicicleta y el Diagnóstico -->
|
|
|
|
|
<!-- 2. Diagnóstico y Repuestos -->
|
|
|
|
|
<div class="border-b border-neutral-800 pb-6">
|
|
|
|
|
<h3 class="text-white font-bold uppercase tracking-wider text-sm mb-4">2. Diagnóstico Inicial</h3>
|
|
|
|
|
<h3 class="text-white font-bold uppercase tracking-wider text-sm mb-4 flex items-center gap-2">
|
|
|
|
|
<span class="bg-neutral-800 text-neon-lime px-2 py-0.5 rounded text-xs">2</span> Diagnóstico y Repuestos
|
|
|
|
|
</h3>
|
|
|
|
|
|
|
|
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
|
|
|
<div class="md:col-span-2">
|
|
|
|
|
<label class="block text-xs font-bold text-gray-400 uppercase mb-2">Modelo de Bici / Color</label>
|
|
|
|
|
<input type="text" name="bike_model" required placeholder="Ej: Venzo Loki Roja R29" class="w-full bg-neutral-900 border border-neutral-700 text-white rounded-lg p-2.5 focus:ring-neon-lime focus:border-neon-lime">
|
|
|
|
|
<!-- Columna Izquierda: Datos Bici -->
|
|
|
|
|
<div class="space-y-4">
|
|
|
|
|
<div>
|
|
|
|
|
<label class="block text-xs font-bold text-gray-400 uppercase mb-2">Modelo de Bici / Color</label>
|
|
|
|
|
<input type="text" name="bike_model" required placeholder="Ej: Venzo Loki Roja R29" class="w-full bg-neutral-900 border border-neutral-700 text-white rounded-lg p-2.5 focus:ring-neon-lime focus:border-neon-lime">
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div>
|
|
|
|
|
<label class="block text-xs font-bold text-gray-400 uppercase mb-2">Problema / Servicio</label>
|
|
|
|
|
<textarea name="problem_description" rows="3" required class="w-full bg-neutral-900 border border-neutral-700 text-white rounded-lg p-2.5 focus:ring-neon-lime focus:border-neon-lime" placeholder="Ej: Service completo, hace ruido la caja..."></textarea>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div>
|
|
|
|
|
<label class="block text-xs font-bold text-gray-400 uppercase mb-2">Problema / Servicio Solicitado</label>
|
|
|
|
|
<textarea name="problem_description" rows="4" required class="w-full bg-neutral-900 border border-neutral-700 text-white rounded-lg p-2.5 focus:ring-neon-lime focus:border-neon-lime" placeholder="Ej: Service completo, hace ruido la caja, regular cambios..."></textarea>
|
|
|
|
|
</div>
|
|
|
|
|
<!-- Columna Derecha: Selector de Repuestos -->
|
|
|
|
|
<div class="bg-neutral-900/50 p-4 rounded-xl border border-neutral-800">
|
|
|
|
|
<label class="block text-xs font-bold text-neon-lime uppercase mb-2">Agregar Repuestos / Servicios</label>
|
|
|
|
|
|
|
|
|
|
<div>
|
|
|
|
|
<label class="block text-xs font-bold text-gray-400 uppercase mb-2">Repuestos Estimados (Opcional)</label>
|
|
|
|
|
<textarea name="parts_needed" rows="4" class="w-full bg-neutral-900 border border-neutral-700 text-white rounded-lg p-2.5 focus:ring-neon-lime focus:border-neon-lime" placeholder="Ej: Cadena nueva, pastillas de freno..."></textarea>
|
|
|
|
|
<!-- Buscador -->
|
|
|
|
|
<div class="relative mb-3">
|
|
|
|
|
<input type="text" id="part-search" class="w-full bg-neutral-800 border border-neutral-700 text-white rounded-lg p-2 text-sm focus:ring-neon-lime focus:border-neon-lime" placeholder="Buscar repuesto..." autocomplete="off">
|
|
|
|
|
<!-- Lista desplegable de sugerencias -->
|
|
|
|
|
<div id="suggestions-box" class="absolute left-0 right-0 z-50 bg-neutral-800 border border-neutral-600 rounded-b-lg shadow-xl max-h-40 overflow-y-auto hidden"></div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- Lista Visual de Seleccionados -->
|
|
|
|
|
<div id="selected-parts-container" class="space-y-2 mb-3 min-h-[50px]">
|
|
|
|
|
<p class="text-xs text-gray-600 italic text-center py-2" id="no-parts-msg">Sin repuestos seleccionados</p>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- Input Oculto Real (Este es el que se envía a la BD) -->
|
|
|
|
|
<textarea name="parts_needed" id="parts_needed_real" class="hidden"></textarea>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- 3. Agenda y Costos -->
|
|
|
|
|
<div>
|
|
|
|
|
<h3 class="text-white font-bold uppercase tracking-wider text-sm mb-4">3. Acuerdo</h3>
|
|
|
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
|
|
|
<h3 class="text-white font-bold uppercase tracking-wider text-sm mb-4 flex items-center gap-2">
|
|
|
|
|
<span class="bg-neutral-800 text-neon-lime px-2 py-0.5 rounded text-xs">3</span> Acuerdo
|
|
|
|
|
</h3>
|
|
|
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-6 items-end">
|
|
|
|
|
<div>
|
|
|
|
|
<label class="block text-xs font-bold text-gray-400 uppercase mb-2">Fecha Prometida / Retiro</label>
|
|
|
|
|
<input type="datetime-local" name="scheduled_at" required class="w-full bg-neutral-900 border border-neutral-700 text-white rounded-lg p-2.5 focus:ring-neon-lime focus:border-neon-lime">
|
|
|
|
|
</div>
|
|
|
|
|
<div>
|
|
|
|
|
<label class="block text-xs font-bold text-gray-400 uppercase mb-2">Presupuesto Aproximado ($)</label>
|
|
|
|
|
<input type="number" name="estimated_cost" step="0.01" class="w-full bg-neutral-900 border border-neutral-700 text-white rounded-lg p-2.5 focus:ring-neon-lime focus:border-neon-lime text-right font-mono" placeholder="0.00">
|
|
|
|
|
|
|
|
|
|
<div class="bg-neutral-800 p-4 rounded-lg border border-neutral-700">
|
|
|
|
|
<label class="block text-xs font-bold text-gray-400 uppercase mb-1">Presupuesto Estimado</label>
|
|
|
|
|
<div class="flex items-center gap-2">
|
|
|
|
|
<span class="text-gray-500">$</span>
|
|
|
|
|
<!-- Input de costo: Se autocalcula pero el usuario puede editarlo manualmente -->
|
|
|
|
|
<input type="number" id="estimated_cost" name="estimated_cost" step="0.01" class="w-full bg-transparent border-0 text-white text-2xl font-black focus:ring-0 p-0" placeholder="0.00">
|
|
|
|
|
</div>
|
|
|
|
|
<p class="text-[10px] text-gray-500 mt-1">* Calculado automáticamente según repuestos. Editable.</p>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="flex justify-end pt-4">
|
|
|
|
|
<button type="submit" class="px-8 py-3 bg-neon-lime text-neutral-900 font-bold rounded-lg hover:bg-[#b3e600] uppercase tracking-wide">
|
|
|
|
|
<div class="flex justify-end pt-4 border-t border-neutral-800">
|
|
|
|
|
<a href="{{ route('taller.index') }}" class="mr-4 px-6 py-3 text-gray-400 hover:text-white font-medium">Cancelar</a>
|
|
|
|
|
<button type="submit" class="px-8 py-3 bg-neon-lime text-neutral-900 font-bold rounded-lg hover:bg-[#b3e600] uppercase tracking-wide shadow-lg shadow-neon-lime/20">
|
|
|
|
|
Ingresar Bicicleta
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
</form>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- Scripts para el Buscador de Repuestos -->
|
|
|
|
|
@push('scripts')
|
|
|
|
|
<script type="module">
|
|
|
|
|
const partsDB = @json($products);
|
|
|
|
|
let selectedParts = [];
|
|
|
|
|
|
|
|
|
|
$(document).ready(function() {
|
|
|
|
|
// --- 1. Lógica del Buscador ---
|
|
|
|
|
$('#part-search').on('keyup focus', function() {
|
|
|
|
|
let term = $(this).val().toLowerCase();
|
|
|
|
|
let $box = $('#suggestions-box');
|
|
|
|
|
|
|
|
|
|
if (term.length === 0) {
|
|
|
|
|
$box.addClass('hidden').empty();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let matches = partsDB.filter(p => p.name.toLowerCase().includes(term) || (p.sku && p.sku.toLowerCase().includes(term)));
|
|
|
|
|
|
|
|
|
|
let html = '';
|
|
|
|
|
if (matches.length > 0) {
|
|
|
|
|
matches.forEach(p => {
|
|
|
|
|
html += `
|
|
|
|
|
<div class="p-2 hover:bg-neutral-700 cursor-pointer text-xs text-white border-b border-neutral-700 last:border-0 suggestion-item flex justify-between items-center"
|
|
|
|
|
data-id="${p.id}" data-name="${p.name}" data-price="${p.price}">
|
|
|
|
|
<span>${p.name}</span>
|
|
|
|
|
<span class="text-neon-lime font-mono">$${p.price}</span>
|
|
|
|
|
</div>`;
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
html = '<div class="p-2 text-xs text-gray-500 italic">No encontrado</div>';
|
|
|
|
|
}
|
|
|
|
|
$box.html(html).removeClass('hidden');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Ocultar sugerencias al hacer clic fuera
|
|
|
|
|
$(document).click(function(e) {
|
|
|
|
|
if (!$(e.target).closest('#part-search, #suggestions-box').length) {
|
|
|
|
|
$('#suggestions-box').addClass('hidden');
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// --- 2. Agregar Repuesto ---
|
|
|
|
|
$(document).on('click', '.suggestion-item', function() {
|
|
|
|
|
let item = {
|
|
|
|
|
id: $(this).data('id'),
|
|
|
|
|
name: $(this).data('name'),
|
|
|
|
|
price: parseFloat($(this).data('price'))
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Agregar al array
|
|
|
|
|
selectedParts.push(item);
|
|
|
|
|
|
|
|
|
|
// Limpiar buscador
|
|
|
|
|
$('#part-search').val('').focus();
|
|
|
|
|
$('#suggestions-box').addClass('hidden');
|
|
|
|
|
|
|
|
|
|
renderList();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// --- 3. Eliminar Repuesto ---
|
|
|
|
|
window.removePart = function(index) {
|
|
|
|
|
selectedParts.splice(index, 1);
|
|
|
|
|
renderList();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// --- 4. Renderizar Lista y Calcular ---
|
|
|
|
|
function renderList() {
|
|
|
|
|
let $container = $('#selected-parts-container');
|
|
|
|
|
$container.empty();
|
|
|
|
|
let totalCost = 0;
|
|
|
|
|
let partsText = ""; // Texto para la BD
|
|
|
|
|
|
|
|
|
|
if (selectedParts.length === 0) {
|
|
|
|
|
$container.html('<p class="text-xs text-gray-600 italic text-center py-2" id="no-parts-msg">Sin repuestos seleccionados</p>');
|
|
|
|
|
} else {
|
|
|
|
|
selectedParts.forEach((p, index) => {
|
|
|
|
|
totalCost += p.price;
|
|
|
|
|
|
|
|
|
|
// Construimos texto para BD: "- Cámara ($5000)\n"
|
|
|
|
|
partsText += `- ${p.name} ($${p.price})\n`;
|
|
|
|
|
|
|
|
|
|
// Visual
|
|
|
|
|
$container.append(`
|
|
|
|
|
<div class="flex justify-between items-center bg-neutral-800 p-2 rounded border border-neutral-700 text-xs">
|
|
|
|
|
<div class="text-white">
|
|
|
|
|
${p.name}
|
|
|
|
|
<span class="text-gray-500 ml-1">($${p.price})</span>
|
|
|
|
|
</div>
|
|
|
|
|
<button type="button" onclick="removePart(${index})" class="text-red-500 hover:text-red-400 font-bold px-1">×</button>
|
|
|
|
|
</div>
|
|
|
|
|
`);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Actualizar Inputs del Formulario
|
|
|
|
|
$('#estimated_cost').val(totalCost > 0 ? totalCost : ''); // Presupuesto
|
|
|
|
|
$('#parts_needed_real').val(partsText); // Texto para la BD
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
</script>
|
|
|
|
|
@endpush
|
|
|
|
|
|
|
|
|
|
</x-layout>
|