add V2
This commit is contained in:
BIN
UI_V2/admin/__pycache__/banner.cpython-313.pyc
Normal file
BIN
UI_V2/admin/__pycache__/banner.cpython-313.pyc
Normal file
Binary file not shown.
BIN
UI_V2/admin/__pycache__/category.cpython-313.pyc
Normal file
BIN
UI_V2/admin/__pycache__/category.cpython-313.pyc
Normal file
Binary file not shown.
BIN
UI_V2/admin/__pycache__/clients.cpython-313.pyc
Normal file
BIN
UI_V2/admin/__pycache__/clients.cpython-313.pyc
Normal file
Binary file not shown.
BIN
UI_V2/admin/__pycache__/dashboard.cpython-313.pyc
Normal file
BIN
UI_V2/admin/__pycache__/dashboard.cpython-313.pyc
Normal file
Binary file not shown.
BIN
UI_V2/admin/__pycache__/orders.cpython-313.pyc
Normal file
BIN
UI_V2/admin/__pycache__/orders.cpython-313.pyc
Normal file
Binary file not shown.
BIN
UI_V2/admin/__pycache__/products.cpython-313.pyc
Normal file
BIN
UI_V2/admin/__pycache__/products.cpython-313.pyc
Normal file
Binary file not shown.
88
UI_V2/admin/banner.py
Normal file
88
UI_V2/admin/banner.py
Normal file
@@ -0,0 +1,88 @@
|
||||
import flet as ft
|
||||
import os
|
||||
import shutil
|
||||
|
||||
class Banner:
|
||||
def __init__(self, page: ft.Page):
|
||||
self.page = page
|
||||
|
||||
self.banner_image = ft.Image(
|
||||
src='images/banner_placeholder.png',
|
||||
height=350,
|
||||
width=1000,
|
||||
fit=ft.ImageFit.COVER
|
||||
)
|
||||
|
||||
self.file_dialog = ft.FilePicker(
|
||||
on_result=self.on_file_picker_result,
|
||||
on_upload=self.on_upload_progress
|
||||
)
|
||||
self.page.overlay.append(self.file_dialog)
|
||||
self.page.update() # Required to register the FilePicker control
|
||||
|
||||
self.uploaded_files = []
|
||||
|
||||
def open_file_picker(self, e=None):
|
||||
self.file_dialog.pick_files(
|
||||
allow_multiple=False,
|
||||
allowed_extensions=["png", "jpg", "jpeg"]
|
||||
)
|
||||
|
||||
def on_file_picker_result(self, e: ft.FilePickerResultEvent):
|
||||
if e.files:
|
||||
file = e.files[0]
|
||||
file_name = file.name
|
||||
upload_url = self.page.get_upload_url(file_name, 600)
|
||||
|
||||
print(f"Uploading {file_name} to {upload_url}")
|
||||
|
||||
upload_task = ft.FilePickerUploadFile(
|
||||
name=file.name,
|
||||
upload_url=upload_url
|
||||
)
|
||||
self.file_dialog.upload([upload_task])
|
||||
|
||||
def on_upload_progress(self, e: ft.FilePickerUploadEvent):
|
||||
if e.progress == 1:
|
||||
print(f"Upload complete: {e.file_name}")
|
||||
|
||||
base_path = os.getcwd() # <-- The correct root path
|
||||
uploads_path = os.path.join(base_path, "uploads")
|
||||
assets_path = os.path.join(base_path, "assets", "images")
|
||||
os.makedirs(assets_path, exist_ok=True)
|
||||
|
||||
source_file = os.path.join(uploads_path, e.file_name)
|
||||
destination_file2 = os.path.join(assets_path, e.file_name)
|
||||
destination_file = os.path.join(assets_path, 'banner.png')
|
||||
|
||||
if not os.path.exists(source_file):
|
||||
print(f"❌ File not found: {source_file}")
|
||||
return
|
||||
|
||||
try:
|
||||
shutil.copy(source_file, destination_file2)
|
||||
shutil.move(source_file, destination_file)
|
||||
print(f"✅ File moved: {source_file} → {destination_file}")
|
||||
self.banner_image.src = f'images/{e.file_name}'
|
||||
self.banner_image.update()
|
||||
self.page.update()
|
||||
self.foto = e.file_name
|
||||
except Exception as ex:
|
||||
print(f"❌ Error moving file: {ex}")
|
||||
|
||||
def build(self):
|
||||
return ft.Container(
|
||||
content=ft.Column(
|
||||
[
|
||||
self.banner_image,
|
||||
ft.Button(
|
||||
"Adauga imagine",
|
||||
on_click=self.open_file_picker,
|
||||
icon=ft.Icons.UPLOAD
|
||||
)
|
||||
],
|
||||
horizontal_alignment=ft.CrossAxisAlignment.CENTER,
|
||||
expand=True
|
||||
),
|
||||
expand=True
|
||||
)
|
||||
242
UI_V2/admin/category.py
Normal file
242
UI_V2/admin/category.py
Normal file
@@ -0,0 +1,242 @@
|
||||
import flet as ft
|
||||
from dbActions.categories import Categories
|
||||
import os
|
||||
import shutil
|
||||
|
||||
class Category:
|
||||
def __init__(self, page: ft.Page):
|
||||
self.page = page
|
||||
self.categories_manager = Categories()
|
||||
self.all_cateogies = self.categories_manager.get_categories()
|
||||
self.list_of_categories = ft.ListView(
|
||||
controls=self.create_list(self.all_cateogies, self.on_edit_btn_click, self.on_delete_btn_click),
|
||||
spacing=10,
|
||||
expand=True
|
||||
)
|
||||
self.foto = None
|
||||
self.edit_id = None
|
||||
|
||||
self.file_dialog = ft.FilePicker(
|
||||
on_result=self.on_file_picker_result,
|
||||
on_upload=self.on_upload_progress
|
||||
)
|
||||
self.page.overlay.append(self.file_dialog)
|
||||
self.page.update() # Required to register the FilePicker control
|
||||
|
||||
self.uploaded_files = []
|
||||
|
||||
self.category_image = ft.Image(
|
||||
width=150,
|
||||
height=150,
|
||||
src='images/placeholder.png',
|
||||
)
|
||||
|
||||
self.category_name = ft.TextField(label="Denumire")
|
||||
|
||||
self.add_dialog = ft.AlertDialog(
|
||||
title=ft.Text("Categorie"),
|
||||
content=ft.Column(
|
||||
[
|
||||
ft.Row(
|
||||
[
|
||||
self.category_image,
|
||||
ft.Button("Incarca", icon=ft.Icons.UPLOAD, on_click=self.open_file_picker)
|
||||
]
|
||||
),
|
||||
self.category_name
|
||||
],
|
||||
height=200,
|
||||
width=400
|
||||
),
|
||||
actions=[
|
||||
ft.Button(
|
||||
"Salveaza",
|
||||
on_click=self.on_save_btn_click,
|
||||
icon=ft.Icons.SAVE,
|
||||
),
|
||||
ft.TextButton(
|
||||
"Anuleaza",
|
||||
on_click=self.on_cancel_btn_click,
|
||||
icon=ft.Icons.CANCEL,
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
self.delete_item_id = None
|
||||
|
||||
self.confirm_delete_alert = ft.AlertDialog(
|
||||
title=ft.Text("Confirmati?"),
|
||||
actions=[
|
||||
ft.Button(
|
||||
"Da",
|
||||
on_click=self.on_delete_product_click,
|
||||
icon=ft.Icons.DELETE,
|
||||
),
|
||||
ft.TextButton(
|
||||
"Nu",
|
||||
on_click=self.on_delete_cancel_btn_click,
|
||||
icon=ft.Icons.CANCEL,
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
def on_file_picker_result(self, e: ft.FilePickerResultEvent):
|
||||
if e.files:
|
||||
file = e.files[0]
|
||||
file_name = file.name
|
||||
upload_url = self.page.get_upload_url(file_name, 600)
|
||||
|
||||
print(f"Uploading {file_name} to {upload_url}")
|
||||
|
||||
upload_task = ft.FilePickerUploadFile(
|
||||
name=file.name,
|
||||
upload_url=upload_url
|
||||
)
|
||||
self.file_dialog.upload([upload_task])
|
||||
|
||||
def open_file_picker(self, e=None):
|
||||
self.file_dialog.pick_files(
|
||||
allow_multiple=False,
|
||||
allowed_extensions=["png", "jpg", "jpeg"]
|
||||
)
|
||||
|
||||
def on_upload_progress(self, e: ft.FilePickerUploadEvent):
|
||||
if e.progress == 1:
|
||||
print(f"Upload complete: {e.file_name}")
|
||||
|
||||
# Resolve paths relative to the UI folder (two levels up from this file)
|
||||
ui_root = os.path.dirname(os.path.dirname(__file__))
|
||||
uploads_path = os.path.join(ui_root, "uploads")
|
||||
assets_path = os.path.join(ui_root, "assets", "images")
|
||||
os.makedirs(assets_path, exist_ok=True)
|
||||
|
||||
source_file = os.path.join(uploads_path, e.file_name)
|
||||
destination_file = os.path.join(assets_path, e.file_name)
|
||||
|
||||
if not os.path.exists(source_file):
|
||||
print(f"❌ File not found: {source_file}")
|
||||
return
|
||||
|
||||
try:
|
||||
shutil.move(source_file, destination_file)
|
||||
print(f"✅ File moved: {source_file} → {destination_file}")
|
||||
self.category_image.src = f'images/{e.file_name}'
|
||||
self.category_image.update()
|
||||
self.page.update()
|
||||
self.foto = e.file_name
|
||||
except Exception as ex:
|
||||
print(f"❌ Error moving file: {ex}")
|
||||
|
||||
def on_add_btn_click(self, e):
|
||||
self.page.open(self.add_dialog)
|
||||
|
||||
def on_save_btn_click(self, e):
|
||||
if self.category_image.src == 'images/placeholder.png' or self.category_name.value == '':
|
||||
return
|
||||
|
||||
if self.edit_id is None:
|
||||
self.categories_manager.add(self.category_name.value, self.category_image.src)
|
||||
else:
|
||||
self.categories_manager.update(self.category_name.value, self.category_image.src, self.edit_id )
|
||||
self.edit_id = None
|
||||
|
||||
self.page.close(self.add_dialog)
|
||||
self.category_image.src = 'images/placeholder.png'
|
||||
self.category_image.update()
|
||||
self.category_name.value = ''
|
||||
self.category_name.update()
|
||||
self.update_list()
|
||||
|
||||
def on_cancel_btn_click(self, e):
|
||||
self.page.close(self.add_dialog)
|
||||
self.category_image.src = 'images/placeholder.png'
|
||||
self.category_image.update()
|
||||
self.category_name.value = ''
|
||||
self.category_name.update()
|
||||
|
||||
def create_list(self, items, on_click_handler, on_click_handler2):
|
||||
"""Helper to create list items for a column."""
|
||||
return [
|
||||
ft.Container(
|
||||
content=ft.Row(
|
||||
[
|
||||
|
||||
ft.Row(
|
||||
[
|
||||
ft.Icon(ft.Icons.ARROW_RIGHT, size=20),
|
||||
ft.Text(value=item['name'])
|
||||
]
|
||||
),
|
||||
|
||||
ft.Row(
|
||||
[
|
||||
ft.IconButton(
|
||||
icon=ft.Icons.EDIT,
|
||||
on_click=lambda e, id=item: on_click_handler(id),
|
||||
),
|
||||
ft.IconButton(
|
||||
icon=ft.Icons.DELETE,
|
||||
on_click=lambda e, id=item['id']: on_click_handler2(id),
|
||||
icon_color=ft.Colors.RED,
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
],
|
||||
alignment=ft.MainAxisAlignment.SPACE_BETWEEN,
|
||||
),
|
||||
width=300,
|
||||
bgcolor=ft.Colors.BROWN_50,
|
||||
border = ft.border.all(1, ft.Colors.GREY),
|
||||
padding=10,
|
||||
border_radius=8,
|
||||
)
|
||||
for item in items
|
||||
]
|
||||
|
||||
def on_edit_btn_click(self, item):
|
||||
self.edit_id = item['id']
|
||||
self.category_name.value = item['name']
|
||||
self.category_image.src = item['image']
|
||||
self.page.open(self.add_dialog)
|
||||
|
||||
def on_delete_btn_click(self, id):
|
||||
self.delete_item_id = id
|
||||
self.page.open(self.confirm_delete_alert)
|
||||
|
||||
def on_delete_product_click(self, e):
|
||||
self.categories_manager.delete(self.delete_item_id )
|
||||
self.delete_item_id = None
|
||||
self.page.close(self.confirm_delete_alert)
|
||||
print('Update list')
|
||||
self.update_list()
|
||||
|
||||
def on_delete_cancel_btn_click(self, e):
|
||||
self.delete_item_id = None
|
||||
self.page.close(self.confirm_delete_alert)
|
||||
|
||||
def update_list(self):
|
||||
self.all_cateogies = self.categories_manager.get_categories()
|
||||
self.list_of_categories.controls.clear()
|
||||
self.list_of_categories.controls = self.create_list(self.all_cateogies, self.on_edit_btn_click, self.on_delete_btn_click)
|
||||
self.list_of_categories.update()
|
||||
self.page.update()
|
||||
|
||||
def build(self):
|
||||
return ft.Container(
|
||||
content=ft.Column(
|
||||
[
|
||||
ft.Row(
|
||||
[
|
||||
ft.Text("Categori", size=18, weight=ft.FontWeight.BOLD),
|
||||
ft.Button("Adauga", icon=ft.Icons.ADD, on_click=self.on_add_btn_click),
|
||||
],
|
||||
alignment=ft.MainAxisAlignment.SPACE_BETWEEN
|
||||
),
|
||||
self.list_of_categories
|
||||
],
|
||||
alignment=ft.MainAxisAlignment.START,
|
||||
expand=True
|
||||
),
|
||||
expand=True,
|
||||
)
|
||||
352
UI_V2/admin/clients.py
Normal file
352
UI_V2/admin/clients.py
Normal file
@@ -0,0 +1,352 @@
|
||||
import flet as ft
|
||||
from dbActions.users import Users
|
||||
from dbActions.company import Company
|
||||
|
||||
class Clients:
|
||||
def __init__(self, page: ft.Page):
|
||||
self.page = page
|
||||
self.user_manager = Users()
|
||||
self.company_manager = Company()
|
||||
|
||||
self.user_name = ft.TextField(label="Nume si Prenume")
|
||||
self.email = ft.TextField(label="E-mail")
|
||||
self.phone = ft.TextField(label="Telefon")
|
||||
self.address = ft.TextField(label="Adresa", multiline=True, min_lines=3, max_lines=5)
|
||||
self.company_name = ft.TextField(label="Denumire firma")
|
||||
self.vat = ft.TextField(label="CUI")
|
||||
self.register_number = ft.TextField(label="Numar registru comert")
|
||||
self.company_address = ft.TextField(label="Sediu", multiline=True, min_lines=3, max_lines=5)
|
||||
self.company_placeholder = ft.Column()
|
||||
self.second_address_placeholder = ft.Column()
|
||||
self.second_address = ft.TextField(
|
||||
label="Adresa de livrare",
|
||||
multiline=True,
|
||||
min_lines=3,
|
||||
max_lines=5
|
||||
)
|
||||
|
||||
self.client_column = ft.Column(
|
||||
[
|
||||
self.user_name,
|
||||
self.email,
|
||||
self.phone,
|
||||
self.address,
|
||||
ft.Button("Persoana Juridica?", on_click=self.on_is_comopany_btn_click),
|
||||
self.company_placeholder,
|
||||
ft.Button("Adresa de livrare difera de adresa de domiciliu?", on_click=self.on_second_address),
|
||||
self.second_address_placeholder
|
||||
],
|
||||
scroll=ft.ScrollMode.ADAPTIVE,
|
||||
width=400,
|
||||
auto_scroll=True
|
||||
)
|
||||
|
||||
self.add_user_dialog = ft.AlertDialog(
|
||||
title="Client",
|
||||
content=self.client_column,
|
||||
actions=[
|
||||
ft.Button(
|
||||
"Salveaza",
|
||||
on_click=self.on_save_btn_click,
|
||||
icon=ft.Icons.SAVE,
|
||||
),
|
||||
ft.TextButton(
|
||||
"Anuleaza",
|
||||
on_click=self.on_cancel_btn_click,
|
||||
icon=ft.Icons.CANCEL,
|
||||
),
|
||||
]
|
||||
)
|
||||
self.is_company = False
|
||||
self.is_second_address = False
|
||||
|
||||
self.all_clients = self.user_manager.get_all()
|
||||
self.list_of_clients = ft.ListView(
|
||||
controls=self.create_list(self.all_clients, self.on_edit_btn_click, self.on_delete_btn_click, self.on_view_btn_click),
|
||||
spacing=10,
|
||||
expand=True
|
||||
)
|
||||
|
||||
self.view_name = ft.Text()
|
||||
self.view_email = ft.Text()
|
||||
self.view_phone = ft.Text()
|
||||
self.view_address = ft.Text()
|
||||
self.view_company_placeholder = ft.Column()
|
||||
self.view_second_address_placeholder = ft.Column()
|
||||
|
||||
self.view_company_name = ft.Text()
|
||||
self.view_company_vat = ft.Text()
|
||||
self.view_company_rn = ft.Text()
|
||||
self.view_company_address = ft.Text()
|
||||
self.view_second_address = ft.Text()
|
||||
|
||||
self.view_dialog = ft.AlertDialog(
|
||||
title=ft.Text("Vizualizeaza"),
|
||||
content=ft.Column(
|
||||
[
|
||||
ft.Text("Utilizator:", weight=ft.FontWeight.BOLD),
|
||||
self.view_name,
|
||||
self.view_email,
|
||||
self.view_phone,
|
||||
self.view_address,
|
||||
self.view_company_placeholder,
|
||||
self.view_second_address_placeholder
|
||||
],
|
||||
scroll=ft.ScrollMode.ADAPTIVE,
|
||||
width=400
|
||||
),
|
||||
actions=[
|
||||
ft.Button("Ok", on_click=self.on_ok_btn_click)
|
||||
]
|
||||
)
|
||||
|
||||
self.delete_item_id = None
|
||||
|
||||
self.confirm_delete_alert = ft.AlertDialog(
|
||||
title=ft.Text("Confirmati?"),
|
||||
actions=[
|
||||
ft.Button(
|
||||
"Da",
|
||||
on_click=self.on_delete_client_click,
|
||||
icon=ft.Icons.DELETE,
|
||||
),
|
||||
ft.TextButton(
|
||||
"Nu",
|
||||
on_click=self.on_delete_cancel_btn_click,
|
||||
icon=ft.Icons.CANCEL,
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
self.edit_id = None
|
||||
|
||||
def on_ok_btn_click(self, e):
|
||||
self.page.close(self.view_dialog)
|
||||
self.view_name.value = ''
|
||||
self.view_email.value = ''
|
||||
self.view_phone.value = ''
|
||||
self.view_address.value = ''
|
||||
self.view_company_placeholder.controls.clear()
|
||||
self.view_second_address_placeholder.controls.clear()
|
||||
|
||||
def on_edit_btn_click(self, item):
|
||||
self.edit_id = item['id']
|
||||
self.user_name.value = item['name']
|
||||
self.email.value = item['email']
|
||||
self.email.disabled = True
|
||||
self.phone.value = item['phone']
|
||||
self.address.value = item['address'].split("~")[0]
|
||||
company = self.company_manager.get_company(item['id'])
|
||||
if company:
|
||||
self.company_name.value = company['name']
|
||||
self.company_placeholder.controls.append(self.company_name)
|
||||
self.vat.value = company['vat']
|
||||
self.company_placeholder.controls.append(self.vat)
|
||||
self.register_number.value = company['register_number']
|
||||
self.company_placeholder.controls.append(self.register_number)
|
||||
self.company_address.value = company['address']
|
||||
self.company_placeholder.controls.append(self.company_address)
|
||||
if len(item['address'].split("~")) > 1:
|
||||
self.second_address.value = item['address'].split("~")[1]
|
||||
self.second_address_placeholder.controls.append(self.second_address)
|
||||
self.page.open(self.add_user_dialog)
|
||||
|
||||
def on_delete_btn_click(self, id):
|
||||
self.delete_item_id = id
|
||||
self.page.open(self.confirm_delete_alert)
|
||||
|
||||
def on_delete_client_click(self, e):
|
||||
self.user_manager.delete(self.delete_item_id)
|
||||
self.delete_item_id = None
|
||||
self.page.close(self.confirm_delete_alert)
|
||||
self.all_clients = self.user_manager.get_all()
|
||||
self.list_of_clients.controls = self.create_list(self.all_clients, self.on_edit_btn_click, self.on_delete_btn_click, self.on_view_btn_click)
|
||||
self.list_of_clients.update()
|
||||
|
||||
def on_delete_cancel_btn_click(self, e):
|
||||
self.delete_item_id = None
|
||||
self.page.close(self.confirm_delete_alert)
|
||||
|
||||
def on_view_btn_click(self, item):
|
||||
self.view_name.value = f"Nume: {item['name']}"
|
||||
self.view_email.value = f"E-mail: {item['email']}"
|
||||
self.view_phone.value = f"Telefon: {item['phone']}"
|
||||
self.view_address.value = f"Adresa: {item['address'].split("~")[0]}"
|
||||
company = self.company_manager.get_company(item['id'])
|
||||
if company:
|
||||
self.view_company_placeholder.controls.append(ft.Text(""))
|
||||
self.view_company_placeholder.controls.append(ft.Text("Date Companie:", weight=ft.FontWeight.BOLD))
|
||||
self.view_company_name.value = f"Denumire: {company['name']}"
|
||||
self.view_company_placeholder.controls.append(self.view_company_name)
|
||||
self.view_company_vat.value = f"CUI: {company['vat']}"
|
||||
self.view_company_placeholder.controls.append(self.view_company_vat)
|
||||
self.view_company_rn.value = f"Registru comertului: {company['register_number']}"
|
||||
self.view_company_placeholder.controls.append(self.view_company_rn)
|
||||
self.view_company_address.value = f"Sediu: {company['address']}"
|
||||
self.view_company_placeholder.controls.append(self.view_company_address)
|
||||
if len(item['address'].split("~")) > 1:
|
||||
self.view_second_address_placeholder.controls.append(ft.Text(""))
|
||||
self.view_second_address_placeholder.controls.append(ft.Text("Adresa Livrare:", weight=ft.FontWeight.BOLD))
|
||||
self.view_second_address.value = f"Adresa: {item['address'].split("~")[1]}"
|
||||
self.view_second_address_placeholder.controls.append(self.view_second_address)
|
||||
self.page.open(self.view_dialog)
|
||||
|
||||
def create_list(self, items, on_click_handler, on_click_handler2, on_click_handler3):
|
||||
"""Helper to create list items for a column."""
|
||||
return [
|
||||
ft.Container(
|
||||
content=ft.Row(
|
||||
[
|
||||
|
||||
ft.Column(
|
||||
[
|
||||
ft.Text(value=item['name'], weight=ft.FontWeight.BOLD),
|
||||
ft.Text(value=item['email'], size=12)
|
||||
]
|
||||
),
|
||||
|
||||
ft.Row(
|
||||
[
|
||||
ft.IconButton(
|
||||
icon=ft.Icons.PREVIEW,
|
||||
on_click=lambda e, id=item: on_click_handler3(id),
|
||||
),
|
||||
ft.IconButton(
|
||||
icon=ft.Icons.EDIT,
|
||||
on_click=lambda e, id=item: on_click_handler(id),
|
||||
),
|
||||
ft.IconButton(
|
||||
icon=ft.Icons.DELETE,
|
||||
on_click=lambda e, id=item['id']: on_click_handler2(id),
|
||||
icon_color=ft.Colors.RED,
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
],
|
||||
alignment=ft.MainAxisAlignment.SPACE_BETWEEN,
|
||||
),
|
||||
width=300,
|
||||
bgcolor=ft.Colors.BROWN_50,
|
||||
border = ft.border.all(1, ft.Colors.GREY),
|
||||
padding=10,
|
||||
border_radius=8,
|
||||
)
|
||||
for item in items
|
||||
]
|
||||
|
||||
def on_save_btn_click(self, e):
|
||||
user_name = self.user_name.value
|
||||
user_email = self.email.value
|
||||
user_phone = self.phone.value
|
||||
user_address = self.address.value
|
||||
company = {}
|
||||
|
||||
company['name'] = self.company_name.value
|
||||
company['vat'] = self.vat.value
|
||||
company['register_number'] = self.register_number.value
|
||||
company['address'] = self.company_address.value
|
||||
delivery_address = self.second_address.value
|
||||
address = f'{user_address} ~ {delivery_address}'
|
||||
if self.edit_id:
|
||||
if len(delivery_address) == 0:
|
||||
self.user_manager.update_user_data(user_name, user_phone, user_address, self.edit_id)
|
||||
else:
|
||||
self.user_manager.update_user_data(user_name, user_phone, address, self.edit_id)
|
||||
exising_company = self.company_manager.get_company(self.edit_id)
|
||||
if exising_company:
|
||||
company['user_id'] = self.edit_id
|
||||
company['id'] = exising_company['id']
|
||||
self.company_manager.update_company(company)
|
||||
else:
|
||||
|
||||
user_id = self.user_manager.invite_user(user_email, user_name, user_phone, user_address)
|
||||
print(user_id)
|
||||
if user_id:
|
||||
company['user_id'] = user_id
|
||||
if self.is_company:
|
||||
self.company_manager.add_company(company)
|
||||
if self.is_second_address:
|
||||
self.user_manager.update_user_data(user_name, user_phone, address, user_id)
|
||||
self.clear_fileds()
|
||||
self.page.close(self.add_user_dialog)
|
||||
self.all_clients = self.user_manager.get_all()
|
||||
self.list_of_clients.controls = self.create_list(self.all_clients, self.on_edit_btn_click, self.on_delete_btn_click, self.on_view_btn_click)
|
||||
self.list_of_clients.update()
|
||||
|
||||
def on_cancel_btn_click(self, e):
|
||||
self.page.close(self.add_user_dialog)
|
||||
self.clear_fileds()
|
||||
|
||||
def clear_fileds(self):
|
||||
self.user_name.value = ''
|
||||
self.user_name.update()
|
||||
self.email.value = ''
|
||||
self.email.update()
|
||||
self.phone.value = ''
|
||||
self.phone.update()
|
||||
self.address.value = ''
|
||||
self.address.update()
|
||||
try:
|
||||
self.company_name.value = ''
|
||||
self.company_name.update()
|
||||
self.vat.value = ''
|
||||
self.vat.update()
|
||||
self.register_number.value = ''
|
||||
self.register_number.update()
|
||||
self.company_address.value = ''
|
||||
self.company_address.update()
|
||||
except Exception as e:
|
||||
print(f'No company, Error: {e}')
|
||||
try:
|
||||
self.second_address.value = ''
|
||||
self.second_address.update()
|
||||
except Exception as e:
|
||||
print(f'No second address, Error: {e}')
|
||||
self.company_placeholder.controls.clear()
|
||||
self.company_placeholder.update()
|
||||
self.second_address_placeholder.controls.clear()
|
||||
self.second_address_placeholder.update()
|
||||
|
||||
def on_is_comopany_btn_click(self, e):
|
||||
self.is_company = True
|
||||
self.company_placeholder.controls.append(ft.Text("Date firma"))
|
||||
self.company_placeholder.controls.append(self.company_name)
|
||||
self.company_placeholder.controls.append(self.vat)
|
||||
self.company_placeholder.controls.append(self.register_number)
|
||||
self.company_placeholder.controls.append(self.company_address)
|
||||
self.company_placeholder.update()
|
||||
|
||||
def on_second_address(self, e):
|
||||
self.is_second_address = True
|
||||
self.second_address_placeholder.controls.append(ft.Text("Adresa de livrare"))
|
||||
self.second_address_placeholder.controls.append(
|
||||
self.second_address
|
||||
)
|
||||
self.second_address_placeholder.update()
|
||||
|
||||
def on_add_btn_click(self, e):
|
||||
self.page.open(self.add_user_dialog)
|
||||
|
||||
def build(self):
|
||||
return ft.Container(
|
||||
content=ft.Column(
|
||||
[
|
||||
ft.Row(
|
||||
[
|
||||
ft.Text("Clienti",
|
||||
weight=ft.FontWeight.BOLD,
|
||||
size=18
|
||||
),
|
||||
ft.Button(
|
||||
icon=ft.Icons.ADD,
|
||||
text = "Invita",
|
||||
on_click= self.on_add_btn_click
|
||||
)
|
||||
],
|
||||
alignment=ft.MainAxisAlignment.SPACE_BETWEEN
|
||||
),
|
||||
self.list_of_clients
|
||||
]
|
||||
)
|
||||
)
|
||||
128
UI_V2/admin/dashboard.py
Normal file
128
UI_V2/admin/dashboard.py
Normal file
@@ -0,0 +1,128 @@
|
||||
import flet as ft
|
||||
from admin.category import Category
|
||||
from admin.products import ProductsPage
|
||||
from admin.banner import Banner
|
||||
from admin.orders import OrdersPage
|
||||
from admin.clients import Clients
|
||||
|
||||
class Dashboard:
|
||||
def __init__(self, page: ft.Page):
|
||||
self.page = page
|
||||
self.category = Category(self.page)
|
||||
self.placeholder = ft.Container(
|
||||
content=self.category.build(),
|
||||
padding=10,
|
||||
expand=True
|
||||
)
|
||||
self.rail = ft.NavigationRail(
|
||||
selected_index=0,
|
||||
label_type=ft.NavigationRailLabelType.ALL,
|
||||
min_width=100,
|
||||
#min_extended_width=400,
|
||||
leading=ft.Image('images/tainagustului.png', width=80),
|
||||
group_alignment=-0.9,
|
||||
destinations=[
|
||||
ft.NavigationRailDestination(
|
||||
icon=ft.Icons.CATEGORY_OUTLINED,
|
||||
selected_icon=ft.Icons.CATEGORY_ROUNDED,
|
||||
label="Categori",
|
||||
),
|
||||
ft.NavigationRailDestination(
|
||||
icon=ft.Icons.ADD_BOX_OUTLINED,
|
||||
selected_icon=ft.Icons.ADD_BOX_ROUNDED,
|
||||
label="Produse",
|
||||
),
|
||||
ft.NavigationRailDestination(
|
||||
icon=ft.Icon(ft.Icons.MANAGE_ACCOUNTS_OUTLINED),
|
||||
selected_icon=ft.Icon(ft.Icons.MANAGE_ACCOUNTS_ROUNDED),
|
||||
label="Clienti",
|
||||
),
|
||||
ft.NavigationRailDestination(
|
||||
icon=ft.Icons.SHOPPING_CART_OUTLINED,
|
||||
selected_icon=ft.Icon(ft.Icons.SHOPPING_CART_ROUNDED),
|
||||
label_content=ft.Text("Comenzi"),
|
||||
),
|
||||
ft.NavigationRailDestination(
|
||||
icon=ft.Icons.SHOPIFY_OUTLINED,
|
||||
selected_icon=ft.Icon(ft.Icons.SHOPIFY_ROUNDED),
|
||||
label_content=ft.Text("Magazin"),
|
||||
),
|
||||
ft.NavigationRailDestination(
|
||||
icon=ft.Icons.IMAGE_OUTLINED,
|
||||
selected_icon=ft.Icon(ft.Icons.IMAGE_ROUNDED),
|
||||
label_content=ft.Text("Banner"),
|
||||
),
|
||||
ft.NavigationRailDestination(
|
||||
icon=ft.Icons.LOGOUT_OUTLINED,
|
||||
selected_icon=ft.Icon(ft.Icons.LOGOUT_ROUNDED),
|
||||
label_content=ft.Text("Logout"),
|
||||
),
|
||||
],
|
||||
on_change=lambda e: self.navigate_to(e),
|
||||
)
|
||||
|
||||
def navigate_to(self, e):
|
||||
index = e.control.selected_index
|
||||
match index:
|
||||
case 0:
|
||||
self.category = Category(self.page)
|
||||
self.placeholder.content = self.category.build()
|
||||
self.placeholder.update()
|
||||
case 1:
|
||||
self.products = ProductsPage(self.page)
|
||||
self.placeholder.content = self.products.build()
|
||||
self.placeholder.update()
|
||||
case 2:
|
||||
self.clients = Clients(self.page)
|
||||
self.placeholder.content = self.clients.build()
|
||||
self.placeholder.update()
|
||||
case 3:
|
||||
self.orders = OrdersPage(self.page)
|
||||
self.placeholder.content = self.orders.build()
|
||||
self.placeholder.update()
|
||||
case 4:
|
||||
self.page.launch_url('http://0.0.0.0:5555/')
|
||||
case 5:
|
||||
self.banner = Banner(self.page)
|
||||
self.placeholder.content = self.banner.build()
|
||||
self.placeholder.update()
|
||||
case 6:
|
||||
self.page.client_storage.clear()
|
||||
self.page.session.clear()
|
||||
self.page.go('/')
|
||||
|
||||
def build(self):
|
||||
if self.page.session.get("user") is None or self.page.session.get("user")['role'] != 'admin':
|
||||
return ft.Container(
|
||||
content=ft.Column(
|
||||
[
|
||||
ft.Text(
|
||||
"Nu aveti drepturi sa accesati pagina de admin!",
|
||||
size=20,
|
||||
weight=ft.FontWeight.BOLD,
|
||||
text_align=ft.TextAlign.CENTER
|
||||
),
|
||||
ft.Text("Va rugam sa va autentificati cu un rol de admin",text_align=ft.TextAlign.CENTER)
|
||||
],
|
||||
alignment=ft.MainAxisAlignment.CENTER,
|
||||
horizontal_alignment=ft.CrossAxisAlignment.CENTER
|
||||
)
|
||||
)
|
||||
else:
|
||||
return ft.Container(
|
||||
content=ft.Column(
|
||||
[
|
||||
ft.Row(
|
||||
[
|
||||
self.rail,
|
||||
ft.VerticalDivider(width=1),
|
||||
self.placeholder
|
||||
],
|
||||
expand=True
|
||||
),
|
||||
#self.shop_page
|
||||
],
|
||||
expand=True
|
||||
),
|
||||
expand=True
|
||||
)
|
||||
374
UI_V2/admin/orders.py
Normal file
374
UI_V2/admin/orders.py
Normal file
@@ -0,0 +1,374 @@
|
||||
import flet as ft
|
||||
from dbActions.orders import Orders
|
||||
from dbActions.users import Users
|
||||
from dbActions.products import Products
|
||||
from helpers.default_user import DefaultUser
|
||||
|
||||
class OrdersPage:
|
||||
def __init__(self, page: ft.Page):
|
||||
self.page = page
|
||||
self.orders = Orders()
|
||||
self.users = Users()
|
||||
self.products = Products()
|
||||
self.selected_user = None
|
||||
self.selected_order = None
|
||||
self.selected_order_products = None
|
||||
self.original_status = None
|
||||
self.customer_email = None
|
||||
self.default_user = DefaultUser(self.page)
|
||||
self.header = ft.Row(
|
||||
[
|
||||
ft.Text(
|
||||
"Comenzi",
|
||||
weight=ft.FontWeight.BOLD,
|
||||
size=18
|
||||
),
|
||||
],
|
||||
alignment=ft.MainAxisAlignment.START
|
||||
)
|
||||
self.all_orders = self.orders.get_orders()
|
||||
self.all_orders = self.all_orders[::-1]
|
||||
self.oll_orders_list = ft.ListView(
|
||||
controls=self.create_list(self.all_orders, self.on_order_click),
|
||||
spacing=10,
|
||||
expand=3,
|
||||
height=700
|
||||
)
|
||||
self.fileters = ft.RadioGroup(
|
||||
content=ft.Row(
|
||||
[
|
||||
ft.Radio(value="on_hold", label="In asteptare"),
|
||||
ft.Radio(value="new", label="Noua"),
|
||||
ft.Radio(value="in_progress", label="In lucru"),
|
||||
ft.Radio(value="completed", label="Complete"),
|
||||
ft.Radio(value="all", label="Toate")
|
||||
]
|
||||
),
|
||||
on_change=self.on_filter_change
|
||||
)
|
||||
self.name = ft.Text()
|
||||
self.email = ft.Text()
|
||||
self.phone = ft.Text()
|
||||
self.address = ft.Text()
|
||||
self.total_pay = ft.Text(weight=ft.FontWeight.BOLD)
|
||||
self.products_column = ft.Column([])
|
||||
self.status = ft.Text()
|
||||
self.buttons_state = ft.RadioGroup(
|
||||
content=ft.Row(
|
||||
[
|
||||
ft.Radio(value="on_hold", label="In asteptare"),
|
||||
ft.Radio(value="new", label="Noua"),
|
||||
ft.Radio(value="in_progress", label="In lucru"),
|
||||
ft.Radio(value="completed", label="Complete"),
|
||||
],
|
||||
),
|
||||
on_change=self.on_radio_value_change
|
||||
)
|
||||
self.total_row = ft.Row(
|
||||
[
|
||||
ft.Text(
|
||||
value="Total platit",
|
||||
weight=ft.FontWeight.BOLD,
|
||||
),
|
||||
self.total_pay
|
||||
],
|
||||
alignment=ft.MainAxisAlignment.SPACE_BETWEEN
|
||||
)
|
||||
|
||||
self.order_details = ft.Column(
|
||||
[
|
||||
ft.Text(
|
||||
value="Detalii utilizator",
|
||||
weight=ft.FontWeight.BOLD,
|
||||
size=18
|
||||
),
|
||||
ft.Row(
|
||||
[
|
||||
ft.Text(
|
||||
value="Nume si prenume",
|
||||
weight=ft.FontWeight.BOLD,
|
||||
),
|
||||
self.name
|
||||
],
|
||||
alignment=ft.MainAxisAlignment.SPACE_BETWEEN
|
||||
),
|
||||
ft.Row(
|
||||
[
|
||||
ft.Text(
|
||||
value="E-mail",
|
||||
weight=ft.FontWeight.BOLD,
|
||||
),
|
||||
self.email
|
||||
],
|
||||
alignment=ft.MainAxisAlignment.SPACE_BETWEEN
|
||||
),
|
||||
ft.Row(
|
||||
[
|
||||
ft.Text(
|
||||
value="Telefon",
|
||||
weight=ft.FontWeight.BOLD,
|
||||
),
|
||||
self.phone
|
||||
],
|
||||
alignment=ft.MainAxisAlignment.SPACE_BETWEEN
|
||||
),
|
||||
ft.Row(
|
||||
[
|
||||
ft.Text(
|
||||
value="Adresa",
|
||||
weight=ft.FontWeight.BOLD,
|
||||
),
|
||||
self.address
|
||||
],
|
||||
alignment=ft.MainAxisAlignment.SPACE_BETWEEN
|
||||
),
|
||||
ft.Row(
|
||||
[
|
||||
ft.Text(
|
||||
value="Status",
|
||||
weight=ft.FontWeight.BOLD,
|
||||
),
|
||||
self.status,
|
||||
],
|
||||
alignment=ft.MainAxisAlignment.SPACE_BETWEEN
|
||||
),
|
||||
self.total_row,
|
||||
ft.Divider(),
|
||||
ft.Text(
|
||||
value="Produse",
|
||||
weight=ft.FontWeight.BOLD,
|
||||
size=18
|
||||
),
|
||||
self.products_column,
|
||||
ft.Divider(),
|
||||
self.buttons_state
|
||||
],
|
||||
expand=True
|
||||
)
|
||||
|
||||
self.order_details_placeholder = ft.Container(
|
||||
expand=7,
|
||||
padding=10,
|
||||
border_radius=10,
|
||||
)
|
||||
|
||||
self.message_field = ft.TextField(
|
||||
label="Scrie un mesaj clientului",
|
||||
min_lines=3,
|
||||
max_lines=5,
|
||||
multiline=True
|
||||
)
|
||||
|
||||
self.change_state_dialog = ft.AlertDialog(
|
||||
title=ft.Text("Modifica statusul"),
|
||||
content=self.message_field,
|
||||
actions=[
|
||||
ft.FilledButton(
|
||||
"Da",
|
||||
on_click=self.on_change_state_btn_click
|
||||
),
|
||||
ft.FilledButton(
|
||||
"Nu",
|
||||
on_click=self.on_cancel_state_btn_click,
|
||||
bgcolor=ft.Colors.GREY
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
def on_radio_value_change(self, e):
|
||||
self.page.open(self.change_state_dialog)
|
||||
|
||||
def on_change_state_btn_click(self, e):
|
||||
self.page.close(self.change_state_dialog)
|
||||
status = self.buttons_state.value
|
||||
self.orders.update_order_status(status, self.selected_order['id'])
|
||||
print(status)
|
||||
self.all_orders = self.orders.get_orders()
|
||||
self.all_orders = self.all_orders[::-1]
|
||||
self.oll_orders_list.controls.clear()
|
||||
self.oll_orders_list.controls = self.create_list(self.all_orders, self.on_order_click)
|
||||
self.oll_orders_list.update()
|
||||
self.order_details_placeholder.content = None
|
||||
self.order_details_placeholder.update()
|
||||
#-------------------------------------------> TBI Send information email to customer
|
||||
message = self.message_field.value
|
||||
self.message_field.value = ''
|
||||
self.message_field.update()
|
||||
print(message)
|
||||
email = self.customer_email
|
||||
|
||||
def on_cancel_state_btn_click(self, e):
|
||||
self.buttons_state.value = self.original_status
|
||||
self.buttons_state.update()
|
||||
self.page.close(self.change_state_dialog)
|
||||
|
||||
def get_total_pay(self):
|
||||
sume = 0
|
||||
print (self.selected_order_products)
|
||||
if self.selected_order_products:
|
||||
for product in self.selected_order_products:
|
||||
sume += (product['price'] - product['price']*product['discount']/100)
|
||||
print(sume)
|
||||
return sume
|
||||
|
||||
def on_order_click(self, item):
|
||||
self.products_column.controls.clear()
|
||||
self.order_details_placeholder.content = None
|
||||
self.order_details_placeholder.content = self.order_details
|
||||
self.order_details_placeholder.bgcolor=ft.Colors.BROWN_50
|
||||
try:
|
||||
self.order_details_placeholder.update()
|
||||
except:
|
||||
print('ERROR Unable to update the Order Details Placeholder')
|
||||
print("order item", item)
|
||||
self.selected_user = self.users.get(item['user_id'])
|
||||
if self.selected_user == None:
|
||||
self.selected_user = self.default_user.default_user
|
||||
self.selected_order = item
|
||||
products = self.orders.get_order_products(item['id'])
|
||||
self.selected_order_products = []
|
||||
if products:
|
||||
for product in products:
|
||||
prod = self.products.get(product['prdouct_id'])
|
||||
print(prod)
|
||||
if prod:
|
||||
self.selected_order_products.append(prod)
|
||||
|
||||
self.name.value = self.selected_user['name'] if '@default.com' not in self.selected_user['email'] else 'Anonim user'
|
||||
self.name.update()
|
||||
self.email.value = self.selected_user['email']
|
||||
self.email.update()
|
||||
self.customer_email = self.selected_user['email']
|
||||
self.address.value = self.selected_user['address'] if '@default.com' not in self.selected_user['email'] else 'Anonim user'
|
||||
self.address.update()
|
||||
self.phone.value = self.selected_user['phone'] if '@default.com' not in self.selected_user['email'] else 'Anonim user'
|
||||
self.phone.update()
|
||||
self.status.value = "Status"
|
||||
self.status.update()
|
||||
for product in self.selected_order_products:
|
||||
name_label = ft.Text(
|
||||
"Denumire produs",
|
||||
weight=ft.FontWeight.BOLD
|
||||
)
|
||||
name = ft.Text(product['name'])
|
||||
name_row = ft.Row(
|
||||
[
|
||||
name_label,
|
||||
name
|
||||
]
|
||||
)
|
||||
image = ft.Image(
|
||||
src=product['image'],
|
||||
width=200,
|
||||
height=200,
|
||||
fit=ft.ImageFit.CONTAIN
|
||||
)
|
||||
quantity_label = ft.Text("Cantitate")
|
||||
quantity = ft.Text(product['quantity'])
|
||||
quantity_row = ft.Row(
|
||||
[
|
||||
quantity_label,
|
||||
quantity
|
||||
]
|
||||
)
|
||||
product_row = ft.Row(
|
||||
[
|
||||
image,
|
||||
ft.Column(
|
||||
[
|
||||
name_row,
|
||||
quantity_row
|
||||
]
|
||||
)
|
||||
]
|
||||
)
|
||||
self.products_column.controls.append(product_row)
|
||||
print(self.products_column.controls)
|
||||
self.total_pay.value = f"{self.get_total_pay()} Lei"
|
||||
self.total_pay.update()
|
||||
self.products_column.update()
|
||||
|
||||
self.buttons_state.value = item['status']
|
||||
self.buttons_state.update()
|
||||
self.original_status = item['status']
|
||||
|
||||
def on_filter_change(self, e):
|
||||
print(e.data)
|
||||
buffer = []
|
||||
if e.data == 'all':
|
||||
self.oll_orders_list.controls = self.create_list(self.all_orders, self.on_order_click)
|
||||
self.oll_orders_list.update()
|
||||
else:
|
||||
for order in self.all_orders:
|
||||
if order['status'] == e.data:
|
||||
buffer.append(order)
|
||||
self.oll_orders_list.controls = self.create_list(buffer, self.on_order_click)
|
||||
self.oll_orders_list.update()
|
||||
|
||||
def get_status(self, status):
|
||||
STATUS = {
|
||||
'on_hold': "In asteptare",
|
||||
'new': "Noua",
|
||||
'in_progress': "In lucru",
|
||||
"completed": "Completa"
|
||||
}
|
||||
return STATUS[status]
|
||||
|
||||
def create_list(self, items, on_click_handler):
|
||||
return [
|
||||
ft.Container(
|
||||
content=ft.Row(
|
||||
[
|
||||
|
||||
ft.Row(
|
||||
[
|
||||
ft.Icon(ft.Icons.ARROW_RIGHT, size=20),
|
||||
ft.Text(value=item['id'])
|
||||
]
|
||||
),
|
||||
ft.Row(
|
||||
[
|
||||
ft.Text(
|
||||
value=self.get_status(item['status'])
|
||||
)
|
||||
]
|
||||
)
|
||||
],
|
||||
alignment=ft.MainAxisAlignment.SPACE_BETWEEN,
|
||||
),
|
||||
width=300,
|
||||
bgcolor=ft.Colors.BROWN_50,
|
||||
padding=10,
|
||||
border_radius=8,
|
||||
ink=True,
|
||||
on_click=lambda e, i=item: on_click_handler(i),
|
||||
border = ft.border.all(1, ft.Colors.GREY),
|
||||
)
|
||||
for item in items
|
||||
]
|
||||
|
||||
def build(self):
|
||||
return ft.Container(
|
||||
content=ft.Column(
|
||||
[
|
||||
self.header,
|
||||
ft.Row(
|
||||
[
|
||||
ft.Text(value="Filtreaza dupa"),
|
||||
self.fileters
|
||||
]
|
||||
),
|
||||
ft.Row(
|
||||
[
|
||||
self.oll_orders_list,
|
||||
self.order_details_placeholder
|
||||
],
|
||||
vertical_alignment=ft.CrossAxisAlignment.START
|
||||
)
|
||||
],
|
||||
alignment=ft.MainAxisAlignment.START,
|
||||
expand=True,
|
||||
#scroll=ft.ScrollMode.ADAPTIVE
|
||||
),
|
||||
expand=True,
|
||||
)
|
||||
308
UI_V2/admin/products.py
Normal file
308
UI_V2/admin/products.py
Normal file
@@ -0,0 +1,308 @@
|
||||
import flet as ft
|
||||
from dbActions.categories import Categories
|
||||
from dbActions.products import Products
|
||||
import os
|
||||
import shutil
|
||||
|
||||
class ProductsPage:
|
||||
def __init__(self, page: ft.Page):
|
||||
self.page = page
|
||||
self.category_manager = Categories()
|
||||
self.product_manager = Products()
|
||||
|
||||
self.name = ft.TextField(label="Denumire")
|
||||
self.description = ft.TextField(label="Descriere", multiline=True, min_lines=3, max_lines=5)
|
||||
self.details = ft.TextField(label="Detalii", multiline=True, min_lines=3, max_lines=5)
|
||||
self.price = ft.TextField(label="Pret")
|
||||
self.discount = ft.TextField(label="Reducere (%)")
|
||||
self.quantity = ft.TextField(label="Cantitate")
|
||||
self.product_image = ft.Image(
|
||||
width=150,
|
||||
height=150,
|
||||
src='images/placeholder.png',
|
||||
)
|
||||
|
||||
self.aviability = ft.Dropdown(
|
||||
label='Disonibilitate',
|
||||
options=[
|
||||
ft.dropdown.Option(key='in_stock', text="In stoc"),
|
||||
ft.dropdown.Option(key='in_provider_stock', text="In stoc la furnizor"),
|
||||
ft.dropdown.Option(key='not_available', text="Indisponibil"),
|
||||
],
|
||||
expand=True
|
||||
)
|
||||
|
||||
self.category = ft.Dropdown(
|
||||
label="Categorie",
|
||||
options=self.get_categories(),
|
||||
expand=True
|
||||
)
|
||||
|
||||
|
||||
self.add_product_dialog = ft.AlertDialog(
|
||||
title=ft.Text("Produs"),
|
||||
content=ft.Column(
|
||||
[
|
||||
ft.Row(
|
||||
[
|
||||
self.product_image,
|
||||
ft.Button("Incarca", icon=ft.Icons.UPLOAD, on_click=self.open_file_picker)
|
||||
]
|
||||
),
|
||||
self.name,
|
||||
self.category,
|
||||
self.description,
|
||||
self.details,
|
||||
self.price,
|
||||
self.discount,
|
||||
self.quantity,
|
||||
self.aviability,
|
||||
],
|
||||
scroll=ft.ScrollMode.ADAPTIVE,
|
||||
width=400
|
||||
),
|
||||
actions=[
|
||||
ft.Button(
|
||||
"Salveaza",
|
||||
on_click=self.on_save_btn_click,
|
||||
icon=ft.Icons.SAVE,
|
||||
),
|
||||
ft.TextButton(
|
||||
"Anuleaza",
|
||||
on_click=self.on_cancel_btn_click,
|
||||
icon=ft.Icons.CANCEL,
|
||||
),
|
||||
]
|
||||
)
|
||||
self.foto = None
|
||||
self.file_dialog = ft.FilePicker(
|
||||
on_result=self.on_file_picker_result,
|
||||
on_upload=self.on_upload_progress
|
||||
)
|
||||
self.page.overlay.append(self.file_dialog)
|
||||
self.page.update() # Required to register the FilePicker control
|
||||
|
||||
self.uploaded_files = []
|
||||
|
||||
self._all_products = self.product_manager.get_all()
|
||||
self.products_list = ft.ListView(
|
||||
controls=self.create_list(self._all_products, self.edit_product, self.delete_product),
|
||||
spacing=10,
|
||||
expand=True
|
||||
)
|
||||
|
||||
self.edit_item_id = None
|
||||
self.delete_item_id = None
|
||||
|
||||
self.confirm_delete_alert = ft.AlertDialog(
|
||||
title=ft.Text("Confirmati?"),
|
||||
actions=[
|
||||
ft.Button(
|
||||
"Da",
|
||||
on_click=self.on_delete_product_click,
|
||||
icon=ft.Icons.DELETE,
|
||||
),
|
||||
ft.TextButton(
|
||||
"Nu",
|
||||
on_click=self.on_delete_cancel_btn_click,
|
||||
icon=ft.Icons.CANCEL,
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
def on_file_picker_result(self, e: ft.FilePickerResultEvent):
|
||||
if e.files:
|
||||
file = e.files[0]
|
||||
file_name = file.name
|
||||
upload_url = self.page.get_upload_url(file_name, 600)
|
||||
|
||||
print(f"Uploading {file_name} to {upload_url}")
|
||||
|
||||
upload_task = ft.FilePickerUploadFile(
|
||||
name=file.name,
|
||||
upload_url=upload_url
|
||||
)
|
||||
self.file_dialog.upload([upload_task])
|
||||
|
||||
def open_file_picker(self, e=None):
|
||||
self.file_dialog.pick_files(
|
||||
allow_multiple=False,
|
||||
allowed_extensions=["png", "jpg", "jpeg"]
|
||||
)
|
||||
|
||||
def on_upload_progress(self, e: ft.FilePickerUploadEvent):
|
||||
if e.progress == 1:
|
||||
print(f"Upload complete: {e.file_name}")
|
||||
|
||||
# Resolve paths relative to the UI folder (two levels up from this file)
|
||||
ui_root = os.path.dirname(os.path.dirname(__file__))
|
||||
uploads_path = os.path.join(ui_root, "uploads")
|
||||
assets_path = os.path.join(ui_root, "assets", "images")
|
||||
os.makedirs(assets_path, exist_ok=True)
|
||||
|
||||
source_file = os.path.join(uploads_path, e.file_name)
|
||||
destination_file = os.path.join(assets_path, e.file_name)
|
||||
|
||||
if not os.path.exists(source_file):
|
||||
print(f"❌ File not found: {source_file}")
|
||||
return
|
||||
|
||||
try:
|
||||
shutil.move(source_file, destination_file)
|
||||
print(f"✅ File moved: {source_file} → {destination_file}")
|
||||
self.product_image.src = f'images/{e.file_name}'
|
||||
self.product_image.update()
|
||||
self.page.update()
|
||||
self.foto = e.file_name
|
||||
except Exception as ex:
|
||||
print(f"❌ Error moving file: {ex}")
|
||||
|
||||
def on_add_btn_click(self, e):
|
||||
self.page.open(self.add_product_dialog)
|
||||
|
||||
def on_save_btn_click(self, e):
|
||||
product = {
|
||||
'name': self.name.value,
|
||||
'description': self.description.value,
|
||||
'details': self.details.value,
|
||||
'price' : self.price.value,
|
||||
'discount' : self.discount.value,
|
||||
'quantity' : self.quantity.value,
|
||||
'image' : self.product_image.src,
|
||||
'aviability' : self.aviability.value,
|
||||
'category_id' : self.category.value
|
||||
}
|
||||
print(product)
|
||||
if self.edit_item_id == None:
|
||||
self.product_manager.add(product)
|
||||
else:
|
||||
self.product_manager.update(product, self.edit_item_id)
|
||||
self.edit_item_id = None
|
||||
|
||||
self.page.close(self.add_product_dialog)
|
||||
self.set_popup_to_default()
|
||||
|
||||
print('Update list')
|
||||
self._all_products = self.product_manager.get_all()
|
||||
self.products_list.controls=self.create_list(self._all_products, self.edit_product, self.delete_product)
|
||||
self.products_list.update()
|
||||
|
||||
def on_cancel_btn_click(self, e):
|
||||
self.page.close(self.add_product_dialog)
|
||||
self.set_popup_to_default()
|
||||
if self.edit_item_id != None:
|
||||
self.edit_item_id = None
|
||||
|
||||
def set_popup_to_default(self):
|
||||
self.name.value = ''
|
||||
self.name.update()
|
||||
self.description.value = ''
|
||||
self.description.update()
|
||||
self.details.value = ''
|
||||
self.details.update()
|
||||
self.price.value = ''
|
||||
self.price.update()
|
||||
self.discount.value = ''
|
||||
self.discount.update()
|
||||
self.quantity.value = ''
|
||||
self.quantity.update()
|
||||
self.product_image.src = 'images/placeholder.png'
|
||||
self.product_image.update()
|
||||
self.aviability.value = None
|
||||
self.aviability.update()
|
||||
self.category.value = None
|
||||
self.category.update()
|
||||
|
||||
|
||||
def get_categories(self):
|
||||
categories = self.category_manager.get_categories()
|
||||
return [
|
||||
ft.dropdown.Option(key=cat['id'], text=cat['name'])
|
||||
for cat in categories
|
||||
]
|
||||
|
||||
def create_list(self, items, on_click_handler, on_click_handler2):
|
||||
"""Helper to create list items for a column."""
|
||||
return [
|
||||
ft.Container(
|
||||
content=ft.Row(
|
||||
[
|
||||
ft.Column(
|
||||
[
|
||||
ft.Text(value=item['name'], weight=ft.FontWeight.BOLD, size=15),
|
||||
ft.Text(value=f"Pret: {item['price']}", size=12)
|
||||
]
|
||||
),
|
||||
ft.Row(
|
||||
[
|
||||
ft.IconButton(
|
||||
icon=ft.Icons.EDIT,
|
||||
on_click=lambda e, id=item: on_click_handler(id),
|
||||
),
|
||||
ft.IconButton(
|
||||
icon = ft.Icons.DELETE,
|
||||
on_click=lambda e, id=item['id']: on_click_handler2(id),
|
||||
icon_color=ft.Colors.RED
|
||||
)
|
||||
]
|
||||
)
|
||||
],
|
||||
alignment=ft.MainAxisAlignment.SPACE_BETWEEN,
|
||||
),
|
||||
width=300,
|
||||
bgcolor=ft.Colors.BROWN_50,
|
||||
padding=10,
|
||||
border_radius=8,
|
||||
border = ft.border.all(1, ft.Colors.GREY),
|
||||
)
|
||||
for item in items
|
||||
]
|
||||
|
||||
def edit_product(self, item):
|
||||
self.edit_item_id = item['id']
|
||||
self.name.value = item['name']
|
||||
self.description.value = item['description']
|
||||
self.details.value = item['details']
|
||||
self.price.value = item['price']
|
||||
self.discount.value = item['discount']
|
||||
self.quantity.value = item['quantity']
|
||||
self.product_image.src = item['image']
|
||||
self.aviability.value = item['aviability']
|
||||
self.category.value = item['category_id']
|
||||
self.page.open(self.add_product_dialog)
|
||||
|
||||
def delete_product(self, id):
|
||||
self.delete_item_id = id
|
||||
self.page.open(self.confirm_delete_alert)
|
||||
|
||||
def on_delete_product_click(self, e):
|
||||
self.product_manager.delete(self.delete_item_id )
|
||||
self.delete_item_id = None
|
||||
self.page.close(self.confirm_delete_alert)
|
||||
print('Update list')
|
||||
self._all_products = self.product_manager.get_all()
|
||||
self.products_list.controls=self.create_list(self._all_products, self.edit_product, self.delete_product)
|
||||
self.products_list.update()
|
||||
|
||||
def on_delete_cancel_btn_click(self, e):
|
||||
self.delete_item_id = None
|
||||
self.page.close(self.confirm_delete_alert)
|
||||
|
||||
def build(self):
|
||||
return ft.Container(
|
||||
content=ft.Column(
|
||||
[
|
||||
ft.Row(
|
||||
[
|
||||
ft.Text("Produse", size=18, weight=ft.FontWeight.BOLD),
|
||||
ft.Button("Adauga", icon=ft.Icons.ADD, on_click=self.on_add_btn_click),
|
||||
],
|
||||
alignment=ft.MainAxisAlignment.SPACE_BETWEEN
|
||||
),
|
||||
self.products_list
|
||||
],
|
||||
alignment=ft.MainAxisAlignment.START,
|
||||
expand=True
|
||||
),
|
||||
expand=True,
|
||||
)
|
||||
Reference in New Issue
Block a user