screen_colonies_ui <- function(id) { ns <- NS(id) shiny::tagList( shiny::uiOutput(ns("status_filters")), shiny::uiOutput(ns("cards")), shiny::br(), shiny::div(class = "d-flex gap-2 mb-2", shiny::actionButton(ns("quick_insp_btn"), shiny::tagList(shiny::icon("bolt"), " Schnelldurchsicht"), class = "btn btn-outline-primary w-100" ), shiny::actionButton(ns("bulk_action_btn"), shiny::tagList(shiny::icon("layer-group"), " Sammelmaßnahme"), class = "btn btn-outline-secondary w-100" ) ), shiny::div(class = "d-flex gap-2 mb-2", shiny::actionButton(ns("lineage_btn"), shiny::tagList(shiny::icon("sitemap"), " Stammbaum"), class = "btn btn-outline-secondary w-100" ) ), shiny::actionButton(ns("add_btn"), shiny::tagList(shiny::icon("plus"), " Neues Volk"), class = "add-dashed btn", style = "width:100%;min-height:80px" ) ) } screen_colonies_server <- function(id, db, nav) { moduleServer(id, function(input, output, session) { ns <- session$ns reload <- reactiveVal(0) status_filter <- reactiveVal("") colonies <- reactive({ req(nav$apiary_id) reload() db_colonies_list(db, apiary_id = nav$apiary_id, include_closed = FALSE) }) output$status_filters <- renderUI({ statuses <- c("Alle" = "", COLONY_STATUSES[names(COLONY_STATUSES) != "Eingegangen"]) shiny::div(class = "d-flex gap-2 mb-3 flex-wrap", lapply(seq_along(statuses), function(i) { val <- statuses[[i]] active <- identical(status_filter(), val) shiny::actionButton( ns(paste0("sf_", i)), names(statuses)[i], class = if (active) "btn btn-primary btn-sm" else "btn btn-outline-secondary btn-sm" ) }) ) }) observe({ statuses <- c("Alle" = "", COLONY_STATUSES[names(COLONY_STATUSES) != "Eingegangen"]) lapply(seq_along(statuses), function(i) { local({ li <- i; val <- statuses[[i]] observeEvent(input[[paste0("sf_", li)]], status_filter(val), ignoreInit = TRUE) }) }) }) filtered <- reactive({ cols <- colonies() sf <- status_filter() if (!is.null(sf) && sf != "") cols[cols$status == sf, ] else cols }) output$cards <- renderUI({ cols <- filtered() if (nrow(cols) == 0) return(shiny::p(class = "text-muted", "Keine Völker gefunden.")) lapply(seq_len(nrow(cols)), function(i) { row <- cols[i, ] days_ago <- if (!is.na(row$last_inspection_date)) { d <- as.integer(Sys.Date() - as.Date(row$last_inspection_date)) if (d == 0) "heute" else if (d == 1) "gestern" else paste0("vor ", d, " Tagen") } else "keine Durchsicht" shiny::div( class = "card tap-card mb-2", onclick = sprintf("Shiny.setInputValue('%s', %d, {priority:'event'})", ns("select"), row$id), bslib::card_body( class = "d-flex justify-content-between align-items-center py-2", shiny::div( shiny::tags$strong(row$name), shiny::tags$p(class = "text-muted small mb-0", days_ago) ), shiny::HTML(colony_status_badge(row$status)) ) ) }) }) observeEvent(input$select, { nav$colony_id <- input$select nav$screen <- "colony" }) observeEvent(input$quick_insp_btn, { nav$screen <- "quick_inspection" }) observeEvent(input$bulk_action_btn, { nav$screen <- "bulk_action" }) observeEvent(input$lineage_btn, { nav$screen <- "lineage" }) # ---- Add colony modal --------------------------------------------------- observeEvent(input$add_btn, { cols <- db_colonies_list(db, include_closed = FALSE) shiny::showModal(shiny::modalDialog( title = "Neues Volk", footer = shiny::tagList( shiny::modalButton("Abbrechen"), shiny::actionButton(ns("confirm_add"), "Anlegen", class = "btn-primary") ), shiny::textInput(ns("new_name"), "Name *"), shiny::selectInput(ns("new_status"), "Status", choices = COLONY_STATUSES[names(COLONY_STATUSES) != "Eingegangen"], selected = "wirtschaftsvolk" ), shiny::selectInput(ns("new_parent"), "Muttervolk (optional)", choices = c("–" = "", setNames(cols$id, cols$name)) ), shiny::textAreaInput(ns("new_notes"), "Notizen", rows = 2) )) }) observeEvent(input$confirm_add, { if (nchar(trimws(input$new_name)) == 0) { shiny::showNotification("Bitte einen Namen eingeben.", type = "warning", duration = 3) return() } req(nav$apiary_id) parent <- if (!is.null(input$new_parent) && input$new_parent != "") as.integer(input$new_parent) else NA db_colonies_insert(db, name = trimws(input$new_name), apiary_id = as.integer(nav$apiary_id), status = input$new_status, parent_colony_id = parent, notes = input$new_notes ) shiny::removeModal(); reload(reload() + 1L) }) }) }