ARREGLOS: Correccion de comentarios y cambio en tablas productos, cambiados los tipos de productos a (bike, accessory, clothing, spare) para manejo futuro de repuestos y carga de datos de excel de productos.
This commit is contained in:
@@ -20,11 +20,11 @@ class CatalogoController extends Controller
|
|||||||
$searchTerm = $request->input('search');
|
$searchTerm = $request->input('search');
|
||||||
|
|
||||||
$query->where(function($q) use ($searchTerm) {
|
$query->where(function($q) use ($searchTerm) {
|
||||||
$q->where('name', 'like', "%{$searchTerm}%") // Buscar por nombre
|
$q->where('name', 'like', "%{$searchTerm}%")
|
||||||
->orWhere('sku', 'like', "%{$searchTerm}%"); // O por código SKU
|
->orWhere('sku', 'like', "%{$searchTerm}%");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
$query->whereIn('type', ['bike', 'accessory']);// Filtros para el público
|
$query->whereIn('type', ['bike', 'accessory', 'clothing', 'spare']);
|
||||||
$query->where('stock_quantity', '>', 0); // Solo mostrar si tiene stock
|
$query->where('stock_quantity', '>', 0); // Solo mostrar si tiene stock
|
||||||
|
|
||||||
// Resultados paginados
|
// Resultados paginados
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ class ClientController extends Controller
|
|||||||
return $q->where('name', 'like', "%{$query}%");
|
return $q->where('name', 'like', "%{$query}%");
|
||||||
})
|
})
|
||||||
->orderBy('name', 'asc')
|
->orderBy('name', 'asc')
|
||||||
//->orderBy('create_at', 'asc')
|
|
||||||
->paginate(10) // Paginamos de a 10
|
->paginate(10) // Paginamos de a 10
|
||||||
->withQueryString(); // Mantiene el filtro de búsqueda al cambiar de página
|
->withQueryString(); // Mantiene el filtro de búsqueda al cambiar de página
|
||||||
|
|
||||||
@@ -53,13 +52,18 @@ class ClientController extends Controller
|
|||||||
// 2. Verificamos el origen
|
// 2. Verificamos el origen
|
||||||
if ($request->input('origin') === 'sales') {
|
if ($request->input('origin') === 'sales') {
|
||||||
|
|
||||||
// Si vino de ventas, volvemos a ventas
|
// Si vino de ventas, volvemos a ventas con el cliente nuevo
|
||||||
// Y pasamos el ID del nuevo cliente para auto-seleccionarlo
|
|
||||||
return redirect()->route('sales.create', ['new_client_id' => $client->id])
|
return redirect()->route('sales.create', ['new_client_id' => $client->id])
|
||||||
->with('success', 'Cliente creado. Ya puedes seleccionarlo.');
|
->with('success', 'Cliente creado. Ya puedes seleccionarlo.');
|
||||||
}
|
}
|
||||||
|
else if ($request->input('origin') === 'taller') {
|
||||||
|
|
||||||
|
// Si vino de taller, volvemos a taller con el cliente nuevo
|
||||||
|
return redirect()->route('taller.create', ['new_client_id' => $client->id])
|
||||||
|
->with('success', 'Cliente creado. Ya puedes seleccionarlo.');
|
||||||
|
}
|
||||||
|
|
||||||
// 3. Si no, comportamiento normal (volver al index de clientes)
|
// 3. Si no, vuelvo al index de clientes
|
||||||
return redirect()->route('clients.index')
|
return redirect()->route('clients.index')
|
||||||
->with('success', 'Cliente creado correctamente.');
|
->with('success', 'Cliente creado correctamente.');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,9 +11,9 @@ class HomeController extends Controller
|
|||||||
{
|
{
|
||||||
// Si tuvieras un campo 'sales_count', podrías usar ->orderByDesc('sales_count')
|
// Si tuvieras un campo 'sales_count', podrías usar ->orderByDesc('sales_count')
|
||||||
$destacados = Product::where('type', 'bike')
|
$destacados = Product::where('type', 'bike')
|
||||||
->latest() // Las más nuevas
|
->latest() // Las más nuevas
|
||||||
->take(5)
|
->take(5)
|
||||||
->get();
|
->get();
|
||||||
|
|
||||||
// Si no hay bicis, traemos cualquier cosa para que no se rompa
|
// Si no hay bicis, traemos cualquier cosa para que no se rompa
|
||||||
if ($destacados->isEmpty()) {
|
if ($destacados->isEmpty()) {
|
||||||
|
|||||||
@@ -14,13 +14,13 @@ class LoginController extends Controller
|
|||||||
'email' => ['required', 'email'],
|
'email' => ['required', 'email'],
|
||||||
'password' => ['required'],
|
'password' => ['required'],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (Auth::attempt($credentials)) {
|
if (Auth::attempt($credentials)) {
|
||||||
$request->session()->regenerate();
|
$request->session()->regenerate();
|
||||||
|
|
||||||
return redirect()->intended('dashboard');
|
return redirect()->intended('dashboard');
|
||||||
}
|
}
|
||||||
|
|
||||||
return back()->withErrors([
|
return back()->withErrors([
|
||||||
'email' => 'Los datos no coinciden.',
|
'email' => 'Los datos no coinciden.',
|
||||||
])->onlyInput('email');
|
])->onlyInput('email');
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ namespace App\Http\Controllers;
|
|||||||
|
|
||||||
use App\Models\Product;
|
use App\Models\Product;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Validation\Rule; // Necesario para validar unicidad al editar
|
use Illuminate\Validation\Rule;
|
||||||
use Illuminate\Support\Facades\Storage; // <--- IMPORTANTE: Agregar esto arriba
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
|
||||||
class ProductosController extends Controller
|
class ProductosController extends Controller
|
||||||
{
|
{
|
||||||
@@ -14,33 +14,30 @@ class ProductosController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function index(Request $request)
|
public function index(Request $request)
|
||||||
{
|
{
|
||||||
// Recuperamos lo que el usuario escribió en el buscador (si escribió algo)
|
// Recuperamos lo escrito en el buscador (si aplica)
|
||||||
$query = $request->input('search');
|
$query = $request->input('search');
|
||||||
$status = $request->input('stock_status');
|
$status = $request->input('stock_status');
|
||||||
|
|
||||||
// Construimos la consulta
|
// Construimos la consulta
|
||||||
$products = Product::query()
|
$products = Product::query()
|
||||||
->when($query, function ($q) use ($query) {
|
->when($query, function ($q) use ($query) {
|
||||||
// Si hay búsqueda, filtra por nombre o SKU
|
// Filtra por nombre o SKU
|
||||||
return $q->where('name', 'like', "%{$query}%")
|
return $q->where('name', 'like', "%{$query}%")
|
||||||
->orWhere('sku', 'like', "%{$query}%");
|
->orWhere('sku', 'like', "%{$query}%");
|
||||||
})
|
})
|
||||||
->when($status, function ($q) use ($status) {
|
->when($status, function ($q) use ($status) {
|
||||||
if ($status === 'low') {
|
if ($status === 'low') {
|
||||||
// Rojo: Menor o igual a la alerta
|
// Rojo: Menor o igual a la alerta
|
||||||
return $q->whereColumn('stock_quantity', '<', 'min_stock_alert')
|
return $q->whereColumn('stock_quantity', '<', 'min_stock_alert');
|
||||||
->where('type', '!=', 'service'); // Ignoramos servicios
|
|
||||||
}
|
}
|
||||||
elseif ($status === 'medium') {
|
elseif ($status === 'medium') {
|
||||||
// Amarillo: Mayor a alerta PERO menor o igual a alerta + 2 (margen pequeño)
|
// Amarillo: Mayor al min y menor o igual al min + 5
|
||||||
return $q->whereColumn('stock_quantity', '>=', 'min_stock_alert')
|
return $q->whereColumn('stock_quantity', '>=', 'min_stock_alert')
|
||||||
->whereRaw('stock_quantity <= (min_stock_alert + 1)') // Ajusta este "+ 5" según tu criterio de "amarillo"
|
->whereRaw('stock_quantity <= (min_stock_alert + 5)');
|
||||||
->where('type', '!=', 'service');
|
|
||||||
}
|
}
|
||||||
elseif ($status === 'ok') {
|
elseif ($status === 'ok') {
|
||||||
// Verde: Stock saludable
|
// Verde: Stock saludable
|
||||||
return $q->whereRaw('stock_quantity > (min_stock_alert + 1)')
|
return $q->whereRaw('stock_quantity > (min_stock_alert + 5)');
|
||||||
->where('type', '!=', 'service');
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
->orderBy('stock_quantity', 'asc') // Ordenamos primero los que tienen poco stock (Alerta visual)
|
->orderBy('stock_quantity', 'asc') // Ordenamos primero los que tienen poco stock (Alerta visual)
|
||||||
@@ -72,7 +69,7 @@ class ProductosController extends Controller
|
|||||||
'cost' => 'nullable|numeric|min:0', // Costo opcional
|
'cost' => 'nullable|numeric|min:0', // Costo opcional
|
||||||
'stock_quantity' => 'required|integer|min:0',
|
'stock_quantity' => 'required|integer|min:0',
|
||||||
'min_stock_alert' => 'required|integer|min:0',
|
'min_stock_alert' => 'required|integer|min:0',
|
||||||
'type' => 'required|in:bike,accessory,service', // Solo permite estos 3 valores
|
'type' => 'required|in:bike,accessory,clothing,spare', // Solo permite estos valores
|
||||||
'serial_number' => 'nullable|string|max:100',
|
'serial_number' => 'nullable|string|max:100',
|
||||||
'image' => 'nullable|image|mimes:jpeg,png,jpg,webp|max:2048',
|
'image' => 'nullable|image|mimes:jpeg,png,jpg,webp|max:2048',
|
||||||
]);
|
]);
|
||||||
@@ -93,6 +90,7 @@ class ProductosController extends Controller
|
|||||||
|
|
||||||
// Para no romper la logica del supplier
|
// Para no romper la logica del supplier
|
||||||
$validated['suppliers_id'] = 1;
|
$validated['suppliers_id'] = 1;
|
||||||
|
|
||||||
// 3. Creamos el producto
|
// 3. Creamos el producto
|
||||||
Product::create($validated);
|
Product::create($validated);
|
||||||
|
|
||||||
@@ -103,7 +101,6 @@ class ProductosController extends Controller
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Muestra el detalle de un producto.
|
* Muestra el detalle de un producto.
|
||||||
* Usamos Route Model Binding: Laravel busca el ID solo.
|
|
||||||
*/
|
*/
|
||||||
public function show(Product $product)
|
public function show(Product $product)
|
||||||
{
|
{
|
||||||
@@ -132,7 +129,7 @@ class ProductosController extends Controller
|
|||||||
'cost' => 'nullable|numeric|min:0',
|
'cost' => 'nullable|numeric|min:0',
|
||||||
'stock_quantity' => 'required|integer|min:0',
|
'stock_quantity' => 'required|integer|min:0',
|
||||||
'min_stock_alert' => 'required|integer|min:0',
|
'min_stock_alert' => 'required|integer|min:0',
|
||||||
'type' => 'required|in:bike,accessory,service',
|
'type' => 'required|in:bike,accessory,clothing,spare',
|
||||||
'serial_number' => 'nullable|string|max:100',
|
'serial_number' => 'nullable|string|max:100',
|
||||||
|
|
||||||
'image' => 'nullable|image|mimes:jpeg,png,jpg,webp|max:2048',
|
'image' => 'nullable|image|mimes:jpeg,png,jpg,webp|max:2048',
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ class RegisterController extends Controller
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
$userData['password'] = bcrypt($userData['password']);
|
$userData['password'] = bcrypt($userData['password']);
|
||||||
|
|
||||||
$user = User::create($userData);
|
$user = User::create($userData);
|
||||||
|
|
||||||
Auth::login($user);
|
Auth::login($user);
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ class TallerController extends Controller
|
|||||||
{
|
{
|
||||||
$clients = Client::orderBy('name')->get();
|
$clients = Client::orderBy('name')->get();
|
||||||
|
|
||||||
$products = Product::whereIn('type', ['accessory'])
|
$products = Product::whereIn('type', ['accessory','spare'])
|
||||||
->where('stock_quantity', '>', 0)
|
->where('stock_quantity', '>', 0)
|
||||||
->get(['id', 'name', 'price', 'sku', 'stock_quantity']); // Solo campos necesarios
|
->get(['id', 'name', 'price', 'sku', 'stock_quantity']); // Solo campos necesarios
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -8,22 +8,22 @@ class Sale extends Model
|
|||||||
{
|
{
|
||||||
//use HasFactory;
|
//use HasFactory;
|
||||||
|
|
||||||
// Permitimos asignación masiva para poder guardar rápido
|
// Permitimos asignación masiva
|
||||||
protected $guarded = [];
|
protected $guarded = [];
|
||||||
|
|
||||||
// Relación 1: Una venta la realiza un Usuario (User)
|
// Rel 1: Una venta la hace un Usuario
|
||||||
public function user()
|
public function user()
|
||||||
{
|
{
|
||||||
return $this->belongsTo(User::class);
|
return $this->belongsTo(User::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Relación 2: Una venta pertenece a un Cliente (User)
|
// Rel 2: Una venta pertenece a un Cliente
|
||||||
public function client()
|
public function client()
|
||||||
{
|
{
|
||||||
return $this->belongsTo(Client::class);
|
return $this->belongsTo(Client::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Relación 3: Una venta tiene muchos items o detalles
|
// Rel 3: Una venta tiene muchos items
|
||||||
public function details()
|
public function details()
|
||||||
{
|
{
|
||||||
return $this->hasMany(SaleDetail::class);
|
return $this->hasMany(SaleDetail::class);
|
||||||
|
|||||||
@@ -9,13 +9,13 @@ class SaleDetail extends Model
|
|||||||
//use HasFactory;
|
//use HasFactory;
|
||||||
protected $guarded = [];
|
protected $guarded = [];
|
||||||
|
|
||||||
// este detalle pertenece a una Venta específica
|
// Rel 1: Este detalle pertenece a una Venta específica
|
||||||
public function sale()
|
public function sale()
|
||||||
{
|
{
|
||||||
return $this->belongsTo(Sale::class);
|
return $this->belongsTo(Sale::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
// este detalle corresponde a un Producto
|
// Rel 2: Este detalle pertenece a un Producto
|
||||||
public function product()
|
public function product()
|
||||||
{
|
{
|
||||||
return $this->belongsTo(Product::class);
|
return $this->belongsTo(Product::class);
|
||||||
|
|||||||
+1
-1
@@ -78,7 +78,7 @@ return [
|
|||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'locale' => env('APP_LOCALE', 'en'),
|
'locale' => env('APP_LOCALE', 'es'),
|
||||||
|
|
||||||
'fallback_locale' => env('APP_FALLBACK_LOCALE', 'en'),
|
'fallback_locale' => env('APP_FALLBACK_LOCALE', 'en'),
|
||||||
|
|
||||||
|
|||||||
@@ -19,23 +19,24 @@ class ProductFactory extends Factory
|
|||||||
$brands = ['Shimano', 'Venzo', 'Trek', 'Specialized', 'Maxxis', 'Sram', 'Raleigh'];
|
$brands = ['Shimano', 'Venzo', 'Trek', 'Specialized', 'Maxxis', 'Sram', 'Raleigh'];
|
||||||
$bikeModels = ['Loki', 'Marlin 5', 'Chisel', 'Talon 3', 'Aspect 950'];
|
$bikeModels = ['Loki', 'Marlin 5', 'Chisel', 'Talon 3', 'Aspect 950'];
|
||||||
$accessories = ['Guantes Grip', 'Calco Reflectora', 'Coderas', 'Rodilleras', 'Casco MTB', 'Luz Delantera USB', 'Cubierta Kevlar'];
|
$accessories = ['Guantes Grip', 'Calco Reflectora', 'Coderas', 'Rodilleras', 'Casco MTB', 'Luz Delantera USB', 'Cubierta Kevlar'];
|
||||||
// PARA DESPUES
|
|
||||||
$spareParts = ['Manubrio', 'Pedales Aluminio', 'Cámara 29"', 'Rayos x50', 'Disco de Freno', 'Cable de Freno', 'Asiento Goma', 'Cadena 9v'];
|
$spareParts = ['Manubrio', 'Pedales Aluminio', 'Cámara 29"', 'Rayos x50', 'Disco de Freno', 'Cable de Freno', 'Asiento Goma', 'Cadena 9v'];
|
||||||
|
$cats = ['Pro', 'Basic', 'Comp', 'Elite'];
|
||||||
$type = $this->faker->randomElement(['bike', 'accessory', 'service']);
|
$type = $this->faker->randomElement(['bike', 'accessory', 'clothing', 'spare']);
|
||||||
|
|
||||||
// Generar nombre según el tipo
|
// Generar nombre según el tipo
|
||||||
if ($type === 'bike') {
|
if ($type === 'bike') {
|
||||||
$name = $this->faker->randomElement($brands) . ' ' . $this->faker->randomElement($bikeModels);
|
$name = $this->faker->randomElement($brands) . ' ' . $this->faker->randomElement($bikeModels);
|
||||||
} elseif ($type === 'accessory') {
|
} elseif ($type === 'accessory') {
|
||||||
$name = $this->faker->randomElement($accessories) . ' ' . $this->faker->randomElement(['Pro', 'Basic', 'Comp', 'Elite']);
|
$name = $this->faker->randomElement($accessories) .' '. $this->faker->randomElement($cats);
|
||||||
|
} elseif ($type === 'clothing') {
|
||||||
|
$name = $this->faker->randomElement(['Remera', 'Pantalon', 'Casco', 'Coderas', 'Guantes']).' '.$this->faker->randomElement($cats);
|
||||||
} else {
|
} else {
|
||||||
$name = $this->faker->randomElement(['Service General', 'Ajuste Cambios', 'Centrado de Rueda', 'Lavado y Engrase']);
|
$name = $this->faker->randomElement($spareParts) .' '. $this->faker->randomElement($cats);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lógica de Precios
|
// Lógica de Precios
|
||||||
$price = $this->faker->numberBetween(5000, 800000);
|
$price = $this->faker->numberBetween(5000, 200000);
|
||||||
$cost = $price * $this->faker->randomFloat(2, 0.5, 0.7);
|
$cost = $price * $this->faker->randomFloat(2, 0.1, 0.8);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'name' => $name,
|
'name' => $name,
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ return new class extends Migration
|
|||||||
public function up(): void
|
public function up(): void
|
||||||
{
|
{
|
||||||
Schema::table('users', function (Blueprint $table) {
|
Schema::table('users', function (Blueprint $table) {
|
||||||
$table->enum('role', ['admin', 'employee'])->default('employee')->after('email');
|
$table->enum('role', ['admin', 'employee', 'guest'])->default('guest')->after('email');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ return new class extends Migration
|
|||||||
$table->integer('stock_quantity')->default(0);
|
$table->integer('stock_quantity')->default(0);
|
||||||
$table->integer('min_stock_alert'); // Alerta
|
$table->integer('min_stock_alert'); // Alerta
|
||||||
|
|
||||||
$table->enum('type', ['bike', 'accessory', 'service']);
|
$table->enum('type', ['bike', 'accessory', 'clothing', 'spare']); // Tipo de producto
|
||||||
$table->string('serial_number')->nullable(); // Solo para bicis
|
$table->string('serial_number')->nullable(); // Solo para bicis
|
||||||
|
|
||||||
$table->foreignId('suppliers_id')->constrained()->default(1);
|
$table->foreignId('suppliers_id')->constrained()->default(1);
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ return new class extends Migration
|
|||||||
// Repuestos estimados (texto simple por ahora)
|
// Repuestos estimados (texto simple por ahora)
|
||||||
$table->text('parts_needed')->nullable()->after('problem_description');
|
$table->text('parts_needed')->nullable()->after('problem_description');
|
||||||
|
|
||||||
// Costo Aproximado (Presupuesto)
|
// Costo (Presupuesto)
|
||||||
$table->decimal('estimated_cost', 10, 2)->nullable()->after('parts_needed');
|
$table->decimal('estimated_cost', 10, 2)->nullable()->after('parts_needed');
|
||||||
|
|
||||||
// Teléfono de contacto rápido (por si es distinto al del cliente registrado)
|
// Teléfono de contacto rápido (por si es distinto al del cliente registrado)
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ class DatabaseSeeder extends Seeder
|
|||||||
{
|
{
|
||||||
//Crear el Super Admin
|
//Crear el Super Admin
|
||||||
User::factory()->create([
|
User::factory()->create([
|
||||||
'name' => 'Jose Admin',
|
'name' => 'Sergio Lauck',
|
||||||
'email' => 'admin@lauck.com',
|
'email' => 'admin@lauck.com',
|
||||||
'password' => bcrypt('password'), // Cambiar en producción
|
'password' => bcrypt('password'), // Cambiar en producción
|
||||||
'role' => 'admin',
|
'role' => 'admin',
|
||||||
@@ -60,7 +60,7 @@ class DatabaseSeeder extends Seeder
|
|||||||
'suppliers_id' => 1
|
'suppliers_id' => 1
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Generar 10 productos aleatorios más
|
// Generar 50 productos aleatorios más
|
||||||
Product::factory(50)->create();
|
Product::factory(50)->create();
|
||||||
|
|
||||||
// Clientes y Turnos
|
// Clientes y Turnos
|
||||||
|
|||||||
@@ -27,11 +27,17 @@
|
|||||||
|
|
||||||
<!-- Badge de Tipo Flotante -->
|
<!-- Badge de Tipo Flotante -->
|
||||||
<div class="absolute top-6 left-6">
|
<div class="absolute top-6 left-6">
|
||||||
@if($product->type == 'bike')
|
<span class="bg-black/50 backdrop-blur text-white px-3 py-1 rounded-full text-xs font-bold uppercase tracking-wide border border-white/10">
|
||||||
<span class="bg-black/50 backdrop-blur text-white px-3 py-1 rounded-full text-xs font-bold uppercase tracking-wide border border-white/10">Bicicleta</span>
|
@if($product->type == 'bike')
|
||||||
@else
|
Bicicleta
|
||||||
<span class="bg-black/50 backdrop-blur text-white px-3 py-1 rounded-full text-xs font-bold uppercase tracking-wide border border-white/10">Accesorio</span>
|
@elseif($product->type == 'clothing')
|
||||||
@endif
|
Indumentaria
|
||||||
|
@elseif($product->type == 'spare')
|
||||||
|
Repuesto
|
||||||
|
@else
|
||||||
|
Accesorio
|
||||||
|
@endif
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
$colors = [
|
$colors = [
|
||||||
'gray' => 'bg-gray-700 text-gray-300',
|
'gray' => 'bg-gray-700 text-gray-300',
|
||||||
'red' => 'bg-red-900/50 text-red-300 border border-red-800',
|
'red' => 'bg-red-900/50 text-red-300 border border-red-800',
|
||||||
|
'blue' => 'bg-blue-900/50 text-blue-300 border border-blue-800',
|
||||||
'green' => 'bg-green-900/50 text-green-300 border border-green-800',
|
'green' => 'bg-green-900/50 text-green-300 border border-green-800',
|
||||||
'yellow' => 'bg-yellow-900/50 text-yellow-300 border border-yellow-800',
|
'yellow' => 'bg-yellow-900/50 text-yellow-300 border border-yellow-800',
|
||||||
'neon' => 'bg-[#ccff00]/10 text-[#ccff00] border border-[#ccff00]/50',
|
'neon' => 'bg-[#ccff00]/10 text-[#ccff00] border border-[#ccff00]/50',
|
||||||
|
|||||||
@@ -26,9 +26,10 @@
|
|||||||
<div class="md:col-span-2">
|
<div class="md:col-span-2">
|
||||||
<x-forms.label for="type" value="Tipo de Producto" />
|
<x-forms.label for="type" value="Tipo de Producto" />
|
||||||
<select id="type" name="type" class="bg-neutral-800 border-neutral-700 text-white text-sm rounded-lg focus:ring-neon-lime focus:border-neon-lime block w-full p-2.5">
|
<select id="type" name="type" class="bg-neutral-800 border-neutral-700 text-white text-sm rounded-lg focus:ring-neon-lime focus:border-neon-lime block w-full p-2.5">
|
||||||
<option value="accessory" {{ old('type') == 'accessory' ? 'selected' : '' }}>Accesorio / Repuesto</option>
|
<option value="accessory" {{ old('type') == 'accessory' ? 'selected' : '' }}>Accesorio</option>
|
||||||
<option value="bike" {{ old('type') == 'bike' ? 'selected' : '' }}>Bicicleta</option>
|
<option value="bike" {{ old('type') == 'bike' ? 'selected' : '' }}>Bicicleta</option>
|
||||||
<option value="service" {{ old('type') == 'service' ? 'selected' : '' }}>Servicio / Mano de Obra</option>
|
<option value="clothing" {{ old('type') == 'clothing' ? 'selected' : '' }}>Indumentaria</option>
|
||||||
|
<option value="spare" {{ old('type') == 'spare' ? 'selected' : '' }}>Repuesto</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,59 +1,3 @@
|
|||||||
{{-- <x-appc>
|
|
||||||
<x-slot name="title">Lauck - Editar</x-slot>
|
|
||||||
<x-slot name="navTitle">Editar - {{$product->nombre}}</x-slot>
|
|
||||||
|
|
||||||
<div class="w-full h-fit flex flex-col justify-start items-center gap-3 p-18">
|
|
||||||
<form class="w-lg mx-auto" action="{{route('productos.update',$product)}}" method="POST">
|
|
||||||
@csrf
|
|
||||||
@method('PUT')
|
|
||||||
<div class="relative z-0 w-full mb-5 group">
|
|
||||||
<input type="text" value="{{$product->nombre}}" name="nombre" id="nombre" class="block py-2.5 px-0 w-full text-sm text-gray-300 bg-transparent border-0 border-b-2 border-gray-300 appearance-none dark:text-white dark:border-gray-600 dark:focus:border-blue-500 focus:outline-none focus:ring-0 focus:border-blue-600 peer"/>
|
|
||||||
<label for="nombre" class="peer-focus:font-medium absolute text-sm text-gray-300 dark:text-gray-300 duration-300 transform -translate-y-6 scale-75 top-3 -z-10 origin-[0] peer-focus:start-0 rtl:peer-focus:translate-x-1/4 rtl:peer-focus:left-auto peer-focus:text-blue-600 peer-focus:dark:text-blue-500 peer-placeholder-shown:scale-100 peer-placeholder-shown:translate-y-0 peer-focus:scale-75 peer-focus:-translate-y-6">Titulo</label>
|
|
||||||
</div>
|
|
||||||
<div class="relative z-0 w-full mb-5 group">
|
|
||||||
<input type="text" value="{{$product->marca}}" name="marca" id="marca" class="block py-2.5 px-0 w-full text-sm text-gray-300 bg-transparent border-0 border-b-2 border-gray-300 appearance-none dark:text-white dark:border-gray-600 dark:focus:border-blue-500 focus:outline-none focus:ring-0 focus:border-blue-600 peer"/>
|
|
||||||
<label for="marca" class="peer-focus:font-medium absolute text-sm text-gray-300 dark:text-gray-300 duration-300 transform -translate-y-6 scale-75 top-3 -z-10 origin-[0] peer-focus:start-0 rtl:peer-focus:translate-x-1/4 peer-focus:text-blue-600 peer-focus:dark:text-blue-500 peer-placeholder-shown:scale-100 peer-placeholder-shown:translate-y-0 peer-focus:scale-75 peer-focus:-translate-y-6">Marca</label>
|
|
||||||
</div>
|
|
||||||
<div class="relative z-0 w-full mb-5 group">
|
|
||||||
<input type="text" value="{{$product->modelo}}" name="modelo" id="modelo" class="block py-2.5 px-0 w-full text-sm text-gray-300 bg-transparent border-0 border-b-2 border-gray-300 appearance-none dark:text-white dark:border-gray-600 dark:focus:border-blue-500 focus:outline-none focus:ring-0 focus:border-blue-600 peer"/>
|
|
||||||
<label for="modelo" class="peer-focus:font-medium absolute text-sm text-gray-300 dark:text-gray-300 duration-300 transform -translate-y-6 scale-75 top-3 -z-10 origin-[0] peer-focus:start-0 rtl:peer-focus:translate-x-1/4 peer-focus:text-blue-600 peer-focus:dark:text-blue-500 peer-placeholder-shown:scale-100 peer-placeholder-shown:translate-y-0 peer-focus:scale-75 peer-focus:-translate-y-6">Modelo</label>
|
|
||||||
</div>
|
|
||||||
<div class="relative z-0 w-full mb-5 group">
|
|
||||||
<textarea type="text" name="descripcion" id="descripcion" class="block py-2.5 px-0 w-full text-sm text-gray-300 bg-transparent border-0 border-b-2 border-gray-300 appearance-none dark:text-white dark:border-gray-600 dark:focus:border-blue-500 focus:outline-none focus:ring-0 focus:border-blue-600 peer">{{$product->descripcion}}</textarea>
|
|
||||||
<label for="descripcion" class="peer-focus:font-medium absolute text-sm text-gray-300 dark:text-gray-300 duration-300 transform -translate-y-6 scale-75 top-3 -z-10 origin-[0] peer-focus:start-0 rtl:peer-focus:translate-x-1/4 peer-focus:text-blue-600 peer-focus:dark:text-blue-500 peer-placeholder-shown:scale-100 peer-placeholder-shown:translate-y-0 peer-focus:scale-75 peer-focus:-translate-y-6">Descripcion</label>
|
|
||||||
</div>
|
|
||||||
<div class="grid md:grid-cols-2 md:gap-6">
|
|
||||||
<div class="relative z-0 w-full mb-5 group">
|
|
||||||
<input type="number" value="{{$product->rodado}}" name="rodado" id="rodado" class="block py-2.5 px-0 w-full text-sm text-gray-300 bg-transparent border-0 border-b-2 border-gray-300 appearance-none dark:text-white dark:border-gray-600 dark:focus:border-blue-500 focus:outline-none focus:ring-0 focus:border-blue-600 peer"/>
|
|
||||||
<label for="rodado" class="peer-focus:font-medium absolute text-sm text-gray-300 dark:text-gray-300 duration-300 transform -translate-y-6 scale-75 top-3 -z-10 origin-[0] peer-focus:start-0 rtl:peer-focus:translate-x-1/4 peer-focus:text-blue-600 peer-focus:dark:text-blue-500 peer-placeholder-shown:scale-100 peer-placeholder-shown:translate-y-0 peer-focus:scale-75 peer-focus:-translate-y-6">Rodado</label>
|
|
||||||
</div>
|
|
||||||
<div class="relative z-0 w-full mb-5 group">
|
|
||||||
<input type="text" value="{{$product->color}}" name="color" id="color"class="block py-2.5 px-0 w-full text-sm text-gray-300 bg-transparent border-0 border-b-2 border-gray-300 appearance-none dark:text-white dark:border-gray-600 dark:focus:border-blue-500 focus:outline-none focus:ring-0 focus:border-blue-600 peer"/>
|
|
||||||
<label for="color" class="peer-focus:font-medium absolute text-sm text-gray-300 dark:text-gray-300 duration-300 transform -translate-y-6 scale-75 top-3 -z-10 origin-[0] peer-focus:start-0 rtl:peer-focus:translate-x-1/4 peer-focus:text-blue-600 peer-focus:dark:text-blue-500 peer-placeholder-shown:scale-100 peer-placeholder-shown:translate-y-0 peer-focus:scale-75 peer-focus:-translate-y-6">Color</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="grid md:grid-cols-2 md:gap-6">
|
|
||||||
<div class="relative z-0 w-full mb-5 group">
|
|
||||||
<input type="text" value="{{$product->tipo}}" name="tipo" id="tipo" class="block py-2.5 px-0 w-full text-sm text-gray-300 bg-transparent border-0 border-b-2 border-gray-300 appearance-none dark:text-white dark:border-gray-600 dark:focus:border-blue-500 focus:outline-none focus:ring-0 focus:border-blue-600 peer"/>
|
|
||||||
<label for="tipo" class="peer-focus:font-medium absolute text-sm text-gray-300 dark:text-gray-300 duration-300 transform -translate-y-6 scale-75 top-3 -z-10 origin-[0] peer-focus:start-0 rtl:peer-focus:translate-x-1/4 peer-focus:text-blue-600 peer-focus:dark:text-blue-500 peer-placeholder-shown:scale-100 peer-placeholder-shown:translate-y-0 peer-focus:scale-75 peer-focus:-translate-y-6">Tipo</label>
|
|
||||||
</div>
|
|
||||||
<div class="relative z-0 w-full mb-5 group">
|
|
||||||
<input type="number" value={{$product->precio}} name="precio" id="precio" class="block py-2.5 px-0 w-full text-sm text-gray-300 bg-transparent border-0 border-b-2 border-gray-300 appearance-none dark:text-white dark:border-gray-600 dark:focus:border-blue-500 focus:outline-none focus:ring-0 focus:border-blue-600 peer" step="0.01"/>
|
|
||||||
<label for="precio" class="peer-focus:font-medium absolute text-sm text-gray-300 dark:text-gray-300 duration-300 transform -translate-y-6 scale-75 top-3 -z-10 origin-[0] peer-focus:start-0 rtl:peer-focus:translate-x-1/4 peer-focus:text-blue-600 peer-focus:dark:text-blue-500 peer-placeholder-shown:scale-100 peer-placeholder-shown:translate-y-0 peer-focus:scale-75 peer-focus:-translate-y-6">Precio (Ej. $9999)</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="flex w-full gap-5">
|
|
||||||
<button type="submit" class="w-full sm:w-auto px-4 py-2 rounded-full text-white font-semibold bg-blue-700 hover:bg-blue-800 dark:bg-blue-700 dark:hover:bg-blue-800">
|
|
||||||
Editar
|
|
||||||
</button>
|
|
||||||
<a href="{{route('productos.show',$product)}}" class="w-full sm:w-auto px-5 py-2 rounded-full text-white font-semibold bg-stone-500">
|
|
||||||
Volver
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</x-appc> --}}
|
|
||||||
<x-layout title="Lauck - Editar Producto">
|
<x-layout title="Lauck - Editar Producto">
|
||||||
<x-section-header subtitle="Inventario" title="Edicion de " highlight="Producto" />
|
<x-section-header subtitle="Inventario" title="Edicion de " highlight="Producto" />
|
||||||
|
|
||||||
@@ -76,9 +20,10 @@
|
|||||||
<div class="md:col-span-2">
|
<div class="md:col-span-2">
|
||||||
<x-forms.label for="type" value="Tipo de Producto" />
|
<x-forms.label for="type" value="Tipo de Producto" />
|
||||||
<select id="type" name="type" class="bg-neutral-800 border-neutral-700 text-white text-sm rounded-lg focus:ring-neon-lime focus:border-neon-lime block w-full p-2.5">
|
<select id="type" name="type" class="bg-neutral-800 border-neutral-700 text-white text-sm rounded-lg focus:ring-neon-lime focus:border-neon-lime block w-full p-2.5">
|
||||||
<option value="accessory" {{ $product->type == 'accessory' ? 'selected' : '' }}>Accesorio / Repuesto</option>
|
<option value="accessory" {{ $product->type == 'accessory' ? 'selected' : '' }}>Accesorio</option>
|
||||||
<option value="bike" {{ $product->type == 'bike' ? 'selected' : '' }}>Bicicleta</option>
|
<option value="bike" {{ $product->type == 'bike' ? 'selected' : '' }}>Bicicleta</option>
|
||||||
<option value="service" {{ $product->type == 'service' ? 'selected' : '' }}>Servicio / Mano de Obra</option>
|
<option value="clothing" {{ $product->type == 'clothing' ? 'selected' : '' }}>Indumentaria</option>
|
||||||
|
<option value="spare" {{ $product->type == 'spare' ? 'selected' : '' }}>Repuesto</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<!-- Precios -->
|
<!-- Precios -->
|
||||||
|
|||||||
@@ -59,18 +59,17 @@
|
|||||||
</td>
|
</td>
|
||||||
<td class="px-6 py-4">
|
<td class="px-6 py-4">
|
||||||
@if($product->type === 'bike') <x-ui.badge color="neon">Bicicleta</x-ui.badge>
|
@if($product->type === 'bike') <x-ui.badge color="neon">Bicicleta</x-ui.badge>
|
||||||
@elseif($product->type === 'accessory') <x-ui.badge color="gray">Accesorio</x-ui.badge>
|
@elseif($product->type === 'clothing') <x-ui.badge color="blue">Indumentaria</x-ui.badge>
|
||||||
@else <x-ui.badge color="yellow">Servicio</x-ui.badge> @endif
|
@elseif($product->type === 'spare') <x-ui.badge color="gray">Repuesto</x-ui.badge>
|
||||||
|
@else <x-ui.badge color="yellow">Accesorio</x-ui.badge> @endif
|
||||||
</td>
|
</td>
|
||||||
<td class="px-6 py-4 font-mono text-white">
|
<td class="px-6 py-4 font-mono text-white">
|
||||||
${{ number_format($product->price, 2) }}
|
${{ number_format($product->price, 2) }}
|
||||||
</td>
|
</td>
|
||||||
<td class="px-6 py-4 text-center">
|
<td class="px-6 py-4 text-center">
|
||||||
@if($product->type === 'service')
|
@if($product->stock_quantity < $product->min_stock_alert)
|
||||||
<span class="text-gray-600">-</span>
|
|
||||||
@elseif($product->stock_quantity < $product->min_stock_alert)
|
|
||||||
<x-ui.badge color="red">{{ $product->stock_quantity }}</x-ui.badge>
|
<x-ui.badge color="red">{{ $product->stock_quantity }}</x-ui.badge>
|
||||||
@elseif($product->stock_quantity <= $product->min_stock_alert+1)
|
@elseif($product->stock_quantity <= $product->min_stock_alert+5)
|
||||||
<x-ui.badge color="yellow">{{ $product->stock_quantity }}</x-ui.badge>
|
<x-ui.badge color="yellow">{{ $product->stock_quantity }}</x-ui.badge>
|
||||||
@else
|
@else
|
||||||
<x-ui.badge color="green">{{ $product->stock_quantity }}</x-ui.badge>
|
<x-ui.badge color="green">{{ $product->stock_quantity }}</x-ui.badge>
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<x-appc>
|
<x-appc>
|
||||||
<div class="max-w-6xl mx-auto px-4 py-8 text-white">
|
<div class="max-w-6xl mx-auto px-4 py-8 text-white">
|
||||||
<a href="{{ route('catalogo') }}">Volver a catalogo</a>
|
<a href="{{ route('catalogo') }}">Volver a catalogo</a>
|
||||||
<h1>Titulo: {{ $producto->nombre }}</h1>
|
<h1>Titulo: {{ $producto->name }}</h1>
|
||||||
<p>
|
<p>
|
||||||
<b>Categoria:</b> {{ $producto->Categoria }}
|
<b>Categoria:</b> {{ $producto->type }}
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
{{ $producto->content }}
|
{{ $producto->content }}
|
||||||
|
|||||||
@@ -60,7 +60,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Lista Visual de Seleccionados -->
|
<!-- Lista Visual de Seleccionados -->
|
||||||
<div id="selected-parts-container" class="space-y-2 mb-3 min-h-[50px]">
|
<div id="selected-parts-container" class="space-y-2 mb-3 min-h-13">
|
||||||
<p class="text-xs text-gray-600 italic text-center py-2" id="no-parts-msg">Sin repuestos seleccionados</p>
|
<p class="text-xs text-gray-600 italic text-center py-2" id="no-parts-msg">Sin repuestos seleccionados</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user