init commit

This commit is contained in:
2025-08-31 17:55:26 +03:00
commit 876ddec94a
78 changed files with 11999 additions and 0 deletions

View File

@@ -0,0 +1,458 @@
import flet as ft
import requests
import time
from config import API_BASE_URL
class ProfilePage:
def __init__(self, page: ft.Page, dashboard):
self.page = page
self.dashboard = dashboard
self.name_field = ft.TextField(
label="Company Name",
disabled=True,
input_filter=ft.InputFilter(
allow=True,
regex_string=r"^[\x20-\x7E]*$",
replacement_string=""
),
)
self.contact_name_field = ft.TextField(
label="Contact Name",
disabled=True,
input_filter=ft.InputFilter(
allow=True,
regex_string=r"^[\x20-\x7E]*$",
replacement_string=""
),
)
self.email_field = ft.TextField(
label="Email",
disabled=True,
input_filter=ft.InputFilter(
allow=True,
regex_string=r"^[\x20-\x7E]*$",
replacement_string=""
),
)
self.phone_field = ft.TextField(
label="Phone",
disabled=True,
input_filter=ft.InputFilter(
allow=True,
regex_string=r"^[\x20-\x7E]*$",
replacement_string=""
),
)
self.register_number_field = ft.TextField(
label="Register Number",
disabled=True,
input_filter=ft.InputFilter(
allow=True,
regex_string=r"^[\x20-\x7E]*$",
replacement_string=""
),
)
self.vat = ft.TextField(
label="VAT",
disabled=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",
disabled=True,
input_filter=ft.InputFilter(
allow=True,
regex_string=r"^[\x20-\x7E]*$",
replacement_string=""
),
)
self.postal_code = ft.TextField(
label="Postal code",
disabled=True,
input_filter=ft.InputFilter(
allow=True,
regex_string=r"^[\x20-\x7E]*$",
replacement_string=""
),
)
self.city = ft.TextField(
label="City",
disabled=True,
input_filter=ft.InputFilter(
allow=True,
regex_string=r"^[\x20-\x7E]*$",
replacement_string=""
),
)
self.region_county = ft.TextField(
label="Region / County",
disabled=True,
input_filter=ft.InputFilter(
allow=True,
regex_string=r"^[\x20-\x7E]*$",
replacement_string=""
),
)
self.country = ft.TextField(
label="Country",
disabled=True,
input_filter=ft.InputFilter(
allow=True,
regex_string=r"^[\x20-\x7E]*$",
replacement_string=""
),
)
self.logo_field = ft.TextField(
label="Logo Filename",
disabled=True,
input_filter=ft.InputFilter(
allow=True,
regex_string=r"^[\x20-\x7E]*$",
replacement_string=""
),
)
self.terms_field = ft.TextField(
label="Terms",
multiline=True,
min_lines=5,
max_lines=10,
disabled=True,
input_filter=ft.InputFilter(
allow=True,
regex_string=r"^[\x20-\x7E]*$",
replacement_string=""
),
)
self.first_order_number_field = ft.TextField(
label="First Order Number",
disabled=True,
input_filter=ft.InputFilter(
allow=True,
regex_string=r"^[\x20-\x7E]*$",
replacement_string=""
),
)
self.created_at_text = ft.Text(value="Created At: TBD") # Set dynamically later
self.edit_button = ft.ElevatedButton(text="Edit Profile", on_click=self.on_edit_click)
self.save_button = ft.ElevatedButton(text="Save Changes", visible=False, on_click=self.on_save_click)
self.cancel_button = ft.TextButton(text="Cancel", visible=False, on_click=self.on_cancel_click)
self.upload_logo_btn = ft.ElevatedButton("Upload Company Logo", icon=ft.Icons.UPLOAD, on_click=self.on_upload_click, disabled=True)
self.message = ft.Text()
self.logo = ft.Image(src="images/image_placeholder.png", width=250)
self.file_picker = ft.FilePicker(on_result=self.on_file_result)
self.page.overlay.append(self.file_picker)
#email credentials
self.email_credentials = None
self.smtp_host = ft.TextField(
label="SMTP HOST",
disabled=True,
input_filter=ft.InputFilter(
allow=True,
regex_string=r"^[\x20-\x7E]*$",
replacement_string=""
),
)
self.smtp_port = ft.TextField(
label="SMTP PORT",
disabled=True,
input_filter=ft.InputFilter(
allow=True,
regex_string=r"^[\x20-\x7E]*$",
replacement_string=""
),
)
self.smtp_user = ft.TextField(
label="Email (SMTP USER)",
disabled=True,
input_filter=ft.InputFilter(
allow=True,
regex_string=r"^[\x20-\x7E]*$",
replacement_string=""
),
)
def _auth_headers(self):
"""Build Authorization header from client storage robustly (web/desktop)."""
t = self.page.client_storage.get("token")
if not t:
return {}
# Token may be stored as dict or quoted string depending on login flow/runtime
if isinstance(t, dict):
t = t.get("access_token") or t.get("token") or ""
if not isinstance(t, str):
t = str(t)
t = t.strip().strip('"')
return {"Authorization": f"Bearer {t}"} if t else {}
def on_edit_click(self, e):
self.name_field.disabled = False
self.contact_name_field.disabled = False
self.email_field.disabled = False
self.phone_field.disabled = False
self.register_number_field.disabled = False
self.vat.disabled = False
self.street_and_number.disabled = False
self.postal_code.disabled = False
self.city.disabled = False
self.region_county.disabled = False
self.country.disabled = False
self.logo_field.disabled = False
self.terms_field.disabled = False
self.first_order_number_field.disabled = False
self.upload_logo_btn.disabled = False
self.smtp_host.disabled = False
self.smtp_port.disabled = False
self.smtp_user.disabled = False
self.edit_button.visible = False
self.save_button.visible = True
self.cancel_button.visible = True
self.page.update()
def on_save_click(self, e):
# Save logic would be implemented here
headers = self._auth_headers()
if not headers:
self.message.value = "Unauthorized: No token"
self.message.color = ft.Colors.RED
self.page.update()
return
address = f'{self.street_and_number.value} %{self.postal_code.value} %{self.city.value} %{self.region_county.value} %{self.country.value}'
data = {
"name": self.name_field.value,
"contact_name": self.contact_name_field.value,
"email": self.email_field.value,
"phone": self.phone_field.value,
"register_number": self.register_number_field.value,
"vat": self.vat.value,
"address": address,
"logo_filename": self.logo_field.value,
"terms": self.terms_field.value,
"first_order_number": self.first_order_number_field.value
}
try:
response = requests.put(f"{API_BASE_URL}/profile/", json=data, headers=headers)
if response.status_code == 200:
self.message.value = "Profile updated successfully!"
self.message.color = ft.Colors.GREEN
# Save logo filename to client storage
self.page.client_storage.set("logo_filename", self.logo_field.value)
self.page.session.set("first_order_number", self.first_order_number_field.value)
else:
self.message.value = f"Failed to update profile: {response.status_code}"
self.message.color = ft.Colors.RED
except Exception as e:
self.message.value = f"Error updating profile: {e}"
self.message.color = ft.Colors.RED
#email credentials
data = {
'smtp_host' : self.smtp_host.value,
'smtp_port' : self.smtp_port.value,
'smtp_user' : self.smtp_user.value
}
try:
if not self.email_credentials:
response = requests.post(f"{API_BASE_URL}/profile/email", json=data, headers=headers)
else:
response = requests.put(f"{API_BASE_URL}/profile/email", json=data, headers=headers)
if response.status_code == 200:
self.message.value = "Profile updated successfully!"
self.message.color = ft.Colors.GREEN
else:
self.message.value = f"Failed to create / update email credentials: {response.status_code}"
self.message.color = ft.Colors.RED
except Exception as e:
self.message.value = f"Error creating / updating email credentials: {e}"
self.message.color = ft.Colors.RED
self.name_field.disabled = True
self.contact_name_field.disabled = True
self.email_field.disabled = True
self.phone_field.disabled = True
self.register_number_field.disabled = True
self.vat.disabled = True
self.street_and_number.disabled = True
self.postal_code.disabled = True
self.city.disabled = True
self.region_county.disabled = True
self.country.disabled = True
self.logo_field.disabled = True
self.terms_field.disabled = True
self.first_order_number_field.disabled = True
self.upload_logo_btn.disabled = True
self.smtp_host.disabled = True
self.smtp_port.disabled = True
self.smtp_user.disabled = True
self.edit_button.visible = True
self.save_button.visible = False
self.cancel_button.visible = False
self.page.update()
def on_cancel_click(self, e):
# Reset fields or fetch previous values here
self.name_field.disabled = True
self.contact_name_field.disabled = True
self.email_field.disabled = True
self.phone_field.disabled = True
self.register_number_field.disabled = True
self.vat.disabled = True
self.street_and_number.disabled = True
self.postal_code.disabled = True
self.city.disabled = True
self.region_county.disabled = True
self.country.disabled = True
self.logo_field.disabled = True
self.terms_field.disabled = True
self.first_order_number_field.disabled = True
self.upload_logo_btn.disabled = True
self.smtp_host.disabled = True
self.smtp_port.disabled = True
self.smtp_user.disabled = True
self.edit_button.visible = True
self.save_button.visible = False
self.cancel_button.visible = False
self.page.update()
def populate_user_data(self):
user_id = self.page.session.get("user_id")
if not user_id:
self.message.value = "User not authenticated."
self.message.color = ft.Colors.RED
return
headers = self._auth_headers()
if not headers:
self.message.value = "Unauthorized: No token"
self.message.color = ft.Colors.RED
return
response = requests.get(f"{API_BASE_URL}/profile/", headers=headers, timeout=10)
if response.status_code == 200:
user_data = response.json()
#print(user_data)
self.name_field.value = user_data.get("name", "")
self.contact_name_field.value = user_data.get("contact_name", "")
self.email_field.value = user_data.get("email", "")
self.phone_field.value = user_data.get("phone", "")
self.register_number_field.value = user_data.get("register_number", "")
self.vat.value = user_data.get("vat", "")
self.street_and_number.value = user_data.get("address").split(" %")[0] if user_data.get("address") and len(user_data.get("address")) > 0 else ''
self.postal_code.value = user_data.get("address").split(" %")[1] if user_data.get("address") and len(user_data.get("address")) > 0 else ''
self.city.value = user_data.get("address").split(" %")[2] if user_data.get("address") and len(user_data.get("address")) > 0 else ''
self.region_county.value = user_data.get("address").split(" %")[3] if user_data.get("address") and len(user_data.get("address")) > 0 else ''
self.country.value = user_data.get("address").split(" %")[4] if user_data.get("address") and len(user_data.get("address")) > 0 else ''
logo_filename = user_data.get("logo_filename", "")
self.logo_field.value = logo_filename
self.logo.src = f"images/{logo_filename}" if logo_filename else "images/image_placeholder.png"
if logo_filename:
self.page.client_storage.set("logo_filename", logo_filename)
self.dashboard.logo.src = f"images/{logo_filename}"
self.dashboard.logo.update()
self.terms_field.value = user_data.get("terms", "")
self.first_order_number_field.value = user_data.get("first_order_number", "")
self.created_at_text.value = f"Created At: {user_data.get('created_at', '')}"
if self.register_number_field.value == '':
self.on_edit_click('')
else:
self.message.value = f"Failed to load user data: {response.text}"
self.message.color = ft.Colors.RED
response = requests.get(f"{API_BASE_URL}/profile/email", headers=headers, timeout=10)
if response.status_code == 200:
self.email_credentials = response.json()
self.smtp_host.value = self.email_credentials['smtp_host']
self.smtp_port.value = self.email_credentials['smtp_port']
self.smtp_user.value = self.email_credentials['smtp_user']
else:
print(f"Failed to load email credentials: {response.text}")
#except Exception as e:
# self.message.value = f"Error fetching user data: {e}"
# self.message.color = ft.Colors.RED
def on_upload_click(self, e):
self.file_picker.pick_files(
allow_multiple=False,
allowed_extensions=["png", "jpg", "jpeg"]
)
def on_file_result(self, e: ft.FilePickerResultEvent):
if not e.files:
return
file = e.files[0]
new_filename = f"user_logo_{self.page.session.get('user_id')}_{file.name}"
upload_url = self.page.get_upload_url(new_filename, 1000)
self.file_picker.upload([ft.FilePickerUploadFile(file.name, upload_url=upload_url)])
import os
import shutil
source_path = os.path.join("uploads", new_filename)
destination_path = os.path.join("assets/images", new_filename)
try:
time.sleep(2)
shutil.move(source_path, destination_path)
self.logo.src = f"images/{new_filename}"
self.logo.update()
self.logo_field.value = new_filename
self.page.update()
self.page.client_storage.set("logo_filename", new_filename)
self.dashboard.logo.src = f"images/{new_filename}"
self.dashboard.logo.update()
except Exception as err:
self.message.value = f"Upload error: {err}"
self.message.color = ft.Colors.RED
self.page.update()
def build(self):
self.populate_user_data()
return ft.Container(
content=ft.Column(
[
ft.Text("User Profile", size=24, weight=ft.FontWeight.BOLD),
ft.Row(
[
ft.Column(
[
self.logo,
self.upload_logo_btn,
self.message,
ft.Text(),
self.smtp_user,
self.smtp_host,
self.smtp_port,
ft.Row([self.edit_button, self.save_button, self.cancel_button])
],
horizontal_alignment=ft.CrossAxisAlignment.CENTER,
width=250
),
ft.Column(
[
self.name_field,
self.contact_name_field,
self.email_field,
self.phone_field,
self.register_number_field,
self.vat,
self.street_and_number,
self.postal_code,
self.city,
self.region_county,
self.country,
self.first_order_number_field,
self.terms_field,
],
spacing=20,
expand=True
)
],
vertical_alignment=ft.CrossAxisAlignment.START
)
],
scroll=ft.ScrollMode.ADAPTIVE
),
)