library(bslib)
ui <- page_navbar(
id = "main_navbar",
fillable = TRUE,
title = "Tropical Cyclone Database",
theme = bs_theme(
bootswatch = "sandstone"
),
nav_panel(
"Home",
card(
"Welcome to the Tropical Cyclone Database",
HTML(
'
Welcome to the Hurricane Cost Normalization Web App
Our platform provides access to normalized hurricane damage data spanning from 1900 to 2024, allowing researchers, policymakers, insurance professionals, and the public to better understand how hurricane costs have changed over time.
Our Data
The core datasets used in this app are based on research by Muller et al. (2025) published in Bulletin of the American Meteorlogical Society. This study updates and refines hurricane damage normalization methodologies to provide a more accurate picture of how historical hurricanes would impact today\'s society.
- MMP24: The Muller-Mooney Population (2024) normalization with RMW weighting on affected population.
- MMH24: The Muller-Mooney Housing (2024) normalization with RMW weighting on affected housing units.
Methodology Innovations
Our platform incorporates several methodological innovations over previously used cost normalization formulas:
- Radius of Maximum Wind (RMW) Data: Using landfalling RMWs to identify impacted coastal counties.
- RMW Affected Area Weighting: Determining affected population and housing unit figures based on RMW.
- Expanded Storm Coverage: Including over 200 storms analyzed with interactive data.
- Up-to-date Data: Using the latest population, housing unit, and economic data through 2024.
'
)
)
),
nav_panel(
"Storm Selector",
layout_columns(
col_widths = c(8, 4),
card(
card_body(
DTOutput("storm_coverage_table")
)
),
layout_columns(
col_widths = 12,
card(
height = 300,
div(
h5(strong(textOutput("dt_storm_name_year"))),
uiOutput("dt_storm_badges")
),
layout_columns(
col_widths = c(6, 6),
card(
class = "bg-light",
card_body(
class = "p-1",
div(
div(tags$small(class = "text-muted", "Track Observations")),
h6(strong(textOutput("dt_track_observations")))
)
)
),
card(
class = "bg-light",
card_body(
class = "p-1",
div(
div(tags$small(class = "text-muted", "Max Category")),
h6(strong(textOutput("dt_max_category")))
)
)
),
card(
class = "bg-light",
card_body(
class = "p-1",
div(
div(tags$small(class = "text-muted", "Max Windspeed")),
h6(strong(textOutput("dt_max_windspeed")))
)
)
),
card(
class = "bg-light",
card_body(
class = "p-1",
div(
div(tags$small(class = "text-muted", "Min Pressure")),
h6(strong(textOutput("dt_min_pressure")))
)
)
)
),
actionButton("load_storm", "Load Storm")
),
card(
height = 700,
card_body(
class = "p-0",
leafletOutput("all_storms_map", height = "100%")
)
)
)
)
),
nav_panel(
title = "Storm Explorer",
navset_card_underline(
nav_item(strong(textOutput("selected_storm_name_year"))),
nav_panel(
"Track",
layout_columns(
col_widths = 12,
layout_column_wrap(
card(
full_screen = TRUE,
card_body(
class = "p-0",
leafletOutput("track_map", height = "100%")
)
),
layout_column_wrap(
width = 1,
card(
card_body(
DTOutput("track_data", fill = TRUE)
)
),
card(
dygraphOutput("track_met_chart", height = "250px")
)
)
)
)
),
nav_panel(
"Cost Normalization",
layout_column_wrap(
col_widths = 1,
card(
full_screen = TRUE,
layout_sidebar(
sidebar = sidebar(
virtualSelectInput(
"storm_overview_cost_index_lf_select",
"Landfalls",
choices = NULL,
showValueAsTags = T,
multiple = T,
autoSelectFirstOption = T
),
radioGroupButtons(
"storm_overview_cost_index_scale",
label = "Value",
choices = c("Index", "Loss"),
status = "outline-primary rounded-0",
justified = T
),
checkboxGroupButtons(
"storm_overview_cost_index_mmh_mmp",
label = "MMH/MMP",
choices = c("MMH", "MMP"),
selected = c("MMH", "MMP"),
status = "outline-primary rounded-0",
justified = T
),
radioGroupButtons(
"storm_overview_cost_index_y_scale",
label = "Y-Axis Scale",
choices = c("Linear", "Log"),
status = "outline-primary rounded-0",
justified = T
)
),
dygraphOutput("cost_index_chart")
)
)
)
),
nav_panel(
"Human Factors",
layout_column_wrap(
width = 1,
layout_columns(
col_widths = 12,
row_heights = c("auto", "1fr", "auto"),
card(
fill = FALSE,
layout_columns(
selectInput(
"growth_trend_lf_select",
"Landfall Select",
choices = NULL
),
radioGroupButtons(
"growth_map_metric",
label = "Display Metric",
choices = c("Population", "Housing"),
selected = "Population",
status = "outline-primary rounded-0",
justified = T
)
),
),
card(
full_screen = TRUE,
card_body(
class = "p-0",
leafletOutput("growth_map", height = "100%")
)
),
card(
fill = FALSE,
sliderInput(
"growth_trend_map_slider",
label = NULL,
min = 0,
max = 2024,
step = 1,
animate = list(
interval = 250,
loop = F
),
value = 0,
sep = "",
width = "100%",
ticks = F
)
)
)
)
),
nav_panel(
"Fatality Map",
layout_columns(
col_widths = c(8, 4),
card(
full_screen = TRUE,
layout_sidebar(
class = "p-0",
sidebar = sidebar(
actionButton("hi", "test"),
open = "always"
),
leafletOutput("fatality_map", height = "100%")
)
),
layout_column_wrap(
width = 1,
card(
plotlyOutput("fatality_pie", height = "100%")
),
card(
plotlyOutput("fatality_heatmap", height = "100%")
)
)
)
),
nav_spacer(),
nav_menu(
title = "Export",
nav_item("Storm report")
)
)
),
nav_menu(
"Data",
nav_panel("What We Track"),
nav_panel("Sources"),
nav_panel("Export")
),
nav_menu(
"About",
nav_panel("Contact Us"),
nav_panel("Our Studies"),
nav_panel("MMH/MMP Methodology")
)
)