customer deposit done
parent
f9064ab4d3
commit
4235d7aa8f
@ -0,0 +1,155 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Customer;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Account;
|
||||
use App\Models\DepositHistory;
|
||||
use App\Models\Setting;
|
||||
use App\Services\GeneralService;
|
||||
use App\Services\MidtransService;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class DepositController extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
$histories = DepositHistory::where('customer_id', auth()->id())
|
||||
->orderBy('updated_at', 'desc')
|
||||
->orderBy('is_valid', 'desc');
|
||||
|
||||
return inertia('Home/Deposit/Index', [
|
||||
'histories' => $histories->paginate(20)
|
||||
]);
|
||||
}
|
||||
|
||||
public function create()
|
||||
{
|
||||
return inertia('Home/Deposit/Topup', [
|
||||
'payments' => GeneralService::getEnablePayment(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function store(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'amount' => 'required|numeric|min:10000',
|
||||
'payment' => [
|
||||
'required',
|
||||
Rule::in([Setting::PAYMENT_MANUAL, Setting::PAYMENT_MIDTRANS])
|
||||
]
|
||||
]);
|
||||
|
||||
DB::beginTransaction();
|
||||
$deposit = DepositHistory::make([
|
||||
'customer_id' => auth()->id(),
|
||||
'debit' => $request->amount,
|
||||
'description' => 'Top Up #' . Str::random(5),
|
||||
'payment_channel' => $request->payment,
|
||||
]);
|
||||
|
||||
if ($request->payment == Setting::PAYMENT_MANUAL) {
|
||||
$deposit->is_valid = DepositHistory::STATUS_WAIT_UPLOAD;
|
||||
$deposit->save();
|
||||
}
|
||||
|
||||
if ($request->payment == Setting::PAYMENT_MIDTRANS) {
|
||||
$deposit->is_valid = DepositHistory::STATUS_WAIT_PAYMENT;
|
||||
$deposit->save();
|
||||
|
||||
$token = (new MidtransService($deposit, Setting::getByKey('MIDTRANS_SERVER_KEY')))->getSnapToken();
|
||||
|
||||
$deposit->update(['payment_token' => $token]);
|
||||
}
|
||||
|
||||
DB::commit();
|
||||
|
||||
return redirect()->route('customer.deposit.show', ['deposit' => $deposit->id, 'direct' => 'true']);
|
||||
}
|
||||
|
||||
public function show(Request $request, DepositHistory $deposit)
|
||||
{
|
||||
return inertia('Home/Deposit/Detail', [
|
||||
'deposit' => $deposit,
|
||||
'accounts' => Account::get(),
|
||||
'midtrans_client_key' => Setting::getByKey('MIDTRANS_CLIENT_KEY'),
|
||||
'is_production' => app()->isProduction(),
|
||||
'direct' => $request->direct
|
||||
]);
|
||||
}
|
||||
|
||||
public function update(Request $request, DepositHistory $deposit)
|
||||
{
|
||||
$request->validate([
|
||||
'account_id' => 'required|exists:accounts,id',
|
||||
'image' => 'required|image',
|
||||
]);
|
||||
|
||||
$file = $request->file('image');
|
||||
$file->store('uploads', 'public');
|
||||
$deposit->update([
|
||||
'image_prove' => $file->hashName('uploads'),
|
||||
'account_id' => $request->account_id,
|
||||
'is_valid' => DepositHistory::STATUS_WAIT_APPROVE
|
||||
]);
|
||||
|
||||
session()->flash('message', ['type' => 'success', 'message' => 'Upload berhasil, silahkan tunggu untuk approve']);;
|
||||
}
|
||||
|
||||
public function midtrans_payment(Request $request, DepositHistory $deposit)
|
||||
{
|
||||
DB::beginTransaction();
|
||||
$transaction_status = $request->result['transaction_status'];
|
||||
if ($transaction_status == 'settlement' || $transaction_status == 'capture') {
|
||||
$is_valid = DepositHistory::STATUS_VALID;
|
||||
$deposit->update_customer_balance();
|
||||
} elseif ($transaction_status == 'pending') {
|
||||
$is_valid = DepositHistory::STATUS_WAIT_PAYMENT;
|
||||
} else {
|
||||
$is_valid = DepositHistory::STATUS_INVALID;
|
||||
}
|
||||
$deposit->update([
|
||||
'is_valid' => $is_valid,
|
||||
'payment_response' => json_encode($request->result),
|
||||
'payment_type' => $request->result['payment_type'],
|
||||
]);
|
||||
|
||||
DB::commit();
|
||||
|
||||
return redirect()->route('customer.deposit.show', ['deposit' => $deposit->id]);
|
||||
}
|
||||
|
||||
public function mindtrans_notification(Request $request)
|
||||
{
|
||||
DB::beginTransaction();
|
||||
$deposit = DepositHistory::where('id', $request->order_id)->first();
|
||||
|
||||
if ($deposit != null && $deposit->is_valid != DepositHistory::STATUS_VALID) {
|
||||
$deposit->fill([
|
||||
'payment_response' => json_encode($request->all()),
|
||||
'payment_type' => $request->result['payment_type'],
|
||||
]);
|
||||
|
||||
if ($request->transaction_status == 'settlement' || $request->transaction_status == 'capture') {
|
||||
$deposit->fill(['payment_status' => DepositHistory::STATUS_VALID]);
|
||||
$deposit->update_customer_balance();
|
||||
} elseif ($request->transaction_status == 'pending') {
|
||||
$deposit->fill(['payment_status' => DepositHistory::STATUS_WAIT_PAYMENT]);
|
||||
} else {
|
||||
$deposit->fill(['payment_status' => DepositHistory::STATUS_INVALID]);
|
||||
}
|
||||
|
||||
$deposit->save();
|
||||
}
|
||||
|
||||
DB::commit();
|
||||
|
||||
return response()->json([
|
||||
'status' => 'ok',
|
||||
'order' => $deposit,
|
||||
]);
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
class PaylaterHistory extends Model
|
||||
{
|
||||
protected $fillable = [
|
||||
'debit',
|
||||
'credit',
|
||||
'description',
|
||||
'customer_id',
|
||||
];
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('paylater_histories', function (Blueprint $table) {
|
||||
$table->ulid('id')->primary();
|
||||
|
||||
$table->decimal('debit', 20, 2)->default(0);
|
||||
$table->decimal('credit', 20, 2)->default(0);
|
||||
$table->text('description')->nullable();
|
||||
$table->ulid('customer_id')->nullable();
|
||||
|
||||
$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_histories');
|
||||
}
|
||||
};
|
Binary file not shown.
After Width: | Height: | Size: 126 KiB |
Binary file not shown.
After Width: | Height: | Size: 38 KiB |
Binary file not shown.
After Width: | Height: | Size: 126 KiB |
Binary file not shown.
After Width: | Height: | Size: 126 KiB |
Binary file not shown.
After Width: | Height: | Size: 93 KiB |
Binary file not shown.
After Width: | Height: | Size: 93 KiB |
@ -0,0 +1,257 @@
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import { Head, router, useForm, usePage } from '@inertiajs/react'
|
||||
import { HiChevronLeft } from 'react-icons/hi2'
|
||||
|
||||
import CustomerLayout from '@/Layouts/CustomerLayout'
|
||||
import { formatIDR } from '@/utils'
|
||||
import FormFile from '@/Components/FormFile'
|
||||
import { isEmpty } from 'lodash'
|
||||
import Alert from '@/Components/Alert'
|
||||
|
||||
const PayButton = () => {
|
||||
const {
|
||||
props: { deposit, midtrans_client_key, is_production, direct, flash },
|
||||
} = usePage()
|
||||
|
||||
const [loading, setLoading] = useState(false)
|
||||
|
||||
const handleResult = (result) => {
|
||||
fetch(route('api.midtrans.payment', deposit), {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ result }),
|
||||
}).finally(() => {
|
||||
router.get(route(route().current(), deposit))
|
||||
})
|
||||
}
|
||||
|
||||
const onClickPay = () => {
|
||||
if (loading) {
|
||||
return
|
||||
}
|
||||
setLoading(true)
|
||||
window.snap.pay(deposit.payment_token, {
|
||||
// Optional
|
||||
onSuccess: function (result) {
|
||||
console.log(result)
|
||||
handleResult(result)
|
||||
setLoading(false)
|
||||
},
|
||||
// Optional
|
||||
onPending: function (result) {
|
||||
console.log(result)
|
||||
handleResult(result)
|
||||
setLoading(false)
|
||||
},
|
||||
// Optional
|
||||
onError: function (result) {
|
||||
console.log(result)
|
||||
handleResult(result)
|
||||
setLoading(false)
|
||||
},
|
||||
onClose: function () {
|
||||
setLoading(false)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
//change this to the script source you want to load, for example this is snap.js sandbox env
|
||||
let midtransScriptUrl = 'https://app.sandbox.midtrans.com/snap/snap.js'
|
||||
if (is_production) {
|
||||
midtransScriptUrl = 'https://app.midtrans.com/snap/snap.js'
|
||||
}
|
||||
//change this according to your client-key
|
||||
let scriptTag = document.createElement('script')
|
||||
scriptTag.src = midtransScriptUrl
|
||||
// optional if you want to set script attribute
|
||||
// for example snap.js have data-client-key attribute
|
||||
scriptTag.setAttribute('data-client-key', midtrans_client_key)
|
||||
|
||||
document.body.appendChild(scriptTag)
|
||||
|
||||
if (direct === 'true') {
|
||||
setTimeout(() => {
|
||||
onClickPay()
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
return () => {
|
||||
document.body.removeChild(scriptTag)
|
||||
}
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className="w-full px-5 py-10">
|
||||
<Alert type={flash.message.type}>
|
||||
<span className="font-semibold">{flash.message.message}</span>
|
||||
</Alert>
|
||||
<div
|
||||
className="px-4 py-2 bg-blue-700 text-white rounded-full border hover:bg-white hover:text-black"
|
||||
onClick={onClickPay}
|
||||
>
|
||||
Bayar
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const FormUpload = () => {
|
||||
const {
|
||||
props: { accounts, deposit, flash },
|
||||
} = usePage()
|
||||
|
||||
const [account, setAccount] = useState(null)
|
||||
const { data, setData, errors, processing, post } = useForm({
|
||||
account_id: '',
|
||||
image: null,
|
||||
image_url: deposit.image_prove_url,
|
||||
})
|
||||
|
||||
const handleSelectAccount = (id) => {
|
||||
if (id === '') {
|
||||
setData('account_id', '')
|
||||
setAccount(null)
|
||||
}
|
||||
const account = accounts.find((acc) => acc.id === id)
|
||||
setData('account_id', account.id)
|
||||
setAccount(account)
|
||||
}
|
||||
|
||||
const handleSubmit = () => {
|
||||
if (processing) {
|
||||
return
|
||||
}
|
||||
post(route('customer.deposit.update', deposit))
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="px-5 mt-4">
|
||||
<div className="my-4">
|
||||
<Alert type={flash.message.type}>
|
||||
<span className="font-semibold">
|
||||
{flash.message.message}
|
||||
</span>
|
||||
</Alert>
|
||||
<div className="mb-1 text-sm">Bank </div>
|
||||
<select
|
||||
className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5"
|
||||
onChange={(e) => handleSelectAccount(e.target.value)}
|
||||
value={data.account_id}
|
||||
name="account_id"
|
||||
>
|
||||
<option value=""></option>
|
||||
{accounts.map((account) => (
|
||||
<option value={account.id} key={account.id}>
|
||||
{account.bank_name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
{data.account_id !== '' && (
|
||||
<>
|
||||
<div className="my-5">
|
||||
<div className="bg-red-200 text-red-600 p-3 border rounded-md border-red-700">
|
||||
<div>Silahkan transfer nominal di atas ke</div>
|
||||
<div>
|
||||
Bank :{' '}
|
||||
<span className="font-bold">
|
||||
{account.bank_name}
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
Atas Nama :{' '}
|
||||
<span className="font-bold">
|
||||
{account.holder_name}
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
Nomor Rekening :{' '}
|
||||
<span className="font-bold">
|
||||
{account.account_number}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<FormFile
|
||||
label={'Bukti Transfer'}
|
||||
onChange={(e) => setData('image', e.target.files[0])}
|
||||
error={errors.image}
|
||||
preview={
|
||||
isEmpty(data.image_url) == false && (
|
||||
<img
|
||||
src={`${data.image_url}`}
|
||||
className="w-full h-52 mb-1"
|
||||
alt="bukti transfer"
|
||||
/>
|
||||
)
|
||||
}
|
||||
/>
|
||||
|
||||
<div
|
||||
className="mt-10 w-full px-4 py-2 border rounded-full bg-blue-600 text-white hover:bg-white hover:text-black"
|
||||
onClick={() => handleSubmit()}
|
||||
>
|
||||
Upload
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const ActionSection = ({ deposit }) => {
|
||||
return (
|
||||
<div className="w-full">
|
||||
{deposit.payment_channel === 'MIDTRANS' ? (
|
||||
<PayButton />
|
||||
) : (
|
||||
<FormUpload />
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default function Detail({ deposit }) {
|
||||
return (
|
||||
<CustomerLayout>
|
||||
<Head title="Top Up" />
|
||||
<div className="flex flex-col min-h-[calc(95dvh)]">
|
||||
<div
|
||||
className="w-full px-5 py-5"
|
||||
onClick={() => {
|
||||
router.get(route('customer.deposit.index'))
|
||||
}}
|
||||
>
|
||||
<HiChevronLeft className="font-bold h-5 w-5" />
|
||||
</div>
|
||||
|
||||
{/* detail */}
|
||||
<div className="flex flex-row justify-between items-center pb-5 border-b px-5">
|
||||
<div>
|
||||
<div className="font-semibold text-xl text-gray-400">
|
||||
{deposit.description}
|
||||
</div>
|
||||
<div className="font-bold text-3xl">
|
||||
Rp {formatIDR(deposit.amount)}
|
||||
</div>
|
||||
<div className="text-gray-400">
|
||||
{deposit.format_created_at}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
className={`text-xs px-2 py-1 rounded-full border ${deposit.status.color} text-white`}
|
||||
>
|
||||
{deposit.status.text}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* action */}
|
||||
{deposit.is_valid !== 0 && <ActionSection deposit={deposit} />}
|
||||
</div>
|
||||
</CustomerLayout>
|
||||
)
|
||||
}
|
@ -0,0 +1,104 @@
|
||||
import React, { useState } from 'react'
|
||||
import { Head, router } from '@inertiajs/react'
|
||||
import CustomerLayout from '@/Layouts/CustomerLayout'
|
||||
import { formatIDR } from '@/utils'
|
||||
|
||||
export default function Index({
|
||||
auth: { user },
|
||||
histories: { data, next_page_url },
|
||||
}) {
|
||||
const [deposites, setDeposites] = useState(data)
|
||||
|
||||
const handleNextPage = () => {
|
||||
router.get(
|
||||
next_page_url,
|
||||
{},
|
||||
{
|
||||
replace: true,
|
||||
preserveState: true,
|
||||
only: ['histories'],
|
||||
onSuccess: (res) => {
|
||||
setDeposites(deposites.concat(res.props.histories.data))
|
||||
},
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<CustomerLayout>
|
||||
<Head title="Top Up" />
|
||||
<div className="flex flex-col w-full min-h-[calc(90dvh)]">
|
||||
<div className="w-full pt-10 px-5">
|
||||
<div className="text-base">{user.fullname}</div>
|
||||
</div>
|
||||
<div className="flex flex-row justify-between items-center pb-10 border-b px-5">
|
||||
<div>
|
||||
<div className="font-semibold text-xl text-gray-400">
|
||||
Saldo
|
||||
</div>
|
||||
<div className="font-bold text-3xl">
|
||||
Rp {user.display_deposit}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
className="px-3 py-2 border rounded-full bg-blue-700 text-white hover:bg-transparent hover:text-black"
|
||||
onClick={() =>
|
||||
router.get(route('customer.deposit.topup'))
|
||||
}
|
||||
>
|
||||
Top Up
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-full">
|
||||
<div className="flex flex-col py-10 space-y-5 px-5">
|
||||
{deposites.map((history) => (
|
||||
<div
|
||||
key={history.id}
|
||||
className="flex flex-row pb-2 items-center justify-between border-b"
|
||||
onClick={() =>
|
||||
router.get(
|
||||
route(
|
||||
'customer.deposit.show',
|
||||
history.id
|
||||
)
|
||||
)
|
||||
}
|
||||
>
|
||||
<div className="flex flex-col">
|
||||
<div className="font-bold">
|
||||
{history.format_human_created_at}
|
||||
</div>
|
||||
<div className="font-thin">
|
||||
{history.description}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col items-end">
|
||||
<div className="font-bold text-lg">
|
||||
{formatIDR(history.amount)}
|
||||
</div>
|
||||
{+history.is_valid !== 0 && (
|
||||
<div
|
||||
className={`text-xs px-2 py-1 rounded-full border ${history.status.color} text-white`}
|
||||
>
|
||||
{history.status.text}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
{next_page_url !== null && (
|
||||
<div
|
||||
onClick={handleNextPage}
|
||||
className="w-full text-center px-2 py-1 border mt-5 hover:bg-blue-600 hover:text-white"
|
||||
>
|
||||
Load more
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</CustomerLayout>
|
||||
)
|
||||
}
|
@ -0,0 +1,118 @@
|
||||
import React from 'react'
|
||||
import { Head, router, useForm } from '@inertiajs/react'
|
||||
import { HiChevronLeft } from 'react-icons/hi2'
|
||||
|
||||
import CustomerLayout from '@/Layouts/CustomerLayout'
|
||||
import FormInput from '@/Components/FormInput'
|
||||
import Alert from '@/Components/Alert'
|
||||
import { formatIDR } from '@/utils'
|
||||
|
||||
export default function Topup({ payments }) {
|
||||
const { data, setData, post, processing, errors, reset, clearErrors } =
|
||||
useForm({
|
||||
amount: '',
|
||||
payment: '',
|
||||
})
|
||||
|
||||
const amounts = [20000, 50000, 100000, 200000, 300000, 500000]
|
||||
|
||||
const isActiveAmount = (amount) => {
|
||||
return `px-3 py-3 border shadow-sm rounded ${
|
||||
+amount === +data.amount ? 'bg-blue-700 text-white' : ''
|
||||
}`
|
||||
}
|
||||
|
||||
const setAmount = (amount) => {
|
||||
setData('amount', amount)
|
||||
}
|
||||
|
||||
const isActivePayment = (payment) => {
|
||||
return `p-2 border shadow rounded flex flex-row items-center space-x-5 h-14 ${
|
||||
payment === data.payment ? 'bg-blue-600 text-white' : ''
|
||||
}`
|
||||
}
|
||||
|
||||
const handleSubmit = () => {
|
||||
if (processing) {
|
||||
return
|
||||
}
|
||||
post(route('customer.deposit.topup'))
|
||||
}
|
||||
|
||||
return (
|
||||
<CustomerLayout>
|
||||
<Head title="Top Up" />
|
||||
<div className="flex flex-col min-h-[calc(95dvh)]">
|
||||
<div
|
||||
className="w-full px-5 py-5"
|
||||
onClick={() => {
|
||||
router.get(route('customer.deposit.index'))
|
||||
}}
|
||||
>
|
||||
<HiChevronLeft className="font-bold h-5 w-5" />
|
||||
</div>
|
||||
<div className="w-full px-5">
|
||||
<div className="mb-2 font-bold">Pilih Nominal</div>
|
||||
<div className="w-full grid grid-cols-3 gap-2 text-center">
|
||||
{amounts.map((amount) => (
|
||||
<div
|
||||
key={amount}
|
||||
className={isActiveAmount(amount)}
|
||||
onClick={() => setAmount(amount)}
|
||||
>
|
||||
{formatIDR(amount)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-row items-center space-x-2 justify-between w-full px-5 py-5">
|
||||
<div className="border-b flex-1"></div>
|
||||
<div>ATAU</div>
|
||||
<div className="border-b flex-1"></div>
|
||||
</div>
|
||||
<div className="w-full px-5">
|
||||
<FormInput
|
||||
placeholder="masukan nominal, minimal 10.000"
|
||||
value={data.amount}
|
||||
onChange={(e) => setData('amount', e.target.value)}
|
||||
error={errors.amount}
|
||||
/>
|
||||
</div>
|
||||
<div className="w-full px-5 mt-10 flex flex-col">
|
||||
<div className="font-bold mb-2">Metode Pembayaran</div>
|
||||
{errors.payment && (
|
||||
<Alert type="error">Pilih metode pembayaran</Alert>
|
||||
)}
|
||||
<div className="mb-2" />
|
||||
<div className="w-full flex flex-col space-y-2">
|
||||
{payments.map((payment) => (
|
||||
<div
|
||||
key={payment.name}
|
||||
className={isActivePayment(payment.name)}
|
||||
onClick={() => setData('payment', payment.name)}
|
||||
>
|
||||
<input type="radio" />
|
||||
{payment.logo === null ? (
|
||||
<p>{payment.display_name}</p>
|
||||
) : (
|
||||
<img
|
||||
src={payment.logo}
|
||||
className="h-7 object-cover"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="fixed bottom-20 right-0 md:right-1/3 md:pl-10 max-w-md w-full">
|
||||
<div
|
||||
onClick={handleSubmit}
|
||||
className="border bg-blue-700 text-white px-5 py-2 mx-5 rounded-full hover:text-black hover:bg-white"
|
||||
>
|
||||
Bayar
|
||||
</div>
|
||||
</div>
|
||||
</CustomerLayout>
|
||||
)
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
import { router } from '@inertiajs/react'
|
||||
import { HiOutlineCash } from 'react-icons/hi'
|
||||
|
||||
export default function BalanceBanner({ user }) {
|
||||
return (
|
||||
<div
|
||||
className="flex flex-row px-5 pb-3 text-base bg-blue-600"
|
||||
onClick={() => router.get(route('customer.deposit.index'))}
|
||||
>
|
||||
<div className="flex flex-row w-full shadow py-2 px-2 rounded bg-white items-center justify-between">
|
||||
<div className="flex flex-col">
|
||||
<div className="text-xs flex flex-row items-center space-x-1 text-gray-400">
|
||||
<HiOutlineCash />
|
||||
<div>Saldo</div>
|
||||
</div>
|
||||
<div className="font-bold">Rp {user.display_deposit}</div>
|
||||
<div className="text-xs flex flex-row items-center space-x-1 text-gray-400">
|
||||
<div>Coin {user.display_coin}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col border-l-2 pl-5 pr-5">
|
||||
<div className="text-xs flex flex-row items-center space-x-1 text-gray-400">
|
||||
{/* <HiOutlineAwa /> */}
|
||||
<div>Rewards</div>
|
||||
</div>
|
||||
<div className="font-bold">{user.level.name} Member</div>
|
||||
<div className="text-xs flex flex-row items-center space-x-1 text-gray-400">
|
||||
<div>Limit 100.000</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
Loading…
Reference in New Issue