diff --git a/TODO.md b/TODO.md index d2e9de8..ccb4872 100644 --- a/TODO.md +++ b/TODO.md @@ -16,7 +16,7 @@ # Back Office - [ ] tambah biaya admin di deposit manual transfer -- [ ] info di ubah jadi html +- [x] info di ubah jadi html - [ ] tambahan detail customer untuk detail mitra wbb - [ ] detail customer level untuk tampilan screen level customer di depan - [ ] rombak fitur affiliasi diff --git a/app/Http/Controllers/AccountController.php b/app/Http/Controllers/AccountController.php index d9712f7..b20dd28 100644 --- a/app/Http/Controllers/AccountController.php +++ b/app/Http/Controllers/AccountController.php @@ -16,6 +16,11 @@ class AccountController extends Controller ]); } + public function create() + { + return inertia('Account/Form'); + } + public function store(Request $request) { $request->validate([ @@ -23,16 +28,29 @@ class AccountController extends Controller 'bank_name' => 'required|string', 'holder_name' => 'required|string', 'account_number' => 'required|string', + 'logo' => 'required|image', ]); + $file = $request->file('logo'); + $file->store('uploads', 'public'); + Account::create([ 'name' => $request->name, 'bank_name' => $request->bank_name, 'holder_name' => $request->holder_name, 'account_number' => $request->account_number, + 'logo' => $file->hashName('uploads'), ]); - session()->flash('message', ['type' => 'success', 'message' => 'Item has been saved']); + return redirect()->route('account.index') + ->with('message', ['type' => 'success', 'message' => 'Item has been saved']); + } + + public function edit(Account $account) + { + return inertia('Account/Form', [ + 'account' => $account + ]); } public function update(Request $request, Account $account) @@ -42,8 +60,16 @@ class AccountController extends Controller 'bank_name' => 'required|string', 'holder_name' => 'required|string', 'account_number' => 'required|string', + 'logo' => 'nullable|image', ]); + + if ($request->hasFile('logo')) { + $file = $request->file('logo'); + $file->store('uploads', 'public'); + $account->fill(['logo' => $file->hashName('uploads')]); + } + $account->update([ 'name' => $request->name, 'bank_name' => $request->bank_name, @@ -51,7 +77,8 @@ class AccountController extends Controller 'account_number' => $request->account_number, ]); - session()->flash('message', ['type' => 'success', 'message' => 'Item has been updated']); + return redirect()->route('account.index') + ->with('message', ['type' => 'success', 'message' => 'Item has been updated']); } public function destroy(Account $account) diff --git a/app/Http/Controllers/InfoController.php b/app/Http/Controllers/InfoController.php index 6945901..29825ce 100644 --- a/app/Http/Controllers/InfoController.php +++ b/app/Http/Controllers/InfoController.php @@ -68,7 +68,6 @@ class InfoController extends Controller { $info->delete(); - return redirect()->route('info.index') - ->with('message', ['type' => 'success', 'message' => 'Item has beed deleted']); + session()->flash('message', ['type' => 'success', 'message' => 'Item has beed deleted']); } } diff --git a/app/Models/Account.php b/app/Models/Account.php index c59acb9..2909225 100644 --- a/app/Models/Account.php +++ b/app/Models/Account.php @@ -2,6 +2,8 @@ namespace App\Models; +use Illuminate\Database\Eloquent\Casts\Attribute; + class Account extends Model { protected $fillable = [ @@ -12,4 +14,15 @@ class Account extends Model 'logo', 'admin_fee', ]; + + protected $appends = [ + 'logo_url', + ]; + + protected function logoUrl(): Attribute + { + return Attribute::make(get: function () { + return asset($this->logo); + }); + } } diff --git a/database/seeders/DummySeeder.php b/database/seeders/DummySeeder.php index 754cff2..369d35b 100644 --- a/database/seeders/DummySeeder.php +++ b/database/seeders/DummySeeder.php @@ -62,8 +62,8 @@ class DummySeeder extends Seeder public function account() { $banks = [ - ['name' => 'BRI', 'bank_name' => 'Bank Rakyat Indonesia', 'holder_name' => 'Aji Kamaludin', 'account_number' => '187391738129'], - ['name' => 'Jago', 'bank_name' => 'Bank Jago', 'holder_name' => 'Aji Kamaludin', 'account_number' => '718297389172'], + ['name' => 'BTPN', 'bank_name' => 'BTPN', 'holder_name' => 'Aji Kamaludin', 'account_number' => '187391738129', 'logo' => 'sample/logo-jenius.png'], + ['name' => 'Jago', 'bank_name' => 'Bank Jago', 'holder_name' => 'Aji Kamaludin', 'account_number' => '718297389172', 'logo' => 'sample/logo-jago.png'], ]; foreach ($banks as $bank) { @@ -72,6 +72,7 @@ class DummySeeder extends Seeder 'bank_name' => $bank['bank_name'], 'holder_name' => $bank['holder_name'], 'account_number' => $bank['account_number'], + 'logo' => $bank['logo'] ]); } } diff --git a/public/sample/logo-jago.png b/public/sample/logo-jago.png new file mode 100644 index 0000000..1544661 Binary files /dev/null and b/public/sample/logo-jago.png differ diff --git a/public/sample/logo-jenius.png b/public/sample/logo-jenius.png new file mode 100644 index 0000000..18db631 Binary files /dev/null and b/public/sample/logo-jenius.png differ diff --git a/resources/js/Layouts/Partials/routes.js b/resources/js/Layouts/Partials/routes.js index 116338f..a9a4b77 100644 --- a/resources/js/Layouts/Partials/routes.js +++ b/resources/js/Layouts/Partials/routes.js @@ -5,6 +5,9 @@ import { HiUserGroup, HiInformationCircle, HiCog, + HiOutlineCash, + HiOutlineTable, + HiCash, } from 'react-icons/hi' import { HiArchiveBox, @@ -157,12 +160,35 @@ export default [ ], }, { - name: 'Bank Akun', + name: 'Akun Pembayaran', show: true, - icon: HiBanknotes, - route: route('account.index'), - active: 'account.*', - permission: 'view-account', + icon: HiOutlineCash, + items: [ + { + name: 'Bank Akun', + show: true, + icon: HiBanknotes, + route: route('account.index'), + active: 'account.*', + permission: 'view-account', + }, + { + name: 'Payment Gateway', + show: true, + icon: HiOutlineTable, + route: route('account.index'), + active: 'account.pg', + permission: 'view-account', + }, + { + name: 'Cash / Setor Tunai', + show: true, + icon: HiCash, + route: route('account.index'), + active: 'account.st', + permission: 'view-account', + }, + ], }, { name: 'Setting', diff --git a/resources/js/Pages/Account/Form.jsx b/resources/js/Pages/Account/Form.jsx new file mode 100644 index 0000000..e202248 --- /dev/null +++ b/resources/js/Pages/Account/Form.jsx @@ -0,0 +1,115 @@ +import React, { useEffect } from 'react' +import { isEmpty } from 'lodash' + +import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout' +import FormInput from '@/Components/FormInput' +import FormFile from '@/Components/FormFile' +import Button from '@/Components/Button' +import { Head, useForm } from '@inertiajs/react' + +export default function Form(props) { + const { account } = props + + const { data, setData, post, processing, errors } = useForm({ + name: '', + bank_name: '', + holder_name: '', + account_number: '', + logo: null, + logo_url: '' + }) + + const handleOnChange = (event) => { + setData( + event.target.name, + event.target.type === 'checkbox' + ? event.target.checked + ? 1 + : 0 + : event.target.value + ) + } + const handleSubmit = () => { + if (isEmpty(account) === false) { + post(route('account.update', account)) + return + } + post(route('account.store')) + } + + useEffect(() => { + if (isEmpty(account) === false) { + setData({ + name: account.name, + bank_name: account.bank_name, + holder_name: account.holder_name, + account_number: account.account_number, + logo_url: account.logo_url + }) + } + }, [account]) + + return ( + + + +
+
+
+
Bank Akun
+ + + + + setData('logo', e.target.files[0])} + error={errors.logo} + preview={ + isEmpty(data.logo_url) === false && ( + preview + ) + } + /> +
+ +
+
+
+
+
+ ) +} diff --git a/resources/js/Pages/Account/Index.jsx b/resources/js/Pages/Account/Index.jsx index c5c0e40..945ed10 100644 --- a/resources/js/Pages/Account/Index.jsx +++ b/resources/js/Pages/Account/Index.jsx @@ -1,7 +1,5 @@ -import React, { useEffect, useState } from 'react' -import { router } from '@inertiajs/react' -import { usePrevious } from 'react-use' -import { Head } from '@inertiajs/react' +import React from 'react' +import { Head, Link, router } from '@inertiajs/react' import { Button, Dropdown } from 'flowbite-react' import { HiPencil, HiTrash } from 'react-icons/hi' import { useModalState } from '@/hooks' @@ -50,12 +48,9 @@ export default function Account(props) {
{canCreate && ( - + + + )}
@@ -81,6 +76,12 @@ export default function Account(props) { > Nomor Rekening + + Logo + {account.account_number} + + bank logo alt + {canUpdate && ( - - toggleFormModal( - account - ) - } - > -
+ +
Ubah
-
+
)} {canDelete && ( diff --git a/resources/js/Pages/Info/FormModal.jsx b/resources/js/Pages/Info/FormModal.jsx deleted file mode 100644 index 3bda590..0000000 --- a/resources/js/Pages/Info/FormModal.jsx +++ /dev/null @@ -1,95 +0,0 @@ -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, put, processing, errors, reset, clearErrors } = - useForm({ - info: '', - is_publish: 1, - }) - - 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 info = modalState.data - if (info !== null) { - put(route('info.update', info), { - onSuccess: () => handleClose(), - }) - return - } - post(route('info.store'), { - onSuccess: () => handleClose(), - }) - } - - useEffect(() => { - const info = modalState.data - if (isEmpty(info) === false) { - setData({ - info: info.title, - is_publish: info.is_publish, - }) - return - } - }, [modalState]) - - return ( - - -
-
Publish
- -
-
- - -
-
- ) -} diff --git a/resources/js/Pages/Info/Index.jsx b/resources/js/Pages/Info/Index.jsx index e38ca52..c3fd371 100644 --- a/resources/js/Pages/Info/Index.jsx +++ b/resources/js/Pages/Info/Index.jsx @@ -1,17 +1,14 @@ -import React, { useEffect, useState } from 'react' +import React from 'react' 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 { useModalState } from '@/hooks' +import { hasPermission } from '@/utils' 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 { hasPermission } from '@/utils' export default function Info(props) { const { diff --git a/routes/admin.php b/routes/admin.php index 6c0cb55..ebdede2 100644 --- a/routes/admin.php +++ b/routes/admin.php @@ -79,8 +79,10 @@ Route::middleware(['http_secure_aware', 'inertia.admin']) // Account Route::get('/accounts', [AccountController::class, 'index'])->name('account.index'); + Route::get('/accounts/create', [AccountController::class, 'create'])->name('account.create'); Route::post('/accounts', [AccountController::class, 'store'])->name('account.store'); - Route::put('/accounts/{account}', [AccountController::class, 'update'])->name('account.update'); + Route::get('/accounts/{account}', [AccountController::class, 'edit'])->name('account.edit'); + Route::post('/accounts/{account}', [AccountController::class, 'update'])->name('account.update'); Route::delete('/accounts/{account}', [AccountController::class, 'destroy'])->name('account.destroy'); // upload