ezgg-lan-manager/src/ez_lan_manager/components/ShoppingCartAndOrders.py
2024-11-27 10:49:37 +01:00

171 lines
7.4 KiB
Python

from asyncio import sleep, create_task
import rio
from rio import Component, Column, Text, TextStyle, Button, Row, ScrollContainer, Spacer, Popup
from src.ez_lan_manager.components.CateringCartItem import CateringCartItem
from src.ez_lan_manager.components.CateringOrderItem import CateringOrderItem
from src.ez_lan_manager.services.AccountingService import AccountingService
from src.ez_lan_manager.services.CateringService import CateringService, CateringError, CateringErrorType
from src.ez_lan_manager.types.CateringOrder import CateringOrder, CateringMenuItemsWithAmount
from src.ez_lan_manager.types.SessionStorage import SessionStorage
POPUP_CLOSE_TIMEOUT_SECONDS = 3
class ShoppingCartAndOrders(Component):
show_cart: bool = True
orders: list[CateringOrder] = []
order_button_loading: bool = False
popup_message: str = ""
popup_is_shown: bool = False
popup_is_error: bool = True
async def switch(self) -> None:
self.show_cart = not self.show_cart
self.orders = await self.session[CateringService].get_orders_for_user(self.session[SessionStorage].user_id)
async def on_remove_item(self, list_id: int) -> None:
catering_service = self.session[CateringService]
user_id = self.session[SessionStorage].user_id
cart = catering_service.get_cart(user_id)
try:
cart.pop(list_id)
except IndexError:
return
catering_service.save_cart(user_id, cart)
await self.force_refresh()
async def on_empty_cart_pressed(self) -> None:
self.session[CateringService].save_cart(self.session[SessionStorage].user_id, [])
await self.force_refresh()
async def on_add_item(self, article_id: int) -> None:
catering_service = self.session[CateringService]
user_id = self.session[SessionStorage].user_id
if not user_id:
return
cart = catering_service.get_cart(user_id)
item_to_add = await catering_service.get_menu_item_by_id(article_id)
cart.append(item_to_add)
catering_service.save_cart(user_id, cart)
await self.force_refresh()
async def show_popup(self, text: str, is_error: bool) -> None:
self.popup_is_error = is_error
self.popup_message = text
self.popup_is_shown = True
await self.force_refresh()
await sleep(POPUP_CLOSE_TIMEOUT_SECONDS)
self.popup_is_shown = False
await self.force_refresh()
async def on_order_pressed(self) -> None:
self.order_button_loading = True
await self.force_refresh()
user_id = self.session[SessionStorage].user_id
cart = self.session[CateringService].get_cart(user_id)
if len(cart) < 1:
_ = create_task(self.show_popup("Warenkorb leer", True))
else:
items_with_amounts: CateringMenuItemsWithAmount = {}
for item in cart:
try:
items_with_amounts[item] += 1
except KeyError:
items_with_amounts[item] = 1
try:
await self.session[CateringService].place_order(items_with_amounts, user_id)
except CateringError as catering_error:
if catering_error.error_type == CateringErrorType.INCLUDES_DISABLED_ITEM:
_ = create_task(self.show_popup("Warenkorb enthält gesperrte Artikel", True))
elif catering_error.error_type == CateringErrorType.INSUFFICIENT_FUNDS:
_ = create_task(self.show_popup("Guthaben nicht ausreichend", True))
else:
_ = create_task(self.show_popup("Unbekannter Fehler", True))
self.session[CateringService].save_cart(self.session[SessionStorage].user_id, [])
self.order_button_loading = False
_ = create_task(self.show_popup("Bestellung erfolgreich aufgegeben!", False))
def build(self) -> rio.Component:
user_id = self.session[SessionStorage].user_id
catering_service = self.session[CateringService]
cart = catering_service.get_cart(user_id)
if self.show_cart:
cart_container = ScrollContainer(
content=Column(
*[CateringCartItem(
article_name=cart_item.name,
article_price=cart_item.price,
article_id=cart_item.item_id,
remove_item_cb=self.on_remove_item,
list_id=idx
) for idx, cart_item in enumerate(cart)],
Spacer(grow_y=True)
),
min_height=8,
min_width=33,
margin=1
)
return Column(
cart_container,
Popup(
anchor=cart_container,
content=Text(self.popup_message, style=TextStyle(fill=self.session.theme.danger_color if self.popup_is_error else self.session.theme.success_color), overflow="wrap", margin=2, justify="center", min_width=20),
is_open=self.popup_is_shown,
position="center",
color=self.session.theme.primary_color
),
Row(
Text(
text=f"Preis: {AccountingService.make_euro_string_from_int(sum(cart_item.price for cart_item in cart))}",
style=TextStyle(
fill=self.session.theme.background_color,
font_size=0.8
),
margin=1
),
Button(
content=Text(
"Warenkorb leeren",
style=TextStyle(fill=self.session.theme.danger_color, font_size=0.9),
align_x=0.2
),
margin=1,
margin_left=0,
shape="rectangle",
style="major",
color="primary",
on_press=self.on_empty_cart_pressed
),
Button(
content=Text(
"Bestellen",
style=TextStyle(fill=self.session.theme.success_color, font_size=0.9),
align_x=0.2
),
margin=1,
margin_left=0,
shape="rectangle",
style="major",
color="primary",
on_press=self.on_order_pressed,
is_loading=self.order_button_loading
)
)
)
else:
orders_container = ScrollContainer(
content=Column(
*[CateringOrderItem(
order_id=order_item.order_id,
order_datetime=order_item.order_date,
order_status=order_item.status,
) for order_item in self.orders],
Spacer(grow_y=True)
),
min_height=8,
min_width=33,
margin=1
)
return Column(orders_container)