diff --git a/app/Http/Controllers/PromotionController.php b/app/Http/Controllers/PromotionController.php new file mode 100644 index 0000000..9b8f9cb --- /dev/null +++ b/app/Http/Controllers/PromotionController.php @@ -0,0 +1,402 @@ +route('login')->with('error', 'Please log in to view promotions.'); + } + + $page = $request->input('page', 1); + $pageSize = 5; + $search = $request->input('_search', null); + + $response = Http::withHeaders([ + 'Accept' => 'application/json', + 'Authorization' => 'Bearer ' . $accessToken, + ])->get("{$this->apiBaseUrl}/promotion", [ + 'page' => $page, + 'page_size' => $pageSize, + '_search' => $search, + ]); + + if ($response->status() === 401 || $response->status() === 403) { + Log::warning('Unauthorized or Forbidden API response: ', $response->json()); + return redirect()->route('login')->with('error', 'Your session has expired. Please log in again.'); + } + + $json = $response->json(); + + if ($response->successful() && isset($json['data']) && is_array($json['data'])) { + $promotions = array_map(function ($promotion) { + return [ + 'id' => $promotion['promotion_uuid'] ?? null, + 'title' => $promotion['title'] ?? '', + 'type' => $promotion['type'] ?? '', + 'startDate' => $promotion['date_start'] ?? '', + 'endDate' => $promotion['date_end'] ?? '', + 'status' => $promotion['status'] ?? '', + ]; + }, $json['data']); + + $total = $json['meta']['total'] ?? count($promotions); + $lastPage = $json['meta']['last_page'] ?? ceil($total / $pageSize); + } else { + Log::warning('No promotion data found or invalid API response: ', $json); + $promotions = []; + $total = 0; + $lastPage = 1; + } + + return view('pages.promotions', [ + 'promotions' => $promotions, + 'currentPage' => $page, + 'lastPage' => $lastPage, + 'total' => $total, + 'search' => $search, + ]); + } catch (\Exception $e) { + Log::error('Error fetching promotions: ' . $e->getMessage()); + return view('pages.promotions', [ + 'promotions' => [], + 'currentPage' => 1, + 'lastPage' => 1, + 'total' => 0, + 'search' => $search, + ]); + } + } +public function create() +{ + try { + $user = Session::get('user'); + $accessToken = $user['access_token'] ?? null; + + if (!$accessToken) { + return redirect()->route('login')->with('error', 'Please log in to add a promotion.'); + } + + $response = Http::withHeaders([ + 'Accept' => 'application/json', + 'Authorization' => 'Bearer ' . $accessToken, + ])->get("{$this->apiBaseUrl}/promoTypes"); + + $json = $response->json(); + Log::info('Promo types API response: ', $json); + + $promoTypes = $response->successful() && isset($json['data']) ? $json['data'] : []; + + if (empty($promoTypes)) { + Log::warning('Failed to fetch promo types from API, using fallback: ', $json); + $promoTypes = ['1' => 'General', '2' => 'Loyalty Exclusive', '3' => 'User Specific']; + } + + return view('pages.add-promotions', ['promoTypes' => $promoTypes]); + } catch (\Exception $e) { + Log::error('Error fetching promo types: ' . $e->getMessage()); + return view('pages.add-promotions', ['promoTypes' => ['1' => 'General', '2' => 'Loyalty Exclusive', '3' => 'User Specific']]); + } +} +public function store(Request $request) +{ + try { + $user = Session::get('user'); + $accessToken = $user['access_token'] ?? null; + + if (!$accessToken) { + return redirect()->route('login')->with('error', 'Please log in to add a promotion.'); + } + + $request->validate([ + 'title' => 'required|string|max:100', + 'type' => 'required', + 'promo_type' => 'required|in:1,2,3', // Based on the promo types IDs + 'description' => 'required|string', + 'image' => 'required|file|mimes:jpeg,png,jpg,gif|max:2048', // 2MB max + 'start_date' => 'required|date', + 'end_date' => 'required|date|after_or_equal:start_date', + 'status' => 'required|in:On Going,Done', + 'is_toppromotion' => 'nullable|in:1,0', + 'is_gps' => 'nullable|in:1,0', + ]); + + $payload = [ + 'title' => $request->input('title'), + 'type' => $request->input('type'), + 'promo_type' => $request->input('promo_type'), + 'description' => $request->input('description'), + 'date_start' => $request->input('start_date'), + 'date_end' => $request->input('end_date'), + 'status' => $request->input('status'), + 'is_toppromotion' => $request->has('is_toppromotion') ? 1 : 0, + 'is_gps' => $request->has('is_gps') ? 1 : 0, + 'station_uuid' => $request->input('station_uuid', '[]'), + ]; + + // Handle the image upload + if ($request->hasFile('image')) { + $image = $request->file('image'); + $payload['image'] = fopen($image->getPathname(), 'r'); + } + + Log::info('Data being sent to API for creating promotion: ', $payload); + + $response = Http::withHeaders([ + 'Accept' => 'application/json', + 'Authorization' => 'Bearer ' . $accessToken, + ])->attach('image', $payload['image'], $image->getClientOriginalName()) + ->post("{$this->apiBaseUrl}/promotion", array_diff_key($payload, ['image' => null])); + + $json = $response->json(); + Log::info('API response for creating promotion: ', $json); + + if ($response->successful()) { + Log::info('Promotion created successfully: ', $json); + return redirect()->route('promotions')->with('success', $json['message'] ?? 'Promotion added successfully.'); + } else { + $errorMessage = $json['message'] ?? 'Failed to add promotion. Please try again.'; + if (isset($json['errors'])) { + $errorMessage .= ' Errors: ' . json_encode($json['errors']); + } + throw new \Exception($errorMessage); + } + } catch (\Exception $e) { + Log::error('Error creating promotion: ' . $e->getMessage()); + return redirect()->back()->with('error', 'An error occurred while adding the promotion: ' . $e->getMessage()); + } +} + public function show($uuid) + { + try { + $user = Session::get('user'); + $accessToken = $user['access_token'] ?? null; + + if (!$accessToken) { + return redirect()->route('login')->with('error', 'Please log in to view a promotion.'); + } + + $response = Http::withHeaders([ + 'Accept' => 'application/json', + 'Authorization' => 'Bearer ' . $accessToken, + ])->get("{$this->apiBaseUrl}/promotion/{$uuid}"); + + $json = $response->json(); + + if ($response->successful() && isset($json['data'])) { + $promotion = [ + 'id' => $json['data']['promotion_uuid'] ?? null, + 'title' => $json['data']['title'] ?? '', + 'type' => $json['data']['type'] ?? '', + 'startDate' => $json['data']['date_start'] ?? '', + 'endDate' => $json['data']['date_end'] ?? '', + 'status' => $json['data']['status'] ?? '', + ]; + return view('pages.promotion-view', ['promotion' => $promotion]); + } else { + Log::warning('No promotion found or invalid API response: ', $json); + return redirect()->back()->with('error', 'Promotion not found.'); + } + } catch (\Exception $e) { + Log::error('Error fetching promotion for view: ' . $e->getMessage()); + return redirect()->back()->with('error', 'An error occurred while loading the promotion.'); + } + } + + public function edit($uuid) +{ + try { + $user = Session::get('user'); + $accessToken = $user['access_token'] ?? null; + + if (!$accessToken) { + return redirect()->route('login')->with('error', 'Please log in to edit a promotion.'); + } + + $response = Http::withHeaders([ + 'Accept' => 'application/json', + 'Authorization' => 'Bearer ' . $accessToken, + ])->get("{$this->apiBaseUrl}/promotion/{$uuid}"); + + $json = $response->json(); + + if ($response->successful() && isset($json['data'])) { + $promotion = [ + 'id' => $json['data']['promotion_uuid'] ?? null, + 'title' => $json['data']['title'] ?? '', + 'type' => $json['data']['type'] ?? '', + 'description' => $json['data']['description'] ?? '', + 'image' => $json['data']['image'] ?? '', + 'startDate' => $json['data']['date_start'] ?? '', + 'endDate' => $json['data']['date_end'] ?? '', + 'status' => $json['data']['status'] ?? '', + 'is_toppromotion' => $json['data']['is_toppromotion'] ?? 0, + 'is_gps' => $json['data']['is_gps'] ?? 0, + ]; + + // Determine promo_type ID based on type + $typeResponse = Http::withHeaders([ + 'Accept' => 'application/json', + 'Authorization' => 'Bearer ' . $accessToken, + ])->get("{$this->apiBaseUrl}/promoTypes"); + + $promoTypes = $typeResponse->successful() ? $typeResponse->json()['data'] ?? [] : ['1' => 'General', '2' => 'Loyalty Exclusive', '3' => 'User Specific']; + + $promotion['promo_type'] = array_search($promotion['type'], $promoTypes) ?: ''; + + return view('pages.promotion-edit', ['promotion' => $promotion, 'promoTypes' => $promoTypes]); + } else { + Log::warning('No promotion found or invalid API response: ', $json); + return redirect()->back()->with('error', 'Promotion not found.'); + } + } catch (\Exception $e) { + Log::error('Error fetching promotion for edit: ' . $e->getMessage()); + return redirect()->back()->with('error', 'An error occurred while loading the promotion.'); + } +} + public function update(Request $request, $uuid) +{ + try { + $user = Session::get('user'); + $accessToken = $user['access_token'] ?? null; + + if (!$accessToken) { + return redirect()->route('login')->with('error', 'Please log in to update a promotion.'); + } + + $request->validate([ + 'title' => 'required|string|max:100', + 'type' => 'required', + 'promo_type' => 'required|in:1,2,3', + 'description' => 'required|string', + 'image' => 'nullable|file|mimes:jpeg,png,jpg,gif|max:2048', + 'start_date' => 'required|date', + 'end_date' => 'required|date|after_or_equal:start_date', + 'status' => 'required|in:On Going,Done', + 'is_toppromotion' => 'nullable|in:1,0', + 'is_gps' => 'nullable|in:1,0', + ]); + + $payload = [ + 'title' => $request->input('title'), + 'type' => $request->input('type'), + 'promo_type' => $request->input('promo_type'), + 'description' => $request->input('description'), + 'date_start' => $request->input('start_date'), + 'date_end' => $request->input('end_date'), + 'status' => $request->input('status'), + 'is_toppromotion' => $request->has('is_toppromotion') ? 1 : 0, + 'is_gps' => $request->has('is_gps') ? 1 : 0, + 'station_uuid' => $request->input('station_uuid', '[]'), + ]; + + $client = Http::withHeaders([ + 'Accept' => 'application/json', + 'Authorization' => 'Bearer ' . $accessToken, + ]); + + if ($request->hasFile('image')) { + $image = $request->file('image'); + $payload['image'] = fopen($image->getPathname(), 'r'); + $response = $client->attach('image', $payload['image'], $image->getClientOriginalName()) + ->post("{$this->apiBaseUrl}/updatePromotion/{$uuid}", array_diff_key($payload, ['image' => null])); + } else { + $response = $client->post("{$this->apiBaseUrl}/updatePromotion/{$uuid}", $payload); + } + + $json = $response->json(); + Log::info('API response for updating promotion: ', $json); + + if ($response->successful()) { + Log::info('Promotion updated successfully: ', $json); + return redirect()->route('promotions')->with('success', $json['message'] ?? 'Promotion updated successfully.'); + } else { + $errorMessage = $json['message'] ?? 'Failed to update promotion. Please try again.'; + if (isset($json['errors'])) { + $errorMessage .= ' Errors: ' . json_encode($json['errors']); + } + return redirect()->back()->with('error', $errorMessage); + } + } catch (\Exception $e) { + Log::error('Error updating promotion: ' . $e->getMessage()); + return redirect()->back()->with('error', 'An error occurred while updating the promotion: ' . $e->getMessage()); + } +} + public function destroy($uuid) + { + try { + $user = Session::get('user'); + $accessToken = $user['access_token'] ?? null; + + if (!$accessToken) { + return redirect()->route('login')->with('error', 'Please log in to delete a promotion.'); + } + + $response = Http::withHeaders([ + 'Accept' => 'application/json', + 'Authorization' => 'Bearer ' . $accessToken, + ])->delete("{$this->apiBaseUrl}/promotion/{$uuid}"); + + if ($response->successful()) { + Log::info('Promotion deleted successfully: ' . $uuid); + return redirect()->route('promotions')->with('success', 'Promotion deleted successfully.'); + } else { + Log::warning('Failed to delete promotion: ', $response->json()); + return redirect()->back()->with('error', $response->json()['message'] ?? 'Failed to delete promotion. Please try again.'); + } + } catch (\Exception $e) { + Log::error('Error deleting promotion: ' . $e->getMessage()); + return redirect()->back()->with('error', 'An error occurred while deleting the promotion.'); + } + } + + public function batchDelete(Request $request) + { + try { + $user = Session::get('user'); + $accessToken = $user['access_token'] ?? null; + + if (!$accessToken) { + return redirect()->route('login')->with('error', 'Please log in to delete promotions.'); + } + + $uuids = $request->input('promotion_uuid', []); + + if (empty($uuids)) { + return redirect()->back()->with('error', 'No promotions selected for deletion.'); + } + + $response = Http::withHeaders([ + 'Accept' => 'application/json', + 'Authorization' => 'Bearer ' . $accessToken, + ])->delete("{$this->apiBaseUrl}/promotionBatchDelete", [ + 'promotion_uuid' => $uuids, + ]); + + if ($response->successful()) { + Log::info('Promotions batch deleted successfully: ', $uuids); + return redirect()->route('promotions')->with('success', 'Selected promotions deleted successfully.'); + } else { + Log::warning('Failed to batch delete promotions: ', $response->json()); + return redirect()->back()->with('error', $response->json()['message'] ?? 'Failed to delete promotions. Please try again.'); + } + } catch (\Exception $e) { + Log::error('Error batch deleting promotions: ' . $e->getMessage()); + return redirect()->back()->with('error', 'An error occurred while deleting the promotions.'); + } + } +} \ No newline at end of file diff --git a/resources/views/components/promotion-component.blade.php b/resources/views/components/promotion-component.blade.php new file mode 100644 index 0000000..b1f01a3 --- /dev/null +++ b/resources/views/components/promotion-component.blade.php @@ -0,0 +1,391 @@ +@props([ + 'pageTitle' => '', + 'data' => [], + 'columns' => [], + 'actions' => [], + 'showAddButton' => false, + 'addButtonUrl' => '#', + 'showCheckboxes' => false, + 'showBatchDelete' => false, + 'showEditModal' => false, + 'showViewModal' => false, + 'currentPage' => 1, + 'lastPage' => 1, + 'total' => 0, +]) + +
+ + | + @endif + @foreach ($columns as $index => $column) ++ {{ $column['name'] }} + @if ($column['sortable']) + + @endif + | + @endforeach + @if (!empty($actions)) +Action | + @endif +
---|