332 lines
12 KiB
Python
332 lines
12 KiB
Python
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 get_client_access(self):
|
|
token = self.page.client_storage.get("token")
|
|
headers = {"Authorization": f"Bearer {token}"}
|
|
response = requests.get(f"{API_BASE_URL}/profile/", headers=headers, timeout=10)
|
|
user = response.json()
|
|
if user['user_role'] == 'user':
|
|
return True
|
|
else:
|
|
id = self.page.session.get("user_id")
|
|
response = requests.get(f"{API_BASE_URL}/company_user/access/{id}", headers=headers)
|
|
return True if response.json()['clients'] == 1 else False
|
|
|
|
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,
|
|
) if self.get_client_access() else ft.Container(
|
|
content=ft.Column(
|
|
[
|
|
ft.Row(
|
|
[
|
|
ft.Text("Clients", size=24, weight=ft.FontWeight.BOLD),
|
|
],
|
|
alignment=ft.MainAxisAlignment.SPACE_BETWEEN
|
|
),
|
|
ft.Row(
|
|
[
|
|
ft.Text(
|
|
"You do not have access to this page content",
|
|
size=24,
|
|
weight=ft.FontWeight.BOLD,
|
|
color=ft.Colors.RED
|
|
)
|
|
],
|
|
alignment=ft.MainAxisAlignment.CENTER
|
|
),
|
|
ft.Text("")
|
|
],
|
|
alignment=ft.MainAxisAlignment.SPACE_BETWEEN,
|
|
expand=True
|
|
),
|
|
expand=True
|
|
) |