feat(push notification): menjadikan notificakasi menggunakan job dan dispatch di beberapa komponen yang membuatuhkan

This commit is contained in:
Yoga Pangestu 2025-11-16 15:33:51 +07:00
parent fd5a85400c
commit 5fa0944811
10 changed files with 127 additions and 37 deletions

View File

@ -0,0 +1,50 @@
<?php
namespace App\Jobs;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
use Minishlink\WebPush\Subscription;
use Minishlink\WebPush\WebPush;
class StorePushNotification implements ShouldQueue
{
use Queueable;
/**
* Create a new job instance.
*/
public function __construct(
protected $notificationQuery,
protected array $payload
) {
//
}
/**
* Execute the job.
*/
public function handle(): void
{
$auth = [
'VAPID' => [
'subject' => config('app.url'),
'publicKey' => config('services.vapid.public_key'),
'privateKey' => config('services.vapid.private_key'),
],
];
$webPush = new WebPush($auth);
$payload = json_encode($this->payload);
foreach ($this->notificationQuery as $notification) {
$webPush->sendOneNotification(
Subscription::create(json_decode($notification->subscriptions, true)),
$payload,
['TTL' => 5000],
);
}
}
}

View File

@ -49,7 +49,7 @@ public function store()
$amount = (int) replaceCurrency($this->amount); $amount = (int) replaceCurrency($this->amount);
DB::transaction(function () use ($amount) { DB::transaction(function () use ($amount, &$adjustment) {
foreach ($this->user_ids as $user_id) { foreach ($this->user_ids as $user_id) {
$periodMonth = Carbon::now()->format('Y-m'); $periodMonth = Carbon::now()->format('Y-m');
@ -61,7 +61,7 @@ public function store()
throw new \Exception('Penggajian tidak ditemukan.'); throw new \Exception('Penggajian tidak ditemukan.');
} }
PayrollAdjustment::create([ $adjustment = PayrollAdjustment::create([
'payroll_id' => $payroll->id, 'payroll_id' => $payroll->id,
'type' => $this->type, 'type' => $this->type,
'description' => $this->description, 'description' => $this->description,
@ -79,6 +79,18 @@ public function store()
$payroll->save(); $payroll->save();
} }
}); });
if ($adjustment->type == SalaryAdjustmentType::BONUS->value) {
return [
'userIds' => $this->user_ids,
'message' => 'Horee, Anda mendapatkan bonus sebesar '.currency($amount, 'Rp').' untuk bulan ini, Lihat detailnya di menu Penggajian.',
];
} elseif ($adjustment->type == SalaryAdjustmentType::DEDUCTION->value) {
return [
'userIds' => $this->user_ids,
'message' => 'Yahh, gaji Anda dipotong sebesar '.currency($amount, 'Rp').' untuk bulan ini, Lihat detailnya di menu Penggajian.',
];
}
} }
public function update() public function update()

View File

@ -60,7 +60,7 @@ public function store()
{ {
$this->validate(); $this->validate();
DB::transaction(function () { DB::transaction(function () use (&$article) {
$article = Article::create([ $article = Article::create([
'author_id' => auth()->id(), 'author_id' => auth()->id(),
'title' => $this->title, 'title' => $this->title,
@ -72,6 +72,8 @@ public function store()
$this->uploadMedia($this->thumbnail, $article, 'thumbnail'); $this->uploadMedia($this->thumbnail, $article, 'thumbnail');
}); });
return $article;
} }
public function update() public function update()

View File

@ -116,7 +116,7 @@ public function store()
// Wrap the entire operation in a database transaction // Wrap the entire operation in a database transaction
// Ensures atomicity — if any step fails, all changes are rolled back // Ensures atomicity — if any step fails, all changes are rolled back
try { try {
DB::transaction(function () use ($invoiceNumber, $cogs, $subtotal, $discount, $total, $items, $pointsEarned) { DB::transaction(function () use (&$order, $invoiceNumber, $cogs, $subtotal, $discount, $total, $items, $pointsEarned) {
$member = User::whereHas('customer', fn ($q) => $q->where('id', $this->member_id)) $member = User::whereHas('customer', fn ($q) => $q->where('id', $this->member_id))
->with(['membership' => fn ($q) => $q->lockForUpdate()]) ->with(['membership' => fn ($q) => $q->lockForUpdate()])
->first(); ->first();
@ -201,6 +201,9 @@ public function store()
]; ];
} }
return ['status' => true]; return [
'status' => true,
'data' => $order,
];
} }
} }

View File

@ -2,10 +2,12 @@
namespace App\Livewire\Studio\Catalog\Perfume; namespace App\Livewire\Studio\Catalog\Perfume;
use App\Jobs\StorePushNotification;
use App\Livewire\Forms\Studio\Catalog\PerfumeForm; use App\Livewire\Forms\Studio\Catalog\PerfumeForm;
use App\Models\Brand; use App\Models\Brand;
use App\Models\Category; use App\Models\Category;
use App\Models\Outlet; use App\Models\Outlet;
use App\Models\PushNotification;
use App\Traits\WithAuthorization; use App\Traits\WithAuthorization;
use App\Traits\WithCategorySelector; use App\Traits\WithCategorySelector;
use App\Traits\WithOutletSelector; use App\Traits\WithOutletSelector;
@ -38,6 +40,14 @@ public function mount()
public function save() public function save()
{ {
StorePushNotification::dispatch(
PushNotification::all(),
[
'title' => 'Parfum',
'body' => 'Ada yang baru nih! Aroma terbaru sudah siap kamu coba. Yuk intip dulu sebelum kehabisan.',
],
);
$this->canOrAbort('create perfume'); $this->canOrAbort('create perfume');
$this->form->store(); $this->form->store();

View File

@ -3,9 +3,11 @@
namespace App\Livewire\Studio\Finance; namespace App\Livewire\Studio\Finance;
use App\Enums\SalaryAdjustmentType; use App\Enums\SalaryAdjustmentType;
use App\Jobs\StorePushNotification;
use App\Livewire\Forms\Studio\Finance\PayrollForm; use App\Livewire\Forms\Studio\Finance\PayrollForm;
use App\Models\Payroll as PayrollModel; use App\Models\Payroll as PayrollModel;
use App\Models\PayrollAdjustment; use App\Models\PayrollAdjustment;
use App\Models\PushNotification;
use App\Models\User; use App\Models\User;
use App\Traits\Notification\WithSubscribeNotification; use App\Traits\Notification\WithSubscribeNotification;
use App\Traits\WithAuthorization; use App\Traits\WithAuthorization;
@ -69,7 +71,15 @@ public function create()
{ {
$this->canOrAbort('manage adjustment'); $this->canOrAbort('manage adjustment');
$this->form->store(); $result = $this->form->store();
StorePushNotification::dispatch(
PushNotification::where('user_id', $result['userIds'])->get(),
[
'title' => 'Order',
'body' => $result['message'],
],
);
$this->loadPayrolls(); $this->loadPayrolls();

View File

@ -2,8 +2,10 @@
namespace App\Livewire\Studio\Loyalty\Voucher; namespace App\Livewire\Studio\Loyalty\Voucher;
use App\Jobs\StorePushNotification;
use App\Livewire\Forms\Studio\Loyalty\VoucherForm; use App\Livewire\Forms\Studio\Loyalty\VoucherForm;
use App\Models\Outlet; use App\Models\Outlet;
use App\Models\PushNotification;
use App\Traits\WithAuthorization; use App\Traits\WithAuthorization;
use App\Traits\WithOutletSelector; use App\Traits\WithOutletSelector;
use App\Traits\WithToast; use App\Traits\WithToast;
@ -27,6 +29,14 @@ public function mount()
public function save() public function save()
{ {
StorePushNotification::dispatch(
PushNotification::all(),
[
'title' => 'Voucher',
'body' => 'Ada voucher baru untuk kamu! Jangan sampai kelewatan, yuk cek sekarang dan nikmati penawarannya.',
],
);
$this->canOrAbort('create voucher'); $this->canOrAbort('create voucher');
$this->form->store(); $this->form->store();

View File

@ -2,7 +2,9 @@
namespace App\Livewire\Studio\Manage\Article; namespace App\Livewire\Studio\Manage\Article;
use App\Jobs\StorePushNotification;
use App\Livewire\Forms\Studio\Manage\ArticleForm; use App\Livewire\Forms\Studio\Manage\ArticleForm;
use App\Models\PushNotification;
use App\Traits\WithAuthorization; use App\Traits\WithAuthorization;
use App\Traits\WithToast; use App\Traits\WithToast;
use App\Traits\WithUpdatedData; use App\Traits\WithUpdatedData;
@ -20,7 +22,15 @@ public function save()
{ {
$this->canOrAbort('create article'); $this->canOrAbort('create article');
$this->form->store(); $result = $this->form->store();
StorePushNotification::dispatch(
PushNotification::all(),
[
'title' => 'Artikel',
'body' => $result->title,
],
);
$this->dispatch('refreshDatatable'); $this->dispatch('refreshDatatable');

View File

@ -2,10 +2,13 @@
namespace App\Livewire\Studio\Manage\Order; namespace App\Livewire\Studio\Manage\Order;
use App\Jobs\StorePushNotification;
use App\Livewire\Forms\Studio\Manage\OrderForm; use App\Livewire\Forms\Studio\Manage\OrderForm;
use App\Models\Bottle; use App\Models\Bottle;
use App\Models\Perfume; use App\Models\Perfume;
use App\Models\Product; use App\Models\Product;
use App\Models\PushNotification;
use App\Models\User;
use App\Traits\Order\WithAddItem; use App\Traits\Order\WithAddItem;
use App\Traits\Order\WithCalculateTotal; use App\Traits\Order\WithCalculateTotal;
use App\Traits\Order\WithDiscount; use App\Traits\Order\WithDiscount;
@ -87,6 +90,16 @@ public function save()
return; return;
} }
$userIds = User::role(['Developer', 'Owner', 'Leader'])->pluck('id')->toArray();
StorePushNotification::dispatch(
PushNotification::whereIn('user_id', $userIds)->get(),
[
'title' => 'Order',
'body' => 'Ada order baru masuk dengan nominal '.$result->total,
],
);
$this->dispatch('refreshDatatable'); $this->dispatch('refreshDatatable');
$this->toast('Order berhasil ditambahkan.'); $this->toast('Order berhasil ditambahkan.');

View File

@ -5,7 +5,6 @@
use App\Livewire\Forms\Studio\Master\FormulaForm; use App\Livewire\Forms\Studio\Master\FormulaForm;
use App\Models\Bottle; use App\Models\Bottle;
use App\Models\Formula as FormulaModel; use App\Models\Formula as FormulaModel;
use App\Models\PushNotification;
use App\Traits\Notification\WithSubscribeNotification; use App\Traits\Notification\WithSubscribeNotification;
use App\Traits\WithAuthorization; use App\Traits\WithAuthorization;
use App\Traits\WithCloseModal; use App\Traits\WithCloseModal;
@ -16,8 +15,6 @@
use Livewire\Attributes\On; use Livewire\Attributes\On;
use Livewire\Attributes\Title; use Livewire\Attributes\Title;
use Livewire\Component; use Livewire\Component;
use Minishlink\WebPush\Subscription;
use Minishlink\WebPush\WebPush;
#[Title('Rumus')] #[Title('Rumus')]
class Formula extends Component class Formula extends Component
@ -97,8 +94,6 @@ public function create()
public function update() public function update()
{ {
$this->pushNotification();
$exists = FormulaModel::where('quality', $this->form->quality) $exists = FormulaModel::where('quality', $this->form->quality)
->where('size', $this->form->size) ->where('size', $this->form->size)
->where('id', '!=', $this->form->formula->id) ->where('id', '!=', $this->form->formula->id)
@ -155,31 +150,6 @@ public function delete(FormulaModel $formula)
Flux::modals()->close(); Flux::modals()->close();
} }
protected function pushNotification()
{
$auth = [
'VAPID' => [
'subject' => config('app.url'),
'publicKey' => config('services.vapid.public_key'),
'privateKey' => config('services.vapid.private_key'),
],
];
$webPush = new WebPush($auth);
$payload = json_encode([
'title' => 'Penggajian',
'body' => 'Penggajian baru telah ditambahkan.',
]);
foreach (PushNotification::all() as $notification) {
$webPush->sendOneNotification(
Subscription::create(json_decode($notification->subscriptions, true)),
$payload,
['TTL' => 5000],
);
}
}
public function render() public function render()
{ {
return view('livewire.studio.master.formulas', [ return view('livewire.studio.master.formulas', [