From 4d56b27731954d2084880ceb28adfbdfcf7b6bdb Mon Sep 17 00:00:00 2001 From: Aji Kamaludin Date: Mon, 5 Jun 2023 00:08:31 +0700 Subject: [PATCH] bit fix sale customer, verified partial, and replan for paylater and coin --- TODO.md | 15 +- .../Controllers/Customer/CartController.php | 50 +++--- .../Customer/VerificationController.php | 32 ++++ .../Controllers/VerificationController.php | 42 +++++ .../HandleInertiaCustomerRequests.php | 2 +- app/Models/CoinHistory.php | 4 +- app/Models/Customer.php | 33 +++- app/Models/PaylaterCustomer.php | 13 ++ app/Models/Voucher.php | 11 ++ ...023_05_24_130522_create_vouchers_table.php | 1 + ...23_05_24_130552_create_customers_table.php | 3 +- ...234950_create_paylater_customers_table.php | 37 ++++ database/seeders/PermissionSeeder.php | 3 - public/sample/ktp_placeholder.png | Bin 0 -> 6582 bytes resources/js/Customer/Cart/Index.jsx | 2 +- resources/js/Customer/Coin/Index.jsx | 2 +- resources/js/Customer/Index/BalanceBanner.jsx | 2 +- resources/js/Customer/Index/Banner.jsx | 2 +- resources/js/Customer/Profile/Form.jsx | 2 +- resources/js/Customer/Profile/Index.jsx | 12 +- resources/js/Customer/Trx/Detail.jsx | 14 +- resources/js/Customer/Trx/VoucherCard.jsx | 6 - resources/js/Customer/Verification/Index.jsx | 102 +++++++++++ resources/js/Layouts/CustomerLayout.jsx | 14 +- resources/js/Layouts/Partials/routes.js | 10 +- .../js/Pages/DepositHistory/FormModal.jsx | 2 +- resources/js/Pages/DepositHistory/Index.jsx | 43 ++--- resources/js/Pages/Verification/Form.jsx | 102 +++++++++++ resources/js/Pages/Verification/Index.jsx | 163 ++++++++++++++++++ routes/admin.php | 6 + routes/web.php | 6 + 31 files changed, 645 insertions(+), 91 deletions(-) create mode 100644 app/Http/Controllers/Customer/VerificationController.php create mode 100644 app/Http/Controllers/VerificationController.php create mode 100644 app/Models/PaylaterCustomer.php create mode 100644 database/migrations/2023_06_04_234950_create_paylater_customers_table.php create mode 100644 public/sample/ktp_placeholder.png create mode 100644 resources/js/Customer/Verification/Index.jsx create mode 100644 resources/js/Pages/Verification/Form.jsx create mode 100644 resources/js/Pages/Verification/Index.jsx diff --git a/TODO.md b/TODO.md index bc267c7..77419d0 100644 --- a/TODO.md +++ b/TODO.md @@ -13,13 +13,20 @@ - [x] Setting Level Customer (view levels, edit name of level,minimal saldo, max amount saldo, max hutang) - [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 -- [ ] Manual Approve Verification +- [ ] Manual Approve Verification -> mendapatkan limit hutang +- [ ] Setting Bonus Coin (memasukan amount bonus coin yang didapat dengan level dan harga voucher) - bonus coin - [ ] Voucher Sales - [ ] Dashboard (gafik hasil penjualan : disorting tanggal, lokasi dan customer) - [ ] Notification (manual deposit, stock voucher) +- [ ] View Customer Coin History +- [ ] Voucher - harga per level +- [ ] Voucher - harga coin + +### Adds + +- hutang (paylater) adalah limit tiap customer jika deposit kurang dalam pembayaran voucher , setiap limit yang digunakan akan di potong / di lunasi ketika melakukan topup deposit +- tukar coin adalah dengan menambahkan harga coin di voucher dan menambahkan 1 fitur di customer untuk explorer voucher yang memiliki harga coin, disimpan menjadi sale biasa dengan cara 1 kali penukaran adalah 1 voucher ### Customer @@ -36,4 +43,6 @@ - [x] Register Refferal - [x] Customer View Coin History - [ ] Verified Akun +- [ ] Paylater +- [ ] Coin Explorer - [ ] Notification (purchase success, deposit success) diff --git a/app/Http/Controllers/Customer/CartController.php b/app/Http/Controllers/Customer/CartController.php index 3c6d597..139a787 100644 --- a/app/Http/Controllers/Customer/CartController.php +++ b/app/Http/Controllers/Customer/CartController.php @@ -96,25 +96,20 @@ class CartController extends Controller DB::beginTransaction(); $carts = collect(session('carts')); + if ($carts->count() == 0) { + return redirect()->route('home.index') + ->with('message', ['type' => 'error', 'message' => 'transaksi gagal, keranjang anda kosong']); + } + // validate voucher is available - $vouchers = Voucher::whereIn('id', $carts->pluck('id')->toArray())->get(); - $carts = $carts->map(function ($item) use ($vouchers) { - $voucher = $vouchers->firstWhere('id', $item['id']); - if ($voucher->is_sold == Voucher::SOLD) { - $voucher = $voucher->shuffle_unsold(); - // rare happen - if ($voucher == null) { - session()->remove('carts'); - return redirect()->route('home.index') - ->with('message', ['type' => 'error', 'message' => 'transaksi gagal, voucher sedang tidak tersedia']); - } + foreach ($carts as $item) { + $batchCount = $item['voucher']->count_unsold(); + if ($batchCount < $item['quantity']) { + session()->remove('carts'); + return redirect()->route('home.index') + ->with('message', ['type' => 'error', 'message' => 'transaksi gagal, voucher sedang tidak tersedia']); } - - return [ - ...$item, - 'voucher' => $voucher - ]; - }); + }; $total = $carts->sum(function ($item) { return $item['quantity'] * $item['voucher']->price; @@ -129,15 +124,18 @@ class CartController extends Controller ]); foreach ($carts as $item) { - $sale->items()->create([ - 'entity_type' => $item['voucher']::class, - 'entity_id' => $item['voucher']->id, - 'price' => $item['voucher']->price, - 'quantity' => $item['quantity'], - 'additional_info_json' => json_encode($item), - ]); - - $item['voucher']->update(['is_sold' => Voucher::SOLD]); + foreach (range(1, $item['quantity']) as $q) { + $voucher = $item['voucher']->shuffle_unsold(); + $sale->items()->create([ + 'entity_type' => $voucher::class, + 'entity_id' => $voucher->id, + 'price' => $voucher->price, + 'quantity' => 1, + 'additional_info_json' => json_encode($item), + ]); + + $voucher->update(['is_sold' => Voucher::SOLD]); + } } $deposit = $customer->deposites()->create([ diff --git a/app/Http/Controllers/Customer/VerificationController.php b/app/Http/Controllers/Customer/VerificationController.php new file mode 100644 index 0000000..164b89c --- /dev/null +++ b/app/Http/Controllers/Customer/VerificationController.php @@ -0,0 +1,32 @@ +validate(['image' => 'required|image']); + + $customer = Customer::where('id', auth()->id())->first(); + + $file = $request->file('image'); + $file->store('uploads/KTP', 'public'); + $customer->update([ + 'identity_image' => $file->hashName('uploads/KTP'), + 'identity_verified' => Customer::IN_VERICATION, + ]); + + return redirect()->route('customer.verification') + ->with('message', ['type' => 'success', 'message' => 'verification is in progress']); + } +} diff --git a/app/Http/Controllers/VerificationController.php b/app/Http/Controllers/VerificationController.php new file mode 100644 index 0000000..4a27b9b --- /dev/null +++ b/app/Http/Controllers/VerificationController.php @@ -0,0 +1,42 @@ +where('identity_verified', Customer::IN_VERICATION) + ->orderBy('updated_at', 'desc'); + + return inertia('Verification/Index', [ + 'query' => $query->paginate() + ]); + } + + public function edit(Customer $customer) + { + $levels = [ + CustomerLevel::where('key', CustomerLevel::GOLD)->first(), + CustomerLevel::where('key', CustomerLevel::PLATINUM)->first(), + ]; + + return inertia('Verification/Form', [ + 'customer' => $customer->load(['level']), + 'levels' => $levels + ]); + } + + public function update(Request $request, Customer $customer) + { + // TODO: here + $request->validate([]); + // + $customer->update([]); + } +} diff --git a/app/Http/Middleware/HandleInertiaCustomerRequests.php b/app/Http/Middleware/HandleInertiaCustomerRequests.php index 9f6998c..4595f7b 100644 --- a/app/Http/Middleware/HandleInertiaCustomerRequests.php +++ b/app/Http/Middleware/HandleInertiaCustomerRequests.php @@ -40,7 +40,7 @@ class HandleInertiaCustomerRequests extends Middleware return array_merge(parent::share($request), [ 'app_name' => env('APP_NAME', 'App Name'), 'auth' => [ - 'user' => auth('customer')->user()?->load(['level']), + 'user' => auth('customer')->user()?->load(['level', 'paylater']), ], 'flash' => [ 'message' => fn () => $request->session()->get('message') ?? ['type' => null, 'message' => null], diff --git a/app/Models/CoinHistory.php b/app/Models/CoinHistory.php index c9efbda..265186b 100644 --- a/app/Models/CoinHistory.php +++ b/app/Models/CoinHistory.php @@ -41,10 +41,10 @@ class CoinHistory extends Model { return Attribute::make(get: function () { if ($this->credit == 0) { - return 'Rp' . number_format($this->debit, 0, ',', '.'); + return number_format($this->debit, 0, ',', '.'); } - return '-Rp' . number_format($this->credit, 0, ',', '.'); + return number_format($this->credit, 0, ',', '.'); }); } diff --git a/app/Models/Customer.php b/app/Models/Customer.php index 3254ea8..0eed2c8 100644 --- a/app/Models/Customer.php +++ b/app/Models/Customer.php @@ -33,7 +33,6 @@ class Customer extends Authenticatable 'google_id', 'deposit_balance', 'coin_balance', - 'paylater_balance', 'identity_verified', 'identity_image', 'customer_level_id', @@ -47,9 +46,11 @@ class Customer extends Authenticatable protected $appends = [ 'image_url', + 'identity_image_url', 'display_deposit', 'display_coin', 'display_phone', + 'paylater_limit', ]; protected static function booted(): void @@ -103,6 +104,19 @@ class Customer extends Authenticatable ); } + public function identityImageUrl(): Attribute + { + return Attribute::make( + get: function () { + if ($this->identity_image != null) { + return asset($this->identity_image); + } + + return asset('sample/ktp_placeholder.png'); + } + ); + } + public function displayPhone(): Attribute { return Attribute::make(get: function () { @@ -128,6 +142,13 @@ class Customer extends Authenticatable }); } + public function paylaterLimit(): Attribute + { + return Attribute::make(get: function () { + return $this->paylater?->limit ?? ''; + }); + } + public function level() { return $this->belongsTo(CustomerLevel::class, 'customer_level_id'); @@ -148,6 +169,16 @@ class Customer extends Authenticatable return $this->hasMany(CoinHistory::class); } + public function paylater() + { + return $this->hasOne(PaylaterCustomer::class); + } + + public function paylaterHistories() + { + return $this->hasMany(PaylaterHistory::class); + } + public function customerRefferals() { return $this->hasMany(CustomerRefferal::class); diff --git a/app/Models/PaylaterCustomer.php b/app/Models/PaylaterCustomer.php new file mode 100644 index 0000000..129540c --- /dev/null +++ b/app/Models/PaylaterCustomer.php @@ -0,0 +1,13 @@ +batch_id] + ])->count(); + + return $voucher; + } } diff --git a/database/migrations/2023_05_24_130522_create_vouchers_table.php b/database/migrations/2023_05_24_130522_create_vouchers_table.php index 29b9593..6a668e5 100644 --- a/database/migrations/2023_05_24_130522_create_vouchers_table.php +++ b/database/migrations/2023_05_24_130522_create_vouchers_table.php @@ -19,6 +19,7 @@ return new class extends Migration $table->ulid('location_id')->nullable(); $table->string('username')->nullable(); $table->string('password')->nullable(); + $table->decimal('price_coin', 20, 2)->default(0); $table->decimal('price', 20, 2)->default(0); $table->decimal('discount', 20, 0)->default(0); $table->decimal('display_price', 20, 2)->default(0); diff --git a/database/migrations/2023_05_24_130552_create_customers_table.php b/database/migrations/2023_05_24_130552_create_customers_table.php index c783247..3f916af 100644 --- a/database/migrations/2023_05_24_130552_create_customers_table.php +++ b/database/migrations/2023_05_24_130552_create_customers_table.php @@ -26,8 +26,7 @@ return new class extends Migration $table->string('google_id')->nullable(); $table->decimal('deposit_balance', 20, 2)->default(0); $table->decimal('coin_balance', 20, 2)->default(0); - $table->decimal('paylater_balance', 20, 2)->default(0); - $table->smallInteger('identity_verified')->nullable(); + $table->smallInteger('identity_verified')->default(0); $table->string('identity_image')->nullable(); $table->ulid('customer_level_id')->nullable(); $table->text('google_oauth_response')->nullable(); diff --git a/database/migrations/2023_06_04_234950_create_paylater_customers_table.php b/database/migrations/2023_06_04_234950_create_paylater_customers_table.php new file mode 100644 index 0000000..f907dde --- /dev/null +++ b/database/migrations/2023_06_04_234950_create_paylater_customers_table.php @@ -0,0 +1,37 @@ +ulid('id')->primary(); + + $table->text('description')->nullable(); + $table->ulid('customer_id')->nullable(); + $table->decimal('limit', 20, 2)->default(0); + $table->decimal('usage', 20, 2)->default(0); + + $table->timestamps(); + $table->softDeletes(); + $table->ulid('created_by')->nullable(); + $table->ulid('updated_by')->nullable(); + $table->ulid('deleted_by')->nullable(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('paylater_customers'); + } +}; diff --git a/database/seeders/PermissionSeeder.php b/database/seeders/PermissionSeeder.php index 91f38f8..8b0d2de 100644 --- a/database/seeders/PermissionSeeder.php +++ b/database/seeders/PermissionSeeder.php @@ -54,10 +54,7 @@ class PermissionSeeder extends Seeder ['id' => Str::ulid(), 'label' => 'Update Customer Level', 'name' => 'update-customer-level'], ['id' => Str::ulid(), 'label' => 'View Customer Level', 'name' => 'view-customer-level'], - ['id' => Str::ulid(), 'label' => 'Create Customer Verification', 'name' => 'create-customer-verification'], - ['id' => Str::ulid(), 'label' => 'Update Customer Verification', 'name' => 'update-customer-verification'], ['id' => Str::ulid(), 'label' => 'View Customer Verification', 'name' => 'view-customer-verification'], - ['id' => Str::ulid(), 'label' => 'Delete Customer Verification', 'name' => 'delete-customer-verification'], ['id' => Str::ulid(), 'label' => 'View Setting', 'name' => 'view-setting'], diff --git a/public/sample/ktp_placeholder.png b/public/sample/ktp_placeholder.png new file mode 100644 index 0000000000000000000000000000000000000000..49a7b8590dc5fc850758462d7655487560dad3f2 GIT binary patch literal 6582 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 literal 0 HcmV?d00001 diff --git a/resources/js/Customer/Cart/Index.jsx b/resources/js/Customer/Cart/Index.jsx index 61b5914..5515590 100644 --- a/resources/js/Customer/Cart/Index.jsx +++ b/resources/js/Customer/Cart/Index.jsx @@ -30,7 +30,7 @@ export default function Index({ auth: { user }, carts, total }) { return ( - +
Keranjang
diff --git a/resources/js/Customer/Coin/Index.jsx b/resources/js/Customer/Coin/Index.jsx index 0c98f9c..44611da 100644 --- a/resources/js/Customer/Coin/Index.jsx +++ b/resources/js/Customer/Coin/Index.jsx @@ -36,7 +36,7 @@ export default function Index({ Coin
- Rp {user.display_coin} + {user.display_coin}
diff --git a/resources/js/Customer/Index/BalanceBanner.jsx b/resources/js/Customer/Index/BalanceBanner.jsx index 2cc9cd5..e021457 100644 --- a/resources/js/Customer/Index/BalanceBanner.jsx +++ b/resources/js/Customer/Index/BalanceBanner.jsx @@ -25,7 +25,7 @@ export default function BalanceBanner({ user }) {
{user.level.name} Member
-
Limit 100.000
+
{user.paylater_limit}
diff --git a/resources/js/Customer/Index/Banner.jsx b/resources/js/Customer/Index/Banner.jsx index 86e8177..b5ad9e6 100644 --- a/resources/js/Customer/Index/Banner.jsx +++ b/resources/js/Customer/Index/Banner.jsx @@ -6,7 +6,7 @@ import { HiChevronLeft } from 'react-icons/hi2' export default function Banner({ banner }) { return ( - +
} /> diff --git a/resources/js/Customer/Profile/Index.jsx b/resources/js/Customer/Profile/Index.jsx index 2c96dca..5860dac 100644 --- a/resources/js/Customer/Profile/Index.jsx +++ b/resources/js/Customer/Profile/Index.jsx @@ -84,7 +84,17 @@ export default function Index({ auth: { user } }) {
+ {/* menu hanya muncul untuk member gold atau platinum */}
+
Paylater
+ +
+
+ router.get(route('customer.verification')) + } + >
Upgrade Member
@@ -101,7 +111,7 @@ export default function Index({ auth: { user } }) { className="flex flex-row justify-between items-center px-2 py-4 w-full border-b border-gray-400 hover:bg-gray-100" onClick={() => router.get(route('customer.coin.index'))} > -
Coin
+
Riwayat Coin
Transaksi #{sale.code}
-
{sale.format_created_at}
+
{sale.format_created_at}
+
+
+
TOTAL
+
{sale.display_amount}
+
+
{sale.items.map((item) => ( ))}
-
-
-
TOTAL
-
{sale.display_amount}
-
-
) diff --git a/resources/js/Customer/Trx/VoucherCard.jsx b/resources/js/Customer/Trx/VoucherCard.jsx index 50b076b..335ae20 100644 --- a/resources/js/Customer/Trx/VoucherCard.jsx +++ b/resources/js/Customer/Trx/VoucherCard.jsx @@ -64,12 +64,6 @@ export default function VoucherCard(props) {
-
-
{formatIDR(voucher.price)}
-
x
-
{quantity}
-
{formatIDR(+voucher.price * +quantity)}
-
diff --git a/resources/js/Customer/Verification/Index.jsx b/resources/js/Customer/Verification/Index.jsx new file mode 100644 index 0000000..6e98d37 --- /dev/null +++ b/resources/js/Customer/Verification/Index.jsx @@ -0,0 +1,102 @@ +import React, { useState } from 'react' +import { Head, useForm, router, usePage } from '@inertiajs/react' +import CustomerLayout from '@/Layouts/CustomerLayout' +import FormFile from '@/Components/FormFile' +import { HiCheckCircle, HiClock } from 'react-icons/hi2' + +// 0 yuk verifikasi +const VerificationForm = () => { + const { + props: { + auth: { user }, + }, + } = usePage() + const [show, setShow] = useState(false) + + const { setData, post, errors } = useForm({ image: null }) + + const handleSubmit = () => { + post(route('customer.verification')) + } + + return ( + <> +
+ upgrade akun kamu untuk mendapatkan banefit lebih, cukup lakukan + verifikasi data dengan upload foto KTP kamu +
+ {show === false ? ( +
setShow(true)} + > +
+ Verifikasi +
+
+ ) : ( +
+ setData('image', e.target.files[0])} + error={errors.image} + preview={ + ktp image + } + /> + +
handleSubmit()} + > + Upload +
+
+ )} + + ) +} + +// 1 verified +const Verified = () => { + return ( +
+ +
+ Akun anda berhasil terverifikasi +
+
+ ) +} + +// 2 your data is in review +const VerificationInProgress = () => { + return ( +
+ +
+ Data anda sedang kami proses untuk verifikasi +
+
+ ) +} + +export default function Index({ auth: { user } }) { + return ( + + +
+
+ Upgrade Member +
+ {+user.identity_verified === 0 && } + {+user.identity_verified === 1 && } + {+user.identity_verified === 2 && } +
+
+ ) +} diff --git a/resources/js/Layouts/CustomerLayout.jsx b/resources/js/Layouts/CustomerLayout.jsx index 32e8329..f075dbf 100644 --- a/resources/js/Layouts/CustomerLayout.jsx +++ b/resources/js/Layouts/CustomerLayout.jsx @@ -6,6 +6,8 @@ import { HiOutlineHome, HiOutlineUserCircle } from 'react-icons/hi' import { HiArrowPathRoundedSquare, HiBars3, + HiGift, + HiOutlineGift, HiOutlineShoppingCart, } from 'react-icons/hi2' @@ -51,7 +53,6 @@ export default function CustomerLayout({ children }) {
Beranda
-
Keranjang
+
handleOnClick('cart.index')} + > +
+ +
+
Coin
+
- +
diff --git a/resources/js/Pages/DepositHistory/Index.jsx b/resources/js/Pages/DepositHistory/Index.jsx index 9c1282e..e29552e 100644 --- a/resources/js/Pages/DepositHistory/Index.jsx +++ b/resources/js/Pages/DepositHistory/Index.jsx @@ -14,7 +14,7 @@ import SearchInput from '@/Components/SearchInput' import { formatIDR, hasPermission } from '@/utils' import { HiEye } from 'react-icons/hi2' -export default function Info(props) { +export default function Index(props) { const { query: { links, data }, auth, @@ -125,31 +125,20 @@ export default function Info(props) { > {deposit.status.text} - ))} @@ -157,7 +146,7 @@ export default function Info(props) {
Customer - - {canUpdate && ( - - toggleFormModal( - deposit - ) - } - > -
- -
- Lihat -
-
-
- )} -
+
+ {canUpdate && ( +
+ toggleFormModal( + deposit + ) + } + > + +
Lihat
+
+ )}
- +
diff --git a/resources/js/Pages/Verification/Form.jsx b/resources/js/Pages/Verification/Form.jsx new file mode 100644 index 0000000..dc60ffe --- /dev/null +++ b/resources/js/Pages/Verification/Form.jsx @@ -0,0 +1,102 @@ +import React, { useEffect, useState } from 'react' +import { useForm, Head, Link } from '@inertiajs/react' +import { isEmpty } from 'lodash' + +import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout' +import Button from '@/Components/Button' + +export default function Form(props) { + const { customer, levels } = props + const { data, setData, post, processing, errors, reset, clearErrors } = + useForm({ + level: '', + image_prove_url: '', + }) + + const handleOnChange = (event) => { + setData( + event.target.name, + event.target.type === 'checkbox' + ? event.target.checked + ? 1 + : 0 + : event.target.value + ) + } + + const handleSubmit = () => { + post(route('customer-verification.update', customer)) + } + + return ( + + + +
+
+
+
+ Verifikasi Customer +
+ + + + + + + + +
Customer: + + {customer.name} + +
+ +
+ +
+ +
+
Level Upgrade
+ +
+
+ +
+
+
+
+
+ ) +} diff --git a/resources/js/Pages/Verification/Index.jsx b/resources/js/Pages/Verification/Index.jsx new file mode 100644 index 0000000..017526c --- /dev/null +++ b/resources/js/Pages/Verification/Index.jsx @@ -0,0 +1,163 @@ +import React, { useEffect, useState } from 'react' +import { router } from '@inertiajs/react' +import { usePrevious } from 'react-use' +import { Head } from '@inertiajs/react' +import { Dropdown } from 'flowbite-react' +import { HiEye } from 'react-icons/hi2' + +import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout' +import Pagination from '@/Components/Pagination' +import SearchInput from '@/Components/SearchInput' + +export default function Index(props) { + const { + query: { links, data }, + auth, + } = props + + const [search, setSearch] = useState('') + const preValue = usePrevious(search) + + const params = { q: search } + useEffect(() => { + if (preValue) { + router.get( + route(route().current()), + { q: search }, + { + replace: true, + preserveState: true, + } + ) + } + }, [search]) + + return ( + + + +
+
+
+
+
+ setSearch(e.target.value)} + value={search} + /> +
+
+
+
+ + + + + + + + + + + + {data.map((customer) => ( + + + + + + + + + ))} + +
+ Nama + + Level + + Deposit + + Coin + + Referal Code + +
+ {customer.name} + + {customer.level.name} + + {customer.display_deposit} + + {customer.display_coin} + + {customer.referral_code} + +
{ + router.get( + route( + 'customer-verification.edit', + customer + ) + ) + }} + > + +
Lihat
+
+
+
+
+ +
+
+
+
+
+
+ ) +} diff --git a/routes/admin.php b/routes/admin.php index 3a8fc61..5480cb4 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\VerificationController; use App\Http\Controllers\DepositController; use App\Http\Controllers\GeneralController; use App\Http\Controllers\InfoController; @@ -83,6 +84,11 @@ Route::middleware(['http_secure_aware', 'inertia.admin']) Route::get('/customer-levels', [CustomerLevelController::class, 'index'])->name('customer-level.index'); Route::put('/customer-levels/{customerLevel}', [CustomerLevelController::class, 'update'])->name('customer-level.update'); + // verification + Route::get('/customers-verifications', [VerificationController::class, 'index'])->name('customer-verification.index'); + Route::get('/customers-verifications/{customer}', [VerificationController::class, 'edit'])->name('customer-verification.edit'); + Route::post('/customers-verifications/{customer}', [VerificationController::class, 'update'])->name('customer-verification.update'); + // customer Route::get('/customers', [CustomerController::class, 'index'])->name('customer.index'); Route::get('/customers/create', [CustomerController::class, 'create'])->name('customer.create'); diff --git a/routes/web.php b/routes/web.php index d8f3799..7862cca 100644 --- a/routes/web.php +++ b/routes/web.php @@ -7,6 +7,7 @@ use App\Http\Controllers\Customer\DepositController; use App\Http\Controllers\Customer\HomeController; use App\Http\Controllers\Customer\ProfileController; use App\Http\Controllers\Customer\TransactionController; +use App\Http\Controllers\Customer\VerificationController; use Illuminate\Support\Facades\Route; /* @@ -30,6 +31,11 @@ Route::middleware(['http_secure_aware', 'guard_should_customer', 'inertia.custom Route::get('profile', [ProfileController::class, 'index'])->name('customer.profile.index'); Route::get('profile/update', [ProfileController::class, 'show'])->name('customer.profile.show'); Route::post('profile/update', [ProfileController::class, 'update']); + + // verification + Route::get('profile/verification', [VerificationController::class, 'index'])->name('customer.verification'); + Route::post('profile/verification', [VerificationController::class, 'update']); + // logout Route::post('logout', [AuthController::class, 'destroy'])->name('customer.logout');