Загрузка данных


import tkinter as tk
from tkinter import messagebox

class Slot:

  def __init__(self, slot_id, dt_str):
    self.id = slot_id
    self.datetime = dt_str
    self.status = "Свободен"
    self.client_name = ""

class SlotManagerApp:

  def __init__(self, root):
    self.root = root
    self.root.title("Система записи на приём по слотам времени")
    self.root.geometry("650x450")
    self.root.minsize(600, 400)
    self.slots = []
    self.counter_id = 1
    self.create_widgets()
  def create_widgets(self):
    frame_add = tk.LabelFrame(
        self.root, text=" 1. Создание нового слота ", padx=10, pady=10
    )
    frame_add.pack(fill="x", padx=10, pady=5)

    tk.Label(frame_add, text="Дата и время (ДД.ММ.ГГГГ ЧЧ:ММ):").grid(
        row=0, column=0, sticky="w", padx=5
    )
    self.entry_datetime = tk.Entry(frame_add, width=20)
    self.entry_datetime.grid(row=0, column=1, padx=5)
    self.entry_datetime.insert(0, "01.11.2026 10:00")
    btn_add_slot = tk.Button(
        frame_add,
        text="Добавить слот",
        command=self.add_slot,
        bg="#e1f5fe",
        cursor="hand2",
    )
    btn_add_slot.grid(row=0, column=2, padx=10)
    frame_action = tk.LabelFrame(
        self.root, text=" 2. Управление бронированием ", padx=10, pady=10
    )
    frame_action.pack(fill="x", padx=10, pady=5)
    tk.Label(frame_action, text="ID слота:").grid(
        row=0, column=0, sticky="w", padx=5
    )
    self.entry_slot_id = tk.Entry(frame_action, width=8)
    self.entry_slot_id.grid(row=0, column=1, padx=5)
    tk.Label(frame_action, text="ФИО клиента:").grid(
        row=0, column=2, sticky="w", padx=5
    )
    self.entry_client = tk.Entry(frame_action, width=25)
    self.entry_client.grid(row=0, column=3, padx=5)
    btn_book = tk.Button(
        frame_action,
        text="Записаться",
        command=self.book_slot,
        bg="#e8f5e9",
        cursor="hand2",
    )
    btn_book.grid(row=0, column=4, padx=5)
    btn_cancel = tk.Button(
        frame_action,
        text="Отменить запись",
        command=self.cancel_booking,
        bg="#ffebee",
        cursor="hand2",
    )
    btn_cancel.grid(row=0, column=5, padx=5)
    frame_list = tk.LabelFrame(
        self.root, text=" 3. Расписание и статусы слотов ", padx=10, pady=10
    )
    frame_list.pack(fill="both", expand=True, padx=10, pady=5)
    self.listbox_slots = tk.Listbox(
        frame_list, font=("Courier New", 10), width=75, height=10
    )
    self.listbox_slots.pack(
        side="left", fill="both", expand=True, padx=(0, 5)
    )
    scrollbar = tk.Scrollbar(
        frame_list, orient="vertical", command=self.listbox_slots.yview
    )
    scrollbar.pack(side="right", fill="y")
    self.listbox_slots.config(yscrollcommand=scrollbar.set)
    btn_refresh = tk.Button(
        self.root, text="Обновить список", command=self.refresh_slots_list
    )
    btn_refresh.pack(pady=5)
  def add_slot(self):
    dt_str = self.entry_datetime.get().strip()
    if not dt_str:
      messagebox.showerror(
          "Ошибка", "Поле даты и времени не может быть пустым"
      )
      return
    new_slot = Slot(self.counter_id, dt_str)
    self.slots.append(new_slot)
    self.counter_id += 1
    messagebox.showinfo("Успех", f"Слот №{new_slot.id} успешно добавлен")
    self.refresh_slots_list()
  def book_slot(self):
    try:
      slot_id = int(self.entry_slot_id.get().strip())
    except ValueError:
      messagebox.showerror("Ошибка", "ID слота должен быть целым числом")
      return
    client_name = self.entry_client.get().strip()
    if len(client_name) < 3:
      messagebox.showerror(
          "Ошибка", "ФИО клиента должно содержать не менее 3 символов"
      )
      return
    target_slot = None
    for s in self.slots:
      if s.id == slot_id:
        target_slot = s
        break
    if not target_slot:
      messagebox.showerror("Ошибка", f"Слот с ID {slot_id} не найден")
      return
    if target_slot.status == "Занят":
      messagebox.showwarning(
          "Внимание",
          f"Слот №{slot_id} уже забронирован клиентом: {target_slot.client_name}",
      )
      return
    target_slot.status = "Занят"
    target_slot.client_name = client_name
    messagebox.showinfo("Успех", f"Слот №{slot_id} успешно забронирован")
    self.refresh_slots_list()
  def cancel_booking(self):
    try:
      slot_id = int(self.entry_slot_id.get().strip())
    except ValueError:
      messagebox.showerror("Ошибка", "ID слота должен быть целым числом")
      return
    target_slot = None
    for s in self.slots:
      if s.id == slot_id:
        target_slot = s
        break
    if not target_slot:
      messagebox.showerror("Ошибка", f"Слот с ID {slot_id} не найден")
      return
    if target_slot.status == "Свободен":
      messagebox.showinfo(
          "Информация", f"Слот №{slot_id} уже свободен, отменять нечего"
      )
      return
    target_slot.status = "Свободен"
    target_slot.client_name = ""
    messagebox.showinfo("Успех", f"Запись на слот №{slot_id} отменена")
    self.refresh_slots_list()
  def refresh_slots_list(self):
    self.listbox_slots.delete(0, tk.END)
    if not self.slots:
      self.listbox_slots.insert(
          tk.END, "Расписание пусто. Добавьте первый слот"
      )
      return
    header = f"{'ID':<4} | {'Дата и время':<18} | {'Статус':<10} | {'Клиент'}"
    self.listbox_slots.insert(tk.END, header)
    self.listbox_slots.insert(tk.END, "-" * 60)
    for s in self.slots:
      client_info = s.client_name if s.client_name else "—"
      row = f"{s.id:<4} | {s.datetime:<18} | {s.status:<10} | {client_info}"
      self.listbox_slots.insert(tk.END, row)

if __name__ == "__main__":
  root = tk.Tk()
  app = SlotManagerApp(root)
  root.mainloop()