feat: expand import form with file upload via base64 JS

This commit is contained in:
2026-05-21 10:32:49 -04:00
parent 578d1ae068
commit 232373cd5c
+58 -3
View File
@@ -546,6 +546,36 @@ indexPage _mode recipes =
filterOk = filter (isRight . Idx.riRecipe)
filterBad = filter (isLeft . Idx.riRecipe)
-- | Inline JavaScript for converting file uploads to base64 before form submission.
fileUploadJs :: Text
fileUploadJs =
T.unlines
[ "(function(){"
, "'use strict';"
, "var form = document.getElementById('import-form');"
, "var fileInput = document.getElementById('file-input');"
, "var b64Field = document.getElementById('file-b64');"
, "var nameField = document.getElementById('file-name');"
, "var mimeField = document.getElementById('file-mime');"
, ""
, "form.addEventListener('submit', function(e) {"
, " if (fileInput.files.length > 0) {"
, " e.preventDefault();"
, " var file = fileInput.files[0];"
, " var reader = new FileReader();"
, " reader.onload = function() {"
, " var b64 = reader.result.split(',')[1];"
, " b64Field.value = b64;"
, " nameField.value = file.name;"
, " mimeField.value = file.type;"
, " form.submit();"
, " };"
, " reader.readAsDataURL(file);"
, " }"
, "});"
, "})();"
]
-- ---------------------------------------------------------------------------
-- Import page (form + result)
-- ---------------------------------------------------------------------------
@@ -560,16 +590,41 @@ importPage merror =
case merror of
Just err -> H.p ! A.style "color: var(--roux-accent);" $ H.toHtml err
Nothing -> pure ()
H.form ! A.method "POST" ! A.action "/import" $ do
H.p ! A.style "font-size: 0.85rem; opacity: 0.7; margin-bottom: 1.5rem;" $
"Paste a recipe URL, upload a PDF or image, or paste recipe text directly."
H.form ! A.method "POST" ! A.action "/import" ! A.id "import-form" $ do
-- URL input
H.label ! A.for "url" $ "Recipe URL"
H.input
! A.type_ "url"
! A.id "url"
! A.name "url"
! A.placeholder "https://cooking.nytimes.com/recipes/..."
! A.required ""
! A.style "width: 100%; margin-bottom: 1rem;"
! A.style "width: 100%; margin-bottom: 1.5rem;"
-- File upload
H.label ! A.for "file-input" $ "Or upload a PDF or image"
H.input
! A.type_ "file"
! A.id "file-input"
! A.accept ".pdf,image/*"
! A.style "width: 100%; margin-bottom: 1.5rem;"
-- Hidden fields for base64 file data (set by JS)
H.input ! A.type_ "hidden" ! A.id "file-b64" ! A.name "file-b64" ! A.value ""
H.input ! A.type_ "hidden" ! A.id "file-name" ! A.name "file-name" ! A.value ""
H.input ! A.type_ "hidden" ! A.id "file-mime" ! A.name "file-mime" ! A.value ""
-- Text area
H.label ! A.for "text" $ "Or paste recipe text"
H.textarea
! A.id "text"
! A.name "text"
! A.rows "8"
! A.placeholder "Paste recipe text here..."
! A.style "width: 100%; margin-bottom: 1.5rem; font-family: monospace; font-size: 0.85rem;"
$ ""
-- Submit
H.button ! A.type_ "submit" $ "Import Recipe"
-- Inline JS for base64 file conversion
H.script ! A.type_ "text/javascript" $ H.preEscapedText fileUploadJs
-- | Render the import result page with an error message.
importResultPage :: ImportError -> ByteString