lambda/src/ui/editor/member_editor.py

156 lines
5.9 KiB
Python

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"]