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/affiliate/ |
Upload File : |
<main class="flex-1 py-4 px-4 bg-purple-50"> <h1 class="text-xl font-bold mb-4 text-[#333]">Detail Affiliate</h1> <?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"> <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/affiliator/update_affiliate/' . $affiliate->id_daftar) ?>" method="POST" class="space-y-8" id="customerForm"> <input type="hidden" name="<?= $this->security->get_csrf_token_name() ?>" value="<?= $this->security->get_csrf_hash() ?>" class="csrf_token"> <!-- Informasi Affiliate Section --> <div class="bg-white rounded-lg shadow-sm p-6" id="affiliateSection"> <h2 class="text-lg font-semibold mb-6">Informasi Affiliate</h2> <!-- Affiliate Nama--> <div class="mb-6"> <div class="flex items-start gap-4"> <!-- Label & Info --> <div class="w-1/3"> <div class="flex items-center gap-2 mb-2"> <label class="text-[#333] font-medium">Nama</label> <span class="text-xs text-gray-500 px-2 py-1 bg-gray-100 rounded">Wajib</span> </div> <div class="mt-3 text-sm text-gray-600"> <p>Pastiin namanya bener ga typo.</p> </div> </div> <div class="w-2/3"> <input id="affiliate_name" type="text" name="affiliate_name" placeholder="Otomatis diisi setelah milih affiliate" autocomplete="off" required value="<?= htmlspecialchars($affiliate->nama) ?>" class="mt-1 w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-1 focus:ring-[#7A4397] focus:outline-none text-[#333] placeholder-gray-500" /> </div> </div> </div> <!-- Affiliate Email--> <div class="mb-6"> <div class="flex items-start gap-4"> <!-- Label & Info --> <div class="w-1/3"> <div class="flex items-center gap-2 mb-2"> <label class="text-[#333] font-medium">Email</label> <span class="text-xs text-gray-500 px-2 py-1 bg-gray-100 rounded">Wajib</span> </div> <div class="mt-3 text-sm text-gray-600"> <p>Pastiin emailnya bener ga typo.</p> </div> </div> <div class="w-2/3"> <input id="affiliate_email" type="text" name="affiliate_email" placeholder="Otomatis diisi setelah milih affiliate" autocomplete="off" required value="<?= htmlspecialchars($affiliate->email) ?>" class="mt-1 w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-1 focus:ring-[#7A4397] focus:outline-none text-[#333] placeholder-gray-500" /> </div> </div> </div> <!-- Affiliate Phone--> <div class="mb-6"> <div class="flex items-start gap-4"> <!-- Label & Info --> <div class="w-1/3"> <div class="flex items-center gap-2 mb-2"> <label class="text-[#333] font-medium">Nomor Telepon</label> <span class="text-xs text-gray-500 px-2 py-1 bg-gray-100 rounded">Wajib</span> </div> <div class="mt-3 text-sm text-gray-600"> <p>Dimulai dari 8 ya, kalau dari 0 itu pertamin*</p> </div> </div> <div class="w-2/3"> <input id="affiliate_phone" type="text" name="affiliate_phone" placeholder="Otomatis diisi setelah milih affiliate" autocomplete="off" required value="<?= htmlspecialchars($affiliate->no_telpon) ?>" class="mt-1 w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-1 focus:ring-[#7A4397] focus:outline-none text-[#333] placeholder-gray-500" /> </div> </div> </div> <!-- Sosial Media --> <div class="mb-6"> <div class="flex items-start gap-4"> <!-- Label & Info --> <div class="w-1/3"> <div class="flex items-center gap-2 mb-2"> <label class="text-[#333] font-medium">Sosial Media</label> <span class="text-xs text-gray-500 px-2 py-1 bg-gray-100 rounded">Wajib</span> </div> <div class="mt-3 text-sm text-gray-600"> <p>Masukin link sosial medianya ya.</p> </div> </div> <div class="w-2/3"> <input id="affiliate_social" type="text" name="affiliate_social" placeholder="Misalnya: https://www.instagram.com/gabriel" autocomplete="off" required value="<?= htmlspecialchars($affiliate->sosial_media) ?>" class="mt-1 w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-1 focus:ring-[#7A4397] focus:outline-none text-[#333] placeholder-gray-500" /> </div> </div> </div> <!-- Kategori Affiliate --> <div class="mb-6"> <div class="flex items-start gap-4"> <!-- Label & Info --> <div class="w-1/3"> <div class="flex items-center gap-2 mb-2"> <label for="affiliate_category" class="text-[#333] font-medium">Kategori</label> </div> <div class="mt-3 text-sm text-gray-600"> <p>Asmaradoor dapet 10% komisi, kalau Asmarasana 20% komisi.</p> </div> </div> <!-- Input & Tips --> <div class="w-2/3"> <select id="affiliate_category" name="affiliate_category" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-1 focus:ring-[#7A4397] focus:outline-none text-[#333] bg-white"> <option value="asmaradoor" <?= $affiliate->kategori == 'asmaradoor' ? 'selected' : '' ?>>Asmaradoor</option> <option value="asmarasana" <?= $affiliate->kategori == 'asmarasana' ? 'selected' : '' ?>>Asmarasana</option> </select> </div> </div> </div> <!-- Status Affiliate --> <div class="mb-6"> <div class="flex items-start gap-4"> <!-- Label & Info --> <div class="w-1/3"> <div class="flex items-center gap-2 mb-2"> <label for="affiliate_status" class="text-[#333] font-medium">Status</label> </div> <div class="mt-3 text-sm text-gray-600"> <p>Status dari affiliate ini, jika disetujui pilih <strong>Disetujui</strong></p> </div> </div> <!-- Input & Tips --> <div class="w-2/3"> <select id="affiliate_status" name="affiliate_status" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-1 focus:ring-[#7A4397] focus:outline-none text-[#333] bg-white"> <option value="approve" <?= $affiliate->status == 'approve' ? 'selected' : '' ?>>Disetujui</option> <option value="waiting" <?= $affiliate->status == 'waiting' ? 'selected' : '' ?>>Menunggu</option> <option value="rejected" <?= $affiliate->status == 'rejected' ? 'selected' : '' ?>>Ditolak</option> </select> </div> </div> </div> <!-- Referral--> <div class="mb-6"> <div class="flex items-start gap-4"> <!-- Label & Info --> <div class="w-1/3"> <div class="flex items-center gap-2 mb-2"> <label class="text-[#333] font-medium">Kode Referral</label> <span class="text-xs text-gray-500 px-2 py-1 bg-gray-100 rounded">Opsional</span> </div> <div class="mt-3 text-sm text-gray-600"> <p>Ini opsional ya, kalau ga diisi, nanti dibuatin otomatis sama sistem dari nama affiliate. Misalnya LACIGAB</p> </div> </div> <div class="w-2/3"> <input id="affiliate_ref" type="text" name="affiliate_ref" placeholder="Misalnya: LACISU" autocomplete="off" value="<?= htmlspecialchars($affiliate->referral) ?>" class="mt-1 w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-1 focus:ring-[#7A4397] focus:outline-none text-[#333] placeholder-gray-500" /> </div> </div> </div> </div> <div class="bg-white rounded-lg shadow-sm p-6"> <h2 class="text-lg font-semibold mb-6">Informasi Produk</h2> <!-- Statistics Cards --> <div class="grid grid-cols-1 md:grid-cols-3 gap-4 mb-6"> <div class="bg-gray-50 rounded-md p-4 text-center"> <div class="text-xl font-bold text-gray-800"><?php echo count($affiliate->product_links); ?></div> <div class="text-sm text-gray-500">Total Produk</div> </div> <div class="bg-gray-50 rounded-md p-4 text-center"> <div class="text-xl font-bold text-gray-800"><?php echo $affiliate->stats->total_orders; ?></div> <div class="text-sm text-gray-500">Total Order</div> </div> <div class="bg-gray-50 rounded-md p-4 text-center"> <div class="text-xl font-bold text-gray-800"><?php echo $affiliate->stats->formatted_commissions; ?></div> <div class="text-sm text-gray-500">Total Komisi</div> </div> </div> <!-- Table --> <div class="flex justify-end mb-4"> <button type="button" id="add-product-link-btn" class="inline-flex items-center px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-[#7A4397] hover:bg-[#6a3784] focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-[#7A4397]"> <i data-feather="plus" class="w-4 h-4 mr-2"></i> Tambah Produk </button> </div> <div class="overflow-x-auto"> <table class="min-w-full divide-y divide-gray-200"> <thead> <tr class="bg-gray-50"> <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">Status</th> <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Open</th> <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Komisi Open Link</th> <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Order</th> <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Komisi Order</th> <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Conversion Rate</th> <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Dibuat</th> <th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Aksi</th> </tr> </thead> <tbody class="bg-white divide-y divide-gray-200"> <?php foreach ($affiliate->product_links as $product): ?> <tr class="hover:bg-gray-50"> <td class="px-4 py-3 text-sm text-gray-900"><?php echo htmlspecialchars($product->product_name); ?></td> <td class="px-4 py-3 text-sm"> <span class="px-2 py-1 text-xs font-medium rounded-full bg-green-100 text-green-800"><?php echo $product->status; ?></span> </td> <td class="px-4 py-3 text-sm text-gray-900"><?php echo $product->open; ?></td> <td class="px-4 py-3 text-sm text-gray-900"><?php echo $product->formatted_komisi; ?></td> <td class="px-4 py-3 text-sm text-gray-900"><?php echo $product->order; ?></td> <td class="px-4 py-3 text-sm text-gray-900"><?php echo $product->formatted_komisi_order; ?></td> <td class="px-4 py-3 text-sm text-gray-900"> <div class="w-full bg-gray-200 rounded-full h-2"> <div class="bg-green-500 h-2 rounded-full" style="width: <?php echo $product->conversion_rate; ?>%"></div> </div> </td> <td class="px-4 py-3 text-sm text-gray-900"><?php echo $product->created_formatted; ?></td> <td class="px-4 py-3 text-right text-sm font-medium space-y-2"> <div class="flex flex-col space-y-2"> <button type="button" data-link="<?php echo $product->link; ?>" class="copy-link-btn inline-flex items-center px-3 py-1.5 border border-gray-300 rounded-md text-xs text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-purple-500"> <i data-feather="copy" class="w-4 h-4 mr-1"></i> Copy Link </button> <!-- Status Pengiriman Produk --> <?php if (isset($product->shipping_status)): ?> <?php if ($product->shipping_status == 'Sudah Dikirim'): ?> <span class="<?php echo $product->shipping_status_class; ?> inline-flex items-center justify-center px-3 py-1.5 text-xs"> <i data-feather="check-circle" class="w-4 h-4 mr-1"></i> Sudah Terkirim </span> <?php elseif ($product->shipping_status == 'Sedang Diproses'): ?> <span class="<?php echo $product->shipping_status_class; ?> inline-flex items-center justify-center px-3 py-1.5 text-xs"> <i data-feather="truck" class="w-4 h-4 mr-1"></i> Sedang Dikirim </span> <?php else: ?> <button data-product-id="<?php echo $product->product_id; ?>" data-customer-id="<?php echo $affiliate->id_customer; ?>" data-product-detail-id="<?php echo $product->product_detail_id; ?>" class="send-product-btn inline-flex items-center px-3 py-1.5 border border-transparent rounded-md text-xs text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"> <i data-feather="send" class="w-4 h-4 mr-1"></i> Kirim Produk </button> <?php endif; ?> <?php else: ?> <button data-product-id="<?php echo $product->product_id; ?>" data-customer-id="<?php echo $affiliate->id_customer; ?>" data-product-detail-id="<?php echo $product->product_detail_id; ?>" class="send-product-btn inline-flex items-center px-3 py-1.5 border border-transparent rounded-md text-xs text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"> <i data-feather="send" class="w-4 h-4 mr-1"></i> Kirim Produk </button> <?php endif; ?> </div> </td> </tr> <?php endforeach; ?> </tbody> </table> </div> </div> <div class="bg-white rounded-lg shadow-sm p-6"> <h2 class="text-lg font-semibold mb-6">Informasi Pengiriman</h2> <!-- Affiliate Address--> <div class="mb-6"> <div class="flex items-start gap-4"> <div class="w-1/3"> <div class="flex items-center gap-2 mb-2"> <label class="text-[#333] font-medium">Alamat Lengkap</label> <span class="text-xs text-gray-500 px-2 py-1 bg-gray-100 rounded">Wajib</span> </div> <div class="mt-3 text-sm text-gray-600"> <p>Dicek lagi, jangan sampe salah.</p> </div> </div> <div class="w-2/3"> <input id="customer_address" type="text" name="customer_address" value="<?= $affiliate->shipping_address ?>" placeholder="Misalnya: Jalanin aja dulu" autocomplete="off" required class="mt-1 w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-1 focus:ring-[#7A4397] focus:outline-none text-[#333] placeholder-gray-500" /> </div> </div> </div> </div> <div class="bg-white rounded-lg shadow-sm p-6"> <h2 class="text-lg font-semibold mb-6">Informasi Pembayaran</h2> <!-- Nama Bank --> <div class="mb-6"> <div class="flex items-start gap-4"> <div class="w-1/3"> <div class="flex items-center gap-2 mb-2"> <label class="text-[#333] font-medium">Nama Bank</label> <span class="text-xs text-gray-500 px-2 py-1 bg-gray-100 rounded">Wajib</span> </div> <div class="mt-3 text-sm text-gray-600"> <p>Pilih bank yang sesuai untuk pencairan komisi</p> </div> </div> <div class="w-2/3"> <input id="affiliate_bank" type="text" name="affiliate_bank" placeholder="Misalnya: BCA, Mandiri, BRI" autocomplete="off" required value="<?= $affiliate->account_type ?>" class="mt-1 w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-1 focus:ring-[#7A4397] focus:outline-none text-[#333] placeholder-gray-500" /> </div> </div> </div> <!-- Nama Pemilik Rekening --> <div class="mb-6"> <div class="flex items-start gap-4"> <div class="w-1/3"> <div class="flex items-center gap-2 mb-2"> <label class="text-[#333] font-medium">Nama Pemilik Rekening</label> <span class="text-xs text-gray-500 px-2 py-1 bg-gray-100 rounded">Wajib</span> </div> <div class="mt-3 text-sm text-gray-600"> <p>Pastikan nama pemilik rekening sesuai dengan data yang terdaftar di bank</p> </div> </div> <div class="w-2/3"> <input id="account_name" type="text" name="account_name" placeholder="Misalnya: Budi Santoso" autocomplete="off" required value="<?= $affiliate->account_name ?>" class="mt-1 w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-1 focus:ring-[#7A4397] focus:outline-none text-[#333] placeholder-gray-500" /> </div> </div> </div> <!-- Nomor Rekening --> <div class="mb-6"> <div class="flex items-start gap-4"> <div class="w-1/3"> <div class="flex items-center gap-2 mb-2"> <label class="text-[#333] font-medium">Nomor Rekening</label> <span class="text-xs text-gray-500 px-2 py-1 bg-gray-100 rounded">Wajib</span> </div> <div class="mt-3 text-sm text-gray-600"> <p>Masukkan nomor rekening tujuan pencairan dana</p> </div> </div> <div class="w-2/3"> <input id="account_number" type="text" name="account_number" placeholder="Misalnya: 1234567890" autocomplete="off" required value="<?= $affiliate->account_number ?>" class="mt-1 w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-1 focus:ring-[#7A4397] focus:outline-none text-[#333] placeholder-gray-500" /> </div> </div> </div> </div> <input type="hidden" id="affiliate_id" name="affiliate_id" value="<?= $affiliate->id_daftar ?>"> <input type="hidden" id="customer_id" name="customer_id" value="<?= $affiliate->id_customer ?>"> <!-- Action Buttons --> <!-- <div class="flex justify-end gap-4 p-6"> <button type="button" class="px-6 py-2 border border-gray-300 rounded-lg hover:bg-gray-50 transition-colors" onclick="window.location.href='<?= base_url('admin/customers/manage') ?>'"> Batal </button> <button type="submit" class="px-6 py-2 bg-[#7A4397] text-white rounded-lg hover:bg-[#7A4397] transition-colors"> Simpan Perubahan </button> </div> --> </form> <!-- <div class="bg-gray-100 p-4 rounded-md"> <pre class="whitespace-pre-wrap text-sm text-[#333]"> <?= htmlspecialchars(json_encode($affiliate, JSON_PRETTY_PRINT), ENT_QUOTES, 'UTF-8') ?> </pre> </div> --> </main> <div id="add-product-link-modal" class="fixed inset-0 z-[99] hidden overflow-y-auto"> <div class="flex items-center justify-center min-h-screen p-4"> <!-- Modal backdrop --> <div class="fixed inset-0 bg-black opacity-50" id="modal-backdrop"></div> <!-- Modal content --> <div class="relative bg-white rounded-lg w-full max-w-4xl mx-auto shadow-xl"> <!-- Modal header --> <div class="flex items-center justify-between px-6 py-4 border-b"> <h3 class="text-lg font-medium text-gray-900">Tambah Link Produk</h3> <button type="button" id="close-modal-btn" class="text-gray-400 hover:text-gray-500"> <i data-feather="x" class="w-5 h-5"></i> </button> </div> <!-- Modal body --> <div class="px-6 py-4"> <!-- Search box --> <div class="mb-4"> <label for="product-search" class="block text-sm font-medium text-gray-700 mb-3">Cari Produk</label> <div class="relative mb-4"> <input type="text" id="product-search" class="shadow-sm focus:ring-[#7A4397] focus:border-[#7A4397] block w-full sm:text-sm border-gray-300 rounded-lg pl-10 pr-4 py-2 transition-all duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-[#7A4397] focus:border-[#7A4397]" placeholder="Cari nama produk..."> <div class="absolute inset-y-0 left-0 flex items-center pl-3"> <i data-feather="search" class="w-5 h-5 text-gray-500"></i> </div> <button type="button" class="absolute inset-y-0 right-0 flex items-center px-3 text-white bg-purple-700 hover:bg-[#7A4397] transition-all duration-200 rounded-r-lg"> <i data-feather="arrow-right" class="w-4 h-4"></i> </button> </div> </div> <!-- Loading indicator --> <div id="products-loading" class="flex justify-center py-8"> <div class="animate-spin rounded-full h-8 w-8 border-t-2 border-b-2 border-[#7A4397]"></div> </div> <!-- Products list --> <div id="products-list" class="hidden overflow-y-auto max-h-96"> <div class="grid grid-cols-1 md:grid-cols-2 gap-4" id="products-grid"> <!-- Product cards will be added dynamically --> </div> </div> <!-- Empty state --> <div id="products-empty" class="hidden py-8 text-center"> <i data-feather="package" class="w-12 h-12 mx-auto text-gray-400 mb-2"></i> <p class="text-gray-500">Tidak ada produk ditemukan</p> </div> <!-- Error state --> <div id="products-error" class="hidden py-8 text-center"> <i data-feather="alert-circle" class="w-12 h-12 mx-auto text-red-400 mb-2"></i> <p class="text-gray-500">Terjadi kesalahan saat mengambil data produk</p> <button id="retry-btn" class="mt-4 inline-flex items-center px-3 py-2 border border-transparent text-sm leading-4 font-medium rounded-md text-white bg-[#7A4397] hover:bg-[#6a3784] focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-[#7A4397]"> <i data-feather="refresh-cw" class="w-4 h-4 mr-2"></i> Coba Lagi </button> </div> </div> <!-- Modal footer --> <div class="px-6 py-4 border-t flex justify-end"> <button type="button" id="cancel-modal-btn" class="bg-white py-2 px-4 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-[#7A4397] mr-3"> Batal </button> <button type="button" id="save-products-btn" class="inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-[#7A4397] hover:bg-[#6a3784] focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-[#7A4397]"> Tambahkan Produk </button> </div> </div> </div> </div> <template id="product-template"> <div class="product-card border rounded-lg p-4 mb-3"> <div class="flex items-start space-x-4 mb-2"> <div class="flex-shrink-0"> <img class="product-image h-16 w-16 object-cover rounded" src="" alt="Product image"> </div> <div class="flex-1 min-w-0"> <h4 class="product-title text-sm font-medium text-gray-900 truncate"></h4> <p class="product-brand text-xs text-gray-500 mt-1"></p> </div> </div> <div class="variant-container"></div> </div> </template> <!-- Template untuk varian produk --> <template id="variant-template"> <div class="variant-item border-t pt-2 mt-2"> <div class="flex items-start space-x-3"> <input type="checkbox" class="variant-checkbox mt-1 rounded text-[#7A4397] focus:ring-[#7A4397] h-4 w-4" data-product-id="" data-product-detail-id="" data-sku="" data-price="" data-stock=""> <div class="flex-1"> <p class="variant-info text-xs text-gray-700"></p> <p class="variant-sku text-xs text-gray-500 mt-1"></p> <div class="flex items-center mt-1"> <span class="variant-price text-sm font-semibold text-gray-900"></span> <span class="variant-stock ml-2 px-2 py-0.5 text-xs rounded-full"></span> </div> </div> </div> </div> </template> <script> document.addEventListener('DOMContentLoaded', function() { const copyButtons = document.querySelectorAll('.copy-link-btn'); copyButtons.forEach(button => { button.addEventListener('click', function() { const link = this.getAttribute('data-link'); navigator.clipboard.writeText(link).then(() => { // Tampilkan notifikasi sukses const originalText = this.innerHTML; this.innerHTML = '<i data-feather="check" class="w-4 h-4 mr-1"></i> Disalin!'; feather.replace(); this.classList.remove('bg-white'); this.classList.add('bg-green-50', 'text-green-700'); setTimeout(() => { this.innerHTML = originalText; feather.replace(); this.classList.remove('bg-green-50', 'text-green-700'); this.classList.add('bg-white'); }, 2000); }).catch(err => { console.error('Gagal menyalin: ', err); }); }); }); // Add event listeners to all send product buttons document.querySelectorAll('.send-product-btn').forEach(button => { button.addEventListener('click', function() { // Get CSRF tokens const CSRF_TOKEN = "<?= $this->security->get_csrf_token_name(); ?>"; const CSRF_HASH = "<?= $this->security->get_csrf_hash(); ?>"; // Get data from button attributes const productId = this.getAttribute('data-product-id'); const daftarId = <?= $affiliate->id_daftar ?>; const customerId = this.getAttribute('data-customer-id'); const productDetailId = this.getAttribute('data-product-detail-id'); // Disable button and show loading state this.disabled = true; const originalText = this.innerHTML; this.innerHTML = '<i data-feather="loader" class="animate-spin w-4 h-4 mr-1"></i> Memproses...'; feather.replace(); // Create FormData object const formData = new FormData(); // Add CSRF token formData.append(CSRF_TOKEN, CSRF_HASH); // Add required data formData.append('product_id', productId); formData.append('customer_id', customerId); formData.append('daftar_id', daftarId); formData.append('product_detail_id', productDetailId); // Send request to create order fetch('<?= base_url('admin/affiliator/send_product') ?>', { method: 'POST', headers: { 'X-Requested-With': 'XMLHttpRequest' }, body: formData, // Add this option to follow redirects redirect: 'follow' }) .then(response => { // Since the server does a PHP redirect, we need to handle it differently if (response.redirected) { // Show success message before redirecting notyf.success('Order berhasil dibuat'); // Follow the redirect after a short delay so user can see the notification setTimeout(() => { window.location.href = response.url; }, 1000); return; } // If not redirected but response is ok, probably needs to refresh if (response.ok) { notyf.success('Order berhasil dibuat'); window.location.reload(); return; } // If we reach here, something went wrong throw new Error('Gagal membuat order'); }) .catch(error => { console.error('Error creating order:', error); notyf.error('Terjadi kesalahan saat membuat order'); // Reset button this.disabled = false; this.innerHTML = originalText; feather.replace(); }); }); }); // Fungsi Modal Tambah Produk Link const modal = document.getElementById('add-product-link-modal'); const modalBackdrop = document.getElementById('modal-backdrop'); const addProductLinkBtn = document.getElementById('add-product-link-btn'); const closeModalBtn = document.getElementById('close-modal-btn'); const cancelModalBtn = document.getElementById('cancel-modal-btn'); const saveProductsBtn = document.getElementById('save-products-btn'); const selectAllCheckbox = document.getElementById('select-all-products'); const productSearch = document.getElementById('product-search'); const retryBtn = document.getElementById('retry-btn'); const productsLoading = document.getElementById('products-loading'); const productsList = document.getElementById('products-list'); const productsGrid = document.getElementById('products-grid'); const productsEmpty = document.getElementById('products-empty'); const productsError = document.getElementById('products-error'); // Format currency function formatRupiah(number) { return 'Rp ' + number.toString().replace(/\B(?=(\d{3})+(?!\d))/g, "."); } // Function to toggle modal function toggleModal() { if (modal.classList.contains('hidden')) { modal.classList.remove('hidden'); document.body.classList.add('overflow-hidden'); // Fetch products when opening modal fetchProducts(); } else { modal.classList.add('hidden'); document.body.classList.remove('overflow-hidden'); // Reset search and selection productSearch.value = ''; selectAllCheckbox.checked = false; } } // Event Listeners for modal addProductLinkBtn.addEventListener('click', toggleModal); closeModalBtn.addEventListener('click', toggleModal); cancelModalBtn.addEventListener('click', toggleModal); modalBackdrop.addEventListener('click', toggleModal); // Fetch products from API function fetchProducts() { // Show loading state productsLoading.classList.remove('hidden'); productsList.classList.add('hidden'); productsEmpty.classList.add('hidden'); productsError.classList.add('hidden'); // Clear previous products productsGrid.innerHTML = ''; // Fetch products from API fetch('<?= base_url('admin/products/get_products?tab=active') ?>') .then(response => { if (!response.ok) { throw new Error('Network response was not ok'); } return response.json(); }) .then(data => { // Hide loading productsLoading.classList.add('hidden'); if (data && data.length > 0) { // Show products list productsList.classList.remove('hidden'); // Render products renderProducts(data); } else { // Show empty state productsEmpty.classList.remove('hidden'); } }) .catch(error => { console.error('Error fetching products:', error); // Hide loading and show error productsLoading.classList.add('hidden'); productsError.classList.remove('hidden'); }); } function renderProducts(products) { const productTemplate = document.getElementById('product-template'); const variantTemplate = document.getElementById('variant-template'); products.forEach(product => { // Clone product template const productElement = document.importNode(productTemplate.content, true); // Set product data const imageUrl = product.image ? '<?= base_url("uploads/product/") ?>' + product.image : '<?= base_url("assets/images/product-placeholder.png") ?>'; productElement.querySelector('.product-image').src = imageUrl; productElement.querySelector('.product-title').textContent = product.title; productElement.querySelector('.product-brand').textContent = 'Brand: ' + (product.brand_title || 'N/A'); // Container untuk varian const variantContainer = productElement.querySelector('.variant-container'); // Render setiap varian if (product.variants && product.variants.length > 0) { product.variants.forEach(variant => { // Clone variant template const variantElement = document.importNode(variantTemplate.content, true); // Set checkbox data attributes const checkbox = variantElement.querySelector('.variant-checkbox'); checkbox.setAttribute('data-product-id', product.id_products); checkbox.setAttribute('data-product-detail-id', variant.product_detail_id); checkbox.setAttribute('data-sku', variant.sku); checkbox.setAttribute('data-price', variant.price); checkbox.setAttribute('data-stock', variant.stock); // Set varian info variantElement.querySelector('.variant-info').textContent = variant.attribute + ': ' + variant.attribute_detail; variantElement.querySelector('.variant-sku').textContent = 'SKU: ' + variant.sku; variantElement.querySelector('.variant-price').textContent = formatRupiah(variant.price); // Set stock status const stockElement = variantElement.querySelector('.variant-stock'); if (variant.stock > 10) { stockElement.textContent = 'Stok Tersedia'; stockElement.classList.add('bg-green-100', 'text-green-800'); } else if (variant.stock > 0) { stockElement.textContent = 'Stok Terbatas'; stockElement.classList.add('bg-yellow-100', 'text-yellow-800'); } else { stockElement.textContent = 'Stok Habis'; stockElement.classList.add('bg-red-100', 'text-red-800'); } // Append varian to container variantContainer.appendChild(variantElement); }); } else { // Jika tidak ada varian, buat opsi default const variantElement = document.importNode(variantTemplate.content, true); const checkbox = variantElement.querySelector('.variant-checkbox'); checkbox.setAttribute('data-product-id', product.id_products); checkbox.setAttribute('data-product-detail-id', product.product_detail_id); checkbox.setAttribute('data-sku', product.sku); checkbox.setAttribute('data-price', product.price); checkbox.setAttribute('data-stock', product.total_stock); variantElement.querySelector('.variant-info').textContent = 'Tidak ada varian'; variantElement.querySelector('.variant-sku').textContent = 'SKU: ' + product.sku; variantElement.querySelector('.variant-price').textContent = formatRupiah(product.price); // Set stock status const stockElement = variantElement.querySelector('.variant-stock'); if (product.total_stock > 10) { stockElement.textContent = 'Stok Tersedia'; stockElement.classList.add('bg-green-100', 'text-green-800'); } else if (product.total_stock > 0) { stockElement.textContent = 'Stok Terbatas'; stockElement.classList.add('bg-yellow-100', 'text-yellow-800'); } else { stockElement.textContent = 'Stok Habis'; stockElement.classList.add('bg-red-100', 'text-red-800'); } variantContainer.appendChild(variantElement); } // Append to grid productsGrid.appendChild(productElement); }); // Initialize feather icons for new elements if (typeof feather !== 'undefined') { feather.replace(); } } // // Select All toggle // selectAllCheckbox.addEventListener('change', function() { // const checkboxes = document.querySelectorAll('.product-checkbox'); // checkboxes.forEach(checkbox => { // checkbox.checked = this.checked; // }); // }); // Filter products on search productSearch.addEventListener('input', function() { const searchTerm = this.value.toLowerCase(); const productCards = document.querySelectorAll('.product-card'); let hasVisibleProducts = false; productCards.forEach(card => { const title = card.querySelector('.product-title').textContent.toLowerCase(); const brand = card.querySelector('.product-brand').textContent.toLowerCase(); // Periksa semua varian dalam kartu produk const variantItems = card.querySelectorAll('.variant-item'); let hasVisibleVariant = false; variantItems.forEach(variantItem => { const variantInfo = variantItem.querySelector('.variant-info').textContent.toLowerCase(); const variantSku = variantItem.querySelector('.variant-sku').textContent.toLowerCase(); // Jika varian cocok dengan pencarian, tampilkan varian if (variantInfo.includes(searchTerm) || variantSku.includes(searchTerm)) { variantItem.style.display = ''; hasVisibleVariant = true; } else { // Jika judul produk atau brand cocok, tampilkan semua varian if (title.includes(searchTerm) || brand.includes(searchTerm)) { variantItem.style.display = ''; hasVisibleVariant = true; } else { variantItem.style.display = 'none'; } } }); // Tampilkan kartu produk jika minimal ada satu varian yang terlihat if (hasVisibleVariant || title.includes(searchTerm) || brand.includes(searchTerm)) { card.style.display = ''; hasVisibleProducts = true; // Jika pencarian cocok dengan judul/brand produk, tampilkan semua varian if (title.includes(searchTerm) || brand.includes(searchTerm)) { variantItems.forEach(item => { item.style.display = ''; }); } } else { card.style.display = 'none'; } }); // Toggle empty state if (hasVisibleProducts) { productsEmpty.classList.add('hidden'); productsList.classList.remove('hidden'); } else { productsEmpty.classList.remove('hidden'); productsList.classList.add('hidden'); } }); // Retry button retryBtn.addEventListener('click', fetchProducts); // Save selected products saveProductsBtn.addEventListener('click', function() { const selectedCheckboxes = document.querySelectorAll('.variant-checkbox:checked'); const customerId = '<?php echo $affiliate->id_customer; ?>'; const affiliatorName = '<?php echo $affiliate->nama; ?>'; const referralCode = '<?php echo $affiliate->referral; ?>'; // Dapatkan kode referral dari data affiliator const CSRF_TOKEN = "<?= $this->security->get_csrf_token_name(); ?>"; const CSRF_HASH = "<?= $this->security->get_csrf_hash(); ?>"; if (selectedCheckboxes.length === 0) { notyf.error('Silakan pilih minimal satu produk'); return; } // Disable button and show loading state this.disabled = true; this.innerHTML = '<i data-feather="loader" class="animate-spin w-4 h-4 mr-2"></i> Menyimpan...'; feather.replace(); // Prepare data for API const selectedProducts = Array.from(selectedCheckboxes).map(checkbox => { // Dapatkan informasi produk const productId = checkbox.getAttribute('data-product-id'); // Dapatkan nama produk dari kartu produk induk const productCard = checkbox.closest('.product-card'); const productName = productCard.querySelector('.product-title').textContent; // Dapatkan informasi varian const productDetailId = checkbox.getAttribute('data-product-detail-id'); const sku = checkbox.getAttribute('data-sku'); const price = checkbox.getAttribute('data-price'); const stock = checkbox.getAttribute('data-stock'); // Dapatkan alias produk - jika tidak tersedia di data attribute, bisa menggunakan hardcoded value // atau kita bisa menambahkan data-alias saat rendering let productAlias = ''; productAlias = productName.replace(/\s+/g, '-').toLowerCase(); // Generate unique ID untuk link (bisa diganti dengan metode yang lebih sesuai) const uniqueId = referralCode; // Buat link produk dengan format yang diminta const productLink = '<?= base_url("product") ?>/' + productAlias + '/' + referralCode; return { product_id: productId, product_detail_id: productDetailId, product_name: productName, sku: sku, price: price, stock: stock, customer_id: customerId, affiliator_name: affiliatorName, unique_id: uniqueId, link: productLink }; }); // Create FormData object const formData = new FormData(); // Add CSRF token formData.append(CSRF_TOKEN, CSRF_HASH); // Add products data as stringified JSON field formData.append('products', JSON.stringify(selectedProducts)); // Send data to backend using FormData fetch('<?= base_url('admin/affiliator/add_product_links') ?>', { method: 'POST', headers: { 'X-Requested-With': 'XMLHttpRequest' }, body: formData }) .then(response => response.json()) .then(data => { if (data.success) { // Close modal and refresh page after 2 seconds notyf.success('Produk berhasil ditambahkan'); setTimeout(() => { window.location.reload(); }, 2000); // 2000 ms = 2 detik } else { notyf.error('Gagal menambahkan produk: ' + (data.message || 'Terjadi kesalahan')); // Reset button state saveProductsBtn.disabled = false; saveProductsBtn.innerHTML = 'Tambahkan Produk'; feather.replace(); } }) .catch(error => { console.error('Error adding products:', error); notyf.error('Terjadi kesalahan saat menambahkan produk'); // Reset button state saveProductsBtn.disabled = false; saveProductsBtn.innerHTML = 'Tambahkan Produk'; feather.replace(); }); }); }); </script>