diff --git a/app/Http/Controllers/Admin/GeneralController.php b/app/Http/Controllers/Admin/GeneralController.php index 44eeff1..da0f1b3 100644 --- a/app/Http/Controllers/Admin/GeneralController.php +++ b/app/Http/Controllers/Admin/GeneralController.php @@ -21,7 +21,7 @@ class GeneralController extends Controller $total_customer_verified = Customer::where('identity_verified', Customer::VERIFIED)->count(); $total_deposit = DepositHistory::where('is_valid', DepositHistory::STATUS_VALID)->sum('debit'); - $month = now()->locale('id')->translatedFormat('F'); + $month = now()->translatedFormat('F'); $startOfMonth = now()->startOfMonth()->format('m/d/Y'); $endOfMonth = now()->endOfMonth()->format('m/d/Y'); $total_voucher_sale_this_month = SaleItem::whereBetween('created_at', [$startOfMonth, $endOfMonth]) diff --git a/app/Http/Controllers/Admin/SettingController.php b/app/Http/Controllers/Admin/SettingController.php index 2185190..6db296b 100644 --- a/app/Http/Controllers/Admin/SettingController.php +++ b/app/Http/Controllers/Admin/SettingController.php @@ -27,6 +27,7 @@ class SettingController extends Controller 'OPEN_WEBSITE_NAME' => 'required|string', 'SHARE_TEXT' => 'required|string', 'ENABLE_CASH_DEPOSIT' => 'required|in:0,1', + 'TEXT_CASH_DEPOSIT' => 'required|string', 'ENABLE_MANUAL_TRANSFER' => 'required|in:0,1', 'MAX_MANUAL_TRANSFER_TIMEOUT' => 'required|numeric', 'MANUAL_TRANSFER_OPEN_HOUR' => 'required|string', diff --git a/app/Http/Controllers/Customer/AuthController.php b/app/Http/Controllers/Customer/AuthController.php index 9ae4c38..8bc2860 100644 --- a/app/Http/Controllers/Customer/AuthController.php +++ b/app/Http/Controllers/Customer/AuthController.php @@ -107,6 +107,7 @@ class AuthController extends Controller 'google_oauth_response' => json_encode($user), 'status' => Customer::STATUS_ACTIVE, ]); + $this->process_referral($customer, session('referral_code', '')); DB::commit(); } else { $customer->update(['google_oauth_response' => json_encode($user)]); @@ -123,11 +124,21 @@ class AuthController extends Controller return redirect()->route('home.index'); } - public function register() + public function register(Request $request) { session()->remove('carts'); - return inertia('Auth/Register'); + $code = ''; + if ($request->referral_code != '') { + session()->put('referral_code', $request->referral_code); + $code = $request->referral_code; + } else { + $code = session('referral_code', ' '); + } + + return inertia('Auth/Register', [ + 'referral_code' => $code, + ]); } public function store(Request $request) @@ -158,25 +169,7 @@ class AuthController extends Controller // send confirmation email AsyncService::async(fn () => Mail::to($request->email)->send(new CustomerVerification($customer))); - if ($request->referral_code != '') { - $refferal = Customer::where('referral_code', $request->referral_code)->first(); - $refferal->customerRefferals()->create([ - 'refferal_id' => $customer->id, - 'customer_code' => $refferal->referral_code, - ]); - - $affilateEnabled = Setting::getByKey('AFFILATE_ENABLED'); - if ($affilateEnabled == 1) { - $bonuspoin = Setting::getByKey('AFFILATE_poin_AMOUNT'); - $poin = $refferal->poins()->create([ - 'debit' => $bonuspoin, - 'description' => 'Bonus Refferal #' . Str::random(5), - ]); - - $poin->update_customer_balance(); - } - } - + $this->process_referral($customer, $request->referral_code); DB::commit(); return redirect()->route('customer.login') @@ -207,4 +200,30 @@ class AuthController extends Controller return redirect()->route('customer.login') ->with('message', ['type' => 'success', 'message' => 'Akun anda berhasil diaktifkan, silahkan login']); } + + private function process_referral(Customer $customer, $code) + { + if ($code != '') { + $refferal = Customer::where('referral_code', $code)->first(); + if ($refferal == null) { + session()->forget('referral_code'); + return; + } + $refferal->customerRefferals()->create([ + 'refferal_id' => $customer->id, + 'customer_code' => $refferal->referral_code, + ]); + + $affilateEnabled = Setting::getByKey('AFFILATE_ENABLED'); + if ($affilateEnabled == 1) { + $bonuspoin = Setting::getByKey('AFFILATE_poin_AMOUNT'); + $poin = $refferal->poins()->create([ + 'debit' => $bonuspoin, + 'description' => 'Bonus Refferal #' . Str::random(5), + ]); + + $poin->update_customer_balance(); + } + } + } } diff --git a/app/Http/Controllers/Customer/DepositController.php b/app/Http/Controllers/Customer/DepositController.php index cc51f1d..21de577 100644 --- a/app/Http/Controllers/Customer/DepositController.php +++ b/app/Http/Controllers/Customer/DepositController.php @@ -6,6 +6,7 @@ use App\Http\Controllers\Controller; use App\Models\Account; use App\Models\Customer; use App\Models\DepositHistory; +use App\Models\DepositLocation; use App\Models\Setting; use App\Services\GeneralService; use App\Services\MidtransService; @@ -77,8 +78,9 @@ class DepositController extends Controller public function show(Request $request, DepositHistory $deposit) { return inertia('Deposit/Detail', [ - 'deposit' => $deposit->load(['account']), + 'deposit' => $deposit->load(['account', 'depositLocation']), 'accounts' => Account::get(), + 'deposit_locations' => DepositLocation::get(), 'midtrans_client_key' => Setting::getByKey('MIDTRANS_CLIENT_KEY'), 'is_production' => app()->isProduction(), 'direct' => $request->direct, @@ -88,15 +90,24 @@ class DepositController extends Controller public function update(Request $request, DepositHistory $deposit) { $request->validate([ - 'account_id' => 'required|exists:accounts,id', 'image' => 'required|image', ]); + if ($deposit->payment_channel == Setting::PAYMENT_CASH_DEPOSIT) { + $request->validate(['deposit_location_id' => 'required|exists:deposit_locations,id']); + } + + if ($deposit->payment_channel == Setting::PAYMENT_MANUAL) { + $request->validate(['account_id' => 'required|exists:accounts,id']); + } + $file = $request->file('image'); $file->store('uploads', 'public'); + $deposit->update([ 'image_prove' => $file->hashName('uploads'), 'account_id' => $request->account_id, + 'deposit_location_id' => $request->deposit_location_id, 'is_valid' => DepositHistory::STATUS_WAIT_APPROVE, ]); diff --git a/app/Http/Controllers/Customer/ProfileController.php b/app/Http/Controllers/Customer/ProfileController.php index 8ae1d97..280e474 100644 --- a/app/Http/Controllers/Customer/ProfileController.php +++ b/app/Http/Controllers/Customer/ProfileController.php @@ -3,6 +3,7 @@ namespace App\Http\Controllers\Customer; use App\Http\Controllers\Controller; +use App\Models\Setting; use Illuminate\Http\Request; use Illuminate\Support\Facades\Hash; @@ -10,7 +11,10 @@ class ProfileController extends Controller { public function index() { - return inertia('Profile/Index'); + $shareText = Setting::getByKey('AFFILATE_SHARE_REFFERAL_CODE'); + return inertia('Profile/Index', [ + 'share_text' => $shareText + ]); } public function show() diff --git a/app/Models/Customer.php b/app/Models/Customer.php index a6e1b90..dd4c27a 100644 --- a/app/Models/Customer.php +++ b/app/Models/Customer.php @@ -9,6 +9,7 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Relations\HasManyThrough; use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Foundation\Auth\User as Authenticatable; +use Illuminate\Support\Carbon; use Illuminate\Support\Str; class Customer extends Authenticatable @@ -70,6 +71,7 @@ class Customer extends Authenticatable 'is_allow_paylater', 'verification_status', 'status_text', + 'poin_expired_text', ]; protected static function booted(): void @@ -208,6 +210,17 @@ class Customer extends Authenticatable }); } + public function poinExpiredText(): Attribute + { + return Attribute::make(get: function () { + if ($this->poin_expired_at != null) { + $date = Carbon::parse($this->poin_expired_at)->translatedFormat('d F Y'); + return "( kadaluarsa pada $date )"; + } + return ''; + }); + } + public function level() { return $this->belongsTo(CustomerLevel::class, 'customer_level_id'); diff --git a/app/Models/DepositHistory.php b/app/Models/DepositHistory.php index 081a466..f1007df 100644 --- a/app/Models/DepositHistory.php +++ b/app/Models/DepositHistory.php @@ -35,6 +35,7 @@ class DepositHistory extends Model 'is_valid', 'image_prove', 'account_id', + 'deposit_location_id', 'payment_token', 'payment_status', 'payment_response', @@ -67,7 +68,7 @@ class DepositHistory extends Model return Attribute::make(get: function () { return [ 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_UPLOAD => ['text' => 'Upload bukti bayar', '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'], @@ -79,14 +80,14 @@ class DepositHistory extends Model public function formatHumanCreatedAt(): Attribute { return Attribute::make(get: function () { - return Carbon::parse($this->created_at)->locale('id')->translatedFormat('d F Y'); + return Carbon::parse($this->created_at)->translatedFormat('d F Y'); }); } public function formatCreatedAt(): Attribute { return Attribute::make(get: function () { - return Carbon::parse($this->created_at)->locale('id')->translatedFormat('d F Y H:i:s'); + return Carbon::parse($this->created_at)->translatedFormat('d F Y H:i:s'); }); } @@ -118,6 +119,11 @@ class DepositHistory extends Model return $this->belongsTo(Account::class); } + public function depositLocation() + { + return $this->belongsTo(DepositLocation::class, 'deposit_location_id'); + } + public function update_customer_balance() { $customer = Customer::find($this->customer_id); diff --git a/app/Models/Notification.php b/app/Models/Notification.php index f120cc1..cb59b75 100644 --- a/app/Models/Notification.php +++ b/app/Models/Notification.php @@ -35,7 +35,7 @@ class Notification extends Model public function formatCreatedAt(): Attribute { return Attribute::make(get: function () { - return Carbon::parse($this->created_at)->locale('id')->translatedFormat('d F Y H:i:s'); + return Carbon::parse($this->created_at)->translatedFormat('d F Y H:i:s'); }); } } diff --git a/app/Models/PaylaterHistory.php b/app/Models/PaylaterHistory.php index 27b4fc6..1149a44 100644 --- a/app/Models/PaylaterHistory.php +++ b/app/Models/PaylaterHistory.php @@ -30,14 +30,14 @@ class PaylaterHistory extends Model public function formatHumanCreatedAt(): Attribute { return Attribute::make(get: function () { - return Carbon::parse($this->created_at)->locale('id')->translatedFormat('d F Y'); + return Carbon::parse($this->created_at)->translatedFormat('d F Y'); }); } public function formatCreatedAt(): Attribute { return Attribute::make(get: function () { - return Carbon::parse($this->created_at)->locale('id')->translatedFormat('d F Y H:i:s'); + return Carbon::parse($this->created_at)->translatedFormat('d F Y H:i:s'); }); } @@ -45,10 +45,10 @@ class PaylaterHistory extends Model { return Attribute::make(get: function () { if ($this->credit == 0) { - return 'Rp'.number_format($this->debit, is_float($this->debit) ? 2 : 0, ',', '.'); + return 'Rp' . number_format($this->debit, is_float($this->debit) ? 2 : 0, ',', '.'); } - return '-Rp'.number_format($this->credit, is_float($this->credit) ? 2 : 0, ',', '.'); + return '-Rp' . number_format($this->credit, is_float($this->credit) ? 2 : 0, ',', '.'); }); } } diff --git a/app/Models/PoinHistory.php b/app/Models/PoinHistory.php index 50b43fe..ffc1b85 100644 --- a/app/Models/PoinHistory.php +++ b/app/Models/PoinHistory.php @@ -25,14 +25,14 @@ class PoinHistory extends Model public function formatHumanCreatedAt(): Attribute { return Attribute::make(get: function () { - return Carbon::parse($this->created_at)->locale('id')->translatedFormat('d F Y'); + return Carbon::parse($this->created_at)->translatedFormat('d F Y'); }); } public function formatCreatedAt(): Attribute { return Attribute::make(get: function () { - return Carbon::parse($this->created_at)->locale('id')->translatedFormat('d F Y H:i:s'); + return Carbon::parse($this->created_at)->translatedFormat('d F Y H:i:s'); }); } diff --git a/app/Models/Sale.php b/app/Models/Sale.php index 90d6738..047c7b1 100644 --- a/app/Models/Sale.php +++ b/app/Models/Sale.php @@ -49,21 +49,21 @@ class Sale extends Model public function formatHumanCreatedAt(): Attribute { return Attribute::make(get: function () { - return Carbon::parse($this->created_at)->locale('id')->translatedFormat('d F Y'); + return Carbon::parse($this->created_at)->translatedFormat('d F Y'); }); } public function formatCreatedAt(): Attribute { return Attribute::make(get: function () { - return Carbon::parse($this->created_at)->locale('id')->translatedFormat('d F Y H:i:s'); + return Carbon::parse($this->created_at)->translatedFormat('d F Y H:i:s'); }); } public function displayAmount(): Attribute { return Attribute::make(get: function () { - return 'Rp'.number_format($this->amount, is_float($this->amount) ? 2 : 0, ',', '.'); + return 'Rp' . number_format($this->amount, is_float($this->amount) ? 2 : 0, ',', '.'); }); } @@ -72,12 +72,12 @@ class Sale extends Model if ($this->payed_with == self::PAYED_WITH_POIN) { Notification::create([ 'entity_type' => User::class, - 'description' => $this->customer->fullname.' melakukan penukaran '.$this->items()->count().' voucher sebesar '.$this->items->value('price').' poin', + 'description' => $this->customer->fullname . ' melakukan penukaran ' . $this->items()->count() . ' voucher sebesar ' . $this->items->value('price') . ' poin', ]); Notification::create([ 'entity_id' => auth()->id(), - 'description' => 'Transaksi '.$this->code.' berhasil', + 'description' => 'Transaksi ' . $this->code . ' berhasil', ]); return; @@ -85,12 +85,12 @@ class Sale extends Model Notification::create([ 'entity_type' => User::class, - 'description' => $this->customer->fullname.' melakukan pembelian '.$this->items()->count().' voucher sebesar '.$this->display_amount, + 'description' => $this->customer->fullname . ' melakukan pembelian ' . $this->items()->count() . ' voucher sebesar ' . $this->display_amount, ]); Notification::create([ 'entity_id' => auth()->id(), - 'description' => 'Transaksi pembelian anda #'.$this->code.' sebesar '.$this->display_amount.' berhasil', + 'description' => 'Transaksi pembelian anda #' . $this->code . ' sebesar ' . $this->display_amount . ' berhasil', ]); } } diff --git a/app/Services/GeneralService.php b/app/Services/GeneralService.php index fcac01d..c3fc70f 100644 --- a/app/Services/GeneralService.php +++ b/app/Services/GeneralService.php @@ -100,7 +100,7 @@ class GeneralService $payment[] = [ 'name' => Setting::PAYMENT_CASH_DEPOSIT, 'logo' => null, - 'display_name' => 'Setor Tunai di Kantor WBB', + 'display_name' => Setting::getByKey('TEXT_CASH_DEPOSIT'), 'admin_fee' => 0 ]; } diff --git a/config/app.php b/config/app.php index 7a3ea32..1347725 100644 --- a/config/app.php +++ b/config/app.php @@ -82,7 +82,7 @@ return [ | */ - 'locale' => 'en', + 'locale' => 'id', /* |-------------------------------------------------------------------------- diff --git a/database/migrations/2023_05_24_130646_create_deposit_histories_table.php b/database/migrations/2023_05_24_130646_create_deposit_histories_table.php index 0bf3cd3..b6f6f9a 100644 --- a/database/migrations/2023_05_24_130646_create_deposit_histories_table.php +++ b/database/migrations/2023_05_24_130646_create_deposit_histories_table.php @@ -20,6 +20,7 @@ return new class extends Migration $table->text('note')->nullable(); $table->ulid('customer_id')->nullable(); $table->ulid('account_id')->nullable(); + $table->ulid('deposit_location_id')->nullable(); $table->string('related_type')->nullable(); $table->string('related_id')->nullable(); $table->smallInteger('is_valid')->default(0); diff --git a/database/seeders/InstallationSeed.php b/database/seeders/InstallationSeed.php index 46d0a82..1ca0620 100644 --- a/database/seeders/InstallationSeed.php +++ b/database/seeders/InstallationSeed.php @@ -36,15 +36,16 @@ class InstallationSeed extends Seeder ['key' => 'MIDTRANS_CLIENT_KEY', 'value' => 'SB-Mid-client-xqqkspzoZOM10iUG', 'type' => 'text'], ['key' => 'MIDTRANS_MERCHANT_ID', 'value' => 'G561244367', 'type' => 'text'], ['key' => 'MIDTRANS_LOGO', 'value' => 'sample/midtrans_logo.png', 'type' => 'image'], - ['key' => 'MIDTRANS_ENABLED', 'value' => '0', 'type' => 'text'], + ['key' => 'MIDTRANS_ENABLED', 'value' => '1', 'type' => 'text'], ['key' => 'MIDTRANS_ADMIN_FEE', 'value' => '2500', 'type' => 'text'], // deposit - ['key' => 'ENABLE_CASH_DEPOSIT', 'value' => '0', 'type' => 'text'], // deposit by location (on/off) - ['key' => 'ENABLE_MANUAL_TRANSFER', 'value' => '0', 'type' => 'text'], // transfer manual (on/off) + ['key' => 'ENABLE_CASH_DEPOSIT', 'value' => '1', 'type' => 'text'], // deposit by location (on/off) + ['key' => 'TEXT_CASH_DEPOSIT', 'value' => 'Setor Tunai di Kantor WBB', 'type' => 'text'], + ['key' => 'ENABLE_MANUAL_TRANSFER', 'value' => '1', 'type' => 'text'], // transfer manual (on/off) ['key' => 'MAX_MANUAL_TRANSFER_TIMEOUT', 'value' => '2', 'type' => 'text'], // dalam jam - ['key' => 'MANUAL_TRANSFER_OPEN_HOUR', 'value' => '06:00', 'type' => 'text'], - ['key' => 'MANUAL_TRANSFER_CLOSE_HOUR', 'value' => '23:00', 'type' => 'text'], + ['key' => 'MANUAL_TRANSFER_OPEN_HOUR', 'value' => '00:00', 'type' => 'text'], + ['key' => 'MANUAL_TRANSFER_CLOSE_HOUR', 'value' => '23:59', 'type' => 'text'], ['key' => 'MAX_POINT_EXPIRED', 'value' => '90', 'type' => 'text'], //dalam hari ]; diff --git a/resources/js/Customer/Auth/Register.jsx b/resources/js/Customer/Auth/Register.jsx index d0c57f1..f3b820b 100644 --- a/resources/js/Customer/Auth/Register.jsx +++ b/resources/js/Customer/Auth/Register.jsx @@ -9,7 +9,7 @@ import Alert from '@/Components/Alert' import FormInputWith from '@/Components/FormInputWith' import TextArea from '@/Components/TextArea' -export default function Index({ app_name, flash }) { +export default function Index({ referral_code, flash }) { const { data, setData, post, processing, errors } = useForm({ username: '', password: '', @@ -19,7 +19,7 @@ export default function Index({ app_name, flash }) { address: '', phone: '', email: '', - referral_code: '', + referral_code: referral_code, }) const handleOnChange = (event) => { diff --git a/resources/js/Customer/Components/HeaderTrx.jsx b/resources/js/Customer/Components/HeaderTrx.jsx index 2cf7bca..f319a75 100644 --- a/resources/js/Customer/Components/HeaderTrx.jsx +++ b/resources/js/Customer/Components/HeaderTrx.jsx @@ -31,9 +31,7 @@ export default function HeaderTrx({ enable = 'deposit' }) {
{user.display_poin} poin
-
- ( kadaluarsa pada 20 juni 2023 ) -
+
{user.poin_expired_text}
diff --git a/resources/js/Customer/Deposit/Detail.jsx b/resources/js/Customer/Deposit/Detail.jsx index 16728df..eb73203 100644 --- a/resources/js/Customer/Deposit/Detail.jsx +++ b/resources/js/Customer/Deposit/Detail.jsx @@ -1,354 +1,17 @@ -import React, { useState, useEffect } from 'react' -import { Head, router, useForm, usePage } from '@inertiajs/react' -import { isEmpty } from 'lodash' -import { - HiChevronLeft, - HiClipboardDocumentList, - HiOutlineClipboardDocumentCheck, - HiOutlineClipboardDocumentList, -} from 'react-icons/hi2' +import React from 'react' +import { Head, router } from '@inertiajs/react' +import { HiChevronLeft } from 'react-icons/hi2' -import { toastSuccess } from '../utils' import CustomerLayout from '@/Layouts/CustomerLayout' -import FormFile from '@/Components/FormFile' -import Alert from '@/Components/Alert' -import { formatIDR } from '@/utils' -import { STATUS_REJECT } from '@/constant' - -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 ( -
- - {flash.message.message} - -
- Bayar -
-
- ) -} - -const FormUpload = () => { - const { - props: { accounts, deposit, flash }, - } = usePage() - - const [imageUrl, setImageUrl] = useState(deposit.image_prove_url) - 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) - return - } - const account = accounts.find((acc) => acc.id === id) - setData('account_id', account.id) - setAccount(account) - } - - const handleCopyToClipboard = (text) => { - toastSuccess('copied to clipboard') - navigator.clipboard.writeText(text) - } - - const handleSubmit = () => { - if (processing) { - return - } - post(route('transactions.deposit.update', deposit), { - replace: true, - preserveState: true, - onSuccess: () => - setTimeout( - () => router.get(route(route().current(), deposit)), - 3000 - ), - }) - } - - useEffect(() => { - if (deposit.account !== null) { - handleSelectAccount(deposit.account.id) - } - }, [deposit]) - - if (isEmpty(imageUrl) == false) { - return ( -
-
Bukti Transfer
- bukti transfer -
setImageUrl(null)} - > - Ubah Bukti Transfer -
-
- ) - } - - return ( -
-
- - - {flash.message.message} - - -
Bank
- - {account !== null ? ( -
-
handleSelectAccount(account.id)} - > -
- logo bank -
-
- {account.name} - {account.bank_name} -
-
-
handleSelectAccount('')} - > -
Ubah
-
-
- ) : ( -
- {accounts.map((account) => ( -
handleSelectAccount(account.id)} - > -
- logo bank -
-
- {account.name} - {account.bank_name} -
-
- ))} -
- )} -
- {account !== null && ( - <> -
-
-
- - {account.bank_name} - -
-
- Atas Nama :{' '} - - {account.holder_name} - -
-
- handleCopyToClipboard( - account.account_number - ) - } - > -
Nomor Rekening :
-
- {account.account_number} -
- -
-
Rincian
- - - - - - - - - - - - - - handleCopyToClipboard( - +account.admin_fee + - +deposit.debit - ) - } - > - - - - - - -
- Jumlah Deposit - : - - {deposit.amount} - - -
Biaya Admin: - - {+account.admin_fee === 0 ? ( - 'Gratis' - ) : ( - <> - Rp.{' '} - {formatIDR( - +account.admin_fee - )} - - )} - - -
Total Transfer : - - Rp.{' '} - {formatIDR( - +account.admin_fee + - +deposit.debit - )} - - - -
-
-
- -
-
Bukti Transfer
- {isEmpty(data.image_url) == false && ( - bukti transfer - )} -
- setData('image', e.target.files[0])} - error={errors.image} - /> -
- upload gambar dalam ekstensi jpg, png, jpeg -
- -
handleSubmit()} - > - Upload -
- - )} -
- ) -} +import { PayButton } from './DetailPartials/PayButton' +import { FormUploadManual } from './DetailPartials/FormUploadManual' +import { FormUploadCashDeposit } from './DetailPartials/FormUploadCashDeposit' +import { + PAYMENT_CASH_DEPOSIT, + PAYMENT_MANUAL, + PAYMENT_MIDTRANS, + STATUS_REJECT, +} from '@/constant' const ActionSection = ({ deposit }) => { if (deposit.is_valid === STATUS_REJECT) { @@ -364,10 +27,10 @@ const ActionSection = ({ deposit }) => { } return (
- {deposit.payment_channel === 'MIDTRANS' ? ( - - ) : ( - + {deposit.payment_channel === PAYMENT_MIDTRANS && } + {deposit.payment_channel === PAYMENT_MANUAL && } + {deposit.payment_channel === PAYMENT_CASH_DEPOSIT && ( + )}
) @@ -388,8 +51,8 @@ export default function Detail({ deposit }) {
{/* detail */} -
-
+
+
{deposit.description}
diff --git a/resources/js/Customer/Deposit/DetailPartials/FormUploadCashDeposit.jsx b/resources/js/Customer/Deposit/DetailPartials/FormUploadCashDeposit.jsx new file mode 100644 index 0000000..a7ef731 --- /dev/null +++ b/resources/js/Customer/Deposit/DetailPartials/FormUploadCashDeposit.jsx @@ -0,0 +1,242 @@ +import React, { useState, useEffect } from 'react' +import { router, useForm, usePage } from '@inertiajs/react' +import { isEmpty } from 'lodash' +import { HiOutlineClipboardDocumentList } from 'react-icons/hi2' + +import { toastSuccess } from '@/Customer/utils' +import FormFile from '@/Components/FormFile' +import Alert from '@/Components/Alert' + +export const FormUploadCashDeposit = () => { + const { + props: { deposit_locations, deposit, flash }, + } = usePage() + + const [imageUrl, setImageUrl] = useState(deposit.image_prove_url) + const [location, setLocation] = useState(null) + const { data, setData, errors, processing, post } = useForm({ + deposit_location_id: '', + image: null, + image_url: deposit.image_prove_url, + }) + + const handleSelectLocation = (id) => { + if (id === '') { + setData('deposit_location_id', '') + setLocation(null) + return + } + const location = deposit_locations.find((acc) => acc.id === id) + setData('deposit_location_id', location.id) + setLocation(location) + } + + const handleCopyToClipboard = (text) => { + toastSuccess('copied to clipboard') + navigator.clipboard.writeText(text) + } + + const handleSubmit = () => { + if (processing) { + return + } + post(route('transactions.deposit.update', deposit), { + replace: true, + preserveState: true, + onSuccess: () => + setTimeout( + () => router.get(route(route().current(), deposit)), + 3000 + ), + }) + } + + useEffect(() => { + if (deposit.deposit_location !== null) { + handleSelectLocation(deposit.deposit_location_id) + } + }, [deposit]) + + if (isEmpty(imageUrl) == false) { + return ( +
+
Bukti Pembayaran
+ bukti Pembayaran +
setImageUrl(null)} + > + Ubah Bukti Pembayaran +
+
+ ) + } + + return ( +
+
+ + + {flash.message.message} + + +
Lokasi Pembayaran
+ + {location !== null ? ( +
+
handleSelectLocation(location.id)} + > +
+ image location +
+
+
{location.name}
+
+ +62{location.phone} +
+
+ Alamat : {location.address} +
+
+ Jam Buka :{' '} + + {location.operational_hour} + +
+
+
+
handleSelectLocation('')} + > +
Ubah
+
+
+ ) : ( +
+ {deposit_locations.map((location) => ( +
+ handleSelectLocation(location.id) + } + > +
+ image location +
+
+
+ {location.name} +
+
+ +62{location.phone} +
+
+ Alamat : {location.address} +
+
+ Jam Buka :{' '} + + {location.operational_hour} + +
+
+
+ ))} +
+ )} +
+ {location !== null && ( + <> +
+
+
+ + {location.name} + +
+
Alamat : {location.address}
+
+ handleCopyToClipboard( + '+62' + location.phone + ) + } + > +
Whatsapp :
+
+ +62{location.phone} +
+ +
+
Rincian
+ + + + handleCopyToClipboard( + deposit.amount + ) + } + > + + + + + + +
Total Deposit : + + {deposit.amount} + + + +
+
+
+ +
+
Bukti Pembayaran
+ {isEmpty(data.image_url) == false && ( + bukti Pembayaran + )} +
+ setData('image', e.target.files[0])} + error={errors.image} + /> +
+ upload gambar dalam ekstensi jpg, png, jpeg +
+ +
handleSubmit()} + > + Upload +
+ + )} +
+ ) +} diff --git a/resources/js/Customer/Deposit/DetailPartials/FormUploadManual.jsx b/resources/js/Customer/Deposit/DetailPartials/FormUploadManual.jsx new file mode 100644 index 0000000..9afd666 --- /dev/null +++ b/resources/js/Customer/Deposit/DetailPartials/FormUploadManual.jsx @@ -0,0 +1,256 @@ +import React, { useState, useEffect } from 'react' +import { router, useForm, usePage } from '@inertiajs/react' +import { HiOutlineClipboardDocumentList } from 'react-icons/hi2' +import { isEmpty } from 'lodash' + +import { toastSuccess } from '@/Customer/utils' +import { formatIDR } from '@/utils' +import FormFile from '@/Components/FormFile' +import Alert from '@/Components/Alert' + +export const FormUploadManual = () => { + const { + props: { accounts, deposit, flash }, + } = usePage() + + const [imageUrl, setImageUrl] = useState(deposit.image_prove_url) + 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) + return + } + const account = accounts.find((acc) => acc.id === id) + setData('account_id', account.id) + setAccount(account) + } + + const handleCopyToClipboard = (text) => { + toastSuccess('copied to clipboard') + navigator.clipboard.writeText(text) + } + + const handleSubmit = () => { + if (processing) { + return + } + post(route('transactions.deposit.update', deposit), { + replace: true, + preserveState: true, + onSuccess: () => + setTimeout( + () => router.get(route(route().current(), deposit)), + 3000 + ), + }) + } + + useEffect(() => { + if (deposit.account !== null) { + handleSelectAccount(deposit.account.id) + } + }, [deposit]) + + if (isEmpty(imageUrl) == false) { + return ( +
+
Bukti Transfer
+ bukti transfer +
setImageUrl(null)} + > + Ubah Bukti Transfer +
+
+ ) + } + + return ( +
+
+ + + {flash.message.message} + + +
Bank
+ + {account !== null ? ( +
+
handleSelectAccount(account.id)} + > +
+ logo bank +
+
+ {account.name} - {account.bank_name} +
+
+
handleSelectAccount('')} + > +
Ubah
+
+
+ ) : ( +
+ {accounts.map((account) => ( +
handleSelectAccount(account.id)} + > +
+ logo bank +
+
+ {account.name} - {account.bank_name} +
+
+ ))} +
+ )} +
+ {account !== null && ( + <> +
+
+
+ + {account.bank_name} + +
+
+ Atas Nama :{' '} + + {account.holder_name} + +
+
+ handleCopyToClipboard( + account.account_number + ) + } + > +
Nomor Rekening :
+
+ {account.account_number} +
+ +
+
Rincian
+ + + + + + + + + + + + + + handleCopyToClipboard( + +account.admin_fee + + +deposit.debit + ) + } + > + + + + + + +
+ Jumlah Deposit + : + + {deposit.amount} + + +
Biaya Admin: + + {+account.admin_fee === 0 ? ( + 'Gratis' + ) : ( + <> + Rp.{' '} + {formatIDR( + +account.admin_fee + )} + + )} + + +
Total Transfer : + + Rp.{' '} + {formatIDR( + +account.admin_fee + + +deposit.debit + )} + + + +
+
+
+ +
+
Bukti Transfer
+ {isEmpty(data.image_url) == false && ( + bukti transfer + )} +
+ setData('image', e.target.files[0])} + error={errors.image} + /> +
+ upload gambar dalam ekstensi jpg, png, jpeg +
+ +
handleSubmit()} + > + Upload +
+ + )} +
+ ) +} diff --git a/resources/js/Customer/Deposit/DetailPartials/PayButton.jsx b/resources/js/Customer/Deposit/DetailPartials/PayButton.jsx new file mode 100644 index 0000000..61360ef --- /dev/null +++ b/resources/js/Customer/Deposit/DetailPartials/PayButton.jsx @@ -0,0 +1,92 @@ +import React, { useState, useEffect } from 'react' +import { router, usePage } from '@inertiajs/react' + +import Alert from '@/Components/Alert' + +export 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 ( +
+ + {flash.message.message} + +
+ Bayar +
+
+ ) +} diff --git a/resources/js/Customer/Deposit/Topup.jsx b/resources/js/Customer/Deposit/Topup.jsx index b6a44b9..6fdf620 100644 --- a/resources/js/Customer/Deposit/Topup.jsx +++ b/resources/js/Customer/Deposit/Topup.jsx @@ -145,7 +145,7 @@ export default function Topup({ payments }) { )} className="flex flex-row items-center w-full text-sm text-gray-400 py-2 gap-1" > -
Daftar lokasi setor tunai
+
Daftar lokasi pembayaran
ada disini
diff --git a/resources/js/Customer/DepositLocation/Index.jsx b/resources/js/Customer/DepositLocation/Index.jsx index 85425db..d747c8a 100644 --- a/resources/js/Customer/DepositLocation/Index.jsx +++ b/resources/js/Customer/DepositLocation/Index.jsx @@ -24,7 +24,7 @@ export default function Index({ locations: { data, next_page_url } }) { } return ( - +
- Lokasi Setor Tunai + Lokasi Pembayaran
diff --git a/resources/js/Customer/Profile/Index.jsx b/resources/js/Customer/Profile/Index.jsx index 5274539..19855a7 100644 --- a/resources/js/Customer/Profile/Index.jsx +++ b/resources/js/Customer/Profile/Index.jsx @@ -13,7 +13,11 @@ import CustomerLayout from '@/Layouts/CustomerLayout' import ModalConfirm from '@/Components/ModalConfirm' import BalanceBanner from '../Index/Partials/BalanceBanner' -export default function Index({ auth: { user }, notification_count }) { +export default function Index({ + auth: { user }, + notification_count, + share_text, +}) { const confirmModal = useModalState() const handleLogoutClick = () => { @@ -24,8 +28,12 @@ export default function Index({ auth: { user }, notification_count }) { router.post(route('customer.logout')) } - const handleCopyToClipboard = (text) => { + const handleReferalCopyToClipboard = (code) => { toastSuccess('copied to clipboard') + const text = + share_text + + '\n' + + route('customer.register', { referral_code: code }) navigator.clipboard.writeText(text) } @@ -80,7 +88,7 @@ export default function Index({ auth: { user }, notification_count }) { className="p-4 text-blue-800 rounded-lg bg-blue-50 flex flex-row space-x-2 w-full items-center" role="alert" onClick={() => - handleCopyToClipboard(user.referral_code) + handleReferalCopyToClipboard(user.referral_code) } >
Referral Code:
diff --git a/resources/js/Pages/Setting/Affilate.jsx b/resources/js/Pages/Setting/Affilate.jsx index 7943939..bf321d5 100644 --- a/resources/js/Pages/Setting/Affilate.jsx +++ b/resources/js/Pages/Setting/Affilate.jsx @@ -29,8 +29,6 @@ export default function Affilate(props) { ), }) - console.log(data) - const handleCheckLevel = (e, level) => { if (e.target.checked) { const isExists = data.AFFILATE_ALLOWED_LEVELS.find( diff --git a/resources/js/Pages/Setting/Index.jsx b/resources/js/Pages/Setting/Index.jsx index 8432651..a44ca23 100644 --- a/resources/js/Pages/Setting/Index.jsx +++ b/resources/js/Pages/Setting/Index.jsx @@ -17,6 +17,7 @@ export default function General(props) { OPEN_WEBSITE_NAME: extractValue(setting, 'OPEN_WEBSITE_NAME'), SHARE_TEXT: extractValue(setting, 'SHARE_TEXT'), ENABLE_CASH_DEPOSIT: extractValue(setting, 'ENABLE_CASH_DEPOSIT'), + TEXT_CASH_DEPOSIT: extractValue(setting, 'TEXT_CASH_DEPOSIT'), ENABLE_MANUAL_TRANSFER: extractValue(setting, 'ENABLE_MANUAL_TRANSFER'), MAX_MANUAL_TRANSFER_TIMEOUT: extractValue( setting, @@ -100,11 +101,18 @@ export default function General(props) {
+
diff --git a/resources/js/constant.js b/resources/js/constant.js index 9f1fdf2..24a2ed8 100644 --- a/resources/js/constant.js +++ b/resources/js/constant.js @@ -3,3 +3,9 @@ export const DEFAULT_EXPIRED_UNIT = 'Hari' export const STATUS_APPROVE = 0 export const STATUS_REJECT = 5 + +export const PAYMENT_MANUAL = 'MANUAL' + +export const PAYMENT_MIDTRANS = 'MIDTRANS' + +export const PAYMENT_CASH_DEPOSIT = 'CASH_DEPOSIT'