diff --git a/main.py b/main.py index 04a79de..7675db0 100644 --- a/main.py +++ b/main.py @@ -2185,17 +2185,25 @@ class App: ttk.Button(search_frame, text="Cari", command=self.reload_order_menu_cards).pack(side='left', padx=3) ttk.Button(search_frame, text="Reset", command=self.reset_order_search).pack(side='left', padx=3) - # Scrollable frame untuk cards (DENGAN BACKGROUND PUTIH) - canvas = tk.Canvas(left, bg='#f5f5f5', height=450, highlightthickness=0) + # Scrollable frame untuk cards (FULL WIDTH FIX) + canvas = tk.Canvas(left, bg='#f5f5f5', highlightthickness=0) scrollbar = ttk.Scrollbar(left, orient="vertical", command=canvas.yview) + self.menu_cards_frame = ttk.Frame(canvas) - self.menu_cards_frame.bind( - "", - lambda e: canvas.configure(scrollregion=canvas.bbox("all")) - ) + # 1. Simpan ID Window saat create_window + frame_window_id = canvas.create_window((0, 0), window=self.menu_cards_frame, anchor="nw") + + # 2. Fungsi agar scroll region update saat konten bertambah + def configure_scroll_region(event): + canvas.configure(scrollregion=canvas.bbox("all")) + self.menu_cards_frame.bind("", configure_scroll_region) + + # 3. FUNGSI KUNCI: Paksa frame selebar canvas (Full Width) + def configure_frame_width(event): + canvas.itemconfig(frame_window_id, width=event.width) + canvas.bind("", configure_frame_width) - canvas.create_window((0, 0), window=self.menu_cards_frame, anchor="nw") canvas.configure(yscrollcommand=scrollbar.set) canvas.pack(side="left", fill="both", expand=True) @@ -2286,23 +2294,23 @@ class App: def reload_order_menu_cards(self): - """Load menu dalam bentuk cards dengan gambar + tombol +/-""" + """Load menu dalam bentuk cards 4 kolom FULL WIDTH""" # Clear existing cards for widget in self.menu_cards_frame.winfo_children(): widget.destroy() - # Get menu data search = self.order_search_var.get().strip() or None results = menu_list(search_text=search, available_only=True) - # Buat dict untuk qty di cart - cart_dict = {} - for cart_item in self.cart_items: - cart_dict[cart_item['menu_id']] = cart_item['qty'] + cart_dict = {item['menu_id']: item['qty'] for item in self.cart_items} - # Configure grid columns (2 kolom sama lebar) - self.menu_cards_frame.columnconfigure(0, weight=1) - self.menu_cards_frame.columnconfigure(1, weight=1) + # === KONFIGURASI 4 KOLOM AGAR RATA (UNIFORM) === + total_columns = 4 + + # 'uniform' membuat lebar setiap kolom identik/sama persis + for i in range(total_columns): + self.menu_cards_frame.columnconfigure(i, weight=1, uniform='menu_col') + # =============================================== row = 0 col = 0 @@ -2310,153 +2318,73 @@ class App: for menu_data in results: mid, nama, kategori, harga, stok, foto, tersedia, item_disc = menu_data + # Buat Card (HAPUS width/height fix agar responsif) card = tk.Frame( self.menu_cards_frame, relief='solid', borderwidth=1, bg='white', - padx=10, - pady=10, - width=200, - height=320 + padx=5, pady=5 ) - card.grid_propagate(False) - card.grid(row=row, column=col, padx=8, pady=8, sticky='nsew') + + # sticky='nsew' MEMAKSA card memenuhi kotak grid-nya + card.grid(row=row, column=col, padx=5, pady=5, sticky='nsew') - # Gambar + # --- Bagian Gambar --- if foto and os.path.exists(foto): try: img = Image.open(foto) - img = img.resize((150, 100), Image.Resampling.LANCZOS) + # Resize agak kecil agar muat 4 kolom + img = img.resize((120, 85), Image.Resampling.LANCZOS) photo = ImageTk.PhotoImage(img) - - img_label = tk.Label(card, image=photo, bg='white') - img_label.image = photo - img_label.pack(pady=(5, 5)) + lbl = tk.Label(card, image=photo, bg='white') + lbl.image = photo + lbl.pack(pady=5) except: - tk.Label( - card, - text="[No Image]", - bg='#e0e0e0', - width=20, - height=6 - ).pack() + tk.Label(card, text="[No Image]", bg='#eee', height=4).pack(fill='x') else: - tk.Label( - card, - text="[No Image]", - bg='#e0e0e0', - width=18, - height=5 - ).pack() + tk.Label(card, text="[No Image]", bg='#eee', height=4).pack(fill='x') - # Nama menu - tk.Label( - card, - text=nama, - font=("Arial", 10, "bold"), - bg='white', - wraplength=140, - justify='center', - height=2 - ).pack(pady=(3, 2)) - - # Kategori - tk.Label( - card, - text=kategori, - font=("Arial", 8), - fg='gray', - bg='white' - ).pack(pady=1) - - # Harga - harga_text = f"Rp {harga:,.0f}" + # --- Bagian Info --- + tk.Label(card, text=nama, font=("Arial", 10, "bold"), bg='white', wraplength=110).pack() + tk.Label(card, text=kategori, font=("Arial", 8), fg='gray', bg='white').pack() + + txt_harga = f"Rp {harga:,.0f}" if item_disc > 0: - harga_text += f"\n(-{item_disc}%)" - tk.Label( - card, - text=harga_text, - font=("Arial", 9, "bold"), - fg='#4CAF50', - bg='white', - justify='center' - ).pack(pady=2) + txt_harga += f"\n(-{item_disc}%)" + fg = '#4CAF50' else: - tk.Label( - card, - text=harga_text, - font=("Arial", 9, "bold"), - fg='green', - bg='white' - ).pack(pady=2) + fg = 'green' + tk.Label(card, text=txt_harga, font=("Arial", 9, "bold"), fg=fg, bg='white').pack(pady=2) + + color = 'blue' if stok > 0 else 'red' + tk.Label(card, text=f"Stok: {stok}", font=("Arial", 8), fg=color, bg='white').pack() - # Stok - stok_color = 'blue' if stok > 0 else 'red' - tk.Label( - card, - text=f"Stok: {stok}", - font=("Arial", 8), - fg=stok_color, - bg='white' - ).pack(pady=2) + # --- Bagian Tombol --- + qty = cart_dict.get(mid, 0) + act_frame = tk.Frame(card, bg='white') + # Pack side bottom agar tombol selalu di bawah card + act_frame.pack(pady=5, fill='x', side='bottom') - qty_in_cart = cart_dict.get(mid, 0) - - btn_frame = tk.Frame(card, bg='white') - btn_frame.pack(pady=(5, 5), fill='x') - - if qty_in_cart > 0: - tk.Button( - btn_frame, - text="➖", - font=("Arial", 10, "bold"), - bg='#FF5722', - fg='white', - width=3, - borderwidth=0, - cursor='hand2', - command=lambda m=mid: self.decrease_from_card(m) - ).pack(side='left', padx=2) - - tk.Label( - btn_frame, - text=str(qty_in_cart), - font=("Arial", 10, "bold"), - bg='white', - width=4 - ).pack(side='left', padx=3) - - tk.Button( - btn_frame, - text="➕", - font=("Arial", 10, "bold"), - bg='#4CAF50', - fg='white', - width=3, - borderwidth=0, - cursor='hand2', - command=lambda m=mid, s=stok: self.increase_from_card(m, s) - ).pack(side='left', padx=2) + if qty > 0: + tk.Button(act_frame, text="-", bg='#FF5722', fg='white', width=2, borderwidth=0, + command=lambda m=mid: self.decrease_from_card(m)).pack(side='left', padx=2) + tk.Label(act_frame, text=str(qty), bg='white').pack(side='left', expand=True) + tk.Button(act_frame, text="+", bg='#4CAF50', fg='white', width=2, borderwidth=0, + command=lambda m=mid, s=stok: self.increase_from_card(m, s)).pack(side='right', padx=2) else: - tk.Button( - btn_frame, - text="➕ Tambah", - font=("Arial", 9, "bold"), - bg='#4CAF50', - fg='white', - borderwidth=0, - cursor='hand2', - command=lambda m=mid, s=stok: self.increase_from_card(m, s) - ).pack(fill='x', padx=2) + tk.Button(act_frame, text="+ Tambah", bg='#4CAF50', fg='white', borderwidth=0, + command=lambda m=mid, s=stok: self.increase_from_card(m, s)).pack(fill='x') + # --- Logika Pindah Baris --- col += 1 - if col >= 2: + if col >= total_columns: col = 0 row += 1 + # Reset row weight for i in range(row + 1): - self.menu_cards_frame.rowconfigure(i, weight=1) + self.menu_cards_frame.rowconfigure(i, weight=0) def reset_order_search(self): diff --git a/meja.csv b/meja.csv index 67560f2..1e2339d 100644 --- a/meja.csv +++ b/meja.csv @@ -1,11 +1,11 @@ nomor_meja,status,transaksi_id -1,terisi, -2,kosong, +1,kosong, +2,terisi, 3,kosong, -4,kosong, -5,terisi, +4,terisi, +5,kosong, 6,kosong, 7,kosong, 8,kosong, -9,terisi, +9,kosong, 10,kosong,