library(bsicons) source("global.R") ui <- function() { page_fillable( h1("Polizeiliche Kriminalstatistik Hamburg", style = "color: #003064; background: #dae5ed; padding: 20px 0px 20px 20px; background-clip: padding-box; font-family: Lato,Arial,Helvetica,sans-serif;font-weight: 400", #text-align: center class = "display-4" ), tags$head( tags$style( HTML(" .selectize-dropdown-content .option { border-bottom: 1px solid #dee2e6; /* Die Trennlinie */ padding: 8px 10px; /* Abstand zwischen Text und Linie */ } .legend { background: white !important; /* Der Hintergrund der Legenden-Box */ opacity: 1 !important; /* Die Box selbst ist nicht transparent */ } /* Erzwingt den Dropdown-Pfeil auch bei Multiple Inputs */ .selectize-control.multi .selectize-input:after { content: ' '; display: block; position: absolute; top: 50%; right: 15px; margin-top: -3px; width: 0; height: 0; border-style: solid; border-width: 5px 5px 0 5px; border-color: #333 transparent transparent transparent; } /* Platz für den Pfeil lassen, damit Text nicht darunter rutscht */ .selectize-control.multi .selectize-input { padding-right: 35px !important; } /* 1. GRUND-LAYOUT */ body { background-color: #f4f7f9 !important; /* Ganz leichtes Blaugrau für Tiefe */ } /* 2. DIE KARTE (HHMAP) */ #hhmap { border-radius: 20px !important; box-shadow: 0 12px 35px rgba(0,0,0,0.1) !important; border: 5px solid white !important; overflow: hidden !important; } /* 3. ALLE CARDS (Diagramme & Container) */ .card { border-radius: 20px !important; border: none !important; box-shadow: 0 10px 30px rgba(149, 157, 165, 0.15) !important; background-color: #ffffff !important; transition: box-shadow 0.3s ease; } .card:hover { transform: none !important; /* Sanfter Schwebeprozess beim Hovern */ } /* 4. SIDEBAR & INPUTS */ .sidebar { background-color: #ffffff !important; border-right: none !important; box-shadow: 5px 0 25px rgba(0,0,0,0.03) !important; border-radius: 0 25px 25px 0 !important; } .selectize-input { border-radius: 12px !important; border: 1px solid #e2e8f0 !important; box-shadow: inset 1px 1px 3px rgba(0,0,0,0.02) !important; padding: 10px 15px !important; } .selectize-input.focus { border-color: #3182bd !important; box-shadow: 0 0 0 3px rgba(49, 130, 189, 0.1) !important; } /* 5. BUTTONS (Falls du welche hast) */ .btn { border-radius: 12px !important; font-weight: 600 !important; box-shadow: 0 4px 6px rgba(0,0,0,0.05) !important; transition: background-color 0.2s, box-shadow 0.2s !important; } .btn:active { transform: scale(0.98); /* Drück-Effekt */ } /* 1. Das gesamte Accordion-Container-Design */ .accordion { border: none !important; background: transparent !important; } /* 2. Die einzelnen Accordion-Items (die 'Streifen') */ .accordion-item { border: none !important; margin-bottom: 15px !important; /* Abstand zwischen den Elementen für den Schweb-Effekt */ border-radius: 15px !important; /* Abgerundete Ecken für jedes Item */ box-shadow: 0 2px 10px rgba(0,0,0,0.05) !important; /* Weicher Schatten */ overflow: hidden; background-color: #ffffff !important; transition: box-shadow 0.2s ease; } .accordion-item:hover { transform: none !important; box-shadow: 0 6px 20px rgba(0,0,0,0.08) !important; } /* Erzeugt dauerhafte Fettschrift für alle Accordion-Titel */ .accordion-button { font-weight: 600 !important; /* Extra fett */ font-size: 16px !important; color: #1a1a1a !important; background-color: #ffffff !important; border: none !important; box-shadow: none !important; } /* Wenn das Accordion ausgeklappt ist */ .accordion-button:not(.collapsed) { font-weight: 600 !important; background-color: #fcfcfc !important; color: #000000 !important; } /* 4. Der Inhaltsbereich (wenn es offen ist) */ .accordion-body { padding: 20px !important; font-size: 14px; line-height: 1.6; color: #555; background-color: #ffffff !important; border-top: 1px solid #f0f0f0 !important; /* Dezente Trennung zum Header */ } /* Speziell für geschachtelte Accordions (die inneren Ebenen) */ .accordion .accordion { margin-top: 10px; padding: 10px; background-color: #fcfcfc !important; /* Leichter Kontrast zur äußeren Card */ border-radius: 15px; } /* Den Text in den Unterpunkten etwas eleganter machen */ .accordion-body p { color: #444; line-height: 1.7; font-size: 15px; padding: 5px; } .accordion-button h4 { font-weight: 600 !important; margin: 0 !important; transition: color 0.2s ease; /* Macht den Farbwechsel beim Klicken weicher */ color: #1a1a1a !important; } /* Den aktiven Header der Unterpunkte hervorheben */ .accordion-button:not(.collapsed) h4 { color: #2b74a9 !important; } /* 4. Der Hover-Effekt (Damit es beim Drüberfahren reagiert) */ .accordion-button:hover, .accordion-button:hover h4 { color: #666666 !important; /* Ein weiches Dunkelgrau beim Hovern */ } ") ) ), navset_card_tab( nav_panel("Karte", page_sidebar( layout_columns( leafletOutput("hhmap"), card( div( # h3 oder div dient als Block-Element und richtet seinen Inhalt (das span) rechtsbündig aus style = "text-align: right; width: 100%; padding: 5px 10px 0 0;", # Der Text wird in ein span verpackt und erhält die Border. # Ein span nimmt nur den Platz ein, den der Inhalt benötigt (inline). tags$span( "2024", style = " border: 1px solid rgba(40,70,94,0.1); border-radius: 5px; padding: 2px 8px; background-color: #eeeeee; " # padding ist der abstand an leerer Fläche in der reihenfolge top right bottom left # farbe rgba ist die exakte Farbe der Trennlinien und Card-Umrandungen aus der App ) ), uiOutput("txt_map_selection_bezirk"), uiOutput("txt_map_selection_stadtteil"), plotOutput("grph_top3"), ), col_widths = breakpoints( sm = c(12, 12), # Auf kleinen Bildschirmen: untereinander (100% Breite) md = c(8, 4) # Auf Desktop: nebeneinander (8 zu 4 Aufteilung) ) ), sidebar = sidebar( radioButtons( inputId = "rd_maptype", label = "Kartentyp", choices = c("Bezirke", "Stadtteile"), selected = "Bezirke" ), selectizeInput( inputId = "search", label = tags$span(icon("search"),"Suche"), choices = NULL, selected = NULL, multiple = FALSE, # Hier wahrscheinlich nur Einzelauswahl gewünscht options = list( placeholder = "Anfangen zu tippen...", openOnFocus = FALSE, allowEmptyOption = TRUE, selectOnTab = FALSE, plugins = list('dropdown_header') ) ), div( tags$h5( "Heatmap zur Häufigkeit der Straftaten:", style = "font-weight: bold; margin-bottom: 10px;" ), selectizeInput( inputId = "heatmap", label = "Wähle eine Straftat:", choices = list_of_crimes, selected = NULL, options = list( placeholder = "Keine Auswahl", plugins = list('clear_button') ) ) ) ), ) ), nav_panel("Interaktiver Vergleich", layout_sidebar( sidebar = sidebar( title = "Vergleichs-Optionen", width = 400, uiOutput("vergleichs_inputs"), selectizeInput( "vergleich_location", "Zu vergleichende Orte", choices = auswahlmöglichkeiten, multiple = TRUE ), selectizeInput( "vergleich_straftat", "Zu vergleichende Straftaten", choices = list_of_crimes, multiple = TRUE ), # 3. Gemeinsamer Input: Das Jahr selectizeInput( "vergleichs_jahr", "Jahr wählen:", choices = c(2024, 2023), selected = 2024, ), ), card( card_header(uiOutput("vergleichs_titel")), # Dynamischer Titel plotOutput("vergleich_balkendiagramm") ) ) ), nav_panel("Weiterführende Informationen", accordion( open = FALSE, #schließt alle Panels beim Start accordion_panel( title = h3("Raub, räuberische Erpressung, räuberischer Angriff auf Kraftfahrer", style = "margin: 0;"), value = "headline_raub", accordion( open = FALSE, accordion_panel( title = h4("Raub nach §§ 249ff. StGB", style = "margin: 0;"), value = "raub_249", p("Raubdelikte sind Straftaten, bei denen jemand eine fremde bewegliche Sache wegnimmt, indem er Gewalt anwendet oder mit Gewalt droht, um sie sich oder einem Dritten rechtswidrig zuzueignen."), ), accordion_panel( title = h4("Räuberische Erpressung nach § 255 StGB", style = "margin: 0;"), value = "raub_255", p("Räuberische Erpressung ist eine schwere Form der Erpressung, bei der Gewalt gegen eine Person oder die Drohung mit gegenwärtiger Lebens- oder Gesundheitsgefahr eingesetzt wird, um eine Vermögensverfügung zu erzwingen, wodurch der Täter wie ein Räuber (§ 249 StGB) bestraft wird, also mit mindestens einem Jahr Freiheitsstrafe."), ), accordion_panel( title = h4("Räuberischer Angriff auf Kraftfahrer nach § 316a StGB", style = "margin: 0;"), value = "raub_316a", p("Ein räuberischer Angriff auf Kraftfahrer ist ein Verbrechen, bei dem ein Täter unter Ausnutzung der besonderen Situation im Straßenverkehr Gewalt gegen den Fahrer oder Mitfahrer anwendet, um einen Raub, räuberischen Diebstahl oder eine räuberische Erpressung zu begehen."), ), ), ), ), ), ) ) }