156 lines
5.9 KiB
Python
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"]
|