From 1ee81f20b6341bd1ba7c712ca13d4a7c3c3fd59b Mon Sep 17 00:00:00 2001 From: Rob Wiederstein Date: Mon, 9 Mar 2026 17:41:20 -0400 Subject: [PATCH] Add Private List tab for off-market owner listings - Form: address, price, sqft, name, email, cell - Appends to data/private_listings.csv with timestamp - Table shows listings < 45 days old (auto-expiry) - Banner reminds users to renew every 45 days --- app.R | 97 +++++++++++++++++++++++++++++++++++++++ data/private_listings.csv | 1 + 2 files changed, 98 insertions(+) create mode 100644 data/private_listings.csv diff --git a/app.R b/app.R index 98c6c10..223d8a0 100644 --- a/app.R +++ b/app.R @@ -97,6 +97,11 @@ ui <- f7Page( title = "Sales", icon = f7Icon("dollarsign_circle_fill") ), + f7PanelItem( + tabName = "PrivateList", + title = "Private List", + icon = f7Icon("lock_fill") + ), f7PanelItem( tabName = "Resources", title = "Resources", @@ -222,6 +227,39 @@ ui <- f7Page( DTOutput("sales_table") ) ), + #### private list ---- + f7Tab( + title = "Private List", + tabName = "PrivateList", + icon = f7Icon("lock_fill"), + f7Block( + tags$p( + style = "text-align:center; color:#ff9500; font-weight:bold;", + "Listings must be renewed every 45 days" + ) + ), + f7Card( + title = "Submit a Listing:", + divider = TRUE, + f7List( + inset = TRUE, dividers = TRUE, strong = TRUE, + f7Text("pl_address", "Address:", placeholder = "895 Chalmers Dr"), + f7Text("pl_price", "Price ($):", placeholder = "325000"), + f7Text("pl_sqft", "Sq Ft:", placeholder = "1800"), + f7Text("pl_name", "Your Name:", placeholder = "Jane Smith"), + f7Text("pl_email", "Email:", placeholder = "jane@email.com"), + f7Text("pl_cell", "Cell:", placeholder = "941-555-1234") + ), + tags$br(), + f7Button("pl_submit", "Submit Listing", color = "blue"), + uiOutput("pl_message") + ), + f7Card( + title = "Active Private Listings:", + divider = TRUE, + DTOutput("pl_table") + ) + ), #### resources ---- f7Tab( title = "Resources", @@ -463,6 +501,65 @@ server <- function(input, output, session) { } ) +# private listings ---- + pl_path <- "./data/private_listings.csv" + + pl_data <- reactivePoll( + intervalMillis = 5000, + session = session, + checkFunc = function() file.info(pl_path)$mtime, + valueFunc = function() { + df <- read.csv(pl_path, stringsAsFactors = FALSE) + if (nrow(df) == 0) return(df) + df$submitted_at <- as.POSIXct(df$submitted_at) + df[difftime(Sys.time(), df$submitted_at, units = "days") <= 45, ] + } + ) + + observeEvent(input$pl_submit, { + req(input$pl_address, input$pl_price, input$pl_name, input$pl_email, input$pl_cell) + new_row <- data.frame( + submitted_at = format(Sys.time(), "%Y-%m-%d %H:%M:%S"), + address = input$pl_address, + price = as.numeric(gsub("[^0-9.]", "", input$pl_price)), + sqft = as.numeric(gsub("[^0-9.]", "", input$pl_sqft)), + name = input$pl_name, + email = input$pl_email, + cell = input$pl_cell, + stringsAsFactors = FALSE + ) + write.table(new_row, pl_path, sep = ",", append = TRUE, + col.names = FALSE, row.names = FALSE, quote = TRUE) + output$pl_message <- renderUI( + tags$p(style = "color:#4cd964;", "Listing submitted successfully!") + ) + updateF7Text(session, "pl_address", value = "") + updateF7Text(session, "pl_price", value = "") + updateF7Text(session, "pl_sqft", value = "") + updateF7Text(session, "pl_name", value = "") + updateF7Text(session, "pl_email", value = "") + updateF7Text(session, "pl_cell", value = "") + }) + + output$pl_table <- renderDT({ + df <- pl_data() + if (nrow(df) == 0) { + return(datatable( + data.frame(Message = "No active listings"), + rownames = FALSE, options = list(dom = 't', searching = FALSE) + )) + } + datatable( + df |> dplyr::mutate( + price = scales::dollar(price), + sqft = formatC(sqft, format = "d", big.mark = ",") + ) |> dplyr::select(address, price, sqft, name, email, cell), + colnames = c("Address", "Price", "Sq Ft", "Name", "Email", "Cell"), + rownames = FALSE, + options = list(pageLength = 25, searching = FALSE, dom = 't') + ) + }) + # listings map ---- output$listings_map <- renderLeaflet({ leaflet(listings) |> diff --git a/data/private_listings.csv b/data/private_listings.csv new file mode 100644 index 0000000..7d20894 --- /dev/null +++ b/data/private_listings.csv @@ -0,0 +1 @@ +"submitted_at","address","price","sqft","name","email","cell"