diff --git a/app/Http/Controllers/Customer/CartController.php b/app/Http/Controllers/Customer/CartController.php index 8f808b0..e4dfa93 100644 --- a/app/Http/Controllers/Customer/CartController.php +++ b/app/Http/Controllers/Customer/CartController.php @@ -49,7 +49,7 @@ class CartController extends Controller $operator = $request->param ?? 'add'; //delete, sub, add $customer = $request->user('customer'); - if (! $customer->allow_transaction) { + if (!$customer->allow_transaction) { $customer->carts()->delete(); return redirect()->back() diff --git a/app/Http/Middleware/HandleInertiaRequests.php b/app/Http/Middleware/HandleInertiaRequests.php index 2bdafef..823644a 100644 --- a/app/Http/Middleware/HandleInertiaRequests.php +++ b/app/Http/Middleware/HandleInertiaRequests.php @@ -45,6 +45,8 @@ class HandleInertiaRequests extends Middleware 'count_unread_notifications' => $notifications->where('is_read', Notification::UNREAD)->count(), 'deposit_notifications' => $notifications->where('type', Notification::TYPE_DEPOSIT) ->where('is_read', Notification::UNREAD)->limit(10)->get(), + 'stock_notifications' => $notifications->where('type', Notification::TYPE_VOUCHER_STOCK) + ->where('is_read', Notification::UNREAD)->limit(10)->get(), ]); } } diff --git a/app/Models/Notification.php b/app/Models/Notification.php index 9447627..19e4dfc 100644 --- a/app/Models/Notification.php +++ b/app/Models/Notification.php @@ -9,6 +9,8 @@ class Notification extends Model { const TYPE_DEPOSIT = 'deposit'; + const TYPE_VOUCHER_STOCK = 'voucher_stock'; + const UNREAD = 0; const READ = 1; diff --git a/app/Models/Voucher.php b/app/Models/Voucher.php index 4496abc..8063a28 100644 --- a/app/Models/Voucher.php +++ b/app/Models/Voucher.php @@ -2,6 +2,7 @@ namespace App\Models; +use App\Events\NotificationEvent; use App\Services\GeneralService; use Illuminate\Database\Eloquent\Casts\Attribute; @@ -173,9 +174,24 @@ class Voucher extends Model $treshold = $this->locationProfile->min_stock; if ($count <= $treshold) { - Notification::create([ + $notification = Notification::create([ 'entity_type' => User::class, - 'description' => 'stok voucher '.$this->locationProfile->name.'tersisa : '.$count, + 'description' => 'stok voucher ' . $this->locationProfile->name . ' tersisa : ' . $count, + 'url' => route('voucher.profile', $this->locationProfile->location_id), + 'type' => Notification::TYPE_VOUCHER_STOCK, + ]); + + NotificationEvent::dispatch([ + 'id' => $notification->id, + 'description' => $notification->description, + 'url' => $notification->url, + 'type' => Notification::TYPE_VOUCHER_STOCK, + 'format_created_at' => now()->translatedFormat('d F Y H:i:s'), + 'stock_notifications' => Notification::where('entity_type', User::class) + ->where('type', Notification::TYPE_VOUCHER_STOCK) + ->where('is_read', Notification::UNREAD)->limit(10) + ->orderBy('created_at', 'desc') + ->get(), ]); } } diff --git a/resources/assets/warning.mp3 b/resources/assets/warning.mp3 new file mode 100644 index 0000000..b15e525 Binary files /dev/null and b/resources/assets/warning.mp3 differ diff --git a/resources/js/Layouts/AuthenticatedLayout.jsx b/resources/js/Layouts/AuthenticatedLayout.jsx index 06d8e7e..8d65d51 100644 --- a/resources/js/Layouts/AuthenticatedLayout.jsx +++ b/resources/js/Layouts/AuthenticatedLayout.jsx @@ -10,6 +10,7 @@ import Dropdown from '@/Components/Defaults/Dropdown' import SidebarNav from './Partials/SidebarNav' import NotificationContent from './Partials/NotificationContent' import NotificationDeposit from './Partials/NotificationDeposit' +import NotificationStock from './Partials/NotificationStock' const customTheme = { button: { @@ -63,6 +64,9 @@ export default function Authenticated({
+
+ +
diff --git a/resources/js/Layouts/Partials/NotificationContent.jsx b/resources/js/Layouts/Partials/NotificationContent.jsx index 5dee34a..0a1f77c 100644 --- a/resources/js/Layouts/Partials/NotificationContent.jsx +++ b/resources/js/Layouts/Partials/NotificationContent.jsx @@ -3,6 +3,7 @@ import { router, usePage } from '@inertiajs/react' import { HiOutlineBell } from 'react-icons/hi2' import Dropdown from '@/Components/Defaults/Dropdown' +import { isEmpty } from 'lodash' export default function NotificationContent() { const { @@ -10,6 +11,10 @@ export default function NotificationContent() { } = usePage() const handleNotification = (notif) => { fetch(route('api.notification.update', notif)) + if (isEmpty(notif.url) === false) { + router.visit(notif.url) + return + } router.get(route(route().current())) } diff --git a/resources/js/Layouts/Partials/NotificationStock.jsx b/resources/js/Layouts/Partials/NotificationStock.jsx new file mode 100644 index 0000000..a7ead54 --- /dev/null +++ b/resources/js/Layouts/Partials/NotificationStock.jsx @@ -0,0 +1,132 @@ +import React, { useState, useEffect, useRef } from 'react' +import { router, usePage } from '@inertiajs/react' +import { isEmpty } from 'lodash' +import { HiOutlineTicket } from 'react-icons/hi2' + +import audioSrc from '@/../assets/warning.mp3' + +import Dropdown from '@/Components/Defaults/Dropdown' +import { browserNotification } from './helpers' + +export default function NotificationStock() { + const { + props: { stock_notifications }, + } = usePage() + const [bounce, setBounce] = useState(false) + const [notif, setNotif] = useState(stock_notifications) + const audioRef = useRef() + + const handleNotification = (notif) => { + if (isEmpty(notif) === false) { + fetch(route('api.notification.update', notif)) + router.get(notif.url) + return + } + fetch(route('api.notification.update')) + router.get(route('dashboard')) + } + + const handleAudioStop = () => { + if (isEmpty(audioRef.current) === false) { + audioRef.current.pause() + audioRef.current.currentTime = 0 + } + setBounce(false) + } + + const handleAudioPlay = () => { + if (audioRef.current.currentTime !== 0) { + handleAudioStop() + } + + try { + audioRef.current.play() + } catch (error) { + console.log(error) + } + + setBounce(true) + setTimeout(() => setBounce(false), 22000) + } + + const handleUpdate = async (e) => { + setNotif(e.message.stock_notifications) + handleAudioPlay() + browserNotification( + 'Notifikasi Stok Voucher', + e.message.description, + e.message.url + ) + } + + useEffect(() => { + window.Echo.channel('notification') + .listen('NotificationEvent', (e) => { + if (e.message.type === 'voucher_stock') { + handleUpdate(e) + } + }) + .error((error) => { + console.error(error) + }) + return () => { + window.Echo.leave('notification') + } + }, []) + + return ( + + + +
handleAudioStop()} + > + +
+
+ {notif.length} +
+
+
+
+ + {notif.map((notif) => ( +
handleNotification(notif)} + key={notif.format_created_at} + > +
{notif.description}
+
{notif.format_created_at}
+
+ ))} + {notif.length > 0 && ( +
+
+ router.get(route('notifications.index')) + } + > + lihat semua +
+
handleNotification()} + > + tandai semua dibaca +
+
+ )} + {notif.length === 0 && ( +
Tidak ada notifikasi
+ )} +
+
+ ) +}