Tambah Produk Baru

Tambah Staff Baru

Draft Pesanan (Hold)

function posApp() { return { // --- 1. STATE DASAR & AUTH --- isLoggedIn: false, activeTab: 'pos', user: {}, loginForm: { username: '', password: '' }, // --- 2. DATA MASTER (Untuk Tabel & Catalog) --- products: [], categories: ['Semua', 'Makanan', 'Minuman', 'Snack'], selectedCategory: 'Semua', staffList: [], cafes: [], transactions: [], stats: { daily_total: 0, total_orders: 0, items_sold: 0, active_staff: 0 }, // --- 3. STATE POS & CHECKOUT --- cart: [], search: '', orderMeta: { table_number: '', customer_name: '' }, showCheckoutModal: false, paymentMethod: 'cash', amountPaid: 0, // --- 4. MODALS & DRAFTS --- showAddProductModal: false, showAddStaffModal: false, showDraftModal: false, drafts: [], // --- 5. FORM INPUT BARU --- newProduct: { name: '', price: '', category: 'Makanan', image: '' }, newStaff: { fullname: '', username: '', password: '', role: 'staff' }, newCafe: { cafeName: '', ownerName: '', username: '', password: '', address: '' }, async init() { if (this.isLoggedIn) { await this.loadProducts(); await this.loadStaff(); await this.loadTransactions(); this.loadDrafts(); if (this.user.role === 'superadmin') await this.loadAllCafes(); } }, // --- 6. FUNGSI PERHITUNGAN (GETTERS) --- get subtotal() { return this.cart.reduce((s, i) => s + (i.price * i.qty), 0); }, get taxAmount() { return this.subtotal * 0.11; }, get cartTotal() { return this.subtotal + this.taxAmount; }, get changeAmount() { return Math.max(0, this.amountPaid - this.cartTotal); }, get filteredProducts() { return this.products.filter(p => { const matchSearch = p.name.toLowerCase().includes(this.search.toLowerCase()); const matchCat = this.selectedCategory === 'Semua' || p.category === this.selectedCategory; return matchSearch && matchCat; }); }, // --- 7. FUNGSI POS & DRAFT --- addToCart(product) { let item = this.cart.find(i => i.id === product.id); if (item) item.qty++; else this.cart.push({ ...product, qty: 1 }); }, removeFromCart(index) { this.cart.splice(index, 1); }, saveDraft() { if(this.cart.length === 0) return; this.drafts.push({ id: Date.now(), time: new Date().toLocaleTimeString(), cart: [...this.cart], meta: {...this.orderMeta} }); this.cart = []; this.orderMeta = { table_number: '', customer_name: '' }; localStorage.setItem('drafts_' + this.user.cafe_id, JSON.stringify(this.drafts)); this.showNotify("Draft berhasil disimpan"); }, loadDrafts() { const saved = localStorage.getItem('drafts_' + this.user.cafe_id); if (saved) this.drafts = JSON.parse(saved); }, recallDraft(index) { const d = this.drafts[index]; this.cart = d.cart; this.orderMeta = d.meta; this.drafts.splice(index, 1); this.showDraftModal = false; localStorage.setItem('drafts_' + this.user.cafe_id, JSON.stringify(this.drafts)); }, // --- 8. FUNGSI LOADING DATA (API) --- async loadProducts() { const res = await fetch('api.php?action=getProducts&cafe_id=' + this.user.cafe_id); const r = await res.json(); this.products = r.data || []; }, async loadStaff() { const res = await fetch('api.php?action=getStaff&cafe_id=' + this.user.cafe_id); const r = await res.json(); this.staffList = r.data || []; }, async loadTransactions() { const res = await fetch('api.php?action=getTransactions&cafe_id=' + this.user.cafe_id); const r = await res.json(); if (r.status === 'success') { this.transactions = r.data; this.stats = r.stats; } }, async loadAllCafes() { const res = await fetch('api.php?action=getCafes'); const r = await res.json(); this.cafes = r.data || []; }, // --- 9. FUNGSI ACTION (DELETE/SAVE) --- async deleteStaff(id) { if (!confirm('Hapus staff ini?')) return; const res = await fetch(`api.php?action=deleteStaff&id=${id}&cafe_id=${this.user.cafe_id}`); const r = await res.json(); if (r.status === 'success') this.loadStaff(); }, async processCheckout() { if (this.cart.length === 0) return; // Logika fetch ke api.php?action=saveTransaction... }, // --- 10. UTILS --- formatIDR(n) { return new Intl.NumberFormat('id-ID', { style: 'currency', currency: 'IDR', minimumFractionDigits: 0 }).format(n || 0); }, showNotify(msg) { alert(msg); // Bisa diganti dengan UI toast nanti } } }