import flet as ft import requests from config import API_BASE_URL class ClientsPage: def __init__(self, page: ft.Page, dashboard): self.page = page self.dashboard = dashboard self.clients = [] self.dialog = None self.name = ft.TextField( label="Name", expand=True, input_filter=ft.InputFilter( allow=True, regex_string=r"^[\x20-\x7E]*$", replacement_string="" ), ) self.address = None self.street_and_number = ft.TextField( label="Street and number", input_filter=ft.InputFilter( allow=True, regex_string=r"^[\x20-\x7E]*$", replacement_string="" ), ) self.postal_code = ft.TextField( label="Postal code", input_filter=ft.InputFilter( allow=True, regex_string=r"^[\x20-\x7E]*$", replacement_string="" ), ) self.city = ft.TextField( label="City", input_filter=ft.InputFilter( allow=True, regex_string=r"^[\x20-\x7E]*$", replacement_string="" ), ) self.region_county = ft.TextField( label="Region / County", input_filter=ft.InputFilter( allow=True, regex_string=r"^[\x20-\x7E]*$", replacement_string="" ), ) self.country = ft.TextField( label="Country", input_filter=ft.InputFilter( allow=True, regex_string=r"^[\x20-\x7E]*$", replacement_string="" ), ) self.register_number = ft.TextField( label="Register Number", expand=True, input_filter=ft.InputFilter( allow=True, regex_string=r"^[\x20-\x7E]*$", replacement_string="" ), ) self.vat = ft.TextField( label="VAT", expand=True, input_filter=ft.InputFilter( allow=True, regex_string=r"^[\x20-\x7E]*$", replacement_string="" ), ) self.contact_person = ft.TextField( label="Contact Person", expand=True, input_filter=ft.InputFilter( allow=True, regex_string=r"^[\x20-\x7E]*$", replacement_string="" ), ) self.phone = ft.TextField( label="Phone", expand=True, input_filter=ft.InputFilter( allow=True, regex_string=r"^[\x20-\x7E]*$", replacement_string="" ), ) self.email = ft.TextField( label="Email", expand=True, input_filter=ft.InputFilter( allow=True, regex_string=r"^[\x20-\x7E]*$", replacement_string="" ), ) self.selected_client_id = None self.clients_list = ft.ListView(expand=True, spacing=10) self.dialog = ft.AlertDialog( modal=True, title=ft.Text("Client Details"), content=ft.Column( controls=[ self.name, self.register_number, self.vat, self.contact_person, self.phone, self.email, self.street_and_number, self.postal_code, self.city, self.region_county, self.country, ], width=600 ), actions=[ ft.TextButton("Cancel", on_click=self.on_cancel_btn_click), ft.ElevatedButton("Save", on_click=self.submit_client) ] ) self.confirm_dialog = ft.AlertDialog( modal=True, title=ft.Text("Delete Client"), content=ft.Text("Are you sure you want to delete this client?"), actions=[ ft.TextButton("Cancel", on_click=lambda e: self.page.close(self.confirm_dialog)), ft.ElevatedButton("Delete", on_click=self.confirm_delete) ] ) self.client_id_to_delete = None self.subscription_error = ft.Text("Please subscribe to add new client", color=ft.Colors.RED) def load_clients(self): try: token = self.page.client_storage.get("token") headers = {"Authorization": f"Bearer {token}"} response = requests.get(f"{API_BASE_URL}/clients/", headers=headers) if response.status_code == 200: self.clients = response.json() self.refresh_clients_list() except Exception as e: print("Error loading clients:", e) def refresh_clients_list(self): self.clients_list.controls.clear() for client in self.clients: self.clients_list.controls.append( ft.Container( content=ft.Row( [ ft.Column([ ft.Text(client["name"], size=16, weight=ft.FontWeight.BOLD), ft.Text(client["register_number"], size=12, italic=True) ], expand=True), ft.Row([ ft.IconButton(icon=ft.Icons.EDIT, on_click=lambda e, c=client: self.open_dialog(c)), ft.IconButton(icon=ft.Icons.DELETE, on_click=lambda e, cid=client["id"]: self.delete_client(cid)), ]) ], alignment=ft.MainAxisAlignment.SPACE_BETWEEN ), padding=10, border=ft.border.all(1, ft.Colors.GREY_300), border_radius=10, bgcolor=ft.Colors.BLUE_50, expand=True ) ) self.page.update() def open_dialog(self, client=None): if client: self.selected_client_id = client["id"] self.name.value = client["name"] self.street_and_number.value = client["address"].split(" %")[0] self.postal_code.value = client["address"].split(" %")[1] self.city.value = client["address"].split(" %")[2] self.region_county.value = client["address"].split(" %")[3] self.country.value = client["address"].split(" %")[4] self.register_number.value = client["register_number"] self.contact_person.value = client["contact_person"] self.phone.value = client["phone"] self.email.value = client["email"] self.vat.value = client['vat'] else: self.selected_client_id = None self.name.value = "" self.street_and_number.value = "" self.postal_code.value = "" self.city.value = "" self.region_county.value = "" self.country.value = "" self.register_number.value = "" self.contact_person.value = "" self.phone.value = "" self.email.value = "" self.vat.value = "" self.page.open(self.dialog) self.page.update() def submit_client(self, e): user_id = self.page.session.get("user_id") address = f'{self.street_and_number.value} %{self.postal_code.value} %{self.city.value} %{self.region_county.value} %{self.country.value}' client_data = { "name": self.name.value, "address": address, "register_number": self.register_number.value, "vat": self.vat.value, "contact_person": self.contact_person.value, "phone": self.phone.value, "email": self.email.value, "user_id": user_id, } try: headers = {"Authorization": f"Bearer {self.page.client_storage.get('token')}"} if self.selected_client_id: requests.put(f"{API_BASE_URL}/clients/{self.selected_client_id}", json=client_data, headers=headers) else: requests.post(f"{API_BASE_URL}/clients/", json=client_data, headers=headers) self.page.close(self.dialog) self.load_clients() self.page.snack_bar = ft.SnackBar(ft.Text("Client saved successfully.")) self.page.snack_bar.open = True self.page.update() except Exception as e: print("Error submitting client:", e) def on_cancel_btn_click(self, e): self.page.close(self.dialog) def delete_client(self, client_id): self.client_id_to_delete = client_id self.page.open(self.confirm_dialog) self.page.update() def confirm_delete(self, e): try: headers = {"Authorization": f"Bearer {self.page.client_storage.get('token')}"} requests.delete(f"{API_BASE_URL}/clients/{self.client_id_to_delete}", headers=headers) self.page.close(self.confirm_dialog) self.load_clients() except Exception as ex: print("Error deleting client:", ex) def get_current_subscription_plan(self): try: token = self.page.client_storage.get("token") headers = {"Authorization": f"Bearer {token}"} response = requests.get(f"{API_BASE_URL}/subscription/", headers=headers) #print(response.text) return response.json()[-1] if response.status_code == 200 else None except Exception as e: print("Error loading subscription:", e) def build(self): self.load_clients() self.subscription = self.get_current_subscription_plan() self.add_client_btn = ft.ElevatedButton("New Client", icon=ft.Icons.ADD, on_click=lambda e: self.open_dialog()) self.header = ft.Row( [ ft.Text("Clients", size=24, weight=ft.FontWeight.BOLD), ], alignment=ft.MainAxisAlignment.SPACE_BETWEEN ) if self.subscription: if self.subscription['status'] != 'expired': self.header.controls.append(self.add_client_btn) else: self.header.controls.append(self.subscription_error) else: self.header.controls.append(self.subscription_error) return ft.Container( content=ft.Column( [ self.header, self.clients_list ], expand=True ), expand=True, )