import flet as ft import requests from helpers.payment_type import PaymentType class PaymentAndSubscription: def __init__(self, page: ft.Page): self.page = page self.base_url = self.page.session.store.get('api_base_url') self.token = self.page.session.store.get('token') self.selected_payment_id = None self.selected_sub_id = None self.payment_type = [ PaymentType().ONE_TIME_ONLY, PaymentType().SUBSCRIPTION.lower() ] # Pre-fetch data as in users.py self.all_payments = self.get_payments_data() self.all_subscriptions = self.get_subscriptions_data() self.name = ft.TextField(label = "Denumire") self.amount = ft.TextField(label="Valoare", suffix="Lei") self.type = ft.RadioGroup( content=ft.Row( [ft.Radio(value=payment, label=payment.upper()) for payment in self.payment_type] ) ) self.error_text = ft.Text(color=ft.Colors.RED) self.payments_list = ft.ListView( controls=self.create_payment_list(self.all_payments, self.on_edit_payment_click), spacing=10, expand=True, padding=10 ) # Elemente pentru Abonamente self.sub_name = ft.TextField(label="Nume Abonament", width=350) self.payment_dropdown = ft.Dropdown( label="Selecteaza Plata", width=350, options=[ ft.dropdown.Option(key=str(p['id']), text=f"{p['name']} ({p['amount']} Lei)") for p in self.all_payments if p['type'].lower() == self.payment_type[1].lower() ] ) self.months_dropdown = ft.Dropdown( label="Numar luni", width=350, options=[ft.dropdown.Option(str(i)) for i in range(1, 13)] ) self.sub_error_text = ft.Text(color=ft.Colors.RED) self.subs_list = ft.ListView( controls=self.create_subscription_list(self.all_subscriptions, self.on_edit_sub_click), spacing=10, expand=True, padding=10 ) self.add_payment_dialog = ft.AlertDialog( title=ft.Text("Detalii Plata"), content=ft.Column( [ self.name, self.amount, ft.Text("Tip plata:", weight=ft.FontWeight.BOLD), self.type, self.error_text ], height=250, tight=True ), actions=[ ft.FilledButton("Salveaza", on_click=self.on_save_btn_click), ft.FilledButton("Cancel", on_click=self.on_cancel_btn_click, bgcolor=ft.Colors.GREY) ] ) self.add_sub_dialog = ft.AlertDialog( title=ft.Text("Detalii Abonament"), content=ft.Column( [ self.sub_name, self.payment_dropdown, self.months_dropdown, self.sub_error_text ], height=280, tight=True ), actions=[ ft.FilledButton("Salveaza", on_click=self.on_save_sub_click), ft.FilledButton("Cancel", on_click=self.on_cancel_btn_click, bgcolor=ft.Colors.GREY) ] ) # --- LOGICA PLATI --- def add_new_payment_btn_click(self, e): self.selected_payment_id = None self.name.value = '' self.amount.value = '' self.type.value = None self.error_text.value = '' self.add_payment_dialog.title = ft.Text("Adauga plata noua") self.page.show_dialog(self.add_payment_dialog) self.page.update() def on_edit_payment_click(self, payment): self.selected_payment_id = payment['id'] self.name.value = payment['name'] self.amount.value = str(payment['amount']) self.type.value = payment['type'] self.error_text.value = '' self.add_payment_dialog.title = ft.Text("Editeaza plata") self.page.show_dialog(self.add_payment_dialog) self.page.update() def get_payments_data(self): try: response = requests.get( f"{self.base_url}/payments/", headers={'Authorization': f'Bearer {self.token}'} ) if response.status_code == 200: return response.json() except Exception as e: print(f"Error fetching payments: {e}") return [] def get_payments(self): self.all_payments = self.get_payments_data() self.payments_list.controls = self.create_payment_list(self.all_payments, self.on_edit_payment_click) if self.payments_list.page: self.payments_list.update() # Actualizăm și opțiunile dropdown-ului pentru abonamente self.payment_dropdown.options = [ ft.dropdown.Option(key=str(p['id']), text=f"{p['name']} ({p['amount']} Lei)") for p in self.all_payments if p['type'].lower() == self.payment_type[1].lower() ] if self.payment_dropdown.page: self.payment_dropdown.update() def create_payment_list(self, items, on_click_handler): return [ ft.Container( content=ft.Row( [ ft.Column( [ ft.Text(p['name'], weight=ft.FontWeight.BOLD), ft.Text(f"{p['amount']} Lei - {p['type'].upper()}", size=12), ], alignment=ft.MainAxisAlignment.CENTER, ), ft.IconButton( icon=ft.Icons.EDIT, on_click=lambda e, payment=p: on_click_handler(payment) ) ], alignment=ft.MainAxisAlignment.SPACE_BETWEEN ), bgcolor=ft.Colors.BLUE_50, padding=10, border_radius=8, border=ft.Border.all(1, ft.Colors.GREY_300), ink=True ) for p in items ] def on_save_btn_click(self, e): if not self.name.value or not self.amount.value or not self.type.value: self.error_text.value = "Toate campurile sunt obligatorii!" self.error_text.update() return print(self.amount.value) try: payload = { "name": self.name.value, "amount": float(self.amount.value), "type": self.type.value } if self.selected_payment_id: # Update url = f"{self.base_url}/payments/update/{self.selected_payment_id}" response = requests.put(url, json=payload, headers={'Authorization': f'Bearer {self.token}'}) else: # Create url = f"{self.base_url}/payments/add" response = requests.post(url, json=payload, headers={'Authorization': f'Bearer {self.token}'}) if response.status_code in [200, 201]: self.page.pop_dialog() self.get_payments() else: self.error_text.value = "Eroare la salvare" self.error_text.update() except Exception as e: print(e) self.error_text.value = "Valoarea trebuie sa fie un numar!" self.error_text.update() # --- LOGICA ABONAMENTE --- def add_new_sub_btn_click(self, e): self.selected_sub_id = None self.sub_name.value = "" # Resetăm dropdown-urile la starea default (fără selecție) self.payment_dropdown.value = "" self.months_dropdown.value = "" self.sub_error_text.value = "" self.add_sub_dialog.title = ft.Text("Adauga Abonament Nou") # Forțăm afișarea dialogului cu valorile proaspăt resetate self.page.show_dialog(self.add_sub_dialog) self.page.update() def on_edit_sub_click(self, sub): self.selected_sub_id = sub['id'] self.sub_name.value = sub['name'] self.payment_dropdown.value = str(sub['pay_and_subs_id']) self.months_dropdown.value = str(sub['mounts']) self.sub_error_text.value = "" self.add_sub_dialog.title = ft.Text("Editeaza Abonament") self.page.show_dialog(self.add_sub_dialog) self.page.update() def get_subscriptions_data(self): try: response = requests.get( f"{self.base_url}/subscriptions/", headers={'Authorization': f'Bearer {self.token}'} ) if response.status_code == 200: return response.json() except Exception as e: print(f"Error fetching subscriptions: {e}") return [] def get_subscriptions(self): self.all_subscriptions = self.get_subscriptions_data() self.subs_list.controls = self.create_subscription_list(self.all_subscriptions, self.on_edit_sub_click) if self.subs_list.page: self.subs_list.update() def create_subscription_list(self, items, on_click_handler): controls = [] for s in items: # Gasim plata asociata pentru a calcula totalul payment = next((p for p in self.all_payments if p['id'] == s['pay_and_subs_id']), None) amount = payment['amount'] if payment else 0 total = amount * (s['mounts'] or 0) controls.append( ft.Container( content=ft.Row( [ ft.Column( [ ft.Text(s['name'], weight=ft.FontWeight.BOLD), ft.Text(f"{s['mounts']} luni x {amount} Lei = {total} Lei Total", size=12, color=ft.Colors.BLUE_700), ], alignment=ft.MainAxisAlignment.CENTER, ), ft.IconButton( icon=ft.Icons.EDIT, on_click=lambda e, sub=s: on_click_handler(sub) ) ], alignment=ft.MainAxisAlignment.SPACE_BETWEEN ), bgcolor=ft.Colors.GREEN_50, padding=10, border_radius=8, border=ft.Border.all(1, ft.Colors.GREEN_200), ink=True ) ) return controls def on_save_sub_click(self, e): if not self.sub_name.value or not self.payment_dropdown.value or not self.months_dropdown.value: self.sub_error_text.value = "Toate campurile sunt obligatorii!" self.sub_error_text.update() return payload = { "name": self.sub_name.value, "pay_and_subs_id": int(self.payment_dropdown.value), "mounts": int(self.months_dropdown.value) } if self.selected_sub_id: url = f"{self.base_url}/subscriptions/update/{self.selected_sub_id}" response = requests.put(url, json=payload, headers={'Authorization': f'Bearer {self.token}'}) else: url = f"{self.base_url}/subscriptions/add" response = requests.post(url, json=payload, headers={'Authorization': f'Bearer {self.token}'}) if response.status_code in [200, 201]: self.page.pop_dialog() self.get_subscriptions() else: self.sub_error_text.value = "Eroare la salvare abonament" self.sub_error_text.update() def on_cancel_btn_click(self, e): self.page.pop_dialog() def build(self): return ft.Container( content=ft.Row( [ # Coloana Stanga: Plati ft.Column( [ ft.Row([ ft.Text("Configurare Plati", size=18, weight=ft.FontWeight.BOLD), ft.IconButton(ft.Icons.ADD_CIRCLE, on_click=self.add_new_payment_btn_click, icon_color=ft.Colors.BLUE) ], alignment=ft.MainAxisAlignment.SPACE_BETWEEN), ft.Divider(), self.payments_list ], expand=1 ), ft.VerticalDivider(width=1), # Coloana Dreapta: Abonamente ft.Column( [ ft.Row([ ft.Text("Gestiune Abonamente", size=18, weight=ft.FontWeight.BOLD), ft.IconButton(ft.Icons.ADD_TASK, on_click=self.add_new_sub_btn_click, icon_color=ft.Colors.GREEN) ], alignment=ft.MainAxisAlignment.SPACE_BETWEEN), ft.Divider(), self.subs_list ], expand=1 ) ], expand=True ), expand=True, padding=20 )