feat: add desciption to category and sub category
This commit is contained in:
@@ -3,10 +3,14 @@
|
|||||||
namespace App\Http\Controllers;
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
use App\Models\Category;
|
use App\Models\Category;
|
||||||
|
use App\Traits\StoresUploads;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
|
||||||
class CategoryController extends Controller
|
class CategoryController extends Controller
|
||||||
{
|
{
|
||||||
|
use StoresUploads;
|
||||||
|
|
||||||
public function index(Request $request)
|
public function index(Request $request)
|
||||||
{
|
{
|
||||||
$query = Category::query()->withCount('subcategories');
|
$query = Category::query()->withCount('subcategories');
|
||||||
@@ -24,9 +28,17 @@ public function store(Request $request)
|
|||||||
{
|
{
|
||||||
$data = $request->validate([
|
$data = $request->validate([
|
||||||
'name' => 'required|string|max:255|unique:categories,name',
|
'name' => 'required|string|max:255|unique:categories,name',
|
||||||
|
'description' => 'nullable|string',
|
||||||
|
'icon' => 'nullable|image|max:8192',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$category = Category::create($data);
|
$category = Category::create([
|
||||||
|
'name' => $data['name'],
|
||||||
|
'description' => $data['description'] ?? null,
|
||||||
|
'icon' => $request->hasFile('icon')
|
||||||
|
? $this->storeUpload($request->file('icon'), 'categories/icons')
|
||||||
|
: null,
|
||||||
|
]);
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => 'Category created successfully',
|
'message' => 'Category created successfully',
|
||||||
@@ -46,10 +58,25 @@ public function update(Request $request, $id)
|
|||||||
$category = Category::findOrFail($id);
|
$category = Category::findOrFail($id);
|
||||||
|
|
||||||
$data = $request->validate([
|
$data = $request->validate([
|
||||||
'name' => 'required|string|max:255|unique:categories,name,' . $category->id,
|
'name' => 'sometimes|string|max:255|unique:categories,name,' . $category->id,
|
||||||
|
'description' => 'nullable|string',
|
||||||
|
'icon' => 'nullable|image|max:8192',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$category->update($data);
|
if (array_key_exists('name', $data)) {
|
||||||
|
$category->name = $data['name'];
|
||||||
|
}
|
||||||
|
if (array_key_exists('description', $data)) {
|
||||||
|
$category->description = $data['description'];
|
||||||
|
}
|
||||||
|
if ($request->hasFile('icon')) {
|
||||||
|
if ($category->icon) {
|
||||||
|
Storage::disk('public')->delete($category->icon);
|
||||||
|
}
|
||||||
|
$category->icon = $this->storeUpload($request->file('icon'), 'categories/icons');
|
||||||
|
}
|
||||||
|
|
||||||
|
$category->save();
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'message' => 'Category updated successfully',
|
'message' => 'Category updated successfully',
|
||||||
@@ -60,6 +87,11 @@ public function update(Request $request, $id)
|
|||||||
public function destroy($id)
|
public function destroy($id)
|
||||||
{
|
{
|
||||||
$category = Category::findOrFail($id);
|
$category = Category::findOrFail($id);
|
||||||
|
|
||||||
|
if ($category->icon) {
|
||||||
|
Storage::disk('public')->delete($category->icon);
|
||||||
|
}
|
||||||
|
|
||||||
$category->delete();
|
$category->delete();
|
||||||
|
|
||||||
return response()->json(['message' => 'Category deleted successfully']);
|
return response()->json(['message' => 'Category deleted successfully']);
|
||||||
|
|||||||
@@ -299,7 +299,7 @@ public function filters(Request $request)
|
|||||||
$categories = Category::query()
|
$categories = Category::query()
|
||||||
->withCount(['media as media_count' => $visibleMedia])
|
->withCount(['media as media_count' => $visibleMedia])
|
||||||
->orderByDesc('media_count')
|
->orderByDesc('media_count')
|
||||||
->get(['id', 'name']);
|
->get(['id', 'name', 'description', 'icon']);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
@@ -310,7 +310,7 @@ public function filters(Request $request)
|
|||||||
$subcategories = SubCategory::query()
|
$subcategories = SubCategory::query()
|
||||||
->withCount(['media as media_count' => $visibleMedia])
|
->withCount(['media as media_count' => $visibleMedia])
|
||||||
->orderByDesc('media_count')
|
->orderByDesc('media_count')
|
||||||
->get(['id', 'category_id', 'name']);
|
->get(['id', 'category_id', 'name', 'description']);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ public function store(Request $request)
|
|||||||
$data = $request->validate([
|
$data = $request->validate([
|
||||||
'category_id' => 'required|exists:categories,id',
|
'category_id' => 'required|exists:categories,id',
|
||||||
'name' => 'required|string|max:255',
|
'name' => 'required|string|max:255',
|
||||||
|
'description' => 'nullable|string',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$existing = SubCategory::where('category_id', $data['category_id'])
|
$existing = SubCategory::where('category_id', $data['category_id'])
|
||||||
@@ -62,6 +63,7 @@ public function update(Request $request, $id)
|
|||||||
$data = $request->validate([
|
$data = $request->validate([
|
||||||
'category_id' => 'sometimes|exists:categories,id',
|
'category_id' => 'sometimes|exists:categories,id',
|
||||||
'name' => 'sometimes|string|max:255',
|
'name' => 'sometimes|string|max:255',
|
||||||
|
'description' => 'nullable|string',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$categoryId = $data['category_id'] ?? $subCategory->category_id;
|
$categoryId = $data['category_id'] ?? $subCategory->category_id;
|
||||||
|
|||||||
@@ -6,7 +6,14 @@
|
|||||||
|
|
||||||
class Category extends Model
|
class Category extends Model
|
||||||
{
|
{
|
||||||
protected $fillable = ['name'];
|
protected $fillable = ['name', 'description', 'icon'];
|
||||||
|
|
||||||
|
protected $appends = ['icon_url'];
|
||||||
|
|
||||||
|
public function getIconUrlAttribute(): ?string
|
||||||
|
{
|
||||||
|
return $this->icon ? asset('storage/' . $this->icon) : null;
|
||||||
|
}
|
||||||
|
|
||||||
public function questions()
|
public function questions()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ class SubCategory extends Model
|
|||||||
{
|
{
|
||||||
protected $table = 'sub_categories';
|
protected $table = 'sub_categories';
|
||||||
|
|
||||||
protected $fillable = ['category_id', 'name'];
|
protected $fillable = ['category_id', 'name', 'description'];
|
||||||
|
|
||||||
public function category(): BelongsTo
|
public function category(): BelongsTo
|
||||||
{
|
{
|
||||||
|
|||||||
+29
@@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('categories', function (Blueprint $table) {
|
||||||
|
$table->text('description')->nullable()->after('name');
|
||||||
|
$table->string('icon')->nullable()->after('description'); // stored icon image path
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('categories', function (Blueprint $table) {
|
||||||
|
$table->dropColumn(['description', 'icon']);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('sub_categories', function (Blueprint $table) {
|
||||||
|
$table->text('description')->nullable()->after('name');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('sub_categories', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('description');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -222,6 +222,8 @@
|
|||||||
Route::post('/media/{id}/note', [MediaController::class, 'storeNote']);
|
Route::post('/media/{id}/note', [MediaController::class, 'storeNote']);
|
||||||
|
|
||||||
// Media categories
|
// Media categories
|
||||||
|
// Explicit POST update so an icon image can be uploaded (multipart can't ride a PUT).
|
||||||
|
Route::post('categories/{id}', [CategoryController::class, 'update']);
|
||||||
Route::apiResource('categories', CategoryController::class);
|
Route::apiResource('categories', CategoryController::class);
|
||||||
|
|
||||||
// Media sub categories
|
// Media sub categories
|
||||||
|
|||||||
Reference in New Issue
Block a user