// Configuration
const API_BASE_URL = 'https://bdwewiveuzpakrzphljo.supabase.co/functions/v1';
let API_KEY = '';
let cart = [];
let currentPage = 1;
let products = [];
let orders = [];
// Page Navigation
function showPage(pageId) {
document.querySelectorAll('.page').forEach(page => page.classList.remove('active'));
document.getElementById(pageId).classList.add('active');
if (pageId === 'customer-page') {
loadProducts();
loadCategories();
} else if (pageId === 'admin-page') {
loadAdminProducts();
loadAdminOrders();
}
}
// Admin Login
function adminLogin(event) {
event.preventDefault();
const apiKey = document.getElementById('api-key-input').value;
if (apiKey) {
API_KEY = apiKey;
showPage('admin-page');
} else {
alert('Please enter a valid API key');
}
}
function logout() {
API_KEY = '';
showPage('landing-page');
}
// API Helper
async function apiRequest(endpoint, method = 'GET', body = null) {
const options = {
method,
headers: {
'Content-Type': 'application/json'
}
};
if (API_KEY) {
options.headers['x-api-key'] = API_KEY;
}
if (body) {
options.body = JSON.stringify(body);
}
try {
const response = await fetch(`${API_BASE_URL}${endpoint}`, options);
if (!response.ok) {
throw new Error(`API Error: ${response.statusText}`);
}
return await response.json();
} catch (error) {
console.error('API Request failed:', error);
alert('Request failed: ' + error.message);
throw error;
}
}
// Customer Functions - Products
async function loadProducts(page = 1) {
try {
const search = document.getElementById('product-search').value;
const category = document.getElementById('category-filter').value;
let endpoint = `/products?page=${page}&limit=12`;
if (search) endpoint += `&search=${encodeURIComponent(search)}`;
if (category) endpoint += `&category=${encodeURIComponent(category)}`;
const data = await apiRequest(endpoint);
products = data.data || [];
currentPage = page;
renderProducts(products);
renderPagination(data.total, data.page, data.limit);
} catch (error) {
document.getElementById('products-grid').innerHTML =
'
Failed to load products
';
}
}
function renderProducts(products) {
const grid = document.getElementById('products-grid');
if (!products || products.length === 0) {
grid.innerHTML = '';
return;
}
grid.innerHTML = products.map(product => `
${product.variants?.[0]?.image_url ?
`

` :
'👕'}
${product.name}
${product.category || 'Uncategorized'}
${product.description || ''}
$${parseFloat(product.base_price).toFixed(2)}
${product.variants?.length > 0 ? `
${product.variants.length} variants available
` : ''}
`).join('');
}
function renderPagination(total, page, limit) {
const pagination = document.getElementById('pagination');
const totalPages = Math.ceil(total / limit);
if (totalPages <= 1) {
pagination.innerHTML = '';
return;
}
let html = ``;
for (let i = 1; i <= totalPages; i++) {
if (i === 1 || i === totalPages || (i >= page - 1 && i <= page + 1)) {
html += ``;
} else if (i === page - 2 || i === page + 2) {
html += '...';
}
}
html += ``;
pagination.innerHTML = html;
}
async function loadCategories() {
// Since the API doesn't have a categories endpoint, we'll populate from loaded products
const categories = [...new Set(products.map(p => p.category).filter(Boolean))];
const select = document.getElementById('category-filter');
select.innerHTML = '' +
categories.map(cat => ``).join('');
}
function searchProducts() {
clearTimeout(window.searchTimeout);
window.searchTimeout = setTimeout(() => loadProducts(1), 500);
}
function filterProducts() {
loadProducts(1);
}
async function showProductDetails(productId) {
try {
const product = await apiRequest(`/products/${productId}`);
const modal = document.getElementById('product-modal');
const details = document.getElementById('product-details');
details.innerHTML = `
${product.name}
${product.category || 'Uncategorized'}
${product.description || 'No description'}
$${parseFloat(product.base_price).toFixed(2)}
${product.variants?.length > 0 ? `
Select Variant:
${product.variants.map(variant => `
`).join('')}
` : 'No variants available
'}
`;
modal.classList.add('active');
} catch (error) {
alert('Failed to load product details');
}
}
// Cart Functions
function addToCart(productId, variantId) {
const product = products.find(p => p.id === productId);
if (!product) return;
const variant = product.variants.find(v => v.id === variantId);
if (!variant || variant.stock_quantity === 0) return;
const existingItem = cart.find(item => item.variantId === variantId);
if (existingItem) {
if (existingItem.quantity < variant.stock_quantity) {
existingItem.quantity++;
} else {
alert('Cannot add more than available stock');
return;
}
} else {
cart.push({
productId: product.id,
variantId: variant.id,
productName: product.name,
variantLabel: `${variant.size || ''} ${variant.color || ''}`.trim(),
price: variant.price_override || product.base_price,
quantity: 1,
maxStock: variant.stock_quantity
});
}
updateCartCount();
closeModal('product-modal');
alert('Added to cart!');
}
function updateCartCount() {
const count = cart.reduce((sum, item) => sum + item.quantity, 0);
document.getElementById('cart-count').textContent = count;
}
function showCart() {
const modal = document.getElementById('cart-modal');
const cartItems = document.getElementById('cart-items');
if (cart.length === 0) {
cartItems.innerHTML = '';
} else {
cartItems.innerHTML = '' + cart.map((item, index) => `
${item.productName}
${item.variantLabel}
${item.quantity}
$${(item.price * item.quantity).toFixed(2)}
`).join('') + '
';
}
const subtotal = cart.reduce((sum, item) => sum + (item.price * item.quantity), 0);
document.getElementById('cart-subtotal').textContent = `$${subtotal.toFixed(2)}`;
modal.classList.add('active');
}
function updateCartQuantity(index, delta) {
const item = cart[index];
const newQuantity = item.quantity + delta;
if (newQuantity <= 0) {
removeFromCart(index);
} else if (newQuantity <= item.maxStock) {
item.quantity = newQuantity;
updateCartCount();
showCart();
} else {
alert('Cannot add more than available stock');
}
}
function removeFromCart(index) {
cart.splice(index, 1);
updateCartCount();
showCart();
}
// Checkout
function showCheckout() {
if (cart.length === 0) {
alert('Your cart is empty');
return;
}
closeModal('cart-modal');
const modal = document.getElementById('checkout-modal');
const subtotal = cart.reduce((sum, item) => sum + (item.price * item.quantity), 0);
const shippingFee = 10;
const total = subtotal + shippingFee;
document.getElementById('checkout-subtotal').textContent = `$${subtotal.toFixed(2)}`;
document.getElementById('checkout-total').textContent = `$${total.toFixed(2)}`;
modal.classList.add('active');
}
async function placeOrder(event) {
event.preventDefault();
const orderData = {
customer_name: document.getElementById('customer-name').value,
customer_email: document.getElementById('customer-email').value,
customer_phone: document.getElementById('customer-phone').value,
shipping_address: {
address: document.getElementById('shipping-address').value
},
shipping_fee: 10,
notes: document.getElementById('order-notes').value,
items: cart.map(item => ({
variant_id: item.variantId,
quantity: item.quantity
}))
};
try {
const result = await apiRequest('/orders', 'POST', orderData);
alert(`Order placed successfully! Your tracking ID is: ${result.tracking_id || 'N/A'}`);
cart = [];
updateCartCount();
closeModal('checkout-modal');
// Reset form
document.getElementById('customer-name').value = '';
document.getElementById('customer-email').value = '';
document.getElementById('customer-phone').value = '';
document.getElementById('shipping-address').value = '';
document.getElementById('order-notes').value = '';
} catch (error) {
alert('Failed to place order: ' + error.message);
}
}
// Order Tracking
async function trackOrder() {
const trackingId = document.getElementById('tracking-input').value.trim();
if (!trackingId) {
alert('Please enter a tracking ID');
return;
}
try {
const data = await apiRequest(`/orders/track/${trackingId}`);
const modal = document.getElementById('tracking-modal');
const result = document.getElementById('tracking-result');
result.innerHTML = `
Tracking ID: ${data.tracking_id}
Status: ${data.status}
Customer: ${data.customer_name}
Order Date: ${new Date(data.created_at).toLocaleDateString()}
Items:
${data.items_summary?.map(item => `- ${item}
`).join('') || '- No items
'}
`;
modal.classList.add('active');
} catch (error) {
alert('Order not found or tracking ID is invalid');
}
}
// Admin Functions - Products
async function loadAdminProducts() {
try {
const data = await apiRequest('/products?limit=100');
products = data.data || [];
renderAdminProducts(products);
} catch (error) {
document.getElementById('admin-products-list').innerHTML =
'Failed to load products
';
}
}
function renderAdminProducts(products) {
const list = document.getElementById('admin-products-list');
if (!products || products.length === 0) {
list.innerHTML = '';
return;
}
list.innerHTML = products.map(product => `
${product.name}
${product.category || 'Uncategorized'} • $${parseFloat(product.base_price).toFixed(2)} •
${product.variants?.length || 0} variants •
${product.is_active ? '✅ Active' : '❌ Inactive'}
`).join('');
}
function searchAdminProducts() {
const search = document.getElementById('admin-product-search').value.toLowerCase();
const filtered = products.filter(p =>
p.name.toLowerCase().includes(search) ||
(p.category || '').toLowerCase().includes(search)
);
renderAdminProducts(filtered);
}
function showProductModal(productId = null) {
const modal = document.getElementById('admin-product-modal');
const title = document.getElementById('product-modal-title');
if (productId) {
title.textContent = 'Edit Product';
const product = products.find(p => p.id === productId);
if (product) {
document.getElementById('edit-product-id').value = product.id;
document.getElementById('product-name').value = product.name;
document.getElementById('product-description').value = product.description || '';
document.getElementById('product-price').value = product.base_price;
document.getElementById('product-category').value = product.category || '';
document.getElementById('product-active').checked = product.is_active;
}
} else {
title.textContent = 'Add Product';
document.getElementById('edit-product-id').value = '';
document.getElementById('product-name').value = '';
document.getElementById('product-description').value = '';
document.getElementById('product-price').value = '';
document.getElementById('product-category').value = '';
document.getElementById('product-active').checked = true;
}
modal.classList.add('active');
}
function editProduct(productId) {
showProductModal(productId);
}
async function saveProduct(event) {
event.preventDefault();
const productId = document.getElementById('edit-product-id').value;
const productData = {
name: document.getElementById('product-name').value,
description: document.getElementById('product-description').value,
base_price: parseFloat(document.getElementById('product-price').value),
category: document.getElementById('product-category').value,
is_active: document.getElementById('product-active').checked
};
try {
if (productId) {
await apiRequest(`/products/${productId}`, 'PUT', productData);
alert('Product updated successfully!');
} else {
await apiRequest('/products', 'POST', productData);
alert('Product created successfully!');
}
closeModal('admin-product-modal');
loadAdminProducts();
} catch (error) {
alert('Failed to save product: ' + error.message);
}
}
async function deleteProduct(productId) {
if (!confirm('Are you sure you want to delete this product?')) return;
try {
await apiRequest(`/products/${productId}`, 'DELETE');
alert('Product deleted successfully!');
loadAdminProducts();
} catch (error) {
alert('Failed to delete product: ' + error.message);
}
}
function manageVariants(productId) {
alert('Variant management feature: Coming soon!\n\nUse the API directly to manage variants for now:\nPOST /variants/' + productId);
}
// Admin Functions - Orders
async function loadAdminOrders() {
try {
const data = await apiRequest('/orders?limit=100');
orders = data.data || [];
renderAdminOrders(orders);
} catch (error) {
document.getElementById('admin-orders-list').innerHTML =
'Failed to load orders
';
}
}
function renderAdminOrders(orders) {
const list = document.getElementById('admin-orders-list');
if (!orders || orders.length === 0) {
list.innerHTML = '';
return;
}
list.innerHTML = orders.map(order => `
Order #${order.tracking_id || order.id.substring(0, 8)}
${order.customer_name} • ${order.customer_email || order.customer_phone} •
${order.items?.length || 0} items •
$${parseFloat(order.total).toFixed(2)} •
${new Date(order.created_at).toLocaleDateString()}
${order.delivery_status}
`).join('');
}
function searchAdminOrders() {
const search = document.getElementById('admin-order-search').value.toLowerCase();
const filtered = orders.filter(o =>
o.customer_name.toLowerCase().includes(search) ||
(o.customer_email || '').toLowerCase().includes(search) ||
(o.tracking_id || '').toLowerCase().includes(search)
);
renderAdminOrders(filtered);
}
function filterOrders() {
const status = document.getElementById('order-status-filter').value;
const filtered = status ? orders.filter(o => o.delivery_status === status) : orders;
renderAdminOrders(filtered);
}
async function updateOrderStatus(orderId, newStatus) {
if (!newStatus) return;
try {
await apiRequest(`/orders/${orderId}`, 'PATCH', { delivery_status: newStatus });
alert('Order status updated successfully!');
loadAdminOrders();
} catch (error) {
alert('Failed to update order status: ' + error.message);
}
}
function viewOrderDetails(orderId) {
const order = orders.find(o => o.id === orderId);
if (!order) return;
const items = order.items?.map(item =>
`${item.product_name} (${item.variant_label}) x${item.quantity} - $${(item.unit_price * item.quantity).toFixed(2)}`
).join('\n') || 'No items';
alert(`Order Details:\n\nTracking ID: ${order.tracking_id}\nCustomer: ${order.customer_name}\nEmail: ${order.customer_email || 'N/A'}\nPhone: ${order.customer_phone}\nStatus: ${order.delivery_status}\n\nItems:\n${items}\n\nSubtotal: $${parseFloat(order.subtotal).toFixed(2)}\nShipping: $${parseFloat(order.shipping_fee).toFixed(2)}\nTotal: $${parseFloat(order.total).toFixed(2)}`);
}
// Admin Tab Navigation
function showAdminTab(tabName) {
document.querySelectorAll('.tab-btn').forEach(btn => btn.classList.remove('active'));
document.querySelectorAll('.admin-tab').forEach(tab => tab.classList.remove('active'));
event.target.classList.add('active');
document.getElementById(`admin-${tabName}`).classList.add('active');
if (tabName === 'products') {
loadAdminProducts();
} else if (tabName === 'orders') {
loadAdminOrders();
}
}
// Modal Functions
function closeModal(modalId) {
document.getElementById(modalId).classList.remove('active');
}
// Close modals when clicking outside
window.onclick = function(event) {
if (event.target.classList.contains('modal')) {
event.target.classList.remove('active');
}
}
// Initialize
document.addEventListener('DOMContentLoaded', () => {
updateCartCount();
});