diff --git a/app/Http/Controllers/CategoryController.php b/app/Http/Controllers/CategoryController.php index 14eefeb..a1ca6b7 100644 --- a/app/Http/Controllers/CategoryController.php +++ b/app/Http/Controllers/CategoryController.php @@ -33,14 +33,14 @@ public function index(Request $request) $query->with('subcategories'); } - $categories = $query->orderBy('name')->get(); + $categories = $query->orderBy('order')->orderBy('name')->get(); // No type filter → also fold in the playlist (music) categories so the // response contains every category across both tables. if (!$request->filled('type')) { $categories = $categories ->concat($this->playlistCategories($request)) - ->sortBy('name') + ->sortBy([['order', 'asc'], ['name', 'asc']]) ->values(); } @@ -88,6 +88,7 @@ public function store(Request $request) Rule::unique('categories', 'name')->where('type', $request->input('type', Category::TYPE_MEDIA)), ], 'type' => ['nullable', Rule::in(Category::TYPES)], + 'order' => 'nullable|integer', 'description' => 'nullable|string', 'icon' => 'nullable|file|extensions:jpg,jpeg,png,gif,webp,bmp,svg|max:8192', ]); @@ -95,6 +96,7 @@ public function store(Request $request) $category = Category::create([ 'name' => $data['name'], 'type' => $data['type'] ?? Category::TYPE_MEDIA, + 'order' => $data['order'] ?? 0, 'description' => $data['description'] ?? null, 'icon' => $request->hasFile('icon') ? $this->storeUpload($request->file('icon'), 'categories/icons') @@ -158,6 +160,7 @@ public function update(Request $request, $id) ->ignore($category->id), ], 'type' => ['nullable', Rule::in(Category::TYPES)], + 'order' => 'nullable|integer', 'description' => 'nullable|string', 'icon' => 'nullable|file|extensions:jpg,jpeg,png,gif,webp,bmp,svg|max:8192', ]); @@ -165,6 +168,9 @@ public function update(Request $request, $id) if (array_key_exists('type', $data) && $data['type'] !== null) { $category->type = $data['type']; } + if (array_key_exists('order', $data) && $data['order'] !== null) { + $category->order = $data['order']; + } if (array_key_exists('name', $data)) { $category->name = $data['name']; } diff --git a/app/Models/Category.php b/app/Models/Category.php index ed3b547..525ea12 100644 --- a/app/Models/Category.php +++ b/app/Models/Category.php @@ -16,7 +16,11 @@ class Category extends Model self::TYPE_BREATHING_TEMPLATE, ]; - protected $fillable = ['name', 'type', 'description', 'icon']; + protected $fillable = ['name', 'type', 'order', 'description', 'icon']; + + protected $casts = [ + 'order' => 'integer', + ]; protected $appends = ['icon_url']; diff --git a/database/migrations/2026_06_27_100000_add_order_to_categories_table.php b/database/migrations/2026_06_27_100000_add_order_to_categories_table.php new file mode 100644 index 0000000..8b79a0a --- /dev/null +++ b/database/migrations/2026_06_27_100000_add_order_to_categories_table.php @@ -0,0 +1,22 @@ +integer('order')->default(0)->after('type')->index(); + }); + } + + public function down(): void + { + Schema::table('categories', function (Blueprint $table) { + $table->dropColumn('order'); + }); + } +};