VARROA_METHODS_DISPLAY <- c( "Nat. Totenfall" = "natuerlicher_totenfall", "Alkoholwäsche" = "alkoholwaesche", "Puderzucker" = "puderzucker" ) screen_varroa_ui <- function(id) { ns <- NS(id) bslib::navset_card_tab( bslib::nav_panel("Kontrolle", shiny::div(class = "p-2", section_card(NULL, shiny::div(class = "row g-2 py-2", shiny::div(class = "col-4", shiny::dateInput(ns("count_date_from"), "Von", value = Sys.Date() - 3L, language = "de", weekstart = 1) ), shiny::div(class = "col-4", shiny::dateInput(ns("count_date_to"), "Bis", value = Sys.Date(), language = "de", weekstart = 1) ), shiny::div(class = "col-4", shiny::textInput(ns("count_time"), "Uhrzeit", value = format(Sys.time(), "%H:%M"), placeholder = "HH:MM") ) ) ), btn_group_row(ns, "count_method", "Methode", VARROA_METHODS_DISPLAY), stepper_row(ns, "count_val", "Anzahl / Wert"), shiny::uiOutput(ns("milben_pro_tag_ui")), section_card(NULL, shiny::div(class = "py-2", shiny::div( class = "bk-check d-flex justify-content-between align-items-center py-2 border-bottom", shiny::tags$label(class = "fw-semibold", `for` = ns("is_ctrl"), "Nachkontrolle zu Behandlung?"), shiny::checkboxInput(ns("is_ctrl"), NULL, value = FALSE) ), shiny::uiOutput(ns("ctrl_extra_ui")), shiny::textAreaInput(ns("count_notes"), "Notizen", rows = 2, width = "100%") ) ), shiny::div(class = "d-grid mt-2", shiny::actionButton(ns("save_count"), "Kontrolle speichern", class = "btn btn-primary btn-lg") ) ) ), bslib::nav_panel("Behandlung", shiny::div(class = "p-2", section_card(NULL, shiny::div(class = "row g-2 py-2", shiny::div(class = "col-6", shiny::dateInput(ns("treat_date"), "Datum", value = Sys.Date(), language = "de", weekstart = 1) ), shiny::div(class = "col-6", shiny::textInput(ns("treat_time"), "Uhrzeit", value = format(Sys.time(), "%H:%M"), placeholder = "HH:MM") ), shiny::div(class = "col-12", shiny::selectizeInput(ns("treat_product"), "Mittel *", choices = c("Mittel wählen…" = "", VARROA_PRODUCTS), options = list(create = TRUE, placeholder = "Mittel wählen…") ) ) ) ), section_card(NULL, shiny::div(class = "py-2", shiny::uiOutput(ns("treat_method_ui")), shiny::textInput(ns("treat_dosage"), "Dosierung", placeholder = "2,3 g / Volk"), shiny::textAreaInput(ns("treat_notes"), "Notizen", rows = 2, width = "100%") ) ), shiny::div(class = "d-grid mt-2", shiny::actionButton(ns("save_treat"), "Behandlung speichern", class = "btn btn-warning btn-lg") ) ) ) ) } screen_varroa_server <- function(id, db, nav) { moduleServer(id, function(input, output, session) { ns <- session$ns count_method <- btn_group_server("count_method", ns, input, output, VARROA_METHODS_DISPLAY, default = "natuerlicher_totenfall") count_val <- stepper_server("count_val", input, output) observeEvent(nav$screen, { if (nav$screen == "varroa") { count_val(NA_integer_) shiny::updateCheckboxInput(session, "is_ctrl", value = FALSE) shiny::updateDateInput(session, "count_date_from", value = Sys.Date() - 3L) shiny::updateDateInput(session, "count_date_to", value = Sys.Date()) shiny::updateTextInput(session, "count_time", value = format(Sys.time(), "%H:%M")) shiny::updateTextInput(session, "treat_time", value = format(Sys.time(), "%H:%M")) } }, ignoreInit = TRUE) output$milben_pro_tag_ui <- renderUI({ v <- count_val() d_von <- input$count_date_from d_bis <- input$count_date_to if (is.na(v) || is.null(d_von) || is.null(d_bis)) return(NULL) days <- as.numeric(as.Date(d_bis) - as.Date(d_von)) if (days < 0) return(shiny::p(class = "text-danger small py-1", "Bis-Datum liegt vor Von-Datum.")) mpt <- round(v / max(1, days), 1) cls <- if (mpt < 1) "text-success" else if (mpt < 3) "text-warning" else "text-danger" shiny::div( class = paste("text-center py-2 fw-bold fs-4", cls), paste0(mpt, " Milben/Tag"), shiny::tags$div(class = "text-muted fw-normal small", paste0(v, " Milben über ", days, " Tage")) ) }) output$ctrl_extra_ui <- renderUI({ req(isTRUE(input$is_ctrl), nav$colony_id) treats <- db_varroa_treatments_list(db, nav$colony_id) if (nrow(treats) == 0) return(shiny::p(class = "text-muted small py-2", "Keine Behandlungen erfasst.")) shiny::tagList( shiny::selectInput(ns("ctrl_treatment"), "Zur Behandlung", choices = setNames(treats$id, paste(treats$date, treats$product)) ), shiny::textInput(ns("ctrl_result"), "Ergebnis / Befund") ) }) output$treat_method_ui <- renderUI({ product <- input$treat_product methods <- if (!is.null(product) && product != "") VARROA_APPLICATION_METHODS[[product]] else NULL if (!is.null(methods)) { shiny::selectizeInput(ns("treat_method"), "Anwendung", choices = c("Anwendung wählen…" = "", methods), options = list(create = TRUE, placeholder = "Anwendung wählen…") ) } else { shiny::textInput(ns("treat_method"), "Anwendung", placeholder = "z. B. Träufeln") } }) observeEvent(input$save_count, { req(nav$colony_id, !is.na(count_val())) db_varroa_counts_insert(db, colony_id = nav$colony_id, date_from = input$count_date_from, date = input$count_date_to, method = count_method() %||% "natuerlicher_totenfall", count = count_val(), notes = input$count_notes, time = input$count_time %||% NA ) if (isTRUE(input$is_ctrl) && !is.null(input$ctrl_treatment)) { db_varroa_controls_insert(db, treatment_id = as.integer(input$ctrl_treatment), colony_id = nav$colony_id, date = input$count_date, result = input$ctrl_result %||% "", notes = input$count_notes ) } count_val(NA_integer_) shiny::updateTextAreaInput(session, "count_notes", value = "") shiny::updateCheckboxInput(session, "is_ctrl", value = FALSE) nav$screen <- "colony" }) observeEvent(input$save_treat, { req(nav$colony_id, nchar(trimws(input$treat_product)) > 0) db_varroa_treatments_insert(db, colony_id = nav$colony_id, date = input$treat_date, product = trimws(input$treat_product), method = input$treat_method, dosage = input$treat_dosage, notes = input$treat_notes, time = input$treat_time %||% NA ) nav$screen <- "colony" }) }) }