Adityadn's picture
Upload 7 files
b28567d verified
raw
history blame
17.2 kB
function checkUID(m = "") {
const userData = JSON.parse(localStorage.getItem("userData")) || {};
const urlNow = window.location.href;
const isNotValidUID = userData.length > 0 && !userData.uid;
const message =
m === "addToCart"
? "Silakan masuk terlebih dahulu untuk menambahkan produk ke keranjang."
: isNotValidUID
? "Sesi Anda telah habis. Silakan masuk kembali untuk melanjutkan."
: m === "jelajah"
? "Anda telah menjelajah selama 5 detik. Silakan masuk terlebih dahulu untuk mendapatkan pengalaman yang lebih baik."
: null;
if (
(Object.keys(userData).length === 0 || isNotValidUID) &&
!urlNow.includes("profile")
) {
localStorage.clear();
window.location.href =
`profile.html?redirect=${urlNow}` +
(message ? `&message=${message}` : "");
}
}
setTimeout(() => {
checkUID("jelajah");
}, 5000);
function formatRupiah(number) {
return "Rp " + number.toLocaleString("id-ID");
}
async function loadProducts() {
const products = await fetchProductsData();
const productList = document.getElementById("product-list");
if (!productList) return;
productList.innerHTML = "";
products.forEach((product) => {
const col = document.createElement("div");
col.className = "col-lg-3 col-md-4 col-sm-6";
const card = document.createElement("div");
card.className = "card h-100";
let thumbnail = "assets/";
if (product.files && product.files.length > 0) {
thumbnail += product.files[0];
}
let thumbHTML = "";
if (thumbnail.match(/\.(jpg|jpeg|png|gif)$/i)) {
thumbHTML = `<img src="${thumbnail}" class="card-img-top" alt="${product.name}">`;
} else {
thumbHTML = `<img src="img/placeholder.jpg" class="card-img-top" alt="${product.name}">`;
}
const cardBody = document.createElement("div");
cardBody.className = "card-body d-flex flex-column";
const title = document.createElement("h5");
title.className = "card-title";
title.innerText = product.name;
const desc = document.createElement("p");
desc.className = "card-text";
desc.innerText = product.description;
const price = document.createElement("p");
price.className = "card-text fw-bold";
price.innerText = formatRupiah(product.price);
const detailLink = document.createElement("a");
detailLink.href = "product.html?id=" + product.id;
detailLink.className = "btn btn-primary btn-lg mt-auto";
detailLink.innerText = "Lihat Detail";
const cartBtn = document.createElement("button");
cartBtn.className = "btn btn-success btn-lg mt-2";
cartBtn.innerText = "Tambah Keranjang";
cartBtn.onclick = async function () {
await promptQuantityAndAdd(product.id);
};
card.innerHTML = thumbHTML;
cardBody.appendChild(title);
cardBody.appendChild(desc);
cardBody.appendChild(price);
cardBody.appendChild(detailLink);
cardBody.appendChild(cartBtn);
card.appendChild(cardBody);
col.appendChild(card);
productList.appendChild(col);
});
}
async function loadProductDetail() {
const params = new URLSearchParams(window.location.search);
const productId = parseInt(params.get("id"));
const container = document.getElementById("product-detail");
if (!container) return;
if (!productId) {
container.innerText = "Produk tidak ditemukan.";
return;
}
const products = await fetchProductsData();
const product = products.find((p) => p.id === productId);
if (!product) {
container.innerText = "Produk tidak ditemukan.";
return;
}
let carouselHTML = "";
if (product.files && product.files.length > 0) {
carouselHTML += `<div id="carouselProduct" class="carousel slide" data-bs-ride="carousel">`;
carouselHTML += `<div class="carousel-indicators">`;
product.files.forEach((file, index) => {
carouselHTML += `<button type="button" data-bs-target="#carouselProduct" data-bs-slide-to="${index}" ${
index === 0 ? 'class="active" aria-current="true"' : ""
} aria-label="Slide ${index + 1}"></button>`;
});
carouselHTML += `</div>`;
carouselHTML += `<div class="carousel-inner">`;
product.files.forEach((file, index) => {
file = "assets/" + file;
carouselHTML += `<div class="carousel-item ${
index === 0 ? "active" : ""
}">`;
if (file.match(/\.(jpg|jpeg|png|gif)$/i)) {
carouselHTML += `<img src="${file}" class="d-block w-100" alt="${product.name}">`;
} else if (file.match(/\.(mp4|webm)$/i)) {
carouselHTML += `<video class="d-block w-100" controls>
<source src="${file}" type="video/mp4">
Browser Anda tidak mendukung video.
</video>`;
}
carouselHTML += `</div>`;
});
carouselHTML += `</div>`;
carouselHTML += `<button class="carousel-control-prev" type="button" data-bs-target="#carouselProduct" data-bs-slide="prev">
<span class="carousel-control-prev-icon bg-primary rounded-circle p-4" aria-hidden="true"></span>
<span class="visually-hidden">Previous</span>
</button>
<button class="carousel-control-next" type="button" data-bs-target="#carouselProduct" data-bs-slide="next">
<span class="carousel-control-next-icon bg-primary rounded-circle p-4" aria-hidden="true"></span>
<span class="visually-hidden">Next</span>
</button>`;
carouselHTML += `</div>`;
}
container.innerHTML = `
<div class="row">
<div class="col-md-6">
${carouselHTML}
</div>
<div class="col-md-6">
<h2>${product.name}</h2>
<p>${product.description}</p>
<h4 class="fw-bold">${formatRupiah(product.price)}</h4>
<div class="mb-2">
<label for="quantity" class="form-label">Jumlah:</label>
<input type="number" id="quantity" class="form-control form-control-lg" value="1" min="1" style="max-width:150px;">
</div>
<button class="btn btn-success btn-lg" onclick="addToCartFromProduct(${
product.id
})">
Tambahkan ke Keranjang
</button>
</div>
</div>
`;
AOS.refresh();
}
function formatTransactionDate(key) {
const parts = key.split("_");
if (parts.length !== 7) return key;
const [year, month, day, hour, minute, second, ms] = parts;
const dateObj = new Date(
year,
parseInt(month) - 1,
day,
hour,
minute,
second,
ms
);
const formattedDate = dateObj.toLocaleDateString("id-ID", {
day: "2-digit",
month: "long",
year: "numeric",
});
const formattedTime = dateObj.toLocaleTimeString("id-ID", {
hour: "2-digit",
minute: "2-digit",
hour12: false,
});
return [formattedDate, formattedTime];
}
async function loadTransactions() {
const userData = await getUserData() || {transactions: {}};
const transactions = userData.transactions || {};
if (Object.keys(transactions).length === 0) {
document.getElementById("transaction-list").innerHTML =
"<p>Anda belum melakukan transaksi apapun. Silahkan beli produk terlebih dahulu.</p>";
alert("Anda belum melakukan transaksi apapun. Silahkan beli produk terlebih dahulu.", false)
return;
}
const transactionList = document.getElementById("transaction-list");
if (!transactionList) return;
transactionList.innerHTML = "";
Object.entries(transactions)
.sort((a, b) => {
const parseDateFromKey = (key) => {
const [year, month, day, hour, minute, second, ms] =
key.split("_");
return new Date(year, month - 1, day, hour, minute, second, ms);
};
return parseDateFromKey(b[0]) - parseDateFromKey(a[0]);
})
.forEach(([transactionKey, transaction]) => {
let total = 0;
transaction.products.forEach((product) => {
total += product.price * product.total;
});
let paymentIcon = "";
switch (transaction.payment_method) {
case "bank":
paymentIcon = "bi-building";
break;
case "qr":
paymentIcon = "bi-qr-code";
break;
case "card":
paymentIcon = "bi-credit-card";
break;
default:
paymentIcon = "bi-currency-dollar";
}
const col = document.createElement("div");
col.className =
"transactions-body col-lg-4 col-md-6 col-sm-12 mt-4";
const card = document.createElement("div");
card.className = "card h-100";
const cardBody = document.createElement("div");
cardBody.className = "card-body d-flex flex-column";
cardBody.style.position = "relative";
const td = formatTransactionDate(transactionKey);
cardBody.innerHTML = `
<div class="payment-icon-bg">
<i class="bi ${paymentIcon}" style="font-size: 2.5rem;"></i>
<span class="m-2">Metode: ${
transaction.payment_method ? transaction.payment_method : "N/A"
}</span>
</div>
<div class="content">
<div class="d-flex justify-content-between align-items-center">
<div class="transaction-total fw-bold">
Total: ${formatRupiah(total)}
</div>
</div>
<div class="d-flex justify-content-between align-items-center mt-auto">
<div class="transaction-date">
Tanggal: ${td[0]} <br> Waktu: ${td[1]}
</div>
</div>
</div>
`;
card.appendChild(cardBody);
col.appendChild(card);
transactionList.appendChild(col);
col.addEventListener(
"click",
() =>
(window.location.href = `transaction.html?date=${transactionKey}`)
);
});
}
let transactionKey;
async function updateActionButtonsPosition() {
const wrapper = document.querySelector(".receipt-wrapper");
const actionButtons = document.querySelector(".action-buttons");
if (!wrapper || !actionButtons) {
console.error("Element tidak ditemukan!");
return;
}
const receiptHeight = wrapper.getBoundingClientRect().height + 128;
actionButtons.setAttribute("style", `top: ${receiptHeight}px !important`);
}
async function loadTransactionDetail() {
const params = new URLSearchParams(window.location.search);
const transactionKey = params.get("date");
const detailsContainer = document.getElementById("transaction-details");
const mainElement = document.querySelector("main");
if (!transactionKey) {
detailsContainer.innerHTML = "<p>Transaksi tidak ditemukan.</p>";
return;
}
const userData = await getUserData();
if (!userData.transactions || !userData.transactions[transactionKey]) {
mainElement.innerHTML = "<p>Transaksi tidak ditemukan.</p>";
return;
}
const transaction = userData.transactions[transactionKey];
const td = formatTransactionDate(transactionKey);
let total = 0;
transaction.products.forEach((prod) => {
total += prod.price * prod.total;
});
let html = `
<div class="receipt-header">
<h2>TonS E-Commerce</h2>
<hr>
<p>Sidoarjo</p>
<p>Telp: 0896-6804-1554</p>
<p>Tanggal: ${td[0]} ${td[1]}</p>
</div>
<table class="receipt-table">
<thead>
<tr>
<th>No</th>
<th>Produk</th>
<th>Harga</th>
<th>Qty</th>
<th>Subtotal</th>
</tr>
</thead>
<tbody>
`;
transaction.products.forEach((prod, index) => {
const qty = prod.total;
const subtotal = prod.price * qty;
html += `
<tr>
<td>${index + 1}</td>
<td>${prod.name}</td>
<td>${formatRupiah(prod.price)}</td>
<td>${qty}</td>
<td>${formatRupiah(subtotal)}</td>
</tr>
`;
});
html += `
<tr class="total-row">
<td colspan="4" class="text-end"><strong>Total</strong></td>
<td><strong>${formatRupiah(total)}</strong></td>
</tr>
</tbody>
</table>
<div class="receipt-footer">
<p>Terima kasih telah berbelanja di TonS</p>
<p>Harap simpan struk ini sebagai bukti pembelian</p>
</div>
`;
detailsContainer.innerHTML = html;
const wrapper = document.createElement("div");
wrapper.className = "receipt-wrapper";
wrapper.innerHTML = detailsContainer.innerHTML;
detailsContainer.innerHTML = "";
detailsContainer.appendChild(wrapper);
await updateActionButtonsPosition();
window.addEventListener("resize", async () => {
requestAnimationFrame(updateActionButtonsPosition);
});
}
document.addEventListener("DOMContentLoaded", async function () {
AOS.init();
if (document.getElementById("product-list")) {
loadProducts();
}
if (document.getElementById("product-detail")) {
loadProductDetail();
}
if (document.getElementById("transaction-details")) {
await loadTransactionDetail();
await updateActionButtonsPosition();
window.addEventListener("resize", async () => {
requestAnimationFrame(updateActionButtonsPosition);
});
document
.getElementById("download-pdf")
.addEventListener("click", async () => {
const mainElement = document.getElementById(
"transaction-details"
);
const receiptWrapperElement =
document.querySelector(".receipt-wrapper");
const widthElement =
receiptWrapperElement.offsetWidth -
receiptWrapperElement.offsetLeft;
const heightElement =
receiptWrapperElement.offsetHeight -
receiptWrapperElement.offsetTop;
const params = new URLSearchParams(window.location.search);
const transactionKey = params.get("date");
try {
await html2pdf()
.from(mainElement)
.set({
margin: 10,
filename: `receipt_${transactionKey}.pdf`,
image: { type: "png", quality: 3 },
html2canvas: { scale: 3, useCORS: true },
jsPDF: {
unit: "px",
format: [widthElement, heightElement],
orientation: "portrait",
},
})
.toPdf()
.save();
} catch (error) {
console.error("Error generating PDF:", error);
}
});
document
.getElementById("print-receipt")
.addEventListener("click", async () => {
const mainElement = document.getElementById(
"transaction-details"
);
const lastMainElement = mainElement.innerHTML;
mainElement.innerHTML += `
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons/font/bootstrap-icons.css">
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/aos.css" />
<script src="https://printjs-4de6.kxcdn.com/print.min.css"></script>
<link rel="stylesheet" href="stylesheet/styles.css">
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" defer></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.9.2/html2pdf.bundle.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/html-to-image/1.11.13/html-to-image.js"></script>
<script src="https://unpkg.com/[email protected]/dist/aos.js" defer></script>
<script src="https://printjs-4de6.kxcdn.com/print.min.js"></script>
`;
await printJS("transaction-details", "html");
mainElement.innerHTML = lastMainElement;
});
}
if (document.getElementById("transaction-list")) {
loadTransactions();
}
let backButton = document.getElementById("backButton");
if (backButton) {
backButton.addEventListener("click", (e) => {
e.preventDefault();
window.history.back();
});
}
});