Server : Apache/2.4.18 (Ubuntu) System : Linux canvaswebdesign 3.13.0-71-generic #114-Ubuntu SMP Tue Dec 1 02:34:22 UTC 2015 x86_64 User : oppastar ( 1041) PHP Version : 7.0.33-0ubuntu0.16.04.15 Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority, Directory : /var/www/laciasmara.com/public_html/shop/application/views/admin_new/orders/ |
Upload File : |
<main class="flex-1 py-4 px-4 bg-purple-50"> <?php if ($this->session->flashdata('message')): ?> <div class="alert flex items-center justify-between bg-<?php echo $this->session->flashdata('message_type') === 'success' ? 'green' : 'red'; ?>-100 border-l-4 border-<?php echo $this->session->flashdata('message_type') === 'success' ? 'green' : 'red'; ?>-500 text-<?php echo $this->session->flashdata('message_type') === 'success' ? 'green' : 'red'; ?>-800 px-6 py-4 rounded-lg shadow-lg transition transform duration-300"> <div class="flex items-center"> <!-- Ikon Feather sesuai jenis pesan --> <i data-feather="<?php echo $this->session->flashdata('message_type') === 'success' ? 'check-circle' : 'x-circle'; ?>" class="h-6 w-6 mr-3"></i> <span class="font-semibold"><?php echo $this->session->flashdata('message'); ?></span> </div> <button class="ml-4 text-<?php echo $this->session->flashdata('message_type') === 'success' ? 'green' : 'red'; ?>-500 hover:text-<?php echo $this->session->flashdata('message_type') === 'success' ? 'green' : 'red'; ?>-700 focus:outline-none" onclick="this.parentElement.style.display='none'"> <i data-feather="x" class="h-5 w-5"></i> </button> </div> <script> feather.replace(); </script> <?php endif; ?> <form action="<?= base_url('admin/orders/create_order') ?>" method="POST" class="mx-auto space-y-4" id="orderForm"> <input type="hidden" name="<?= $this->security->get_csrf_token_name() ?>" value="<?= $this->security->get_csrf_hash() ?>" class="csrf_token"> <!-- Header --> <div class="bg-white rounded-xl shadow-sm border border-gray-200 p-6"> <div class="flex items-center justify-between"> <div> <h1 class="text-2xl font-bold text-gray-900">Tambah Pesanan Baru</h1> <p class="text-gray-600 mt-1">Lengkapi informasi pesanan pelanggan</p> </div> <div class="flex items-center space-x-2"> <div class="w-3 h-3 bg-blue-400 rounded-full"></div> <span class="text-sm text-gray-600">Pesanan Baru</span> </div> </div> </div> <!-- Marketplace Order Section --> <div class="bg-white rounded-xl shadow-sm border border-gray-200"> <div class="bg-gradient-to-r from-purple-50 to-pink-50 px-6 py-4 border-b border-gray-200"> <div class="flex items-center space-x-3"> <div class="w-8 h-8 bg-purple-500 rounded-lg flex items-center justify-center"> <svg class="w-4 h-4 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 11V7a4 4 0 00-8 0v4M8 11v6h8v-6M8 11H6a2 2 0 00-2 2v6a2 2 0 002 2h12a2 2 0 002-2v-6a2 2 0 00-2-2h-2"></path> </svg> </div> <h2 class="text-lg font-semibold text-gray-900">Jenis Pesanan</h2> </div> </div> <div class="p-6"> <div class="grid md:grid-cols-3 gap-6 items-start"> <div class="space-y-2"> <label class="flex items-center text-sm font-medium text-gray-700"> Pesanan Marketplace? <span class="ml-2 inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-gray-100 text-gray-600"> Opsional </span> </label> <p class="text-xs text-gray-500">Centang jika pesanan berasal dari marketplace (Tokopedia)</p> </div> <div class="flex items-center space-x-3"> <label class="relative inline-flex items-center cursor-pointer"> <input id="is_marketplace" type="checkbox" name="is_marketplace" class="sr-only peer" value="1"> <div class="w-11 h-6 bg-gray-400 peer-focus:outline-none peer-focus:ring-2 peer-focus:ring-purple-500 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-purple-500"></div> </label> <span id="marketplaceOrder" class="text-sm text-gray-700">Ini pesanan website</span> </div> <div id="marketplaceBadge" class="hidden"> <span class="inline-flex items-center px-3 py-1 rounded-full text-xs font-medium bg-purple-100 text-purple-800"> Pesanan Marketplace - Tokopedia </span> </div> </div> </div> </div> <!-- Tokopedia Invoice Section --> <div class="bg-white rounded-xl shadow-sm border border-gray-200 hidden" id="invoiceSection"> <div class="bg-gradient-to-r from-orange-50 to-amber-50 px-6 py-4 border-b border-gray-200"> <div class="flex items-center space-x-3"> <div class="w-8 h-8 bg-orange-500 rounded-lg flex items-center justify-center"> <svg class="w-4 h-4 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path> </svg> </div> <h2 class="text-lg font-semibold text-gray-900">Invoice Tokopedia</h2> </div> </div> <div class="p-6"> <div class="space-y-2"> <label for="tokopedia_invoice" class="flex items-center text-sm font-medium text-gray-700"> Tokopedia Invoice <span class="ml-2 inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-red-100 text-red-800"> Wajib </span> </label> <input id="tokopedia_invoice" type="text" name="tokopedia_invoice" placeholder="Masukkan Invoice Tokopedia" autocomplete="off" class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-1 focus:ring-purple-500 focus:border-purple-500 transition-colors text-gray-900 placeholder-gray-500" /> <p class="text-xs text-gray-500">Wajib diisi untuk pesanan marketplace</p> </div> </div> </div> <!-- Hidden Fields --> <input type="hidden" name="selected_address_id" id="selected_address_id"> <input type="hidden" name="address" id="address"> <input type="hidden" name="address_notes" id="address_notes"> <input type="hidden" name="shipping_subdistrict" id="shipping_subdistrict"> <input type="hidden" name="shipping_district" id="shipping_district"> <input type="hidden" name="shipping_province" id="shipping_province"> <input type="hidden" name="shipping_city" id="shipping_city"> <input type="hidden" name="shipping_phone" id="shipping_phone"> <input type="hidden" name="shipping_lat" id="shipping_lat"> <input type="hidden" name="shipping_lng" id="shipping_lng"> <input type="hidden" name="shipping_postcode" id="shipping_postcode"> <input type="hidden" name="email" id="email"> <input type="hidden" name="name" id="name"> <input type="hidden" name="id_customers" id="id_customers"> <!-- Customer Information Section --> <div class="bg-white rounded-xl shadow-sm border border-gray-200" id="customerSection"> <div class="bg-gradient-to-r from-blue-50 to-indigo-50 px-6 py-4 border-b border-gray-200"> <div class="flex items-center space-x-3"> <div class="w-8 h-8 bg-blue-500 rounded-lg flex items-center justify-center"> <svg class="w-4 h-4 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"></path> </svg> </div> <h2 class="text-lg font-semibold text-gray-900">Informasi Pelanggan</h2> </div> </div> <div class="p-6"> <!-- Customer Selection Row --> <div class="space-y-2"> <!-- Customer --> <div class="space-y-2"> <label for="customer" class="flex items-center text-sm font-medium text-gray-700 mb-2"> Pelanggan <span class="ml-2 inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-red-100 text-red-800"> Wajib </span> </label> <select name="customer" id="customer" class="w-full"> <option value="">Pilih atau Ketik Nama Customer</option> <?php foreach ($customers as $customer) : ?> <option value="<?= $customer->id_customers ?>"><?= $customer->name ?></option> <?php endforeach; ?> </select> <p class="text-xs text-gray-500">Jangan sampai salah memilih pelanggan</p> </div> </div> <!-- Hidden Fields --> <div id="addressSelectionContainer" class="hidden mt-4"> <div class="space-y-2"> <label class="flex items-center text-sm font-medium text-gray-700"> Pilih Alamat Pengiriman <span class="ml-2 inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-red-100 text-red-800"> Wajib </span> </label> <p class="text-xs text-gray-500 mb-4">Pilih salah satu alamat pengiriman pelanggan</p> </div> <!-- Loading State --> <div id="addressLoading" class="flex items-center justify-center py-8"> <div class="flex items-center space-x-3"> <div class="w-6 h-6 border-2 border-gray-200 border-t-purple-500 rounded-full animate-spin"></div> <span class="text-gray-600">Memuat alamat pelanggan...</span> </div> </div> <!-- Address Cards Container --> <div id="addressCardsContainer" class="space-y-4 hidden mt-2"> <!-- Address cards will be populated here --> </div> <!-- No Address State --> <div id="noAddressState" class="hidden text-center py-8"> <div class="flex flex-col items-center space-y-3"> <svg class="w-12 h-12 text-gray-300" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z"></path> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 11a3 3 0 11-6 0 3 3 0 016 0z"></path> </svg> <div> <h3 class="text-lg font-medium text-gray-900">Tidak Ada Alamat</h3> <p class="text-gray-500">Pelanggan belum memiliki alamat tersimpan</p> </div> </div> </div> </div> </div> </div> <!-- Product Section --> <div class="bg-white rounded-xl shadow-sm border border-gray-200"> <div class="bg-gradient-to-r from-green-50 to-emerald-50 px-6 py-4 border-b border-gray-200"> <div class="flex items-center space-x-3"> <div class="w-8 h-8 bg-green-500 rounded-lg flex items-center justify-center"> <svg class="w-4 h-4 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-10L4 7m8 4v10M4 7v10l8 4"></path> </svg> </div> <h2 class="text-lg font-semibold text-gray-900">Produk</h2> <span class="inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-red-100 text-red-800"> Wajib </span> </div> </div> <div class="p-6 space-y-6"> <!-- Product Selection --> <div id="productForm"> <div class="space-y-2"> <label for="productSelection" class="text-sm font-medium text-gray-700"> Pilih Produk </label> <div class="relative"> <select id="productSelection" class="w-full" multiple></select> </div> <p class="text-xs text-gray-500">Pilih satu atau lebih produk untuk pesanan ini</p> <input type="hidden" name="variant" id="variant"> </div> </div> <!-- Product Table --> <div class="border border-gray-200 rounded-lg"> <div class="overflow-x-auto"> <table class="w-full"> <thead class="bg-gray-50"> <tr> <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Nama Produk</th> <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">SKU</th> <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Harga Jual</th> <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Stok</th> <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Jumlah Beli</th> <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Subtotal</th> </tr> </thead> <tbody id="productTableBody" class="bg-white divide-y divide-gray-200"> <tr> <td colspan="6" class="px-4 py-8 text-center text-gray-500"> <div class="flex flex-col items-center space-y-2"> <svg class="w-8 h-8 text-gray-300" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-10L4 7m8 4v10M4 7v10l8 4"></path> </svg> <span>Belum ada produk yang ditambahkan</span> </div> </td> </tr> </tbody> </table> </div> </div> </div> </div> <!-- Payment & Shipping Section --> <div class="bg-white rounded-xl shadow-sm border border-gray-200"> <div class="bg-gradient-to-r from-yellow-50 to-orange-50 px-6 py-4 border-b border-gray-200"> <div class="flex items-center space-x-3"> <div class="w-8 h-8 bg-yellow-500 rounded-lg flex items-center justify-center"> <svg class="w-4 h-4 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 9V7a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2m2 4h10a2 2 0 002-2v-6a2 2 0 00-2-2H9a2 2 0 00-2 2v6a2 2 0 002 2zm7-5a2 2 0 11-4 0 2 2 0 014 0z"></path> </svg> </div> <h2 class="text-lg font-semibold text-gray-900">Pembayaran & Pengiriman</h2> </div> </div> <div class="p-6 space-y-6"> <!-- Payment and Shipping Row --> <div class="grid md:grid-cols-2 gap-6"> <!-- Payment Method --> <div class="space-y-2"> <label for="paymentMethod" class="flex items-center text-sm font-medium text-gray-700 mb-2"> Metode Pembayaran <span class="ml-2 inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-red-100 text-red-800"> Wajib </span> </label> <select name="paymentMethod" id="paymentMethod" class="w-full" autocomplete="off"> <option value="">Pilih Metode Pembayaran</option> <?php foreach ($paymentMethods as $paymentMethod) : ?> <option value="<?= $paymentMethod->id_bank ?>"><?= htmlspecialchars(ucwords($paymentMethod->bank_name)) ?></option> <?php endforeach; ?> </select> <p class="text-xs text-gray-500">Pilih metode pembayaran untuk pesanan</p> </div> <!-- Shipping Method --> <div class="space-y-2"> <label for="shippingMethod" class="flex items-center text-sm font-medium text-gray-700 mb-2"> Metode Pengiriman <span class="ml-2 inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-red-100 text-red-800"> Wajib </span> </label> <select name="shippingMethod" id="shippingMethod" class="w-full" autocomplete="off"> <option value="">Pilih Metode Pengiriman</option> <?php foreach ($shippingMethods as $shippingMethod) : ?> <option value="<?= $shippingMethod->id ?>"><?= htmlspecialchars(ucwords($shippingMethod->name)) ?></option> <?php endforeach; ?> </select> <p class="text-xs text-gray-500">Pilih metode pengiriman untuk pesanan</p> </div> </div> <!-- Shipping Fee --> <div id="shippingFeeSection"> <div class="space-y-2"> <label for="shipping_fee" class="flex items-center text-sm font-medium text-gray-700"> Biaya Pengiriman <span class="ml-2 inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-gray-100 text-gray-600"> Otomatis </span> </label> <input id="shipping_fee" type="text" name="shipping_fee" placeholder="Biaya pengiriman akan otomatis diisi" required autocomplete="off" class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-1 focus:ring-purple-500 focus:border-purple-500 transition-colors text-gray-900 placeholder-gray-500" /> <p class="text-xs text-gray-500">Otomatis terhitung saat memilih metode pengiriman sesuai alamat pelanggan</p> </div> </div> </div> </div> <!-- Notes --> <div class="bg-white rounded-xl shadow-sm border border-gray-200"> <div class="bg-gradient-to-r from-blue-50 to-sky-50 px-6 py-4 border-b border-gray-200"> <div class="flex items-center space-x-3"> <div class="w-8 h-8 bg-blue-500 rounded-lg flex items-center justify-center"> <svg class="w-4 h-4 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M12 20a8 8 0 100-16 8 8 0 000 16z" /> </svg> </div> <h2 class="text-lg font-semibold text-gray-900">Catatan</h2> </div> </div> <div class="p-6 space-y-6"> <!-- Admin Notes --> <div class="space-y-2"> <label for="admin_note" class="flex items-center text-sm font-medium text-gray-700"> Catatan Admin <span class="ml-2 inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-gray-100 text-gray-600"> Opsional </span> </label> <input id="admin_note" type="text" name="admin_note" placeholder="Misalnya: ORDER TIKTOKSHOP: GABRIEL" autocomplete="off" class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-1 focus:ring-purple-500 focus:border-purple-500 transition-colors text-gray-900 placeholder-gray-500" /> <p class="text-xs text-gray-500">Hanya ditampilkan di admin panel</p> </div> <div class="space-y-2"> <label for="customer_invoice_note" class="flex items-center text-sm font-medium text-gray-700"> Catatan <span class="ml-2 inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-gray-100 text-gray-600"> Opsional </span> </label> <input id="customer_invoice_note" type="text" name="customer_invoice_note" placeholder="Misalnya: FREE MIRAI" autocomplete="off" class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-1 focus:ring-purple-500 focus:border-purple-500 transition-colors text-gray-900 placeholder-gray-500" /> <p class="text-xs text-gray-500">Ditampilkan di invoice</p> </div> </div> </div> <!-- Discount Section --> <div class="bg-white rounded-xl shadow-sm border border-gray-200"> <div class="bg-gradient-to-r from-pink-50 to-rose-50 px-6 py-4 border-b border-gray-200"> <div class="flex items-center space-x-3"> <div class="w-8 h-8 bg-pink-500 rounded-lg flex items-center justify-center"> <svg class="w-4 h-4 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z"></path> </svg> </div> <h2 class="text-lg font-semibold text-gray-900">Potongan</h2> </div> </div> <div class="p-6"> <div class="space-y-2"> <label for="voucherSelect" class="flex items-center text-sm font-medium text-gray-700 mb-2"> Voucher <span class="ml-2 inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-gray-100 text-gray-600"> Opsional </span> </label> <select name="voucher_code" id="voucherSelect" class="w-full" autocomplete="off"> <option value="">Pilih Atau Ketik Voucher</option> <?php foreach ($vouchers as $voucher) : ?> <option value="<?= $voucher->voucher_code ?>" data-discount-type="<?= $voucher->discount_type ?>" data-discount-value="<?= $voucher->discount_value ?>"> <?= htmlspecialchars(ucwords($voucher->voucher_code)) ?> </option> <?php endforeach; ?> </select> <p class="text-xs text-gray-500">Voucher yang akan digunakan untuk pesanan ini</p> <!-- Hidden Voucher Fields --> <input type="hidden" name="redeemed_voucher_type" id="redeemed_voucher_type"> <input type="hidden" name="redeemed_voucher_code" id="redeemed_voucher_code"> <input type="hidden" name="redeemed_voucher_value" id="redeemed_voucher_value"> <input type="hidden" name="redeemed_voucher_amount" id="redeemed_voucher_amount"> </div> </div> </div> <!-- Order Summary Section --> <div class="bg-white rounded-xl shadow-sm border border-gray-200"> <div class="bg-gradient-to-r from-indigo-50 to-purple-50 px-6 py-4 border-b border-gray-200"> <div class="flex items-center space-x-3"> <div class="w-8 h-8 bg-indigo-500 rounded-lg flex items-center justify-center"> <svg class="w-4 h-4 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 7h6m0 10v-3m-3 3h.01M9 17h.01M9 14h.01M12 14h.01M15 11h.01M12 11h.01M9 11h.01M7 21h10a2 2 0 002-2V5a2 2 0 00-2-2H7a2 2 0 00-2 2v14a2 2 0 002 2z"></path> </svg> </div> <h2 class="text-lg font-semibold text-gray-900">Ringkasan Pesanan</h2> </div> </div> <div class="p-6 space-y-4"> <div class="flex justify-between items-center py-2"> <span class="text-sm font-medium text-gray-700">Sub Total</span> <span id="subtotalPrice" class="text-lg font-semibold text-gray-900">Rp 0</span> </div> <div class="flex justify-between items-center py-2"> <span class="text-sm font-medium text-gray-700">Potongan Voucher</span> <span id="voucherDiscount" class="text-lg font-semibold text-red-500">-Rp 0</span> </div> <div class="flex justify-between items-center py-2"> <span class="text-sm font-medium text-gray-700">Biaya Pengiriman</span> <span id="shippingFee" class="text-lg font-semibold text-gray-900">Rp 0</span> </div> <div class="border-t border-gray-200 pt-4"> <div class="flex justify-between items-center"> <span class="text-xl font-bold text-gray-900">Total</span> <span id="totalPrice" class="text-xl font-bold text-[#7a4397]">Rp 0</span> </div> </div> </div> </div> <!-- Hidden Price Fields --> <input type="hidden" name="subtotal_price" id="subtotal_price"> <input type="hidden" name="total_price" id="total_price"> <input type="hidden" name="selected_products_data" id="selected_products_data"> <!-- Action Buttons --> <div class="bg-white rounded-xl shadow-sm border border-gray-200 p-6"> <div class="flex flex-col sm:flex-row justify-end gap-4"> <button type="button" class="w-full sm:w-auto px-6 py-3 border border-gray-300 rounded-lg text-gray-700 hover:bg-gray-50 hover:border-gray-400 transition-all duration-200 font-medium" onclick="window.location.href='<?= base_url('admin/orders/manage-order') ?>'"> <svg class="w-4 h-4 inline mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path> </svg> Batal </button> <button type="submit" class="w-full sm:w-auto px-6 py-3 bg-blue-600 hover:bg-blue-700 text-white rounded-lg transition-all duration-200 font-medium shadow-sm hover:shadow-md"> <svg class="w-4 h-4 inline mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path> </svg> Simpan & Tambah Baru </button> </div> </div> </form> </main> <style> .animate-fade-in { animation: fade-in 0.4s ease-in-out forwards; } @keyframes fade-in { from { opacity: 0; transform: translateY(-10px); } to { opacity: 1; transform: translateY(0); } } </style> <script src="https://cdn.jsdelivr.net/npm/tom-select@2.2.2/dist/js/tom-select.complete.min.js"></script> <script> const productSelection = document.getElementById("productSelection"); const productTableBody = document.getElementById("productTableBody"); let tomSelectProducts; let selectedProducts = []; let productData = {}; let url = ''; let shippingSubdistrictId = null; let shippingMethodId = null; let totalShippingFee = 0; let originalShippingFee = 0; let shippingDetails = {}; let isFreeShipping = false; let discountApplied = 0; let discountType = null; let discountValue = 0; let subtotal = 0; let voucherDiscount = 0; let totalSubtotal = 0; let totalPrice = 0; let isFromMarketplace = false; const BASE_URL_CALCULATE_SHIPPING = "<?= base_url('shipping/calculate_shipping_fee'); ?>"; const BASE_URL_BITESHIP_SHIPPING = "<?= base_url('shipping/get_shipping_rates'); ?>"; const CSRF_TOKEN = "<?= $this->security->get_csrf_token_name(); ?>"; const CSRF_HASH = "<?= $this->security->get_csrf_hash(); ?>"; const shippingFeeSummary = document.getElementById("shippingFee"); const subtotalPriceSummary = document.getElementById("subtotalPrice"); const voucherDiscountSummary = document.getElementById("voucherDiscount"); const customerSection = document.getElementById('customerSection'); const invoiceSection = document.getElementById('invoiceSection'); const shippingFeeSection = document.getElementById('shippingFeeSection'); const selectedAddressIdInput = document.getElementById('selected_address_id'); const addressInput = document.getElementById('address'); const addressNotesInput = document.getElementById('address_notes'); const shippingSubdistrictInput = document.getElementById('shipping_subdistrict'); const shippingDistrictInput = document.getElementById('shipping_district'); const shippingProvinceInput = document.getElementById('shipping_province'); const shippingCityInput = document.getElementById('shipping_city'); const shippingPhoneInput = document.getElementById('shipping_phone'); const shippingLatInput = document.getElementById('shipping_lat'); const shippingLngInput = document.getElementById('shipping_lng'); const shippingPostcodeInput = document.getElementById('shipping_postcode'); const emailInput = document.getElementById('email'); const nameInput = document.getElementById('name'); const customersIdInput = document.getElementById('id_customers'); const shippingSelect = document.getElementById("shippingMethod"); const shippingFeeInput = document.getElementById("shipping_fee"); const addressSelectionContainer = document.getElementById('addressSelectionContainer'); const addressLoading = document.getElementById('addressLoading'); const addressCardsContainer = document.getElementById('addressCardsContainer'); const noAddressState = document.getElementById('noAddressState'); let selectedAddressId = null; let customerAddresses = []; const customerSelect = new TomSelect("#customer", { plugins: ["remove_button"], persist: false, create: false, sortField: { field: "text", direction: "asc" }, onInitialize: function() { const wrapper = this.wrapper; const control = this.control_input.parentNode; wrapper.classList.add( 'w-full', ); control.classList.add('text-gray-900'); } }); customerSelect.on('change', async function(customerId) { if (customerId) { initProductSelection(); await loadCustomerAddresses(customerId); } else { hideAddressSelection(); clearAddressData(); } }); document.addEventListener('DOMContentLoaded', function() { if (shippingSelect) { shippingSelect.addEventListener("change", async function() { shippingMethodId = this.value || null; // Simpan nilai shipping_id yang dipilih if (shippingMethodId) { await updateShippingFee(); } }); } // Event listener saat nilai shipping fee diubah shippingFeeInput.addEventListener("input", function() { let inputFee = parseInt(this.value.replace(/[^\d]/g, "")) || 0; // Ambil angka, jika tidak valid set ke 0 totalShippingFee = inputFee; shippingFeeSummary.textContent = `Rp ${new Intl.NumberFormat('id-ID').format(totalShippingFee)}`; updateTotalPrice(); }); new TomSelect("#paymentMethod", { plugins: ["remove_button"], persist: false, create: false, sortField: { field: "text", direction: "asc" } }); // Metode Pengiriman new TomSelect("#shippingMethod", { plugins: ["remove_button"], persist: false, create: false, sortField: null, }); new TomSelect("#voucherSelect", { plugins: ["remove_button"], persist: false, create: false, sortField: { field: "text", direction: "asc" }, onChange: function(value) { applyVoucherDiscount(); updateTotalPrice(); } }); const marketplaceCheckbox = document.getElementById('is_marketplace'); const marketplaceText = document.getElementById('marketplaceOrder'); marketplaceCheckbox.addEventListener("change", function() { if (this.checked) { // Set UI untuk marketplace marketplaceText.textContent = "Iya, ini pesanan marketplace"; customerSection.classList.add("hidden"); shippingFeeSection.classList.add("hidden"); invoiceSection.classList.remove("hidden"); // Set marketplace flag isFromMarketplace = true; // Disable customer selection customerSelect.disabled = true; // Reset shipping fee untuk marketplace totalShippingFee = 0; shippingFeeInput.value = "0"; shippingFeeSummary.textContent = "Rp 0"; // Set data alamat marketplace dengan urutan yang benar customerSelect.value = "2615"; selectedAddressIdInput.value = "0"; addressInput.value = "Tebet, Jakarta Selatan, DKI Jakarta"; shippingSubdistrictInput.value = "Tebet Timur"; shippingDistrictInput.value = "Tebet"; shippingProvinceInput.value = "DKI Jakarta"; shippingCityInput.value = "Jakarta Selatan"; shippingPhoneInput.value = "881024181692"; emailInput.value = "tokped.laciasmara@gmail.com"; nameInput.value = "Order Tokopedia"; customersIdInput.value = "2615"; // Set shipping subdistrict ID shippingSubdistrictId = 17589; // Tampilkan badge marketplace marketplaceBadge.classList.remove("hidden"); marketplaceBadge.classList.add("animate-fade-in"); // Panggil fungsi init SETELAH data diset initProductSelection(); updateTotalPrice(); } else { // Reset UI untuk pesanan website marketplaceText.textContent = "Ini pesanan website"; isFromMarketplace = false; // Tampilkan kembali section yang disembunyikan customerSection.classList.remove("hidden"); shippingFeeSection.classList.remove("hidden"); invoiceSection.classList.add("hidden"); // Reset semua field alamat dengan konsisten selectedAddressIdInput.value = ""; addressInput.value = ""; shippingSubdistrictInput.value = ""; shippingDistrictInput.value = ""; shippingProvinceInput.value = ""; shippingCityInput.value = ""; shippingPhoneInput.value = ""; emailInput.value = ""; nameInput.value = ""; customersIdInput.value = ""; // Konsisten: kosongkan, bukan set ke 2615 // Reset customer selection customerSelect.value = ""; customerSelect.disabled = false; // Reset shipping totalShippingFee = 0; shippingFeeInput.value = ""; shippingFeeSummary.textContent = "Rp 0"; shippingSubdistrictId = null; // Reset ke null atau 0 // Reset placeholder addressInput.placeholder = "Pilih pelanggan dulu.."; // Sembunyikan badge marketplace marketplaceBadge.classList.add("hidden"); marketplaceBadge.classList.remove("animate-fade-in"); // Panggil fungsi init setelah reset initProductSelection(); updateTotalPrice(); } }); // Inisialisasi TomSelect untuk pemilihan produk tomSelectProducts = new TomSelect('#productSelection', { plugins: ['remove_button', "clear_button"], valueField: 'id', labelField: 'title', searchField: ['title', 'atribut', 'sku'], placeholder: 'Pilih atau ketik produk', render: { option: function(item, escape) { let price = `<span>Rp ${new Intl.NumberFormat('id-ID').format(item.price)}</span>`; return `<div class="py-2 px-3"> <div class="font-medium">${escape(item.title)} ${item.atribut ? '- ' + escape(item.atribut) : ''}</div> <div class="text-sm">SKU: ${escape(item.sku)} | ${price} | Stok: ${item.stock_sell}</div> </div>`; }, item: function(item, escape) { return `<div>${escape(item.title)} ${item.atribut ? '- ' + escape(item.atribut) : ''}</div>`; }, no_results: function() { return '<div class="py-2 px-3">Produk tidak ditemukan</div>'; } }, onChange: handleProductSelection }); }); function debugAddressData() { console.log("=== Debug Address Data ==="); console.log("Selected Address ID:", selectedAddressIdInput.value); console.log("Address:", addressInput.value); console.log("Subdistrict:", shippingSubdistrictInput.value); console.log("District:", shippingDistrictInput.value); console.log("Province:", shippingProvinceInput.value); console.log("City:", shippingCityInput.value); console.log("Phone:", shippingPhoneInput.value); console.log("Email:", emailInput.value); console.log("Name:", nameInput.value); console.log("Customer ID:", customersIdInput.value); console.log("Customer Select:", customerSelect.value); console.log("Is Marketplace:", isFromMarketplace); } async function updateShippingFee() { const productRows = productTableBody.querySelectorAll('tr'); const cartItems = []; totalSubtotal = 0; // Reset total subtotal // Build cart items untuk Biteship productRows.forEach(row => { const productDetailIdInput = row.querySelector('input[name="product_ids[]"]'); if (productDetailIdInput) { const productDetailId = productDetailIdInput.value; const product = productData[productDetailId]; const qty = parseInt(row.querySelector('input[name="qty[]"]').value); const weight = parseFloat(row.querySelector('input[name="product_weight[]"]').value) || 1000; const length = parseFloat(row.querySelector('input[name="product_length[]"]').value) || 10; const width = parseFloat(row.querySelector('input[name="product_width[]"]').value) || 10; const height = parseFloat(row.querySelector('input[name="product_height[]"]').value) || 10; const hargaJual = product.discounted_price !== "0" ? product.discounted_price : product.price; const subtotal = hargaJual * qty; totalSubtotal += subtotal; // Build cart item object for Biteship cartItems.push({ id: productDetailId, qty: qty, name: product.title || 'Product', sku: product.sku || `SKU-${productDetailId}`, price: hargaJual, weight: weight, length: length, width: width, height: height, value: hargaJual }); } }); if (isFromMarketplace) { totalShippingFee = 0; originalShippingFee = 0; shippingDetails = null; isFreeShipping = true; discountApplied = 0; // Update UI shippingFeeInput.value = "0"; shippingFeeSummary.textContent = "Rp 0"; // Update total price dan return early updateTotalPrice(); return; } // Validasi untuk pesanan website biasa if (!shippingMethodId) { console.warn("Shipping method belum dipilih!"); return; } // Validasi alamat tujuan if (!shippingLatInput.value || !shippingLngInput.value) { console.warn("Koordinat alamat tujuan belum tersedia!"); return; } // Hitung shipping fee untuk pesanan website biasa menggunakan Biteship try { const shippingFeeData = await calculateBiteshipShippingFee( cartItems, shippingMethodId, shippingLatInput.value, shippingLngInput.value, shippingPostcodeInput.value ); if (shippingFeeData && shippingFeeData.success) { const rates = shippingFeeData.data.shipping_rates; if (rates && rates.length > 0) { // Ambil rate pertama (seharusnya hanya ada 1 karena sudah spesifik courier:service) const selectedRate = rates[0]; totalShippingFee = selectedRate.price; originalShippingFee = selectedRate.price; shippingDetails = { courier_name: selectedRate.courier_name, service_name: selectedRate.service_name, duration: selectedRate.duration, description: selectedRate.description }; isFreeShipping = false; discountApplied = 0; // Update UI shippingFeeInput.value = totalShippingFee ? `${totalShippingFee}` : "0"; shippingFeeSummary.textContent = totalShippingFee ? `Rp ${new Intl.NumberFormat('id-ID').format(totalShippingFee)}` : "Rp 0"; } else { console.error("❌ No shipping rates available"); shippingFeeInput.value = "Tidak tersedia"; shippingFeeSummary.textContent = "Tidak tersedia"; } } else { console.error("❌ Failed to calculate shipping fee:", shippingFeeData); shippingFeeInput.value = "Gagal menghitung"; shippingFeeSummary.textContent = "Gagal menghitung"; } } catch (error) { console.error("❌ Error calculating shipping fee:", error); shippingFeeInput.value = "Error"; shippingFeeSummary.textContent = "Error"; } // Update total price updateTotalPrice(); } async function calculateBiteshipShippingFee(cartItems, shippingMethodId, destinationLat, destinationLng, postalCode) { try { const csrfTokenInput = document.querySelector('.csrf_token'); if (!csrfTokenInput) { console.error('CSRF token not found!'); return null; } const csrfName = csrfTokenInput.name; const csrfToken = csrfTokenInput.value; const shippingData = { [csrfName]: csrfToken, cart_items: JSON.stringify(cartItems), shipping_method_id: shippingMethodId, destination_latitude: destinationLat, destination_longitude: destinationLng, destination_postal_code: postalCode }; // Show loading state shippingFeeInput.value = "Menghitung..."; shippingFeeInput.classList.add("animate-pulse"); // Disable shipping method selector if exists if (typeof shippingSelect !== 'undefined') { shippingSelect.disabled = true; } const response = await fetch(BASE_URL_BITESHIP_SHIPPING, { // Perlu ditambahkan konstanta ini method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: new URLSearchParams(shippingData) }); const responseText = await response.text(); let parsedResponse; try { parsedResponse = JSON.parse(responseText); } catch (parseError) { console.error("Failed to parse JSON response:", responseText); return null; } return parsedResponse; } catch (error) { console.error("Error fetching Biteship shipping fee:", error); return null; } finally { // Remove loading state shippingFeeInput.classList.remove("animate-pulse"); // Re-enable shipping method selector if (typeof shippingSelect !== 'undefined') { shippingSelect.disabled = false; } } } async function loadCustomerAddresses(customerId) { try { showAddressLoading(); const response = await fetch(`<?= base_url('admin/customers/getCustomerAddresses') ?>?customer_id=${customerId}`); const data = await response.json(); if (data.success && data.addresses && data.addresses.length > 0) { customerAddresses = data.addresses; renderAddressCards(data.addresses, data.customer); showAddressCards(); } else { showNoAddressState(); } } catch (error) { console.error('Error loading addresses:', error); showNoAddressState(); } } function showAddressLoading() { addressSelectionContainer.classList.remove('hidden'); addressLoading.classList.remove('hidden'); addressCardsContainer.classList.add('hidden'); noAddressState.classList.add('hidden'); } // Show address cards function showAddressCards() { addressLoading.classList.add('hidden'); addressCardsContainer.classList.remove('hidden'); noAddressState.classList.add('hidden'); } // Show no address state function showNoAddressState() { addressSelectionContainer.classList.remove('hidden'); addressLoading.classList.add('hidden'); addressCardsContainer.classList.add('hidden'); noAddressState.classList.remove('hidden'); } // Hide address selection function hideAddressSelection() { addressSelectionContainer.classList.add('hidden'); selectedAddressId = null; } // Clear address data function clearAddressData() { selectedAddressIdInput.value = ''; addressInput.value = ''; shippingSubdistrictInput.value = ''; shippingDistrictInput.value = ''; shippingProvinceInput.value = ''; shippingCityInput.value = ''; shippingPhoneInput.value = ''; emailInput.value = ''; nameInput.value = ''; customersIdInput.value = ''; } // Get label icon function getLabelIcon(label) { const labelLower = label.toLowerCase(); switch (labelLower) { case 'rumah': case 'home': return '🏠'; case 'kantor': case 'office': return '🏢'; case 'apartment': case 'apartemen': return '🏬'; case 'kos': case 'kost': return '🏘️'; default: return '📍'; } } // Render address cards function renderAddressCards(addresses, customer) { const container = addressCardsContainer; container.innerHTML = ''; addresses.forEach(address => { const isDefault = address.is_default == 1; const cardClass = isDefault ? 'ring-2 ring-green-500 border-green-500 bg-green-50' : 'border-gray-200 bg-gray-50 hover:border-purple-300'; const card = document.createElement('div'); card.className = `relative border rounded-lg p-4 cursor-pointer transition-all ${cardClass}`; card.onclick = () => selectAddress(address, customer); card.innerHTML = ` ${isDefault ? ` <div class="absolute -top-2 -right-2"> <span class="inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-green-600 text-white"> <svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path> </svg> Utama </span> </div> ` : ''} <div class="flex items-start justify-between"> <div class="flex-1"> <!-- Header --> <div class="flex items-center space-x-3 mb-3"> <div class="flex items-center space-x-2"> <div class="w-6 h-6 bg-blue-100 rounded-full flex items-center justify-center text-sm"> ${getLabelIcon(address.label)} </div> <h3 class="text-sm font-semibold text-gray-900">${address.label}</h3> </div> <div class="flex items-center text-xs text-gray-500"> <svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z"></path> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 11a3 3 0 11-6 0 3 3 0 016 0z"></path> </svg> ${address.city} </div> </div> <!-- Recipient Info --> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-3"> <div class="flex items-center space-x-2"> <svg class="w-4 h-4 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"></path> </svg> <span class="text-sm font-medium text-gray-700">${address.recipient_name}</span> </div> <div class="flex items-center space-x-2"> <svg class="w-4 h-4 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z"></path> </svg> <span class="text-sm text-gray-600">${address.phone}</span> </div> </div> <!-- Full Address --> <div class="mb-2"> <p class="text-sm text-gray-700 leading-relaxed">${address.address}</p> </div> ${address.notes ? ` <div class="flex items-center space-x-2 mb-3"> <svg class="w-4 h-4 text-amber-500 mt-0.5 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 8h10M7 12h4m1 8l-4-4H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-3l-4 4z"></path> </svg> <span class="text-sm text-amber-700 bg-amber-50 px-2 py-1 rounded"> Catatan: ${address.notes} </span> </div> ` : ''} <!-- Location Details --> <div class="flex flex-wrap gap-2 text-xs"> <span class="inline-flex items-center px-2 py-1 bg-gray-100 text-gray-600 rounded"> ${address.province} </span> <span class="inline-flex items-center px-2 py-1 bg-gray-100 text-gray-600 rounded"> ${address.district} </span> <span class="inline-flex items-center px-2 py-1 bg-gray-100 text-gray-600 rounded"> ${address.subdistrict} </span> <span class="inline-flex items-center px-2 py-1 bg-blue-100 text-blue-700 rounded font-medium"> ${address.postal_code} </span> </div> </div> <!-- Selection Indicator --> <div class="ml-4"> <div class="w-6 h-6 border-2 border-gray-300 rounded-full flex items-center justify-center ${selectedAddressId === address.id ? 'bg-purple-500 border-purple-500' : ''}" id="radio-${address.id}"> ${selectedAddressId === address.id ? '<div class="w-2 h-2 bg-white rounded-full"></div>' : ''} </div> </div> </div> `; container.appendChild(card); }); const defaultAddress = addresses.find(addr => addr.is_default == 1); if (defaultAddress) { selectAddress(defaultAddress, customer); } } // Select address function selectAddress(address, customer) { // Update visual selection customerAddresses.forEach(addr => { const radio = document.getElementById(`radio-${addr.id}`); if (radio) { if (addr.id === address.id) { radio.className = 'w-6 h-6 border-2 border-purple-500 bg-purple-500 rounded-full flex items-center justify-center'; radio.innerHTML = '<div class="w-2 h-2 bg-white rounded-full"></div>'; radio.parentElement.parentElement.parentElement.className = radio.parentElement.parentElement.parentElement.className.replace(/border-gray-200|hover:border-purple-300/g, '') + ' border-purple-500 bg-purple-50'; } else { radio.className = 'w-6 h-6 border-2 border-gray-300 rounded-full flex items-center justify-center'; radio.innerHTML = ''; const card = radio.parentElement.parentElement.parentElement; const isDefault = addr.is_default == 1; const cardClass = isDefault ? 'ring-2 ring-green-500 border-green-500 bg-green-50' : 'border-gray-200 bg-gray-50 hover:border-purple-300'; card.className = `relative border rounded-lg p-4 cursor-pointer transition-all ${cardClass}`; } } }); // Update selected address selectedAddressId = address.id; // Fill hidden form fields selectedAddressIdInput.value = address.id; addressInput.value = address.address; addressNotesInput.value = address.notes; shippingSubdistrictInput.value = address.subdistrict; shippingDistrictInput.value = address.district; shippingProvinceInput.value = address.province; shippingCityInput.value = address.city; shippingPhoneInput.value = address.phone; shippingLatInput.value = address.latitude; shippingLngInput.value = address.longitude; shippingPostcodeInput.value = address.postal_code; emailInput.value = customer.email; nameInput.value = customer.name; customersIdInput.value = customer.id_customers; shippingSubdistrictId = address.rajaongkir_subdistrict_id; // Trigger other functions if needed updateShippingFee(); updateTotalPrice(); } async function initProductSelection() { tomSelectProducts.clear(); tomSelectProducts.clearOptions(); productData = {}; selectedProducts = []; url = '<?= base_url('admin/orders/get_products') ?>'; if (customerSelect.value == "2615") { url = '<?= base_url('admin/orders/get_tokopedia_products') ?>'; } updateProductTable(); try { // Tampilkan indikator loading tomSelectProducts.addOption({ id: 'loading', title: 'Memuat produk...', disabled: true }); tomSelectProducts.refreshOptions(false); const response = await fetch(url); const products = await response.json(); tomSelectProducts.removeOption('loading'); if (products && products.length > 0) { // Tambahkan produk ke Tom Select dan simpan data produk products.forEach(product => { // Tambahkan ke opsi Tom Select tomSelectProducts.addOption({ id: product.id_detail, title: product.title, atribut: product.atribut, sku: product.sku, price: product.price, discounted_price: product.discounted_price, stock_sell: product.stock_sell, }); // Simpan data lengkap produk untuk diakses nanti productData[product.id_detail] = { id_products: product.id_products, id_detail: product.id_detail, title: product.title, atribut: product.atribut, sku: product.sku, price: product.price, discounted_price: product.discounted_price, stock_sell: product.stock_sell, }; }); tomSelectProducts.refreshOptions(false); } else { // Jika tidak ada produk, tambahkan pesan tomSelectProducts.addOption({ id: 'no-products', title: 'Tidak ada produk tersedia', disabled: true }); tomSelectProducts.refreshOptions(false); } } catch (error) { console.error('Error loading products:', error); tomSelectProducts.removeOption('loading'); tomSelectProducts.addOption({ id: 'error', title: 'Gagal memuat produk', disabled: true }); tomSelectProducts.refreshOptions(false); } }; function applyVoucherDiscount() { const selectedOption = voucherSelect.selectedOptions[0]; if (!selectedOption || !selectedOption.value) { // Reset input hidden jika tidak ada voucher yang dipilih document.getElementById("redeemed_voucher_code").value = ""; document.getElementById("redeemed_voucher_value").value = ""; document.getElementById("redeemed_voucher_amount").value = ""; return 0; // Jika tidak ada voucher yang dipilih, diskon 0 } const voucherCode = selectedOption.value; // Ambil kode voucher const discountType = selectedOption.getAttribute("data-discount-type"); // "percentage" atau "amount" const discountValue = parseFloat(selectedOption.getAttribute("data-discount-value")) || 0; const subtotal = calculateSubtotal(); // Ambil total harga sebelum diskon let voucherDiscount = 0; if (discountType === "percentage") { voucherDiscount = subtotal * (discountValue / 100); // Hitung diskon berdasarkan persentase } else if (discountType === "amount") { voucherDiscount = discountValue; } // Update tampilan potongan voucher voucherDiscountSummary.textContent = `Rp ${new Intl.NumberFormat("id-ID").format(voucherDiscount)}`; // Perbarui nilai input hidden document.getElementById("redeemed_voucher_type").value = discountType; document.getElementById("redeemed_voucher_code").value = voucherCode; document.getElementById("redeemed_voucher_value").value = discountValue; document.getElementById("redeemed_voucher_amount").value = voucherDiscount; return voucherDiscount; } function calculateSubtotal() { let subtotal = 0; document.querySelectorAll(".subtotal").forEach(subtotalCell => { subtotal += parseInt(subtotalCell.textContent.replace(/[^\d]/g, "")) || 0; }); document.getElementById("subtotal_price").value = subtotal; return subtotal; } // Fungsi untuk menangani perubahan pemilihan produk function handleProductSelection() { const selectedValues = tomSelectProducts.getValue(); // Reset selected products array selectedProducts = []; // Tambahkan produk yang dipilih ke array selectedValues.forEach(productDetailId => { const trimmedId = productDetailId.trim(); // Trim whitespace dari ID if (productData[trimmedId]) { selectedProducts.push(productData[trimmedId]); } else { console.warn(`Product with ID ${trimmedId} not found in data`); } }); // Perbarui tabel updateProductTable(); } // Fungsi untuk memperbarui tabel produk function updateProductTable() { productTableBody.innerHTML = ""; if (selectedProducts.length === 0) { productTableBody.innerHTML = `<tr> <td colspan="6" class="text-center p-4 text-gray-500">Belum ada produk yang ditambahkan</td> </tr>`; document.getElementById("totalPrice").textContent = "0"; return; } totalPrice = 0; // Reset total price selectedProducts.forEach(product => { const hargaJual = product.discounted_price !== "0" ? product.discounted_price : product.price; const formattedPrice = new Intl.NumberFormat('id-ID').format(hargaJual); const subtotal = hargaJual * 1; totalPrice += subtotal; productTableBody.innerHTML += ` <tr class="border-t"> <td class="p-2"> ${product.title} ${product.variant_info ? '- ' + product.variant_info : ''} </td> <input type="hidden" name="product_weight[]" value="${product.weight}"> <input type="hidden" name="product_height[]" value="${product.height}"> <input type="hidden" name="product_length[]" value="${product.length}"> <input type="hidden" name="product_width[]" value="${product.width}"> <td class="p-2"> <input type="hidden" name="product_ids[]" value="${product.id_detail}"> ${product.sku} </td> <td class="p-2"> <input type="number" class="border rounded p-1 w-full focus:ring-1 focus:ring-[#7A4397] focus:outline-none" name="price[]" placeholder="Harga" min="0" value="${hargaJual}" data-original-price="${hargaJual}" data-id="${product.id_detail}" required> <div class="text-xs text-green-600">Harga Jual: Rp ${formattedPrice}</div> </td> <td class="p-2">${product.stock_sell}</td> <td class="p-2"> <input type="number" class="border rounded p-1 w-full focus:ring-1 focus:ring-[#7A4397] focus:outline-none" name="qty[]" placeholder="Jumlah" min="1" max="${product.stock_sell}" value="1" required> </td> <td class="p-2 subtotal">${new Intl.NumberFormat('id-ID').format(subtotal)}</td> </tr> `; }); subtotalPriceSummary.textContent = `Rp ${new Intl.NumberFormat('id-ID').format(totalPrice)}`; document.getElementById("totalPrice").textContent = `Rp ${new Intl.NumberFormat('id-ID').format(totalPrice)}`; addQuantityAndPriceEventListeners(); updateTotalPrice(); updateSelectedProductsData(); } // Fungsi untuk menambahkan event listeners ke input jumlah function addQuantityAndPriceEventListeners() { // Event listener untuk input jumlah const qtyInputs = document.querySelectorAll('input[name="qty[]"]'); qtyInputs.forEach(input => { input.addEventListener('change', function() { // Periksa apakah nilai tidak melebihi stok const max = parseInt(this.getAttribute('max')); if (parseInt(this.value) > max) { this.value = max; notyf.error(`Stok maksimum adalah ${max}`); } // Periksa apakah nilai tidak kurang dari minimum const min = parseInt(this.getAttribute('min')); if (parseInt(this.value) < min) { this.value = min; notyf.error(`Minimum pembelian adalah ${min}`); } updateRowSubtotal(this.closest("tr")); updateTotalPrice(); updateSelectedProductsData(); }); }); // Event listener untuk input harga const priceInputs = document.querySelectorAll('input[name="price[]"]'); priceInputs.forEach(input => { input.addEventListener('change', function() { // Periksa apakah nilai tidak kurang dari 0 if (parseInt(this.value) < 0) { this.value = 0; } // Tambahkan indikator jika harga berubah dari harga asli const originalPrice = parseInt(this.getAttribute('data-original-price')); const row = this.closest("tr"); const priceIndicator = row.querySelector('.price-change-indicator'); if (parseInt(this.value) !== originalPrice) { if (!priceIndicator) { const indicatorDiv = document.createElement('div'); indicatorDiv.className = 'text-xs text-orange-500 price-change-indicator'; indicatorDiv.textContent = 'Harga telah diubah'; this.parentNode.appendChild(indicatorDiv); } } else { if (priceIndicator) { priceIndicator.remove(); } } updateRowSubtotal(row); updateTotalPrice(); updateSelectedProductsData(); }); }); } // Fungsi baru untuk memperbarui subtotal per baris function updateRowSubtotal(row) { const price = parseInt(row.querySelector('input[name="price[]"]').value); const qty = parseInt(row.querySelector('input[name="qty[]"]').value); const subtotal = price * qty; row.querySelector(".subtotal").textContent = new Intl.NumberFormat('id-ID').format(subtotal); } function updateTotalPrice() { let totalPrice = calculateSubtotal(); let voucherDiscount = applyVoucherDiscount(); subtotalPriceSummary.textContent = `Rp ${new Intl.NumberFormat('id-ID').format(totalPrice)}`; totalPrice += totalShippingFee; totalPrice -= voucherDiscount; document.getElementById("total_price").value = totalPrice; voucherDiscountSummary.textContent = `Rp ${new Intl.NumberFormat('id-ID').format(voucherDiscount)}`; document.getElementById("totalPrice").textContent = `Rp ${new Intl.NumberFormat('id-ID').format(totalPrice)}`; } // Fungsi untuk memperbarui input tersembunyi dengan data produk yang dipilih function updateSelectedProductsData() { const productRows = productTableBody.querySelectorAll('tr'); const selectedProductsData = []; let totalSubtotal = 0; const productIds = []; const itemIds = []; const qtys = []; const prices = []; const weights = []; const lengths = []; const widths = []; const heights = []; productRows.forEach(row => { const productDetailIdInput = row.querySelector('input[name="product_ids[]"]'); if (productDetailIdInput) { const productDetailId = productDetailIdInput.value; const qty = row.querySelector('input[name="qty[]"]').value; const price = row.querySelector('input[name="price[]"]').value; const weight = row.querySelector('input[name="product_weight[]"]').value; const length = row.querySelector('input[name="product_length[]"]').value; const width = row.querySelector('input[name="product_width[]"]').value; const height = row.querySelector('input[name="product_height[]"]').value; const subtotal = parseInt(price) * parseInt(qty); totalSubtotal += subtotal; const product = productData[productDetailId]; selectedProductsData.push({ id_products: product.id_products, id_detail: productDetailId, product: product.title, sku: product.sku, weight: product.weight, length: product.length, width: product.width, height: product.height, atribut: product.atribut, price: parseInt(price), original_price: product.price, qty: qty, stock: product.stock_sell, subtotal: subtotal, shipping_id_subdistrict: shippingSubdistrictId }); productIds.push(product.id_products); itemIds.push(productDetailId); qtys.push(qty); weights.push(weight); lengths.push(length); widths.push(width); heights.push(height); prices.push(price); } }); document.getElementById('selected_products_data').value = JSON.stringify(selectedProductsData); } </script>