diff --git a/app/Http/Controllers/CatalogoController.php b/app/Http/Controllers/CatalogoController.php new file mode 100644 index 0000000..8991f3e --- /dev/null +++ b/app/Http/Controllers/CatalogoController.php @@ -0,0 +1,41 @@ +has('search')) { + $searchTerm = $request->input('search'); + + $query->where(function($q) use ($searchTerm) { + $q->where('name', 'like', "%{$searchTerm}%") // Buscar por nombre + ->orWhere('sku', 'like', "%{$searchTerm}%"); // O por código SKU + }); + } + $query->whereIn('type', ['bike', 'accessory']);// Filtros para el público + $query->where('stock_quantity', '>', 0); // Solo mostrar si tiene stock + + // Resultados paginados + $products = $query->paginate(12)->withQueryString(); // withQueryString mantiene la búsqueda al cambiar de página + + // Devuelve la vista + return view('catalogo.index', compact('products')); + } + + public function show(Product $product) + { + return view('catalogo.show', compact('product')); + } +} diff --git a/app/Http/Controllers/ClientController.php b/app/Http/Controllers/ClientController.php new file mode 100644 index 0000000..b456d43 --- /dev/null +++ b/app/Http/Controllers/ClientController.php @@ -0,0 +1,109 @@ +input('search'); + + $clients = Client::query() + ->when($query, function ($q) use ($query) { + // Si hay búsqueda, filtra por nombre o SKU + return $q->where('name', 'like', "%{$query}%"); + }) + ->orderBy('name', 'asc') + //->orderBy('create_at', 'asc') + ->paginate(10) // Paginamos de a 10 + ->withQueryString(); // Mantiene el filtro de búsqueda al cambiar de página + + return view('clients.index', compact('clients')); + } + + /** + * Show the form for creating a new resource. + */ + public function create() + { + return view('clients.create'); + } + + /** + * Store a newly created resource in storage. + */ + public function store(Request $request) + { + $validated = $request->validate([ + 'name' => 'required|string|max:255', + 'phone' => 'nullable|string|max:50', + 'email' => 'nullable|email|max:255|unique:clients,email', + 'address' => 'nullable|string|max:255', + ]); + + // 1. Guardamos el cliente en una variable para tener su ID + $client = Client::create($validated); + + // 2. Verificamos el origen + if ($request->input('origin') === 'sales') { + + // Si vino de ventas, volvemos a ventas + // Y pasamos el ID del nuevo cliente para auto-seleccionarlo + return redirect()->route('sales.create', ['new_client_id' => $client->id]) + ->with('success', 'Cliente creado. Ya puedes seleccionarlo.'); + } + + // 3. Si no, comportamiento normal (volver al index de clientes) + return redirect()->route('clients.index') + ->with('success', 'Cliente creado correctamente.'); + } + + /** + * Display the specified resource. + */ + public function show(string $id) + { + // + } + + public function edit(Client $client) + { + // Reutilizamos la vista de create, o creamos una edit.blade.php similar + return view('clients.edit', compact('client')); + } + + public function update(Request $request, Client $client) + { + $validated = $request->validate([ + 'name' => 'required|string|max:255', + 'phone' => 'nullable|string|max:50', + 'email' => 'nullable|email|max:255|unique:clients,email,' . $client->id, // Ignorar email propio + 'address' => 'nullable|string|max:255', + ]); + + $client->update($validated); + + return redirect()->route('clients.index')->with('success', 'Cliente actualizado correctamente.'); + } + + + /** + * Remove the specified resource from storage. + */ + public function destroy(Client $client) + { + try { + $client->delete(); + return redirect()->route('clients.index')->with('success', 'Cliente eliminado correctamente.'); + } catch (\Illuminate\Database\QueryException $e) { + + return back()->with('error', 'No se puede eliminar el cliente porque tiene ventas registradas.'); + } + } +} diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php index dbaf3e2..fd970d4 100644 --- a/app/Http/Controllers/HomeController.php +++ b/app/Http/Controllers/HomeController.php @@ -3,11 +3,23 @@ namespace App\Http\Controllers; use Illuminate\Http\Request; +use App\Models\Product; class HomeController extends Controller { - public function __invoke() // * Controlador con un unico metodo se usa __invoke + public function __invoke(Request $request) { - return view('welcome'); + // Si tuvieras un campo 'sales_count', podrías usar ->orderByDesc('sales_count') + $destacados = Product::where('type', 'bike') + ->latest() // Las más nuevas + ->take(5) + ->get(); + + // Si no hay bicis, traemos cualquier cosa para que no se rompa + if ($destacados->isEmpty()) { + $destacados = Product::take(5)->get(); + } + + return view('welcome', compact('destacados')); } } diff --git a/app/Http/Controllers/ProductosController.php b/app/Http/Controllers/ProductosController.php index be40fa0..92e1c74 100644 --- a/app/Http/Controllers/ProductosController.php +++ b/app/Http/Controllers/ProductosController.php @@ -4,62 +4,169 @@ namespace App\Http\Controllers; use App\Models\Product; use Illuminate\Http\Request; +use Illuminate\Validation\Rule; // Necesario para validar unicidad al editar +use Illuminate\Support\Facades\Storage; // <--- IMPORTANTE: Agregar esto arriba class ProductosController extends Controller { - public function index(){ - $products = Product::orderBy('id','desc')->paginate(); + /** + * Muestra la lista de productos con buscador y paginación. + */ + public function index(Request $request) + { + // Recuperamos lo que el usuario escribió en el buscador (si escribió algo) + $query = $request->input('search'); + $status = $request->input('stock_status'); + + // Construimos la consulta + $products = Product::query() + ->when($query, function ($q) use ($query) { + // Si hay búsqueda, filtra por nombre o SKU + return $q->where('name', 'like', "%{$query}%") + ->orWhere('sku', 'like', "%{$query}%"); + }) + ->when($status, function ($q) use ($status) { + if ($status === 'low') { + // Rojo: Menor o igual a la alerta + return $q->whereColumn('stock_quantity', '<', 'min_stock_alert') + ->where('type', '!=', 'service'); // Ignoramos servicios + } + elseif ($status === 'medium') { + // Amarillo: Mayor a alerta PERO menor o igual a alerta + 2 (margen pequeño) + return $q->whereColumn('stock_quantity', '>=', 'min_stock_alert') + ->whereRaw('stock_quantity <= (min_stock_alert + 1)') // Ajusta este "+ 5" según tu criterio de "amarillo" + ->where('type', '!=', 'service'); + } + elseif ($status === 'ok') { + // Verde: Stock saludable + return $q->whereRaw('stock_quantity > (min_stock_alert + 1)') + ->where('type', '!=', 'service'); + } + }) + ->orderBy('stock_quantity', 'asc') // Ordenamos primero los que tienen poco stock (Alerta visual) + ->paginate(10) // Paginamos de a 10 + ->withQueryString(); // Mantiene el filtro de búsqueda al cambiar de página + return view('productos.index', compact('products')); } - public function create(){ + /** + * Muestra el formulario de creación. + */ + public function create() + { return view('productos.create'); } - public function show($id){ - $producto = Product::find($id); - return view('productos.show', compact('producto')); - } - - public function edit($id){ - $producto = Product::find($id); - return view('productos.edit', compact('producto')); - } - - public function store(Request $request){ - $request->validate([ - 'nombre' => 'required', - 'marca' => 'required', - 'modelo' => 'required', - 'descripcion' => 'required', - 'rodado' => 'required', - 'color' => 'required', - 'tipo' => 'required', - 'precio' => 'required' + /** + * Guarda el producto nuevo en la base de datos. + */ + public function store(Request $request) + { + // 1. Validamos los datos con las nuevas columnas + $validated = $request->validate([ + 'name' => 'required|string|max:255', + 'sku' => 'nullable|string|unique:products,sku|max:50', // SKU único + 'description' => 'nullable|string', + 'price' => 'required|numeric|min:0', + 'cost' => 'nullable|numeric|min:0', // Costo opcional + 'stock_quantity' => 'required|integer|min:0', + 'min_stock_alert' => 'required|integer|min:0', + 'type' => 'required|in:bike,accessory,service', // Solo permite estos 3 valores + 'serial_number' => 'nullable|string|max:100', + 'image' => 'nullable|image|mimes:jpeg,png,jpg,webp|max:2048', ]); - Product::create($request->all()); - return redirect(route('productos.index')); + // 2. Si no viene SKU, generamos uno automático (Opcional pero útil) + if (empty($validated['sku'])) { + $validated['sku'] = 'GEN-' . strtoupper(uniqid()); + } + + // 3. Validacion de imagenes + if ($request->hasFile('image')) { + // Guarda el archivo en storage/app/public/products y devuelve la ruta + $path = $request->file('image')->store('products', 'public'); + $validated['image_path'] = $path; + } + + unset($validated['image']); + + // Para no romper la logica del supplier + $validated['suppliers_id'] = 1; + // 3. Creamos el producto + Product::create($validated); + + // 4. Redireccionamos con mensaje de éxito (Necesitas el componente Alert en el layout) + return redirect()->route('productos.index') + ->with('success', 'Producto creado correctamente.'); } - public function update(Request $request,Product $producto){ - $request->validate([ - 'nombre' => 'required', - 'marca' => 'required', - 'modelo' => 'required', - 'descripcion' => 'required', - 'rodado' => 'required', - 'color' => 'required', - 'tipo' => 'required', - 'precio' => 'required' + /** + * Muestra el detalle de un producto. + * Usamos Route Model Binding: Laravel busca el ID solo. + */ + public function show(Product $product) + { + return view('productos.show', compact('product')); + } + + /** + * Muestra el formulario de edición. + */ + public function edit(Product $product) + { + return view('productos.edit', compact('product')); + } + + /** + * Actualiza el producto existente. + */ + public function update(Request $request, Product $product) + { + $validated = $request->validate([ + 'name' => 'required|string|max:255', + // Validamos que el SKU sea único PERO ignoramos el ID de este producto actual + 'sku' => ['nullable', 'string', Rule::unique('products')->ignore($product->id)], + 'description' => 'nullable|string', + 'price' => 'required|numeric|min:0', + 'cost' => 'nullable|numeric|min:0', + 'stock_quantity' => 'required|integer|min:0', + 'min_stock_alert' => 'required|integer|min:0', + 'type' => 'required|in:bike,accessory,service', + 'serial_number' => 'nullable|string|max:100', + + 'image' => 'nullable|image|mimes:jpeg,png,jpg,webp|max:2048', ]); - $producto->update($request->all()); - return redirect(route('productos.show',$producto)); + + // 2. Manejo de imagen al actualizar + if ($request->hasFile('image')) { + // Borrar la imagen anterior + if ($product->image_path) { + Storage::disk('public')->delete($product->image_path); + } + + // Guardar la nueva + $path = $request->file('image')->store('products', 'public'); + $validated['image_path'] = $path; + } + unset($validated['image']); + + // Para no romper la logica del supplier + $validated['suppliers_id'] = 1; + + $product->update($validated); + + return redirect()->route('productos.index') + ->with('success', 'Producto actualizado exitosamente.'); } - public function destroy($id){ - $producto = Product::find($id); - $producto->delete(); - return redirect(route('productos.index')); + /** + * Elimina el producto. + */ + public function destroy(Product $product) + { + $product->delete(); + return redirect()->route('productos.index') + ->with('success', 'Producto eliminado.'); } -} +} \ No newline at end of file diff --git a/app/Http/Controllers/RegisterController.php b/app/Http/Controllers/RegisterController.php index 7dc5bde..39f4fe1 100644 --- a/app/Http/Controllers/RegisterController.php +++ b/app/Http/Controllers/RegisterController.php @@ -13,7 +13,7 @@ class RegisterController extends Controller { $userData = $request->validate([ 'name' => ['required', 'string'], - 'email' => ['required', 'email'], + 'email' => ['required', 'email', 'unique:users,email'], 'password' => ['required', 'confirmed'] ]); diff --git a/app/Http/Controllers/SaleController.php b/app/Http/Controllers/SaleController.php new file mode 100644 index 0000000..f491de7 --- /dev/null +++ b/app/Http/Controllers/SaleController.php @@ -0,0 +1,100 @@ +orderBy('created_at', 'desc') + ->paginate(15); + + return view('sales.index', compact('sales')); + } + + public function create() + { + // Traemos productos con stock y clientes para los selectores + $products = Product::where('stock_quantity', '>', 0)->get(); + $clients = Client::orderBy('name')->get(); + + return view('sales.create', compact('products', 'clients')); + } + + public function store(Request $request) + { + // Validación estricta + $request->validate([ + 'client_id' => 'nullable|exists:clients,id', + 'payment_method' => 'required|string', + 'items' => 'required|array', + 'items.*.product_id' => 'required|exists:products,id', + 'items.*.quantity' => 'required|integer|min:1', + ]); + + try { + // Variable para guardar el objeto venta y usarlo fuera del closure + $sale = DB::transaction(function () use ($request) { + $totalSale = 0; + + foreach ($request->items as $item) { + $product = Product::find($item['product_id']); + $totalSale += $product->price * $item['quantity']; + + if ($product->stock_quantity < $item['quantity']) { + throw new \Exception("No hay suficiente stock de " . $product->name); + } + + } + + //cabecera + $newSale = Sale::create([ + //'user_id' => auth()->id(), //empleado logueado + 'client_id' => $request->client_id, + 'total' => $totalSale, + 'payment_method' => $request->payment_method, + ]); + + // 3. Guardar Detalle y Restar Stock + foreach ($request->items as $itemData) { + $product = Product::findOrFail($itemData['product_id']); + + SaleDetail::create([ + 'sale_id' => $newSale->id, + 'product_id' => $product->id, + 'quantity' => $itemData['quantity'], + 'price' => $product->price, + ]); + + $product->decrement('stock_quantity', $itemData['quantity']); + } + return $newSale; // Retornamos la venta creada fuera de la transacción + }); + + // 4. REDIRECCIÓN AL DETALLE + return redirect()->route('sales.show', $sale)->with('success', '¡Venta registrada exitosamente!'); + + } catch (\Exception $e) { + return back()->with('error', $e->getMessage())->withInput(); + } + } + + /** + * Muestra el detalle de una venta específica. + */ + public function show(Sale $sale) + { + // Cargamos la venta con el cliente y los detalles + $sale->load(['client', 'details.product']); + + return view('sales.show', compact('sale')); + } +} diff --git a/app/Models/Appointment.php b/app/Models/Appointment.php new file mode 100644 index 0000000..85d1752 --- /dev/null +++ b/app/Models/Appointment.php @@ -0,0 +1,30 @@ + 'datetime', // Laravel lo convierte a objeto Carbon automáticamente + ]; + + // Relación: Un turno pertenece a un cliente + public function client() + { + return $this->belongsTo(Client::class); + } +} diff --git a/app/Models/Client.php b/app/Models/Client.php new file mode 100644 index 0000000..6286e3f --- /dev/null +++ b/app/Models/Client.php @@ -0,0 +1,26 @@ +hasMany(Sale::class); + } + + + // Relación: Un cliente tiene muchos turnos + public function appointments() + { + return $this->hasMany(Appointment::class); + } +} diff --git a/app/Models/Product.php b/app/Models/Product.php index 143a9b8..f9ce056 100644 --- a/app/Models/Product.php +++ b/app/Models/Product.php @@ -8,14 +8,33 @@ use Illuminate\Database\Eloquent\Model; class Product extends Model { use HasFactory; - protected $fillable = [ - 'nombre', - 'marca', - 'modelo', - 'rodado', - 'color', - 'tipo', - 'descripcion', - 'precio' - ]; + protected $guarded = []; + + + public function hasLowStock(): bool + { + return $this->stock_quantity <= $this->min_stock_alert; + } + + public function supplier() + { + return $this->belongsTo(Supplier::class); + } + + // Opción 1: Relación directa con los detalles (Renglones de ticket) + // Útil para saber cantidad total vendida: $product->saleDetails->sum('quantity') + public function saleDetails() + { + return $this->hasMany(SaleDetail::class); + } + + // Opción 2 (Pro Tip): Relación directa con las Ventas a través de los detalles + // Útil para saber EN QUÉ fechas se vendió: $product->sales + public function sales() + { + return $this->belongsToMany(Sale::class, 'sale_details'); + } } +/**$user->sales: Te da la lista de todas las compras de ese usuario. + +$product->saleDetails->count(): Te dice cuántas veces aparece ese producto en tickets.**/ \ No newline at end of file diff --git a/app/Models/Sale.php b/app/Models/Sale.php new file mode 100644 index 0000000..67f7dcb --- /dev/null +++ b/app/Models/Sale.php @@ -0,0 +1,31 @@ +belongsTo(User::class); + } + + // Relación 2: Una venta pertenece a un Cliente (User) + public function client() + { + return $this->belongsTo(Client::class); + } + + // Relación 3: Una venta tiene muchos items o detalles + public function details() + { + return $this->hasMany(SaleDetail::class); + } +} diff --git a/app/Models/SaleDetail.php b/app/Models/SaleDetail.php new file mode 100644 index 0000000..597eff4 --- /dev/null +++ b/app/Models/SaleDetail.php @@ -0,0 +1,23 @@ +belongsTo(Sale::class); + } + + // este detalle corresponde a un Producto + public function product() + { + return $this->belongsTo(Product::class); + } +} \ No newline at end of file diff --git a/app/Models/Supplier.php b/app/Models/Supplier.php new file mode 100644 index 0000000..c72f08a --- /dev/null +++ b/app/Models/Supplier.php @@ -0,0 +1,15 @@ +hasMany(Product::class); + } +} diff --git a/app/View/Components/Alert2.php b/app/View/Components/Alert2.php deleted file mode 100644 index bf1d9bb..0000000 --- a/app/View/Components/Alert2.php +++ /dev/null @@ -1,40 +0,0 @@ -class = $class; - } - - //* Get the view / contents that represent the component. - public function render(): View|Closure|string - { - return view('components.alert2'); - } -} diff --git a/database/factories/ProductFactory.php b/database/factories/ProductFactory.php index 3210886..2ab688a 100644 --- a/database/factories/ProductFactory.php +++ b/database/factories/ProductFactory.php @@ -16,15 +16,39 @@ class ProductFactory extends Factory */ public function definition(): array { + $brands = ['Shimano', 'Venzo', 'Trek', 'Specialized', 'Maxxis', 'Sram', 'Raleigh']; + $bikeModels = ['Loki', 'Marlin 5', 'Chisel', 'Talon 3', 'Aspect 950']; + $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']; + + $type = $this->faker->randomElement(['bike', 'accessory', 'service']); + + // Generar nombre según el tipo + if ($type === 'bike') { + $name = $this->faker->randomElement($brands) . ' ' . $this->faker->randomElement($bikeModels); + } elseif ($type === 'accessory') { + $name = $this->faker->randomElement($accessories) . ' ' . $this->faker->randomElement(['Pro', 'Basic', 'Comp', 'Elite']); + } else { + $name = $this->faker->randomElement(['Service General', 'Ajuste Cambios', 'Centrado de Rueda', 'Lavado y Engrase']); + } + + // Lógica de Precios + $price = $this->faker->numberBetween(5000, 800000); + $cost = $price * $this->faker->randomFloat(2, 0.5, 0.7); + return [ - 'nombre' => $this->faker->sentence(3), - 'marca'=> $this->faker->randomElement(['Cube','Giant','Megamo','KTM','MMR','Liv','Ghost','Lapierre']), - 'modelo'=> $this->faker->bothify('????-####'), - 'rodado'=> $this->faker->numberBetween(12,30), - 'color'=> $this->faker->safeColorName(), - 'tipo'=> $this->faker->word(), - 'descripcion'=> $this->faker->text(), - 'precio'=> $this->faker->randomFloat(2,100,200) + 'name' => $name, + 'sku' => strtoupper($this->faker->bothify('???-#####')), + 'description' => $this->faker->sentence(10), + 'price' => $price, + 'cost' => $cost, + 'stock_quantity' => $type === 'service' ? 0 : $this->faker->numberBetween(0, 50), + 'min_stock_alert' => $this->faker->numberBetween(2, 10), + 'type' => $type, + // Nro de serie si es bicicleta + 'serial_number' => $type === 'bike' ? strtoupper($this->faker->bothify('##??##??')) : null, + 'suppliers_id'=> 1 ]; } } diff --git a/database/migrations/2025_12_06_063046_add_role_to_users_table.php b/database/migrations/2025_12_06_063046_add_role_to_users_table.php new file mode 100644 index 0000000..78352f6 --- /dev/null +++ b/database/migrations/2025_12_06_063046_add_role_to_users_table.php @@ -0,0 +1,28 @@ +enum('role', ['admin', 'employee'])->default('employee')->after('email'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('users', function (Blueprint $table) { + $table->dropColumn('role'); + }); + } +}; diff --git a/database/migrations/2025_08_05_005156_create_products_table.php b/database/migrations/2025_12_06_063539_create_clients_table.php similarity index 51% rename from database/migrations/2025_08_05_005156_create_products_table.php rename to database/migrations/2025_12_06_063539_create_clients_table.php index ecbf13a..8699303 100644 --- a/database/migrations/2025_08_05_005156_create_products_table.php +++ b/database/migrations/2025_12_06_063539_create_clients_table.php @@ -11,16 +11,12 @@ return new class extends Migration */ public function up(): void { - Schema::create('products', function (Blueprint $table) { + Schema::create('clients', function (Blueprint $table) { $table->id(); - $table->string('nombre'); - $table->string('marca'); - $table->string('modelo'); - $table->string('rodado'); - $table->string('color'); - $table->string('tipo'); - $table->text('descripcion'); - $table->float('precio'); + $table->string('name'); + $table->string('phone')->nullable(); // Clave para WhatsApp + $table->string('email')->nullable(); + $table->text('address')->nullable(); $table->timestamps(); }); } @@ -30,6 +26,6 @@ return new class extends Migration */ public function down(): void { - Schema::dropIfExists('products'); + Schema::dropIfExists('clients'); } }; diff --git a/database/migrations/2025_12_06_063714_create_appointments_table.php b/database/migrations/2025_12_06_063714_create_appointments_table.php new file mode 100644 index 0000000..3989e83 --- /dev/null +++ b/database/migrations/2025_12_06_063714_create_appointments_table.php @@ -0,0 +1,39 @@ +id(); + + // Si se borra cliente, se borran sus turnos + $table->foreignId('client_id')->constrained()->onDelete('cascade'); + + $table->dateTime('scheduled_at'); // Fecha y hora del turno + $table->string('bike_model'); + $table->text('problem_description'); // Ej: "Hace ruido la caja" + + $table->enum('status', ['pending', 'confirmed', 'in_progress', 'ready', 'delivered']) + ->default('pending'); + + $table->text('notes')->nullable(); // Notas internas del mecánico + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('appointments'); + } +}; diff --git a/database/migrations/2025_12_06_182356_create_suppliers_table.php b/database/migrations/2025_12_06_182356_create_suppliers_table.php new file mode 100644 index 0000000..ed43605 --- /dev/null +++ b/database/migrations/2025_12_06_182356_create_suppliers_table.php @@ -0,0 +1,30 @@ +id(); + $table->string('name'); + $table->string('phone'); + $table->string('email'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('suppliers'); + } +}; diff --git a/database/migrations/2025_12_06_182358_create_products_table.php b/database/migrations/2025_12_06_182358_create_products_table.php new file mode 100644 index 0000000..ea3aba5 --- /dev/null +++ b/database/migrations/2025_12_06_182358_create_products_table.php @@ -0,0 +1,41 @@ +id(); + $table->string('name'); + $table->string('sku')->unique()->nullable(); // Código de barras o interno + $table->text('description')->nullable(); + + $table->decimal('price', 10, 2); // Precio venta + $table->decimal('cost', 10, 2)->nullable(); // Costo (solo admin) + + $table->integer('stock_quantity')->default(0); + $table->integer('min_stock_alert'); // Alerta + + $table->enum('type', ['bike', 'accessory', 'service']); + $table->string('serial_number')->nullable(); // Solo para bicis + + $table->foreignId('suppliers_id')->constrained()->default(1); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('products'); + } +}; \ No newline at end of file diff --git a/database/migrations/2025_12_06_193913_create_sales_table.php b/database/migrations/2025_12_06_193913_create_sales_table.php new file mode 100644 index 0000000..2125264 --- /dev/null +++ b/database/migrations/2025_12_06_193913_create_sales_table.php @@ -0,0 +1,32 @@ +id(); + //$table->foreignId('user_id')->constrained(); + // nullable para que no sea obligatrio + $table->foreignId('client_id')->nullable()->constrained(); + $table->decimal('total', 10, 2); + $table->string('payment_method'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('sales'); + } +}; diff --git a/database/migrations/2025_12_06_201853_create_sale_details_table.php b/database/migrations/2025_12_06_201853_create_sale_details_table.php new file mode 100644 index 0000000..3e0818a --- /dev/null +++ b/database/migrations/2025_12_06_201853_create_sale_details_table.php @@ -0,0 +1,31 @@ +id(); + $table->foreignId('sale_id')->constrained()->onDelete('cascade'); + $table->foreignId('product_id')->constrained(); + $table->integer('quantity'); + $table->decimal('price', 10, 2); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('sale_details'); + } +}; diff --git a/database/migrations/2026_01_06_210513_add_image_to_products_table.php b/database/migrations/2026_01_06_210513_add_image_to_products_table.php new file mode 100644 index 0000000..addaf25 --- /dev/null +++ b/database/migrations/2026_01_06_210513_add_image_to_products_table.php @@ -0,0 +1,22 @@ +string('image_path')->nullable()->after('type'); + }); + } + + public function down(): void + { + Schema::table('products', function (Blueprint $table) { + $table->dropColumn('image_path'); + }); + } +}; diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index db087de..925158c 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -2,26 +2,80 @@ namespace Database\Seeders; -use App\Models\Product; -use App\Models\User; -// use Illuminate\Database\Console\Seeds\WithoutModelEvents; use Illuminate\Database\Seeder; +use App\Models\User; +use App\Models\Product; +use App\Models\Client; +use App\Models\Supplier; +use App\Models\Appointment; +// use Illuminate\Database\Console\Seeds\WithoutModelEvents; class DatabaseSeeder extends Seeder { - /** - * Seed the application's database. - */ public function run(): void { - User::factory(10)->create(); - + //Crear el Super Admin User::factory()->create([ - 'name' => 'admin', - 'email' => 'admin@laravel.com', - 'password' => 'admin' + 'name' => 'Jose Admin', + 'email' => 'admin@lauck.com', + 'password' => bcrypt('password'), // Cambiar en producción + 'role' => 'admin', ]); + //Crear un Empleado de prueba + User::factory()->create([ + 'name' => 'Empleado Test', + 'email' => 'taller@lauck.com', + 'password' => bcrypt('password'), + 'role' => 'employee', + ]); + + Supplier::create([ + 'name' => 'Cámara 29 Válvula Auto', + 'phone' => '3434567890', + 'email' => 'suplier@suplier.com' + ]); + + //Crear Productos + Product::create([ + 'name' => 'Cámara 29 Válvula Auto', + 'sku' => 'CAM-29-A', + 'price' => 5000, + 'cost' => 2500, + 'stock_quantity' => 20, + 'min_stock_alert' => 5, + 'type' => 'accessory', + 'suppliers_id' => 1 + ]); + + Product::create([ + 'name' => 'Venzo Loki Evo 29', + 'sku' => 'BIC-VEN-001', + 'price' => 450000, + 'cost' => 300000, + 'stock_quantity' => 2, + 'min_stock_alert' => 1, + 'type' => 'bike', + 'serial_number' => 'VZ998877', + 'suppliers_id' => 1 + ]); + + // Generar 10 productos aleatorios más Product::factory(50)->create(); + + // Clientes y Turnos + $client = Client::create([ + 'name' => 'Juan Perez', + 'phone' => '1122334455', + 'email' => 'juan@gmail.com' + ]); + + Appointment::create([ + 'client_id' => $client->id, + 'scheduled_at' => now()->addDays(1)->setHour(10)->setMinute(0), + 'bike_model' => 'Trek Marlin 5', + 'problem_description' => 'Service completo y ajuste de cambios', + 'status' => 'pending' + ]); } } diff --git a/package-lock.json b/package-lock.json index 9b5e238..278d680 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,19 +4,463 @@ "requires": true, "packages": { "": { + "dependencies": { + "@tailwindcss/postcss": "^4.1.18", + "jquery": "^3.7.1", + "select2": "^4.1.0-rc.0" + }, "devDependencies": { - "@tailwindcss/vite": "^4.0.0", + "@tailwindcss/vite": "^4.1.18", + "autoprefixer": "^10.4.22", "axios": "^1.8.2", "concurrently": "^9.0.1", "laravel-vite-plugin": "^2.0.0", - "tailwindcss": "^4.0.0", + "postcss": "^8.5.6", + "tailwindcss": "^4.1.18", "vite": "^7.0.4" } }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", + "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", + "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", + "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", + "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", + "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", + "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", + "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", + "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", + "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", + "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", + "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", + "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", + "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", + "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", + "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", + "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", + "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", + "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", + "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", + "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", + "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", + "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", + "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", + "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", + "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@esbuild/win32-x64": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.9.tgz", - "integrity": "sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", + "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", "cpu": [ "x64" ], @@ -30,24 +474,10 @@ "node": ">=18" } }, - "node_modules/@isaacs/fs-minipass": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", - "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^7.0.4" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.13", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", @@ -58,7 +488,6 @@ "version": "2.3.5", "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", @@ -69,7 +498,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.0.0" @@ -79,24 +507,316 @@ "version": "1.5.5", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.30", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.30.tgz", - "integrity": "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==", - "dev": true, + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.3.tgz", + "integrity": "sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.3.tgz", + "integrity": "sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.3.tgz", + "integrity": "sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.3.tgz", + "integrity": "sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.3.tgz", + "integrity": "sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.3.tgz", + "integrity": "sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.3.tgz", + "integrity": "sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.3.tgz", + "integrity": "sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.3.tgz", + "integrity": "sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.3.tgz", + "integrity": "sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.3.tgz", + "integrity": "sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.3.tgz", + "integrity": "sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.3.tgz", + "integrity": "sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.3.tgz", + "integrity": "sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.3.tgz", + "integrity": "sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.3.tgz", + "integrity": "sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.3.tgz", + "integrity": "sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.3.tgz", + "integrity": "sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.3.tgz", + "integrity": "sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.3.tgz", + "integrity": "sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.3.tgz", + "integrity": "sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.50.0.tgz", - "integrity": "sha512-xMmiWRR8sp72Zqwjgtf3QbZfF1wdh8X2ABu3EaozvZcyHJeU0r+XAnXdKgs4cCAp6ORoYoCygipYP1mjmbjrsg==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.3.tgz", + "integrity": "sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ==", "cpu": [ "x64" ], @@ -108,58 +828,223 @@ ] }, "node_modules/@tailwindcss/node": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.12.tgz", - "integrity": "sha512-3hm9brwvQkZFe++SBt+oLjo4OLDtkvlE8q2WalaD/7QWaeM7KEJbAiY/LJZUaCs7Xa8aUu4xy3uoyX4q54UVdQ==", - "dev": true, + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.18.tgz", + "integrity": "sha512-DoR7U1P7iYhw16qJ49fgXUlry1t4CpXeErJHnQ44JgTSKMaZUdf17cfn5mHchfJ4KRBZRFA/Coo+MUF5+gOaCQ==", "license": "MIT", "dependencies": { "@jridgewell/remapping": "^2.3.4", "enhanced-resolve": "^5.18.3", - "jiti": "^2.5.1", - "lightningcss": "1.30.1", - "magic-string": "^0.30.17", + "jiti": "^2.6.1", + "lightningcss": "1.30.2", + "magic-string": "^0.30.21", "source-map-js": "^1.2.1", - "tailwindcss": "4.1.12" + "tailwindcss": "4.1.18" } }, "node_modules/@tailwindcss/oxide": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.12.tgz", - "integrity": "sha512-gM5EoKHW/ukmlEtphNwaGx45fGoEmP10v51t9unv55voWh6WrOL19hfuIdo2FjxIaZzw776/BUQg7Pck++cIVw==", - "dev": true, - "hasInstallScript": true, + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.18.tgz", + "integrity": "sha512-EgCR5tTS5bUSKQgzeMClT6iCY3ToqE1y+ZB0AKldj809QXk1Y+3jB0upOYZrn9aGIzPtUsP7sX4QQ4XtjBB95A==", "license": "MIT", - "dependencies": { - "detect-libc": "^2.0.4", - "tar": "^7.4.3" - }, "engines": { "node": ">= 10" }, "optionalDependencies": { - "@tailwindcss/oxide-android-arm64": "4.1.12", - "@tailwindcss/oxide-darwin-arm64": "4.1.12", - "@tailwindcss/oxide-darwin-x64": "4.1.12", - "@tailwindcss/oxide-freebsd-x64": "4.1.12", - "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.12", - "@tailwindcss/oxide-linux-arm64-gnu": "4.1.12", - "@tailwindcss/oxide-linux-arm64-musl": "4.1.12", - "@tailwindcss/oxide-linux-x64-gnu": "4.1.12", - "@tailwindcss/oxide-linux-x64-musl": "4.1.12", - "@tailwindcss/oxide-wasm32-wasi": "4.1.12", - "@tailwindcss/oxide-win32-arm64-msvc": "4.1.12", - "@tailwindcss/oxide-win32-x64-msvc": "4.1.12" + "@tailwindcss/oxide-android-arm64": "4.1.18", + "@tailwindcss/oxide-darwin-arm64": "4.1.18", + "@tailwindcss/oxide-darwin-x64": "4.1.18", + "@tailwindcss/oxide-freebsd-x64": "4.1.18", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.18", + "@tailwindcss/oxide-linux-arm64-gnu": "4.1.18", + "@tailwindcss/oxide-linux-arm64-musl": "4.1.18", + "@tailwindcss/oxide-linux-x64-gnu": "4.1.18", + "@tailwindcss/oxide-linux-x64-musl": "4.1.18", + "@tailwindcss/oxide-wasm32-wasi": "4.1.18", + "@tailwindcss/oxide-win32-arm64-msvc": "4.1.18", + "@tailwindcss/oxide-win32-x64-msvc": "4.1.18" } }, - "node_modules/@tailwindcss/oxide-win32-x64-msvc": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.12.tgz", - "integrity": "sha512-NKIh5rzw6CpEodv/++r0hGLlfgT/gFN+5WNdZtvh6wpU2BpGNgdjvj6H2oFc8nCM839QM1YOhjpgbAONUb4IxA==", + "node_modules/@tailwindcss/oxide-android-arm64": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.18.tgz", + "integrity": "sha512-dJHz7+Ugr9U/diKJA0W6N/6/cjI+ZTAoxPf9Iz9BFRF2GzEX8IvXxFIi/dZBloVJX/MZGvRuFA9rqwdiIEZQ0Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-darwin-arm64": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.18.tgz", + "integrity": "sha512-Gc2q4Qhs660bhjyBSKgq6BYvwDz4G+BuyJ5H1xfhmDR3D8HnHCmT/BSkvSL0vQLy/nkMLY20PQ2OoYMO15Jd0A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-darwin-x64": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.18.tgz", + "integrity": "sha512-FL5oxr2xQsFrc3X9o1fjHKBYBMD1QZNyc1Xzw/h5Qu4XnEBi3dZn96HcHm41c/euGV+GRiXFfh2hUCyKi/e+yw==", "cpu": [ "x64" ], - "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-freebsd-x64": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.18.tgz", + "integrity": "sha512-Fj+RHgu5bDodmV1dM9yAxlfJwkkWvLiRjbhuO2LEtwtlYlBgiAT4x/j5wQr1tC3SANAgD+0YcmWVrj8R9trVMA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.18.tgz", + "integrity": "sha512-Fp+Wzk/Ws4dZn+LV2Nqx3IilnhH51YZoRaYHQsVq3RQvEl+71VGKFpkfHrLM/Li+kt5c0DJe/bHXK1eHgDmdiA==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.18.tgz", + "integrity": "sha512-S0n3jboLysNbh55Vrt7pk9wgpyTTPD0fdQeh7wQfMqLPM/Hrxi+dVsLsPrycQjGKEQk85Kgbx+6+QnYNiHalnw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-musl": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.18.tgz", + "integrity": "sha512-1px92582HkPQlaaCkdRcio71p8bc8i/ap5807tPRDK/uw953cauQBT8c5tVGkOwrHMfc2Yh6UuxaH4vtTjGvHg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-gnu": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.18.tgz", + "integrity": "sha512-v3gyT0ivkfBLoZGF9LyHmts0Isc8jHZyVcbzio6Wpzifg/+5ZJpDiRiUhDLkcr7f/r38SWNe7ucxmGW3j3Kb/g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-musl": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.18.tgz", + "integrity": "sha512-bhJ2y2OQNlcRwwgOAGMY0xTFStt4/wyU6pvI6LSuZpRgKQwxTec0/3Scu91O8ir7qCR3AuepQKLU/kX99FouqQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.18.tgz", + "integrity": "sha512-LffYTvPjODiP6PT16oNeUQJzNVyJl1cjIebq/rWWBF+3eDst5JGEFSc5cWxyRCJ0Mxl+KyIkqRxk1XPEs9x8TA==", + "bundleDependencies": [ + "@napi-rs/wasm-runtime", + "@emnapi/core", + "@emnapi/runtime", + "@tybys/wasm-util", + "@emnapi/wasi-threads", + "tslib" + ], + "cpu": [ + "wasm32" + ], + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1", + "@emnapi/wasi-threads": "^1.1.0", + "@napi-rs/wasm-runtime": "^1.1.0", + "@tybys/wasm-util": "^0.10.1", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.18.tgz", + "integrity": "sha512-HjSA7mr9HmC8fu6bdsZvZ+dhjyGCLdotjVOgLA2vEqxEBZaQo9YTX4kwgEvPCpRh8o4uWc4J/wEoFzhEmjvPbA==", + "cpu": [ + "arm64" + ], "license": "MIT", "optional": true, "os": [ @@ -169,16 +1054,45 @@ "node": ">= 10" } }, + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.18.tgz", + "integrity": "sha512-bJWbyYpUlqamC8dpR7pfjA0I7vdF6t5VpUGMWRkXVE3AXgIZjYUYAK7II1GNaxR8J1SSrSrppRar8G++JekE3Q==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/postcss": { + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.1.18.tgz", + "integrity": "sha512-Ce0GFnzAOuPyfV5SxjXGn0CubwGcuDB0zcdaPuCSzAa/2vII24JTkH+I6jcbXLb1ctjZMZZI6OjDaLPJQL1S0g==", + "license": "MIT", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "@tailwindcss/node": "4.1.18", + "@tailwindcss/oxide": "4.1.18", + "postcss": "^8.4.41", + "tailwindcss": "4.1.18" + } + }, "node_modules/@tailwindcss/vite": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.12.tgz", - "integrity": "sha512-4pt0AMFDx7gzIrAOIYgYP0KCBuKWqyW8ayrdiLEjoJTT4pKTjrzG/e4uzWtTLDziC+66R9wbUqZBccJalSE5vQ==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.18.tgz", + "integrity": "sha512-jVA+/UpKL1vRLg6Hkao5jldawNmRo7mQYrZtNHMIVpLfLhDml5nMRUo/8MwoX2vNXvnaXNNMedrMfMugAVX1nA==", "dev": true, "license": "MIT", "dependencies": { - "@tailwindcss/node": "4.1.12", - "@tailwindcss/oxide": "4.1.12", - "tailwindcss": "4.1.12" + "@tailwindcss/node": "4.1.18", + "@tailwindcss/oxide": "4.1.18", + "tailwindcss": "4.1.18" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7" @@ -224,10 +1138,48 @@ "dev": true, "license": "MIT" }, + "node_modules/autoprefixer": { + "version": "10.4.22", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.22.tgz", + "integrity": "sha512-ARe0v/t9gO28Bznv6GgqARmVqcWOV3mfgUPn9becPHMiD3o9BwlRgaeccZnwTpZ7Zwqrm+c1sUSsMxIzQzc8Xg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "browserslist": "^4.27.0", + "caniuse-lite": "^1.0.30001754", + "fraction.js": "^5.3.4", + "normalize-range": "^0.1.2", + "picocolors": "^1.1.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, "node_modules/axios": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.11.0.tgz", - "integrity": "sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz", + "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==", "dev": true, "license": "MIT", "dependencies": { @@ -236,6 +1188,51 @@ "proxy-from-env": "^1.1.0" } }, + "node_modules/baseline-browser-mapping": { + "version": "2.9.6", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.6.tgz", + "integrity": "sha512-v9BVVpOTLB59C9E7aSnmIF8h7qRsFpx+A2nugVMTszEOMcfjlZMsXRm4LF23I3Z9AJxc8ANpIvzbzONoX9VJlg==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, + "node_modules/browserslist": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, "node_modules/call-bind-apply-helpers": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", @@ -250,6 +1247,27 @@ "node": ">= 0.4" } }, + "node_modules/caniuse-lite": { + "version": "1.0.30001760", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001760.tgz", + "integrity": "sha512-7AAMPcueWELt1p3mi13HR/LHH0TJLT11cnwDJEs3xA4+CK/PLKeO9Kl1oru24htkyUKtkGCvAx4ohB0Ttry8Dw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -280,16 +1298,6 @@ "node": ">=8" } }, - "node_modules/chownr": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", - "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=18" - } - }, "node_modules/cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", @@ -374,10 +1382,9 @@ } }, "node_modules/detect-libc": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", - "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", - "dev": true, + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", "license": "Apache-2.0", "engines": { "node": ">=8" @@ -398,6 +1405,13 @@ "node": ">= 0.4" } }, + "node_modules/electron-to-chromium": { + "version": "1.5.267", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz", + "integrity": "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==", + "dev": true, + "license": "ISC" + }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -406,10 +1420,9 @@ "license": "MIT" }, "node_modules/enhanced-resolve": { - "version": "5.18.3", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz", - "integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==", - "dev": true, + "version": "5.18.4", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.4.tgz", + "integrity": "sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q==", "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", @@ -469,9 +1482,9 @@ } }, "node_modules/esbuild": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.9.tgz", - "integrity": "sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==", + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", + "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -482,32 +1495,32 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.9", - "@esbuild/android-arm": "0.25.9", - "@esbuild/android-arm64": "0.25.9", - "@esbuild/android-x64": "0.25.9", - "@esbuild/darwin-arm64": "0.25.9", - "@esbuild/darwin-x64": "0.25.9", - "@esbuild/freebsd-arm64": "0.25.9", - "@esbuild/freebsd-x64": "0.25.9", - "@esbuild/linux-arm": "0.25.9", - "@esbuild/linux-arm64": "0.25.9", - "@esbuild/linux-ia32": "0.25.9", - "@esbuild/linux-loong64": "0.25.9", - "@esbuild/linux-mips64el": "0.25.9", - "@esbuild/linux-ppc64": "0.25.9", - "@esbuild/linux-riscv64": "0.25.9", - "@esbuild/linux-s390x": "0.25.9", - "@esbuild/linux-x64": "0.25.9", - "@esbuild/netbsd-arm64": "0.25.9", - "@esbuild/netbsd-x64": "0.25.9", - "@esbuild/openbsd-arm64": "0.25.9", - "@esbuild/openbsd-x64": "0.25.9", - "@esbuild/openharmony-arm64": "0.25.9", - "@esbuild/sunos-x64": "0.25.9", - "@esbuild/win32-arm64": "0.25.9", - "@esbuild/win32-ia32": "0.25.9", - "@esbuild/win32-x64": "0.25.9" + "@esbuild/aix-ppc64": "0.25.12", + "@esbuild/android-arm": "0.25.12", + "@esbuild/android-arm64": "0.25.12", + "@esbuild/android-x64": "0.25.12", + "@esbuild/darwin-arm64": "0.25.12", + "@esbuild/darwin-x64": "0.25.12", + "@esbuild/freebsd-arm64": "0.25.12", + "@esbuild/freebsd-x64": "0.25.12", + "@esbuild/linux-arm": "0.25.12", + "@esbuild/linux-arm64": "0.25.12", + "@esbuild/linux-ia32": "0.25.12", + "@esbuild/linux-loong64": "0.25.12", + "@esbuild/linux-mips64el": "0.25.12", + "@esbuild/linux-ppc64": "0.25.12", + "@esbuild/linux-riscv64": "0.25.12", + "@esbuild/linux-s390x": "0.25.12", + "@esbuild/linux-x64": "0.25.12", + "@esbuild/netbsd-arm64": "0.25.12", + "@esbuild/netbsd-x64": "0.25.12", + "@esbuild/openbsd-arm64": "0.25.12", + "@esbuild/openbsd-x64": "0.25.12", + "@esbuild/openharmony-arm64": "0.25.12", + "@esbuild/sunos-x64": "0.25.12", + "@esbuild/win32-arm64": "0.25.12", + "@esbuild/win32-ia32": "0.25.12", + "@esbuild/win32-x64": "0.25.12" } }, "node_modules/escalade": { @@ -560,9 +1573,9 @@ } }, "node_modules/form-data": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", - "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", "dev": true, "license": "MIT", "dependencies": { @@ -576,6 +1589,35 @@ "node": ">= 6" } }, + "node_modules/fraction.js": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz", + "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -652,7 +1694,6 @@ "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true, "license": "ISC" }, "node_modules/has-flag": { @@ -718,15 +1759,20 @@ } }, "node_modules/jiti": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.5.1.tgz", - "integrity": "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w==", - "dev": true, + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", + "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", "license": "MIT", "bin": { "jiti": "lib/jiti-cli.mjs" } }, + "node_modules/jquery": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz", + "integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==", + "license": "MIT" + }, "node_modules/laravel-vite-plugin": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/laravel-vite-plugin/-/laravel-vite-plugin-2.0.1.tgz", @@ -748,10 +1794,9 @@ } }, "node_modules/lightningcss": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz", - "integrity": "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==", - "dev": true, + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.2.tgz", + "integrity": "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==", "license": "MPL-2.0", "dependencies": { "detect-libc": "^2.0.3" @@ -764,26 +1809,226 @@ "url": "https://opencollective.com/parcel" }, "optionalDependencies": { - "lightningcss-darwin-arm64": "1.30.1", - "lightningcss-darwin-x64": "1.30.1", - "lightningcss-freebsd-x64": "1.30.1", - "lightningcss-linux-arm-gnueabihf": "1.30.1", - "lightningcss-linux-arm64-gnu": "1.30.1", - "lightningcss-linux-arm64-musl": "1.30.1", - "lightningcss-linux-x64-gnu": "1.30.1", - "lightningcss-linux-x64-musl": "1.30.1", - "lightningcss-win32-arm64-msvc": "1.30.1", - "lightningcss-win32-x64-msvc": "1.30.1" + "lightningcss-android-arm64": "1.30.2", + "lightningcss-darwin-arm64": "1.30.2", + "lightningcss-darwin-x64": "1.30.2", + "lightningcss-freebsd-x64": "1.30.2", + "lightningcss-linux-arm-gnueabihf": "1.30.2", + "lightningcss-linux-arm64-gnu": "1.30.2", + "lightningcss-linux-arm64-musl": "1.30.2", + "lightningcss-linux-x64-gnu": "1.30.2", + "lightningcss-linux-x64-musl": "1.30.2", + "lightningcss-win32-arm64-msvc": "1.30.2", + "lightningcss-win32-x64-msvc": "1.30.2" } }, - "node_modules/lightningcss-win32-x64-msvc": { - "version": "1.30.1", - "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.1.tgz", - "integrity": "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==", + "node_modules/lightningcss-android-arm64": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.30.2.tgz", + "integrity": "sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.2.tgz", + "integrity": "sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.2.tgz", + "integrity": "sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.2.tgz", + "integrity": "sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.2.tgz", + "integrity": "sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==", + "cpu": [ + "arm" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.2.tgz", + "integrity": "sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.2.tgz", + "integrity": "sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.2.tgz", + "integrity": "sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.2.tgz", + "integrity": "sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.2.tgz", + "integrity": "sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.30.2", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.2.tgz", + "integrity": "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==", "cpu": [ "x64" ], - "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -798,10 +2043,9 @@ } }, "node_modules/magic-string": { - "version": "0.30.18", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.18.tgz", - "integrity": "sha512-yi8swmWbO17qHhwIBNeeZxTceJMeBvWJaId6dyvTSOwTipqeHhMhOrz6513r1sOKnpvQ7zkhlG8tPrpilwTxHQ==", - "dev": true, + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" @@ -840,50 +2084,10 @@ "node": ">= 0.6" } }, - "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/minizlib": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz", - "integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==", - "dev": true, - "license": "MIT", - "dependencies": { - "minipass": "^7.1.2" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/mkdirp": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", - "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", - "dev": true, - "license": "MIT", - "bin": { - "mkdirp": "dist/cjs/src/bin.js" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/nanoid": { "version": "3.3.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", - "dev": true, "funding": [ { "type": "github", @@ -898,11 +2102,27 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/node-releases": { + "version": "2.0.27", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", + "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, "license": "ISC" }, "node_modules/picomatch": { @@ -911,6 +2131,7 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -922,7 +2143,6 @@ "version": "8.5.6", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", - "dev": true, "funding": [ { "type": "opencollective", @@ -938,6 +2158,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -947,6 +2168,13 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true, + "license": "MIT" + }, "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", @@ -965,9 +2193,9 @@ } }, "node_modules/rollup": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.50.0.tgz", - "integrity": "sha512-/Zl4D8zPifNmyGzJS+3kVoyXeDeT/GrsJM94sACNg9RtUE0hrHa1bNPtRSrfHTMH5HjRzce6K7rlTh3Khiw+pw==", + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.3.tgz", + "integrity": "sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==", "dev": true, "license": "MIT", "dependencies": { @@ -981,27 +2209,28 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.50.0", - "@rollup/rollup-android-arm64": "4.50.0", - "@rollup/rollup-darwin-arm64": "4.50.0", - "@rollup/rollup-darwin-x64": "4.50.0", - "@rollup/rollup-freebsd-arm64": "4.50.0", - "@rollup/rollup-freebsd-x64": "4.50.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.50.0", - "@rollup/rollup-linux-arm-musleabihf": "4.50.0", - "@rollup/rollup-linux-arm64-gnu": "4.50.0", - "@rollup/rollup-linux-arm64-musl": "4.50.0", - "@rollup/rollup-linux-loongarch64-gnu": "4.50.0", - "@rollup/rollup-linux-ppc64-gnu": "4.50.0", - "@rollup/rollup-linux-riscv64-gnu": "4.50.0", - "@rollup/rollup-linux-riscv64-musl": "4.50.0", - "@rollup/rollup-linux-s390x-gnu": "4.50.0", - "@rollup/rollup-linux-x64-gnu": "4.50.0", - "@rollup/rollup-linux-x64-musl": "4.50.0", - "@rollup/rollup-openharmony-arm64": "4.50.0", - "@rollup/rollup-win32-arm64-msvc": "4.50.0", - "@rollup/rollup-win32-ia32-msvc": "4.50.0", - "@rollup/rollup-win32-x64-msvc": "4.50.0", + "@rollup/rollup-android-arm-eabi": "4.53.3", + "@rollup/rollup-android-arm64": "4.53.3", + "@rollup/rollup-darwin-arm64": "4.53.3", + "@rollup/rollup-darwin-x64": "4.53.3", + "@rollup/rollup-freebsd-arm64": "4.53.3", + "@rollup/rollup-freebsd-x64": "4.53.3", + "@rollup/rollup-linux-arm-gnueabihf": "4.53.3", + "@rollup/rollup-linux-arm-musleabihf": "4.53.3", + "@rollup/rollup-linux-arm64-gnu": "4.53.3", + "@rollup/rollup-linux-arm64-musl": "4.53.3", + "@rollup/rollup-linux-loong64-gnu": "4.53.3", + "@rollup/rollup-linux-ppc64-gnu": "4.53.3", + "@rollup/rollup-linux-riscv64-gnu": "4.53.3", + "@rollup/rollup-linux-riscv64-musl": "4.53.3", + "@rollup/rollup-linux-s390x-gnu": "4.53.3", + "@rollup/rollup-linux-x64-gnu": "4.53.3", + "@rollup/rollup-linux-x64-musl": "4.53.3", + "@rollup/rollup-openharmony-arm64": "4.53.3", + "@rollup/rollup-win32-arm64-msvc": "4.53.3", + "@rollup/rollup-win32-ia32-msvc": "4.53.3", + "@rollup/rollup-win32-x64-gnu": "4.53.3", + "@rollup/rollup-win32-x64-msvc": "4.53.3", "fsevents": "~2.3.2" } }, @@ -1015,6 +2244,12 @@ "tslib": "^2.1.0" } }, + "node_modules/select2": { + "version": "4.1.0-rc.0", + "resolved": "https://registry.npmjs.org/select2/-/select2-4.1.0-rc.0.tgz", + "integrity": "sha512-Hr9TdhyHCZUtwznEH2CBf7967mEM0idtJ5nMtjvk3Up5tPukOLXbHUNmh10oRfeNIhj+3GD3niu+g6sVK+gK0A==", + "license": "MIT" + }, "node_modules/shell-quote": { "version": "1.8.3", "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz", @@ -1032,7 +2267,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -1083,17 +2317,15 @@ } }, "node_modules/tailwindcss": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.12.tgz", - "integrity": "sha512-DzFtxOi+7NsFf7DBtI3BJsynR+0Yp6etH+nRPTbpWnS2pZBaSksv/JGctNwSWzbFjp0vxSqknaUylseZqMDGrA==", - "dev": true, + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.18.tgz", + "integrity": "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==", "license": "MIT" }, "node_modules/tapable": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.3.tgz", - "integrity": "sha512-ZL6DDuAlRlLGghwcfmSn9sK3Hr6ArtyudlSAiCqQ6IfE+b+HHbydbYDIG15IfS5do+7XQQBdBiubF/cV2dnDzg==", - "dev": true, + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", + "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", "license": "MIT", "engines": { "node": ">=6" @@ -1103,33 +2335,15 @@ "url": "https://opencollective.com/webpack" } }, - "node_modules/tar": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", - "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", - "dev": true, - "license": "ISC", - "dependencies": { - "@isaacs/fs-minipass": "^4.0.0", - "chownr": "^3.0.0", - "minipass": "^7.1.2", - "minizlib": "^3.0.1", - "mkdirp": "^3.0.1", - "yallist": "^5.0.0" - }, - "engines": { - "node": ">=18" - } - }, "node_modules/tinyglobby": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", - "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", "dev": true, "license": "MIT", "dependencies": { - "fdir": "^6.4.4", - "picomatch": "^4.0.2" + "fdir": "^6.5.0", + "picomatch": "^4.0.3" }, "engines": { "node": ">=12.0.0" @@ -1152,22 +2366,54 @@ "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true, + "devOptional": true, "license": "0BSD" }, + "node_modules/update-browserslist-db": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.2.tgz", + "integrity": "sha512-E85pfNzMQ9jpKkA7+TJAi4TJN+tBCuWh5rUcS/sv6cFi+1q9LYDwDI5dpUL0u/73EElyQ8d3TEaeW4sPedBqYA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, "node_modules/vite": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.4.tgz", - "integrity": "sha512-X5QFK4SGynAeeIt+A7ZWnApdUyHYm+pzv/8/A57LqSGcI88U6R6ipOs3uCesdc6yl7nl+zNO0t8LmqAdXcQihw==", + "version": "7.2.7", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.2.7.tgz", + "integrity": "sha512-ITcnkFeR3+fI8P1wMgItjGrR10170d8auB4EpMLPqmx6uxElH3a/hHGQabSHKdqd4FXWO1nFIp9rRn7JQ34ACQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", - "tinyglobby": "^0.2.14" + "tinyglobby": "^0.2.15" }, "bin": { "vite": "bin/vite.js" @@ -1282,16 +2528,6 @@ "node": ">=10" } }, - "node_modules/yallist": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", - "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", - "dev": true, - "license": "BlueOak-1.0.0", - "engines": { - "node": ">=18" - } - }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", diff --git a/package.json b/package.json index 34c62c7..259ef1c 100644 --- a/package.json +++ b/package.json @@ -7,11 +7,18 @@ "dev": "vite" }, "devDependencies": { - "@tailwindcss/vite": "^4.0.0", + "@tailwindcss/vite": "^4.1.18", + "autoprefixer": "^10.4.22", "axios": "^1.8.2", "concurrently": "^9.0.1", "laravel-vite-plugin": "^2.0.0", - "tailwindcss": "^4.0.0", + "postcss": "^8.5.6", + "tailwindcss": "^4.1.18", "vite": "^7.0.4" + }, + "dependencies": { + "@tailwindcss/postcss": "^4.1.18", + "jquery": "^3.7.1", + "select2": "^4.1.0-rc.0" } } diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 0000000..34d4d9f --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + '@tailwindcss/postcss': {}, + autoprefixer: {}, + }, +}; \ No newline at end of file diff --git a/public/img/logoLauck.png b/public/img/logoLauck.png new file mode 100644 index 0000000..f0ac15f Binary files /dev/null and b/public/img/logoLauck.png differ diff --git a/public/img/logoLauckGem.png b/public/img/logoLauckGem.png new file mode 100644 index 0000000..bddf046 Binary files /dev/null and b/public/img/logoLauckGem.png differ diff --git a/public/img/logoLauckT.png b/public/img/logoLauckT.png new file mode 100644 index 0000000..50e665b Binary files /dev/null and b/public/img/logoLauckT.png differ diff --git a/resources/css/app.css b/resources/css/app.css index c198cf5..24bd901 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -1,17 +1,52 @@ -@import 'tailwindcss'; +/* 1. Importar fuente Montserrat */ +@import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@400;600;800&display=swap'); +/* 2. Importar Tailwind (v4) */ +@import "tailwindcss"; @source '../../vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php'; @source '../../storage/framework/views/*.php'; @source '../**/*.blade.php'; @source '../**/*.js'; +/* 3. Configuración del Tema (NUEVO EN v4) */ @theme { - --font-sans: 'Instrument Sans', ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', - 'Segoe UI Symbol', 'Noto Color Emoji'; + /* Definimos el color personalizado 'dark-bg' */ + --color-dark-bg: #121212; + /* TRADUCCIÓN: fontFamily: { sans: [...] } */ + --font-sans: 'Montserrat', sans-serif; + + /* TRADUCCIÓN: colors: { ... } + La sintaxis es: --color-nombre-del-color: valor; + */ + --color-neon-lime: #ccff00; + --color-dark-bg: #1a1a1a; + --color-panel-bg: #242424; } -@keyframes gradientMove { - 0%{ background-position: 0% 50%;} - 50%{ background-position: 100% 50%;} - 100%{ background-position: 0% 50%;} +/* 4. Patrón de fondo estilo "Técnico" */ +.bg-grid-pattern { + /* CAMBIO: Usamos rgba(255,255,255, 0.1) para que las líneas sean claras sobre fondo oscuro */ + background-image: linear-gradient(to right, rgba(255, 255, 255, 0.05) 1px, transparent 1px), + linear-gradient(to bottom, rgba(255, 255, 255, 0.05) 1px, transparent 1px); + background-size: 40px 40px; + background-position: center; } + +/* 5. Personalización del Scrollbar */ +::-webkit-scrollbar { + width: 8px; + height: 8px; +} + +::-webkit-scrollbar-track { + background: #1a1a1a; +} + +::-webkit-scrollbar-thumb { + background: #444; + border-radius: 4px; +} + +::-webkit-scrollbar-thumb:hover { + background: #ccff00; /* Verde Neón */ +} \ No newline at end of file diff --git a/resources/js/app.js b/resources/js/app.js index e59d6a0..d0ead51 100644 --- a/resources/js/app.js +++ b/resources/js/app.js @@ -1 +1,13 @@ import './bootstrap'; +// 1. Importar jQuery +import jQuery from 'jquery'; + +// 2. Hacerlo global (IMPORTANTE para que funcione $(document).ready en Blade) +window.$ = window.jQuery = jQuery; + +// 3. Importar Select2 +import select2 from 'select2'; +select2(); // Inicializar el plugin + +// 4. Importar los estilos de Select2 (Opcional aquí, o en CSS) +import 'select2/dist/css/select2.css'; diff --git a/resources/js/bootstrap.js b/resources/js/bootstrap.js index 5f1390b..6c675bf 100644 --- a/resources/js/bootstrap.js +++ b/resources/js/bootstrap.js @@ -2,3 +2,10 @@ import axios from 'axios'; window.axios = axios; window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; + +/** + * Configuración de jQuery global (window.$) + */ +import jQuery from 'jquery'; +window.$ = jQuery; +window.jQuery = jQuery; diff --git a/resources/views/catalogo.blade.php b/resources/views/catalogo.blade.php deleted file mode 100644 index fa26743..0000000 --- a/resources/views/catalogo.blade.php +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/resources/views/catalogo/index.blade.php b/resources/views/catalogo/index.blade.php new file mode 100644 index 0000000..4e22482 --- /dev/null +++ b/resources/views/catalogo/index.blade.php @@ -0,0 +1,54 @@ + + + + + +
+ + @if ($products->count() > 0) +
+ @foreach ($products as $product) +
+ {{-- Imagen si existe --}} + @if (!empty($product->image_path)) + {{ $product->name }} + @else +
+ Sin imagen +
+ @endif + + {{-- Nombre --}} +

{{ $product->name }}

+ + {{-- Descripción corta --}} +
+ @if (!empty($product->description)) +

{{ $product->description }}

+ @endif +
+ + {{-- Precio --}} + @if (!empty($product->price)) +

${{ number_format($product->price, 2, ',', '.') }}

+ @endif + + {{-- Botón --}} + + Ver + + + +
+ @endforeach +
+ @else +

No hay productos disponibles.

+ @endif + +
+ {{ $products->links() }} +
+
+
diff --git a/resources/views/catalogo/show.blade.php b/resources/views/catalogo/show.blade.php new file mode 100644 index 0000000..a7834cb --- /dev/null +++ b/resources/views/catalogo/show.blade.php @@ -0,0 +1,105 @@ + + +
+ + + + + Volver al Catálogo + + +
+
+ + +
+ + @if($product->image_path) + {{ $product->name }} + @else +
+ + Sin Imagen +
+ @endif + + +
+ @if($product->type == 'bike') + Bicicleta + @else + Accesorio + @endif +
+ +
+ + +
+ + +
+

SKU: {{ $product->sku ?? 'N/A' }}

+

{{ $product->name }}

+ + +
+ @if($product->stock_quantity > 5) + + En Stock ({{ $product->stock_quantity }} unid.) + @elseif($product->stock_quantity > 0) + + ¡Últimas Unidades! ({{ $product->stock_quantity }}) + @else + + Agotado + @endif +
+
+ + +
+ Precio Contado +
+ ${{ number_format($product->price, 0, ',', '.') }} + ARG +
+

* Consultar financiación en el local.

+
+ + +
+

Descripción

+

+ {{ $product->description ?? 'Sin descripción detallada disponible para este producto. Por favor, acérquese al local para más información.' }} +

+
+ + +
+ + + + + WhatsApp + +
+ +
+
+
+
+
+ {{-- Editar +
+ @csrf + @method('DELETE') + +
--}} \ No newline at end of file diff --git a/resources/views/clients/create.blade.php b/resources/views/clients/create.blade.php new file mode 100644 index 0000000..34bacb0 --- /dev/null +++ b/resources/views/clients/create.blade.php @@ -0,0 +1,49 @@ + + + + +
+ +
+ @csrf + + + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + + @error('address') + {{ $message }} + @enderror +
+ +
+ +
+ Cancelar + + +
+ +
+
+
\ No newline at end of file diff --git a/resources/views/clients/edit.blade.php b/resources/views/clients/edit.blade.php new file mode 100644 index 0000000..bb10afb --- /dev/null +++ b/resources/views/clients/edit.blade.php @@ -0,0 +1,79 @@ + + + + +
+ +
+ @csrf + @method('PUT')
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + + + @error('address') + {{ $message }} + @enderror +
+ +
+ +
+ + + Cancelar + + + +
+ +
+
+
\ No newline at end of file diff --git a/resources/views/clients/index.blade.php b/resources/views/clients/index.blade.php new file mode 100644 index 0000000..d2853b0 --- /dev/null +++ b/resources/views/clients/index.blade.php @@ -0,0 +1,105 @@ + + + + + @if(session('success')) +
+ {{ session('success') }} +
+ @endif + +
+ +
+
+
+ +
+ +
+
+ + + + Nuevo Cliente + +
+ +
+ + + + + + + + + + + @forelse($clients as $client) + + + + + + + + + + + + @empty + + + + @endforelse + +
Cliente / EmailTeléfono / WhatsAppDirecciónAcciones
+
{{ $client->name }}
+
+ {{ $client->email ?? 'Sin email registrado' }} +
+
+ @if($client->phone) +
+ {{ $client->phone }} + WA +
+ @else + No registrado + @endif +
+ + {{ $client->address ?? '-' }} + + + + Editar + + +
+ @csrf + @method('DELETE') + + +
+
+
+ + + +

No se encontraron clientes.

+
+
+
+ +
+ {{ $clients->links() }} +
+ +
\ No newline at end of file diff --git a/resources/views/components/alert.blade.php b/resources/views/components/alert.blade.php deleted file mode 100644 index f787036..0000000 --- a/resources/views/components/alert.blade.php +++ /dev/null @@ -1,25 +0,0 @@ -@props(['type' => 'dark']) - -@php - switch ($type) { - case 'info': - $class = 'text-blue-800 bg-blue-50 dark:text-blue-400'; - break; - case 'danger': - $class = 'text-red-800 bg-red-50 dark:text-red-400'; - break; - case 'success': - $class = 'text-green-800 bg-green-50 dark:text-green-400'; - break; - case 'warning': - $class = 'text-yellow-800 bg-yellow-50 dark:text-yellow-300'; - break; - default: - $class = 'text-gray-800 bg-gray-50 dark:text-gray-300'; - break; - } -@endphp - -
merge(['class'=>'p-4 my-4 mx-auto text-md max-w-[80%] rounded-lg dark:bg-gray-800 '.$class])}} role="alert"> - {{$title}} {{$content}} -
diff --git a/resources/views/components/alert2.blade.php b/resources/views/components/alert2.blade.php deleted file mode 100644 index 4c0f3a0..0000000 --- a/resources/views/components/alert2.blade.php +++ /dev/null @@ -1,3 +0,0 @@ -
merge(['class'=>'p-4 mb-4 text-sm rounded-lg dark:bg-gray-800 '.$class])}} role="alert"> - {{$title}} {{$slot}} -
\ No newline at end of file diff --git a/resources/views/components/appc.blade.php b/resources/views/components/appc.blade.php index 3591db2..a054ae7 100644 --- a/resources/views/components/appc.blade.php +++ b/resources/views/components/appc.blade.php @@ -1,103 +1,123 @@ @props(['auth' => false]) - - + - {{ $title ?? 'Lauck - Home' }} + + + + + + - - + + {{ $slot }} + + + - - + + + + \ No newline at end of file diff --git a/resources/views/components/footer.blade.php b/resources/views/components/footer.blade.php new file mode 100644 index 0000000..c1105a8 --- /dev/null +++ b/resources/views/components/footer.blade.php @@ -0,0 +1,16 @@ + \ No newline at end of file diff --git a/resources/views/components/forms/input.blade.php b/resources/views/components/forms/input.blade.php new file mode 100644 index 0000000..5f0c99c --- /dev/null +++ b/resources/views/components/forms/input.blade.php @@ -0,0 +1,7 @@ +@props(['disabled' => false, 'error' => null]) + +merge(['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 placeholder-gray-500 transition-colors ' . ($error ? 'border-red-500 focus:border-red-500 focus:ring-red-500' : '')]) !!}> + +@if($error) +

{{ $error }}

+@endif \ No newline at end of file diff --git a/resources/views/components/forms/label.blade.php b/resources/views/components/forms/label.blade.php new file mode 100644 index 0000000..e729c95 --- /dev/null +++ b/resources/views/components/forms/label.blade.php @@ -0,0 +1,5 @@ +@props(['value']) + + diff --git a/resources/views/components/forms/select.blade.php b/resources/views/components/forms/select.blade.php new file mode 100644 index 0000000..697461c --- /dev/null +++ b/resources/views/components/forms/select.blade.php @@ -0,0 +1,39 @@ +@props(['disabled' => false, 'error' => null, 'options' => [], 'placeholder' => 'Seleccionar...']) + + +
+ + + +
+ + + +
+ + + @if($error) +

{{ $error }}

+ @endif +
+ +{{-- + NOTA DE ESTILO: + - `appearance-none`: Quita el estilo feo por defecto del navegador. + - `bg-transparent`: Fondo transparente para que se vea el color de fondo de tu web. + - `border-b-2`: Borde solo abajo (estilo línea). + - `focus:ring-0`: Quita el anillo azul de Chrome al hacer click. + - `peer`: Permite que el icono de la flecha cambie de color cuando el select tiene foco. +--}} \ No newline at end of file diff --git a/resources/views/components/layout.blade.php b/resources/views/components/layout.blade.php new file mode 100644 index 0000000..b6f852c --- /dev/null +++ b/resources/views/components/layout.blade.php @@ -0,0 +1,41 @@ + + + + + + + {{ $title ?? 'Lauck Dashboard' }} + + + @vite(['resources/css/app.css', 'resources/js/app.js']) + + + + + +
+ + + + + +
+ {{ $slot }} +
+ + + + + + + @stack('scripts') + + + \ No newline at end of file diff --git a/resources/views/components/navbar.blade.php b/resources/views/components/navbar.blade.php new file mode 100644 index 0000000..a3a1721 --- /dev/null +++ b/resources/views/components/navbar.blade.php @@ -0,0 +1,94 @@ + \ No newline at end of file diff --git a/resources/views/components/section-header.blade.php b/resources/views/components/section-header.blade.php new file mode 100644 index 0000000..560d266 --- /dev/null +++ b/resources/views/components/section-header.blade.php @@ -0,0 +1,11 @@ +@props(['subtitle', 'title', 'highlight' => null]) + +
+

{{ $subtitle }}

+

+ {{ $title }} + @if($highlight) + {{ $highlight }} + @endif +

+
\ No newline at end of file diff --git a/resources/views/components/ui/alert.blade.php b/resources/views/components/ui/alert.blade.php new file mode 100644 index 0000000..6ec3194 --- /dev/null +++ b/resources/views/components/ui/alert.blade.php @@ -0,0 +1,11 @@ +@if (session('success')) + +@endif + +@if (session('error')) + +@endif \ No newline at end of file diff --git a/resources/views/components/ui/badge.blade.php b/resources/views/components/ui/badge.blade.php new file mode 100644 index 0000000..e455129 --- /dev/null +++ b/resources/views/components/ui/badge.blade.php @@ -0,0 +1,16 @@ +@props(['color' => 'gray']) + +@php +$colors = [ + 'gray' => 'bg-gray-700 text-gray-300', + 'red' => 'bg-red-900/50 text-red-300 border border-red-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', + 'neon' => 'bg-[#ccff00]/10 text-[#ccff00] border border-[#ccff00]/50', +]; +$classes = $colors[$color] ?? $colors['gray']; +@endphp + + + {{ $slot }} + \ No newline at end of file diff --git a/resources/views/components/ui/card.blade.php b/resources/views/components/ui/card.blade.php new file mode 100644 index 0000000..46cde58 --- /dev/null +++ b/resources/views/components/ui/card.blade.php @@ -0,0 +1,15 @@ +@props(['href' => '#', 'title', 'description', 'linkText' => 'Ver detalles']) + + + +
+ {{ $slot }} +
+ +

{{ $title }}

+

{{ $description }}

+ +
+ {{ $linkText }} +
+
\ No newline at end of file diff --git a/resources/views/components/ui/carrousel.blade.php b/resources/views/components/ui/carrousel.blade.php new file mode 100644 index 0000000..63d71b1 --- /dev/null +++ b/resources/views/components/ui/carrousel.blade.php @@ -0,0 +1,141 @@ +@props(['items']) + + + + \ No newline at end of file diff --git a/resources/views/components/ui/imgcard.blade.php b/resources/views/components/ui/imgcard.blade.php new file mode 100644 index 0000000..13054cb --- /dev/null +++ b/resources/views/components/ui/imgcard.blade.php @@ -0,0 +1,31 @@ +@props(['href' => '#', 'title', 'description', 'price', 'image' => null]) + +
+ {{-- Imagen si existe --}} + @if ($image) + {{ $title }} + @else +
+ Sin imagen +
+ @endif + + {{-- Nombre --}} +

{{ $title }}

+ + {{-- Descripción corta --}} +
+ @if (!empty($description)) +

{{ $description }}

+ @endif +
+ + {{-- Precio --}} +

${{ number_format($price, 2, ',', '.') }}

+ + {{-- Botón --}} + + Ver producto + +
\ No newline at end of file diff --git a/resources/views/dashboard.blade.php b/resources/views/dashboard.blade.php index 1b0b21e..ec8aef8 100644 --- a/resources/views/dashboard.blade.php +++ b/resources/views/dashboard.blade.php @@ -1,6 +1,49 @@ + + + + -

BIENVENIDO {{Auth::user()->name}}

-
- @csrf - -
+ +
+ + + + + + + + + + + + + + + + + +
+ 85% + Eficiencia Taller +
+
+
+
+
+ + +
+
+ @csrf + ¿Sesión finalizada? + +
+
+ +
\ No newline at end of file diff --git a/resources/views/layouts/app.blade.php b/resources/views/layouts/app.blade.php deleted file mode 100644 index 67c46ad..0000000 --- a/resources/views/layouts/app.blade.php +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - @yield('title','Lauck - Home') - - - -
Cabeza
- - @yield('main') - -
Pies
- - \ No newline at end of file diff --git a/resources/views/login.blade.php b/resources/views/login.blade.php index d390937..9875eac 100644 --- a/resources/views/login.blade.php +++ b/resources/views/login.blade.php @@ -1,48 +1,45 @@ - - - - - - - Bicicletería Lauck - Inicio de sesión - - - - -
+ +
-

Bicicletería Lauck

- - -
+

Bicicletería Lauck

+ + + +
@csrf -{{-- No muestra los errores, ver --}} - @if ($errors->any()) -
-
    - @foreach ($errors->all() as $error) -
  • {{ $error }}
  • - @endforeach -
-
- @endif + {{-- No muestra los errores, ver --}} + {{-- Bloque de errores de validación y autenticación --}} + @if ($errors->any()) +
+ {{-- Muestra el primer mensaje de error sin lista --}} +

+ {{ $errors->first() }} +

+
+ @endif
- + + class="w-full px-4 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-lime-400 text-gray-600">
- + + class="w-full px-4 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-lime-400 text-gray-600">
+ class="w-full bg-lime-400 font-bold text-white py-2 rounded-md hover:bg-lime-500 transition-colors">

@@ -51,7 +48,4 @@

- - - - + \ No newline at end of file diff --git a/resources/views/productos/create.blade.php b/resources/views/productos/create.blade.php index 7cc48a7..02f9d6b 100644 --- a/resources/views/productos/create.blade.php +++ b/resources/views/productos/create.blade.php @@ -1,61 +1,82 @@ - - Lauck - Agregar - Agregar - Producto + + + - @if ($errors->any()) - - Error: - Todos los campos son obligatorios. - - @endif -
-
+
+ + @csrf -
- - -
-
- - -
-
- - -
-
- - -
-
-
- - + + +
+ + +
+ +
-
- - + + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ +
+ + +
+ + +
+ + +
+ +
+ + +
+ + +
+ + +
+ +
+ + + {{-- @error('image') {{ $message }} @enderror --}}
-
-
- - -
-
- - -
-
-
- - - Volver -
+
- - + \ No newline at end of file diff --git a/resources/views/productos/edit.blade.php b/resources/views/productos/edit.blade.php index 5e7752f..afc80e7 100644 --- a/resources/views/productos/edit.blade.php +++ b/resources/views/productos/edit.blade.php @@ -1,44 +1,44 @@ - +{{-- Lauck - Editar - Editar - {{$producto->nombre}} + Editar - {{$product->nombre}}
-
+ @csrf @method('PUT')
- +
- +
- +
- +
- +
- +
- +
- 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"/> + 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"/>
@@ -46,11 +46,73 @@ - + Volver
- \ No newline at end of file + --}} + + + +
+
+ @csrf + @method('PUT') +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+ + +
+ +
+ + +
+
+ + +
+ +
+ + +
+
+ + +
+ Cancelar + +
+
+
+
\ No newline at end of file diff --git a/resources/views/productos/index.blade.php b/resources/views/productos/index.blade.php index e12544a..bd97bde 100644 --- a/resources/views/productos/index.blade.php +++ b/resources/views/productos/index.blade.php @@ -1,44 +1,97 @@ - - Lauck - Home - Productos - Productos + + + -
- - Agregar Producto + + + + +
+ + +
+
+
+ +
+ +
+ +
+ +
+ +
+ + +
+ + Nuevo Producto -
- - - - - - - - - - - - - - @foreach ($products as $prod) - - - - - - - - - - @endforeach - -
NombreMarcaModeloRodadoColorTipoPrecio
- {{ $prod->nombre }} - {{ $prod->marca }}{{ $prod->modelo }}{{ $prod->rodado }}{{ $prod->color }}{{ $prod->tipo }}{{ $prod->precio }}
-
- - {{$products->links()}}
- - + +
+ + + + + + + + + + + + @forelse($products as $product) + + + + + + + + @empty + + + + @endforelse + +
Producto / SKUTipoPrecioStockAcciones
+
{{ $product->name }}
+
{{ $product->sku }}
+
+ @if($product->type === 'bike') Bicicleta + @elseif($product->type === 'accessory') Accesorio + @else Servicio @endif + + ${{ number_format($product->price, 2) }} + + @if($product->type === 'service') + - + @elseif($product->stock_quantity < $product->min_stock_alert) + {{ $product->stock_quantity }} + @elseif($product->stock_quantity <= $product->min_stock_alert+1) + {{ $product->stock_quantity }} + @else + {{ $product->stock_quantity }} + @endif + + Editar +
+ No se encontraron productos. +
+
+ +
+ {{ $products->links() }} +
+ \ No newline at end of file diff --git a/resources/views/productos/show.blade.php b/resources/views/productos/show.blade.php index 47bfa91..2ed4516 100644 --- a/resources/views/productos/show.blade.php +++ b/resources/views/productos/show.blade.php @@ -1,56 +1,50 @@ - - Lauck - Vista - Producto - Producto - {{$producto->nombre}} + -
-
-
-
Marca
-
{{$producto->marca}}
-
-
-
Modelo
-
{{$producto->modelo}}
-
-
-
Color
-
{{$producto->color}}
-
-
-
Rodado
-
{{$producto->rodado}}
-
-
-
Tipo
-
{{$producto->tipo}}
-
-
-
Descripcion
-
{{$producto->descripcion}}
-
-
-
Precio
-
{{$producto->precio}}
-
-
-
- Volver - Editar -
- @csrf - @method('DELETE') - -
+ + + +
+
+
+
Marca
+
{{$product->name}}
+
+
SKU
+
{{$product->sku}}
+
+
+
Descripcion
+
{{$product->description}}
+
+
+
Costo
+
{{$product->cost}}
+
+
+
Precio
+
{{$product->price}}
+
+
+
Cantidad en Stock
+
{{$product->stock_quantity}}
+
+
+
Tipo
+
{{$product->type}}
+
+
+
+ Volver + Editar +
+ @csrf + @method('DELETE') + +
+
- - - - {{-- componente alerta --}} - {{-- - Jose! - Lorem ipsum dolor sit amet consectetur adipisicing elit. Libero, vel omnis - --}} \ No newline at end of file + \ No newline at end of file diff --git a/resources/views/productos/vistaUsuario.blade.php b/resources/views/productos/vistaUsuario.blade.php new file mode 100644 index 0000000..fbcbba2 --- /dev/null +++ b/resources/views/productos/vistaUsuario.blade.php @@ -0,0 +1,12 @@ + +
+ Volver a catalogo +

Titulo: {{ $producto->nombre }}

+

+ Categoria: {{ $producto->Categoria }} +

+

+ {{ $producto->content }} +

+
+
diff --git a/resources/views/prueba.blade.php b/resources/views/prueba.blade.php new file mode 100644 index 0000000..08a0492 --- /dev/null +++ b/resources/views/prueba.blade.php @@ -0,0 +1,9 @@ + + +
+ Contraseña + +
+ +
\ No newline at end of file diff --git a/resources/views/register.blade.php b/resources/views/register.blade.php index 4cc5c48..6439a7f 100644 --- a/resources/views/register.blade.php +++ b/resources/views/register.blade.php @@ -1,56 +1,59 @@ - - - - - - Bicicletería Lauck - Registro - - - + -
- -

- Bicicletería Lauck -

+
+ +

Bicicletería Lauck

- -
-

Registrarse

-

Por favor completá el formulario para crear una cuenta.

+ +
+

Registrarse

+

Por favor completá el formulario para crear una cuenta.

-
- @csrf -
- - + + @csrf + @if ($errors->any()) +
+
    + @foreach ($errors->all() as $error) +
  • {{ $error }}
  • + @endforeach +
+
+ @endif +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ +
+ +

+ ¿Ya tenés una cuenta? Iniciá sesión acá. +

+
- -
- - -
- -
- - -
- -
- - -
- -
- -
- -

- ¿Ya tenés una cuenta? Iniciá sesión acá. -

-
-
- - + \ No newline at end of file diff --git a/resources/views/sales.blade.php b/resources/views/sales.blade.php new file mode 100644 index 0000000..40a18ab --- /dev/null +++ b/resources/views/sales.blade.php @@ -0,0 +1,91 @@ + + + + + + + +
+ + +
+
+
+ +
+ +
+
+ + + + + +
+
+ + + + + Registrar Venta + +
+ + +
+ + + + + + + + + + + + @forelse($sales as $product) + + + + + + + + @empty + + + + @endforelse + +
ID VentaDescripcionCant. ProductosTotal VentaAcciones
+
{{ $product->sku }}
+
+
{{ $product->name }}
+
+ {{ $product->stock_quantity }} + + ${{ number_format(($product->price * 2), 2) }} + {{-- @if($product->type === 'service') + - + @elseif($product->stock_quantity <= $product->min_stock_alert) + {{ $product->stock_quantity }} + @else + {{ $product->stock_quantity }} + @endif --}} + + Editar +
+ No se encontraron productos. +
+
+ + +
+ {{ $sales->links() }} +
+ +
\ No newline at end of file diff --git a/resources/views/sales/create.blade.php b/resources/views/sales/create.blade.php new file mode 100644 index 0000000..49d437d --- /dev/null +++ b/resources/views/sales/create.blade.php @@ -0,0 +1,281 @@ + + @push('styles') + + @endpush + + + +
+ + + + @if($errors->any()) +
+
    + @foreach($errors->all() as $error) +
  • {{ $error }}
  • + @endforeach +
+
+ @endif + +
+ @csrf + +
+
+ +
+ +
+
+ +
+ +
+
+ +
+ Total Items: 1 +
+
+ +
+ +
+ +
+ + +
+ +
+ + +
+ +
+ Subtotal + $0.00 +
+ +
+ +
+
+
+ +
+ +
+ +
+
+ Monto Total a Pagar + $0.00 +
+
+
+ +
+ +
+ + +
+ +
+ + Cancelar + + +
+
+ +
+
+ + +
diff --git a/resources/views/sales/index.blade.php b/resources/views/sales/index.blade.php new file mode 100644 index 0000000..faee08e --- /dev/null +++ b/resources/views/sales/index.blade.php @@ -0,0 +1,42 @@ + + + + + +
+ +
+ +
+ + + + + Registrar Venta + +
+ + +
+ + + + + + + + + + + + + + +
# RefFechaClienteMétodo PagoTotalAcciones
+
+ + +
+
+ +
\ No newline at end of file diff --git a/resources/views/sales/show.blade.php b/resources/views/sales/show.blade.php new file mode 100644 index 0000000..9271fa9 --- /dev/null +++ b/resources/views/sales/show.blade.php @@ -0,0 +1,149 @@ + + + + + + +
+ + + Volver al Historial + + + +
+ + +
+ + +
+
+ +
+
+ +
+ + CICLES LAUCK + +
+

+ Av. Francisco Ramírez 1389
+ Paraná, Entre Ríos
+ Tel: 343 422-0103 +

+
+ +
+

Comprobante de Venta

+
#{{ str_pad($sale->id, 5, '0', STR_PAD_LEFT) }}
+
+ Fecha: {{ $sale->created_at->format('d/m/Y') }}
+ Hora: {{ $sale->created_at->format('H:i') }} hs +
+
+
+ + +
+
+

Facturado A:

+ @if($sale->client) +

{{ $sale->client->name }}

+

{{ $sale->client->phone }}

+

{{ $sale->client->email }}

+ @if($sale->client->address) +

{{ $sale->client->address }}

+ @endif + @else +

Consumidor Final

+

Venta anónima de mostrador

+ @endif +
+ +
+

Método de Pago:

+ + {{ $sale->payment_method }} + +
+
+ + +
+ + + + + + + + + + + @foreach($sale->details as $detail) + + + + + + + @endforeach + + + + + + + +
ProductoPrecio Unit.Cant.Subtotal
+
{{ $detail->product->name }}
+
{{ $detail->product->sku }}
+
+ ${{ number_format($detail->price, 2, ',', '.') }} + + {{ $detail->quantity }} + + ${{ number_format($detail->price * $detail->quantity, 2, ',', '.') }} +
Total a Pagar + ${{ number_format($sale->total, 2, ',', '.') }} +
+
+ + +
+

¡Gracias por tu compra!

+

Documento no valido como factura.

+
+ +
+ + + + +
\ No newline at end of file diff --git a/resources/views/welcome.blade.php b/resources/views/welcome.blade.php index 5cd7b3b..e8d5dc3 100644 --- a/resources/views/welcome.blade.php +++ b/resources/views/welcome.blade.php @@ -1,5 +1,10 @@ - - Lauck - Inicio - Bienvenido - + + + +
+ + +
+ +
diff --git a/routes/web.php b/routes/web.php index 69a2d2d..5e6ba69 100644 --- a/routes/web.php +++ b/routes/web.php @@ -1,6 +1,9 @@ name('login'); +// Route::get('/catalogo', [CatalogoController::class,'catalogo'])->name('catalogo'); +Route::resource('catalogo', CatalogoController::class)->only(['index', 'show'])->parameters(['catalogo' => 'product']); -Route::post('login', LoginController::class) -->middleware('throttle:5,1') -->name('login.attempt'); - -Route::view('dashboard', 'dashboard') -->middleware('auth') -->name('dashboard'); - -Route::post('logout', function(){ - Auth::guard('web')->logout(); - - Session::invalidate(); - Session::regenerateToken(); - - return redirect('/'); -})->name('logout'); +Route::get('login', function(){ return view('login'); })->name('login'); +Route::post('login', LoginController::class)->middleware('throttle:5,1')->name('login.attempt'); Route::view('register', 'register')->name('register'); Route::post('register', RegisterController::class)->name('register.store'); +Route::post('logout', function(){ + Auth::guard('web')->logout(); + + Session::invalidate(); + Session::regenerateToken(); + + return redirect('/'); +})->name('logout'); + Route::middleware(['auth'])->group(function () { - Route::get('/productos',[ProductosController::class,'index'])->name('productos.index'); - Route::get('/productos/create',[ProductosController::class,'create'])->name('productos.create'); - Route::get('/productos/{id}', [ProductosController::class,'show'])->name('productos.show'); - Route::get('/productos/{id}/edit', [ProductosController::class,'edit'])->name('productos.edit'); - Route::post('/productos',[ProductosController::class,'store'])->name('productos.store'); - Route::put('/productos/{id}',[ProductosController::class,'update'])->name('productos.update'); - Route::delete('/productos/{id}', [ProductosController::class,'destroy'])->name('productos.destroy'); + Route::view('dashboard', 'dashboard')->name('dashboard'); + Route::resource('clients', ClientController::class); + Route::resource('productos', ProductosController::class)->parameters([ + 'productos' => 'product' + ]); + Route::resource('sales', SaleController::class)->only(['index', 'create', 'store', 'show']); + }); -Route::view('catalogo','catalogo')->name('catalogo'); \ No newline at end of file + +Route::get('/productos/{id}/vistaUsuario', [ProductosController::class,'vistaUsuario'])->name('productos.vistaUsuario'); \ No newline at end of file diff --git a/tailwind.config.js b/tailwind.config.js new file mode 100644 index 0000000..20be7ba --- /dev/null +++ b/tailwind.config.js @@ -0,0 +1,22 @@ +/** @type {import('tailwindcss').Config} */ +export default { + content: [ + "./resources/**/*.blade.php", + "./resources/**/*.js", + "./resources/**/*.vue", + ], + theme: { + extend: { + fontFamily: { + sans: ['Montserrat', 'sans-serif'], // Define Montserrat como fuente principal + }, + colors: { + // Tus colores personalizados + 'neon-lime': '#ccff00', + 'dark-bg': '#1a1a1a', + 'panel-bg': '#242424', + } + }, + }, + plugins: [], +} \ No newline at end of file