From 8059a523ddce146f6f96b447556982d288403a69 Mon Sep 17 00:00:00 2001 From: Aji Kamaludin Date: Wed, 28 Jun 2023 09:46:32 +0700 Subject: [PATCH] migrate to postgresql, and check functional --- TODO.md | 2 +- .../Controllers/Admin/GeneralController.php | 4 +- app/Http/Controllers/Admin/SaleController.php | 4 +- .../Controllers/Customer/CartController.php | 21 +-- .../Controllers/Customer/HomeController.php | 35 ++-- .../Customer/PoinExchangeController.php | 21 ++- app/Models/CustomerCart.php | 5 + app/Models/LocationProfile.php | 90 ++++++++++- app/Models/Voucher.php | 28 +--- composer.json | 10 +- composer.lock | 149 +++++++++--------- ..._02_05_153320_create_permissions_table.php | 2 +- docker-compose.yml | 36 ++++- package-lock.json | 98 ++++++------ resources/js/Customer/Cart/VoucherCard.jsx | 32 ++-- .../Index/IndexPartials/AllVoucher.jsx | 18 +-- .../Index/IndexPartials/FavoriteVoucher.jsx | 6 +- .../Customer/Index/Partials/VoucherCard.jsx | 42 +++-- resources/js/Customer/Poin/Exchange.jsx | 149 +++++++++++++----- resources/js/Customer/Poin/VoucherCard.jsx | 2 +- resources/js/Customer/Trx/VoucherCard.jsx | 2 +- resources/js/Layouts/GuestLayout.jsx | 10 +- resources/js/Pages/LocationProfile/Index.jsx | 2 +- resources/js/Pages/Sale/Detail.jsx | 71 +++++---- resources/js/Pages/Voucher/Index.jsx | 2 +- routes/web.php | 2 +- 26 files changed, 520 insertions(+), 323 deletions(-) diff --git a/TODO.md b/TODO.md index 2fc080b..d7d4084 100644 --- a/TODO.md +++ b/TODO.md @@ -3,7 +3,7 @@ ## Note [x] Kerjakan dulu semua yang terkait penjualan normal, deposit normal dan bonus poin transaksi dan downline -[ ] setelah itu baru penukaran voucher +[ ] setelah itu baru penukaran voucher -> sedang ngerjain ini [ ] baru setelah itu yang berhubungan dengan mitrawbb dan hutang ## Front diff --git a/app/Http/Controllers/Admin/GeneralController.php b/app/Http/Controllers/Admin/GeneralController.php index da0f1b3..64684c4 100644 --- a/app/Http/Controllers/Admin/GeneralController.php +++ b/app/Http/Controllers/Admin/GeneralController.php @@ -36,7 +36,7 @@ class GeneralController extends Controller $deposites = DepositHistory::whereDate('created_at', now()->format('Y-m-d')) ->where('is_valid', DepositHistory::STATUS_VALID) ->where('debit', '!=', '0') - ->groupBy('customer_id') + ->groupBy('is_valid', 'customer_id') ->orderBy('total', 'desc') ->with('customer') ->limit(20) @@ -46,7 +46,7 @@ class GeneralController extends Controller $sales = SaleItem::whereDate('sale_items.created_at', now()->format('Y-m-d')) ->join('sales', 'sales.id', '=', 'sale_items.sale_id') ->join('customers', 'customers.id', '=', 'sales.customer_id') - ->groupBy('sales.customer_id') + ->groupBy('sales.customer_id', 'customers.name', 'entity_id') ->orderBy('total', 'desc') ->limit(20) ->selectRaw('sum(sale_items.price) as total, sum(quantity) as count, sales.customer_id, customers.name, entity_id') diff --git a/app/Http/Controllers/Admin/SaleController.php b/app/Http/Controllers/Admin/SaleController.php index 486b456..e1aec70 100644 --- a/app/Http/Controllers/Admin/SaleController.php +++ b/app/Http/Controllers/Admin/SaleController.php @@ -10,7 +10,7 @@ class SaleController extends Controller { public function index(Request $request) { - $query = Sale::with(['items.voucher', 'customer.level']) + $query = Sale::with(['items', 'customer.level']) ->withCount(['items']) ->orderBy('updated_at', 'desc'); @@ -31,7 +31,7 @@ class SaleController extends Controller public function show(Sale $sale) { return inertia('Sale/Detail', [ - 'sale' => $sale->load(['items.voucher.location', 'customer.level']), + 'sale' => $sale->load(['items', 'customer.level']), ]); } } diff --git a/app/Http/Controllers/Customer/CartController.php b/app/Http/Controllers/Customer/CartController.php index 6525787..70efa68 100644 --- a/app/Http/Controllers/Customer/CartController.php +++ b/app/Http/Controllers/Customer/CartController.php @@ -5,6 +5,7 @@ namespace App\Http\Controllers\Customer; use App\Http\Controllers\Controller; use App\Models\Customer; use App\Models\DepositHistory; +use App\Models\LocationProfile; use App\Models\PoinReward; use App\Models\Sale; use App\Models\Setting; @@ -25,9 +26,9 @@ class CartController extends Controller public function index(Request $request) { $customer = $request->user('customer'); - $carts = $customer->carts->load(['voucher.locationProfile.location']); + $carts = $customer->carts->load(['locationProfile.location']); $total = $carts->sum(function ($item) { - return $item->quantity * $item->voucher->validate_price; + return $item->quantity * $item->locationProfile->validate_price; }); $checkAllowProcess = [ @@ -48,12 +49,12 @@ class CartController extends Controller /** * handle cart add, remove or sub */ - public function store(Request $request, Voucher $voucher) + public function store(Request $request, LocationProfile $profile) { $operator = $request->param ?? 'add'; //delete, sub, add $customer = $request->user('customer'); - $item = $customer->carts()->where(['entity_id' => $voucher->id])->first(); + $item = $customer->carts()->where(['entity_id' => $profile->id])->first(); if ($item !== null) { if ($operator == 'delete') { $item->delete(); @@ -74,7 +75,7 @@ class CartController extends Controller } } else { $customer->carts()->create([ - 'entity_id' => $voucher->id, + 'entity_id' => $profile->id, 'quantity' => 1 ]); @@ -102,7 +103,7 @@ class CartController extends Controller ]); $customer = $request->user('customer'); - $carts = $customer->carts->load(['voucher.locationProfile.location']); + $carts = $customer->carts->load(['locationProfile.location']); // validate carts not empty if ($carts->count() == 0) { @@ -112,7 +113,7 @@ class CartController extends Controller // validate voucher is available foreach ($carts as $item) { - $batchCount = $item->voucher->count_unsold(); + $batchCount = $item->locationProfile->count_unsold(); if ($batchCount < $item->quantity) { $customer->carts()->delete(); @@ -123,7 +124,7 @@ class CartController extends Controller // calculate total $total = $carts->sum(function ($item) { - return $item->quantity * $item->voucher->validate_price; + return $item->quantity * $item->locationProfile->validate_price; }); DB::beginTransaction(); @@ -136,7 +137,7 @@ class CartController extends Controller // create sale item by per voucher foreach ($carts as $item) { - $vouchers = $item->voucher->shuffle_unsold($item->quantity); + $vouchers = $item->locationProfile->shuffle_unsold($item->quantity); foreach ($vouchers as $voucher) { $sale->items()->create([ 'entity_type' => $voucher::class, @@ -149,7 +150,7 @@ class CartController extends Controller ]); $voucher->update(['is_sold' => Voucher::SOLD]); - + $voucher->check_stock_notification(); $voucher->create_bonus_poin($customer); diff --git a/app/Http/Controllers/Customer/HomeController.php b/app/Http/Controllers/Customer/HomeController.php index cfef46e..38190b4 100644 --- a/app/Http/Controllers/Customer/HomeController.php +++ b/app/Http/Controllers/Customer/HomeController.php @@ -8,6 +8,7 @@ use App\Models\Customer; use App\Models\CustomerLocationFavorite; use App\Models\Info; use App\Models\Location; +use App\Models\LocationProfile; use App\Models\Notification; use App\Models\Voucher; use Illuminate\Http\Request; @@ -31,30 +32,29 @@ class HomeController extends Controller $slocations = []; - $vouchers = Voucher::with(['locationProfile.location']) - ->where('is_sold', Voucher::UNSOLD) - ->orderBy('updated_at', 'desc') - ->groupBy('location_profile_id'); + $profiles = LocationProfile::with(['location']) + ->whereHas('vouchers', function ($q) { + $q->where('is_sold', Voucher::UNSOLD); + }) + ->orderBy('updated_at', 'desc'); if ($request->location_ids != '') { - $vouchers->whereHas('locationProfile', function ($q) use ($request) { - return $q->whereIn('location_id', $request->location_ids); - }); + $profiles->whereIn('location_id', $request->location_ids); $slocations = Location::whereIn('id', $request->location_ids)->get(); - $vouchers = tap($vouchers->paginate(self::LIMIT))->setHidden(['username', 'password']); + $profiles = $profiles->paginate(self::LIMIT); } if (auth()->guard('customer')->guest() && $request->location_ids == '') { - $vouchers = tap($vouchers->paginate(self::LIMIT))->setHidden(['username', 'password']); + $profiles = $profiles->paginate(self::LIMIT); } return inertia('Index/Index', [ 'infos' => $infos, 'banners' => $banners, 'locations' => $locations, - 'vouchers' => $vouchers, + 'profiles' => $profiles, '_slocations' => $slocations, '_status' => 0 ]); @@ -66,21 +66,20 @@ class HomeController extends Controller $banners = Banner::orderBy('updated_at', 'desc')->get(); $locations = Location::orderBy('name', 'asc')->get(); - $vouchers = Voucher::with(['locationProfile.location']) - ->where('is_sold', Voucher::UNSOLD) - ->orderBy('updated_at', 'desc') - ->groupBy('location_profile_id'); + $profiles = LocationProfile::with(['location']) + ->whereHas('vouchers', function ($q) { + $q->where('is_sold', Voucher::UNSOLD); + }) + ->orderBy('updated_at', 'desc'); $customer = Customer::find(auth()->id()); - $vouchers->whereHas('locationProfile', function ($q) use ($customer) { - return $q->whereIn('location_id', $customer->locationFavorites()->pluck('id')->toArray()); - }); + $profiles->whereIn('location_id', $customer->locationFavorites()->pluck('id')->toArray()); return inertia('Index/Index', [ 'infos' => $infos, 'banners' => $banners, 'locations' => $locations, - 'vouchers' => tap($vouchers->paginate(self::LIMIT))->setHidden(['username', 'password']), + 'profiles' => $profiles->paginate(self::LIMIT), '_flocations' => $customer->locationFavorites, '_status' => 1 ]); diff --git a/app/Http/Controllers/Customer/PoinExchangeController.php b/app/Http/Controllers/Customer/PoinExchangeController.php index eb528ad..79f666f 100644 --- a/app/Http/Controllers/Customer/PoinExchangeController.php +++ b/app/Http/Controllers/Customer/PoinExchangeController.php @@ -14,20 +14,24 @@ class PoinExchangeController extends Controller { public function index(Request $request) { + $favorite = $request->favorite ?? 1; + $customer = $request->user('customer'); + $flocations = $customer->locationFavorites; + $slocations = []; $locations = Location::orderBy('name', 'asc')->get(); $vouchers = Voucher::with(['locationProfile.location']) ->whereHas('locationProfile', function ($q) { - $q->where(['price_poin', '!=', 0]) + $q->where('price_poin', '!=', 0) ->orWhereHas('prices', function ($q) { - return $q->where(['price_poin', '!=', 0]); + return $q->where('price_poin', '!=', 0); }); }) ->where('is_sold', Voucher::UNSOLD) ->groupBy('location_profile_id') ->orderBy('updated_at', 'desc'); - if ($request->location_id != '') { + if ($request->location_ids != '') { $vouchers->whereHas('locationProfile', function ($q) use ($request) { return $q->whereIn('location_id', $request->location_ids); }); @@ -37,15 +41,20 @@ class PoinExchangeController extends Controller $vouchers = tap($vouchers->paginate(20))->setHidden(['username', 'password']); } - if (auth()->guard('customer')->guest() && $request->location_ids == '') { + if ($request->location_ids == '' && $flocations->count() > 0) { + $favorite = 1; + $vouchers->whereHas('locationProfile', function ($q) use ($flocations) { + return $q->whereIn('location_id', $flocations->pluck('id')->toArray()); + }); $vouchers = tap($vouchers->paginate(20))->setHidden(['username', 'password']); } return inertia('Poin/Exchange', [ 'locations' => $locations, 'vouchers' => $vouchers, - '_location_id' => $request->location_id ?? '', '_slocations' => $slocations, + '_flocations' => $flocations, + '_favorite' => $favorite ]); } @@ -54,7 +63,7 @@ class PoinExchangeController extends Controller $batchCount = $voucher->count_unsold(); if ($batchCount < 1) { return redirect()->route('customer.poin.exchange') - ->with('message', ['type' => 'error', 'message'=> 'transaksi gagal, voucher sedang tidak tersedia']); + ->with('message', ['type' => 'error', 'message' => 'transaksi gagal, voucher sedang tidak tersedia']); } $customer = Customer::find(auth()->id()); diff --git a/app/Models/CustomerCart.php b/app/Models/CustomerCart.php index 6a2aff6..5eeae2f 100644 --- a/app/Models/CustomerCart.php +++ b/app/Models/CustomerCart.php @@ -18,4 +18,9 @@ class CustomerCart extends Model { return $this->belongsTo(Voucher::class, 'entity_id'); } + + public function locationProfile() + { + return $this->belongsTo(LocationProfile::class, 'entity_id'); + } } diff --git a/app/Models/LocationProfile.php b/app/Models/LocationProfile.php index 06a8bf3..9648061 100644 --- a/app/Models/LocationProfile.php +++ b/app/Models/LocationProfile.php @@ -38,7 +38,10 @@ class LocationProfile extends Model ]; protected $appends = [ - 'diplay_expired', + 'display_expired', + 'validate_price', + 'validate_display_price', + 'validate_discount', ]; protected static function booted(): void @@ -60,6 +63,19 @@ class LocationProfile extends Model }); } + private static $instance = []; + + private static function getInstance() + { + if (count(self::$instance) == 0) { + self::$instance = [ + 'customer' => Customer::find(auth()->guard('customer')->id()) + ]; + } + + return self::$instance; + } + public function prices() { return $this->hasMany(LocationProfilePrice::class); @@ -75,7 +91,7 @@ class LocationProfile extends Model return $this->hasMany(Voucher::class); } - public function diplayExpired(): Attribute + public function displayExpired(): Attribute { return Attribute::make(get: function () { return $this->expired . ' ' . $this->expired_unit; @@ -93,4 +109,74 @@ class LocationProfile extends Model ]; }); } + + public function validatePrice(): Attribute + { + return Attribute::make(get: function () { + if ($this->prices->count() > 0) { + $price = $this->prices; + if (auth()->guard('customer')->check()) { + $customer = self::getInstance()['customer']; + return $price->where('customer_level_id', $customer->customer_level_id) + ->value('price'); + } + return $price->max('price'); + } + return $this->price; + }); + } + + public function validateDisplayPrice(): Attribute + { + return Attribute::make(get: function () { + if ($this->prices->count() > 0) { + $price = $this->prices; + if (auth()->guard('customer')->check()) { + $customer = self::getInstance()['customer']; + return $price->where('customer_level_id', $customer->customer_level_id) + ->value('display_price'); + } + return $price->max('display_price'); + } + return $this->display_price; + }); + } + + public function validateDiscount(): Attribute + { + return Attribute::make(get: function () { + if ($this->prices->count() > 0) { + $price = $this->prices; + if (auth()->guard('customer')->check()) { + $customer = self::getInstance()['customer']; + return $price->where('customer_level_id', $customer->customer_level_id) + ->value('discount'); + } + return $price->min('discount'); + } + return $this->discount; + }); + } + + public function shuffle_unsold($limit) + { + $vouchers = Voucher::where([ + ['is_sold', '=', Voucher::UNSOLD], + ['location_profile_id', '=', $this->id], + ]) + ->limit($limit) + ->get(); + + return $vouchers; + } + + public function count_unsold() + { + $voucher = Voucher::where([ + ['is_sold', '=', Voucher::UNSOLD], + ['location_profile_id', '=', $this->id], + ])->count(); + + return $voucher; + } } diff --git a/app/Models/Voucher.php b/app/Models/Voucher.php index 6890a48..a74425b 100644 --- a/app/Models/Voucher.php +++ b/app/Models/Voucher.php @@ -149,28 +149,6 @@ class Voucher extends Model }); } - public function shuffle_unsold($limit) - { - $vouchers = Voucher::where([ - ['is_sold', '=', self::UNSOLD], - ['location_profile_id', '=', $this->location_profile_id], - ]) - ->limit($limit) - ->get(); - - return $vouchers; - } - - public function count_unsold() - { - $voucher = Voucher::where([ - ['is_sold', '=', self::UNSOLD], - ['location_profile_id', '=', $this->location_profile_id], - ])->count(); - - return $voucher; - } - public function check_stock_notification() { $count = Voucher::where([ @@ -192,10 +170,12 @@ class Voucher extends Model { $locationCallback = fn ($q) => $q->where('location_id', $location->id); $count_voucher_total = Voucher::whereHas('locationProfile', $locationCallback)->count(); + $sum_voucher_total = Voucher::whereHas('locationProfile', $locationCallback) ->join('location_profiles', 'location_profiles.id', '=', 'vouchers.location_profile_id') - ->selectRaw('(count(vouchers.id) * location_profiles.price) as total') + ->selectRaw('(sum(location_profiles.price)) as total') ->value('total'); + $count_voucher_sold = Voucher::whereHas('locationProfile', $locationCallback) ->where('is_sold', Voucher::SOLD)->count(); $count_voucher_unsold = Voucher::whereHas('locationProfile', $locationCallback) @@ -203,7 +183,7 @@ class Voucher extends Model $sum_voucher_unsold = Voucher::whereHas('locationProfile', $locationCallback) ->where('is_sold', Voucher::UNSOLD) ->join('location_profiles', 'location_profiles.id', '=', 'vouchers.location_profile_id') - ->selectRaw('(count(vouchers.id) * location_profiles.price) as total') + ->selectRaw('(sum(location_profiles.price)) as total') ->value('total'); $sum_voucher_sold = SaleItem::whereHas('voucher', function ($q) use ($locationCallback) { diff --git a/composer.json b/composer.json index eb22356..30e8442 100644 --- a/composer.json +++ b/composer.json @@ -14,17 +14,17 @@ "laravel/socialite": "^5.6.3", "laravel/tinker": "^2.8.1", "midtrans/midtrans-php": "^2.5.2", - "react/async": "^4", + "react/async": "^4.1", "socialiteproviders/google": "^4.1", "tightenco/ziggy": "^1.6.0" }, "require-dev": { "beyondcode/laravel-dump-server": "^1.9", "fakerphp/faker": "^1.23.0", - "laradumps/laradumps": "^1.12", - "laravel/breeze": "^1.21.0", - "laravel/pint": "^1.10.2", - "laravel/sail": "^1.22.0", + "laradumps/laradumps": "^1.12.3", + "laravel/breeze": "^1.21.1", + "laravel/pint": "^1.10.3", + "laravel/sail": "^1.23.0", "mockery/mockery": "^1.6.2", "nunomaduro/collision": "^6.4", "phpunit/phpunit": "^9.6.9", diff --git a/composer.lock b/composer.lock index 4e2891b..cb7c812 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "1dc99b21d1aa2534f1a2a2e6f28ed566", + "content-hash": "9a5a4aa44ec60adc8aa5223f1cdf6e32", "packages": [ { "name": "brick/math", @@ -138,28 +138,28 @@ }, { "name": "doctrine/inflector", - "version": "2.0.6", + "version": "2.0.8", "source": { "type": "git", "url": "https://github.com/doctrine/inflector.git", - "reference": "d9d313a36c872fd6ee06d9a6cbcf713eaa40f024" + "reference": "f9301a5b2fb1216b2b08f02ba04dc45423db6bff" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/inflector/zipball/d9d313a36c872fd6ee06d9a6cbcf713eaa40f024", - "reference": "d9d313a36c872fd6ee06d9a6cbcf713eaa40f024", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/f9301a5b2fb1216b2b08f02ba04dc45423db6bff", + "reference": "f9301a5b2fb1216b2b08f02ba04dc45423db6bff", "shasum": "" }, "require": { "php": "^7.2 || ^8.0" }, "require-dev": { - "doctrine/coding-standard": "^10", + "doctrine/coding-standard": "^11.0", "phpstan/phpstan": "^1.8", "phpstan/phpstan-phpunit": "^1.1", "phpstan/phpstan-strict-rules": "^1.3", "phpunit/phpunit": "^8.5 || ^9.5", - "vimeo/psalm": "^4.25" + "vimeo/psalm": "^4.25 || ^5.4" }, "type": "library", "autoload": { @@ -209,7 +209,7 @@ ], "support": { "issues": "https://github.com/doctrine/inflector/issues", - "source": "https://github.com/doctrine/inflector/tree/2.0.6" + "source": "https://github.com/doctrine/inflector/tree/2.0.8" }, "funding": [ { @@ -225,7 +225,7 @@ "type": "tidelift" } ], - "time": "2022-10-20T09:10:12+00:00" + "time": "2023-06-16T13:40:37+00:00" }, { "name": "doctrine/lexer", @@ -2081,16 +2081,16 @@ }, { "name": "monolog/monolog", - "version": "3.3.1", + "version": "3.4.0", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "9b5daeaffce5b926cac47923798bba91059e60e2" + "reference": "e2392369686d420ca32df3803de28b5d6f76867d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/9b5daeaffce5b926cac47923798bba91059e60e2", - "reference": "9b5daeaffce5b926cac47923798bba91059e60e2", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/e2392369686d420ca32df3803de28b5d6f76867d", + "reference": "e2392369686d420ca32df3803de28b5d6f76867d", "shasum": "" }, "require": { @@ -2105,7 +2105,7 @@ "doctrine/couchdb": "~1.0@dev", "elasticsearch/elasticsearch": "^7 || ^8", "ext-json": "*", - "graylog2/gelf-php": "^1.4.2 || ^2@dev", + "graylog2/gelf-php": "^1.4.2 || ^2.0", "guzzlehttp/guzzle": "^7.4.5", "guzzlehttp/psr7": "^2.2", "mongodb/mongodb": "^1.8", @@ -2113,7 +2113,7 @@ "phpstan/phpstan": "^1.9", "phpstan/phpstan-deprecation-rules": "^1.0", "phpstan/phpstan-strict-rules": "^1.4", - "phpunit/phpunit": "^9.5.26", + "phpunit/phpunit": "^10.1", "predis/predis": "^1.1 || ^2", "ruflin/elastica": "^7", "symfony/mailer": "^5.4 || ^6", @@ -2166,7 +2166,7 @@ ], "support": { "issues": "https://github.com/Seldaek/monolog/issues", - "source": "https://github.com/Seldaek/monolog/tree/3.3.1" + "source": "https://github.com/Seldaek/monolog/tree/3.4.0" }, "funding": [ { @@ -2178,7 +2178,7 @@ "type": "tidelift" } ], - "time": "2023-02-06T13:46:10+00:00" + "time": "2023-06-21T08:46:11+00:00" }, { "name": "nesbot/carbon", @@ -2433,16 +2433,16 @@ }, { "name": "nikic/php-parser", - "version": "v4.15.5", + "version": "v4.16.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "11e2663a5bc9db5d714eedb4277ee300403b4a9e" + "reference": "19526a33fb561ef417e822e85f08a00db4059c17" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/11e2663a5bc9db5d714eedb4277ee300403b4a9e", - "reference": "11e2663a5bc9db5d714eedb4277ee300403b4a9e", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/19526a33fb561ef417e822e85f08a00db4059c17", + "reference": "19526a33fb561ef417e822e85f08a00db4059c17", "shasum": "" }, "require": { @@ -2483,9 +2483,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.15.5" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.16.0" }, - "time": "2023-05-19T20:20:00+00:00" + "time": "2023-06-25T14:52:30+00:00" }, { "name": "nunomaduro/termwind", @@ -3315,16 +3315,16 @@ }, { "name": "react/async", - "version": "v4.0.0", + "version": "v4.1.0", "source": { "type": "git", "url": "https://github.com/reactphp/async.git", - "reference": "2aa8d89057e1059f59666e4204100636249b7be0" + "reference": "b9641ac600b4b144e71a87dcf1be4d41dd3a3548" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/async/zipball/2aa8d89057e1059f59666e4204100636249b7be0", - "reference": "2aa8d89057e1059f59666e4204100636249b7be0", + "url": "https://api.github.com/repos/reactphp/async/zipball/b9641ac600b4b144e71a87dcf1be4d41dd3a3548", + "reference": "b9641ac600b4b144e71a87dcf1be4d41dd3a3548", "shasum": "" }, "require": { @@ -3333,7 +3333,8 @@ "react/promise": "^3.0 || ^2.8 || ^1.2.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpstan/phpstan": "1.10.18", + "phpunit/phpunit": "^9.5" }, "type": "library", "autoload": { @@ -3377,19 +3378,15 @@ ], "support": { "issues": "https://github.com/reactphp/async/issues", - "source": "https://github.com/reactphp/async/tree/v4.0.0" + "source": "https://github.com/reactphp/async/tree/v4.1.0" }, "funding": [ { - "url": "https://github.com/WyriHaximus", - "type": "github" - }, - { - "url": "https://github.com/clue", - "type": "github" + "url": "https://opencollective.com/reactphp", + "type": "open_collective" } ], - "time": "2022-07-11T14:21:02+00:00" + "time": "2023-06-22T14:10:50+00:00" }, { "name": "react/event-loop", @@ -4168,16 +4165,16 @@ }, { "name": "symfony/http-foundation", - "version": "v6.3.0", + "version": "v6.3.1", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "718a97ed430d34e5c568ea2c44eab708c6efbefb" + "reference": "e0ad0d153e1c20069250986cd9e9dd1ccebb0d66" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/718a97ed430d34e5c568ea2c44eab708c6efbefb", - "reference": "718a97ed430d34e5c568ea2c44eab708c6efbefb", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/e0ad0d153e1c20069250986cd9e9dd1ccebb0d66", + "reference": "e0ad0d153e1c20069250986cd9e9dd1ccebb0d66", "shasum": "" }, "require": { @@ -4225,7 +4222,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v6.3.0" + "source": "https://github.com/symfony/http-foundation/tree/v6.3.1" }, "funding": [ { @@ -4241,20 +4238,20 @@ "type": "tidelift" } ], - "time": "2023-05-19T12:46:45+00:00" + "time": "2023-06-24T11:51:27+00:00" }, { "name": "symfony/http-kernel", - "version": "v6.3.0", + "version": "v6.3.1", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "241973f3dd900620b1ca052fe409144f11aea748" + "reference": "161e16fd2e35fb4881a43bc8b383dfd5be4ac374" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/241973f3dd900620b1ca052fe409144f11aea748", - "reference": "241973f3dd900620b1ca052fe409144f11aea748", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/161e16fd2e35fb4881a43bc8b383dfd5be4ac374", + "reference": "161e16fd2e35fb4881a43bc8b383dfd5be4ac374", "shasum": "" }, "require": { @@ -4338,7 +4335,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v6.3.0" + "source": "https://github.com/symfony/http-kernel/tree/v6.3.1" }, "funding": [ { @@ -4354,7 +4351,7 @@ "type": "tidelift" } ], - "time": "2023-05-30T19:03:32+00:00" + "time": "2023-06-26T06:07:32+00:00" }, { "name": "symfony/mailer", @@ -5317,16 +5314,16 @@ }, { "name": "symfony/routing", - "version": "v6.3.0", + "version": "v6.3.1", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "827f59fdc67eecfc4dfff81f9c93bf4d98f0c89b" + "reference": "d37ad1779c38b8eb71996d17dc13030dcb7f9cf5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/827f59fdc67eecfc4dfff81f9c93bf4d98f0c89b", - "reference": "827f59fdc67eecfc4dfff81f9c93bf4d98f0c89b", + "url": "https://api.github.com/repos/symfony/routing/zipball/d37ad1779c38b8eb71996d17dc13030dcb7f9cf5", + "reference": "d37ad1779c38b8eb71996d17dc13030dcb7f9cf5", "shasum": "" }, "require": { @@ -5379,7 +5376,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v6.3.0" + "source": "https://github.com/symfony/routing/tree/v6.3.1" }, "funding": [ { @@ -5395,7 +5392,7 @@ "type": "tidelift" } ], - "time": "2023-04-28T15:57:00+00:00" + "time": "2023-06-05T15:30:22+00:00" }, { "name": "symfony/service-contracts", @@ -5813,16 +5810,16 @@ }, { "name": "symfony/var-dumper", - "version": "v6.3.0", + "version": "v6.3.1", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "6acdcd5c122074ee9f7b051e4fb177025c277a0e" + "reference": "c81268d6960ddb47af17391a27d222bd58cf0515" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/6acdcd5c122074ee9f7b051e4fb177025c277a0e", - "reference": "6acdcd5c122074ee9f7b051e4fb177025c277a0e", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/c81268d6960ddb47af17391a27d222bd58cf0515", + "reference": "c81268d6960ddb47af17391a27d222bd58cf0515", "shasum": "" }, "require": { @@ -5875,7 +5872,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v6.3.0" + "source": "https://github.com/symfony/var-dumper/tree/v6.3.1" }, "funding": [ { @@ -5891,7 +5888,7 @@ "type": "tidelift" } ], - "time": "2023-05-25T13:09:35+00:00" + "time": "2023-06-21T12:08:28+00:00" }, { "name": "tightenco/ziggy", @@ -6627,16 +6624,16 @@ }, { "name": "laravel/breeze", - "version": "v1.21.0", + "version": "v1.21.1", "source": { "type": "git", "url": "https://github.com/laravel/breeze.git", - "reference": "a7e7e2acfb2fd332183aae41c445be7a2329e93e" + "reference": "1cb124f74debc1d5914a7bf2856b793c44ba396d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/breeze/zipball/a7e7e2acfb2fd332183aae41c445be7a2329e93e", - "reference": "a7e7e2acfb2fd332183aae41c445be7a2329e93e", + "url": "https://api.github.com/repos/laravel/breeze/zipball/1cb124f74debc1d5914a7bf2856b793c44ba396d", + "reference": "1cb124f74debc1d5914a7bf2856b793c44ba396d", "shasum": "" }, "require": { @@ -6685,20 +6682,20 @@ "issues": "https://github.com/laravel/breeze/issues", "source": "https://github.com/laravel/breeze" }, - "time": "2023-05-04T15:02:53+00:00" + "time": "2023-06-16T21:23:43+00:00" }, { "name": "laravel/pint", - "version": "v1.10.2", + "version": "v1.10.3", "source": { "type": "git", "url": "https://github.com/laravel/pint.git", - "reference": "f78de1a1bbab7aa41a6ea211c5962b0530d1a301" + "reference": "c472786bca01e4812a9bb7933b23edfc5b6877b7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/pint/zipball/f78de1a1bbab7aa41a6ea211c5962b0530d1a301", - "reference": "f78de1a1bbab7aa41a6ea211c5962b0530d1a301", + "url": "https://api.github.com/repos/laravel/pint/zipball/c472786bca01e4812a9bb7933b23edfc5b6877b7", + "reference": "c472786bca01e4812a9bb7933b23edfc5b6877b7", "shasum": "" }, "require": { @@ -6709,7 +6706,7 @@ "php": "^8.1.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^3.17.0", + "friendsofphp/php-cs-fixer": "^3.18.0", "illuminate/view": "^10.5.1", "laravel-zero/framework": "^10.0.2", "mockery/mockery": "^1.5.1", @@ -6751,20 +6748,20 @@ "issues": "https://github.com/laravel/pint/issues", "source": "https://github.com/laravel/pint" }, - "time": "2023-06-12T10:50:04+00:00" + "time": "2023-06-20T15:55:03+00:00" }, { "name": "laravel/sail", - "version": "v1.22.0", + "version": "v1.23.0", "source": { "type": "git", "url": "https://github.com/laravel/sail.git", - "reference": "923e1e112b6a8598664dbb0ee79dd3137f1c9d56" + "reference": "a2e046f748e87d3ef8b2b381e0e5c5a11f34e46b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/sail/zipball/923e1e112b6a8598664dbb0ee79dd3137f1c9d56", - "reference": "923e1e112b6a8598664dbb0ee79dd3137f1c9d56", + "url": "https://api.github.com/repos/laravel/sail/zipball/a2e046f748e87d3ef8b2b381e0e5c5a11f34e46b", + "reference": "a2e046f748e87d3ef8b2b381e0e5c5a11f34e46b", "shasum": "" }, "require": { @@ -6816,7 +6813,7 @@ "issues": "https://github.com/laravel/sail/issues", "source": "https://github.com/laravel/sail" }, - "time": "2023-05-04T14:52:56+00:00" + "time": "2023-06-16T21:20:12+00:00" }, { "name": "mockery/mockery", diff --git a/database/migrations/2023_02_05_153320_create_permissions_table.php b/database/migrations/2023_02_05_153320_create_permissions_table.php index 45d6e94..840a9d6 100644 --- a/database/migrations/2023_02_05_153320_create_permissions_table.php +++ b/database/migrations/2023_02_05_153320_create_permissions_table.php @@ -14,7 +14,7 @@ return new class extends Migration public function up() { Schema::create('permissions', function (Blueprint $table) { - $table->uuid('id')->primary(); + $table->ulid('id')->primary(); $table->string('label'); $table->string('name'); $table->timestamps(); diff --git a/docker-compose.yml b/docker-compose.yml index cabb433..66c64f7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -50,7 +50,6 @@ services: mariadb: image: mariadb:latest container_name: voucher-mariadb - restart: always ports: - 3306:3306 volumes: @@ -67,6 +66,24 @@ services: networks: voucher: ipv4_address: 10.25.10.99 + postgresql: + image: postgres:14-alpine3.17 + container_name: voucher-postgres + ports: + - 5432:5432 + volumes: + - postgres:/var/lib/postgresql/data + - ./database:/database + environment: + POSTGRES_DB: voucher + POSTGRES_USER: aji + POSTGRES_PASSWORD: eta + mem_limit: 254m + mem_reservation: 128M + cpus: 0.5 + networks: + voucher: + ipv4_address: 10.25.10.199 portainer: image: portainer/portainer-ce:latest ports: @@ -74,7 +91,20 @@ services: volumes: - data:/data - /var/run/docker.sock:/var/run/docker.sock - restart: unless-stopped + networks: + - voucher + phpcli: + image: voucher + container_name: voucher-app-cli + volumes: + - ./:/var/www + working_dir: /var/www + entrypoint: ["php","artisan", "schedule:work"] + mem_limit: 128M + mem_reservation: 128M + cpus: 0.5 + depends_on: + - app networks: - voucher @@ -83,6 +113,8 @@ volumes: driver: local mariadb: driver: local + postgres: + driver: local networks: voucher: diff --git a/package-lock.json b/package-lock.json index 82d52bb..b05c4be 100644 --- a/package-lock.json +++ b/package-lock.json @@ -756,16 +756,16 @@ } }, "node_modules/@floating-ui/core": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.3.0.tgz", - "integrity": "sha512-vX1WVAdPjZg9DkDkC+zEx/tKtnST6/qcNpwcjeBgco3XRNHz5PUA+ivi/yr6G3o0kMR60uKBJcfOdfzOFI7PMQ==" + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.3.1.tgz", + "integrity": "sha512-Bu+AMaXNjrpjh41znzHqaz3r2Nr8hHuHZT6V2LBKMhyMl0FgKA62PNYbqnfgmzOhoWZj70Zecisbo4H1rotP5g==" }, "node_modules/@floating-ui/dom": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.3.0.tgz", - "integrity": "sha512-qIAwejE3r6NeA107u4ELDKkH8+VtgRKdXqtSPaKflL2S2V+doyN+Wt9s5oHKXPDo4E8TaVXaHT3+6BbagH31xw==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.4.2.tgz", + "integrity": "sha512-VKmvHVatWnewmGGy+7Mdy4cTJX71Pli6v/Wjb5RQBuq5wjUYx+Ef+kRThi8qggZqDgD8CogCpqhRoVp3+yQk+g==", "dependencies": { - "@floating-ui/core": "^1.3.0" + "@floating-ui/core": "^1.3.1" } }, "node_modules/@floating-ui/react": { @@ -811,9 +811,9 @@ } }, "node_modules/@inertiajs/core": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@inertiajs/core/-/core-1.0.8.tgz", - "integrity": "sha512-8nr1C76bE9Pfb5OwDGtjtSsiy2g6EG5J7w/w4dWHmoQdY9g01F+VnN3+QYtf/fsFkd8l7A6HoCBgUEZHkwdhXg==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@inertiajs/core/-/core-1.0.9.tgz", + "integrity": "sha512-Vd/4akXnY90qwtPJ1nVGtLXYhyGZdDjvQ4rv5qeqFYmqLEARdhDd7Lku1BwkboZX6GSTgDkipBSSGTKuRemOkQ==", "dev": true, "dependencies": { "axios": "^1.2.0", @@ -823,12 +823,12 @@ } }, "node_modules/@inertiajs/react": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@inertiajs/react/-/react-1.0.8.tgz", - "integrity": "sha512-rbuP8IiRow7lMmAFWP7KzoogXCRphbCEwAmMDMRw18BtpgXMG/CD97Cvszsu3JeVbV0M0dH4fnIfetMO2CRx+A==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@inertiajs/react/-/react-1.0.9.tgz", + "integrity": "sha512-0H9qwReRhc3QCEONX6B+EYUSDKmJG0pJMeswxB2iq+nmeYO2lgnus9DiknZTeN2Y/iLcSnYvNcgGGSqQus1Qfg==", "dev": true, "dependencies": { - "@inertiajs/core": "1.0.8", + "@inertiajs/core": "1.0.9", "lodash.isequal": "^4.5.0" }, "peerDependencies": { @@ -1112,9 +1112,9 @@ } }, "node_modules/browserslist": { - "version": "4.21.8", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.8.tgz", - "integrity": "sha512-j+7xYe+v+q2Id9qbBeCI8WX5NmZSRe8es1+0xntD/+gaWXznP8tFEkv5IgSaHf5dS1YwVMbX/4W6m937mj+wQw==", + "version": "4.21.9", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.9.tgz", + "integrity": "sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg==", "dev": true, "funding": [ { @@ -1131,8 +1131,8 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001502", - "electron-to-chromium": "^1.4.428", + "caniuse-lite": "^1.0.30001503", + "electron-to-chromium": "^1.4.431", "node-releases": "^2.0.12", "update-browserslist-db": "^1.0.11" }, @@ -1164,9 +1164,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001503", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001503.tgz", - "integrity": "sha512-Sf9NiF+wZxPfzv8Z3iS0rXM1Do+iOy2Lxvib38glFX+08TCYYYGR5fRJXk4d77C4AYwhUjgYgMsMudbh2TqCKw==", + "version": "1.0.30001508", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001508.tgz", + "integrity": "sha512-sdQZOJdmt3GJs1UMNpCCCyeuS2IEGLXnHyAo9yIO5JJDjbjoVRij4M1qep6P6gFpptD1PqIYgzM+gwJbOi92mw==", "dev": true, "funding": [ { @@ -1425,9 +1425,9 @@ "integrity": "sha512-GJRqdiy2h+EXy6a8E6R+ubmqUM08BK0FWNq41k24fup6045biQ8NXxoXimiwegMQvFFV3t1emADdGNL1TlS61A==" }, "node_modules/electron-to-chromium": { - "version": "1.4.430", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.430.tgz", - "integrity": "sha512-FytjTbGwz///F+ToZ5XSeXbbSaXalsVRXsz2mHityI5gfxft7ieW3HqFLkU5V1aIrY42aflICqbmFoDxW10etg==", + "version": "1.4.442", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.442.tgz", + "integrity": "sha512-RkrZF//Ya+0aJq2NM3OdisNh5ZodZq1rdXOS96G8DdDgpDKqKE81yTbbQ3F/4CKm1JBPsGu1Lp/akkna2xO06Q==", "dev": true }, "node_modules/error-stack-parser": { @@ -2201,9 +2201,9 @@ } }, "node_modules/pirates": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", - "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", "engines": { "node": ">= 6" } @@ -2402,9 +2402,9 @@ } }, "node_modules/react-datepicker": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-4.13.0.tgz", - "integrity": "sha512-1S8yAqzcHE+LjCjMrTXJfUkTVijTPogxUYrmQmSpmRJ23fdC2w8cg04jzaEAyesTzyUa06JzayZJKk85QHbvcw==", + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-4.14.1.tgz", + "integrity": "sha512-uiPfjD+25KI5WOfCAXlzQgSLyksTagk3wwKn1KGBdF19YtybFDregRmcoNNGveQHAbT10SJZdCvk/8pbc7zxJg==", "dependencies": { "@popperjs/core": "^2.9.2", "classnames": "^2.2.6", @@ -2451,9 +2451,9 @@ } }, "node_modules/react-icons": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.9.0.tgz", - "integrity": "sha512-ijUnFr//ycebOqujtqtV9PFS7JjhWg0QU6ykURVHuL4cbofvRCf3f6GMn9+fBktEFQOIVZnuAYLZdiyadRQRFg==", + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.10.1.tgz", + "integrity": "sha512-/ngzDP/77tlCfqthiiGNZeYFACw85fUjZtLbedmJ5DTlNDIwETxhwBzdOJ21zj4iJdvc0J3y7yOsX3PpxAJzrw==", "peerDependencies": { "react": "*" } @@ -2630,9 +2630,9 @@ } }, "node_modules/rollup": { - "version": "3.25.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.25.1.tgz", - "integrity": "sha512-tywOR+rwIt5m2ZAWSe5AIJcTat8vGlnPFAv15ycCrw33t6iFsXZ6mzHVFh2psSjxQPmI+xgzMZZizUAukBI4aQ==", + "version": "3.25.3", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.25.3.tgz", + "integrity": "sha512-ZT279hx8gszBj9uy5FfhoG4bZx8c+0A1sbqtr7Q3KNWIizpTdDEPZbV2xcbvHsnFp4MavCQYZyzApJ+virB8Yw==", "dev": true, "bin": { "rollup": "dist/bin/rollup" @@ -2787,9 +2787,9 @@ } }, "node_modules/stylis": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", - "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.0.tgz", + "integrity": "sha512-E87pIogpwUsUwXw7dNyU4QDjdgVMy52m+XEOPEKUn161cCzWjjhPSQhByfd1CcNvrOLnXQ6OnnZDwnJrz/Z4YQ==" }, "node_modules/sucrase": { "version": "3.32.0", @@ -2836,9 +2836,9 @@ } }, "node_modules/tabbable": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.1.2.tgz", - "integrity": "sha512-qCN98uP7i9z0fIS4amQ5zbGBOq+OSigYeGvPy7NDk8Y9yncqDZ9pRPgfsc2PJIVM9RrJj7GIfuRgmjoUU9zTHQ==" + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", + "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==" }, "node_modules/tailwindcss": { "version": "3.3.2", @@ -2905,9 +2905,9 @@ } }, "node_modules/tinymce": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/tinymce/-/tinymce-6.5.0.tgz", - "integrity": "sha512-I23hTUhbIyU/HCruy6wpIpOtr8UJhRJjRmJS9DCalN7UxT9iunkkbrcHa0FO9sG4GdMAOmVbZTHFBrgbDPYU6Q==" + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/tinymce/-/tinymce-6.5.1.tgz", + "integrity": "sha512-J67fxJiX3tjvVqer1dg1+cOxMeE2P55ESGhaakvqGPbAUU45HnCMLSioaOsxV1KfcXustw9WJo0rtn1SNQlVKQ==" }, "node_modules/to-fast-properties": { "version": "2.0.0", @@ -2945,9 +2945,9 @@ "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==" }, "node_modules/tslib": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz", - "integrity": "sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==" + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", + "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==" }, "node_modules/update-browserslist-db": { "version": "1.0.11", diff --git a/resources/js/Customer/Cart/VoucherCard.jsx b/resources/js/Customer/Cart/VoucherCard.jsx index d1d9c30..92f8b64 100644 --- a/resources/js/Customer/Cart/VoucherCard.jsx +++ b/resources/js/Customer/Cart/VoucherCard.jsx @@ -2,50 +2,58 @@ import { formatIDR } from '@/utils' import { router } from '@inertiajs/react' import { HiMinusCircle, HiPlusCircle, HiTrash } from 'react-icons/hi2' -export default function VoucherCard({ item: { voucher, quantity } }) { +export default function VoucherCard({ item: { location_profile, quantity } }) { const handleDelete = () => { - router.post(route('cart.store', { voucher: voucher, param: 'delete' })) + router.post( + route('cart.store', { profile: location_profile, param: 'delete' }) + ) } const handleAdd = () => { - router.post(route('cart.store', { voucher: voucher, param: 'add' })) + router.post( + route('cart.store', { profile: location_profile, param: 'add' }) + ) } const handleSub = () => { - router.post(route('cart.store', { voucher: voucher, param: 'sub' })) + router.post( + route('cart.store', { profile: location_profile, param: 'sub' }) + ) } return (
- {voucher.location_profile.location.name} + {location_profile.location.name}
- {voucher.location_profile.display_note} + {location_profile.display_note}
- Rp {formatIDR(voucher.validate_price)} + Rp {formatIDR(location_profile.validate_price)}
- {+voucher.discount !== 0 && ( + {+location_profile.discount !== 0 && (
- {voucher.discount}% + {location_profile.discount}%
- {formatIDR(voucher.validate_display_price)} + {formatIDR( + location_profile.validate_display_price + )}
)}
- {voucher.location_profile.quota} + {location_profile.quota}
- {voucher.location_profile.diplay_expired} + {location_profile.display_expired}
diff --git a/resources/js/Customer/Index/IndexPartials/AllVoucher.jsx b/resources/js/Customer/Index/IndexPartials/AllVoucher.jsx index b932bb8..28db6f9 100644 --- a/resources/js/Customer/Index/IndexPartials/AllVoucher.jsx +++ b/resources/js/Customer/Index/IndexPartials/AllVoucher.jsx @@ -4,7 +4,7 @@ import { HiXMark } from 'react-icons/hi2' import { useModalState } from '@/hooks' import VoucherCard from '../Partials/VoucherCard' -import FormLocation from '../../Components/FormLocation' +import FormLocation from '@/Customer/Components/FormLocation' import LocationModal from '../Partials/LocationModal' const EmptyLocation = () => { @@ -33,7 +33,7 @@ export default function AllVoucher() { const { props: { locations, - vouchers: { data, next_page_url }, + profiles: { data, next_page_url }, _slocations, }, } = usePage() @@ -68,10 +68,10 @@ export default function AllVoucher() { { replace: true, preserveState: true, - only: ['vouchers'], + only: ['profiles'], onSuccess: (res) => { - if (res.props.vouchers.data !== undefined) { - setItems(items.concat(res.props.vouchers.data)) + if (res.props.profiles.data !== undefined) { + setItems(items.concat(res.props.profiles.data)) } }, } @@ -88,8 +88,8 @@ export default function AllVoucher() { replace: true, preserveState: true, onSuccess: (res) => { - if (res.props.vouchers.data !== undefined) { - setItems(res.props.vouchers.data) + if (res.props.profiles.data !== undefined) { + setItems(res.props.profiles.data) return } setItems([]) @@ -124,8 +124,8 @@ export default function AllVoucher() { {/* voucher */}
- {items.map((voucher) => ( - + {items.map((item) => ( + ))} {nextPageUrl !== null && (
{ export default function FavoriteVoucher() { const { props: { - vouchers: { data, next_page_url }, + profiles: { data, next_page_url }, _flocations, }, } = usePage() @@ -92,8 +92,8 @@ export default function FavoriteVoucher() { {/* voucher */}
- {items.map((voucher) => ( - + {items.map((item) => ( + ))} {nextPageUrl !== null && (
{ +const Voucher = ({ item, onClick }) => { return (
-
- {voucher.location_profile.location.name} -
+
{item.location.name}
- {voucher.location_profile.display_note} + {item.display_note}
- Rp {formatIDR(voucher.validate_price)} + Rp {formatIDR(item.validate_price)}
- {+voucher.discount !== 0 && ( + {+item.validate_discount !== 0 && (
- {voucher.discount}% + {item.validate_discount}%
- {formatIDR(voucher.validate_display_price)} + {formatIDR(item.validate_display_price)}
)}
-
- {voucher.location_profile.quota} -
-
- {voucher.location_profile.diplay_expired} -
+
{item.quota}
+
{item.display_expired}
@@ -50,27 +44,27 @@ const Voucher = ({ voucher, onClick }) => { } const ModalChoose = (props) => { - const { state, voucher } = props + const { state, item } = props const onDirectBuy = () => { - router.post(route('cart.store', voucher), { direct: 1 }) + router.post(route('cart.store', item), { direct: 1 }) state.toggle() } const addToCarts = () => { - router.post(route('cart.store', voucher)) + router.post(route('cart.store', item)) state.toggle() } return ( state.toggle()}> - - {voucher.location_profile.display_note !== null && ( + + {item.display_note !== null && (
- {voucher.location_profile.display_note} + {item.display_note}
)}
@@ -91,7 +85,7 @@ const ModalChoose = (props) => { ) } -export default function VoucherCard({ voucher }) { +export default function VoucherCard({ item }) { const chooseModalState = useModalState() const onVoucherChoose = () => { @@ -101,9 +95,9 @@ export default function VoucherCard({ voucher }) { return ( <>
onVoucherChoose()}> - +
- + ) } diff --git a/resources/js/Customer/Poin/Exchange.jsx b/resources/js/Customer/Poin/Exchange.jsx index ccb0d21..6f83a88 100644 --- a/resources/js/Customer/Poin/Exchange.jsx +++ b/resources/js/Customer/Poin/Exchange.jsx @@ -1,8 +1,14 @@ import React, { useState } from 'react' import { Head, router } from '@inertiajs/react' +import { HiXMark, HiOutlineStar } from 'react-icons/hi2' import CustomerLayout from '@/Layouts/CustomerLayout' import VoucherCard from './VoucherCard' +import LocationModal from '../Index/Partials/LocationModal' +import FormLocation from '@/Customer/Components/FormLocation' + +import { ALL, FAVORITE } from '../Index/utils' +import { useModalState } from '@/hooks' const EmptyHere = () => { return ( @@ -19,86 +25,150 @@ export default function Exhange(props) { const { locations, vouchers: { data, next_page_url }, - _location_id, + _favorite, + _slocations, + _flocations, } = props - const [locId, setLocId] = useState(_location_id) - const [v, setV] = useState(data) + const [favorite, setFavorite] = useState(_favorite) + const [vouchers, setVouchers] = useState(data) - const handleSelectLoc = (loc) => { - if (loc.id === locId) { - setLocId('') - fetch('') - return - } - setLocId(loc.id) - fetch(loc.id) - } + const [fLocations] = useState(_flocations) + const [sLocations, setSLocations] = useState(_slocations) + const locationModal = useModalState() const handleNextPage = () => { + let location_ids = sLocations.map((l) => l.id) + router.get( next_page_url, - { - location_id: locId, - }, + { location_ids }, { replace: true, preserveState: true, only: ['vouchers'], onSuccess: (res) => { - setV(v.concat(res.props.vouchers.data)) + setVouchers(vouchers.concat(res.props.vouchers.data)) }, } ) } - const fetch = (locId) => { + const fetch = (locations) => { + let location_ids = locations.map((l) => l.id) + router.get( route(route().current()), - { location_id: locId }, + { location_ids }, { replace: true, preserveState: true, onSuccess: (res) => { - setV(res.props.vouchers.data) + setVouchers(res.props.vouchers.data) }, } ) } + const handleAddLocation = (location) => { + const isExists = sLocations.find((l) => l.id === location.id) + if (!isExists) { + const locations = [location].concat(...sLocations) + setSLocations(locations) + fetch(locations) + } + } + + const handleRemoveLocation = (index) => { + const locations = sLocations.filter((_, i) => i !== index) + setSLocations(locations) + fetch(locations) + } + + const isStatus = (s) => { + if (s === favorite) { + return 'px-2 py-1 rounded-2xl hover:bg-blue-800 text-white bg-blue-600 border border-blue-800' + } + return 'px-2 py-1 rounded-2xl hover:bg-blue-800 hover:text-white bg-blue-100 border border-blue-200' + } + + const handleFavorite = () => { + setFavorite(FAVORITE) + fetch(fLocations) + } + + const handleAll = () => { + setFavorite(ALL) + fetch(sLocations) + } + return (
-
Tukar poin
+
Tukar Poin
tukarkan poin anda dengan voucher manarik
- - {v.length <= 0 ? ( - - ) : ( -
- {/* chips */} -
- {locations.map((location) => ( +
+
+
+
+ Semua +
+
+ Favorit +
+
+
+
+ +
+ {favorite === ALL ? ( +
+ {sLocations.map((location, index) => (
handleSelectLoc(location)} + className="flex flex-row items-center gap-1 px-2 py-1 rounded-2xl bg-blue-100 border border-blue-200 hover:bg-blue-500" key={location.id} - className={`px-2 py-1 rounded-2xl ${ - location.id === locId - ? 'text-white bg-blue-600 border border-blue-800' - : 'bg-blue-100 border border-blue-200' - }`} + onClick={() => handleRemoveLocation(index)} > - {location.name} +
{location.name}
+
+ +
))}
- + ) : ( +
+ {fLocations.map((location, index) => ( +
handleRemoveLocation(index)} + > +
{location.name}
+
+ +
+
+ ))} +
+ )} +
+ {vouchers.length <= 0 ? ( + + ) : ( +
{/* voucher */}
- {v.map((voucher) => ( + {vouchers.map((voucher) => ( )}
+ ) } diff --git a/resources/js/Customer/Poin/VoucherCard.jsx b/resources/js/Customer/Poin/VoucherCard.jsx index 3e1ad2d..bcf51f3 100644 --- a/resources/js/Customer/Poin/VoucherCard.jsx +++ b/resources/js/Customer/Poin/VoucherCard.jsx @@ -81,7 +81,7 @@ export default function VoucherCard({ voucher }) { {voucher.location_profile.quota}
- {voucher.location_profile.diplay_expired} + {voucher.location_profile.display_expired}
diff --git a/resources/js/Customer/Trx/VoucherCard.jsx b/resources/js/Customer/Trx/VoucherCard.jsx index 62c5503..66f3ff7 100644 --- a/resources/js/Customer/Trx/VoucherCard.jsx +++ b/resources/js/Customer/Trx/VoucherCard.jsx @@ -62,7 +62,7 @@ export default function VoucherCard(props) { {voucher.location_profile.quota}
- {voucher.location_profile.diplay_expired} + {voucher.location_profile.display_expired}
diff --git a/resources/js/Layouts/GuestLayout.jsx b/resources/js/Layouts/GuestLayout.jsx index 1377b30..81a563c 100644 --- a/resources/js/Layouts/GuestLayout.jsx +++ b/resources/js/Layouts/GuestLayout.jsx @@ -1,13 +1,13 @@ -import React from 'react'; -import ApplicationLogo from '@/Components/Defaults/ApplicationLogo'; -import { Link } from '@inertiajs/react'; +import React from 'react' +import ApplicationLogo from '@/Components/Defaults/ApplicationLogo' +import { Link } from '@inertiajs/react' export default function Guest({ children }) { return (
- +
@@ -15,5 +15,5 @@ export default function Guest({ children }) { {children}
- ); + ) } diff --git a/resources/js/Pages/LocationProfile/Index.jsx b/resources/js/Pages/LocationProfile/Index.jsx index 4f0fc89..d5a5da1 100644 --- a/resources/js/Pages/LocationProfile/Index.jsx +++ b/resources/js/Pages/LocationProfile/Index.jsx @@ -154,7 +154,7 @@ export default function Index(props) { scope="row" className="py-4 px-6" > - {profile.diplay_expired} + {profile.display_expired} { + const { voucher } = JSON.parse(item.additional_info_json) + console.log(voucher) + return ( + <> + + {index + 1} + + + {voucher.location_profile.location.name} + + + {voucher.location_profile.name} + + + {voucher.username} + + + {voucher.comment} + + + {voucher.location_profile.quota} + + + {voucher.location_profile.display_expired} + + + ) +} + export default function Detail(props) { const { sale } = props @@ -50,13 +83,10 @@ export default function Detail(props) { Lokasi - Username - - - Password + Profile - Profile + Kode Comment @@ -64,38 +94,19 @@ export default function Detail(props) { Kuota + + + Masa Aktif + {sale.items.map((item, index) => ( - - {index + 1} - - - {item.voucher.location.name} - - - {item.voucher.username} - - - {item.voucher.password} - - - {item.voucher.profile} - - - {item.voucher.comment} - - - {item.voucher.display_quota} - + ))} diff --git a/resources/js/Pages/Voucher/Index.jsx b/resources/js/Pages/Voucher/Index.jsx index b749f3f..0f967db 100644 --- a/resources/js/Pages/Voucher/Index.jsx +++ b/resources/js/Pages/Voucher/Index.jsx @@ -317,7 +317,7 @@ export default function Index(props) { className="py-4 px-6" >
{voucher.status.text}
diff --git a/routes/web.php b/routes/web.php index d34891b..8a912db 100644 --- a/routes/web.php +++ b/routes/web.php @@ -73,7 +73,7 @@ Route::middleware(['http_secure_aware', 'guard_should_customer', 'inertia.custom // cart Route::get('cart', [CartController::class, 'index'])->name('cart.index'); Route::post('cart/process', [CartController::class, 'purchase'])->name('cart.purchase'); - Route::post('cart/{voucher}', [CartController::class, 'store'])->name('cart.store'); + Route::post('cart/{profile}', [CartController::class, 'store'])->name('cart.store'); // notification Route::get('notifications', [HomeController::class, 'notification'])->name('notification.index');