From 612ccc0ac1f773576ab3d9974d22db94a8d57cac Mon Sep 17 00:00:00 2001 From: Aji Kamaludin Date: Wed, 7 Jun 2023 02:42:36 +0700 Subject: [PATCH] notifikasi , bit fix dashboard --- TODO.md | 8 +- .../Api/NotificationController.php | 19 +++ .../Controllers/Customer/CartController.php | 2 + .../Customer/DepositController.php | 5 + .../Controllers/Customer/HomeController.php | 10 ++ app/Http/Controllers/DepositController.php | 1 + .../Controllers/NotificationController.php | 20 +++ app/Http/Controllers/VoucherController.php | 4 + .../HandleInertiaCustomerRequests.php | 8 +- app/Http/Middleware/HandleInertiaRequests.php | 3 + app/Models/DepositHistory.php | 29 ++++ app/Models/Notification.php | 27 ++++ app/Models/Sale.php | 13 ++ app/Models/Voucher.php | 17 ++ resources/js/Components/Defaults/Dropdown.jsx | 75 +++++---- resources/js/Customer/Index/Notification.jsx | 70 +++++++++ resources/js/Customer/Index/UserBanner.jsx | 13 +- resources/js/Customer/Profile/Index.jsx | 18 ++- resources/js/Layouts/AuthenticatedLayout.jsx | 146 ++++++++++++++---- resources/js/Pages/Dashboard.jsx | 8 +- resources/js/Pages/Notification/Index.jsx | 110 +++++++++++++ resources/js/Pages/Voucher/Index.jsx | 17 +- routes/admin.php | 4 + routes/api.php | 2 + routes/web.php | 3 + 25 files changed, 548 insertions(+), 84 deletions(-) create mode 100644 app/Http/Controllers/Api/NotificationController.php create mode 100644 app/Http/Controllers/NotificationController.php create mode 100644 resources/js/Customer/Index/Notification.jsx create mode 100644 resources/js/Pages/Notification/Index.jsx diff --git a/TODO.md b/TODO.md index 6a82e0f..5ac1453 100644 --- a/TODO.md +++ b/TODO.md @@ -18,11 +18,7 @@ - [x] Setting Bonus Coin (memasukan amount bonus coin yang didapat dengan level dan harga voucher) - bonus coin - [x] Voucher Sales (index: customer, total, jumlah voucher, detail: customer, list voucher, payment) - [x] Dashboard (gafik hasil penjualan : disorting tanggal, lokasi dan customer) - [total voucher] [total customer] [total customer verified] [total deposit] - [total voucher terjual bulan xxx] [jumlah voucher terjual bulan xxx] [total voucher terjual hari ini ] [jumlah voucher terjual hari ini] - [cart penjualan per tanggal, pilih range tanggal (range default 7), bisa filter by lokasi dan customer] - [list customer dengan total beli hari ini] -- [ ] Notification (manual deposit, deposit success, stock voucher, sale) +- [x] Notification ([x]manual deposit, [x]deposit success, [x]stock voucher, [x]sale) - [ ] View Customer Coin History - [ ] Voucher - harga per level - [ ] Voucher - harga coin @@ -48,5 +44,5 @@ - [x] Customer View Coin History - [x] Verified Akun - [x] Paylater: index paylater, payment cart, deposite repay +- [x] Notification ([x] purchase success, [x] deposit success) - [ ] Coin Explorer: list voucher, modal voucher to excange -- [ ] Notification (purchase success, deposit success) diff --git a/app/Http/Controllers/Api/NotificationController.php b/app/Http/Controllers/Api/NotificationController.php new file mode 100644 index 0000000..8e9c15e --- /dev/null +++ b/app/Http/Controllers/Api/NotificationController.php @@ -0,0 +1,19 @@ +id == null) { + (new Notification())->mark_all_as_read(); + return; + } + $notif->mark_as_read(); + } +} diff --git a/app/Http/Controllers/Customer/CartController.php b/app/Http/Controllers/Customer/CartController.php index 65302c8..08cdd56 100644 --- a/app/Http/Controllers/Customer/CartController.php +++ b/app/Http/Controllers/Customer/CartController.php @@ -155,8 +155,10 @@ class CartController extends Controller ]); $voucher->update(['is_sold' => Voucher::SOLD]); + $voucher->check_stock_notification(); } } + $sale->create_notification(); $bonus = CoinReward::where('customer_level_id', $customer->customer_level_id) ->where('amount_buy', '<=', $total) diff --git a/app/Http/Controllers/Customer/DepositController.php b/app/Http/Controllers/Customer/DepositController.php index 06686ed..3c9925c 100644 --- a/app/Http/Controllers/Customer/DepositController.php +++ b/app/Http/Controllers/Customer/DepositController.php @@ -65,6 +65,7 @@ class DepositController extends Controller $deposit->update(['payment_token' => $token]); } + $deposit->create_notification(); DB::commit(); @@ -97,6 +98,8 @@ class DepositController extends Controller 'is_valid' => DepositHistory::STATUS_WAIT_APPROVE, ]); + $deposit->create_notification(); + session()->flash('message', ['type' => 'success', 'message' => 'Upload berhasil, silahkan tunggu untuk approve']); } @@ -147,6 +150,8 @@ class DepositController extends Controller $deposit->update_customer_balance(); $customer = Customer::find($deposit->customer_id); $customer->repayPaylater($deposit); + $deposit->create_notification(); + $deposit->create_notification_user(); } elseif ($request->transaction_status == 'pending') { $deposit->fill(['payment_status' => DepositHistory::STATUS_WAIT_PAYMENT]); } else { diff --git a/app/Http/Controllers/Customer/HomeController.php b/app/Http/Controllers/Customer/HomeController.php index 450071d..dad4082 100644 --- a/app/Http/Controllers/Customer/HomeController.php +++ b/app/Http/Controllers/Customer/HomeController.php @@ -6,6 +6,7 @@ use App\Http\Controllers\Controller; use App\Models\Banner; use App\Models\Info; use App\Models\Location; +use App\Models\Notification; use App\Models\Voucher; use Illuminate\Http\Request; @@ -40,4 +41,13 @@ class HomeController extends Controller 'banner' => $banner, ]); } + + public function notification() + { + Notification::where('entity_id', auth()->id())->where('is_read', Notification::UNREAD)->update(['is_read' => Notification::READ]); + + return inertia('Index/Notification', [ + 'notification' => Notification::where('entity_id', auth()->id())->orderBy('updated_at', 'desc')->paginate() + ]); + } } diff --git a/app/Http/Controllers/DepositController.php b/app/Http/Controllers/DepositController.php index 3c9ee28..cfd2f4f 100644 --- a/app/Http/Controllers/DepositController.php +++ b/app/Http/Controllers/DepositController.php @@ -59,6 +59,7 @@ class DepositController extends Controller $customer = Customer::find($deposit->customer_id); $customer->repayPaylater($deposit); + $deposit->create_notification_user(); } DB::commit(); diff --git a/app/Http/Controllers/NotificationController.php b/app/Http/Controllers/NotificationController.php new file mode 100644 index 0000000..77dc325 --- /dev/null +++ b/app/Http/Controllers/NotificationController.php @@ -0,0 +1,20 @@ +orderBy('is_read', 'asc') + ->orderBy('created_at', 'desc'); + + return inertia('Notification/Index', [ + 'query' => $query->paginate(), + ]); + } +} diff --git a/app/Http/Controllers/VoucherController.php b/app/Http/Controllers/VoucherController.php index 58eb385..51b2277 100644 --- a/app/Http/Controllers/VoucherController.php +++ b/app/Http/Controllers/VoucherController.php @@ -20,6 +20,10 @@ class VoucherController extends Controller ->orWhere('profile', 'like', "%$request->q%"); } + if ($request->location_id != '') { + $query->where('location_id', $request->location_id); + } + return inertia('Voucher/Index', [ 'query' => $query->paginate(), ]); diff --git a/app/Http/Middleware/HandleInertiaCustomerRequests.php b/app/Http/Middleware/HandleInertiaCustomerRequests.php index 4595f7b..9a32b4e 100644 --- a/app/Http/Middleware/HandleInertiaCustomerRequests.php +++ b/app/Http/Middleware/HandleInertiaCustomerRequests.php @@ -2,6 +2,7 @@ namespace App\Http\Middleware; +use App\Models\Notification; use Illuminate\Http\Request; use Inertia\Middleware; @@ -37,6 +38,11 @@ class HandleInertiaCustomerRequests extends Middleware } } + $notification_count = 0; + if (auth('customer')->check()) { + $notification_count = Notification::where('entity_id', auth()->id())->where('is_read', Notification::UNREAD)->count(); + } + return array_merge(parent::share($request), [ 'app_name' => env('APP_NAME', 'App Name'), 'auth' => [ @@ -45,7 +51,7 @@ class HandleInertiaCustomerRequests extends Middleware 'flash' => [ 'message' => fn () => $request->session()->get('message') ?? ['type' => null, 'message' => null], ], - 'notification_count' => 0, + 'notification_count' => $notification_count, 'cart_count' => $cart_count, ]); } diff --git a/app/Http/Middleware/HandleInertiaRequests.php b/app/Http/Middleware/HandleInertiaRequests.php index 592894d..5c113b2 100644 --- a/app/Http/Middleware/HandleInertiaRequests.php +++ b/app/Http/Middleware/HandleInertiaRequests.php @@ -2,6 +2,7 @@ namespace App\Http\Middleware; +use App\Models\Notification; use Illuminate\Http\Request; use Inertia\Middleware; @@ -38,6 +39,8 @@ class HandleInertiaRequests extends Middleware ], 'app_name' => env('APP_NAME', 'App Name'), 'csrf_token' => csrf_token(), + 'notifications' => Notification::where('entity_type', \App\Models\User::class)->orderBy('created_at', 'desc')->limit(10)->get(), + 'count_unread_notifications' => Notification::where('entity_type', \App\Models\User::class)->where('is_read', Notification::UNREAD)->count(), ]); } } diff --git a/app/Models/DepositHistory.php b/app/Models/DepositHistory.php index 2766d68..8d12f99 100644 --- a/app/Models/DepositHistory.php +++ b/app/Models/DepositHistory.php @@ -105,4 +105,33 @@ class DepositHistory extends Model $customer = Customer::find($this->customer_id); $customer->update(['deposit_balance' => $customer->deposit_balance + $this->debit - $this->credit]); } + + public function create_notification() + { + if ($this->payment_channel == Setting::PAYMENT_MANUAL) { + $status = ""; + if ($this->is_valid == self::STATUS_WAIT_APPROVE) { + $status = " (bukti bayar di upload, membutuhkan konfirmasi)"; + } + Notification::create([ + 'entity_type' => User::class, + 'description' => $this->customer->fullname . ' melakukan deposit manual sebesar : ' . $this->amount . $status, + ]); + } + + if ($this->payment_channel == Setting::PAYMENT_MIDTRANS) { + Notification::create([ + 'entity_type' => User::class, + 'description' => $this->customer->fullname . ' melakukan deposit via midtrans sebesar : ' . $this->amount, + ]); + } + } + + public function create_notification_user() + { + Notification::create([ + 'entity_id' => $this->customer_id, + 'description' => 'Deposit ' . $this->description . ' sebesar ' . $this->amount . ' sudah sukses diterima', + ]); + } } diff --git a/app/Models/Notification.php b/app/Models/Notification.php index 8b9a4c5..bef61c6 100644 --- a/app/Models/Notification.php +++ b/app/Models/Notification.php @@ -2,12 +2,39 @@ namespace App\Models; +use Illuminate\Database\Eloquent\Casts\Attribute; +use Illuminate\Support\Carbon; + class Notification extends Model { + const UNREAD = 0; + const READ = 1; + protected $fillable = [ 'entity_type', 'entity_id', 'description', 'is_read', ]; + + protected $appends = [ + 'format_created_at' + ]; + + public function mark_as_read() + { + $this->update(['is_read' => self::READ]); + } + + public function mark_all_as_read() + { + Notification::where('is_read', self::UNREAD)->where('entity_type', User::class)->update(['is_read' => self::READ]); + } + + public function formatCreatedAt(): Attribute + { + return Attribute::make(get: function () { + return Carbon::parse($this->created_at)->locale('id')->translatedFormat('d F Y H:i:s'); + }); + } } diff --git a/app/Models/Sale.php b/app/Models/Sale.php index a6ffbb5..2b9d35c 100644 --- a/app/Models/Sale.php +++ b/app/Models/Sale.php @@ -67,4 +67,17 @@ class Sale extends Model return 'Rp' . number_format($this->amount, 0, ',', '.'); }); } + + public function create_notification() + { + Notification::create([ + 'entity_type' => User::class, + 'description' => $this->customer->fullname . ' melakukan pembelian ' . $this->items()->count() . ' voucher sebesar ' . $this->display_amount, + ]); + + Notification::create([ + 'entity_id' => auth()->id(), + 'description' => 'Transaksi pembelian anda #' . $this->code . ' sebesar ' . $this->display_amount . ' berhasil', + ]); + } } diff --git a/app/Models/Voucher.php b/app/Models/Voucher.php index 6fd1369..aa39cff 100644 --- a/app/Models/Voucher.php +++ b/app/Models/Voucher.php @@ -98,4 +98,21 @@ class Voucher extends Model return $voucher; } + + public function check_stock_notification() + { + $count = Voucher::where([ + ['is_sold', '=', self::UNSOLD], + ['batch_id', '=', $this->batch_id] + ])->count(); + + $treshold = Setting::getByKey('VOUCHER_STOCK_NOTIFICATION'); + + if ($count <= $treshold) { + Notification::create([ + 'entity_type' => User::class, + 'description' => "stok voucher " . $this->location->name . " ( " . $this->profile . " ) " . "tersisa : " . $count, + ]); + } + } } diff --git a/resources/js/Components/Defaults/Dropdown.jsx b/resources/js/Components/Defaults/Dropdown.jsx index 085d884..bbd704a 100644 --- a/resources/js/Components/Defaults/Dropdown.jsx +++ b/resources/js/Components/Defaults/Dropdown.jsx @@ -1,50 +1,60 @@ -import React, { useState, useContext, Fragment } from 'react'; -import { Link } from '@inertiajs/react'; -import { Transition } from '@headlessui/react'; +import React, { useState, useContext, Fragment } from 'react' +import { Link } from '@inertiajs/react' +import { Transition } from '@headlessui/react' -const DropDownContext = React.createContext(); +const DropDownContext = React.createContext() const Dropdown = ({ children }) => { - const [open, setOpen] = useState(false); + const [open, setOpen] = useState(false) const toggleOpen = () => { - setOpen((previousState) => !previousState); - }; + setOpen((previousState) => !previousState) + } return (
{children}
- ); -}; + ) +} const Trigger = ({ children }) => { - const { open, setOpen, toggleOpen } = useContext(DropDownContext); + const { open, setOpen, toggleOpen } = useContext(DropDownContext) return ( <>
{children}
- {open &&
setOpen(false)}>
} + {open && ( +
setOpen(false)} + >
+ )} - ); -}; + ) +} -const Content = ({ align = 'right', width = '48', contentClasses = 'py-1 bg-white', children }) => { - const { open, setOpen } = useContext(DropDownContext); +const Content = ({ + align = 'right', + width = '48', + contentClasses = 'py-1 bg-white', + children, +}) => { + const { open, setOpen } = useContext(DropDownContext) - let alignmentClasses = 'origin-top'; + let alignmentClasses = 'origin-top' if (align === 'left') { - alignmentClasses = 'origin-top-left left-0'; + alignmentClasses = 'origin-top-left left-0' } else if (align === 'right') { - alignmentClasses = 'origin-top-right right-0'; + alignmentClasses = 'origin-top-right right-0' } - let widthClasses = ''; + let widthClasses = 'w-96' if (width === '48') { - widthClasses = 'w-48'; + widthClasses = 'w-48' } return ( @@ -63,12 +73,19 @@ const Content = ({ align = 'right', width = '48', contentClasses = 'py-1 bg-whit className={`absolute z-50 mt-2 rounded-md shadow-lg ${alignmentClasses} ${widthClasses}`} onClick={() => setOpen(false)} > -
{children}
+
+ {children} +
- ); -}; + ) +} const DropdownLink = ({ href, method, as, children }) => { return ( @@ -80,11 +97,11 @@ const DropdownLink = ({ href, method, as, children }) => { > {children} - ); -}; + ) +} -Dropdown.Trigger = Trigger; -Dropdown.Content = Content; -Dropdown.Link = DropdownLink; +Dropdown.Trigger = Trigger +Dropdown.Content = Content +Dropdown.Link = DropdownLink -export default Dropdown; +export default Dropdown diff --git a/resources/js/Customer/Index/Notification.jsx b/resources/js/Customer/Index/Notification.jsx new file mode 100644 index 0000000..3995fe9 --- /dev/null +++ b/resources/js/Customer/Index/Notification.jsx @@ -0,0 +1,70 @@ +import React, { useState } from 'react' +import { Head, router } from '@inertiajs/react' +import CustomerLayout from '@/Layouts/CustomerLayout' +import { HiChevronLeft } from 'react-icons/hi2' + +export default function Index({ + auth: { user }, + notification: { data, next_page_url }, +}) { + const [_notification, setCoins] = useState(data) + + const handleNextPage = () => { + router.get( + next_page_url, + {}, + { + replace: true, + preserveState: true, + only: ['notification'], + onSuccess: (res) => { + setCoins(_notification.concat(res.props.notification.data)) + }, + } + ) + } + + return ( + + +
+
{ + router.get(route('home.index')) + }} + > + +
+
Notifikasi
+
+
+ {_notification.map((notification) => ( +
+
+
+ {notification.format_created_at} +
+
+ {notification.description} +
+
+
+ ))} + {next_page_url !== null && ( +
+ Load more +
+ )} +
+
+
+
+ ) +} diff --git a/resources/js/Customer/Index/UserBanner.jsx b/resources/js/Customer/Index/UserBanner.jsx index ae4db45..78663ca 100644 --- a/resources/js/Customer/Index/UserBanner.jsx +++ b/resources/js/Customer/Index/UserBanner.jsx @@ -1,8 +1,12 @@ import React from 'react' import { HiOutlineCash, HiOutlineBell } from 'react-icons/hi' import BalanceBanner from './BalanceBanner' +import { router, usePage } from '@inertiajs/react' export default function UserBanner({ user }) { + const { + props: { notification_count }, + } = usePage() return (
{/* user */} @@ -16,11 +20,16 @@ export default function UserBanner({ user }) {
-
+
{ + router.get(route('notification.index')) + }} + >
- 0 + {notification_count}
diff --git a/resources/js/Customer/Profile/Index.jsx b/resources/js/Customer/Profile/Index.jsx index c3ece33..dc9c047 100644 --- a/resources/js/Customer/Profile/Index.jsx +++ b/resources/js/Customer/Profile/Index.jsx @@ -13,7 +13,7 @@ import { useModalState } from '@/hooks' import ModalConfirm from '@/Components/ModalConfirm' import BalanceBanner from '../Index/BalanceBanner' -export default function Index({ auth: { user } }) { +export default function Index({ auth: { user }, notification_count }) { const confirmModal = useModalState() const handleLogoutClick = () => { @@ -56,11 +56,16 @@ export default function Index({ auth: { user } }) {
-
+
{ + router.get(route('notification.index')) + }} + >
- 1 + {notification_count}
@@ -127,7 +132,12 @@ export default function Index({ auth: { user } }) {
Transaksi
-
+
{ + router.get(route('notification.index')) + }} + >
Notifikasi
diff --git a/resources/js/Layouts/AuthenticatedLayout.jsx b/resources/js/Layouts/AuthenticatedLayout.jsx index d4b6dff..364294a 100644 --- a/resources/js/Layouts/AuthenticatedLayout.jsx +++ b/resources/js/Layouts/AuthenticatedLayout.jsx @@ -1,19 +1,35 @@ -import React, { useState, useEffect } from 'react'; -import { ToastContainer, toast } from 'react-toastify'; -import ApplicationLogo from '@/Components/Defaults/ApplicationLogo'; -import Dropdown from '@/Components/Defaults/Dropdown'; -import { Link } from '@inertiajs/react'; -import { Breadcrumb } from 'flowbite-react'; +import React, { useState, useEffect } from 'react' +import { ToastContainer, toast } from 'react-toastify' +import ApplicationLogo from '@/Components/Defaults/ApplicationLogo' +import Dropdown from '@/Components/Defaults/Dropdown' +import { Link, usePage } from '@inertiajs/react' +import { Breadcrumb } from 'flowbite-react' import { HiMenu, HiChevronDown, HiHome } from 'react-icons/hi' -import { router } from '@inertiajs/react'; -import SidebarNav from './Partials/SidebarNav'; +import { router } from '@inertiajs/react' +import SidebarNav from './Partials/SidebarNav' +import { HiOutlineBell } from 'react-icons/hi2' -export default function Authenticated({ auth, children, flash, page = '', action = ''}) { - const [showingNavigationDropdown, setShowingNavigationDropdown] = useState(false); +export default function Authenticated({ + auth, + children, + flash, + page = '', + action = '', +}) { + const { + props: { count_unread_notifications, notifications }, + } = usePage() + const [showingNavigationDropdown, setShowingNavigationDropdown] = + useState(false) + + const handleNotification = (notif) => { + fetch(route('api.notification.update', notif)) + router.get(route(route().current())) + } useEffect(() => { if (flash.message !== null) { - toast(flash.message.message, {type: flash.message.type}) + toast(flash.message.message, { type: flash.message.type }) } }, [flash]) @@ -28,10 +44,63 @@ export default function Authenticated({ auth, children, flash, page = '', action
-
+
+ + +
+ +
+
+ {count_unread_notifications} +
+
+
+
+ + {notifications.map((notif) => ( +
+ handleNotification(notif) + } + key={notif.id} + > + {notif.description} +
+ ))} + {notifications.length > 0 && ( +
+
+ router.get( + route( + 'notifications.index' + ) + ) + } + > + lihat semua +
+
+ handleNotification() + } + > + tandai semua dibaca +
+
+ )} +
+
+
@@ -41,14 +110,22 @@ export default function Authenticated({ auth, children, flash, page = '', action className="inline-flex items-center px-3 py-2 border border-transparent text-sm leading-4 font-medium rounded-md text-gray-500 bg-white hover:text-gray-700 focus:outline-none transition ease-in-out duration-150 dark:bg-gray-700 dark:hover:text-gray-50 dark:text-gray-200 gap-2" > {auth.user.name} - + - Profile - + + Profile + + Log Out @@ -58,45 +135,48 @@ export default function Authenticated({ auth, children, flash, page = '', action
- -
-
- +
+
+
-
+
{page !== '' && ( - + router.visit(route('dashboard'))} icon={HiHome} > -

{page}

+

{page}

{action !== '' && ( - - {action} - + {action} )}
)} -
- {children} -
+
{children}
- ); + ) } diff --git a/resources/js/Pages/Dashboard.jsx b/resources/js/Pages/Dashboard.jsx index 255e7de..7ad35b0 100644 --- a/resources/js/Pages/Dashboard.jsx +++ b/resources/js/Pages/Dashboard.jsx @@ -103,7 +103,7 @@ export default function Dashboard(props) {
-
+
Total Voucher @@ -171,8 +171,8 @@ export default function Dashboard(props) {
-
-
+
+
Penjualan
@@ -205,7 +205,7 @@ export default function Dashboard(props) {
-
+
Deposit Hari Ini
diff --git a/resources/js/Pages/Notification/Index.jsx b/resources/js/Pages/Notification/Index.jsx new file mode 100644 index 0000000..084745c --- /dev/null +++ b/resources/js/Pages/Notification/Index.jsx @@ -0,0 +1,110 @@ +import React from 'react' +import { Head, router } from '@inertiajs/react' +import { useModalState } from '@/hooks' + +import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout' +import Pagination from '@/Components/Pagination' +import { HiPencilSquare } from 'react-icons/hi2' +import { HiPencilAlt } from 'react-icons/hi' + +export default function Index(props) { + const { + query: { links, data }, + } = props + + const formModal = useModalState() + const handleNotification = (notif) => { + fetch(route('api.notification.update', notif)) + router.get(route(route().current())) + } + return ( + + + +
+
+
+
+ {/* {canCreate && ( + + )} */} +
+
+
+
+ + + + + + + + {data.map((notification) => ( + + + + + + ))} + +
+ Deskripsi + + Dibaca + +
+ {notification.description} + + {+notification.is_read === 1 + ? 'Sudah dibaca' + : 'Belum dibaca'} + + +
+ handleNotification( + notification + ) + } + > + Tandai dibaca +
+
+
+
+ +
+
+
+
+
+ + ) +} diff --git a/resources/js/Pages/Voucher/Index.jsx b/resources/js/Pages/Voucher/Index.jsx index 2a89a0c..3607280 100644 --- a/resources/js/Pages/Voucher/Index.jsx +++ b/resources/js/Pages/Voucher/Index.jsx @@ -10,6 +10,7 @@ import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout' import Pagination from '@/Components/Pagination' import ModalConfirm from '@/Components/ModalConfirm' import SearchInput from '@/Components/SearchInput' +import LocationSelectionInput from '../Location/SelectionInput' import { hasPermission } from '@/utils' export default function Index(props) { @@ -18,8 +19,9 @@ export default function Index(props) { auth, } = props + const [location, setLocation] = useState(null) const [search, setSearch] = useState('') - const preValue = usePrevious(search) + const preValue = usePrevious(`${search}${location}`) const confirmModal = useModalState() @@ -34,19 +36,19 @@ export default function Index(props) { } } - const params = { q: search } + const params = { q: search, location_id: location } useEffect(() => { if (preValue) { router.get( route(route().current()), - { q: search }, + { q: search, location_id: location }, { replace: true, preserveState: true, } ) } - }, [search]) + }, [search, location]) const canCreate = hasPermission(auth, 'create-voucher') const canUpdate = hasPermission(auth, 'update-voucher') @@ -78,7 +80,12 @@ export default function Index(props) {
)} -
+
+ setLocation(id)} + placeholder={'filter lokasi'} + /> setSearch(e.target.value)} value={search} diff --git a/routes/admin.php b/routes/admin.php index 82f0da0..ea78f7d 100644 --- a/routes/admin.php +++ b/routes/admin.php @@ -1,6 +1,7 @@ name('sale.index'); Route::get('/sales/{sale}', [SaleController::class, 'show'])->name('sale.show'); + + // notification + Route::get('/notifications', [NotificationController::class, 'index'])->name('notifications.index'); }); }); diff --git a/routes/api.php b/routes/api.php index db50ee6..252b0ca 100644 --- a/routes/api.php +++ b/routes/api.php @@ -4,6 +4,7 @@ use App\Http\Controllers\Api\LocationController; use App\Http\Controllers\Api\RoleController; use App\Http\Controllers\Customer\DepositController; use App\Http\Controllers\Api\CustomerController; +use App\Http\Controllers\Api\NotificationController; use Illuminate\Http\Request; use Illuminate\Support\Facades\Route; @@ -26,6 +27,7 @@ Route::middleware('auth:sanctum')->get('/user', function (Request $request) { Route::get('/roles', [RoleController::class, 'index'])->name('api.role.index'); Route::get('/locations', [LocationController::class, 'index'])->name('api.location.index'); Route::get('/customers', [CustomerController::class, 'index'])->name('api.customer.index'); +Route::get('/notifications/{notif?}', [NotificationController::class, 'update'])->name('api.notification.update'); // midtrans Route::post('mindtrans/notification', [DepositController::class, 'mindtrans_notification'])->name('api.midtrans.notification'); diff --git a/routes/web.php b/routes/web.php index 007974b..e207874 100644 --- a/routes/web.php +++ b/routes/web.php @@ -63,6 +63,9 @@ Route::middleware(['http_secure_aware', 'guard_should_customer', 'inertia.custom // transaction Route::get('sale/trx', [TransactionController::class, 'index'])->name('transactions.index'); Route::get('sale/trx/{sale}', [TransactionController::class, 'show'])->name('transactions.show'); + + // notification + Route::get('notifications', [HomeController::class, 'notification'])->name('notification.index'); }); Route::middleware('guest:customer')->group(function () {