cambios en el formulario de solicitudes
Browse files- app/main.py +91 -26
app/main.py
CHANGED
|
@@ -237,14 +237,45 @@ def main(page: ft.Page):
|
|
| 237 |
)
|
| 238 |
|
| 239 |
elif page.route == "/prestamos":
|
| 240 |
-
|
| 241 |
-
|
| 242 |
-
|
| 243 |
-
|
| 244 |
-
h_ext = ft.
|
| 245 |
-
h_dev = ft.
|
|
|
|
| 246 |
st_txt = ft.Text("", weight="bold")
|
| 247 |
lista_historial = ft.ListView(expand=True, spacing=10)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 248 |
|
| 249 |
def crear_card(d):
|
| 250 |
icon = ft.Icons.HOURGLASS_EMPTY
|
|
@@ -258,7 +289,7 @@ def main(page: ft.Page):
|
|
| 258 |
|
| 259 |
return ft.Container(
|
| 260 |
content=ft.ListTile(
|
| 261 |
-
title=ft.Text(d['
|
| 262 |
subtitle=ft.Text(f"{d['item']} (x{d['cantidad']})"),
|
| 263 |
trailing=ft.Icon(icon, color=color),
|
| 264 |
on_click=lambda _: mostrar_factura(d)
|
|
@@ -274,28 +305,39 @@ def main(page: ft.Page):
|
|
| 274 |
refactor_list()
|
| 275 |
|
| 276 |
def registrar(e):
|
| 277 |
-
if not nombre.value
|
| 278 |
-
st_txt.value = "⚠️
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 279 |
|
|
|
|
|
|
|
|
|
|
| 280 |
loan_id = str(uuid.uuid4())
|
| 281 |
-
|
|
|
|
| 282 |
mensaje_tg = (
|
| 283 |
-
"🛠 *SOLICITUD DE PRÉSTAMO*\n"
|
| 284 |
-
f"👤 {escape_md(nombre.value)}\n"
|
| 285 |
-
f"
|
| 286 |
-
f"
|
| 287 |
-
f"🕒 Hora: {escape_md(h_ext.value)}"
|
| 288 |
)
|
| 289 |
|
| 290 |
res_tg = enviar_telegram_con_botones(loan_id, mensaje_tg)
|
| 291 |
|
| 292 |
nuevo = {
|
| 293 |
"id": loan_id,
|
| 294 |
-
"
|
| 295 |
-
"item":
|
| 296 |
-
"cantidad":
|
| 297 |
"hora": h_ext.value,
|
| 298 |
-
"devolucion": h_dev.value
|
| 299 |
"status_loan": "PENDING",
|
| 300 |
"status_tg": res_tg
|
| 301 |
}
|
|
@@ -305,18 +347,41 @@ def main(page: ft.Page):
|
|
| 305 |
|
| 306 |
st_txt.value = "✅ Solicitud Enviada" if res_tg == "OK" else f"⚠️ Error Telegram: {res_tg}"
|
| 307 |
st_txt.color = "green" if res_tg == "OK" else "orange"
|
| 308 |
-
nombre.value = ""
|
|
|
|
|
|
|
|
|
|
| 309 |
|
| 310 |
page.views.append(
|
| 311 |
ft.View("/prestamos", [
|
| 312 |
ft.AppBar(title=ft.Text("Préstamos"), bgcolor="#1a1c1e"),
|
| 313 |
ft.Column([
|
| 314 |
-
ft.
|
| 315 |
-
|
| 316 |
-
|
| 317 |
-
|
| 318 |
-
|
| 319 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 320 |
])
|
| 321 |
)
|
| 322 |
|
|
|
|
| 237 |
)
|
| 238 |
|
| 239 |
elif page.route == "/prestamos":
|
| 240 |
+
# --- CONFIGURACIÓN DE TIEMPO (8:00 - 15:00) ---
|
| 241 |
+
opciones_hora = [ft.dropdown.Option(f"{h:02d}:00") for h in range(8, 16)]
|
| 242 |
+
|
| 243 |
+
nombre = ft.TextField(label="Nombre del Alumno", expand=True, prefix_icon=ft.Icons.PERSON)
|
| 244 |
+
h_ext = ft.Dropdown(label="Hora Salida", options=opciones_hora, value="08:00", expand=1)
|
| 245 |
+
h_dev = ft.Dropdown(label="Devolución", options=opciones_hora, value="15:00", expand=1)
|
| 246 |
+
|
| 247 |
st_txt = ft.Text("", weight="bold")
|
| 248 |
lista_historial = ft.ListView(expand=True, spacing=10)
|
| 249 |
+
|
| 250 |
+
# --- GESTIÓN DE FILAS DINÁMICAS ---
|
| 251 |
+
container_items = ft.Column(spacing=10)
|
| 252 |
+
|
| 253 |
+
def crear_fila_item():
|
| 254 |
+
return ft.Row([
|
| 255 |
+
ft.Dropdown(
|
| 256 |
+
label="Categoría",
|
| 257 |
+
options=[
|
| 258 |
+
ft.dropdown.Option("Herramientas"),
|
| 259 |
+
ft.dropdown.Option("Dispositivos Eléctricos")
|
| 260 |
+
],
|
| 261 |
+
value="Herramientas",
|
| 262 |
+
width=180
|
| 263 |
+
),
|
| 264 |
+
ft.TextField(label="Descripción", expand=True),
|
| 265 |
+
ft.TextField(label="Cant.", value="1", width=70, text_align=ft.TextAlign.CENTER),
|
| 266 |
+
ft.IconButton(ft.Icons.DELETE_OUTLINE, icon_color="red", on_click=lambda e: eliminar_fila(e))
|
| 267 |
+
], alignment=ft.MainAxisAlignment.START)
|
| 268 |
+
|
| 269 |
+
def eliminar_fila(e):
|
| 270 |
+
if len(container_items.controls) > 1:
|
| 271 |
+
container_items.controls.remove(e.control.parent)
|
| 272 |
+
page.update()
|
| 273 |
+
|
| 274 |
+
def agregar_fila(e):
|
| 275 |
+
container_items.controls.append(crear_fila_item())
|
| 276 |
+
page.update()
|
| 277 |
+
|
| 278 |
+
container_items.controls.append(crear_fila_item())
|
| 279 |
|
| 280 |
def crear_card(d):
|
| 281 |
icon = ft.Icons.HOURGLASS_EMPTY
|
|
|
|
| 289 |
|
| 290 |
return ft.Container(
|
| 291 |
content=ft.ListTile(
|
| 292 |
+
title=ft.Text(d['Solicitante'], weight="bold"),
|
| 293 |
subtitle=ft.Text(f"{d['item']} (x{d['cantidad']})"),
|
| 294 |
trailing=ft.Icon(icon, color=color),
|
| 295 |
on_click=lambda _: mostrar_factura(d)
|
|
|
|
| 305 |
refactor_list()
|
| 306 |
|
| 307 |
def registrar(e):
|
| 308 |
+
if not nombre.value:
|
| 309 |
+
st_txt.value = "⚠️ Nombre de solicitante requerido"; st_txt.color="red"; page.update(); return
|
| 310 |
+
|
| 311 |
+
items_solicitados = []
|
| 312 |
+
for fila in container_items.controls:
|
| 313 |
+
cat = fila.controls[0].value
|
| 314 |
+
txt = fila.controls[1].value
|
| 315 |
+
ct = fila.controls[2].value
|
| 316 |
+
if txt:
|
| 317 |
+
items_solicitados.append(f"• [{cat}] {txt} (x{ct})")
|
| 318 |
|
| 319 |
+
if not items_solicitados:
|
| 320 |
+
st_txt.value = "⚠️ Agrega al menos una herramienta"; st_txt.color="red"; page.update(); return
|
| 321 |
+
|
| 322 |
loan_id = str(uuid.uuid4())
|
| 323 |
+
lista_items_str = "\n".join(items_solicitados)
|
| 324 |
+
|
| 325 |
mensaje_tg = (
|
| 326 |
+
"🛠 *NUEVA SOLICITUD DE PRÉSTAMO*\n"
|
| 327 |
+
f"👤 *Alumno:* {escape_md(nombre.value)}\n"
|
| 328 |
+
f"� *Horario:* {h_ext.value} a {h_dev.value}\n"
|
| 329 |
+
f"� *Herramientas:*\n{escape_md(lista_items_str)}"
|
|
|
|
| 330 |
)
|
| 331 |
|
| 332 |
res_tg = enviar_telegram_con_botones(loan_id, mensaje_tg)
|
| 333 |
|
| 334 |
nuevo = {
|
| 335 |
"id": loan_id,
|
| 336 |
+
"Solicitante": nombre.value,
|
| 337 |
+
"item": lista_items_str,
|
| 338 |
+
"cantidad": "Multiple",
|
| 339 |
"hora": h_ext.value,
|
| 340 |
+
"devolucion": h_dev.value,
|
| 341 |
"status_loan": "PENDING",
|
| 342 |
"status_tg": res_tg
|
| 343 |
}
|
|
|
|
| 347 |
|
| 348 |
st_txt.value = "✅ Solicitud Enviada" if res_tg == "OK" else f"⚠️ Error Telegram: {res_tg}"
|
| 349 |
st_txt.color = "green" if res_tg == "OK" else "orange"
|
| 350 |
+
nombre.value = ""
|
| 351 |
+
container_items.controls.clear()
|
| 352 |
+
container_items.controls.append(crear_fila_item())
|
| 353 |
+
page.update()
|
| 354 |
|
| 355 |
page.views.append(
|
| 356 |
ft.View("/prestamos", [
|
| 357 |
ft.AppBar(title=ft.Text("Préstamos"), bgcolor="#1a1c1e"),
|
| 358 |
ft.Column([
|
| 359 |
+
ft.Row([
|
| 360 |
+
ft.Text("SOLICITAR PRÉSTAMO", size=18, weight="bold"),
|
| 361 |
+
ft.ElevatedButton("🔔 ACTIVAR ALERTAS", icon=ft.Icons.NOTIFICATIONS_ACTIVE,
|
| 362 |
+
on_click=lambda _: page.get_notification_permission(), bgcolor=ft.Colors.BLUE_GREY_900)
|
| 363 |
+
], alignment=ft.MainAxisAlignment.SPACE_BETWEEN),
|
| 364 |
+
|
| 365 |
+
nombre,
|
| 366 |
+
ft.Row([h_ext, h_dev], spacing=10),
|
| 367 |
+
|
| 368 |
+
ft.Divider(),
|
| 369 |
+
ft.Row([
|
| 370 |
+
ft.Text("LISTA DE HERRAMIENTAS", size=14, weight="bold"),
|
| 371 |
+
ft.IconButton(ft.Icons.ADD_CIRCLE, icon_color="green", on_click=agregar_fila)
|
| 372 |
+
], alignment=ft.MainAxisAlignment.SPACE_BETWEEN),
|
| 373 |
+
|
| 374 |
+
container_items,
|
| 375 |
+
|
| 376 |
+
ft.ElevatedButton("ENVIAR SOLICITUD TOTAL", icon=ft.Icons.SEND, on_click=registrar,
|
| 377 |
+
bgcolor=ft.Colors.GREEN_800, color="white", height=50, width=float("inf")),
|
| 378 |
+
|
| 379 |
+
st_txt,
|
| 380 |
+
ft.Divider(),
|
| 381 |
+
ft.Text("HISTORIAL RECIENTE", size=18, weight="bold"),
|
| 382 |
+
lista_historial,
|
| 383 |
+
ft.TextButton("Volver", on_click=lambda _: page.go("/"))
|
| 384 |
+
], scroll=ft.ScrollMode.ADAPTIVE, expand=True, spacing=15)
|
| 385 |
])
|
| 386 |
)
|
| 387 |
|