import flet as ft import datetime import requests import time from pages.view_page import ViewPage #from pages.archive_page import ArchivePage from config import API_BASE_URL import logging class OrdersEditPage: def __init__(self, page: ft.Page, dashbaord, archive_page): self.page = page self.dashboard = dashbaord self.archive_page = archive_page self.order_id = self.page.session.get('order_id') self.order = self.get_order() print('Edit order') #print(self.order_id) #print(self.order) #print(type(self.order_id)) self.selected_client_id = self.order['client_id'] self.all_clients = self.get_all_clients() self.filtered_clients = self.all_clients.copy() self.client_search_field = ft.TextField(label="Search Clients...", on_change=self.on_searching_client) self.client_results = ft.Column( spacing=10, controls=[ ft.Container( content=ft.Row( controls=[ft.Text(client["name"], expand=True)], expand=True ), bgcolor=ft.Colors.BLUE_100 if client["id"] == self.selected_client_id else ft.Colors.BLUE_50, padding=10, ink=True, on_click=lambda e, c=client: self.on_client_selected(e, c), border=ft.border.all(1, ft.Colors.GREY_300), border_radius=10, expand=True ) for client in self.all_clients ] ) for client in self.all_clients: if client["id"] == self.selected_client_id: self.client_search_field.value = client['name'] self.all_transporters = self.get_all_transporters() self.filtered_transporters = self.all_transporters.copy() self.selected_transporter_id = self.order['transporter_id'] self.transporter_search_field = ft.TextField(label="Search Transporters...", on_change=self.on_searching_transporter) self.transporter_results = ft.Column( spacing=10, controls=[ ft.Container( content=ft.Row( controls=[ft.Text(transporter["name"], expand=True)], expand=True ), bgcolor=ft.Colors.BLUE_100 if transporter["id"] == self.selected_transporter_id else ft.Colors.BLUE_50, padding=10, ink=True, on_click=lambda e, t=transporter: self.on_transporter_selected(e, t), border=ft.border.all(1, ft.Colors.GREY_300), border_radius=10, expand=True ) for transporter in self.all_transporters ] ) for transporter in self.all_transporters: if transporter["id"] == self.selected_transporter_id: self.transporter_search_field.value = transporter['name'] self.all_addresses = self.get_all_addresses() self.selected_loading_address_id = None self.filtered_addresses = self.all_addresses.copy() self.loading_address_search_field = ft.TextField(label="Search Loading Address...", on_change=self.on_searching_loading_address) self.loading_address_results = ft.Column( spacing=10, controls=[ ft.Container( content=ft.Row( controls=[ ft.Text(address["name"], expand=True), ft.IconButton(icon=ft.Icons.LOCATION_PIN, on_click=lambda e, t=address: self.on_location_btn_click(t)) ], expand=True ), bgcolor=ft.Colors.BLUE_50, padding=10, ink=True, on_click=lambda e, t=address: self.on_loading_address_selected(e, t), border=ft.border.all(1, ft.Colors.GREY_300), border_radius=10, expand=True ) for address in self.all_addresses ] ) self.loading_informations = ft.TextField( label="Loading Instructions", min_lines=3, max_lines=7, multiline=True, input_filter=ft.InputFilter( allow=True, regex_string=r"^[\x20-\x7E]*$", replacement_string="" ), ) self.loading_date = ft.TextField(label="Date", expand=True, read_only=True) self.loading_hour = ft.TextField(label="Hour", expand=True, read_only=True) self.loading = ft.ListView( spacing=10, ) self.selected_unloading_address_id = None self.filtered_addresses_ul = self.all_addresses.copy() self.unloading_address_search_field = ft.TextField(label="Search Unloading Address...", on_change=self.on_searching_unloading_address) self.unloading_address_results = ft.Column( spacing=10, controls=[ ft.Container( content=ft.Row( controls=[ ft.Text(address["name"], expand=True), ft.IconButton(icon=ft.Icons.LOCATION_PIN, on_click=lambda e, t=address: self.on_location_btn_click(t)) ], expand=True ), bgcolor=ft.Colors.BLUE_50, padding=10, ink=True, on_click=lambda e, t=address: self.on_unloading_address_selected(e, t), border=ft.border.all(1, ft.Colors.GREY_300), border_radius=10, expand=True ) for address in self.all_addresses ] ) self.unloading_informations = ft.TextField( label="Unloading Instructions", min_lines=3, max_lines=7, multiline=True, input_filter=ft.InputFilter( allow=True, regex_string=r"^[\x20-\x7E]*$", replacement_string="" ), ) self.unloading_date = ft.TextField(label="Date", expand=True, read_only=True) self.unloading_hour = ft.TextField(label="Hour", expand=True, read_only=True) self.unloading = ft.ListView( spacing=10, ) self.ldm_quantity = ft.TextField( expand=True, keyboard_type=ft.KeyboardType.NUMBER, input_filter=ft.InputFilter(allow=True, regex_string=r"^[0-9]*\.?[0-9]*$", replacement_string=""), value=self.order['ldb_quantity'] ) self.kg_quantity = ft.TextField( expand=True, keyboard_type=ft.KeyboardType.NUMBER, input_filter=ft.InputFilter(allow=True, regex_string=r"^[0-9]*\.?[0-9]*$", replacement_string=""), value=self.order['kg_quantity'] ) self.track_reg_number = ft.TextField( label="Track Reg. Number", input_filter=ft.InputFilter( allow=True, regex_string=r"^[\x20-\x7E]*$", replacement_string="" ), value=self.order['track_reg_number'] ) self.trailer_reg_number = ft.TextField( label="Trailer Reg. Number", input_filter=ft.InputFilter( allow=True, regex_string=r"^[\x20-\x7E]*$", replacement_string="" ), value=self.order['trailer_reg_number'] ) self.received_price = ft.TextField( label="Price Received - visible only to you!", keyboard_type=ft.KeyboardType.NUMBER, input_filter=ft.InputFilter(allow=True, regex_string=r"^[0-9]*\.?[0-9]*$", replacement_string=""), value=self.order['received_price'] ) self.paid_price = ft.TextField( label="Price Paid", keyboard_type=ft.KeyboardType.NUMBER, input_filter=ft.InputFilter(allow=True, regex_string=r"^[0-9]*\.?[0-9]*$", replacement_string=""), value = self.order['paid_price'] ) self.first_order_number = self.page.session.get("first_order_number") last_orders = self.load_orders() if len(last_orders) == 0: number = f'First Order: {self.first_order_number}' else: ln = last_orders[0]['order_number'] #print(last_orders) number = f'Last used: {ln}' self.order_number = ft.TextField( label=f"{number}", input_filter=ft.InputFilter( allow=True, regex_string=r"^[\x20-\x7E]*$", replacement_string="" ), value = self.order['order_number'] ) self.error_message = ft.Text(color = ft.Colors.RED) self.loading_query = [] self.loading_error_message = ft.Text(color= ft.Colors.RED) self.unloading_query = [] self.unloading_error_message = ft.Text(color= ft.Colors.RED) self.product_description= ft.TextField( label="Description", multiline=True, min_lines=3, max_lines=5, input_filter=ft.InputFilter( allow=True, regex_string=r"^[\x20-\x7E]*$", replacement_string="" ), value=self.order['products_description'] ) #add loading points self.init_loading_query = self.order['loading_points'] addresses = [] for init_addr in self.init_loading_query: for all_addr in self.all_addresses: if init_addr['destination_id'] == all_addr['id']: adr = '' street_and_number = all_addr["address"].split(" %")[0] postal_code = all_addr["address"].split(" %")[1] city = all_addr["address"].split(" %")[2] region_county = all_addr["address"].split(" %")[3] country = all_addr["address"].split(" %")[4] if len(street_and_number) > 0: adr += street_and_number +', ' if len(postal_code) > 0: adr += postal_code +', ' if len(city) > 0: adr += city +', ' if len(region_county) > 0: adr += region_county +', ' if len(country) > 0: adr += country address = { 'loading_address_id': init_addr['destination_id'], 'loading_address_name': all_addr['name'], 'loading_address': adr, 'loading_date': init_addr['point_data'], 'loading_hour': init_addr['point_hour'], 'loading_informatins': init_addr['informatins'] } addresses.append(address) break self.loading_query = addresses self.loading.controls = self.create_loading_list(addresses, self.on_delete_loading_address_btn_click) #add unloading points self.init_unloading_query = self.order['unloading_points'] addresses = [] for init_addr in self.init_unloading_query: for all_addr in self.all_addresses: if init_addr['destination_id'] == all_addr['id']: adr = '' street_and_number = all_addr["address"].split(" %")[0] postal_code = all_addr["address"].split(" %")[1] city = all_addr["address"].split(" %")[2] region_county = all_addr["address"].split(" %")[3] country = all_addr["address"].split(" %")[4] if len(street_and_number) > 0: adr += street_and_number +', ' if len(postal_code) > 0: adr += postal_code +', ' if len(city) > 0: adr += city +', ' if len(region_county) > 0: adr += region_county +', ' if len(country) > 0: adr += country address = { 'unloading_address_id': init_addr['destination_id'], 'unloading_address_name': all_addr['name'], 'unloading_address': adr, 'unloading_date': init_addr['point_data'], 'unloading_hour': init_addr['point_hour'], 'unloading_informatins': init_addr['informatins'] } addresses.append(address) break self.unloading_query = addresses self.unloading.controls = self.create_unloading_list(addresses, self.on_delete_unloading_address_btn_click) def get_order(self): try: token = self.page.client_storage.get("token") headers = {"Authorization": f"Bearer {token}"} type(self.order_id) response = requests.get(f"{API_BASE_URL}/orders/{self.order_id}", headers=headers) return response.json() if response.status_code == 200 else [] except Exception as e: print("Error loading orders:", e) def load_orders(self): try: token = self.page.client_storage.get("token") headers = {"Authorization": f"Bearer {token}"} response = requests.get(f"{API_BASE_URL}/orders/list", headers=headers) return response.json() if response.status_code == 200 else [] except Exception as e: print("Error loading orders:", e) def on_location_btn_click(self, destination): query = destination["address"].replace(", ", "+") maps_url = f"https://www.google.com/maps/search/?api=1&query={query}" self.page.launch_url(maps_url) def on_searching_client(self, e): query = e.control.value.lower() self.filtered_clients = [client for client in self.all_clients if query in client["name"].lower()] self.update_client_list(self.filtered_clients) def init_search_client(self): query = self.client_search_field.value.lower() self.filtered_clients = [client for client in self.all_clients if query in client["name"].lower()] self.client_results.controls.clear() for client in self.filtered_clients: self.client_results.controls.append( ft.Container( content=ft.Row( controls=[ft.Text(client["name"], expand=True)], expand=True ), bgcolor=ft.Colors.BLUE_100 if client["id"] == self.selected_client_id else ft.Colors.BLUE_50, padding=10, ink=True, on_click=lambda e, c=client: self.on_client_selected(e, c), border=ft.border.all(1, ft.Colors.GREY_300), border_radius=10, expand=True ) ) def update_client_list(self, clients): self.client_results.controls.clear() for client in clients: self.client_results.controls.append( ft.Container( content=ft.Row( controls=[ft.Text(client["name"], expand=True)], expand=True ), bgcolor=ft.Colors.BLUE_100 if client["id"] == self.selected_client_id else ft.Colors.BLUE_50, padding=10, ink=True, on_click=lambda e, c=client: self.on_client_selected(e, c), border=ft.border.all(1, ft.Colors.GREY_300), border_radius=10, expand=True ) ) self.client_results.update() def on_client_selected(self, e, client): self.selected_client_id = client["id"] self.client_search_field.value = client["name"] self.client_search_field.update() self.update_client_list(self.filtered_clients) def on_searching_transporter(self, e): query = e.control.value.lower() self.filtered_transporters = [t for t in self.all_transporters if query in t["name"].lower()] self.update_transporter_list(self.filtered_transporters) def init_search_transporter(self): query = self.transporter_search_field.value.lower() self.filtered_transporters = [transporter for transporter in self.all_transporters if query in transporter["name"].lower()] self.transporter_results.controls.clear() for transporter in self.filtered_transporters: self.transporter_results.controls.append( ft.Container( content=ft.Row( controls=[ft.Text(transporter["name"], expand=True)], expand=True ), bgcolor=ft.Colors.BLUE_100 if transporter["id"] == self.selected_transporter_id else ft.Colors.BLUE_50, padding=10, ink=True, on_click=lambda e, t=transporter: self.on_transporter_selected(e, t), border=ft.border.all(1, ft.Colors.GREY_300), border_radius=10, expand=True ) ) def update_transporter_list(self, transporters): self.transporter_results.controls.clear() for transporter in transporters: self.transporter_results.controls.append( ft.Container( content=ft.Row( controls=[ft.Text(transporter["name"], expand=True)], expand=True ), bgcolor=ft.Colors.BLUE_100 if transporter["id"] == self.selected_transporter_id else ft.Colors.BLUE_50, padding=10, ink=True, on_click=lambda e, t=transporter: self.on_transporter_selected(e, t), border=ft.border.all(1, ft.Colors.GREY_300), border_radius=10, expand=True ) ) self.transporter_results.update() def on_transporter_selected(self, e, transporter): self.selected_transporter_id = transporter["id"] self.transporter_search_field.value = transporter["name"] self.transporter_search_field.update() self.update_transporter_list(self.filtered_transporters) def on_searching_loading_address(self, e): query = e.control.value.lower() self.filtered_addresses = [a for a in self.all_addresses if query in a["name"].lower()] self.update_loading_addresses_list(self.filtered_addresses) def update_loading_addresses_list(self, addresses): self.loading_address_results.controls.clear() for address in addresses: self.loading_address_results.controls.append( ft.Container( content=ft.Row( controls=[ft.Text(address["name"], expand=True)], expand=True ), bgcolor=ft.Colors.BLUE_100 if address["id"] == getattr(self, "selected_loading_address_id", None) else ft.Colors.BLUE_50, padding=10, ink=True, on_click=lambda e,a=address: self.on_loading_address_selected(e, a), border=ft.border.all(1, ft.Colors.GREY_300), border_radius=10, expand=True ) ) self.loading_address_results.update() def on_loading_address_selected(self, e, address): self.selected_loading_address_id = address["id"] self.loading_address_search_field.value = address["name"] self.loading_address_search_field.update() self.update_loading_addresses_list(self.filtered_addresses) def on_loading_date_click(self, e): self.loading_date.value = e.control.value.strftime('%m/%d/%Y') self.loading_date.update() #print(self.loading_date.value) def on_loading_hour_click(self, e): if len(self.loading_hour.value) != None and len(self.loading_hour.value)==0: self.loading_hour.value = str(e.control.value) else: self.loading_hour.value += f' - {e.control.value}' self.loading_hour.update() #print(self.loading_hour.value) def on_reset_loading_hour_btn_click(self, e): self.loading_hour.value = None self.loading_hour.update() def add_loading_point_btn_click(self, e): adr = None name = None #print(self.selected_loading_address_id) for _address in self.all_addresses: if _address['id'] == self.selected_loading_address_id: adr = '' street_and_number = _address["address"].split(" %")[0] postal_code = _address["address"].split(" %")[1] city = _address["address"].split(" %")[2] region_county = _address["address"].split(" %")[3] country = _address["address"].split(" %")[4] if len(street_and_number) > 0: adr += street_and_number +', ' if len(postal_code) > 0: adr += postal_code +', ' if len(city) > 0: adr += city +', ' if len(region_county) > 0: adr += region_county +', ' if len(country) > 0: adr += country name = _address['name'] #print(adr) #print(_address['address']) loading_informatins = self.loading_informations.value date = self.loading_date.value hour = self.loading_hour.value #create loading list address = { 'loading_address_id': self.selected_loading_address_id, 'loading_address_name': name, 'loading_address': adr, 'loading_informatins': loading_informatins, 'loading_date': date, 'loading_hour': hour } #print(address) if self.selected_loading_address_id == None: self.loading_error_message.value = "Please select loading point!" self.loading_error_message.update() return if self.loading_informations.value == None or len(self.loading_informations.value) == 0: self.loading_error_message.value = "Add loading informations!" self.loading_error_message.update() return if self.loading_date.value == None or len(str(self.loading_date.value)) == 0: self.loading_error_message.value = "Add loading date!" self.loading_error_message.update() return # if self.loading_hour.value == None or len(str(self.loading_hour.value)) == 0: # self.loading_error_message.value = "Add loading hour!" # self.loading_error_message.update() # return if self.selected_loading_address_id: self.loading_query.append(address) self.loading.controls.clear() self.loading.controls = self.create_loading_list(self.loading_query, self.on_delete_loading_address_btn_click) self.loading.update() #reset to default self.selected_loading_address_id = None self.loading_informations.value = None self.loading_informations.update() self.loading_date.value = None self.loading_date.update() self.loading_hour.value = None self.loading_hour.update() self.loading_error_message.value = None self.loading_error_message.update() else: self.loading_error_message.value = "All fields of the loading address are required." self.loading_error_message.update() def on_searching_unloading_address(self, e): query = e.control.value.lower() self.filtered_addresses_ul = [a for a in self.all_addresses if query in a["name"].lower()] self.update_unloading_addresses_list(self.filtered_addresses_ul) def update_unloading_addresses_list(self, addresses): self.unloading_address_results.controls.clear() for address in addresses: self.unloading_address_results.controls.append( ft.Container( content=ft.Row( controls=[ft.Text(address["name"], expand=True)], expand=True ), bgcolor=ft.Colors.BLUE_100 if address["id"] == getattr(self, "selected_unloading_address_id", None) else ft.Colors.BLUE_50, padding=10, ink=True, on_click=lambda e,a=address: self.on_unloading_address_selected(e, a), border=ft.border.all(1, ft.Colors.GREY_300), border_radius=10, expand=True ) ) self.unloading_address_results.update() def on_unloading_address_selected(self, e, address): self.selected_unloading_address_id = address["id"] self.unloading_address_search_field.value = address["name"] self.unloading_address_search_field.update() self.update_unloading_addresses_list(self.filtered_addresses_ul) def on_unloading_date_click(self, e): self.unloading_date.value = e.control.value.strftime('%m/%d/%Y') self.unloading_date.update() def on_unloading_hour_click(self, e): if len(self.unloading_hour.value) != None and len(self.unloading_hour.value)==0: self.unloading_hour.value = str(e.control.value) else: self.unloading_hour.value += f' - {e.control.value}' self.unloading_hour.update() def on_reset_unloading_hour_btn_click(self, e): self.unloading_hour.value = None self.unloading_hour.update() def add_unloading_point_btn_click(self, e): adr = None name = None #print(self.selected_unloading_address_id) for _address in self.all_addresses: if _address['id'] == self.selected_unloading_address_id: adr = '' street_and_number = _address["address"].split(" %")[0] postal_code = _address["address"].split(" %")[1] city = _address["address"].split(" %")[2] region_county = _address["address"].split(" %")[3] country = _address["address"].split(" %")[4] if len(street_and_number) > 0: adr += street_and_number +', ' if len(postal_code) > 0: adr += postal_code +', ' if len(city) > 0: adr += city +', ' if len(region_county) > 0: adr += region_county +', ' if len(country) > 0: adr += country name = _address['name'] unloading_informatins = self.unloading_informations.value date = self.unloading_date.value hour = self.unloading_hour.value address = { 'unloading_address_id': self.selected_unloading_address_id, 'unloading_address_name': name, 'unloading_address': adr, 'unloading_informatins': unloading_informatins, 'unloading_date': date, 'unloading_hour': hour } if self.selected_unloading_address_id == None: self.unloading_error_message.value = "Please select unloading point!" self.unloading_error_message.update() return if self.unloading_informations.value == None or len(self.unloading_informations.value) == 0: self.unloading_error_message.value = "Add unloading informations!" self.unloading_error_message.update() return if self.unloading_date.value == None or len(str(self.unloading_date.value)) == 0: self.unloading_error_message.value = "Add unloading date!" self.unloading_error_message.update() return # if self.unloading_hour.value == None or len(str(self.unloading_hour.value)) == 0: # self.unloading_error_message.value = "Add unloading hour!" # self.unloading_error_message.update() # return if self.selected_unloading_address_id: self.unloading_query.append(address) self.unloading.controls.clear() self.unloading.controls = self.create_unloading_list(self.unloading_query, self.on_delete_unloading_address_btn_click) self.unloading.update() #reset to default self.selected_unloading_address_id = None self.unloading_informations.value = None self.unloading_informations.update() self.unloading_date.value = None self.unloading_date.update() self.unloading_hour.value = None self.unloading_hour.update() self.unloading_error_message.value = None self.unloading_error_message.update() else: self.unloading_error_message.value = "All fields of the unloading address are required." self.unloading_error_message.update() def get_all_clients(self): 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: return response.json() else: print("Failed to fetch clients:", response.status_code) return [] def get_all_transporters(self): token = self.page.client_storage.get("token") headers = {"Authorization": f"Bearer {token}"} user_id = self.page.session.get("user_id") response = requests.get(f"{API_BASE_URL}/transporters/", headers=headers) if response.status_code == 200: return response.json() else: print("Failed to fetch transporters:", response.status_code) return [] def get_all_addresses(self): token = self.page.client_storage.get("token") headers = {"Authorization": f"Bearer {token}"} response = requests.get(f"{API_BASE_URL}/destinations/", headers=headers) if response.status_code == 200: return response.json() else: print("Failed to fetch addresses:", response.status_code) return [] def create_loading_list(self, items, on_click_handler): """Helper to create list items for a column.""" return [ ft.Container( content=ft.Row( [ ft.Column( [ ft.Text( item['loading_address_name'], expand=True, size=15, weight=ft.FontWeight.BOLD ), ft.Text( item['loading_address'], expand=True, size=12, ), ft.Row( [ ft.Text( f"Date: {item['loading_date']}", expand=True, size=12, ), ft.Text( f"Hour: {item['loading_hour']}", expand=True, size=12, ) ] ) ] ), ft.Row( [ ft.FilledButton( "Delete", bgcolor=ft.Colors.RED, on_click=lambda e, id=item: on_click_handler(id), width=100 ) ] ) ], alignment=ft.MainAxisAlignment.SPACE_BETWEEN, ), width=300, bgcolor=ft.Colors.BLUE_50, padding=10, border_radius=8, border=ft.border.all(1, ft.Colors.GREY_300), #ink=True, # To enable click effect #on_click=lambda e, id=item: on_click_handler(id), # Attach the click handler ) for item in items ] def on_delete_loading_address_btn_click(self, item): self.loading_query.remove(item) self.loading.controls.clear() self.loading.controls = self.create_loading_list(self.loading_query, self.on_delete_loading_address_btn_click) self.loading.update() def create_unloading_list(self, items, on_click_handler): """Helper to create list items for a column.""" return [ ft.Container( content=ft.Row( [ ft.Column( [ ft.Text( item['unloading_address_name'], expand=True, size=15, weight=ft.FontWeight.BOLD ), ft.Text( item['unloading_address'], expand=True, size=12, ), ft.Row( [ ft.Text( f"Date: {item['unloading_date']}", expand=True, size=12, ), ft.Text( f"Hour: {item['unloading_hour']}", expand=True, size=12, ) ] ) ] ), ft.Row( [ ft.FilledButton( "Delete", bgcolor=ft.Colors.RED, on_click=lambda e, id=item: on_click_handler(id), width=100 ) ] ) ], alignment=ft.MainAxisAlignment.SPACE_BETWEEN, ), width=300, bgcolor=ft.Colors.BLUE_50, padding=10, border_radius=8, border=ft.border.all(1, ft.Colors.GREY_300), #ink=True, # To enable click effect #on_click=lambda e, id=item: on_click_handler(id), # Attach the click handler ) for item in items ] def on_delete_unloading_address_btn_click(self, item): #print(item) #print(self.unloading_query) self.unloading_query.remove(item) self.unloading.controls.clear() self.unloading.controls = self.create_unloading_list(self.unloading_query, self.on_delete_unloading_address_btn_click) self.unloading.update() def on_save_btn_click(self, e): loading_addresses = [] unloading_addresses = [] for laddr in self.loading_query: laddr_copy = laddr.copy() if isinstance(laddr_copy.get("loading_hour"), datetime.time): laddr_copy["loading_hour"] = laddr_copy["loading_hour"].strftime("%H:%M") loading_addresses.append(laddr_copy) for uaddr in self.unloading_query: uaddr_copy = uaddr.copy() if isinstance(uaddr_copy.get("unloading_hour"), datetime.time): uaddr_copy["unloading_hour"] = uaddr_copy["unloading_hour"].strftime("%H:%M") unloading_addresses.append(uaddr_copy) saved_data = { 'order_number': self.order_number.value, 'client_id': self.selected_client_id, 'transporter_id': self.selected_transporter_id, 'products_description': self.product_description.value, 'ldb_quantity': self.ldm_quantity.value, 'kg_quantity': self.kg_quantity.value, 'track_reg_number': self.track_reg_number.value, 'trailer_reg_number': self.trailer_reg_number.value, 'received_price': self.received_price.value, 'paid_price': self.paid_price.value, 'loading_addresses': loading_addresses, 'unloading_addresses': unloading_addresses } #print(saved_data) if self.order_number.value == None or len(self.order_number.value)==0: self.error_message.value = "Order number is mandatory!" self.error_message.color = ft.Colors.RED self.error_message.update() return if self.selected_client_id == None: self.error_message.value = "Please select the client!" self.error_message.color = ft.Colors.RED self.error_message.update() return if self.selected_transporter_id == None: self.error_message.value = "Please select the transporter!" self.error_message.color = ft.Colors.RED self.error_message.update() return if self.product_description.value == None or len(self.product_description.value)==0: self.error_message.value = "Please insert product description!" self.error_message.color = ft.Colors.RED self.error_message.update() return # if self.ldm_quantity.value == None or len(self.ldm_quantity.value)==0: # self.error_message.value = "Please insert LDM!" # self.error_message.color = ft.Colors.RED # self.error_message.update() # return # if self.kg_quantity.value == None or len(self.kg_quantity.value)==0: # self.error_message.value = "Please insert KG!" # self.error_message.color = ft.Colors.RED # self.error_message.update() # return if self.track_reg_number.value == None or len(self.track_reg_number.value)==0: self.error_message.value = "Please insert Track Registration Number!" self.error_message.color = ft.Colors.RED self.error_message.update() return if self.trailer_reg_number.value == None or len(self.trailer_reg_number.value)==0: self.error_message.value = "Please insert Trailer Registration Number!" self.error_message.color = ft.Colors.RED self.error_message.update() return if self.received_price.value == None or len(str(self.received_price.value))==0: self.error_message.value = "Please insert Price received!" self.error_message.color = ft.Colors.RED self.error_message.update() return if self.paid_price.value == None or len(str(self.paid_price.value))==0: self.error_message.value = "Please insert Price paid!" self.error_message.color = ft.Colors.RED self.error_message.update() return if len(loading_addresses) == 0: self.error_message.value = "Please add loading point!" self.error_message.color = ft.Colors.RED self.error_message.update() return if len(unloading_addresses) == 0: self.error_message.value = "Please add unloading point!" self.error_message.color = ft.Colors.RED self.error_message.update() return # --- POST request to save the order in the database --- token = self.page.client_storage.get("token") headers = {"Authorization": f"Bearer {token}"} user_id = self.page.session.get("user_id") saved_data["user_id"] = user_id user = self.get_user_data() saved_data['terms'] = user['terms'] try: response = requests.put(f"{API_BASE_URL}/orders/{self.order_id}", json=saved_data, headers=headers) if response.status_code == 200: self.error_message.value = "Order saved successfully, Please wait!" self.error_message.color = ft.Colors.GREEN self.error_message.update() order_id = response.json()['order_id'] time.sleep(3) pdf_name = f'order_{user_id}_{saved_data['order_number']}.pdf' view_page = ViewPage(self.page, pdf_name, self, self.dashboard, order_id) self.dashboard.placeholder.content = view_page.build() self.dashboard.placeholder.update() else: self.error_message.value = f"Failed to save order: {response.status_code} - {response.text}" self.error_message.update() except Exception as ex: self.error_message.value = f"Error: {str(ex)}" self.error_message.update() def get_user_data(self): try: token = self.page.client_storage.get("token") if not token: self.message.value = "Unauthorized: No token" return response = requests.get(f"{API_BASE_URL}/profile", headers={"Authorization": f"Bearer {token}"}) if response.status_code == 200: user_data = response.json() return user_data return None except Exception as e: return None def on_archive_btn_click(self, e): #archive_page = ArchivePage(self.page, self.dashboard, self) self.dashboard.placeholder.content = self.archive_page.build() self.dashboard.placeholder.update() 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) logging.info(response.text) return response.json()[-1] if response.status_code == 200 else None #except Exception as e: # print("Error loading subscription:", e) # return None def build(self): self.save_btn = ft.FilledButton( "Save and Generate", width=200, on_click=self.on_save_btn_click, ) self.save_row = ft.Row([],alignment=ft.MainAxisAlignment.CENTER) if self.get_current_subscription_plan()['status'] != 'expired': self.save_row.controls.append(self.save_btn) self.init_search_client() self.init_search_transporter() return ft.Container( ft.Column( [ ft.Row( [ ft.Column( [ ft.Text('Edit Order', size=24, weight=ft.FontWeight.BOLD), ft.Row( [ ft.Text("Number", size=18, weight=ft.FontWeight.BOLD), self.order_number ] ) ], alignment=ft.MainAxisAlignment.START ), ft.ElevatedButton("Archive", on_click=self.on_archive_btn_click, width=150) ], alignment=ft.MainAxisAlignment.SPACE_BETWEEN, vertical_alignment=ft.CrossAxisAlignment.START ), ft.Row( [ ft.Column( [ ft.Text("Client", size=18, weight=ft.FontWeight.BOLD), self.client_search_field, ft.Container( content=ft.Container( content=ft.Column( controls=[self.client_results], scroll=ft.ScrollMode.ADAPTIVE, ), #clip_behavior=ft.ClipBehavior., expand=True, padding=0, ), height=250 #if len(self.filtered_clients) > 4 else None, ) ], expand=5 ), ft.Column( [ ft.Text("Transporter", size=18, weight=ft.FontWeight.BOLD), self.transporter_search_field, ft.Container( content=ft.Container( content=ft.Column( controls=[self.transporter_results], scroll=ft.ScrollMode.ADAPTIVE ), expand=True, padding=0, ), height=250 #if len(self.filtered_transporters) > 4 else None, ) ], expand=5 ), ], expand=True, spacing=20, vertical_alignment=ft.CrossAxisAlignment.START ), ft.Divider(), ft.Row( [ ft.Column( [ ft.Row( [ ft.Text("Product Details", size=18, weight=ft.FontWeight.BOLD) ], alignment=ft.MainAxisAlignment.START ), ft.Column( [ ft.Container( content = self.product_description, expand=True ), ft.Row( [ ft.Text( value="LDM" ), self.ldm_quantity, ft.Text(" "), ft.Text( value="KG" ), self.kg_quantity, ], expand=True ) ], expand=True, ) ], expand=5 ), ft.Column( [ ft.Row( [ ft.Text("Truck / Trailer Info", size=18, weight=ft.FontWeight.BOLD) ], alignment=ft.MainAxisAlignment.START ), ft.Column( [ self.track_reg_number, self.trailer_reg_number ], expand=True ) ], expand=2.5 ), ft.Column( [ ft.Row( [ ft.Text("Price", size=18, weight=ft.FontWeight.BOLD) ], alignment=ft.MainAxisAlignment.START ), self.received_price, self.paid_price ], expand=2.5 ) ], expand=True, spacing=20, vertical_alignment=ft.CrossAxisAlignment.START ), ft.Divider(), ft.Row( [ ft.Column( [ ft.Text("Loading Points", size=18, weight=ft.FontWeight.BOLD), ft.Column( [ self.loading_address_search_field, ft.Container( content=ft.Container( content=ft.Column( controls=[self.loading_address_results], scroll=ft.ScrollMode.ADAPTIVE ), expand=True, padding=0, ), height=250 if len(self.filtered_addresses) > 4 else None, ) ], expand=5 ), ft.Container( content = self.loading_informations, expand = True ), ft.Row( [ self.loading_date, ft.ElevatedButton( "Pick date", icon=ft.Icons.CALENDAR_MONTH, on_click=lambda e: self.page.open( ft.DatePicker( first_date=datetime.datetime(year=2000, month=10, day=1), last_date=datetime.datetime(year=2025, month=10, day=1), on_change=self.on_loading_date_click, ) ), ) ], expand=True ), ft.Row( [ self.loading_hour, ft.ElevatedButton( "Pick hour - Start", icon=ft.Icons.CALENDAR_MONTH, on_click=lambda e: self.page.open( ft.TimePicker( confirm_text="Confirm", error_invalid_text="Time out of range", help_text="Pick your time slot", on_change=self.on_loading_hour_click, time_picker_entry_mode = ft.TimePickerEntryMode.INPUT_ONLY ) ), ), ft.ElevatedButton( "Pick hour - End", icon=ft.Icons.CALENDAR_MONTH, on_click=lambda e: self.page.open( ft.TimePicker( confirm_text="Confirm", error_invalid_text="Time out of range", help_text="Pick your time slot", on_change=self.on_loading_hour_click, time_picker_entry_mode = ft.TimePickerEntryMode.INPUT_ONLY ) ), ), ft.ElevatedButton( "Reset", on_click = self.on_reset_loading_hour_btn_click ), ], expand=True ), self.loading_error_message, ft.Row( [ ft.ElevatedButton( "Add Loading Point", on_click=self.add_loading_point_btn_click, icon=ft.Icons.ADD ) ], alignment=ft.MainAxisAlignment.CENTER ), self.loading ], expand=5, alignment=ft.MainAxisAlignment.START ), ft.Column( [ ft.Text("Unloading Points", size=18, weight=ft.FontWeight.BOLD), ft.Column( [ self.unloading_address_search_field, ft.Container( content=ft.Container( content=ft.Column( controls=[self.unloading_address_results], scroll=ft.ScrollMode.ADAPTIVE ), expand=True, padding=0, ), height=250 if len(self.filtered_addresses_ul) > 4 else None, ) ], expand=5 ), ft.Container( content = self.unloading_informations, expand=True ), ft.Row( [ self.unloading_date, ft.ElevatedButton( "Pick date", icon=ft.Icons.CALENDAR_MONTH, on_click=lambda e: self.page.open( ft.DatePicker( first_date=datetime.datetime(year=2000, month=10, day=1), last_date=datetime.datetime(year=2025, month=10, day=1), on_change=self.on_unloading_date_click, ) ), ) ], expand=True ), ft.Row( [ self.unloading_hour, ft.ElevatedButton( "Pick hour - Start", icon=ft.Icons.CALENDAR_MONTH, on_click=lambda e: self.page.open( ft.TimePicker( confirm_text="Confirm", error_invalid_text="Time out of range", help_text="Pick your time slot", on_change=self.on_unloading_hour_click, time_picker_entry_mode = ft.TimePickerEntryMode.INPUT_ONLY ) ), ), ft.ElevatedButton( "Pick hour - End", icon=ft.Icons.CALENDAR_MONTH, on_click=lambda e: self.page.open( ft.TimePicker( confirm_text="Confirm", error_invalid_text="Time out of range", help_text="Pick your time slot", on_change=self.on_unloading_hour_click, time_picker_entry_mode = ft.TimePickerEntryMode.INPUT_ONLY ) ), ), ft.ElevatedButton( "Reset", on_click = self.on_reset_unloading_hour_btn_click ), ], expand=True ), self.unloading_error_message, ft.Row( [ ft.ElevatedButton( "Add Unloading Point", on_click=self.add_unloading_point_btn_click, icon=ft.Icons.ADD ) ], alignment=ft.MainAxisAlignment.CENTER ), self.unloading ], expand=5, alignment=ft.MainAxisAlignment.START ) ], expand=True, spacing=20, vertical_alignment=ft.CrossAxisAlignment.START ), ft.Row( [ self.error_message, ], alignment=ft.MainAxisAlignment.CENTER ), self.save_row, ], expand=True, scroll=ft.ScrollMode.ADAPTIVE, spacing=20 ) )