checkout & create payment
This commit is contained in:
parent
d80b42c297
commit
fa00ee377a
|
|
@ -6,6 +6,7 @@ use App\Models\Address;
|
|||
use App\Models\Location;
|
||||
use App\Repositories\Member\Cart\MemberCartRepository;
|
||||
use App\Repositories\Member\ShippingRepository;
|
||||
use App\Repositories\Member\Transaction\TransactionRepository;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class CheckoutController extends Controller
|
||||
|
|
@ -77,6 +78,12 @@ class CheckoutController extends Controller
|
|||
|
||||
$location_id = session('location_id', 22);
|
||||
|
||||
|
||||
if ($delivery_method == null || $address_id == null || $location_id == null) {
|
||||
|
||||
return redirect()->route('checkout.delivery');
|
||||
}
|
||||
|
||||
$subtotal = $memberCartRepository->getSubtotal($location_id);
|
||||
$total = $subtotal;
|
||||
|
||||
|
|
@ -97,11 +104,6 @@ class CheckoutController extends Controller
|
|||
'cost' => $row['shipping_fee'],
|
||||
];
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
return view('checkout.v1-delivery-1-shipping', [
|
||||
'carts' => $request->user()->carts,
|
||||
|
|
@ -113,8 +115,6 @@ class CheckoutController extends Controller
|
|||
'shipping_list' => $shipping_list,
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
dd($e);
|
||||
|
||||
return redirect()->route('checkout.delivery')->with('error', 'Invalid checkout data');
|
||||
}
|
||||
}
|
||||
|
|
@ -131,22 +131,73 @@ class CheckoutController extends Controller
|
|||
|
||||
session(['checkout_courier' => $courier]);
|
||||
session(['checkout_service' => $service]);
|
||||
session(['checkout_shipping_cost' => $cost]);
|
||||
// session(['checkout_shipping_cost' => $cost]);
|
||||
|
||||
return redirect()->route('checkout.payment');
|
||||
}
|
||||
|
||||
public function choosePayment(Request $request)
|
||||
public function choosePayment(Request $request, TransactionRepository $repository, MemberCartRepository $memberCartRepository)
|
||||
{
|
||||
try {
|
||||
|
||||
// proses checkout
|
||||
|
||||
$address_id = session('checkout_address_id');
|
||||
|
||||
$courier = session('checkout_courier');
|
||||
$service = session('checkout_service');
|
||||
|
||||
$location_id = session('location_id', 22);
|
||||
|
||||
$items = [];
|
||||
|
||||
$request->merge(['location_id' => $location_id]);
|
||||
$carts = $memberCartRepository->getList($request);
|
||||
|
||||
if (count($carts) == 0) {
|
||||
return redirect()->route('checkout.delivery')->with('error', 'No items in cart');
|
||||
}
|
||||
|
||||
foreach ($carts as $cart) {
|
||||
$items[] = [
|
||||
"item_reference_id" => $cart->item_reference_id,
|
||||
"qty" => $cart->qty
|
||||
];
|
||||
}
|
||||
|
||||
$data = [
|
||||
"address_id" => $address_id,
|
||||
"note" => "",
|
||||
"courier_company" => $courier,
|
||||
"courier_type" => $service,
|
||||
"location_id" => $location_id,
|
||||
"items" => $items,
|
||||
"vouchers" => [],
|
||||
"use_customer_points" => 0,
|
||||
];
|
||||
|
||||
$item = $repository->create($data);
|
||||
|
||||
$notification = new \App\Notifications\Member\Transaction\OrderWaitPayment($item);
|
||||
$user = auth()->user();
|
||||
$user->notify($notification->delay(now()->addMinutes(1)));
|
||||
|
||||
// return new CheckoutResource($item);
|
||||
|
||||
// proses payment
|
||||
|
||||
|
||||
$payment = $item->payments()->where("method_type",'App\Models\XenditLink')
|
||||
->where("status",'PENDING')
|
||||
->first();
|
||||
$invoice_url = $payment ? @$payment->method->invoice_url: "";
|
||||
|
||||
return redirect()->to($invoice_url);
|
||||
|
||||
|
||||
|
||||
} catch (\Exception $e) {
|
||||
|
||||
dd($e);
|
||||
|
||||
return redirect()->route('checkout.delivery')->with('error', 'Invalid checkout data');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,8 +6,9 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|||
use Illuminate\Database\Eloquent\Model;
|
||||
use Awobaz\Compoships\Compoships;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Cache;
|
||||
|
||||
|
||||
class ItemReference extends Model
|
||||
{
|
||||
|
|
@ -126,9 +127,7 @@ class ItemReference extends Model
|
|||
|
||||
});
|
||||
|
||||
// Log::info([$location_id, $is_consignment]);
|
||||
|
||||
return $this->hasOne(Discount::class,DB::raw("discount_items.item_reference_id"))
|
||||
return $this->hasOne(Discount::class, 'id', 'item_reference_id')
|
||||
->leftJoin("discount_items","discounts.id","=","discount_id")
|
||||
->where("discounts.type","discount")
|
||||
->orderBy("discounts.created_at","desc")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,66 @@
|
|||
<?php
|
||||
|
||||
namespace App\Repositories\Auth;
|
||||
|
||||
use App\Models\Permission;
|
||||
use App\Models\Role;
|
||||
use DB;
|
||||
use Hash;
|
||||
|
||||
class RoleRepository
|
||||
{
|
||||
public function getList(array $params = [])
|
||||
{
|
||||
$limit = @$params["limit"] ? (int) @$params["limit"] : 10;
|
||||
$sortColumn = @$params["sort"]["column"] ? $params["sort"]["column"] : "id";
|
||||
$sortDir = @$params["sort"]["dir"] ? $params["sort"]["dir"] : "desc";
|
||||
|
||||
return Role::when(@$params['search'], function($query) use ($params) {
|
||||
return $query->where('name', 'iLIKE', '%' . $params['search'] . '%');
|
||||
})
|
||||
->orderBy($sortColumn, $sortDir)
|
||||
->paginate($limit);
|
||||
}
|
||||
|
||||
public function getPermission(array $params = [])
|
||||
{
|
||||
return Permission::orderBy("code")->paginate(1000);
|
||||
}
|
||||
|
||||
public function create(array $data)
|
||||
{
|
||||
$item = Role::create($data);
|
||||
$item->permissions()->sync($data["permissions"]);
|
||||
$item->save();
|
||||
return $item;
|
||||
}
|
||||
|
||||
public function update(Role $item, array $data)
|
||||
{
|
||||
$item->update($data);
|
||||
$item->permissions()->sync($data["permissions"]);
|
||||
$item->save();
|
||||
return $item;
|
||||
}
|
||||
|
||||
public function delete(Role $item)
|
||||
{
|
||||
$item->delete();
|
||||
}
|
||||
|
||||
public function findBy($column, $value)
|
||||
{
|
||||
$item = Role::where($column, $value)->firstOrFail();
|
||||
return $item;
|
||||
}
|
||||
|
||||
public function findUserByPermission($code)
|
||||
{
|
||||
$roles = Role::whereHas("permissions", function($query) use ($code){
|
||||
$query->where("code", $code);
|
||||
})->get();
|
||||
return $roles->flatMap(function($role){
|
||||
return $role->users;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Member\Transaction;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Member\Transaction\TransactionRequest;
|
||||
use App\Http\Resources\Member\Transaction\CheckoutResource;
|
||||
use App\Repositories\Member\Transaction\TransactionRepository;
|
||||
use App\Notifications\Member\Transaction\OrderWaitPayment;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
|
||||
class CheckoutController extends Controller
|
||||
{
|
||||
public function index(TransactionRequest $request, TransactionRepository $repository)
|
||||
{
|
||||
$data = $request->validated();
|
||||
$item = $repository->create($data);
|
||||
|
||||
$notification = new OrderWaitPayment($item);
|
||||
$user = auth()->user();
|
||||
$user->notify($notification->delay(now()->addMinutes(1)));
|
||||
|
||||
return new CheckoutResource($item);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,149 @@
|
|||
<?php
|
||||
|
||||
namespace App\Repositories\Member\Voucher;
|
||||
|
||||
use App\Models\Voucher;
|
||||
use App\Models\Customer;
|
||||
use App\Models\User;
|
||||
use App\Models\Cart;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class VoucherRepository
|
||||
{
|
||||
public function getList($request)
|
||||
{
|
||||
$user_id = auth()->user()->id;
|
||||
$customer = Customer::where("user_id", $user_id)->first();
|
||||
$model = Voucher::where('customer_id', (int) @$customer->id)
|
||||
->where('used_at', null)
|
||||
->where('expired_at','>=',Carbon::now())
|
||||
->orderBy('created_at','desc')->paginate($request->limit);
|
||||
|
||||
return $model;
|
||||
}
|
||||
|
||||
|
||||
public function getValidByItems($carts, $customer_id)
|
||||
{
|
||||
$item_reference_ids = $carts->pluck("item_reference_id")->toArray();
|
||||
// collect voucher ids valids
|
||||
if (count($item_reference_ids) == 0){
|
||||
$item_reference_ids[] = 0;
|
||||
}
|
||||
|
||||
$item_ids = implode(',', $item_reference_ids);
|
||||
$ids = DB::select("SELECT distinct vouchers.id from vouchers
|
||||
left join voucher_events on vouchers.voucher_event_id = voucher_events.id
|
||||
left join voucher_items on voucher_items.voucher_event_id = voucher_events.id
|
||||
where used_at is null and
|
||||
(expired_at > now() or expired_at is null) and
|
||||
customer_id = ? and (
|
||||
redeem_point > 0 or
|
||||
( vouchers.voucher_event_id is null and vouchers.item_reference_id is null) or
|
||||
( vouchers.voucher_event_id is not null and voucher_items.item_reference_id is null) or
|
||||
( vouchers.item_reference_id is not null and vouchers.item_reference_id in ($item_ids)) or
|
||||
( vouchers.voucher_event_id is not null and voucher_items.item_reference_id in ($item_ids))
|
||||
)",[$customer_id]);
|
||||
$ids = collect($ids)->pluck("id")->toArray();
|
||||
return $ids;
|
||||
}
|
||||
|
||||
public function getSum($params)
|
||||
{
|
||||
$user_id = auth()->user()->id;
|
||||
$customer = Customer::where("user_id", $user_id)->firstOrFail();
|
||||
$voucher_ids = $params["voucher_ids"];
|
||||
// collect item_reference_ids
|
||||
$cart_ids = @$params["cart_ids"] ?? [];
|
||||
$carts = Cart::where("user_id", $user_id)
|
||||
->where(function($query) use ($cart_ids){
|
||||
if (count($cart_ids)){
|
||||
$query->whereIn("id", $cart_ids);
|
||||
}
|
||||
})
|
||||
->get();
|
||||
$ids = $this->getValidByItems($carts, $customer->id);
|
||||
|
||||
return Voucher::where('customer_id', (int) @$customer->id)
|
||||
->where('used_at', null)
|
||||
->whereIn('id', $ids)
|
||||
->whereIn('id', $ids)
|
||||
->orderBy('created_at','desc')
|
||||
->get();
|
||||
}
|
||||
|
||||
public function getValid($params)
|
||||
{
|
||||
$user_id = auth()->user()->id;
|
||||
$customer = Customer::where("user_id", $user_id)->first();
|
||||
$limit = $params["limit"] ?? 10;
|
||||
|
||||
// collect item_reference_ids
|
||||
$cart_ids = @$params["cart_ids"] ?? [];
|
||||
$carts = Cart::where("user_id", $user_id)
|
||||
->where(function($query) use ($cart_ids){
|
||||
if (count($cart_ids)){
|
||||
$query->whereIn("id", $cart_ids);
|
||||
}
|
||||
})
|
||||
->get();
|
||||
|
||||
$ids = $this->getValidByItems($carts, $customer->id);
|
||||
|
||||
return Voucher::where('customer_id', (int) @$customer->id)
|
||||
->where('used_at', null)
|
||||
->orderBy('created_at','desc')->paginate($limit)
|
||||
->transform(function ($voucher, $key) use ($ids) {
|
||||
$voucher->is_valid = in_array($voucher->id, $ids);
|
||||
return $voucher;
|
||||
});
|
||||
}
|
||||
|
||||
public function detail($id)
|
||||
{
|
||||
$model = Voucher::findOrFail($id);
|
||||
return $model;
|
||||
}
|
||||
|
||||
public function send($id, $data)
|
||||
{
|
||||
$model = DB::transaction(function () use ($id, $data) {
|
||||
|
||||
$customer = Customer::where("user_id", $data['customer_id'])->firstOrFail();
|
||||
$model = Voucher::findOrFail($id);
|
||||
|
||||
\Log::info("VOUCHER SEND FROM ".$model->customer_id." TO ".$customer->id);
|
||||
|
||||
$model->customer_id = $customer->id;
|
||||
$model->save();
|
||||
|
||||
return $model;
|
||||
});
|
||||
|
||||
return $model;
|
||||
}
|
||||
|
||||
public function phoneCheck($data)
|
||||
{
|
||||
$model = DB::transaction(function () use ($data) {
|
||||
|
||||
$model = Customer::where('phone', $data['phone'])->first();
|
||||
|
||||
if ($model->user_id == null) {
|
||||
|
||||
throw ValidationException::withMessages([
|
||||
"phone" => "User dari phone number belum terdaftar"
|
||||
]);
|
||||
}
|
||||
|
||||
$model = User::findOrfail($model->user_id);
|
||||
|
||||
return $model;
|
||||
});
|
||||
|
||||
return $model;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
namespace App\ThirdParty\Xendit;
|
||||
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
|
||||
class Xendit
|
||||
{
|
||||
public function createPaymentLink($payload){
|
||||
|
||||
$url = "https://api.xendit.co/v2/invoices";
|
||||
$key = env("XENDIT_PRIVATE_KEY");
|
||||
$res = Http::withBasicAuth($key, "")
|
||||
->withBody(json_encode($payload), 'application/json')
|
||||
->post($url);
|
||||
|
||||
if ($res->status() == 200)
|
||||
return $res->json();
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -37,9 +37,7 @@
|
|||
</h1>
|
||||
<form action="{{ route('checkout.shipping.process') }}" method="post">
|
||||
@csrf
|
||||
<input type="hidden" name="delivery_method" value="{{ $delivery_method }}">
|
||||
<input type="hidden" name="address_id" value="{{ $address_id }}">
|
||||
|
||||
|
||||
@if ($delivery_method == 'shipping')
|
||||
@foreach ($shipping_list as $shipping)
|
||||
<div class="form-check mb-3">
|
||||
|
|
@ -100,360 +98,137 @@
|
|||
@section('scripts')
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Delivery method selection
|
||||
const deliveryOption = document.getElementById('deliveryOption');
|
||||
const pickupOption = document.getElementById('pickupOption');
|
||||
const deliveryOptions = document.getElementById('deliveryOptions');
|
||||
const pickupOptions = document.getElementById('pickupOptions');
|
||||
const shippingAddress = document.getElementById('shippingAddress');
|
||||
const continueButton = document.getElementById('continueButton');
|
||||
// Shipping option selection handler
|
||||
const shippingRadios = document.querySelectorAll('input[name="shipping_option"]');
|
||||
console.log('Found shipping radios:', shippingRadios.length);
|
||||
|
||||
// Handle delivery method change
|
||||
deliveryOption.addEventListener('change', function() {
|
||||
if (this.checked) {
|
||||
deliveryOptions.style.display = 'block';
|
||||
pickupOptions.style.display = 'none';
|
||||
resetPickupSelection();
|
||||
// Update button text for delivery
|
||||
document.getElementById('continueButtonText').textContent =
|
||||
'{{ __('checkout.continue_to_shipping') }}';
|
||||
// Update hidden input values
|
||||
document.getElementById('deliveryMethodInput').value = 'delivery';
|
||||
// Update address ID from selected address
|
||||
const addressSelect = document.getElementById('addressSelect');
|
||||
if (addressSelect && addressSelect.value) {
|
||||
document.getElementById('addressIdInput').value = addressSelect.value;
|
||||
}
|
||||
// Show shipping address step and shipping row
|
||||
const shippingAddressStep = document.getElementById('shippingAddressStep');
|
||||
const shippingRow = document.getElementById('shipping-row');
|
||||
if (shippingAddressStep) {
|
||||
console.log("Showing shipping address step");
|
||||
shippingAddressStep.style.visibility = 'visible';
|
||||
shippingAddressStep.style.height = 'auto';
|
||||
shippingAddressStep.style.overflow = 'visible';
|
||||
shippingAddressStep.style.margin = '';
|
||||
shippingAddressStep.style.padding = '';
|
||||
}
|
||||
if (shippingRow) {
|
||||
console.log("Showing shipping row");
|
||||
shippingRow.style.visibility = 'visible';
|
||||
shippingRow.style.height = 'auto';
|
||||
shippingRow.style.overflow = 'visible';
|
||||
shippingRow.style.margin = '';
|
||||
shippingRow.style.padding = '';
|
||||
} else {
|
||||
console.log("Shipping row not found");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
pickupOption.addEventListener('change', function() {
|
||||
if (this.checked) {
|
||||
deliveryOptions.style.display = 'none';
|
||||
pickupOptions.style.display = 'block';
|
||||
resetDeliverySelection();
|
||||
// Update button text for pickup
|
||||
document.getElementById('continueButtonText').textContent =
|
||||
'{{ __('checkout.continue_to_payment') }}';
|
||||
// Update hidden input values
|
||||
document.getElementById('deliveryMethodInput').value = 'pickup';
|
||||
document.getElementById('addressIdInput').value = '';
|
||||
// Hide shipping address step and shipping row
|
||||
const shippingAddressStep = document.getElementById('shippingAddressStep');
|
||||
const shippingRow = document.getElementById('shipping-row');
|
||||
console.log("Elements found:", shippingAddressStep, shippingRow);
|
||||
if (shippingAddressStep) {
|
||||
console.log("Hiding shipping address step");
|
||||
shippingAddressStep.style.visibility = 'hidden';
|
||||
shippingAddressStep.style.height = '0';
|
||||
shippingAddressStep.style.overflow = 'hidden';
|
||||
shippingAddressStep.style.margin = '0';
|
||||
shippingAddressStep.style.padding = '0';
|
||||
}
|
||||
if (shippingRow) {
|
||||
console.log("Hiding shipping row");
|
||||
shippingRow.style.visibility = 'hidden';
|
||||
shippingRow.style.height = '0';
|
||||
shippingRow.style.overflow = 'hidden';
|
||||
shippingRow.style.margin = '0';
|
||||
shippingRow.style.padding = '0';
|
||||
} else {
|
||||
console.log("Shipping row not found");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Address selection handler
|
||||
const addressSelect = document.getElementById('addressSelect');
|
||||
if (addressSelect) {
|
||||
// Auto-populate form with first selected address on page load
|
||||
function populateAddressForm() {
|
||||
const selectedOption = addressSelect.options[addressSelect.selectedIndex];
|
||||
|
||||
if (selectedOption && selectedOption.value) {
|
||||
// Populate all shipping address form fields
|
||||
document.getElementById('firstName').value = selectedOption.dataset.firstName || '';
|
||||
document.getElementById('lastName').value = selectedOption.dataset.lastName || '';
|
||||
document.getElementById('address').value = selectedOption.dataset.address || '';
|
||||
document.getElementById('city').value = selectedOption.dataset.city || '';
|
||||
document.getElementById('state').value = selectedOption.dataset.state || '';
|
||||
document.getElementById('zip').value = selectedOption.dataset.postcode || '';
|
||||
document.getElementById('phone').value = selectedOption.dataset.phone || '';
|
||||
document.getElementById('postcode').value = selectedOption.dataset.postcode || '';
|
||||
|
||||
// Update order summary with postcode
|
||||
if (selectedOption.dataset.postcode) {
|
||||
updateOrderSummaryWithShipping();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Populate on page load
|
||||
populateAddressForm();
|
||||
// Set initial address ID
|
||||
if (addressSelect.value) {
|
||||
document.getElementById('addressIdInput').value = addressSelect.value;
|
||||
}
|
||||
|
||||
addressSelect.addEventListener('change', function() {
|
||||
const selectedOption = this.options[this.selectedIndex];
|
||||
|
||||
if (this.value === 'new' || this.value === '') {
|
||||
// Clear form fields for new address
|
||||
document.getElementById('firstName').value = '';
|
||||
document.getElementById('lastName').value = '';
|
||||
document.getElementById('address').value = '';
|
||||
document.getElementById('city').value = '';
|
||||
document.getElementById('state').value = '';
|
||||
document.getElementById('zip').value = '';
|
||||
document.getElementById('phone').value = '';
|
||||
document.getElementById('postcode').value = '';
|
||||
// Clear address ID input
|
||||
document.getElementById('addressIdInput').value = '';
|
||||
} else {
|
||||
// Populate form fields with selected address
|
||||
document.getElementById('firstName').value = selectedOption.dataset.firstName || '';
|
||||
document.getElementById('lastName').value = selectedOption.dataset.lastName || '';
|
||||
document.getElementById('address').value = selectedOption.dataset.address || '';
|
||||
document.getElementById('city').value = selectedOption.dataset.city || '';
|
||||
document.getElementById('state').value = selectedOption.dataset.state || '';
|
||||
document.getElementById('zip').value = selectedOption.dataset.postcode || '';
|
||||
document.getElementById('phone').value = selectedOption.dataset.phone || '';
|
||||
document.getElementById('postcode').value = selectedOption.dataset.postcode || '';
|
||||
// Update address ID input
|
||||
document.getElementById('addressIdInput').value = this.value;
|
||||
|
||||
// Update order summary with postcode
|
||||
if (selectedOption.dataset.postcode) {
|
||||
updateOrderSummaryWithShipping();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Auto-update order summary when postcode changes
|
||||
document.getElementById('postcode').addEventListener('input', function() {
|
||||
if (this.value) {
|
||||
updateOrderSummaryWithShipping();
|
||||
}
|
||||
});
|
||||
|
||||
// Store selection for pickup
|
||||
const storeRadios = document.querySelectorAll('input[name="store"]');
|
||||
storeRadios.forEach(radio => {
|
||||
shippingRadios.forEach((radio, index) => {
|
||||
console.log(`Radio ${index}:`, radio.value, radio.checked);
|
||||
radio.addEventListener('change', function() {
|
||||
console.log('Shipping option changed:', this.value, this.checked);
|
||||
if (this.checked) {
|
||||
updateOrderSummaryForPickup();
|
||||
updateOrderSummaryWithShippingCost(this.value);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Form validation before continue
|
||||
continueButton.addEventListener('click', function(e) {
|
||||
const selectedMethod = document.querySelector('input[name="deliveryMethod"]:checked').value;
|
||||
function updateOrderSummaryWithShippingCost(shippingValue) {
|
||||
console.log('updateOrderSummaryWithShippingCost called with:', shippingValue);
|
||||
|
||||
if (selectedMethod === 'delivery') {
|
||||
if (!validateDeliveryForm()) {
|
||||
e.preventDefault();
|
||||
return;
|
||||
}
|
||||
} else if (selectedMethod === 'pickup') {
|
||||
if (!validatePickupForm()) {
|
||||
e.preventDefault();
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function resetDeliverySelection() {
|
||||
resetShippingCalculation();
|
||||
}
|
||||
|
||||
function resetPickupSelection() {
|
||||
document.querySelectorAll('input[name="store"]').forEach(radio => {
|
||||
radio.checked = false;
|
||||
});
|
||||
resetShippingCalculation();
|
||||
}
|
||||
|
||||
function resetShippingCalculation() {
|
||||
// Reset order summary to original state
|
||||
const shippingElement = document.querySelector('[data-shipping-cost]');
|
||||
if (shippingElement) {
|
||||
shippingElement.style.display = 'none';
|
||||
// Parse the shipping value: courier|service|cost
|
||||
const parts = shippingValue.split('|');
|
||||
console.log('Parsed parts:', parts);
|
||||
if (parts.length !== 3) {
|
||||
console.log('Invalid shipping value format');
|
||||
return;
|
||||
}
|
||||
|
||||
const totalElement = document.getElementById('cart-estimated-total');
|
||||
if (totalElement && window.originalTotal) {
|
||||
totalElement.textContent = `Rp ${window.originalTotal}`;
|
||||
}
|
||||
}
|
||||
|
||||
function updateOrderSummaryWithShipping() {
|
||||
// Simulate shipping cost calculation based on postcode
|
||||
const shippingCost = calculateShippingCost(document.getElementById('postcode').value);
|
||||
const courier = parts[0];
|
||||
const service = parts[1];
|
||||
const cost = parseInt(parts[2]);
|
||||
console.log('Extracted cost:', cost);
|
||||
|
||||
// Update order summary
|
||||
const subtotalElement = document.getElementById('cart-subtotal');
|
||||
console.log('Subtotal element:', subtotalElement);
|
||||
if (!subtotalElement) {
|
||||
console.log('Subtotal element not found');
|
||||
return;
|
||||
}
|
||||
|
||||
const currentSubtotal = parseFloat(subtotalElement.textContent.replace(/[^\d]/g, ''));
|
||||
const newTotal = currentSubtotal + shippingCost;
|
||||
console.log('Current subtotal:', currentSubtotal);
|
||||
const newTotal = currentSubtotal + cost;
|
||||
console.log('New total:', newTotal);
|
||||
|
||||
// Store original total
|
||||
if (!window.originalTotal) {
|
||||
window.originalTotal = subtotalElement.textContent;
|
||||
console.log('Stored original total:', window.originalTotal);
|
||||
}
|
||||
|
||||
// Update total
|
||||
const totalElement = document.getElementById('cart-estimated-total');
|
||||
totalElement.textContent = `Rp ${number_format(newTotal, 0, ',', '.')}`;
|
||||
console.log('Total element:', totalElement);
|
||||
if (totalElement) {
|
||||
totalElement.textContent = `Rp ${number_format(newTotal, 0, ',', '.')}`;
|
||||
console.log('Updated total to:', totalElement.textContent);
|
||||
}
|
||||
|
||||
// Show shipping cost in summary
|
||||
showShippingCost(shippingCost);
|
||||
}
|
||||
|
||||
function updateOrderSummaryForPickup() {
|
||||
// Pickup is usually free
|
||||
const subtotalElement = document.getElementById('cart-subtotal');
|
||||
const currentSubtotal = parseFloat(subtotalElement.textContent.replace(/[^\d]/g, ''));
|
||||
|
||||
// Store original total
|
||||
if (!window.originalTotal) {
|
||||
window.originalTotal = subtotalElement.textContent;
|
||||
}
|
||||
|
||||
// Update total (same as subtotal for pickup)
|
||||
const totalElement = document.getElementById('cart-estimated-total');
|
||||
totalElement.textContent = subtotalElement.textContent;
|
||||
|
||||
// Show free shipping
|
||||
showShippingCost(0, true);
|
||||
}
|
||||
|
||||
function calculateShippingCost(postcode) {
|
||||
// Simple shipping cost calculation based on postcode
|
||||
// In real implementation, this would call an API
|
||||
const jakartaPostcodes = ['10000', '10110', '10220', '10310', '10410'];
|
||||
const bandungPostcodes = ['40111', '40112', '40113', '40114', '40115'];
|
||||
|
||||
if (jakartaPostcodes.includes(postcode)) {
|
||||
return 15000; // Jakarta: Rp 15,000
|
||||
} else if (bandungPostcodes.includes(postcode)) {
|
||||
return 25000; // Bandung: Rp 25,000
|
||||
} else {
|
||||
return 35000; // Other areas: Rp 35,000
|
||||
}
|
||||
showShippingCost(cost);
|
||||
}
|
||||
|
||||
function showShippingCost(cost, isFree = false) {
|
||||
// Find or create shipping cost element in order summary
|
||||
let shippingElement = document.querySelector('[data-shipping-cost]');
|
||||
console.log('showShippingCost called with:', cost, isFree);
|
||||
|
||||
if (!shippingElement) {
|
||||
const orderSummary = document.querySelector('.list-unstyled');
|
||||
const shippingLi = document.createElement('li');
|
||||
shippingLi.className = 'd-flex justify-content-between';
|
||||
shippingLi.setAttribute('data-shipping-cost', '');
|
||||
shippingLi.innerHTML = `
|
||||
<span>{{ __('checkout.shipping') }}:</span>
|
||||
<span class="text-dark-emphasis fw-medium" id="shipping-cost">Rp 0</span>
|
||||
`;
|
||||
orderSummary.appendChild(shippingLi);
|
||||
shippingElement = shippingLi;
|
||||
// Use existing shipping row in order summary
|
||||
const shippingRow = document.getElementById('shipping-row');
|
||||
console.log('Shipping row element:', shippingRow);
|
||||
if (!shippingRow) {
|
||||
console.log('Shipping row not found');
|
||||
return;
|
||||
}
|
||||
|
||||
const costElement = shippingRow.querySelector('span:last-child');
|
||||
console.log('Cost element:', costElement);
|
||||
if (!costElement) {
|
||||
console.log('Cost element not found');
|
||||
return;
|
||||
}
|
||||
|
||||
const costElement = document.getElementById('shipping-cost');
|
||||
if (isFree) {
|
||||
costElement.textContent = '{{ __('checkout.free') }}';
|
||||
costElement.className = 'text-success fw-medium';
|
||||
console.log('Set to free shipping');
|
||||
} else {
|
||||
costElement.textContent = `Rp ${number_format(cost, 0, ',', '.')}`;
|
||||
costElement.className = 'text-dark-emphasis fw-medium';
|
||||
console.log('Set shipping cost to:', costElement.textContent);
|
||||
}
|
||||
|
||||
shippingElement.style.display = 'flex';
|
||||
// Ensure the shipping row is visible
|
||||
shippingRow.style.display = 'flex';
|
||||
console.log('Made shipping row visible');
|
||||
}
|
||||
|
||||
function validateDeliveryForm() {
|
||||
const postcode = document.getElementById('postcode').value;
|
||||
const firstName = document.getElementById('firstName').value;
|
||||
const address = document.getElementById('address').value;
|
||||
const city = document.getElementById('city').value;
|
||||
const phone = document.getElementById('phone').value;
|
||||
|
||||
if (!postcode) {
|
||||
alert('{{ __('checkout.enter_postcode') }}');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!firstName || !address || !city || !phone) {
|
||||
alert('{{ __('checkout.fill_required_fields') }}');
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
// Initialize shipping cost on page load for checked option
|
||||
const checkedShippingRadio = document.querySelector('input[name="shipping_option"]:checked');
|
||||
console.log('Checked shipping radio on load:', checkedShippingRadio);
|
||||
if (checkedShippingRadio) {
|
||||
console.log('Initializing with value:', checkedShippingRadio.value);
|
||||
updateOrderSummaryWithShippingCost(checkedShippingRadio.value);
|
||||
}
|
||||
|
||||
function validatePickupForm() {
|
||||
const selectedStore = document.querySelector('input[name="store"]:checked');
|
||||
// Number formatting helper
|
||||
function number_format(number, decimals, dec_point, thousands_sep) {
|
||||
number = (number + '').replace(/[^0-9+\-Ee.]/g, '');
|
||||
var n = !isFinite(+number) ? 0 : +number;
|
||||
var prec = !isFinite(+decimals) ? 0 : Math.abs(decimals);
|
||||
var sep = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep;
|
||||
var dec = (typeof dec_point === 'undefined') ? '.' : dec_point;
|
||||
|
||||
if (!selectedStore) {
|
||||
alert('{{ __('checkout.select_store') }}');
|
||||
return false;
|
||||
var s = '';
|
||||
var toFixedFix = function(n, prec) {
|
||||
var k = Math.pow(10, prec);
|
||||
return '' + Math.round(n * k) / k;
|
||||
};
|
||||
|
||||
s = (prec ? toFixedFix(n, prec) : '' + Math.round(n)).split('.');
|
||||
if (thousands_sep) {
|
||||
var re = /(-?\d+)(\d{3})/;
|
||||
while (re.test(s[0])) {
|
||||
s[0] = s[0].replace(re, '$1' + sep + '$2');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Number formatting helper
|
||||
function number_format(number, decimals, dec_point, thousands_sep) {
|
||||
number = (number + '').replace(/[^0-9+\-Ee.]/g, '');
|
||||
var n = !isFinite(+number) ? 0 : +number;
|
||||
var prec = !isFinite(+decimals) ? 0 : Math.abs(decimals);
|
||||
var sep = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep;
|
||||
var dec = (typeof dec_point === 'undefined') ? '.' : dec_point;
|
||||
|
||||
var s = '';
|
||||
var toFixedFix = function(n, prec) {
|
||||
var k = Math.pow(10, prec);
|
||||
return '' + Math.round(n * k) / k;
|
||||
};
|
||||
|
||||
s = (prec ? toFixedFix(n, prec) : '' + Math.round(n)).split('.');
|
||||
if (thousands_sep) {
|
||||
var re = /(-?\d+)(\d{3})/;
|
||||
while (re.test(s[0])) {
|
||||
s[0] = s[0].replace(re, '$1' + sep + '$2');
|
||||
}
|
||||
}
|
||||
|
||||
if ((s[1] || '').length < prec) {
|
||||
s[1] = s[1] || '';
|
||||
s[1] += new Array(prec - s[1].length + 1).join('0');
|
||||
}
|
||||
|
||||
return s.join(dec);
|
||||
if ((s[1] || '').length < prec) {
|
||||
s[1] = s[1] || '';
|
||||
s[1] += new Array(prec - s[1].length + 1).join('0');
|
||||
}
|
||||
|
||||
return s.join(dec);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@endsection
|
||||
|
|
|
|||
|
|
@ -8,6 +8,13 @@
|
|||
<div class="container py-5">
|
||||
<div class="row pt-1 pt-sm-3 pt-lg-4 pb-2 pb-md-3 pb-lg-4 pb-xl-5">
|
||||
|
||||
{{-- show error message --}}
|
||||
@if(session('error'))
|
||||
<div class="alert alert-danger">
|
||||
{{ session('error') }}
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<!-- Delivery info (Step 1) -->
|
||||
<div class="col-lg-8 col-xl-7 mb-5 mb-lg-0">
|
||||
<div class="d-flex flex-column gap-5 pe-lg-4 pe-xl-0">
|
||||
|
|
|
|||
Loading…
Reference in New Issue