Styling Totoro
This commit is contained in:
parent
61547a4012
commit
673a693020
BIN
img/totoro_logo.png
Normal file
BIN
img/totoro_logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 129 KiB |
295
main.py
295
main.py
@ -12,6 +12,24 @@ import tkinter as tk
|
||||
from tkinter import ttk, messagebox, filedialog, simpledialog
|
||||
from PIL import Image, ImageTk
|
||||
|
||||
# ========================================
|
||||
# UI STYLING - TOTORO THEME COLORS
|
||||
# ========================================
|
||||
COLORS = {
|
||||
'bg_main': '#F5F5DC', # Beige/Krem lembut (background utama)
|
||||
'bg_secondary': '#FFFFFF', # Putih untuk cards
|
||||
'primary': '#8FBFA8', # Hijau Totoro (medium)
|
||||
'primary_dark': '#6B9080', # Hijau tua
|
||||
'accent': '#A8D5BA', # Hijau pastel lembut
|
||||
'brown': '#8B7355', # Coklat kayu
|
||||
'text_dark': '#3D3D3D', # Text gelap
|
||||
'text_light': '#666666', # Text abu-abu
|
||||
'success': '#6B9080', # Hijau untuk success
|
||||
'warning': '#D4A574', # Coklat muda untuk warning
|
||||
'danger': '#C9797A', # Merah lembut untuk danger
|
||||
'border': '#D4C5B9', # Border coklat muda
|
||||
}
|
||||
|
||||
USERS_CSV = "users.csv"
|
||||
MENU_CSV = "menu.csv"
|
||||
PROMO_CSV = "promo.csv"
|
||||
@ -793,7 +811,7 @@ def report_get_monthly_summary(year=None, month=None, method_filter=None):
|
||||
def report_export_to_text(report_data, report_type='daily'):
|
||||
"""Export laporan ke format text"""
|
||||
text = "=" * 70 + "\n"
|
||||
text += "LAPORAN PENJUALAN CAFE TOTORO MANIA\n"
|
||||
text += "LAPORAN PENJUALAN CAFÉ TOTORO \n"
|
||||
text += "=" * 70 + "\n\n"
|
||||
|
||||
if report_type == 'daily':
|
||||
@ -1101,51 +1119,195 @@ def meja_get(nomor_meja):
|
||||
class App:
|
||||
def __init__(self, root):
|
||||
self.root = root
|
||||
self.root.title("Cafe Totoro Mania")
|
||||
self.root.title("Totoro Cafe")
|
||||
self.session = None
|
||||
self.img_cache = {}
|
||||
self.setup_ui()
|
||||
|
||||
def setup_ui(self):
|
||||
self.root.geometry("1000x650")
|
||||
self.root.resizable(False, False)
|
||||
self.login_frame()
|
||||
# UI STYLING - Window setup dengan tema Totoro
|
||||
self.root.geometry("1200x750")
|
||||
self.root.resizable(True, True) # Bisa maximize
|
||||
self.root.configure(bg=COLORS['bg_main'])
|
||||
|
||||
# UI STYLING - Custom styles untuk tema Totoro
|
||||
style = ttk.Style()
|
||||
style.configure("Accent.TButton", font=("Arial", 11, "bold"))
|
||||
style.configure("TButton", padding=6) # Padding tombol lebih besar
|
||||
style.theme_use('clam')
|
||||
|
||||
# Background colors
|
||||
style.configure(".", background=COLORS['bg_main'], foreground=COLORS['text_dark'])
|
||||
|
||||
# Frame styles
|
||||
style.configure("TFrame", background=COLORS['bg_main'])
|
||||
style.configure("TLabelframe", background=COLORS['bg_main'], bordercolor=COLORS['border'])
|
||||
style.configure("TLabelframe.Label", background=COLORS['bg_main'], foreground=COLORS['brown'], font=("Arial", 10, "bold"))
|
||||
|
||||
# Button styles
|
||||
style.configure("TButton",
|
||||
background=COLORS['primary'],
|
||||
foreground="white",
|
||||
borderwidth=0,
|
||||
focuscolor='none',
|
||||
font=("Arial", 10),
|
||||
padding=10)
|
||||
style.map("TButton",
|
||||
background=[('active', COLORS['primary_dark']), ('pressed', COLORS['primary_dark'])],
|
||||
foreground=[('active', 'white')])
|
||||
|
||||
style.configure("Accent.TButton",
|
||||
background=COLORS['brown'],
|
||||
foreground="white",
|
||||
font=("Arial", 11, "bold"),
|
||||
padding=12)
|
||||
style.map("Accent.TButton",
|
||||
background=[('active', '#6B5D48'), ('pressed', '#6B5D48')])
|
||||
|
||||
# Label styles
|
||||
style.configure("TLabel", background=COLORS['bg_main'], foreground=COLORS['text_dark'], font=("Arial", 10))
|
||||
|
||||
# Entry styles
|
||||
style.configure("TEntry", fieldbackground="white", bordercolor=COLORS['border'])
|
||||
|
||||
# Treeview styles
|
||||
style.configure("Treeview",
|
||||
background="white",
|
||||
foreground=COLORS['text_dark'],
|
||||
fieldbackground="white",
|
||||
borderwidth=0,
|
||||
font=("Arial", 9))
|
||||
style.configure("Treeview.Heading",
|
||||
background=COLORS['primary'],
|
||||
foreground="white",
|
||||
font=("Arial", 10, "bold"))
|
||||
style.map("Treeview.Heading",
|
||||
background=[('active', COLORS['primary_dark'])])
|
||||
|
||||
# Notebook (tabs) styles
|
||||
style.configure("TNotebook", background=COLORS['bg_main'], borderwidth=0)
|
||||
style.configure("TNotebook.Tab",
|
||||
background=COLORS['accent'],
|
||||
foreground=COLORS['text_dark'],
|
||||
padding=[20, 10],
|
||||
font=("Arial", 10))
|
||||
style.map("TNotebook.Tab",
|
||||
background=[('selected', COLORS['primary'])],
|
||||
foreground=[('selected', 'white')],
|
||||
expand=[('selected', [1, 1, 1, 0])])
|
||||
|
||||
self.login_frame()
|
||||
|
||||
def login_frame(self):
|
||||
for w in self.root.winfo_children():
|
||||
w.destroy()
|
||||
frame = ttk.Frame(self.root, padding=20)
|
||||
frame.pack(expand=True)
|
||||
|
||||
ttk.Label(frame, text="Login Duluu...", font=("Arial", 24)).grid(row=0, column=0, columnspan=2, pady=10)
|
||||
# UI STYLING - Main container dengan background Totoro
|
||||
main_container = tk.Frame(self.root, bg=COLORS['bg_main'])
|
||||
main_container.pack(fill='both', expand=True)
|
||||
|
||||
ttk.Label(frame, text="Username:").grid(row=1, column=0, sticky='e', pady=5)
|
||||
# UI STYLING - Center frame untuk login card
|
||||
center_frame = tk.Frame(main_container, bg=COLORS['bg_main'])
|
||||
center_frame.place(relx=0.5, rely=0.5, anchor='center')
|
||||
|
||||
# UI STYLING - Login card dengan shadow effect
|
||||
card = tk.Frame(center_frame, bg='white', relief='flat', borderwidth=0)
|
||||
card.pack(padx=20, pady=20)
|
||||
|
||||
# UI STYLING - Header dengan tema Totoro
|
||||
header_frame = tk.Frame(card, bg=COLORS['primary'], height=100)
|
||||
header_frame.pack(fill='x', pady=(0, 30))
|
||||
|
||||
# UI STYLING - Logo Totoro di atas card
|
||||
try:
|
||||
totoro_img = Image.open("img/totoro_logo.png")
|
||||
totoro_img = totoro_img.resize((100, 100), Image.Resampling.LANCZOS)
|
||||
totoro_photo = ImageTk.PhotoImage(totoro_img)
|
||||
|
||||
self.totoro_logo = 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))
|
||||
|
||||
|
||||
tk.Label(header_frame,
|
||||
text="🌿 TOTORO CAFÉ 🌿",
|
||||
font=("Arial", 24, "bold"),
|
||||
bg=COLORS['primary'],
|
||||
fg='white').pack(pady=20)
|
||||
|
||||
tk.Label(header_frame,
|
||||
text="Selamat Datang di Sistem Manajemen Cafe",
|
||||
font=("Arial", 10),
|
||||
bg=COLORS['primary'],
|
||||
fg='white').pack(pady=(0, 10))
|
||||
|
||||
# UI STYLING - Form container
|
||||
form_frame = tk.Frame(card, bg='white')
|
||||
form_frame.pack(padx=50, pady=20)
|
||||
|
||||
# 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))
|
||||
self.username_var = tk.StringVar()
|
||||
ttk.Entry(frame, textvariable=self.username_var, width=30).grid(row=1, column=1, pady=5)
|
||||
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)
|
||||
|
||||
ttk.Label(frame, text="Password:").grid(row=2, column=0, sticky='e', pady=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))
|
||||
self.password_var = tk.StringVar()
|
||||
ttk.Entry(frame, textvariable=self.password_var, show="*", width=30).grid(row=2, column=1, pady=5)
|
||||
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)
|
||||
|
||||
# TAMBAHAN: Input nama pembeli (untuk role pembeli)
|
||||
ttk.Label(frame, text="Nama Lengkap:", font=("Arial", 9)).grid(row=3, column=0, sticky='e', pady=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')
|
||||
|
||||
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))
|
||||
|
||||
# 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))
|
||||
self.customer_name_var = tk.StringVar()
|
||||
customer_entry = ttk.Entry(frame, textvariable=self.customer_name_var, width=30)
|
||||
customer_entry.grid(row=3, column=1, pady=5)
|
||||
ttk.Label(frame, text="(Khusus untuk Pembeli)", font=("Arial", 7), foreground='gray').grid(row=4, column=1, sticky='w')
|
||||
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)
|
||||
|
||||
# TAMBAHAN BARU: Input nomor meja (untuk role pembeli)
|
||||
ttk.Label(frame, text="Nomor Meja:", font=("Arial", 9)).grid(row=5, column=0, sticky='e', pady=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))
|
||||
self.customer_meja_var = tk.StringVar()
|
||||
meja_entry = ttk.Entry(frame, textvariable=self.customer_meja_var, width=30)
|
||||
meja_entry.grid(row=5, column=1, pady=5)
|
||||
ttk.Label(frame, text="(Khusus untuk Pembeli - Meja 1-10)", font=("Arial", 7), foreground='gray').grid(row=6, column=1, sticky='w')
|
||||
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)
|
||||
|
||||
ttk.Button(frame, text="Login", command=self.handle_login).grid(row=7, column=0, columnspan=2, pady=12)
|
||||
# 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))
|
||||
|
||||
# Hover effect untuk button
|
||||
def on_enter(e):
|
||||
login_btn['background'] = COLORS['primary_dark']
|
||||
def on_leave(e):
|
||||
login_btn['background'] = COLORS['primary']
|
||||
|
||||
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))
|
||||
|
||||
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):
|
||||
@ -1230,23 +1392,74 @@ class App:
|
||||
def dashboard_frame(self):
|
||||
for w in self.root.winfo_children():
|
||||
w.destroy()
|
||||
top = ttk.Frame(self.root)
|
||||
# UI STYLING - Header dashboard dengan tema Totoro
|
||||
top = tk.Frame(self.root, bg=COLORS['primary'], height=60)
|
||||
top.pack(fill='x')
|
||||
|
||||
# Text untuk header
|
||||
if self.session['role'] in ['pembeli', 'user'] and 'customer_name' in self.session:
|
||||
header_text = f"👤 {self.session['customer_name']} | User: {self.session['username']} | Role: {self.session['role']}"
|
||||
else:
|
||||
header_text = f"User: {self.session['username']} | Role: {self.session['role']}"
|
||||
# Left side - User info
|
||||
left_info = tk.Frame(top, bg=COLORS['primary'])
|
||||
left_info.pack(side='left', padx=20, pady=10)
|
||||
|
||||
# UI STYLING - Logo kecil di header
|
||||
try:
|
||||
totoro_header = Image.open("img/totoro_logo.png")
|
||||
totoro_header = totoro_header.resize((40, 40), 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))
|
||||
except:
|
||||
tk.Label(top, text="🌿", font=("Arial", 24), bg=COLORS['primary']).pack(side='left', padx=(20, 5))
|
||||
|
||||
|
||||
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()}"
|
||||
else:
|
||||
header_text = f"👤 {self.session['username']}"
|
||||
subtext = 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(left_info,
|
||||
text=subtext,
|
||||
font=("Arial", 9),
|
||||
bg=COLORS['primary'],
|
||||
fg='white').pack(anchor='w')
|
||||
|
||||
# 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)
|
||||
|
||||
# Hover effect
|
||||
def on_enter(e):
|
||||
logout_btn['background'] = '#6B5D48'
|
||||
def on_leave(e):
|
||||
logout_btn['background'] = COLORS['brown']
|
||||
logout_btn.bind("<Enter>", on_enter)
|
||||
logout_btn.bind("<Leave>", on_leave)
|
||||
|
||||
# UI STYLING - Container untuk tabs
|
||||
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)
|
||||
|
||||
ttk.Label(
|
||||
top,
|
||||
text=header_text,
|
||||
font=("Arial", 12)
|
||||
).pack(side='left', padx=10, pady=6)
|
||||
ttk.Button(top, text="Logout", command=self.logout).pack(side='right', padx=10)
|
||||
main = ttk.Notebook(self.root)
|
||||
main.pack(fill='both', expand=True, padx=10, pady=8)
|
||||
self.tab_menu_manage = ttk.Frame(main)
|
||||
self.tab_menu_view = ttk.Frame(main)
|
||||
self.tab_promo = ttk.Frame(main)
|
||||
@ -4328,8 +4541,8 @@ class App:
|
||||
|
||||
# Build struk string
|
||||
struk = "═════════════════════════════════════════\n"
|
||||
struk += " CAFE TOTORO MANIA\n"
|
||||
struk += " Jl. Raya Kampus No. 123, Surabaya\n"
|
||||
struk += " TOTORO CAFE\n"
|
||||
struk += " Jl. Raya Totoro No. 123, Surabaya\n"
|
||||
struk += " Telp: 031-123456\n"
|
||||
struk += "═════════════════════════════════════════\n\n"
|
||||
struk += f"No. Struk : STR-{tid}-{datetime.now().strftime('%Y%m%d')}\n"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user