fix: send URL-encoded form data instead of multipart, show errors inline, default empty date to today
Build and Deploy / build-and-deploy (push) Successful in 15m46s

This commit is contained in:
2026-05-25 22:26:53 -04:00
parent 930fba369c
commit 14f43a4ae9
2 changed files with 33 additions and 20 deletions
+11 -5
View File
@@ -658,11 +658,13 @@ cookLogJs =
, "var form = document.getElementById('roux-record-form');"
, "var dateInput = document.getElementById('roux-record-date');"
, "var commentInput = document.getElementById('roux-record-comment');"
, "var errorEl = document.getElementById('roux-record-error');"
, "if (!btn || !modal || !form) return;"
, ""
, "function showModal() {"
, " dateInput.value = new Date().toISOString().slice(0,10);"
, " commentInput.value = '';"
, " errorEl.style.display = 'none';"
, " modal.style.display = 'block';"
, " dateInput.focus();"
, "}"
@@ -681,20 +683,23 @@ cookLogJs =
, ""
, "form.addEventListener('submit', async function(e) {"
, " e.preventDefault();"
, " var date = dateInput.value;"
, " var comment = commentInput.value;"
, " var filename = btn.dataset.filename;"
, " var fd = new FormData(form);"
, " var body = 'cooked-date=' + encodeURIComponent(date);"
, " if (comment) body += '&comment=' + encodeURIComponent(comment);"
, " var res = await fetch('/cook-log/' + encodeURIComponent(filename), {"
, " method: 'POST',"
, " body: fd"
, " headers: { 'Content-Type': 'application/x-www-form-urlencoded' },"
, " body: body"
, " });"
, " if (!res.ok) {"
, " var err = await res.json();"
, " alert(err.error || 'Failed to log cooking');"
, " errorEl.textContent = err.error || 'Failed to log cooking';"
, " errorEl.style.display = 'block';"
, " return;"
, " }"
, " hideModal();"
, " var date = fd.get('cooked-date');"
, " var comment = fd.get('comment');"
, " var entryDiv = document.createElement('div');"
, " entryDiv.style.margin = '0.3rem 0';"
, " entryDiv.style.fontSize = '0.9rem';"
@@ -983,6 +988,7 @@ renderRecipe filename recipe entries = do
H.input ! A.type_ "date" ! A.id "roux-record-date" ! A.name "cooked-date" ! A.required ""
H.label ! A.for "roux-record-comment" $ "Comment (optional)"
H.textarea ! A.id "roux-record-comment" ! A.name "comment" ! A.placeholder "How did it go?" ! A.maxlength "500" $ ""
H.p ! A.id "roux-record-error" ! A.style "color: var(--roux-accent); font-size: 0.8rem; margin: 0 0 0.5rem; display: none;" $ ""
H.div ! A.class_ "roux-modal-actions" $ do
H.button ! A.type_ "button" ! A.class_ "roux-modal-cancel" ! A.id "roux-modal-cancel" $ "Cancel"
H.button ! A.type_ "submit" ! A.class_ "roux-modal-confirm" $ "Log it"
+13 -6
View File
@@ -26,7 +26,6 @@ import qualified Data.Map.Strict as Map
import Data.Text (Text)
import qualified Data.Text as T
import Data.Text.Encoding (encodeUtf8)
import Data.Time.Clock (diffUTCTime, getCurrentTime)
import qualified Network.HTTP.Types as HTTP
import qualified Network.Wai as Wai
@@ -48,6 +47,7 @@ import qualified Data.ByteString as BS
import Data.Maybe (fromMaybe, mapMaybe)
import qualified Data.Text.Encoding as TE
import Data.Time.Calendar (Day, fromGregorianValid)
import Data.Time.Clock (diffUTCTime, getCurrentTime, utctDay)
import qualified Data.Time.Format as Time
import qualified Database.SQLite.Simple as SQL
import Roux.Config (AnthropicConfig (..), RouxConfig (..))
@@ -672,16 +672,19 @@ handleCookLogPost db filename request respond = do
let params = parseFormBody body
dateStr = fromMaybe "" (lookup "cooked-date" params)
comment = lookup "comment" params
case parseDate dateStr of
Just day -> do
_ <- CookLog.insertEntry db filename day comment
let resp =
let doInsert d = do
_ <- CookLog.insertEntry db filename d comment
respond $
Wai.responseLBS
HTTP.status200
[("Content-Type", "application/json")]
(LB.fromStrict (encodeUtf8 "{\"ok\":true}"))
respond resp
case parseDate dateStr of
Just d -> doInsert d
Nothing ->
if T.null dateStr
then getCurrentDay >>= doInsert
else
let resp =
Wai.responseLBS
HTTP.status400
@@ -689,6 +692,10 @@ handleCookLogPost db filename request respond = do
(LB.fromStrict (encodeUtf8 "{\"error\":\"Invalid date format\"}"))
in respond resp
-- | Get today's date.
getCurrentDay :: IO Day
getCurrentDay = utctDay <$> getCurrentTime
-- | Parse a YYYY-MM-DD date string.
parseDate :: Text -> Maybe Day
parseDate t = case T.splitOn "-" t of