"""The meds page.""" from reflex_ipad import styles from reflex_ipad.templates import template from reflex_ipad.state import State import datetime import asyncio import time import reflex as rx from reflex_ipad.models import * from sqlmodel import Field, Session, SQLModel, create_engine, select class NewMedicineState(rx.State): """Define your app state here.""" show_med_add_form: bool = False medicine: Optional[Medicine] = None medicine_name: str = "" last_scan: Scan = Scan(uuid="", timestamp=0) last_scan_uuid: str = "" last_scan_time: str = "" updated_uuid: bool = False scanning: bool = False rate: float = 2 lastupdatetime: int = time.time() def start_scan(self): self.set_scanning(True) self.lastupdatetime = time.time() self.last_scan_uuid = "" return NewMedicineState.do_scanning def load_last_scan(self): with rx.session() as session: statement = select(Scan).order_by(Scan.timestamp.desc()).limit(1) results = session.exec(statement) self.last_scan = results.first() if self.last_scan.timestamp > self.lastupdatetime: self.last_scan_uuid = self.last_scan.uuid if not self.show_med_add_form: self.update_medicine(self.last_scan.uuid) self.updated_uuid = True self.lastupdatetime = time.time() ts = datetime.datetime.fromtimestamp(self.last_scan.timestamp) self.last_scan_time = ts.strftime("%Y-%m-%d %H:%M") def uuid_used(self): self.updated_uuid = False def update_medicine(self, uuid): with rx.session() as session: statement = select(Medicine).where(Medicine.uuid == uuid) results = session.exec(statement) self.medicine = results.first() if self.medicine is not None: self.medicine_name = ( f"{self.medicine.name} - {self.medicine.owner.name}" ) @rx.background async def do_scanning(self): while True: await asyncio.sleep(1 / self.rate) if not self.scanning: break async with self: self.load_last_scan() @rx.var def owners(self): with rx.session() as session: statement = select(Owner) results = session.exec(statement) owners = results.all() return [owner.name for owner in owners] def do_show_med_add_form(self): self.set_show_med_add_form(True) def stop_show_med_add_form(self): self.set_show_med_add_form(False) def handle_submit(self, form_data: dict): self.form_data = form_data with rx.session() as session: statement = select(Owner).where(Owner.name == form_data["owner"]) results = session.exec(statement) owner = results.first() medicine = Medicine( name=form_data["name"], package_size=form_data["pkg_size"], pzn=form_data["pzn"] or "", owner_id=owner.id, uuid=State.last_scan_uuid, cron=form_data["schedule"], ) session.add(medicine) session.commit() self.uuid_used() self.set_show_med_add_form(False) def handle_log(self, form_data: dict): with rx.session() as session: statement = select(Medicine).where(Medicine.uuid == form_data["uuid"]) results = session.exec(statement) medicine = results.first() medicineLog = MedicineLog(medicine_id=medicine.id, timestamp=time.time()) session.add(medicineLog) session.commit() self.uuid_used() def cancel_log(self, form_data: dict): self.uuid_used() def new_medicine_form(): return rx.vstack( rx.form( rx.vstack( rx.input( placeholder="Name", name="name", ), rx.input( placeholder="Packungsgröße", name="pkg_size", ), rx.input( placeholder="PZN", name="pzn", ), rx.select( NewMedicineState.owners, placeholder="Für wen", name="owner", ), rx.hstack( rx.text("Crontab lines für Einnahme"), rx.popover( rx.popover_trigger(rx.button("Help")), rx.popover_content( rx.popover_header("Crontab help"), rx.popover_body( rx.html("
0	7	*	*	*	
"), "Täglich sieben Uhr", ), rx.popover_body( rx.html("
0	21	*	*	0	
"), "Jeden Sonntag um 21:00 Uhr.", ), rx.popover_body( rx.html("
0	7	*	*	1-5	
"), "Montags bis Freitags jeweils um 07:00", ), rx.popover_close_button(), ), ), ), rx.text_area(name="schedule"), rx.input( value=NewMedicineState.last_scan_uuid, name="uuid", placeholder="UUID", disabled=True, ), rx.hstack( rx.text("Gescannt:"), rx.text( NewMedicineState.last_scan_time, ), ), rx.button("Submit", type_="submit"), ), on_submit=NewMedicineState.handle_submit, reset_on_submit=True, ), rx.divider(), ) def taken_form(): with rx.session() as session: if NewMedicineState.medicine is None: return rx.vstack() return rx.vstack( rx.heading(NewMedicineState.medicine_name, size="lg", color="darkblue"), rx.hstack( rx.form( rx.button("Ja", type_="submit", color_scheme="green", size="lg"), rx.input( value=NewMedicineState.last_scan_uuid, name="uuid", disabled=True, hidden=True, type_="hidden", ), on_submit=NewMedicineState.handle_log, ), rx.form( rx.button("Nein", type_="submit", color_scheme="red", size="lg"), on_submit=NewMedicineState.cancel_log, ), reset_on_submit=True, ), rx.divider(), ) @template(route="/medicine", title="Medikamente") def medicine() -> rx.Component: """The dashboard page. Returns: The UI for the dashboard page. """ return rx.vstack( rx.hstack( rx.spacer(), rx.heading("Medikamente", font_size="3em"), rx.spacer(), rx.cond( NewMedicineState.show_med_add_form, rx.button( rx.text( "-", ), on_click=NewMedicineState.stop_show_med_add_form(), ), rx.button( rx.text( "+", ), on_click=NewMedicineState.do_show_med_add_form(), ), ), width="100%", border_bottom=styles.border, padding="1em", ), rx.cond(NewMedicineState.show_med_add_form, new_medicine_form()), rx.cond( NewMedicineState.updated_uuid, taken_form(), rx.text( "Scan the Med", ), ), on_mount=NewMedicineState.start_scan, )