From 2f9cd2994c61ea0eb25f3d6b31ae12216021171d Mon Sep 17 00:00:00 2001 From: Aji Kamaludin Date: Sat, 3 Jun 2023 23:00:26 +0700 Subject: [PATCH] Deposit manual approve done --- TODO.md | 4 +- .../Controllers/Customer/AuthController.php | 2 +- app/Http/Controllers/DepositController.php | 51 +++++- app/Models/DepositHistory.php | 21 ++- database/seeders/PermissionSeeder.php | 4 +- resources/js/Components/FormInput.jsx | 1 + resources/js/Components/FormInputWith.jsx | 1 + resources/js/Components/Input.jsx | 2 + resources/js/Layouts/CustomerLayout.jsx | 64 +++---- resources/js/Layouts/Partials/routes.js | 11 +- .../js/Pages/DepositHistory/FormModal.jsx | 162 +++++++++++++++++ resources/js/Pages/DepositHistory/Index.jsx | 169 ++++++++++++++++++ resources/js/Pages/Home/Deposit/Detail.jsx | 4 +- resources/js/Pages/Home/Deposit/Index.jsx | 2 +- resources/js/Pages/Home/Index/VoucherCard.jsx | 2 +- routes/admin.php | 5 + 16 files changed, 455 insertions(+), 50 deletions(-) create mode 100644 resources/js/Pages/DepositHistory/FormModal.jsx create mode 100644 resources/js/Pages/DepositHistory/Index.jsx diff --git a/TODO.md b/TODO.md index bc58527..ef2d0fd 100644 --- a/TODO.md +++ b/TODO.md @@ -11,8 +11,8 @@ - [x] Import Voucher - [x] Setting Web (enable affilate, amount bonus affilate) - [x] Setting Level Customer (view levels, edit name of level,minimal saldo, max amount saldo, max hutang) -- [ ] Deposit Menu (view daftar histori deposit) -- [ ] Manual Approve Deposit +- [x] Deposit Menu (view daftar histori deposit) +- [x] Manual Approve Deposit - [ ] Setting Bonus Coin (memasukan amount bonus coin yang didapat dengan level dan harga voucher) - coin rewards - [ ] View Customer Coin History - [ ] List Customer Verification diff --git a/app/Http/Controllers/Customer/AuthController.php b/app/Http/Controllers/Customer/AuthController.php index 88ea783..642a0b5 100644 --- a/app/Http/Controllers/Customer/AuthController.php +++ b/app/Http/Controllers/Customer/AuthController.php @@ -44,7 +44,7 @@ class AuthController extends Controller } return redirect()->route('customer.login') - ->with('message', ['type' => 'error', 'message' => 'invalid credentials']); + ->with('message', ['type' => 'error', 'message' => 'Invalid credentials']); } public function signin_google() diff --git a/app/Http/Controllers/DepositController.php b/app/Http/Controllers/DepositController.php index 4f1871d..78549cc 100644 --- a/app/Http/Controllers/DepositController.php +++ b/app/Http/Controllers/DepositController.php @@ -2,15 +2,62 @@ namespace App\Http\Controllers; +use App\Models\DepositHistory; use Illuminate\Http\Request; +use Illuminate\Support\Facades\DB; +use Illuminate\Validation\Rule; class DepositController extends Controller { - public function index() + public function index(Request $request) { + $query = DepositHistory::with(['customer', 'account']) + ->where('credit', 0) + ->orderBy('is_valid', 'desc') + ->orderBy('updated_at', 'desc'); + + if ($request->q != '') { + $query->where(function ($query) use ($request) { + $query->where('description', 'like', "%$request->q%") + ->orWhereHas('customer', function ($query) use ($request) { + $query->where('fullname', 'like', "%$request->q%") + ->orWhere('email', 'like', "%$request->q%") + ->orWhere('phone', 'like', "%$request->q%"); + }); + }); + } + + if ($request->status != '') { + $query->where('is_valid', $request->status); + } + + if ($request->customer_id != '') { + $query->where('is_valid', $request->customer_id); + } + + return inertia('DepositHistory/Index', [ + 'query' => $query->paginate() + ]); } - public function update() + public function update(Request $request, DepositHistory $deposit) { + $request->validate([ + 'status' => [ + 'required', + Rule::in([DepositHistory::STATUS_VALID, DepositHistory::STATUS_REJECT]) + ] + ]); + + DB::beginTransaction(); + $deposit->update([ + 'is_valid' => $request->status, + ]); + if ($request->status === DepositHistory::STATUS_VALID) { + $deposit->update_customer_balance(); + } + DB::commit(); + + session()->flash('message', ['type' => 'success', 'message' => 'Item has beed updated']); } } diff --git a/app/Models/DepositHistory.php b/app/Models/DepositHistory.php index 43bbdb7..4d1e738 100644 --- a/app/Models/DepositHistory.php +++ b/app/Models/DepositHistory.php @@ -48,12 +48,12 @@ class DepositHistory extends Model { return Attribute::make(get: function () { return [ - self::STATUS_VALID => ['text' => 'Success', 'color' => 'bg-green-600'], - self::STATUS_WAIT_UPLOAD => ['text' => 'Upload bukti transfer', 'color' => 'bg-red-600'], - self::STATUS_WAIT_APPROVE => ['text' => 'Menunggu Approve', 'color' => 'bg-green-600'], - self::STATUS_WAIT_PAYMENT => ['text' => 'Menunggu Pembayaran', 'color' => 'bg-green-600'], - self::STATUS_INVALID => ['text' => 'Error', 'color' => 'bg-red-600'], - self::STATUS_REJECT => ['text' => 'Reject', 'color' => 'bg-red-600'], + self::STATUS_VALID => ['text' => 'Success', 'color' => 'bg-green-600', 'text_color' => 'text-green-600'], + self::STATUS_WAIT_UPLOAD => ['text' => 'Upload bukti transfer', 'color' => 'bg-red-600', 'text_color' => 'text-red-600'], + self::STATUS_WAIT_APPROVE => ['text' => 'Menunggu Approve', 'color' => 'bg-green-600', 'text_color' => 'text-green-600'], + self::STATUS_WAIT_PAYMENT => ['text' => 'Menunggu Pembayaran', 'color' => 'bg-green-600', 'text_color' => 'text-green-600'], + self::STATUS_INVALID => ['text' => 'Error', 'color' => 'bg-red-600', 'text_color' => 'text-red-600'], + self::STATUS_REJECT => ['text' => 'Reject', 'color' => 'bg-red-600', 'text_color' => 'text-red-600'], ][$this->is_valid]; }); } @@ -76,9 +76,9 @@ class DepositHistory extends Model { return Attribute::make(get: function () { if ($this->credit == 0) { - return $this->debit; + return 'Rp' . number_format($this->debit, 0, ',', '.'); } - return $this->credit; + return '-Rp' . number_format($this->credit, 0, ',', '.'); }); } @@ -94,6 +94,11 @@ class DepositHistory extends Model return $this->belongsTo(Customer::class); } + public function account() + { + return $this->belongsTo(Account::class); + } + public function update_customer_balance() { $customer = Customer::find($this->customer_id); diff --git a/database/seeders/PermissionSeeder.php b/database/seeders/PermissionSeeder.php index 562eb22..91f38f8 100644 --- a/database/seeders/PermissionSeeder.php +++ b/database/seeders/PermissionSeeder.php @@ -61,8 +61,8 @@ class PermissionSeeder extends Seeder ['id' => Str::ulid(), 'label' => 'View Setting', 'name' => 'view-setting'], - ['id' => Str::ulid(), 'label' => 'View Deposit', 'name' => 'view-deposite'], - ['id' => Str::ulid(), 'label' => 'Update Deposit', 'name' => 'update-deposite'], + ['id' => Str::ulid(), 'label' => 'View Deposit', 'name' => 'view-deposit'], + ['id' => Str::ulid(), 'label' => 'Update Deposit', 'name' => 'update-deposit'], ['id' => Str::ulid(), 'label' => 'View Coin', 'name' => 'view-coin'], ['id' => Str::ulid(), 'label' => 'Update Coin', 'name' => 'update-coin'], diff --git a/resources/js/Components/FormInput.jsx b/resources/js/Components/FormInput.jsx index 20ab80b..ff5b4af 100644 --- a/resources/js/Components/FormInput.jsx +++ b/resources/js/Components/FormInput.jsx @@ -31,6 +31,7 @@ export default function FormInput({ {leftItem} )} { if (route().current(r)) { - return 'text-blue-700 h-8 w-8' + return 'text-blue-700' } - return 'text-gray-600 h-8 w-8' + return 'text-gray-600' } return ( @@ -33,41 +34,44 @@ export default function CustomerLayout({ children }) {
handleOnClick('home.index')} > - + +
Beranda
-
- -
-
- 1 +
+
+ +
+
+ 1 +
+
Keranjang
-
- +
+ +
Transaksi
+
+
+ handleOnClick( + user !== null + ? 'customer.profile.index' + : 'customer.login' + ) + } + > + +
Menu
- {user !== null ? ( -
handleOnClick('customer.profile.index')} - > - -
- ) : ( -
handleOnClick('customer.login')} - > - -
- )}
diff --git a/resources/js/Layouts/Partials/routes.js b/resources/js/Layouts/Partials/routes.js index 9c46eae..7d24c67 100644 --- a/resources/js/Layouts/Partials/routes.js +++ b/resources/js/Layouts/Partials/routes.js @@ -8,6 +8,8 @@ import { } from 'react-icons/hi' import { HiBanknotes, + HiCurrencyDollar, + HiFaceSmile, HiMap, HiOutlineGlobeAlt, HiQuestionMarkCircle, @@ -24,7 +26,14 @@ export default [ active: 'dashboard', permission: 'view-dashboard', }, - + { + name: 'Deposit', + show: true, + icon: HiCurrencyDollar, + route: route('deposit.index'), + active: 'deposit.*', + permission: 'view-deposit', + }, { name: 'Lokasi', show: true, diff --git a/resources/js/Pages/DepositHistory/FormModal.jsx b/resources/js/Pages/DepositHistory/FormModal.jsx new file mode 100644 index 0000000..bd8a132 --- /dev/null +++ b/resources/js/Pages/DepositHistory/FormModal.jsx @@ -0,0 +1,162 @@ +import React, { useEffect } from 'react' +import Modal from '@/Components/Modal' +import { useForm } from '@inertiajs/react' +import Button from '@/Components/Button' +import FormInput from '@/Components/FormInput' +import RoleSelectionInput from '../Role/SelectionInput' + +import { isEmpty } from 'lodash' + +export default function FormModal(props) { + const { modalState } = props + const { data, setData, post, processing, errors, reset, clearErrors } = + useForm({ + amount: '', + image_prove_url: '', + status: '', + account: { + name: '', + bank_name: '', + holder_name: '', + account_number: '', + }, + payment_channel: '', + is_valid: 0, + status: '', + status_text: '', + text_color: '', + customer_name: '', + customer_phone: '', + description: '', + }) + + const handleOnChange = (event) => { + setData( + event.target.name, + event.target.type === 'checkbox' + ? event.target.checked + ? 1 + : 0 + : event.target.value + ) + } + + const handleReset = () => { + modalState.setData(null) + reset() + clearErrors() + } + + const handleClose = () => { + handleReset() + modalState.toggle() + } + + const handleSubmit = () => { + const deposit = modalState.data + post(route('deposit.update', deposit), { + onSuccess: () => handleClose(), + }) + } + + useEffect(() => { + const deposit = modalState.data + if (isEmpty(deposit) === false) { + setData({ + amount: deposit.amount, + account: deposit.account, + image_prove_url: deposit.image_prove_url, + payment_channel: deposit.payment_channel, + is_valid: deposit.is_valid, + status_text: deposit.status.text, + text_color: deposit.status.text_color, + customer_name: `${deposit.customer.name} ( ${ + deposit.customer.phone ?? deposit.customer.email + } )`, + description: deposit.description, + }) + return + } + }, [modalState]) + + return ( + + + + + + + + + + + + + + + + + + + {data.account !== null && ( + + + + + + )} + + + + + + + + + + + +
Customer:{data.customer_name}
Deskripsi:{data.description}
Metode Pembayaran:{data.payment_channel}
Bank Akun: + {data.account.name} ({data.account.bank_name}) +
Jumlah:{data.amount}
Status:{data.status_text}
+ + {isEmpty(data.image_prove_url) === false && ( +
+ +
+ )} + {+data.is_valid !== 0 && ( + <> +
+
Status
+ +
+
+ + +
+ + )} +
+ ) +} diff --git a/resources/js/Pages/DepositHistory/Index.jsx b/resources/js/Pages/DepositHistory/Index.jsx new file mode 100644 index 0000000..9c1282e --- /dev/null +++ b/resources/js/Pages/DepositHistory/Index.jsx @@ -0,0 +1,169 @@ +import React, { useEffect, useState } from 'react' +import { 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 { useModalState } from '@/hooks' + +import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout' +import Pagination from '@/Components/Pagination' +import ModalConfirm from '@/Components/ModalConfirm' +import FormModal from './FormModal' +import SearchInput from '@/Components/SearchInput' +import { formatIDR, hasPermission } from '@/utils' +import { HiEye } from 'react-icons/hi2' + +export default function Info(props) { + const { + query: { links, data }, + auth, + } = props + + const [search, setSearch] = useState('') + const preValue = usePrevious(search) + + const formModal = useModalState() + + const toggleFormModal = (deposit = null) => { + formModal.setData(deposit) + formModal.toggle() + } + + const params = { q: search } + useEffect(() => { + if (preValue) { + router.get( + route(route().current()), + { q: search }, + { + replace: true, + preserveState: true, + } + ) + } + }, [search]) + + const canUpdate = hasPermission(auth, 'update-deposit') + + return ( + + + +
+
+
+
+
+ setSearch(e.target.value)} + value={search} + /> +
+
+
+
+ + + + + + + + + + + {data.map((deposit) => ( + + + + + + + + ))} + +
+ Customer + + Deposit + + Deskripsi + + Status + +
+ {deposit.customer.name} + + {deposit.amount} + + {deposit.description} + + {deposit.status.text} + + + {canUpdate && ( + + toggleFormModal( + deposit + ) + } + > +
+ +
+ Lihat +
+
+
+ )} +
+
+
+
+ +
+
+
+
+
+ +
+ ) +} diff --git a/resources/js/Pages/Home/Deposit/Detail.jsx b/resources/js/Pages/Home/Deposit/Detail.jsx index 6851c58..85368f2 100644 --- a/resources/js/Pages/Home/Deposit/Detail.jsx +++ b/resources/js/Pages/Home/Deposit/Detail.jsx @@ -159,7 +159,7 @@ const FormUpload = () => { {accounts.map((account) => ( ))} @@ -257,7 +257,7 @@ export default function Detail({ deposit }) { {deposit.description}
- Rp {formatIDR(deposit.amount)} + {deposit.amount}
{deposit.format_created_at} diff --git a/resources/js/Pages/Home/Deposit/Index.jsx b/resources/js/Pages/Home/Deposit/Index.jsx index dd0e735..e816873 100644 --- a/resources/js/Pages/Home/Deposit/Index.jsx +++ b/resources/js/Pages/Home/Deposit/Index.jsx @@ -76,7 +76,7 @@ export default function Index({
- {formatIDR(history.amount)} + {history.amount}
{+history.is_valid !== 0 && (
+
{voucher.location.name}
diff --git a/routes/admin.php b/routes/admin.php index 892dea7..3a8fc61 100644 --- a/routes/admin.php +++ b/routes/admin.php @@ -5,6 +5,7 @@ use App\Http\Controllers\Auth\AuthenticatedSessionController; use App\Http\Controllers\BannerController; use App\Http\Controllers\CustomerController; use App\Http\Controllers\CustomerLevelController; +use App\Http\Controllers\DepositController; use App\Http\Controllers\GeneralController; use App\Http\Controllers\InfoController; use App\Http\Controllers\LocationController; @@ -103,5 +104,9 @@ Route::middleware(['http_secure_aware', 'inertia.admin']) // setting Route::get('/settings', [SettingController::class, 'index'])->name('setting.index'); Route::post('/settings', [SettingController::class, 'update'])->name('setting.update'); + + // deposit + Route::get('/deposites', [DepositController::class, 'index'])->name('deposit.index'); + Route::post('/deposites/{deposit}', [DepositController::class, 'update'])->name('deposit.update'); }); });