Styling Update
This commit is contained in:
parent
673a693020
commit
3d7b31f218
BIN
img/totoro_sitting.png
Normal file
BIN
img/totoro_sitting.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 225 KiB |
559
main.py
559
main.py
@ -12,8 +12,10 @@ import tkinter as tk
|
||||
from tkinter import ttk, messagebox, filedialog, simpledialog
|
||||
from PIL import Image, ImageTk
|
||||
|
||||
|
||||
|
||||
# ========================================
|
||||
# UI STYLING - TOTORO THEME COLORS
|
||||
# UI STYLING - TOTORO THEME COLORS + FONTS
|
||||
# ========================================
|
||||
COLORS = {
|
||||
'bg_main': '#F5F5DC', # Beige/Krem lembut (background utama)
|
||||
@ -28,6 +30,19 @@ COLORS = {
|
||||
'warning': '#D4A574', # Coklat muda untuk warning
|
||||
'danger': '#C9797A', # Merah lembut untuk danger
|
||||
'border': '#D4C5B9', # Border coklat muda
|
||||
'shadow': '#D0D0D0', # Shadow abu-abu lembut
|
||||
}
|
||||
|
||||
# Font configuration untuk tema Totoro
|
||||
FONTS = {
|
||||
'header': ('Comic Sans MS', 16, 'bold'),
|
||||
'subheader': ('Segoe UI', 12, 'bold'),
|
||||
'body': ('Segoe UI', 10),
|
||||
'body_bold': ('Segoe UI', 10, 'bold'),
|
||||
'small': ('Segoe UI', 9),
|
||||
'tiny': ('Segoe UI', 8),
|
||||
'button': ('Segoe UI', 11, 'bold'),
|
||||
'mono': ('Consolas', 9),
|
||||
}
|
||||
|
||||
USERS_CSV = "users.csv"
|
||||
@ -40,6 +55,28 @@ MEJA_CSV = "meja.csv"
|
||||
PEMBAYARAN_CSV = "pembayaran.csv"
|
||||
IMG_PREVIEW_SIZE = (120, 80)
|
||||
|
||||
def create_placeholder_image():
|
||||
"""Buat placeholder jika gambar belum ada"""
|
||||
if not os.path.exists('img'):
|
||||
os.makedirs('img')
|
||||
|
||||
if not os.path.exists('img/totoro_sitting.png'):
|
||||
try:
|
||||
from PIL import Image, ImageDraw
|
||||
|
||||
# Buat gambar placeholder 300x300
|
||||
img = Image.new('RGB', (300, 300), color=COLORS['accent'])
|
||||
draw = ImageDraw.Draw(img)
|
||||
|
||||
# Tulis text
|
||||
draw.text((50, 140), "TOTORO\nPLACEHOLDER", fill=COLORS['brown'])
|
||||
|
||||
img.save('img/totoro_sitting.png')
|
||||
except:
|
||||
pass
|
||||
|
||||
# Panggil saat init
|
||||
create_placeholder_image()
|
||||
|
||||
def ensure_file(path, fieldnames):
|
||||
if not os.path.exists(path):
|
||||
@ -1124,6 +1161,47 @@ class App:
|
||||
self.img_cache = {}
|
||||
self.setup_ui()
|
||||
|
||||
def create_hover_button(self, parent, text, command, style='primary', width=None):
|
||||
"""Helper untuk membuat button dengan hover effect"""
|
||||
|
||||
bg_colors = {
|
||||
'primary': (COLORS['primary'], COLORS['primary_dark']),
|
||||
'success': (COLORS['success'], COLORS['primary_dark']),
|
||||
'danger': (COLORS['danger'], '#B85555'),
|
||||
'brown': (COLORS['brown'], '#6B5D48')
|
||||
}
|
||||
|
||||
bg_normal, bg_hover = bg_colors.get(style, bg_colors['primary'])
|
||||
|
||||
btn = tk.Button(
|
||||
parent,
|
||||
text=text,
|
||||
command=command,
|
||||
bg=bg_normal,
|
||||
fg='white',
|
||||
font=FONTS['button'],
|
||||
relief='flat',
|
||||
cursor='hand2',
|
||||
borderwidth=0,
|
||||
padx=20,
|
||||
pady=10
|
||||
)
|
||||
|
||||
if width:
|
||||
btn.config(width=width)
|
||||
|
||||
def on_enter(e):
|
||||
btn['background'] = bg_hover
|
||||
|
||||
def on_leave(e):
|
||||
btn['background'] = bg_normal
|
||||
|
||||
btn.bind('<Enter>', on_enter)
|
||||
btn.bind('<Leave>', on_leave)
|
||||
|
||||
return btn
|
||||
|
||||
|
||||
def setup_ui(self):
|
||||
# UI STYLING - Window setup dengan tema Totoro
|
||||
self.root.geometry("1200x750")
|
||||
@ -1200,97 +1278,228 @@ class App:
|
||||
for w in self.root.winfo_children():
|
||||
w.destroy()
|
||||
|
||||
# UI STYLING - Main container dengan background Totoro
|
||||
# ========================================
|
||||
# TOTORO LOGIN - LANDSCAPE LAYOUT (FIXED)
|
||||
# ========================================
|
||||
|
||||
# Main container dengan background
|
||||
main_container = tk.Frame(self.root, bg=COLORS['bg_main'])
|
||||
main_container.pack(fill='both', expand=True)
|
||||
|
||||
# UI STYLING - Center frame untuk login card
|
||||
# Center frame untuk positioning
|
||||
center_frame = tk.Frame(main_container, bg=COLORS['bg_main'])
|
||||
center_frame.place(relx=0.5, rely=0.5, anchor='center')
|
||||
center_frame.pack(expand=True, pady=50)
|
||||
|
||||
# UI STYLING - Login card dengan shadow effect
|
||||
card = tk.Frame(center_frame, bg='white', relief='flat', borderwidth=0)
|
||||
card.pack(padx=20, pady=20)
|
||||
# ========================================
|
||||
# MAIN CARD - LANDSCAPE (TANPA SHADOW DULU)
|
||||
# ========================================
|
||||
card = tk.Frame(
|
||||
center_frame,
|
||||
bg='white',
|
||||
relief='ridge',
|
||||
borderwidth=3,
|
||||
padx=0,
|
||||
pady=0
|
||||
)
|
||||
card.pack()
|
||||
|
||||
# UI STYLING - Header dengan tema Totoro
|
||||
header_frame = tk.Frame(card, bg=COLORS['primary'], height=100)
|
||||
header_frame.pack(fill='x', pady=(0, 30))
|
||||
# ========================================
|
||||
# CONTAINER HORIZONTAL (2 PANEL)
|
||||
# ========================================
|
||||
container = tk.Frame(card, bg='white')
|
||||
container.pack()
|
||||
|
||||
# UI STYLING - Logo Totoro di atas card
|
||||
# ========================================
|
||||
# LEFT PANEL - TOTORO ILLUSTRATION
|
||||
# ========================================
|
||||
left_panel = tk.Frame(container, bg=COLORS['accent'], width=350)
|
||||
left_panel.pack(side='left', fill='y', padx=0, pady=0)
|
||||
|
||||
# Spacer atas
|
||||
tk.Label(left_panel, text="", bg=COLORS['accent'], height=2).pack()
|
||||
|
||||
# Totoro illustration
|
||||
try:
|
||||
totoro_img = Image.open("img/totoro_logo.png")
|
||||
totoro_img = totoro_img.resize((100, 100), Image.Resampling.LANCZOS)
|
||||
totoro_img = Image.open("img/totoro_sitting.png")
|
||||
totoro_img = totoro_img.resize((250, 250), Image.Resampling.LANCZOS)
|
||||
totoro_photo = ImageTk.PhotoImage(totoro_img)
|
||||
|
||||
self.totoro_logo = totoro_photo
|
||||
self.totoro_login_img = totoro_photo
|
||||
|
||||
img_label = tk.Label(card, image=totoro_photo, bg='white')
|
||||
img_label.pack(pady=(20, 10))
|
||||
except:
|
||||
# Fallback jika gambar tidak ditemukan
|
||||
tk.Label(card, text="🌿", font=("Arial", 48), bg='white').pack(pady=(20, 10))
|
||||
img_label = tk.Label(left_panel, image=totoro_photo, bg=COLORS['accent'])
|
||||
img_label.pack(pady=20)
|
||||
except Exception as e:
|
||||
print(f"⚠️ Gambar tidak ditemukan: {e}")
|
||||
tk.Label(
|
||||
left_panel,
|
||||
text="🌿\n\n🍃\n\n🌳",
|
||||
font=('Arial', 50),
|
||||
bg=COLORS['accent'],
|
||||
fg=COLORS['primary_dark']
|
||||
).pack(pady=40)
|
||||
|
||||
# Welcome text
|
||||
tk.Label(
|
||||
left_panel,
|
||||
text="Welome to Totoro Café\nTotoro is waiting for you!",
|
||||
font=('Comic Sans MS', 11, 'italic'),
|
||||
bg=COLORS['accent'],
|
||||
fg=COLORS['brown']
|
||||
).pack(pady=(10, 30))
|
||||
|
||||
tk.Label(header_frame,
|
||||
text="🌿 TOTORO CAFÉ 🌿",
|
||||
font=("Arial", 24, "bold"),
|
||||
bg=COLORS['primary'],
|
||||
fg='white').pack(pady=20)
|
||||
# ========================================
|
||||
# RIGHT PANEL - LOGIN FORM
|
||||
# ========================================
|
||||
right_panel = tk.Frame(container, bg='white', padx=40, pady=30)
|
||||
right_panel.pack(side='right', fill='both')
|
||||
|
||||
tk.Label(header_frame,
|
||||
text="Selamat Datang di Sistem Manajemen Cafe",
|
||||
font=("Arial", 10),
|
||||
bg=COLORS['primary'],
|
||||
fg='white').pack(pady=(0, 10))
|
||||
# Header
|
||||
tk.Label(
|
||||
right_panel,
|
||||
text="🌿 TOTORO CAFÉ 🌿",
|
||||
font=('Comic Sans MS', 22, 'bold'),
|
||||
bg='white',
|
||||
fg=COLORS['primary']
|
||||
).pack(pady=(10, 5))
|
||||
|
||||
# UI STYLING - Form container
|
||||
form_frame = tk.Frame(card, bg='white')
|
||||
form_frame.pack(padx=50, pady=20)
|
||||
tk.Label(
|
||||
right_panel,
|
||||
text="Cafe Management System",
|
||||
font=('Segoe UI', 9),
|
||||
bg='white',
|
||||
fg=COLORS['text_light']
|
||||
).pack(pady=(0, 20))
|
||||
|
||||
# Form container
|
||||
form_frame = tk.Frame(right_panel, bg='white')
|
||||
form_frame.pack(pady=10)
|
||||
|
||||
# Username
|
||||
tk.Label(form_frame, text="Username:", font=("Arial", 11), bg='white', fg=COLORS['text_dark']).grid(row=0, column=0, sticky='w', pady=(10, 5))
|
||||
tk.Label(
|
||||
form_frame,
|
||||
text="Username:",
|
||||
font=('Segoe UI', 10, 'bold'),
|
||||
bg='white',
|
||||
fg=COLORS['text_dark']
|
||||
).grid(row=0, column=0, sticky='w', pady=(10, 5), padx=5)
|
||||
|
||||
self.username_var = tk.StringVar()
|
||||
username_entry = tk.Entry(form_frame, textvariable=self.username_var, width=35, font=("Arial", 11), relief='solid', borderwidth=1)
|
||||
username_entry.grid(row=1, column=0, pady=(0, 15), ipady=8)
|
||||
username_entry = tk.Entry(
|
||||
form_frame,
|
||||
textvariable=self.username_var,
|
||||
width=32,
|
||||
font=('Segoe UI', 10),
|
||||
relief='solid',
|
||||
borderwidth=1
|
||||
)
|
||||
username_entry.grid(row=1, column=0, pady=(0, 15), ipady=7, padx=5)
|
||||
|
||||
# Password
|
||||
tk.Label(form_frame, text="Password:", font=("Arial", 11), bg='white', fg=COLORS['text_dark']).grid(row=2, column=0, sticky='w', pady=(10, 5))
|
||||
tk.Label(
|
||||
form_frame,
|
||||
text="Password:",
|
||||
font=('Segoe UI', 10, 'bold'),
|
||||
bg='white',
|
||||
fg=COLORS['text_dark']
|
||||
).grid(row=2, column=0, sticky='w', pady=(5, 5), padx=5)
|
||||
|
||||
self.password_var = tk.StringVar()
|
||||
password_entry = tk.Entry(form_frame, textvariable=self.password_var, show="●", width=35, font=("Arial", 11), relief='solid', borderwidth=1)
|
||||
password_entry.grid(row=3, column=0, pady=(0, 15), ipady=8)
|
||||
password_entry = tk.Entry(
|
||||
form_frame,
|
||||
textvariable=self.password_var,
|
||||
show="●",
|
||||
width=32,
|
||||
font=('Segoe UI', 10),
|
||||
relief='solid',
|
||||
borderwidth=1
|
||||
)
|
||||
password_entry.grid(row=3, column=0, pady=(0, 15), ipady=7, padx=5)
|
||||
|
||||
# UI STYLING - Info untuk pembeli
|
||||
info_frame = tk.Frame(form_frame, bg='#FFF9E6', relief='solid', borderwidth=1)
|
||||
info_frame.grid(row=4, column=0, pady=15, sticky='ew')
|
||||
# Separator
|
||||
separator = tk.Frame(form_frame, bg=COLORS['border'], height=2)
|
||||
separator.grid(row=4, column=0, sticky='ew', pady=12, padx=5)
|
||||
|
||||
tk.Label(info_frame, text="ℹ️ Khusus untuk Pembeli", font=("Arial", 9, "bold"), bg='#FFF9E6', fg=COLORS['brown']).pack(anchor='w', padx=10, pady=(10, 5))
|
||||
# Info box
|
||||
info_frame = tk.Frame(
|
||||
form_frame,
|
||||
bg='#FFF9E6',
|
||||
relief='solid',
|
||||
borderwidth=1
|
||||
)
|
||||
info_frame.grid(row=5, column=0, pady=8, sticky='ew', padx=5)
|
||||
|
||||
tk.Label(
|
||||
info_frame,
|
||||
text="ℹ️ Khusus untuk Pembeli",
|
||||
font=('Segoe UI', 9, 'bold'),
|
||||
bg='#FFF9E6',
|
||||
fg=COLORS['brown']
|
||||
).pack(anchor='w', padx=10, pady=(8, 3))
|
||||
|
||||
tk.Label(
|
||||
info_frame,
|
||||
text="Silakan isi Nama & Nomor Meja",
|
||||
font=('Segoe UI', 8),
|
||||
bg='#FFF9E6',
|
||||
fg=COLORS['text_light']
|
||||
).pack(anchor='w', padx=10, pady=(0, 8))
|
||||
|
||||
# Nama Lengkap
|
||||
tk.Label(form_frame, text="Nama Lengkap:", font=("Arial", 10), bg='white', fg=COLORS['text_light']).grid(row=5, column=0, sticky='w', pady=(5, 3))
|
||||
tk.Label(
|
||||
form_frame,
|
||||
text="Nama Lengkap:",
|
||||
font=('Segoe UI', 9),
|
||||
bg='white',
|
||||
fg=COLORS['text_light']
|
||||
).grid(row=6, column=0, sticky='w', pady=(10, 3), padx=5)
|
||||
|
||||
self.customer_name_var = tk.StringVar()
|
||||
customer_entry = tk.Entry(form_frame, textvariable=self.customer_name_var, width=35, font=("Arial", 10), relief='solid', borderwidth=1)
|
||||
customer_entry.grid(row=6, column=0, pady=(0, 10), ipady=6)
|
||||
customer_entry = tk.Entry(
|
||||
form_frame,
|
||||
textvariable=self.customer_name_var,
|
||||
width=32,
|
||||
font=('Segoe UI', 9),
|
||||
relief='solid',
|
||||
borderwidth=1
|
||||
)
|
||||
customer_entry.grid(row=7, column=0, pady=(0, 10), ipady=6, padx=5)
|
||||
|
||||
# Nomor Meja
|
||||
tk.Label(form_frame, text="Nomor Meja (1-10):", font=("Arial", 10), bg='white', fg=COLORS['text_light']).grid(row=7, column=0, sticky='w', pady=(5, 3))
|
||||
tk.Label(
|
||||
form_frame,
|
||||
text="Nomor Meja (1-10):",
|
||||
font=('Segoe UI', 9),
|
||||
bg='white',
|
||||
fg=COLORS['text_light']
|
||||
).grid(row=8, column=0, sticky='w', pady=(5, 3), padx=5)
|
||||
|
||||
self.customer_meja_var = tk.StringVar()
|
||||
meja_entry = tk.Entry(form_frame, textvariable=self.customer_meja_var, width=35, font=("Arial", 10), relief='solid', borderwidth=1)
|
||||
meja_entry.grid(row=8, column=0, pady=(0, 20), ipady=6)
|
||||
meja_entry = tk.Entry(
|
||||
form_frame,
|
||||
textvariable=self.customer_meja_var,
|
||||
width=32,
|
||||
font=('Segoe UI', 9),
|
||||
relief='solid',
|
||||
borderwidth=1
|
||||
)
|
||||
meja_entry.grid(row=9, column=0, pady=(0, 20), ipady=6, padx=5)
|
||||
|
||||
# UI STYLING - Login button dengan style Totoro
|
||||
login_btn = tk.Button(form_frame,
|
||||
text="🌿 LOGIN",
|
||||
command=self.handle_login,
|
||||
bg=COLORS['primary'],
|
||||
fg='white',
|
||||
font=("Arial", 12, "bold"),
|
||||
relief='flat',
|
||||
cursor='hand2',
|
||||
width=30,
|
||||
height=2)
|
||||
login_btn.grid(row=9, column=0, pady=(10, 20))
|
||||
# Login button
|
||||
login_btn = tk.Button(
|
||||
form_frame,
|
||||
text="LOGIN",
|
||||
command=self.handle_login,
|
||||
bg=COLORS['primary'],
|
||||
fg='white',
|
||||
font=('Segoe UI', 11, 'bold'),
|
||||
relief='flat',
|
||||
cursor='hand2',
|
||||
width=28,
|
||||
height=2,
|
||||
borderwidth=0
|
||||
)
|
||||
login_btn.grid(row=10, column=0, pady=(10, 15), padx=5)
|
||||
|
||||
# Hover effect untuk button
|
||||
def on_enter(e):
|
||||
login_btn['background'] = COLORS['primary_dark']
|
||||
def on_leave(e):
|
||||
@ -1299,15 +1508,15 @@ class App:
|
||||
login_btn.bind("<Enter>", on_enter)
|
||||
login_btn.bind("<Leave>", on_leave)
|
||||
|
||||
# UI STYLING - Footer
|
||||
footer_frame = tk.Frame(card, bg='white')
|
||||
footer_frame.pack(fill='x', pady=(0, 20))
|
||||
# Footer
|
||||
tk.Label(
|
||||
right_panel,
|
||||
text="© 2025 Café Totoro - UAS Informatika",
|
||||
font=('Segoe UI', 7),
|
||||
bg='white',
|
||||
fg=COLORS['text_light']
|
||||
).pack(side='bottom', pady=(20, 10))
|
||||
|
||||
tk.Label(footer_frame,
|
||||
text="© 2025 Café Totoro - Proyek UAS Informatika",
|
||||
font=("Arial", 8),
|
||||
bg='white',
|
||||
fg=COLORS['text_light']).pack()
|
||||
|
||||
|
||||
def handle_login(self):
|
||||
@ -1392,58 +1601,94 @@ class App:
|
||||
def dashboard_frame(self):
|
||||
for w in self.root.winfo_children():
|
||||
w.destroy()
|
||||
# UI STYLING - Header dashboard dengan tema Totoro
|
||||
top = tk.Frame(self.root, bg=COLORS['primary'], height=60)
|
||||
|
||||
# ========================================
|
||||
# DASHBOARD HEADER - IMPROVED
|
||||
# ========================================
|
||||
top = tk.Frame(self.root, bg=COLORS['primary'], height=70)
|
||||
top.pack(fill='x')
|
||||
|
||||
# Left side - User info
|
||||
left_info = tk.Frame(top, bg=COLORS['primary'])
|
||||
left_info.pack(side='left', padx=20, pady=10)
|
||||
# Left side - Logo + Title
|
||||
left_side = tk.Frame(top, bg=COLORS['primary'])
|
||||
left_side.pack(side='left', padx=20, pady=10)
|
||||
|
||||
# UI STYLING - Logo kecil di header
|
||||
# Logo
|
||||
try:
|
||||
totoro_header = Image.open("img/totoro_logo.png")
|
||||
totoro_header = totoro_header.resize((40, 40), Image.Resampling.LANCZOS)
|
||||
totoro_header = totoro_header.resize((45, 45), Image.Resampling.LANCZOS)
|
||||
totoro_header_photo = ImageTk.PhotoImage(totoro_header)
|
||||
|
||||
self.totoro_header_logo = totoro_header_photo
|
||||
|
||||
tk.Label(top, image=totoro_header_photo, bg=COLORS['primary']).pack(side='left', padx=(20, 5))
|
||||
tk.Label(left_side, image=totoro_header_photo, bg=COLORS['primary']).pack(side='left', padx=(0, 10))
|
||||
except:
|
||||
tk.Label(top, text="🌿", font=("Arial", 24), bg=COLORS['primary']).pack(side='left', padx=(20, 5))
|
||||
tk.Label(left_side, text="🌿", font=('Arial', 28), bg=COLORS['primary']).pack(side='left', padx=(0, 10))
|
||||
|
||||
# Title + Subtitle
|
||||
title_frame = tk.Frame(left_side, bg=COLORS['primary'])
|
||||
title_frame.pack(side='left')
|
||||
|
||||
tk.Label(
|
||||
title_frame,
|
||||
text="TOTORO CAFÉ",
|
||||
font=('Comic Sans MS', 16, 'bold'),
|
||||
bg=COLORS['primary'],
|
||||
fg='white'
|
||||
).pack(anchor='w')
|
||||
|
||||
tk.Label(
|
||||
title_frame,
|
||||
text="Your Cozy Corner for Every Order",
|
||||
font=FONTS['small'],
|
||||
bg=COLORS['primary'],
|
||||
fg='white'
|
||||
).pack(anchor='w')
|
||||
|
||||
# Center - User info (IMPROVED)
|
||||
center_info = tk.Frame(top, bg=COLORS['primary'])
|
||||
center_info.pack(side='left', expand=True, padx=20)
|
||||
|
||||
if self.session['role'] in ['pembeli', 'user'] and 'customer_name' in self.session:
|
||||
header_text = f"👤 {self.session['customer_name']}"
|
||||
subtext = f"Meja {self.session.get('nomor_meja', '-')} • {self.session['role'].title()}"
|
||||
user_text = f"👤 {self.session['customer_name']}"
|
||||
role_text = f"🪑 Meja {self.session.get('nomor_meja', '-')} • {self.session['role'].title()}"
|
||||
else:
|
||||
header_text = f"👤 {self.session['username']}"
|
||||
subtext = f"Role: {self.session['role'].title()}"
|
||||
user_text = f"👤 {self.session['username']}"
|
||||
role_text = f"🎭 Role: {self.session['role'].title()}"
|
||||
|
||||
tk.Label(left_info,
|
||||
text=header_text,
|
||||
font=("Arial", 13, "bold"),
|
||||
bg=COLORS['primary'],
|
||||
fg='white').pack(anchor='w')
|
||||
tk.Label(
|
||||
center_info,
|
||||
text=user_text,
|
||||
font=FONTS['subheader'],
|
||||
bg=COLORS['primary'],
|
||||
fg='white'
|
||||
).pack()
|
||||
|
||||
tk.Label(left_info,
|
||||
text=subtext,
|
||||
font=("Arial", 9),
|
||||
bg=COLORS['primary'],
|
||||
fg='white').pack(anchor='w')
|
||||
tk.Label(
|
||||
center_info,
|
||||
text=role_text,
|
||||
font=FONTS['small'],
|
||||
bg=COLORS['primary'],
|
||||
fg='white'
|
||||
).pack()
|
||||
|
||||
# Right side - Logout button
|
||||
logout_btn = tk.Button(top,
|
||||
text="🚪 Logout",
|
||||
command=self.logout,
|
||||
bg=COLORS['brown'],
|
||||
fg='white',
|
||||
font=("Arial", 10, "bold"),
|
||||
relief='flat',
|
||||
cursor='hand2',
|
||||
padx=20,
|
||||
pady=8)
|
||||
logout_btn.pack(side='right', padx=20, pady=10)
|
||||
# Right side - Logout button dengan shadow
|
||||
right_side = tk.Frame(top, bg=COLORS['primary'])
|
||||
right_side.pack(side='right', padx=20, pady=10)
|
||||
|
||||
logout_btn = tk.Button(
|
||||
right_side,
|
||||
text="Logout",
|
||||
command=self.logout,
|
||||
bg=COLORS['brown'],
|
||||
fg='white',
|
||||
font=FONTS['button'],
|
||||
relief='flat',
|
||||
cursor='hand2',
|
||||
padx=25,
|
||||
pady=10,
|
||||
borderwidth=0
|
||||
)
|
||||
logout_btn.pack()
|
||||
|
||||
# Hover effect
|
||||
def on_enter(e):
|
||||
@ -1453,13 +1698,14 @@ class App:
|
||||
logout_btn.bind("<Enter>", on_enter)
|
||||
logout_btn.bind("<Leave>", on_leave)
|
||||
|
||||
# UI STYLING - Container untuk tabs
|
||||
# Tab container dengan styling
|
||||
tab_container = tk.Frame(self.root, bg=COLORS['bg_main'])
|
||||
tab_container.pack(fill='both', expand=True, padx=15, pady=10)
|
||||
|
||||
main = ttk.Notebook(tab_container)
|
||||
main.pack(fill='both', expand=True)
|
||||
|
||||
|
||||
self.tab_menu_manage = ttk.Frame(main)
|
||||
self.tab_menu_view = ttk.Frame(main)
|
||||
self.tab_promo = ttk.Frame(main)
|
||||
@ -2054,21 +2300,27 @@ class App:
|
||||
for cart_item in self.cart_items:
|
||||
cart_dict[cart_item['menu_id']] = cart_item['qty']
|
||||
|
||||
# Render cards dalam grid (2 kolom)
|
||||
# Configure grid columns (2 kolom sama lebar)
|
||||
self.menu_cards_frame.columnconfigure(0, weight=1)
|
||||
self.menu_cards_frame.columnconfigure(1, weight=1)
|
||||
|
||||
row = 0
|
||||
col = 0
|
||||
|
||||
for menu_data in results:
|
||||
mid, nama, kategori, harga, stok, foto, tersedia, item_disc = menu_data
|
||||
|
||||
# Create card frame (DENGAN BACKGROUND PUTIH + BORDER)
|
||||
card = tk.Frame(
|
||||
self.menu_cards_frame,
|
||||
relief='solid',
|
||||
borderwidth=1,
|
||||
bg='white',
|
||||
padx=10,
|
||||
pady=10
|
||||
pady=10,
|
||||
width=200,
|
||||
height=320
|
||||
)
|
||||
card.grid_propagate(False)
|
||||
card.grid(row=row, column=col, padx=8, pady=8, sticky='nsew')
|
||||
|
||||
# Gambar
|
||||
@ -2080,41 +2332,85 @@ class App:
|
||||
|
||||
img_label = tk.Label(card, image=photo, bg='white')
|
||||
img_label.image = photo
|
||||
img_label.pack()
|
||||
img_label.pack(pady=(5, 5))
|
||||
except:
|
||||
tk.Label(card, text="[No Image]", bg='#e0e0e0', width=20, height=6).pack()
|
||||
tk.Label(
|
||||
card,
|
||||
text="[No Image]",
|
||||
bg='#e0e0e0',
|
||||
width=20,
|
||||
height=6
|
||||
).pack()
|
||||
else:
|
||||
tk.Label(card, text="[No Image]", bg='#e0e0e0', width=20, height=6).pack()
|
||||
tk.Label(
|
||||
card,
|
||||
text="[No Image]",
|
||||
bg='#e0e0e0',
|
||||
width=18,
|
||||
height=5
|
||||
).pack()
|
||||
|
||||
# Nama menu
|
||||
tk.Label(card, text=nama, font=("Arial", 11, "bold"), bg='white', wraplength=150).pack(pady=(5, 2))
|
||||
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", 9), fg='gray', bg='white').pack()
|
||||
tk.Label(
|
||||
card,
|
||||
text=kategori,
|
||||
font=("Arial", 8),
|
||||
fg='gray',
|
||||
bg='white'
|
||||
).pack(pady=1)
|
||||
|
||||
# Harga
|
||||
harga_text = f"Rp {harga:,.0f}"
|
||||
if item_disc > 0:
|
||||
harga_text += f" (-{item_disc}%)"
|
||||
tk.Label(card, text=harga_text, font=("Arial", 10, "bold"), fg='#4CAF50', bg='white').pack(pady=2)
|
||||
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)
|
||||
else:
|
||||
tk.Label(card, text=harga_text, font=("Arial", 10, "bold"), fg='green', bg='white').pack(pady=2)
|
||||
tk.Label(
|
||||
card,
|
||||
text=harga_text,
|
||||
font=("Arial", 9, "bold"),
|
||||
fg='green',
|
||||
bg='white'
|
||||
).pack(pady=2)
|
||||
|
||||
# Stok info
|
||||
tk.Label(card, text=f"Stok: {stok}", font=("Arial", 8), fg='blue', bg='white').pack(pady=2)
|
||||
# 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)
|
||||
|
||||
# Tombol +/- atau + saja
|
||||
qty_in_cart = cart_dict.get(mid, 0)
|
||||
|
||||
btn_frame = tk.Frame(card, bg='white')
|
||||
btn_frame.pack(pady=5)
|
||||
btn_frame.pack(pady=(5, 5), fill='x')
|
||||
|
||||
if qty_in_cart > 0:
|
||||
# Tampilkan - [qty] +
|
||||
tk.Button(
|
||||
btn_frame,
|
||||
text="➖",
|
||||
font=("Arial", 12, "bold"),
|
||||
font=("Arial", 10, "bold"),
|
||||
bg='#FF5722',
|
||||
fg='white',
|
||||
width=3,
|
||||
@ -2126,15 +2422,15 @@ class App:
|
||||
tk.Label(
|
||||
btn_frame,
|
||||
text=str(qty_in_cart),
|
||||
font=("Arial", 12, "bold"),
|
||||
font=("Arial", 10, "bold"),
|
||||
bg='white',
|
||||
width=3
|
||||
).pack(side='left', padx=5)
|
||||
width=4
|
||||
).pack(side='left', padx=3)
|
||||
|
||||
tk.Button(
|
||||
btn_frame,
|
||||
text="➕",
|
||||
font=("Arial", 12, "bold"),
|
||||
font=("Arial", 10, "bold"),
|
||||
bg='#4CAF50',
|
||||
fg='white',
|
||||
width=3,
|
||||
@ -2143,25 +2439,26 @@ class App:
|
||||
command=lambda m=mid, s=stok: self.increase_from_card(m, s)
|
||||
).pack(side='left', padx=2)
|
||||
else:
|
||||
# Tampilkan tombol + aja
|
||||
tk.Button(
|
||||
btn_frame,
|
||||
text="➕ Tambah",
|
||||
font=("Arial", 10, "bold"),
|
||||
font=("Arial", 9, "bold"),
|
||||
bg='#4CAF50',
|
||||
fg='white',
|
||||
width=12,
|
||||
borderwidth=0,
|
||||
cursor='hand2',
|
||||
command=lambda m=mid, s=stok: self.increase_from_card(m, s)
|
||||
).pack()
|
||||
).pack(fill='x', padx=2)
|
||||
|
||||
# Next column
|
||||
col += 1
|
||||
if col >= 2:
|
||||
col = 0
|
||||
row += 1
|
||||
|
||||
for i in range(row + 1):
|
||||
self.menu_cards_frame.rowconfigure(i, weight=1)
|
||||
|
||||
|
||||
def reset_order_search(self):
|
||||
self.order_search_var.set("")
|
||||
self.reload_order_menu_cards()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user