library(shiny) library(shinyMobile) library(shinyalert) library(shinyWidgets) library(glue) library(dplyr) library(dbplyr) library(stringr) word_wrap <- function(x){ str_split(x, ",") |> unlist() |> str_trim("both") |> sapply(FUN = function(k){ if_else(is.na(k), "-", k) }) |> sapply(FUN = function(z){ if_else(nchar(z) > 90, paste(substring(z, 1, 30), substring(z, 31, 60), substring(z, 61, 90), substring(z, 91), sep = "
"), if_else(nchar(z) > 60, paste(substring(z, 1, 30), substring(z, 31, 60), substring(z, 61), sep = "
"), if_else(nchar(z) > 30, paste(substring(z, 1, 30), substring(z, 31), sep = "
"), z))) }) |> str_c(collapse = ",
") |> HTML() } ui <- f7Page( options = list(theme = "ios", dark = FALSE, skeletonOnLoad = TRUE), allowPWA = TRUE, f7TabLayout( navbar = f7Navbar(title = "SIMPASI"), f7Tabs(animated = T, id = "tabs", f7Tab(tabName = "input_menu", title = "Input Menu", active = TRUE, icon = f7Icon("book"), # Content f7Card( h4(span(f7Icon("calendar"), "Tanggal"), style="margin:0px 0px 10px 0px;"), f7DatePicker("tgl", NULL), hr() ), f7Card( h4(span(f7Icon("tray"), "Karbohidrat"), style="margin:0px 0px 10px 0px;"), f7TextArea("karbo", NULL, resize = TRUE), hr() ), f7Card( h4(span(f7Icon("poultry_leg"), "Protein Hewani"), style="margin:0px 0px 10px 0px;"), f7TextArea("protein_hewani", NULL, resize = TRUE), hr() ), f7Card( h4(span(f7Icon("tree"), "Protein Nabati"), style="margin:0px 0px 10px 0px;"), f7TextArea("protein_nabati", NULL, resize = TRUE), hr() ), f7Card( h4(span(f7Icon("leaf_arrow_circlepath"), "Buah/Sayur"), style="margin:0px 0px 10px 0px;"), f7TextArea("buah_sayur", NULL, resize = TRUE), hr() ), f7Card( h4(span(f7Icon("drop"), "Lemak Tambahan"), style="margin:0px 0px 10px 0px;"), f7TextArea("lemak_tambahan", NULL, resize = TRUE), hr() ), f7Card( h4(span(f7Icon("circle_grid_hex"), "Camilan"), style="margin:0px 0px 10px 0px;"), f7TextArea("camilan", NULL, resize = TRUE), hr() ), f7Card( h4(span(f7Icon("bandage"), "Gejala Alergi"), style="margin:0px 0px 10px 0px;"), f7TextArea("gejala", NULL, resize = TRUE), hr() ), f7Card( h4(span(f7Icon("calendar_today"), "Tanggal Terjadi Gejala"), style="margin:0px 0px 10px 0px;"), f7DatePicker("tgl_gejala", NULL), hr() ), f7Card( f7Button("save", "Simpan", size = "large"), br(), p("Copyright (C) 2024 aephidayatuloh", style = "text-align: center") ) ), f7Tab(tabName = "cari", title = "Cari Catatan", icon = f7Icon("doc_text_search"), # Content f7Card( f7Select("komponen", "Cari berdasarkan:", width = "100%", choices = list("Tanggal" = "tanggal", "Karbohidrat" = "karbo", "Protein Hewani" = "protein_hewani", "Protein Nabati" = "protein_nabati", "Buah/Sayur" = "buah_sayur", "Lemak Tambahan" = "lemak_tambahan", "Camilan" = "camilan", "Gejala Alergi" = "gejala")) ), conditionalPanel("input.komponen == 'tanggal'", f7Card( h4(span(f7Icon("calendar"), "Tanggal MPASI"), style="margin:0px 0px 10px 0px;"), f7DatePicker("cari_date", NULL, value = Sys.Date()), hr() ), f7Card( f7Segment(container = "row", f7Button("prev", "< Prev", size = "large"), f7Button("nex", "Next >", size = "large") ) ), f7Card(uiOutput("out_cari_tgl")) ), conditionalPanel("input.komponen != 'tanggal'", f7Card( p("Kata Kunci", style="text-align:center;"), f7Text("keyword", NULL, value = ""), hr(style="margin:5px 0px;") ), uiOutput("out_cari_komponen") ) ), f7Tab(tabName = "update_gejala", title = "Update Gejala", icon = f7Icon("bubble_left_bubble_right"), # Content f7Card( h4(span(f7Icon("calendar_today"), "Tanggal Terjadi Gejala"), style="margin:0px 0px 10px 0px;"), f7DatePicker("edit_tgl_gejala", NULL), hr() ), f7Card( h4(span(f7Icon("bandage"), "Gejala Alergi"), style="margin:0px 0px 10px 0px;"), f7TextArea("edit_gejala", NULL, resize = TRUE), hr() ), f7Card( h4(span(f7Icon("bandage"), "Tanggal Pemberian MPASI"), style="margin:0px 0px 10px 0px;"), f7DatePicker("edit_tanggal", NULL), hr() ), f7Card( f7Button("edit_update", "Update", size = "large") ) ) ) ) ) server <- function(input, output, session){ menu_tbl <- reactive({ # source("dbconnect.R") # menu <- pg_con |> pg_con |> tbl("menu") # dbDisconnect(pg_con) # return(menu) }) observeEvent(input$save, { shinyalert(text = "Yakin ingin menyimpan?", type = "info", showCancelButton = TRUE, callbackR = function(x){ if(x != FALSE){ shinyalert(text = "Menyimpan data ...", type = "info", showConfirmButton = FALSE, closeOnEsc = FALSE, closeOnClickOutside = FALSE) tgl_gejala <- if_else(input$gejala %in% c(NA, NULL, "", "-"), NA , as.Date(input$tgl_gejala)) # source("dbconnect.R") # query <- glue("INSERT INTO public.menu (id_parent, id_anak, tanggal, karbo, protein_hewani, protein_nabati, buah_sayur, lemak_tambahan, camilan, gejala, tgl_gejala, created_date) # VALUES (1, 2, '{input$tgl}', '{input$karbo}', '{input$protein_hewani}', '{input$protein_nabati}', '{input$buah_sayur}', '{input$lemak_tambahan}', '{input$camilan}', '{input$gejala}', {tgl_gejala}, '{Sys.time()}')") menu_data <- tribble( ~id_parent, ~id_anak, ~tanggal, ~karbo, ~protein_hewani, ~protein_nabati, ~buah_sayur, ~lemak_tambahan, ~camilan, ~gejala, ~tgl_gejala, ~created_date, 1, 2, input$tgl, input$karbo, input$protein_hewani, input$protein_nabati, input$buah_sayur, input$lemak_tambahan, input$camilan, input$gejala, tgl_gejala, Sys.time() ) pg_con |> dbAppendTable(name = "menu", value = menu_data) # dbDisconnect(pg_con) updateF7DatePicker(session = session, "tgl", NULL, value = Sys.Date()) updateF7TextArea(session = session, "karbo", NULL, value = "") updateF7TextArea(session = session, "protein_hewani", NULL, value = "") updateF7TextArea(session = session, "protein_nabati", NULL, value = "") updateF7TextArea(session = session, "buah_sayur", NULL, value = "") updateF7TextArea(session = session, "lemak_tambahan", NULL, value = "") updateF7TextArea(session = session, "camilan", NULL, value = "") updateF7TextArea(session = session, "gejala", NULL, value = "") updateF7DatePicker(session = session, "tgl_gejala", NULL, value = Sys.Date()) # closeAlert() shinyalert(text = "Data berhasil disimpan.", type = "success", immediate = TRUE) } }) }) observeEvent(input$prev, { date_val <- reactiveValues() date_val$curr_dt <- input$cari_date updateF7DatePicker("cari_date", NULL, value = date_val$curr_dt - 1, session = session) } ) observeEvent(input$nex, { date_val <- reactiveValues() date_val$curr_dt <- input$cari_date updateF7DatePicker("cari_date", NULL, value = date_val$curr_dt + 1, session = session) } ) observeEvent(input$prev_history, { date_val_history <- reactiveValues() date_val_history$curr_dt_history <- as.Date(input$history_date) updateF7DatePicker(inputId = "history_date", NULL, value = date_val_history$curr_dt_history - 1, session = session) } ) observeEvent(input$nex_history, { message("Next sampai sini bisa") date_val_history <- reactiveValues() message("Next sampai reactivevalues() bisa") date_val_history$curr_dt_history <- as.Date(input$history_date) message("Next sampai update reactiveValues bisa") updateF7DatePicker(inputId = "history_date", NULL, value = date_val_history$curr_dt_history + 1, session = session) } ) output$out_cari_tgl <- renderUI({ cari_menu <- menu_tbl() |> collect() |> mutate(across(karbo:gejala, ~if_else(.x == "", "-", .x))) |> filter(tanggal == input$cari_date) |> mutate(tgl_gejala = tgl_gejala |> as.Date() |> format("%d %b %Y")) if(nrow(cari_menu) == 0){ p("Tidak ada catatan", style="text-align: center;") } else { f7List( f7ListItem(media = f7Icon("calendar"), header = "Tanggal", h5(format(input$cari_date, "%d %b %Y"), style="margin: 5px 0px;") ), f7ListItem(media = f7Icon("tray"), header = "Karbohidrat", h5(word_wrap(cari_menu$karbo), style="margin: 5px 0px;") ), f7ListItem(media = f7Icon("poultry_leg"), header = "Protein Hewani", h5(word_wrap(cari_menu$protein_hewani), style="margin: 5px 0px;") ), f7ListItem(media = f7Icon("tree"), header = "Protein Nabati", h5(word_wrap(cari_menu$protein_nabati), style="margin: 5px 0px;") ), f7ListItem(media = f7Icon("leaf_arrow_circlepath"), header = "Buah/Sayur", h5(word_wrap(cari_menu$buah_sayur), style="margin: 5px 0px;") ), f7ListItem(media = f7Icon("drop"), header = "Lemak Tambahan", h5(word_wrap(cari_menu$lemak_tambahan), style="margin: 5px 0px;") ), f7ListItem(media = f7Icon("circle_grid_hex"), header = "Camilan", h5(word_wrap(cari_menu$camilan), style="margin: 5px 0px;") ), f7ListItem(media = f7Icon("bandage"), header = "Gejala Alergi", h5(word_wrap(cari_menu$gejala), style="margin: 5px 0px;color: red;") ), f7ListItem(media = f7Icon("calendar_today"), header = "Tanggal Terjadi Gejala", h5(ifelse(is.na(cari_menu$tgl_gejala), "-", cari_menu$tgl_gejala), style="margin: 5px 0px;color: red;") ) ) } }) cari_history <- reactive({ if(input$keyword != ""){ menu_tbl() |> collect() |> mutate(across(karbo:gejala, ~if_else(.x == "", "-", .x))) |> mutate(tgl_gejala = tgl_gejala |> as.Date() |> format("%d %b %Y")) |> mutate(kolom := tolower(!!sym(input$komponen))) |> #slice(1) filter(str_detect(kolom, tolower(input$keyword))) |> arrange(tanggal) } else { x <- data.frame(x = 0) return(x) } }) history <- reactive({ cari_history() |> slice(input$index_history_komponen) }) output$out_history <- renderUI({ if(ncol(cari_history()) == 1 | input$keyword == "" | nrow(history()) == 0){ wellPanel(style="background-color:transparent;", p("Tidak ada catatan", style="text-align: center;") ) } else if(ncol(cari_history()) >= 1){ f7Card( f7List( f7ListItem(media = f7Icon("calendar"), header = "Tanggal", h5(format(as.Date(history()$tanggal), "%d %b %Y"), style="margin: 5px 0px;") ), f7ListItem(media = f7Icon("tray"), header = "Karbohidrat", h5(word_wrap(history()$karbo), style="margin: 5px 0px;max-width: 300px;overflow-wrap: inherit;word-wrap: inherit;hyphens: auto;") ), f7ListItem(media = f7Icon("poultry_leg"), header = "Protein Hewani", h5(word_wrap(history()$protein_hewani), style="margin: 5px 0px;max-width: 300px;overflow-wrap: inherit;word-wrap: inherit;hyphens: auto;") ), f7ListItem(media = f7Icon("tree"), header = "Protein Nabati", h5(word_wrap(history()$protein_nabati), style="margin: 5px 0px;max-width: 300px;") ), f7ListItem(media = f7Icon("leaf_arrow_circlepath"), header = "Buah/Sayur", h5(word_wrap(history()$buah_sayur), style="margin: 5px 0px;") ), f7ListItem(media = f7Icon("drop"), header = "Lemak Tambahan", h5(word_wrap(history()$lemak_tambahan), style="margin: 5px 0px;") ), f7ListItem(media = f7Icon("circle_grid_hex"), header = "Camilan", h5(word_wrap(history()$camilan), style="margin: 5px 0px;") ), f7ListItem(media = f7Icon("bandage"), header = "Gejala Alergi", h5(word_wrap(history()$gejala), style="margin: 5px 0px;color: red;") ), f7ListItem(media = f7Icon("calendar_today"), header = "Tanggal Terjadi Gejala", h5(ifelse(is.na(history()$tgl_gejala), "-", history()$tgl_gejala), style="margin: 5px 0px;color: red;") ) ) ) } }) output$out_cari_komponen <- renderUI({ if(ncol(cari_history()) == 1 | input$keyword == "" | nrow(cari_history()) == 0){ f7Card(p("Tidak ada catatan", style="text-align: center;")) } else if(nrow(cari_history()) > 1){ n_history_komponen <- nrow(cari_history()) tagList( # f7DatePicker("history_date", NULL, # value = min(cari_history()$tanggal)), div(style="margin-left: 120px;width:150%;", f7Stepper("index_history_komponen", label = NULL, value = 1, min = 1, max = n_history_komponen, step = 1, raised = TRUE, rounded = TRUE, size = "small", fill = TRUE, color = "blue", wraps = TRUE) ), # f7Segment(container = "segment", # f7Button("prev_history", "< Prev"), # f7Button("nex_history", "Next >") # ), uiOutput("out_history") ) } else { f7Card( f7List( f7ListItem(media = f7Icon("calendar"), header = "Tanggal", h5(format(as.Date(cari_history()$tanggal), "%d %b %Y"), style="margin: 5px 0px;") ), f7ListItem(media = f7Icon("tray"), header = "Karbohidrat", h5(word_wrap(cari_history()$karbo), style="margin: 5px 0px;max-width: 300px;overflow-wrap: inherit;word-wrap: inherit;hyphens: auto;") ), f7ListItem(media = f7Icon("poultry_leg"), header = "Protein Hewani", h5(word_wrap(cari_history()$protein_hewani), style="margin: 5px 0px;max-width: 300px;overflow-wrap: inherit;word-wrap: inherit;hyphens: auto;") ), f7ListItem(media = f7Icon("tree"), header = "Protein Nabati", h5(word_wrap(cari_history()$protein_nabati), style="margin: 5px 0px;max-width: 300px;") ), f7ListItem(media = f7Icon("leaf_arrow_circlepath"), header = "Buah/Sayur", h5(word_wrap(cari_history()$buah_sayur), style="margin: 5px 0px;") ), f7ListItem(media = f7Icon("drop"), header = "Lemak Tambahan", h5(word_wrap(cari_history()$lemak_tambahan), style="margin: 5px 0px;") ), f7ListItem(media = f7Icon("circle_grid_hex"), header = "Camilan", h5(word_wrap(cari_history()$camilan), style="margin: 5px 0px;") ), f7ListItem(media = f7Icon("bandage"), header = "Gejala Alergi", h5(word_wrap(cari_history()$gejala), style="margin: 5px 0px;color: red;") ), f7ListItem(media = f7Icon("calendar_today"), header = "Tanggal Terjadi Gejala", h5(ifelse(is.na(cari_history()$tgl_gejala), "-", cari_history()$tgl_gejala), style="margin: 5px 0px;color: red;") ) ) ) } }) observeEvent(input$edit_update, { shinyalert(type = "info", text = "Anda yakin ingin memperbarui data?", showCancelButton = TRUE, showConfirmButton = TRUE, callbackR = function(x){ if(x != FALSE){ shinyalert(type = "info", text = "Sedang diproses...", immediate = TRUE, showConfirmButton = FALSE, closeOnEsc = FALSE, closeOnClickOutside = FALSE) if(menu_tbl() |> collect() |> filter(tanggal == input$edit_tanggal) |> nrow() < 1){ shinyalert(type = "warning", text = "Tidak ada data untuk tanggal MPASI tersebut", immediate = TRUE, showCancelButton = FALSE, showConfirmButton = TRUE, closeOnEsc = FALSE, closeOnClickOutside = FALSE) } else { qr <- glue("UPDATE public.menu SET gejala = '{input$edit_gejala}', tgl_gejala = '{input$edit_tgl_gejala}' WHERE tanggal = '{input$edit_tanggal}'") r <- dbSendQuery(pg_con, qr) dbClearResult(r) updateF7DatePicker("edit_tgl_gejala", NULL, value = Sys.Date(), session = session) updateF7TextArea("edit_gejala", NULL, value = "", session = session) updateF7DatePicker("edit_tanggal", NULL, value = Sys.Date(), session = session) shinyalert(type = "success", text = "Data berhasil diperbarui", immediate = TRUE, showCancelButton = FALSE, showConfirmButton = TRUE, closeOnEsc = FALSE, closeOnClickOutside = FALSE) } } }) }) } shinyApp(ui, server, onStart = function(){ source("dbconnect.R") onStop(function(){ dbDisconnect(pg_con) }) } )