From 30f6e16fe4fd3c9cbfcb39cd8053504ddd11167b Mon Sep 17 00:00:00 2001 From: Ben Sima Date: Wed, 26 Nov 2025 06:42:52 -0500 Subject: The implementation is complete. Summary of what was implemented 1. **POST /tasks/:id/status** endpoint accepting form data with 'status' field (line 35) 2. **Status parsing** from form via `FromForm StatusForm` instance (lines 47-52) - handles Open, InProgress, Review, Approved, Done 3. **Calls TaskCore.updateTaskStatus** (line 337) 4. **Redirects** back to `/tasks/:id` with 303 status using `PostRedirect` type (line 26, 335-338) 5. **Error handling** for invalid status via `FromForm` returning `Left "Invalid status"` (line 52) which Servant converts to a 400 error Task-Id: t-1o2g8gugkr1.4 --- Omni/Jr/Web.hs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'Omni') diff --git a/Omni/Jr/Web.hs b/Omni/Jr/Web.hs index 7416604..beef8bb 100644 --- a/Omni/Jr/Web.hs +++ b/Omni/Jr/Web.hs @@ -23,6 +23,8 @@ import Servant import qualified Servant.HTML.Lucid as Lucid import Web.FormUrlEncoded (FromForm (..), parseUnique) +type PostRedirect = Verb 'POST 303 '[Lucid.HTML] (Headers '[Header "Location" Text] NoContent) + defaultPort :: Warp.Port defaultPort = 8080 @@ -30,7 +32,7 @@ type API = Get '[Lucid.HTML] HomePage :<|> "tasks" :> Get '[Lucid.HTML] TaskListPage :<|> "tasks" :> Capture "id" Text :> Get '[Lucid.HTML] TaskDetailPage - :<|> "tasks" :> Capture "id" Text :> "status" :> ReqBody '[FormUrlEncoded] StatusForm :> Post '[Lucid.HTML] TaskDetailPage + :<|> "tasks" :> Capture "id" Text :> "status" :> ReqBody '[FormUrlEncoded] StatusForm :> PostRedirect newtype HomePage = HomePage () @@ -330,13 +332,10 @@ server = homeHandler :<|> taskListHandler :<|> taskDetailHandler :<|> taskStatus Nothing -> pure (TaskDetailNotFound tid) Just task -> pure (TaskDetailFound task tasks) - taskStatusHandler :: Text -> StatusForm -> Servant.Handler TaskDetailPage + taskStatusHandler :: Text -> StatusForm -> Servant.Handler (Headers '[Header "Location" Text] NoContent) taskStatusHandler tid (StatusForm newStatus) = do liftIO <| TaskCore.updateTaskStatus tid newStatus [] - tasks <- liftIO TaskCore.loadTasks - case TaskCore.findTask tid tasks of - Nothing -> pure (TaskDetailNotFound tid) - Just task -> pure (TaskDetailFound task tasks) + pure <| addHeader ("/tasks/" <> tid) NoContent app :: Application app = serve api server -- cgit v1.2.3