1+ <?php
2+
3+ namespace App \Http \Controllers \Api ;
4+
5+ use App \Http \Controllers \Controller ;
6+ use App \Models \Category ;
7+ use Illuminate \Http \Request ;
8+ use Illuminate \Http \JsonResponse ;
9+ use Illuminate \Validation \Rule ;
10+
11+ class CategoryController extends Controller
12+ {
13+ /**
14+ * Display a listing of categories.
15+ */
16+ public function index (Request $ request ): JsonResponse
17+ {
18+ try {
19+ $ query = Category::query ()->with ('children ' );
20+
21+ // Filter by parent category
22+ if ($ request ->has ('parent_id ' )) {
23+ $ query ->where ('parent_id ' , $ request ->parent_id );
24+ }
25+
26+ // Filter by active status
27+ if ($ request ->has ('active ' )) {
28+ $ query ->where ('is_active ' , $ request ->boolean ('active ' ));
29+ }
30+
31+ // Only top-level categories if no parent specified
32+ if (!$ request ->has ('parent_id ' )) {
33+ $ query ->whereNull ('parent_id ' );
34+ }
35+
36+ $ categories = $ query ->orderBy ('sort_order ' )
37+ ->orderBy ('name ' )
38+ ->get ();
39+
40+ return response ()->json ([
41+ 'success ' => true ,
42+ 'data ' => $ categories ,
43+ 'message ' => 'Categories retrieved successfully '
44+ ]);
45+
46+ } catch (\Exception $ e ) {
47+ return response ()->json ([
48+ 'success ' => false ,
49+ 'message ' => 'Failed to retrieve categories ' ,
50+ 'error ' => $ e ->getMessage ()
51+ ], 500 );
52+ }
53+ }
54+
55+ /**
56+ * Store a newly created category.
57+ */
58+ public function store (Request $ request ): JsonResponse
59+ {
60+ try {
61+ $ validated = $ request ->validate ([
62+ 'name ' => 'required|string|max:255 ' ,
63+ 'slug ' => 'required|string|max:255|unique:categories ' ,
64+ 'description ' => 'nullable|string ' ,
65+ 'parent_id ' => 'nullable|exists:categories,id ' ,
66+ 'sort_order ' => 'integer|min:0 ' ,
67+ 'is_active ' => 'boolean ' ,
68+ 'seo_title ' => 'nullable|string|max:255 ' ,
69+ 'seo_description ' => 'nullable|string ' ,
70+ ]);
71+
72+ $ category = Category::create ($ validated );
73+
74+ return response ()->json ([
75+ 'success ' => true ,
76+ 'data ' => $ category ->load ('parent ' ),
77+ 'message ' => 'Category created successfully '
78+ ], 201 );
79+
80+ } catch (\Illuminate \Validation \ValidationException $ e ) {
81+ return response ()->json ([
82+ 'success ' => false ,
83+ 'message ' => 'Validation failed ' ,
84+ 'errors ' => $ e ->errors ()
85+ ], 422 );
86+
87+ } catch (\Exception $ e ) {
88+ return response ()->json ([
89+ 'success ' => false ,
90+ 'message ' => 'Failed to create category ' ,
91+ 'error ' => $ e ->getMessage ()
92+ ], 500 );
93+ }
94+ }
95+
96+ /**
97+ * Display the specified category.
98+ */
99+ public function show (Category $ category ): JsonResponse
100+ {
101+ try {
102+ $ category ->load (['parent ' , 'children ' , 'products ' => function ($ query ) {
103+ $ query ->where ('is_active ' , true )->with ('primaryVariant ' );
104+ }]);
105+
106+ return response ()->json ([
107+ 'success ' => true ,
108+ 'data ' => $ category ,
109+ 'message ' => 'Category retrieved successfully '
110+ ]);
111+
112+ } catch (\Exception $ e ) {
113+ return response ()->json ([
114+ 'success ' => false ,
115+ 'message ' => 'Failed to retrieve category ' ,
116+ 'error ' => $ e ->getMessage ()
117+ ], 500 );
118+ }
119+ }
120+
121+ /**
122+ * Update the specified category.
123+ */
124+ public function update (Request $ request , Category $ category ): JsonResponse
125+ {
126+ try {
127+ $ validated = $ request ->validate ([
128+ 'name ' => 'required|string|max:255 ' ,
129+ 'slug ' => ['required ' , 'string ' , 'max:255 ' , Rule::unique ('categories ' )->ignore ($ category ->id )],
130+ 'description ' => 'nullable|string ' ,
131+ 'parent_id ' => 'nullable|exists:categories,id ' ,
132+ 'sort_order ' => 'integer|min:0 ' ,
133+ 'is_active ' => 'boolean ' ,
134+ 'seo_title ' => 'nullable|string|max:255 ' ,
135+ 'seo_description ' => 'nullable|string ' ,
136+ ]);
137+
138+ $ category ->update ($ validated );
139+
140+ return response ()->json ([
141+ 'success ' => true ,
142+ 'data ' => $ category ->fresh ()->load ('parent ' ),
143+ 'message ' => 'Category updated successfully '
144+ ]);
145+
146+ } catch (\Illuminate \Validation \ValidationException $ e ) {
147+ return response ()->json ([
148+ 'success ' => false ,
149+ 'message ' => 'Validation failed ' ,
150+ 'errors ' => $ e ->errors ()
151+ ], 422 );
152+
153+ } catch (\Exception $ e ) {
154+ return response ()->json ([
155+ 'success ' => false ,
156+ 'message ' => 'Failed to update category ' ,
157+ 'error ' => $ e ->getMessage ()
158+ ], 500 );
159+ }
160+ }
161+
162+ /**
163+ * Remove the specified category.
164+ */
165+ public function destroy (Category $ category ): JsonResponse
166+ {
167+ try {
168+ // Check if category has children
169+ if ($ category ->children ()->count () > 0 ) {
170+ return response ()->json ([
171+ 'success ' => false ,
172+ 'message ' => 'Cannot delete category with child categories '
173+ ], 422 );
174+ }
175+
176+ // Check if category has products
177+ if ($ category ->products ()->count () > 0 ) {
178+ return response ()->json ([
179+ 'success ' => false ,
180+ 'message ' => 'Cannot delete category with associated products '
181+ ], 422 );
182+ }
183+
184+ $ category ->delete ();
185+
186+ return response ()->json ([
187+ 'success ' => true ,
188+ 'message ' => 'Category deleted successfully '
189+ ]);
190+
191+ } catch (\Exception $ e ) {
192+ return response ()->json ([
193+ 'success ' => false ,
194+ 'message ' => 'Failed to delete category ' ,
195+ 'error ' => $ e ->getMessage ()
196+ ], 500 );
197+ }
198+ }
199+
200+ /**
201+ * Get category tree structure.
202+ */
203+ public function tree (): JsonResponse
204+ {
205+ try {
206+ $ categories = Category::whereNull ('parent_id ' )
207+ ->where ('is_active ' , true )
208+ ->with (['children ' => function ($ query ) {
209+ $ query ->where ('is_active ' , true )
210+ ->orderBy ('sort_order ' )
211+ ->orderBy ('name ' );
212+ }])
213+ ->orderBy ('sort_order ' )
214+ ->orderBy ('name ' )
215+ ->get ();
216+
217+ return response ()->json ([
218+ 'success ' => true ,
219+ 'data ' => $ categories ,
220+ 'message ' => 'Category tree retrieved successfully '
221+ ]);
222+
223+ } catch (\Exception $ e ) {
224+ return response ()->json ([
225+ 'success ' => false ,
226+ 'message ' => 'Failed to retrieve category tree ' ,
227+ 'error ' => $ e ->getMessage ()
228+ ], 500 );
229+ }
230+ }
231+ }
0 commit comments