bit fix filter modal

dev
Aji Kamaludin 1 year ago
parent f1ed0f8808
commit cf943e30b4
No known key found for this signature in database
GPG Key ID: 19058F67F0083AD3

@ -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

@ -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,

@ -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',

@ -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) {
</Link>
)}
<div className="flex flex-col gap-1 items-end">
<div className="max-w-md">
<SearchInput
onChange={handleSearchChange}
value={search.q}
/>
</div>
<div className="flex flex-row gap-1">
<div className="w-full max-w-md">
<LevelSelectionInput
itemSelected={level}
onItemSelected={(id) =>
setLevel(id)
}
placeholder={'filter level'}
/>
<div
className="px-3 py-2 rounded-md border bg-gray-600 border-gray-700 hover:bg-gray-500"
onClick={() => filterModal.toggle()}
>
<HiOutlineFilter className="w-5 h-5 text-white" />
</div>
<div className="w-full max-w-md">
<LocationSelectionInput
itemSelected={location}
onItemSelected={(id) =>
setLocation(id)
}
placeholder={'filter lokasi'}
<div>
<SearchInput
onChange={handleSearchChange}
value={search.q}
/>
</div>
</div>
@ -386,6 +376,7 @@ export default function Customer(props) {
</div>
<ModalConfirm modalState={confirmModal} onConfirm={onDelete} />
<ModalFilter state={filterModal} handleFilter={handleFilter} />
</AuthenticatedLayout>
)
}

@ -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 (
<Modal isOpen={state.isOpen} toggle={state.toggle} title={'Filter'}>
<div>Lokasi: </div>
<div className="p-2 border rounded-md">
<div className="flex flex-row w-full gap-1 flex-wrap mb-2">
{locations.map((location) => (
<div
className="px-2 py-1 border border-gray-300 rounded-md bg-gray-100 flex flex-row items-center gap-1"
key={location.id}
>
<div className="">{location.name}</div>
<div onClick={() => handleRemoveLocation(location)}>
<HiXCircle className="text-red-600 w-5 h-5" />
</div>
</div>
))}
</div>
<LocationSelectionInput
placeholder="pilih lokasi"
type="item"
itemSelected={null}
onItemSelected={(item) => handleAddLocation(item)}
/>
</div>
<div className="mb-1 text-sm">Level : </div>
{levels.map((level) => (
<Checkbox
key={level.id}
label={level.name}
value={isLevelChecked(level)}
onChange={(e) => handleLevelChecked(level, e)}
/>
))}
<div className="mb-2"></div>
<Button onClick={() => handleClickFilter()}>Filter</Button>
</Modal>
)
}

@ -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) {
</Link>
)}
<div className="flex flex-col gap-1 items-end">
<div className="max-w-md">
<SearchInput
onChange={handleSearchChange}
value={search.q}
/>
</div>
<div className="flex flex-row gap-1">
<div className="w-full max-w-md">
<LevelSelectionInput
itemSelected={level}
onItemSelected={(id) =>
setLevel(id)
}
placeholder={'filter level'}
only={['gold', 'platinum']}
/>
<div
className="px-3 py-2 rounded-md border bg-gray-600 border-gray-700 hover:bg-gray-500"
onClick={() => filterModal.toggle()}
>
<HiOutlineFilter className="w-5 h-5 text-white" />
</div>
<div className="w-full max-w-md">
<LocationSelectionInput
itemSelected={location}
onItemSelected={(id) =>
setLocation(id)
}
placeholder={'filter lokasi'}
<div>
<SearchInput
onChange={handleSearchChange}
value={search.q}
/>
</div>
</div>
@ -409,6 +398,7 @@ export default function Customer(props) {
</div>
</div>
<ModalConfirm modalState={confirmModal} onConfirm={onDelete} />
<ModalFilter state={filterModal} handleFilter={handleFilter} />
</AuthenticatedLayout>
)
}

@ -43,7 +43,6 @@ export default function ModalFilter(props) {
return (
<Modal isOpen={state.isOpen} toggle={state.toggle} title={'Filter'}>
{/* TODO: buat modal dengan filter, lokasi multiple, range tanggal, type pembayaran */}
<div>Lokasi: </div>
<div className="p-2 border rounded-md">
<div className="flex flex-row w-full gap-1 flex-wrap mb-2">

Loading…
Cancel
Save