import tkinter as tk from tkinter import ttk, simpledialog, messagebox from PIL import Image, ImageTk from ttkthemes import ThemedTk import balance from balance import show_balance import json # Lista para mantener un registro de las compras del usuario purchase_history = [] version = "0.7" # Crear la ventana principal root = ThemedTk(theme="arc") root.title("Menú del Restaurante") version_label = tk.Label(root, text=f"Versión: {version}", anchor='w') version_label.pack(side='bottom', fill='x') search_frame = ttk.Frame(root) search_frame.pack() menu_frame = ttk.Frame(root, padding="50") menu_frame.pack() # Lista de menús menus = [ {"nombre": "Pizza", "precio": 10.00, "imagen": Image.open("imagenes/pizza.png").resize((100, 100))}, {"nombre": "Hamburguesa", "precio": 8.50, "imagen": Image.open("imagenes/hamburguesa.png").resize((100, 100))}, {"nombre": "Ensalada", "precio": 7.00, "imagen": Image.open("imagenes/ensalada.png").resize((100, 100))}, {"nombre": "Churro", "precio": 2.00, "imagen": Image.open("imagenes/churro.png").resize((100, 100))}, {"nombre": "Agua", "precio": 5.00, "imagen": Image.open("imagenes/agua.png").resize((100, 100))}, {"nombre": "Coca-Cola", "precio": 5.00, "imagen": Image.open("imagenes/gaseosa.png").resize((100, 100))}, {"nombre": "Capuchino", "precio": 2.00, "imagen": Image.open("imagenes/capuchino.png").resize((100, 100))}, {"nombre": "Filete de Pescado", "precio": 7.00, "imagen": Image.open("imagenes/filetepescado.png").resize((100, 100))} ] # Convertir las imágenes a PhotoImage después de redimensionarlas for menu in menus: menu['imagen'] = ImageTk.PhotoImage(menu['imagen']) # Ordenar la lista de menús por nombre para la búsqueda binaria menus.sort(key=lambda x: x['nombre'].lower()) # Función de búsqueda binaria def binary_search(item_list, item): low = 0 high = len(item_list) - 1 while low <= high: mid = (low + high) // 2 if item_list[mid]['nombre'].lower() == item: return mid elif item_list[mid]['nombre'].lower() < item: low = mid + 1 else: high = mid - 1 return None def add_product_to_menu(nombre, precio, imagen_filename): # Crear los detalles del producto product_details = { "nombre": nombre, "precio": precio, "imagen": imagen_filename, # Guarda la ruta al archivo de la imagen } # Añadir el producto al menú menus.append(product_details) # Guardar el estado de la aplicación def show_menu(): for product_details in menus: # Cargar la imagen desde el archivo product_image = Image.open(product_details["imagen"]) product_details["imagen"] = ImageTk.PhotoImage(product_image) # Mostrar el producto en la interfaz de usuario # ... # Crear un Label para mostrar el saldo del usuario balance_var = tk.StringVar() balance_var.set(f"Saldo: ${balance.get_balance()}") balance_label = ttk.Label(root, textvariable=balance_var, anchor='e') balance_label.pack(side='top', fill='x', anchor='e') def update_balance_label(): # Obtener el saldo actualizado updated_balance = balance.get_balance() # Actualizar la variable balance_var para reflejar el nuevo saldo balance_var.set(f"Saldo: ${updated_balance}") # Pasar la función de actualización a balance.py balance.set_update_callback(update_balance_label) def search(*args): # Limpiar el frame de botones for widget in button_frame.winfo_children(): widget.destroy() # Buscar el producto result = binary_search(menus, search_var.get().lower()) if result is not None: # Si se encuentra el producto, mostrar solo ese producto menu = menus[result] button = ttk.Button(button_frame, text=f"{menu['nombre']} - ${menu['precio']}", image=menu['imagen'], compound='top', command=lambda m=menu: show_details(m)) button.grid(row=0, column=0) # Organizar los botones en filas y columnas button_list.append(button) elif search_var.get() == '': # Si la caja de texto está vacía, mostrar todos los productos for i, menu in enumerate(menus): button = ttk.Button(button_frame, text=f"{menu['nombre']} - ${menu['precio']}", image=menu['imagen'], compound='top', command=lambda m=menu: show_details(m)) button.grid(row=i//3, column=i%3) # Organizar los botones en filas y columnas button_list.append(button) else: print("Producto no encontrado") button_frame.update() canvas.configure(scrollregion=canvas.bbox('all')) # Actualizar el scrollregion del Canvas # Crear una variable de control para la entrada de búsqueda search_var = tk.StringVar() # Crear una entrada de búsqueda search_entry = ttk.Entry(search_frame, textvariable=search_var) search_entry.pack() search_entry.bind('', search) # # Lista para mantener un registro de los productos seleccionados selected_products = [] # Función para mostrar detalles del menú def show_details(menu): quantity = simpledialog.askinteger("Cantidad", "¿Cuántos quieres ordenar?") if quantity is not None and quantity > 0: # Solo añadir el producto si la cantidad es mayor que 0 # Revisar si el producto ya está en la lista de productos seleccionados for product in selected_products: if product['menu']['nombre'] == menu['nombre']: # Si el producto ya está en la lista, sumar la cantidad product['quantity'] += quantity break else: # Si el producto no está en la lista, añadir un nuevo producto selected_products.append({"menu": menu, "quantity": quantity}) # Calcular el precio total basándose en todos los productos seleccionados update_total_price() def update_total_price(): # Calcular el precio total basándose en todos los productos seleccionados total_price = sum(product['menu']['precio'] * product['quantity'] for product in selected_products) total_label['text'] = f"El precio total a pagar es ${total_price}." def update_balance(): # Calcular el precio total basándose en todos los productos seleccionados total_price = sum(product['menu']['precio'] * product['quantity'] for product in selected_products) # Actualizar el saldo del usuario después de cada compra balance.update_balance(total_price) # Actualizar el Label para reflejar el nuevo saldo balance_var.set(f"Saldo: ${balance.get_balance()}") def handle_purchase(): # Crear una nueva ventana para mostrar los detalles de la compra purchase_window = tk.Toplevel(root) purchase_window.title("Detalles de la compra") # Crear un Canvas para los productos seleccionados canvas = tk.Canvas(purchase_window) canvas.pack(side='left', fill='both', expand=True) # Crear una barra de desplazamiento y añadirla al Canvas scrollbar = ttk.Scrollbar(purchase_window, orient='vertical', command=canvas.yview) scrollbar.pack(side='right', fill='y') # Configurar el Canvas para que se desplace con la barra de desplazamiento canvas.configure(yscrollcommand=scrollbar.set) # Crear un Frame dentro del Canvas para contener los detalles de los productos details_frame = ttk.Frame(canvas) canvas.create_window((0, 0), window=details_frame, anchor='nw') column = 0 for i, product in enumerate(selected_products): ttk.Label(details_frame, image=product['menu']['imagen']).grid(row=i*2, column=column) ttk.Label(details_frame, text=f"{product['menu']['nombre']}").grid(row=i*2+1, column=column+1) ttk.Label(details_frame, text=f"Cantidad: {product['quantity']}").grid(row=i*2+2, column=column+1) ttk.Label(details_frame, text=f"Precio: ${product['menu']['precio']}").grid(row=i*2+3, column=column+1) ttk.Button(details_frame, text="Eliminar", command=lambda p=product: remove_product(p, details_frame, purchase_window)).grid(row=i*2+4, column=column+1) if column == 0: column = 2 else: column = 0 # Actualizar el scrollregion del Canvas después de que se hayan añadido los detalles details_frame.update() canvas.configure(scrollregion=canvas.bbox('all')) # Crear un Frame para los botones de confirmación y cancelación button_frame = ttk.Frame(purchase_window) button_frame.pack() # Añadir botones para confirmar o cancelar la compra ttk.Button(button_frame, text="Confirmar compra", command=lambda: confirm_purchase(purchase_window)).grid(row=0, column=0) ttk.Button(button_frame, text="Cancelar compra", command=lambda: cancel_purchase(purchase_window)).grid(row=0, column=1) def remove_product(product, details_frame, purchase_window): # Eliminar el producto de la lista de productos seleccionados selected_products.remove(product) # Actualizar el precio total update_total_price() # Destruir la ventana de compra actual purchase_window.destroy() # Volver a abrir la ventana de compra para reflejar los cambios handle_purchase() def cancel_purchase(purchase_window): # Vaciar la lista de productos seleccionados selected_products.clear() # Actualizar el precio total update_total_price() # Cerrar la ventana de compra purchase_window.destroy() def confirm_purchase(purchase_window): # Calcular el precio total basándose en todos los productos seleccionados total_price = sum(product['menu']['precio'] * product['quantity'] for product in selected_products) # Verificar si el usuario tiene suficiente saldo para realizar la compra if balance.get_balance() < total_price: # Si el usuario no tiene suficiente saldo, mostrar un mensaje de error y no realizar la compra tk.messagebox.showerror(title="Error", message="No tienes suficiente saldo para realizar esta compra. Por favor, recarga tu billetera.") else: # Si el usuario tiene suficiente saldo, proceder con la compra # Descontar el precio total de la compra del saldo del usuario balance.update_balance(-total_price) # Actualizar el Label para reflejar el nuevo saldo en la ventana principal balance_var.set(f"Saldo: ${balance.get_balance()}") tk.messagebox.showinfo(title="Compra", message="¡Gracias por tu compra!") # Añadir la compra al historial de compras purchase_history.append(selected_products.copy()) # Vaciar la lista de productos seleccionados después de la compra selected_products.clear() # Actualizar el precio total update_total_price() # Cerrar la ventana de compra purchase_window.destroy() def show_purchase_history(): # Crear una nueva ventana para mostrar el historial de compras history_window = tk.Toplevel(root) history_window.title("Historial de compras") # Mostrar cada compra en el historial for i, purchase in enumerate(purchase_history): purchase_label = ttk.Label(history_window, text=f"Compra {i+1}:") purchase_label.pack() for product in purchase: product_label = ttk.Label(history_window, text=f"{product['menu']['nombre']} - Cantidad: {product['quantity']} - Precio: ${product['menu']['precio']}") product_label.pack() # Crear un Canvas para los botones del menú canvas = tk.Canvas(menu_frame) canvas.pack(side='left', fill='both', expand=True) # Crear una barra de desplazamiento y añadirla al Canvas scrollbar = ttk.Scrollbar(menu_frame, orient='vertical', command=canvas.yview) scrollbar.pack(side='right', fill='y') # Configurar el Canvas para que se desplace con la barra de desplazamiento canvas.configure(yscrollcommand=scrollbar.set) # Crear un Frame dentro del Canvas para contener los botones button_frame = ttk.Frame(canvas) canvas.create_window((0, 0), window=button_frame, anchor='nw') # Añadir botones al Frame para cada menú button_list = [] for i, menu in enumerate(menus): button = ttk.Button(button_frame, text=f"{menu['nombre']} - ${menu['precio']}", image=menu['imagen'], compound='top', command=lambda m=menu: show_details(m)) button.grid(row=i//3, column=i%3) # Organizar los botones en filas y columnas button_list.append(button) button_frame.update() canvas.configure(scrollregion=canvas.bbox('all')) # Actualizar el scrollregion del Canvas buy_button = ttk.Button(menu_frame, text="Comprar", command=handle_purchase) buy_button.pack() # Crear un botón de billetera wallet_button = ttk.Button(menu_frame, text="Billetera", command=lambda: show_balance(root)) wallet_button.pack() # Crear un Label para mostrar el precio total total_label = ttk.Label(menu_frame, text="") total_label.pack() # Crear un Label para mostrar la imagen del producto image_label = ttk.Label(menu_frame) image_label.pack() # Crear un menú emergente popup = tk.Menu(root, tearoff=0) popup.add_command(label="Ver historial de compras", command=show_purchase_history) popup.add_command(label="Opción 2") popup.add_command(label="Opción 3") def show_popup(event): popup.post(event.x_root, event.y_root) root.bind("", show_popup) root.mainloop()