855 lines
36 KiB
PHP
855 lines
36 KiB
PHP
<!DOCTYPE html>
|
||
<html lang="en">
|
||
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta content="width=device-width, initial-scale=1.0" name="viewport">
|
||
|
||
<title>Ellia Cellular</title>
|
||
<meta content="" name="description">
|
||
<meta content="" name="keywords">
|
||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||
|
||
|
||
<!-- Favicons -->
|
||
<link href="{{ asset('assets/img/logo_ellia_cellular.jpeg') }}" rel="icon">
|
||
<link href="{{ asset('assets/img/apple-touch-icon.png') }}" rel="apple-touch-icon">
|
||
|
||
|
||
<!-- Google Fonts -->
|
||
<link href="https://fonts.gstatic.com" rel="preconnect">
|
||
<link
|
||
href="https://fonts.googleapis.com/css?family=Open+Sans:300,300i,400,400i,600,600i,700,700i|Nunito:300,300i,400,400i,600,600i,700,700i|Poppins:300,300i,400,400i,500,500i,600,600i,700,700i"
|
||
rel="stylesheet">
|
||
|
||
<!-- Tambahkan ini di bagian <head> atau sebelum penutup </body> -->
|
||
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
||
|
||
|
||
<!-- Vendor CSS Files -->
|
||
<link href="{{ asset('assets/vendor/bootstrap/css/bootstrap.min.css') }}" rel="stylesheet">
|
||
<link href="{{ asset('assets/vendor/bootstrap-icons/bootstrap-icons.css') }}" rel="stylesheet">
|
||
<link href="{{ asset('assets/vendor/boxicons/css/boxicons.min.css') }}" rel="stylesheet">
|
||
<link href="{{ asset('assets/vendor/quill/quill.snow.css') }}" rel="stylesheet">
|
||
<link href="{{ asset('assets/vendor/quill/quill.bubble.css') }}" rel="stylesheet">
|
||
<link href="{{ asset('assets/vendor/remixicon/remixicon.css') }}" rel="stylesheet">
|
||
<link href="{{ asset('assets/vendor/simple-datatables/style.css') }}" rel="stylesheet">
|
||
|
||
<!-- Template Main CSS File -->
|
||
<link href="{{ asset('assets/css/style.css') }}" rel="stylesheet">
|
||
</head>
|
||
|
||
<body>
|
||
|
||
<!-- ======= Header ======= -->
|
||
@include('header')
|
||
<!-- ======= Sidebar ======= -->
|
||
@include('sidebar')
|
||
|
||
<!-- ======= Orderbar ======= -->
|
||
<aside id="orderbar" class="orderbar">
|
||
<h3>Detail Order</h3>
|
||
<div class="no-items">Tidak ada item yang dipilih</div>
|
||
|
||
<hr>
|
||
|
||
<div class="order-list"></div>
|
||
|
||
<div class="order-summary">
|
||
<p class="subtotal"><span>Sub Total</span> <span>Rp 0</span></p>
|
||
<p class="total"><strong>Total</strong> <strong>Rp 0</strong></p>
|
||
<button class="pay-button btn btn-primary" id="openPaymentModal" data-bs-toggle="modal"
|
||
data-bs-target="#paymentModal">
|
||
Bayar
|
||
</button>
|
||
</div>
|
||
</aside>
|
||
|
||
<!-- ======= End Orderbar ======= -->
|
||
|
||
<main id="main" class="main">
|
||
<div class="pagetitle">
|
||
<h1>Kasir</h1>
|
||
<nav>
|
||
<ol class="breadcrumb">
|
||
<li class="breadcrumb-item"><a href="index.html">Home</a></li>
|
||
<li class="breadcrumb-item">Kasir</li>
|
||
</ol>
|
||
</nav>
|
||
</div><!-- End Page Title -->
|
||
|
||
<section class="section">
|
||
<div class="row">
|
||
<div class="col-lg-12">
|
||
<div class="card">
|
||
<div class="card-body">
|
||
<h5 class="card-title">Kasir</h5>
|
||
<div class="mb-2">
|
||
<input type="text" class="form-control" id="searchInput" placeholder="Cari..."
|
||
style="width: 200px;">
|
||
</div>
|
||
|
||
<div class="row row-cols-1 row-cols-md-2 g-4 mt-3">
|
||
@foreach ($product as $p)
|
||
<div class="col">
|
||
<div class="card h-100 d-flex flex-column p-3">
|
||
<div class="d-flex flex-row">
|
||
<div class="w-50 d-flex flex-column justify-content-center">
|
||
<span class="text-muted">{{ $p->category->nama_kategori }}</span>
|
||
<h5 class="mt-1 fw-bold">{{ $p->nama_produk }}</h5>
|
||
<p class="mb-1 text-muted">Stok: {{ $p->stok }}</p>
|
||
<p class="fw-bold text-primary">Rp
|
||
{{ number_format($p->harga, 0, ',', '.') }}</p>
|
||
</div>
|
||
<div class="w-50 d-flex justify-content-end">
|
||
<img src="{{ asset('upload/produk/' . ($p->image && $p->image != '' ? $p->image : 'Gambar_HP_Awal.png')) }}"
|
||
class="rounded"
|
||
style="width: 50%; height: auto; object-fit: cover;"
|
||
alt="Produk">
|
||
</div>
|
||
</div>
|
||
<div class="mt-auto">
|
||
<button class="btn btn-outline-primary w-100 masuk-order"
|
||
data-id="{{ $p->id }}" data-name="{{ $p->nama_produk }}"
|
||
data-price="{{ $p->harga }}"
|
||
data-image="{{ asset('upload/produk/' . $p->image) }}">
|
||
Masuk Order
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
@endforeach
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
</main><!-- End #main -->
|
||
|
||
<!-- Modal Pembayaran (Hanya Satu Modal) -->
|
||
<div class="modal fade" id="paymentModal" tabindex="-1" aria-labelledby="paymentModalLabel" aria-hidden="true">
|
||
<div class="modal-dialog modal-lg">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h5 class="modal-title" id="paymentModalLabel">Pembayaran Order</h5>
|
||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||
</div>
|
||
<form id="paymentForm"><div class="chat-container">
|
||
</div>
|
||
|
||
<script>
|
||
// Get the chat input and send button elements
|
||
const chatInput = document.getElementById('chat-input');
|
||
const sendButton = document.getElementById('send-button');
|
||
|
||
// Add an event listener to the send button
|
||
sendButton.addEventListener('click', () => {
|
||
// Get the message from the chat input
|
||
const message = chatInput.value.trim();
|
||
|
||
// Check if the message is not empty
|
||
if (message) {
|
||
// Send the message to the server (replace with your server-side logic)
|
||
// For demonstration purposes, we'll just display the message in the chat
|
||
const chatMessages = document.querySelector('.chat-messages');
|
||
const messageElement = document.createElement('div');
|
||
messageElement.textContent = message;
|
||
chatMessages.appendChild(messageElement);
|
||
|
||
// Clear the chat input
|
||
chatInput.value = '';
|
||
}
|
||
});
|
||
</script>
|
||
<div class="modal-body">
|
||
<div class="row">
|
||
<div class="col-md-6">
|
||
{{-- <h6 id="cashierId">#-</h6> --}}
|
||
<ul class="list-unstyled" id="orderItems">
|
||
<li>Tidak ada item</li>
|
||
</ul>
|
||
<hr>
|
||
<p>Subtotal: <strong id="subtotalText">Rp 0</strong></p>
|
||
<p>Diskon: <strong id="discountText">Rp 0</strong></p>
|
||
<p>Total: <strong id="totalText">Rp 0</strong></p>
|
||
<p>Bayar: <strong id="paidText">Rp 0</strong></p>
|
||
<p>Kembalian: <strong id="changeText">Rp 0</strong></p>
|
||
</div>
|
||
<div class="col-md-6">
|
||
<label for="discountInput" class="form-label">Masukkan Diskon</label>
|
||
<input type="number" class="form-control" id="discountInput" name="discount" placeholder="Masukkan diskon">
|
||
<label for="paymentMethod" class="form-label mt-3">Metode Pembayaran</label>
|
||
<select class="form-select" id="paymentMethod" name="paymentMethod" required>
|
||
<option value="Cash">Cash</option>
|
||
<option value="Qris">Qris</option>
|
||
<option value="Debit">Debit</option>
|
||
</select>
|
||
<label class="form-label mt-3">Masukkan Jumlah Bayar</label>
|
||
<input type="number" class="form-control" id="amountPaid" name="amountPaid" placeholder="Rp 0">
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Tutup</button>
|
||
<button type="submit" class="btn btn-primary">Bayar</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- JavaScript untuk Menampilkan Modal dengan Data yang Benar -->
|
||
<script>
|
||
document.querySelectorAll(".masuk-order").forEach(button => {
|
||
button.addEventListener("click", function() {
|
||
let productId = this.getAttribute("data-id");
|
||
let productName = this.getAttribute("data-name");
|
||
let productPrice = parseInt(this.getAttribute("data-price"));
|
||
let productStock = parseInt(this.getAttribute("data-stock")); // Ambil stok produk
|
||
|
||
// Cek apakah stok kosong, jika iya maka tidak masuk ke order list
|
||
if (productStock === 0) {
|
||
alert(`Stok ${productName} habis!`);
|
||
return;
|
||
}
|
||
|
||
let existingItem = selectedProducts.find(item => item.id === productId);
|
||
if (!existingItem) {
|
||
selectedProducts.push({
|
||
id: productId,
|
||
name: productName,
|
||
price: productPrice
|
||
});
|
||
}
|
||
|
||
updateOrderList();
|
||
});
|
||
});
|
||
|
||
document.addEventListener("DOMContentLoaded", function() {
|
||
let selectedProducts = [];
|
||
let orderItems = {};
|
||
|
||
function updateOrderList() {
|
||
let orderList = document.querySelector(".order-list");
|
||
let subtotalElement = document.querySelector(".subtotal span:last-child");
|
||
let totalElement = document.querySelector(".total strong:last-child");
|
||
let noItemsMessage = document.querySelector(".no-items");
|
||
|
||
orderList.innerHTML = "";
|
||
let subtotal = 0;
|
||
|
||
if (selectedProducts.length === 0) {
|
||
noItemsMessage.style.display = "block";
|
||
subtotalElement.textContent = "Rp 0";
|
||
totalElement.textContent = "Rp 0";
|
||
} else {
|
||
noItemsMessage.style.display = "none";
|
||
selectedProducts.forEach(item => {
|
||
let listItem = document.createElement("div");
|
||
listItem.classList.add("order-item");
|
||
listItem.innerHTML =
|
||
`<p>${item.name} - Rp ${item.price.toLocaleString("id-ID")}</p>`;
|
||
orderList.appendChild(listItem);
|
||
subtotal += item.price;
|
||
});
|
||
|
||
subtotalElement.textContent = `Rp ${subtotal.toLocaleString("id-ID")}`;
|
||
totalElement.textContent = `Rp ${subtotal.toLocaleString("id-ID")}`;
|
||
}
|
||
}
|
||
|
||
document.getElementById("openPaymentModal").addEventListener("click", function() {
|
||
let orderItemsContainer = document.getElementById("orderItems");
|
||
let subtotalText = document.getElementById("subtotalText");
|
||
let totalText = document.getElementById("totalText");
|
||
|
||
orderItemsContainer.innerHTML = "";
|
||
let orderItems = document.querySelectorAll(".order-item");
|
||
|
||
if (orderItems.length > 0) {
|
||
orderItems.forEach((item) => {
|
||
let clonedItem = item.cloneNode(true);
|
||
orderItemsContainer.appendChild(clonedItem);
|
||
});
|
||
} else {
|
||
orderItemsContainer.innerHTML = "<li>Tidak ada item</li>";
|
||
}
|
||
|
||
let subtotalElement = document.querySelector(".subtotal span:last-child");
|
||
let totalElement = document.querySelector(".total strong:last-child");
|
||
|
||
let subtotal = parseInt(subtotalElement.textContent.replace(/\D/g, "")) || 0;
|
||
let total = parseInt(totalElement.textContent.replace(/\D/g, "")) || 0;
|
||
|
||
subtotalText.textContent = `Rp ${subtotal.toLocaleString("id-ID")}`;
|
||
totalText.textContent = `Rp ${total.toLocaleString("id-ID")}`;
|
||
});
|
||
|
||
// Update total setelah diskon diinput
|
||
document.getElementById("discountInput").addEventListener("input", function() {
|
||
let subtotal = parseInt(document.getElementById("subtotalText").textContent.replace(/\D/g,
|
||
"")) || 0;
|
||
let discount = parseInt(this.value) || 0;
|
||
let total = subtotal - discount;
|
||
total = total < 0 ? 0 : total; // Pastikan total tidak negatif
|
||
|
||
document.getElementById("discountText").textContent =
|
||
`Rp ${discount.toLocaleString("id-ID")}`;
|
||
document.getElementById("totalText").textContent = `Rp ${total.toLocaleString("id-ID")}`;
|
||
|
||
// Perbarui jumlah bayar jika metode pembayaran adalah Qris atau Debit
|
||
updatePaymentMethod();
|
||
});
|
||
|
||
// Update jumlah bayar berdasarkan metode pembayaran
|
||
document.getElementById("paymentMethod").addEventListener("change", updatePaymentMethod);
|
||
|
||
function updatePaymentMethod() {
|
||
let paymentMethod = document.getElementById("paymentMethod").value;
|
||
let total = parseInt(document.getElementById("totalText").textContent.replace(/\D/g, "")) || 0;
|
||
let amountPaidInput = document.getElementById("amountPaid");
|
||
let paidText = document.getElementById("paidText");
|
||
|
||
if (paymentMethod === "Qris" || paymentMethod === "Debit") {
|
||
amountPaidInput.value = total;
|
||
amountPaidInput.setAttribute("disabled", "disabled");
|
||
paidText.textContent = `Rp ${total.toLocaleString("id-ID")}`;
|
||
} else {
|
||
amountPaidInput.value = "";
|
||
amountPaidInput.removeAttribute("disabled");
|
||
paidText.textContent = "Rp 0";
|
||
}
|
||
|
||
// Perhitungan ulang kembalian jika ada perubahan
|
||
updateChange();
|
||
}
|
||
|
||
// Perhitungan Kembalian
|
||
document.getElementById("amountPaid").addEventListener("input", updateChange);
|
||
|
||
function updateChange() {
|
||
let total = parseInt(document.getElementById("totalText").textContent.replace(/\D/g, "")) || 0;
|
||
let amountPaidInput = document.getElementById("amountPaid");
|
||
let amountPaid = parseInt(amountPaidInput.value) || 0;
|
||
let change = amountPaid - total;
|
||
|
||
document.getElementById("changeText").textContent =
|
||
`Rp ${change < 0 ? 0 : change.toLocaleString("id-ID")}`;
|
||
document.getElementById("paidText").textContent = `Rp ${amountPaid.toLocaleString("id-ID")}`;
|
||
}
|
||
|
||
// Expose orderItems to be accessible from the payment form event handler
|
||
window.orderItems = orderItems;
|
||
});
|
||
|
||
document.getElementById("paymentForm").addEventListener("submit", function(event) {
|
||
event.preventDefault();
|
||
|
||
let orderItemElements = document.querySelector(".orderbar .order-list").querySelectorAll(".order-item");
|
||
|
||
if (orderItemElements.length === 0) {
|
||
Swal.fire({
|
||
title: 'Error!',
|
||
text: 'Tidak ada item yang dipilih',
|
||
icon: 'error',
|
||
confirmButtonText: 'OK'
|
||
});
|
||
return;
|
||
}
|
||
|
||
let processedProductIds = new Set();
|
||
let subtotal = parseInt(document.getElementById("subtotalText").textContent.replace(/\D/g, "")) || 0;
|
||
let discount = parseInt(document.getElementById("discountInput").value) || 0;
|
||
let total = parseInt(document.getElementById("totalText").textContent.replace(/\D/g, "")) || 0;
|
||
let amountPaid = parseInt(document.getElementById("amountPaid").value) || 0;
|
||
let change = amountPaid - total;
|
||
let paymentMethod = document.getElementById("paymentMethod").value;
|
||
|
||
let savePromises = [];
|
||
|
||
orderItemElements.forEach(item => {
|
||
let plusButton = item.querySelector(".plus");
|
||
if (!plusButton) return;
|
||
|
||
let productId = plusButton.getAttribute("data-id");
|
||
|
||
if (processedProductIds.has(productId)) return;
|
||
processedProductIds.add(productId);
|
||
|
||
let quantity = parseInt(item.querySelector("span.mx-2").textContent);
|
||
|
||
let orderData = {
|
||
produk_id: productId,
|
||
jumlah_item: quantity,
|
||
total: total,
|
||
sub_total: subtotal,
|
||
bayar: amountPaid,
|
||
kembalian: change,
|
||
diskon: discount,
|
||
tipe_bayar: paymentMethod
|
||
};
|
||
|
||
let savePromise = fetch("/cashier/store", {
|
||
method: "POST",
|
||
headers: {
|
||
"Content-Type": "application/json",
|
||
"X-CSRF-TOKEN": document.querySelector('meta[name="csrf-token"]').getAttribute("content")
|
||
},
|
||
body: JSON.stringify(orderData)
|
||
})
|
||
.then(response => response.json())
|
||
.then(data => {
|
||
if (data.status === 'error' && data.message.includes('tidak mencukupi')) {
|
||
throw new Error(data.message);
|
||
}
|
||
return data;
|
||
});
|
||
|
||
savePromises.push(savePromise);
|
||
});
|
||
|
||
if (savePromises.length > 0) {
|
||
Promise.all(savePromises)
|
||
.then(results => {
|
||
const allSuccess = results.every(data => data.status === "success");
|
||
|
||
if (allSuccess) {
|
||
Swal.fire({
|
||
title: 'Sukses!',
|
||
text: 'Transaksi berhasil dan stok telah diperbarui!',
|
||
icon: 'success',
|
||
confirmButtonText: 'OK'
|
||
}).then(() => {
|
||
location.reload();
|
||
});
|
||
} else {
|
||
const errors = results
|
||
.filter(data => data.status !== "success")
|
||
.map(data => data.message || JSON.stringify(data.errors))
|
||
.join(", ");
|
||
|
||
Swal.fire({
|
||
title: 'Sebagian Error!',
|
||
text: 'Beberapa produk gagal disimpan: ' + errors,
|
||
icon: 'warning',
|
||
confirmButtonText: 'OK'
|
||
});
|
||
}
|
||
})
|
||
.catch(error => {
|
||
console.error("Error:", error);
|
||
Swal.fire({
|
||
title: 'Error!',
|
||
text: error.message || 'Terjadi kesalahan saat mengirim data.',
|
||
icon: 'error',
|
||
confirmButtonText: 'OK'
|
||
});
|
||
});
|
||
}
|
||
});
|
||
</script>
|
||
|
||
|
||
|
||
|
||
{{-- <!-- ======= Footer ======= -->
|
||
@include('footer') --}}
|
||
|
||
{{-- <a href="#" class="back-to-top d-flex align-items-center justify-content-center"><i
|
||
class="bi bi-arrow-up-short"></i></a> --}}
|
||
|
||
<!-- Vendor JS Files -->
|
||
<script src="{{ asset('assets/vendor/apexcharts/apexcharts.min.js') }}"></script>
|
||
<script src="{{ asset('assets/vendor/bootstrap/js/bootstrap.bundle.min.js') }}"></script>
|
||
<script src="{{ asset('assets/vendor/chart.js/chart.umd.js') }}"></script>
|
||
<script src="{{ asset('assets/vendor/echarts/echarts.min.js') }}"></script>
|
||
<script src="{{ asset('assets/vendor/quill/quill.js') }}"></script>
|
||
<script src="{{ asset('assets/vendor/simple-datatables/simple-datatables.js') }}"></script>
|
||
<script src="{{ asset('assets/vendor/tinymce/tinymce.min.js') }}"></script>
|
||
<script src="{{ asset('assets/vendor/php-email-form/validate.js') }}"></script>
|
||
|
||
<!-- Template Main JS File -->
|
||
<script src="{{ asset('assets/js/main.js') }}"></script>
|
||
|
||
<!-- script untuk search dan pagination -->
|
||
<script>
|
||
document.addEventListener("DOMContentLoaded", function() {
|
||
const cards = document.querySelectorAll('.col'); // Ambil semua kartu produk
|
||
const paginationContainer = document.createElement("div"); // Buat container pagination
|
||
paginationContainer.className =
|
||
"pagination-container mt-3 d-flex justify-content-end"; // Gunakan justify-content-end untuk meletakkan di kanan
|
||
|
||
const cardsPerPage = 4; // Menampilkan 4 kartu per halaman
|
||
let currentPage = 1;
|
||
|
||
// Fungsi untuk menampilkan kartu berdasarkan halaman
|
||
function displayCards(page, filteredCards) {
|
||
const totalPages = Math.ceil(filteredCards.length / cardsPerPage);
|
||
if (page > totalPages) page = totalPages;
|
||
if (page < 1) page = 1;
|
||
|
||
// Sembunyikan semua kartu
|
||
cards.forEach(card => (card.style.display = "none"));
|
||
|
||
// Tampilkan kartu sesuai halaman
|
||
const startIndex = (page - 1) * cardsPerPage;
|
||
const endIndex = startIndex + cardsPerPage;
|
||
filteredCards.forEach((card, index) => {
|
||
if (index >= startIndex && index < endIndex) {
|
||
card.style.display = "block";
|
||
}
|
||
});
|
||
|
||
updatePagination(page, totalPages);
|
||
}
|
||
|
||
// Fungsi untuk memperbarui pagination
|
||
function updatePagination(currentPage, totalPages) {
|
||
paginationContainer.innerHTML = ""; // Hapus pagination sebelumnya
|
||
|
||
if (totalPages <= 1) return;
|
||
|
||
// Batasi jumlah nomor halaman yang ditampilkan (maksimal 5)
|
||
const maxPagesToShow = 5;
|
||
let startPage = Math.max(1, currentPage - Math.floor(maxPagesToShow / 2));
|
||
let endPage = Math.min(totalPages, startPage + maxPagesToShow - 1);
|
||
|
||
// Jika jumlah halaman yang ditampilkan kurang dari 5, geser startPage
|
||
if (endPage - startPage + 1 < maxPagesToShow) {
|
||
startPage = Math.max(1, endPage - maxPagesToShow + 1);
|
||
}
|
||
|
||
// Tampilkan nomor halaman
|
||
for (let i = startPage; i <= endPage; i++) {
|
||
const button = document.createElement("button");
|
||
button.textContent = i;
|
||
button.className = "btn btn-sm btn-outline-primary mx-1";
|
||
if (i === currentPage) button.classList.add("active");
|
||
|
||
button.addEventListener("click", () => {
|
||
displayCards(i, getFilteredCards());
|
||
});
|
||
|
||
paginationContainer.appendChild(button);
|
||
}
|
||
}
|
||
|
||
// Fungsi untuk mendapatkan kartu yang difilter berdasarkan pencarian
|
||
function getFilteredCards() {
|
||
const filter = document.getElementById('searchInput').value.toLowerCase();
|
||
return Array.from(cards).filter(card => {
|
||
const productName = card.querySelector('h5').innerText.toLowerCase();
|
||
return productName.includes(filter);
|
||
});
|
||
}
|
||
|
||
// Event listener untuk pencarian
|
||
document.getElementById('searchInput').addEventListener('keyup', function() {
|
||
const filteredCards = getFilteredCards();
|
||
displayCards(1, filteredCards); // Tampilkan halaman pertama setelah pencarian
|
||
});
|
||
|
||
// Tampilkan halaman pertama saat pertama kali dimuat
|
||
displayCards(1, Array.from(cards));
|
||
document.querySelector(".row").parentNode.appendChild(paginationContainer);
|
||
});
|
||
</script>
|
||
|
||
{{-- <!-- script untuk search -->
|
||
<script>
|
||
document.getElementById('searchInput').addEventListener('keyup', function() {
|
||
let filter = this.value.toLowerCase();
|
||
let cards = document.querySelectorAll('.col'); // Target semua kartu produk
|
||
|
||
cards.forEach(card => {
|
||
let productName = card.querySelector('h5').innerText
|
||
.toLowerCase(); // Ambil teks nama produk
|
||
if (productName.includes(filter)) {
|
||
card.style.display = 'block'; // Tampilkan jika cocok
|
||
} else {
|
||
card.style.display = 'none'; // Sembunyikan jika tidak cocok
|
||
}
|
||
});
|
||
});
|
||
</script>
|
||
|
||
<!-- script untuk pagination -->
|
||
<script>
|
||
document.addEventListener("DOMContentLoaded", function() {
|
||
const cards = document.querySelectorAll('.col'); // Ambil semua kartu produk
|
||
const paginationContainer = document.createElement("div"); // Buat container pagination
|
||
paginationContainer.className =
|
||
"pagination-container mt-3 d-flex justify-content-end"; // Gunakan justify-content-end untuk meletakkan di kanan
|
||
|
||
const cardsPerPage = 4; // Menampilkan 4 kartu per halaman
|
||
let currentPage = 1;
|
||
|
||
function displayCards(page) {
|
||
const totalPages = Math.ceil(cards.length / cardsPerPage);
|
||
if (page > totalPages) page = totalPages;
|
||
if (page < 1) page = 1;
|
||
|
||
// Sembunyikan semua kartu
|
||
cards.forEach(card => (card.style.display = "none"));
|
||
|
||
// Tampilkan kartu sesuai halaman
|
||
const startIndex = (page - 1) * cardsPerPage;
|
||
const endIndex = startIndex + cardsPerPage;
|
||
cards.forEach((card, index) => {
|
||
if (index >= startIndex && index < endIndex) {
|
||
card.style.display = "block";
|
||
}
|
||
});
|
||
|
||
updatePagination(page, totalPages);
|
||
}
|
||
|
||
function updatePagination(currentPage, totalPages) {
|
||
paginationContainer.innerHTML = ""; // Hapus pagination sebelumnya
|
||
|
||
if (totalPages <= 1) return;
|
||
|
||
// Batasi jumlah nomor halaman yang ditampilkan (maksimal 5)
|
||
const maxPagesToShow = 5;
|
||
let startPage = Math.max(1, currentPage - Math.floor(maxPagesToShow / 2));
|
||
let endPage = Math.min(totalPages, startPage + maxPagesToShow - 1);
|
||
|
||
// Jika jumlah halaman yang ditampilkan kurang dari 5, geser startPage
|
||
if (endPage - startPage + 1 < maxPagesToShow) {
|
||
startPage = Math.max(1, endPage - maxPagesToShow + 1);
|
||
}
|
||
|
||
// Tampilkan nomor halaman
|
||
for (let i = startPage; i <= endPage; i++) {
|
||
const button = document.createElement("button");
|
||
button.textContent = i;
|
||
button.className = "btn btn-sm btn-outline-primary mx-1";
|
||
if (i === currentPage) button.classList.add("active");
|
||
|
||
button.addEventListener("click", () => {
|
||
displayCards(i);
|
||
});
|
||
|
||
paginationContainer.appendChild(button);
|
||
}
|
||
}
|
||
|
||
// Tampilkan halaman pertama saat pertama kali dimuat
|
||
displayCards(1);
|
||
document.querySelector(".row").parentNode.appendChild(paginationContainer);
|
||
});
|
||
</script> --}}
|
||
|
||
<!-- script untuk orderbar -->
|
||
<script>
|
||
document.addEventListener("DOMContentLoaded", function() {
|
||
const orderBar = document.querySelector(".orderbar");
|
||
const orderList = document.createElement("div");
|
||
orderList.className = "order-list";
|
||
orderBar.insertBefore(orderList, orderBar.querySelector("hr"));
|
||
|
||
const subtotalElement = document.querySelector(".subtotal span:last-child");
|
||
const totalElement = document.querySelector(".total strong:last-child");
|
||
const noItemsMessage = document.querySelector(".no-items");
|
||
const buttons = document.querySelectorAll(".masuk-order");
|
||
|
||
let orderItems = {};
|
||
|
||
function updateOrderUI() {
|
||
orderList.innerHTML = "";
|
||
let subtotal = 0;
|
||
|
||
Object.values(orderItems).forEach(item => {
|
||
let itemTotal = item.price * item.quantity;
|
||
subtotal += itemTotal;
|
||
|
||
const orderItem = document.createElement("div");
|
||
orderItem.className =
|
||
"order-item d-flex align-items-center justify-content-between p-2 border-bottom";
|
||
|
||
orderItem.innerHTML = `
|
||
<div class="d-flex align-items-center">
|
||
<img src="${item.image}" class="rounded me-2" style="width: 50px; height: 50px; object-fit: cover;">
|
||
<div>
|
||
<h6 class="mb-1">${item.name}</h6>
|
||
<p class="mb-0 text-muted">Rp ${item.price.toLocaleString()}</p>
|
||
</div>
|
||
</div>
|
||
<div class="d-flex align-items-center">
|
||
<button class="btn btn-sm btn-outline-secondary minus" data-id="${item.id}">−</button>
|
||
<span class="mx-2">${item.quantity}</span>
|
||
<button class="btn btn-sm btn-outline-secondary plus" data-id="${item.id}">+</button>
|
||
</div>
|
||
`;
|
||
|
||
orderList.appendChild(orderItem);
|
||
});
|
||
|
||
subtotalElement.textContent = `Rp ${subtotal.toLocaleString()}`;
|
||
totalElement.textContent = `Rp ${subtotal.toLocaleString()}`;
|
||
noItemsMessage.style.display = Object.keys(orderItems).length === 0 ? "block" : "none";
|
||
|
||
attachEventListeners();
|
||
}
|
||
|
||
function attachEventListeners() {
|
||
document.querySelectorAll(".plus").forEach(btn => {
|
||
btn.addEventListener("click", function() {
|
||
let id = this.getAttribute("data-id");
|
||
if (orderItems[id].quantity < orderItems[id].stock) {
|
||
orderItems[id].quantity++;
|
||
updateOrderUI();
|
||
}
|
||
});
|
||
});
|
||
|
||
document.querySelectorAll(".minus").forEach(btn => {
|
||
btn.addEventListener("click", function() {
|
||
let id = this.getAttribute("data-id");
|
||
if (orderItems[id].quantity > 1) {
|
||
orderItems[id].quantity--;
|
||
} else {
|
||
delete orderItems[id];
|
||
}
|
||
updateOrderUI();
|
||
});
|
||
});
|
||
}
|
||
|
||
buttons.forEach(button => {
|
||
button.addEventListener("click", function() {
|
||
const productId = this.getAttribute("data-id");
|
||
const productName = this.closest(".card").querySelector("h5").textContent;
|
||
const productPrice = parseInt(this.closest(".card").querySelector(
|
||
".fw-bold.text-primary").textContent.replace(/\D/g, ""));
|
||
const productImage = this.closest(".card").querySelector("img").src;
|
||
const productStock = parseInt(this.closest(".card").querySelector(
|
||
".text-muted.mb-1").textContent.replace(/\D/g, ""));
|
||
|
||
// Jika stok kosong, tidak ada respons
|
||
if (productStock === 0) return;
|
||
|
||
// Jika produk sudah ada di orderItems dan belum mencapai batas stok, tambahkan jumlah
|
||
if (orderItems[productId]) {
|
||
if (orderItems[productId].quantity < orderItems[productId].stock) {
|
||
orderItems[productId].quantity++;
|
||
}
|
||
} else {
|
||
orderItems[productId] = {
|
||
id: productId,
|
||
name: productName,
|
||
price: productPrice,
|
||
quantity: 1,
|
||
stock: productStock,
|
||
image: productImage
|
||
};
|
||
}
|
||
|
||
updateOrderUI();
|
||
});
|
||
});
|
||
|
||
updateOrderUI();
|
||
});
|
||
</script>
|
||
|
||
|
||
|
||
|
||
<style>
|
||
.orderbar {
|
||
position: fixed;
|
||
right: 0;
|
||
top: 60px;
|
||
/* Mulai setelah header (sesuaikan dengan tinggi header) */
|
||
width: 250px;
|
||
height: calc(100% - 60px);
|
||
/* Sesuaikan tinggi supaya tidak keluar layar */
|
||
background: #ffffff;
|
||
box-shadow: -2px 0 5px rgba(0, 0, 0, 0.1);
|
||
padding: 20px;
|
||
overflow-y: auto;
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: space-between;
|
||
}
|
||
|
||
|
||
.orderbar h3 {
|
||
text-align: left;
|
||
font-size: 20px;
|
||
/* Perbesar ukuran teks */
|
||
font-weight: bold;
|
||
margin-bottom: 15px;
|
||
color: #333;
|
||
/* Warna lebih gelap agar kontras */
|
||
}
|
||
|
||
.no-items {
|
||
color: #555;
|
||
/* Lebih gelap dari sebelumnya */
|
||
font-size: 16px;
|
||
/* Perbesar ukuran */
|
||
font-style: italic;
|
||
/* Buat lebih menarik */
|
||
text-align: center;
|
||
/* Posisi tengah */
|
||
background: #f8f8f8;
|
||
/* Tambahkan latar belakang */
|
||
padding: 10px;
|
||
/* Tambahkan ruang agar tidak menempel */
|
||
border-radius: 5px;
|
||
/* Beri sudut lengkung */
|
||
margin-bottom: 15px;
|
||
}
|
||
|
||
|
||
hr {
|
||
border: 0;
|
||
border-top: 1px solid #ddd;
|
||
margin: 10px 0;
|
||
}
|
||
|
||
.order-summary {
|
||
margin-top: auto;
|
||
text-align: left;
|
||
}
|
||
|
||
.order-summary p {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
font-size: 14px;
|
||
margin: 5px 0;
|
||
}
|
||
|
||
.total {
|
||
font-size: 16px;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.pay-button {
|
||
width: 100%;
|
||
background: #222;
|
||
color: white;
|
||
padding: 12px;
|
||
border: none;
|
||
border-radius: 8px;
|
||
font-size: 16px;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.pay-button:hover {
|
||
background: #000;
|
||
}
|
||
|
||
.main {
|
||
margin-right: 270px;
|
||
}
|
||
</style>
|
||
|
||
|
||
</body>
|
||
|
||
</html> |