import logging import re from typing import Dict, Callable from PySide6.QtGui import QGuiApplication, QAction from PySide6.QtQml import QQmlApplicationEngine from PySide6 import QtWidgets, QtCore from PySide6.QtWidgets import QVBoxLayout, QFormLayout, QLineEdit, QHBoxLayout, QPushButton, QDialog, QMessageBox from models import Member from database.member import create_member, update_member from utils.errors.database import DatabaseError, DatabaseConnectionError, DuplicateEntryError class MemberEditor(QDialog): def __init__(self, member: Member = None, refresh_callback: Callable[[Dict[str, object]], None] = None): super().__init__() self.logger = logging.getLogger(__name__) self.create_layout() self.refresh_callback = refresh_callback if member: self.member_id = member.id self.logger.debug(f"Editing member {member.first_name} {member.last_name}") self.fill_with_existing_data(member) self.create_new = False else: self.logger.debug("Editing a new member") self.create_new = True def create_layout(self): self.setWindowTitle("Members") self.setMinimumWidth(400) # Create main layout self.layout = QVBoxLayout(self) # Form layout for member fields self.form_layout = QFormLayout() # First name field self.first_name_input = QLineEdit() self.form_layout.addRow("First name:", self.first_name_input) # Last name field self.last_name_input = QLineEdit() self.form_layout.addRow("Last name: ", self.last_name_input) # E-mail field self.email_input = QLineEdit() self.form_layout.addRow("E-mail:", self.email_input) # Phone number self.phone_number_input = QLineEdit() self.form_layout.addRow("Phone number:", self.phone_number_input) self.layout.addLayout(self.form_layout) # Buttons self.button_layout = QHBoxLayout() self.save_button = QPushButton("Save") self.save_button.clicked.connect(self.save_member) self.button_layout.addWidget(self.save_button) self.cancel_button = QPushButton("Discard") self.cancel_button.clicked.connect(self.reject) self.button_layout.addWidget(self.cancel_button) self.layout.addLayout(self.button_layout) def fill_with_existing_data(self, member: Member): self.first_name_input.setText(member.first_name) self.last_name_input.setText(member.last_name) self.email_input.setText(member.email) self.phone_number_input.setText(member.phone) def save_member(self): try: member_object = self.parse_inputs() if self.create_new: create_member(member_object) QMessageBox.information(None, "Success", "Member created successfully", QMessageBox.StandardButton.Ok, QMessageBox.StandardButton.NoButton) else: member_object["id"] = self.member_id update_member(member_object) QMessageBox.information(None, "Success", "Member updated successfully", QMessageBox.StandardButton.Ok, QMessageBox.StandardButton.NoButton) if self.refresh_callback: self.refresh_callback(member_object) self.accept() except ValueError as e: QMessageBox.critical(None, "Invalid Input", f"Input validation failed: {e}", QMessageBox.StandardButton.Ok, QMessageBox.StandardButton.NoButton) except DuplicateEntryError as e: QMessageBox.critical(None, f"Duplicate {e.duplicate_entry_name}", f"The {e.duplicate_entry_name} is already in use", QMessageBox.StandardButton.Ok, QMessageBox.StandardButton.NoButton) except DatabaseConnectionError as e: QMessageBox.critical(None, "Connection error", "Could not connect to the database", QMessageBox.StandardButton.Ok) except DatabaseError as e: QMessageBox.critical(None, "Unknown database error", f"Could not save the book because of the following error: {e}", QMessageBox.StandardButton.Ok) def parse_inputs(self) -> Dict: first_name = self.first_name_input.text().strip() if not first_name or len(first_name) > 50: raise ValueError("First name must be non-empty and at most 50 characters long.") last_name = self.last_name_input.text().strip() if not last_name or len(last_name) > 50: raise ValueError("Last name must be non-empty and at most 50 characters long.") email = self.email_input.text().strip() email_regex = r"^[\w\-\.]+@([\w\-]+\.)+[\w\-]{2,}$" if not re.match(email_regex, email): raise ValueError("E-mail address is not in a valid format.") phone_number = self.phone_number_input.text().strip() phone_number_regex = r"(\+\d{1,3})?\d{9}" if not re.match(phone_number_regex, phone_number): raise ValueError("Phone number is not in valid format.") return { "first_name": first_name, "last_name": last_name, "email": email, "phone": phone_number } __all__ = ["MemberEditor"]