Files
aza/APP/backup 24.2.26/aza_whatsapp.py
2026-03-25 14:14:07 +01:00

358 lines
13 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: utf-8 -*-
"""
AzA WhatsApp - WhatsApp Integration für Arztpraxis
"""
import os
import sys
import json
import tkinter as tk
from tkinter import ttk, messagebox, scrolledtext
from datetime import datetime
# Konfigurationsdatei
CONFIG_FILENAME = "aza_whatsapp_config.json"
def _config_path():
return os.path.join(os.path.dirname(os.path.abspath(__file__)), CONFIG_FILENAME)
def load_whatsapp_config():
"""Lädt WhatsApp Konfiguration."""
try:
path = _config_path()
if os.path.isfile(path):
with open(path, "r", encoding="utf-8") as f:
return json.load(f)
except Exception:
pass
return {}
def save_whatsapp_config(data):
"""Speichert WhatsApp Konfiguration."""
try:
path = _config_path()
with open(path, "w", encoding="utf-8") as f:
json.dump(data, f, indent=2, ensure_ascii=False)
except Exception:
pass
def _load_font_sizes():
try:
p = os.path.join(os.path.dirname(os.path.abspath(__file__)), "aza_font_sizes.json")
if os.path.isfile(p):
with open(p, "r", encoding="utf-8") as f:
return json.load(f)
except Exception:
pass
return {}
def _save_font_size(key, size):
try:
d = _load_font_sizes()
d[key] = size
p = os.path.join(os.path.dirname(os.path.abspath(__file__)), "aza_font_sizes.json")
with open(p, "w", encoding="utf-8") as f:
json.dump(d, f, indent=2, ensure_ascii=False)
except Exception:
pass
def add_text_font_size_control(parent_frame, text_widget, initial_size=10, label="Aa", bg_color="#F5FCFF", save_key=None):
"""▲▼-Pfeile für Textfeld-Schriftgröße (520pt), unauffällig im Hintergrund."""
if save_key:
saved = _load_font_sizes().get(save_key)
if saved is not None:
initial_size = int(saved)
_size = [max(5, min(20, initial_size))]
_fg = "#8AAFC0"
_fg_hover = "#1a4d6d"
cf = tk.Frame(parent_frame, bg=bg_color, highlightthickness=0, bd=0)
cf.pack(side="right", padx=4)
tk.Label(cf, text=label, font=("Segoe UI", 8), bg=bg_color, fg=_fg).pack(side="left", padx=(0, 1))
size_lbl = tk.Label(cf, text=str(_size[0]), font=("Segoe UI", 8), bg=bg_color, fg=_fg, width=2, anchor="center")
size_lbl.pack(side="left")
def _apply(ns):
ns = max(5, min(20, ns))
_size[0] = ns
size_lbl.configure(text=str(ns))
text_widget.configure(font=("Segoe UI", ns))
if save_key:
_save_font_size(save_key, ns)
text_widget.configure(font=("Segoe UI", _size[0]))
btn_up = tk.Label(cf, text="\u25B2", font=("Segoe UI", 7), bg=bg_color, fg=_fg, cursor="hand2", bd=0, highlightthickness=0)
btn_up.pack(side="left", padx=(2, 0))
btn_down = tk.Label(cf, text="\u25BC", font=("Segoe UI", 7), bg=bg_color, fg=_fg, cursor="hand2", bd=0, highlightthickness=0)
btn_down.pack(side="left")
btn_up.bind("<Button-1>", lambda e: _apply(_size[0] + 1))
btn_down.bind("<Button-1>", lambda e: _apply(_size[0] - 1))
for w in (btn_up, btn_down):
w.bind("<Enter>", lambda e, ww=w: ww.configure(fg=_fg_hover))
w.bind("<Leave>", lambda e, ww=w: ww.configure(fg=_fg))
return _size
class WhatsAppApp:
def __init__(self, root):
self.root = root
self.root.title("AzA WhatsApp")
self.root.geometry("1000x600")
self.root.minsize(800, 500)
# Farben (WhatsApp-ähnlich)
self.bg_dark = "#075E54" # WhatsApp Dunkelgrün
self.bg_medium = "#128C7E" # WhatsApp Mittelgrün
self.bg_light = "#DCF8C6" # WhatsApp Hellgrün (eigene Nachricht)
self.bg_white = "#FFFFFF"
self.bg_chat = "#ECE5DD" # WhatsApp Chat-Hintergrund
self.fg_dark = "#2C3E50"
self.fg_light = "#FFFFFF"
self.root.configure(bg=self.bg_dark)
# Dummy-Daten
self.contacts = [
{"name": "Dr. Müller", "phone": "+41 79 123 45 67", "last_msg": "Termin bestätigt"},
{"name": "Patient Hans", "phone": "+41 78 234 56 78", "last_msg": "Vielen Dank!"},
{"name": "Apotheke Linden", "phone": "+41 44 123 45 67", "last_msg": "Rezept bereit"},
]
self.current_contact = None
self.messages = []
# Gespeicherte Geometrie laden
config = load_whatsapp_config()
saved_geom = config.get("geometry", "")
if saved_geom:
try:
self.root.geometry(saved_geom)
except:
pass
self.root.protocol("WM_DELETE_WINDOW", self._on_close)
self._build_ui()
def _on_close(self):
"""Speichert Geometrie beim Schließen."""
config = load_whatsapp_config()
config["geometry"] = self.root.geometry()
save_whatsapp_config(config)
self.root.destroy()
def _build_ui(self):
"""Baut die Benutzeroberfläche."""
# Toolbar
self._create_toolbar()
# Hauptbereich: 2 Spalten (Kontakte, Chat)
main_paned = ttk.PanedWindow(self.root, orient="horizontal")
main_paned.pack(fill="both", expand=True)
# Linke Spalte: Kontaktliste
left_frame = tk.Frame(main_paned, bg="#FFFFFF", width=300)
main_paned.add(left_frame, weight=1)
# Rechte Spalte: Chat
right_frame = tk.Frame(main_paned, bg=self.bg_chat)
main_paned.add(right_frame, weight=3)
self._create_contact_list(left_frame)
self._create_chat_area(right_frame)
# Statusleiste
self.status_var = tk.StringVar(value="Bereit")
status_bar = tk.Label(
self.root, textvariable=self.status_var,
bg=self.bg_dark, fg=self.fg_light,
font=("Segoe UI", 9), anchor="w", padx=10
)
status_bar.pack(side="bottom", fill="x")
def _create_toolbar(self):
"""Erstellt die Toolbar."""
toolbar = tk.Frame(self.root, bg=self.bg_dark, height=50)
toolbar.pack(side="top", fill="x")
toolbar.pack_propagate(False)
tk.Label(
toolbar, text="💬 WhatsApp", bg=self.bg_dark, fg=self.fg_light,
font=("Segoe UI", 14, "bold")
).pack(side="left", padx=20, pady=10)
btn_frame = tk.Frame(toolbar, bg=self.bg_dark)
btn_frame.pack(side="right", padx=20, pady=10)
self._create_toolbar_button(btn_frame, " Neuer Chat", self._new_chat).pack(side="left", padx=2)
self._create_toolbar_button(btn_frame, "🔍 Suchen", self._search_contacts).pack(side="left", padx=2)
def _create_toolbar_button(self, parent, text, command):
"""Erstellt einen Toolbar-Button."""
btn = tk.Button(
parent, text=text, command=command,
bg=self.bg_medium, fg=self.fg_light,
font=("Segoe UI", 10), relief="flat",
padx=12, pady=6, cursor="hand2"
)
def on_enter(e):
btn.configure(bg="#0E7A6E")
def on_leave(e):
btn.configure(bg=self.bg_medium)
btn.bind("<Enter>", on_enter)
btn.bind("<Leave>", on_leave)
return btn
def _create_contact_list(self, parent):
"""Erstellt die Kontaktliste."""
tk.Label(
parent, text="Chats", bg="#FFFFFF", fg=self.fg_dark,
font=("Segoe UI", 12, "bold"), anchor="w", padx=10
).pack(fill="x", pady=(10, 5))
# Listbox für Kontakte
list_frame = tk.Frame(parent, bg="#FFFFFF")
list_frame.pack(fill="both", expand=True, padx=5, pady=5)
scrollbar = tk.Scrollbar(list_frame)
scrollbar.pack(side="right", fill="y")
self.contact_listbox = tk.Listbox(
list_frame, font=("Segoe UI", 10),
relief="flat", bd=0, highlightthickness=0,
yscrollcommand=scrollbar.set, selectmode="single"
)
self.contact_listbox.pack(side="left", fill="both", expand=True)
scrollbar.config(command=self.contact_listbox.yview)
# Kontakte einfügen
for contact in self.contacts:
display = f"{contact['name']}\n{contact['last_msg']}"
self.contact_listbox.insert("end", display)
self.contact_listbox.insert("end", "") # Trenner
self.contact_listbox.bind("<<ListboxSelect>>", self._on_contact_select)
def _create_chat_area(self, parent):
"""Erstellt den Chat-Bereich."""
# Header
header_frame = tk.Frame(parent, bg="#EDEDED", height=60)
header_frame.pack(fill="x")
header_frame.pack_propagate(False)
self.chat_header_label = tk.Label(
header_frame, text="Wählen Sie einen Chat aus",
bg="#EDEDED", fg=self.fg_dark,
font=("Segoe UI", 12, "bold"), anchor="w", padx=15
)
self.chat_header_label.pack(fill="both", expand=True)
# Chat-Verlauf
chat_scroll_frame = tk.Frame(parent, bg=self.bg_chat)
chat_scroll_frame.pack(fill="both", expand=True, padx=10, pady=10)
chat_header = tk.Frame(chat_scroll_frame, bg=self.bg_chat)
chat_header.pack(fill="x", anchor="w")
self.chat_display = scrolledtext.ScrolledText(
chat_scroll_frame, wrap="word", font=("Segoe UI", 10),
relief="flat", bd=0, bg=self.bg_chat, state="disabled"
)
self.chat_display.pack(fill="both", expand=True)
add_text_font_size_control(chat_header, self.chat_display, initial_size=10, bg_color=self.bg_chat, save_key="whatsapp_chat")
# Eingabe-Bereich
input_frame = tk.Frame(parent, bg="#F0F0F0", height=60)
input_frame.pack(fill="x", padx=10, pady=(0, 10))
input_frame.pack_propagate(False)
self.message_entry = tk.Entry(
input_frame, font=("Segoe UI", 11),
relief="solid", bd=1
)
self.message_entry.pack(side="left", fill="both", expand=True, padx=(5, 5), pady=10)
self.message_entry.bind("<Return>", lambda e: self._send_message())
send_btn = tk.Button(
input_frame, text="📤", command=self._send_message,
bg=self.bg_medium, fg=self.fg_light,
font=("Segoe UI", 14), relief="flat",
width=3, cursor="hand2"
)
send_btn.pack(side="right", padx=(0, 5), pady=10)
def _on_contact_select(self, event):
"""Wird aufgerufen, wenn ein Kontakt ausgewählt wird."""
selection = self.contact_listbox.curselection()
if not selection:
return
idx = selection[0] // 2
if idx < len(self.contacts):
self.current_contact = self.contacts[idx]
self.chat_header_label.config(text=self.current_contact["name"])
self._load_messages()
def _load_messages(self):
"""Lädt Nachrichten für den aktuellen Kontakt."""
# Dummy-Nachrichten
self.messages = [
{"from": "me", "text": "Hallo, wie geht es Ihnen?", "time": "10:30"},
{"from": "them", "text": "Danke, gut! Ich hätte gerne einen Termin.", "time": "10:32"},
{"from": "me", "text": "Gerne, wann passt es Ihnen?", "time": "10:35"},
]
self.chat_display.configure(state="normal")
self.chat_display.delete("1.0", "end")
for msg in self.messages:
if msg["from"] == "me":
self.chat_display.insert("end", f"[{msg['time']}] Sie: {msg['text']}\n\n")
else:
self.chat_display.insert("end", f"[{msg['time']}] {self.current_contact['name']}: {msg['text']}\n\n")
self.chat_display.configure(state="disabled")
self.chat_display.see("end")
def _send_message(self):
"""Sendet eine Nachricht."""
if not self.current_contact:
messagebox.showinfo("Hinweis", "Bitte wählen Sie zuerst einen Chat aus.")
return
text = self.message_entry.get().strip()
if not text:
return
# Nachricht hinzufügen
now = datetime.now().strftime("%H:%M")
self.messages.append({"from": "me", "text": text, "time": now})
self.chat_display.configure(state="normal")
self.chat_display.insert("end", f"[{now}] Sie: {text}\n\n")
self.chat_display.configure(state="disabled")
self.chat_display.see("end")
self.message_entry.delete(0, "end")
self.status_var.set("Nachricht gesendet.")
def _new_chat(self):
"""Startet einen neuen Chat."""
messagebox.showinfo("Neuer Chat", "Neue Chat-Funktion wird in einer zukünftigen Version implementiert.")
def _search_contacts(self):
"""Durchsucht Kontakte."""
messagebox.showinfo("Suchen", "Suchfunktion wird in einer zukünftigen Version implementiert.")
def main():
root = tk.Tk()
app = WhatsAppApp(root)
root.mainloop()
if __name__ == "__main__":
main()