from PyQt6.QtWidgets import QLabel, QListWidget, QListWidgetItem from PyQt6 import QtCore from gui.v2.ui.pages.Page import Page from gui.v2.ui.styles.styles import TERMINAL_LIST_QSS from gui.v2.workers.ticketing_worker_thread import TicketingWorkerThread class PlanPickerPage(Page): def __init__(self, page_stack, main_window=None, parent=None): super().__init__("PickPlan", page_stack, main_window, parent) self.update_status = main_window self.pricing_data = None self.worker = None self.title.setText("Pick a Plan") self.title.setGeometry(QtCore.QRect(290, 30, 220, 40)) self.title.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) self.button_reverse.setVisible(True) self.button_reverse.clicked.connect(self.reverse) self.intro_label = QLabel( "All members of the group expire at the same time. How much you pay depends on when you join.", self) self.intro_label.setGeometry(40, 90, 720, 40) self.intro_label.setStyleSheet("color: white; font-size: 13px;") self.intro_label.setWordWrap(True) self.intro_label.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) self.plan_list = QListWidget(self) self.plan_list.setGeometry(60, 140, 680, 320) self.plan_list.setStyleSheet(TERMINAL_LIST_QSS) self.plan_list.itemClicked.connect(self.on_plan_clicked) self.status_label = QLabel("", self) self.status_label.setGeometry(60, 470, 680, 30) self.status_label.setStyleSheet("color: #cccccc; font-size: 13px;") self.status_label.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter) def start_sync(self): self.plan_list.clear() self.status_label.setText("Syncing prices...") self.update_status.update_status("Syncing ticket prices...") self.worker = TicketingWorkerThread('SYNC_PRICES') self.worker.sync_done.connect(self.on_sync_done) self.worker.error.connect(self.on_error) self.worker.start() def on_sync_done(self, pricing_data): if isinstance(pricing_data, dict) and pricing_data.get('valid') is False: err = pricing_data.get('error_code', 'unknown') self.status_label.setText(f"Sync failed: {err}") self.update_status.update_status(f"Sync failed: {err}") return if isinstance(pricing_data, dict) and isinstance(pricing_data.get('data'), dict): plans = pricing_data['data'] elif isinstance(pricing_data, dict): plans = pricing_data else: self.status_label.setText("Unexpected pricing data.") return self.pricing_data = plans self.populate_plans(plans) self.status_label.setText("Pick a plan above.") self.update_status.update_status("Plans loaded.") def populate_plans(self, pricing_data): self.plan_list.clear() if not isinstance(pricing_data, dict): self.status_label.setText("Unexpected pricing data.") return for plan_key, plan_data in pricing_data.items(): if not isinstance(plan_data, dict): continue cost = plan_data.get('cost', '?') months = plan_data.get('months', '?') days = plan_data.get('days', '?') profiles = plan_data.get('profiles', '?') label = f" Plan {plan_key} | €{cost} | {months}months {days}d left | {profiles} profiles" item = QListWidgetItem(label) item.setData(QtCore.Qt.ItemDataRole.UserRole, plan_key) self.plan_list.addItem(item) def on_plan_clicked(self, item): plan_key = item.data(QtCore.Qt.ItemDataRole.UserRole) if not plan_key: return self.custom_window.navigator.navigate("ticket_crypto_picker") crypto_page = self.custom_window.navigator.get_cached("ticket_crypto_picker") if crypto_page is not None: crypto_page.set_selected_plan(plan_key) def on_error(self, msg): self.status_label.setText(f"Error: {msg}") self.update_status.update_status(f"Sync error: {msg}") def reverse(self): self.custom_window.navigator.navigate("id")