diff --git a/TODO.md b/TODO.md index ab2ee25..c5adff5 100644 --- a/TODO.md +++ b/TODO.md @@ -38,7 +38,7 @@ tambah batas bayar -> after save redirect history penambahan batas bayar) - [x] menu mitra wbb ada tombol tambah mitra untuk registrasi dengan full form - [x] menu pembayaran hutang [admin dapat melakukan pembayaran hutang dari customer, atau mengkonfirmasi pembayaran yang dilakukan custoemr] +- [x] ubah filter di mitra list dan customer list menjadi seperti di sale index - [ ] untuk detail mitra nanti akan ada button untuk (transaksi mitra dengan cakupan: pembelian voucher, pembayaran hutang, topuplimit, penambahan batas bayar, history deposit) -- [ ] ubah filter di mitra list dan customer list menjadi seperti di sale index - [ ] tambah floating button untuk notifikasi deposit (angka saja), di dashboard tambahkan list deposit terbaru diff --git a/app/Http/Controllers/Admin/CustomerController.php b/app/Http/Controllers/Admin/CustomerController.php index 83d97c3..ad0fc53 100644 --- a/app/Http/Controllers/Admin/CustomerController.php +++ b/app/Http/Controllers/Admin/CustomerController.php @@ -31,23 +31,30 @@ class CustomerController extends Controller }); } - if ($request->location_id != '') { - $query->whereHas('locationFavorites', fn ($q) => $q->where('id', $request->location_id)); + if ($request->location_ids != '') { + $query->whereHas('locationFavorites', fn ($q) => $q->whereIn('id', $request->location_ids)); } - if ($request->level_id != '') { - $query->where('customer_level_id', $request->level_id); + if ($request->levels != '') { + $query->whereIn('customer_level_id', $request->levels); } + $sortBy = 'updated_at'; + $sortRule = 'desc'; if ($request->sortBy != '' && $request->sortRule != '') { - $query->orderBy($request->sortBy, $request->sortRule); - } else { - $query->orderBy('updated_at', 'desc'); + $sortBy = $request->sortBy; + $sortRule = $request->sortRule; } + $query->orderBy($sortBy, $sortRule); + return inertia('Customer/Index', [ 'query' => $query->paginate(), 'stats' => $stats, + 'levels' => CustomerLevel::all(), + '_search' => $request->q, + '_sortBy' => $sortBy, + '_sortOrder' => $sortRule, ]); } @@ -108,8 +115,8 @@ class CustomerController extends Controller public function update(Request $request, Customer $customer) { $request->validate([ - 'email' => 'nullable|email|unique:customers,email,'.$customer->id, - 'username' => 'required|string|min:5|alpha_dash|unique:customers,username,'.$customer->id, + 'email' => 'nullable|email|unique:customers,email,' . $customer->id, + 'username' => 'required|string|min:5|alpha_dash|unique:customers,username,' . $customer->id, 'password' => 'nullable|string|min:8', 'name' => 'required|string', 'fullname' => 'required|string', @@ -189,7 +196,6 @@ class CustomerController extends Controller 'items.*.type' => 'required|in:text,file', 'items.*.value' => 'nullable|string', ]); - // $partner = CustomerAsDataPartner::updateOrCreate([ 'customer_id' => $customer->id, diff --git a/app/Http/Controllers/Admin/CustomerMitraController.php b/app/Http/Controllers/Admin/CustomerMitraController.php index c002713..ae76626 100644 --- a/app/Http/Controllers/Admin/CustomerMitraController.php +++ b/app/Http/Controllers/Admin/CustomerMitraController.php @@ -51,23 +51,30 @@ class CustomerMitraController extends Controller }); } - if ($request->location_id != '') { - $query->whereHas('locationFavorites', fn ($q) => $q->where('id', $request->location_id)); + if ($request->location_ids != '') { + $query->whereHas('locationFavorites', fn ($q) => $q->whereIn('id', $request->location_ids)); } - if ($request->level_id != '') { - $query->where('customer_level_id', $request->level_id); + if ($request->levels != '') { + $query->whereIn('customer_level_id', $request->levels); } + $sortBy = 'updated_at'; + $sortRule = 'desc'; if ($request->sortBy != '' && $request->sortRule != '') { - $query->orderBy($request->sortBy, $request->sortRule); - } else { - $query->orderBy('updated_at', 'desc'); + $sortBy = $request->sortBy; + $sortRule = $request->sortRule; } + $query->orderBy($sortBy, $sortRule); + return inertia('CustomerMitra/Index', [ 'query' => $query->paginate(), 'stats' => $stats, + 'levels' => CustomerLevel::all(), + '_search' => $request->q, + '_sortBy' => $sortBy, + '_sortOrder' => $sortRule, ]); } @@ -213,8 +220,8 @@ class CustomerMitraController extends Controller public function update(Request $request, Customer $customer) { $request->validate([ - 'email' => 'nullable|email|unique:customers,email,'.$customer->id, - 'username' => 'required|string|min:5|alpha_dash|unique:customers,username,'.$customer->id, + 'email' => 'nullable|email|unique:customers,email,' . $customer->id, + 'username' => 'required|string|min:5|alpha_dash|unique:customers,username,' . $customer->id, 'password' => 'nullable|string|min:8', 'name' => 'required|string', 'fullname' => 'required|string', diff --git a/resources/js/Pages/Customer/Index.jsx b/resources/js/Pages/Customer/Index.jsx index cefd842..919e32e 100644 --- a/resources/js/Pages/Customer/Index.jsx +++ b/resources/js/Pages/Customer/Index.jsx @@ -3,7 +3,7 @@ import { Link, router } from '@inertiajs/react' import { usePrevious } from 'react-use' import { Head } from '@inertiajs/react' import { Button, Dropdown } from 'flowbite-react' -import { HiPencil, HiTrash } from 'react-icons/hi' +import { HiOutlineFilter, HiPencil, HiTrash } from 'react-icons/hi' import { useModalState } from '@/hooks' import { formatIDR, hasPermission } from '@/utils' @@ -11,9 +11,8 @@ 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 LevelSelectionInput from '../CustomerLevel/SelectionInput' import ThSort from '@/Components/ThSortComponent' +import ModalFilter from './ModalFilter' export default function Customer(props) { const { @@ -25,16 +24,15 @@ export default function Customer(props) { _sortOrder, } = props - const [location, setLocation] = useState(null) - const [level, setLevel] = useState(null) const [search, setSearch] = useState({ q: _search, sortBy: _sortBy, sortOrder: _sortOrder, }) - const preValue = usePrevious(`${search}${location}${level}`) + const preValue = usePrevious(`${search}`) const confirmModal = useModalState() + const filterModal = useModalState() const handleDeleteClick = (customer) => { confirmModal.setData(customer) @@ -70,19 +68,23 @@ export default function Customer(props) { }) } - const params = { q: search, location_id: location, level_id: level } + const handleFilter = (filter) => { + setSearch({ ...search, ...filter }) + } + + const params = { ...search } useEffect(() => { if (preValue) { router.get( route(route().current()), - { ...search, location_id: location, level_id: level }, + { ...search }, { replace: true, preserveState: true, } ) } - }, [search, location, level]) + }, [search]) const canCreate = hasPermission(auth, 'create-customer') const canUpdate = hasPermission(auth, 'update-customer') @@ -132,29 +134,17 @@ export default function Customer(props) { )}
-
- -
-
- - setLevel(id) - } - placeholder={'filter level'} - /> +
filterModal.toggle()} + > +
-
- - setLocation(id) - } - placeholder={'filter lokasi'} +
+
@@ -386,6 +376,7 @@ export default function Customer(props) {
+ ) } diff --git a/resources/js/Pages/Customer/ModalFilter.jsx b/resources/js/Pages/Customer/ModalFilter.jsx new file mode 100644 index 0000000..5440802 --- /dev/null +++ b/resources/js/Pages/Customer/ModalFilter.jsx @@ -0,0 +1,94 @@ +import React, { useState } from 'react' +import { HiXCircle } from 'react-icons/hi2' + +import Modal from '@/Components/Modal' +import Button from '@/Components/Button' +import LocationSelectionInput from '../Location/SelectionInput' +import Checkbox from '@/Components/Checkbox' +import { usePage } from '@inertiajs/react' + +export default function ModalFilter(props) { + const { + props: { levels }, + } = usePage() + const { state, handleFilter } = props + + const [locations, setLocations] = useState([]) + const [checkedLevels, setCheckedLevels] = useState([]) + + const handleAddLocation = (location) => { + const isExists = locations.find((l) => l.id === location.id) + if (!isExists) { + setLocations(locations.concat(location)) + } + } + + const handleRemoveLocation = (location) => { + setLocations(locations.filter((l) => l.id !== location.id)) + } + + const handleLevelChecked = (level, e) => { + const isExists = isLevelChecked(level) + if (!isExists && e.target.checked) { + setCheckedLevels(checkedLevels.concat(level)) + return + } + + setCheckedLevels(checkedLevels.filter((l) => l.id !== level.id)) + } + + const isLevelChecked = (level) => { + const isExists = checkedLevels.find((l) => l.id === level.id) + if (isExists) { + return true + } + return false + } + + const handleClickFilter = () => { + handleFilter({ + location_ids: locations.map((l) => l.id), + levels: checkedLevels.map((l) => l.id), + }) + state.toggle() + } + + return ( + +
Lokasi:
+
+
+ {locations.map((location) => ( +
+
{location.name}
+
handleRemoveLocation(location)}> + +
+
+ ))} +
+ handleAddLocation(item)} + /> +
+
Level :
+ {levels.map((level) => ( + handleLevelChecked(level, e)} + /> + ))} + +
+ +
+ ) +} diff --git a/resources/js/Pages/CustomerMitra/Index.jsx b/resources/js/Pages/CustomerMitra/Index.jsx index 4971ef4..4316bc9 100644 --- a/resources/js/Pages/CustomerMitra/Index.jsx +++ b/resources/js/Pages/CustomerMitra/Index.jsx @@ -3,7 +3,8 @@ import { Link, router } from '@inertiajs/react' import { usePrevious } from 'react-use' import { Head } from '@inertiajs/react' import { Button, Dropdown } from 'flowbite-react' -import { HiPencil, HiTrash } from 'react-icons/hi' +import { HiOutlineFilter, HiPencil, HiTrash } from 'react-icons/hi' +import { HiEye } from 'react-icons/hi2' import { useModalState } from '@/hooks' import { formatIDR, hasPermission } from '@/utils' @@ -11,10 +12,8 @@ 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 LevelSelectionInput from '../CustomerLevel/SelectionInput' import ThSort from '@/Components/ThSortComponent' -import { HiEye } from 'react-icons/hi2' +import ModalFilter from '../Customer/ModalFilter' export default function Customer(props) { const { @@ -26,16 +25,15 @@ export default function Customer(props) { _sortOrder, } = props - const [location, setLocation] = useState(null) - const [level, setLevel] = useState(null) const [search, setSearch] = useState({ q: _search, sortBy: _sortBy, sortOrder: _sortOrder, }) - const preValue = usePrevious(`${search}${location}${level}`) + const preValue = usePrevious(`${search}`) const confirmModal = useModalState() + const filterModal = useModalState() const handleDeleteClick = (customer) => { confirmModal.setData(customer) @@ -71,19 +69,23 @@ export default function Customer(props) { }) } - const params = { q: search, location_id: location, level_id: level } + const handleFilter = (filter) => { + setSearch({ ...search, ...filter }) + } + + const params = { ...search } useEffect(() => { if (preValue) { router.get( route(route().current()), - { ...search, location_id: location, level_id: level }, + { ...search }, { replace: true, preserveState: true, } ) } - }, [search, location, level]) + }, [search]) const canCreate = hasPermission(auth, 'create-mitra') const canUpdate = hasPermission(auth, 'update-mitra') @@ -155,30 +157,17 @@ export default function Customer(props) { )}
-
- -
-
- - setLevel(id) - } - placeholder={'filter level'} - only={['gold', 'platinum']} - /> +
filterModal.toggle()} + > +
-
- - setLocation(id) - } - placeholder={'filter lokasi'} +
+
@@ -409,6 +398,7 @@ export default function Customer(props) {
+ ) } diff --git a/resources/js/Pages/Sale/ModalFilter.jsx b/resources/js/Pages/Sale/ModalFilter.jsx index 242b1b2..625bdfb 100644 --- a/resources/js/Pages/Sale/ModalFilter.jsx +++ b/resources/js/Pages/Sale/ModalFilter.jsx @@ -43,7 +43,6 @@ export default function ModalFilter(props) { return ( - {/* TODO: buat modal dengan filter, lokasi multiple, range tanggal, type pembayaran */}
Lokasi: