diff --git a/api/server.js b/api/server.js index 3b7a796..22d16f1 100644 --- a/api/server.js +++ b/api/server.js @@ -4,17 +4,16 @@ const {host, port} = require("./settings") const app = express() app.use(express.json()) +app.use(express.urlencoded({ extended: true })) -app.delete("/api/v1/tasks/:uuid", (req, res) => { - const {uuid} = req.params - console.log(`DELETE Task('${uuid}')`) +app.delete("/api/v1/tasks/:pk", (req, res) => { res.status(200).end() }) -app.patch("/api/v1/tasks/:uuid", (req, res) => { - const {uuid} = req.params - console.log(`PATCH Task('${uuid}')`) - res.status(200).end() +app.patch("/api/v1/tasks/:pk", (req, res) => { + const {pk} = req.params + const completed = req.body.completed === "true" + res.status(200).json({pk, completed}) }) app.listen(port, host, () => { diff --git a/src/index.js b/src/index.js index 7e1ecf0..6c6ba56 100644 --- a/src/index.js +++ b/src/index.js @@ -18,3 +18,5 @@ import "./scss/list.scss" import "./scss/profile.scss" import "./scss/sign-in.scss" import "./scss/sign-up.scss" + +import "./js/tasks" diff --git a/src/js/tasks.js b/src/js/tasks.js new file mode 100644 index 0000000..e090058 --- /dev/null +++ b/src/js/tasks.js @@ -0,0 +1,65 @@ +const swapTaskListCompletedStatus = ({pk, completed}) => { + const element = document.getElementById(pk) + if (element) element.setAttribute("data-task-completed", completed) +} + + +const swapTaskDetailedCompletedStatus = ({completed}) => { + const element = document.querySelector("h1#summary") + if (!element) return + + if (completed) { + const icon = document.createElement("i") + icon.classList.add("bi", "bi-check-lg", "text-success") + element.prepend(icon) + } else { + const icon = element.querySelector("i.bi.bi-check-lg") + element.removeChild(icon) + } +} + + +const updateListActionButton = (element, completed) => { + element.classList.remove("bi-arrow-repeat", "bi-check-lg") + if (completed) { + element.classList.add("bi-arrow-repeat") + } else { + element.classList.add("bi-check-lg") + } +} + + +const updateDetailActionButton = (element, completed) => { + element.classList.remove("btn-outline-warning", "btn-outline-success") + if (completed) { + element.classList.add("btn-outline-warning") + element.textContent = "Reopen" + } else { + element.classList.add("btn-outline-success") + element.textContent = "Complete" + } +} + + +const swapTaskPatchButton = ({element, completed}) => { + element.setAttribute("hx-vals", `js:{completed:${!completed}}`) + if (element.matches("i[role=button]")) updateListActionButton(element, completed) + if (element.matches("button.btn")) updateDetailActionButton(element, completed) +} + + +document.body.addEventListener("htmx:afterOnLoad", (event) => { + const xhr = event.detail.xhr + if (xhr.status !== 200) return // do nothing if request wasn't successful + + const triggeredElement = event.detail.elt + const action = triggeredElement.getAttribute("data-task-action") + let response = xhr.response + + if (action === "patch" && xhr.responseURL.includes("tasks")) { + response = JSON.parse(response) + swapTaskPatchButton({...response, element: triggeredElement}) + swapTaskDetailedCompletedStatus(response) + swapTaskListCompletedStatus(response) + } +}) diff --git a/src/scss/list.scss b/src/scss/list.scss index fade689..d13a469 100644 --- a/src/scss/list.scss +++ b/src/scss/list.scss @@ -25,15 +25,11 @@ $list-img-max-size: 5rem; } // action buttons - [aria-label=complete] { + [data-task-action=patch] { color: var(--bs-success); } - [aria-label=reopen] { - color: var(--bs-warning); - } - - [aria-label=delete] { + [data-task-action=delete] { color: var(--bs-danger); } } @@ -43,4 +39,8 @@ $list-img-max-size: 5rem; color: var(--bs-secondary-color) !important; text-decoration: line-through !important; } + + [data-task-action=patch] { + color: var(--bs-warning) + } } diff --git a/src/views/partials/detail_main.hbs b/src/views/partials/detail_main.hbs index 7392a32..024df57 100644 --- a/src/views/partials/detail_main.hbs +++ b/src/views/partials/detail_main.hbs @@ -1,9 +1,9 @@
-

- {{#if completed}} {{/if}} - {{summary}} +

+ {{#if completed}}{{/if}} + {{summary}}


@@ -33,12 +33,14 @@
{{#if completed}} {{else}} {{/if}} diff --git a/src/views/partials/list_main.hbs b/src/views/partials/list_main.hbs index ded18c1..620c3ec 100644 --- a/src/views/partials/list_main.hbs +++ b/src/views/partials/list_main.hbs @@ -16,7 +16,7 @@ {{! repeating tasks block }} {{>list_task - pk="a76e9fac-f8ca-45ca-ae57-063459443ff0" + pk="d5870f6d-8431-47ac-84e4-ef9de83ee622" summary="Shield at the holodeck was the energy of assimilation, lowered to a chemical c-beam." description="The creature is more transformator now than starship. solid and always quirky. energy at the wormhole was the life of ellipse, grabed to a mysterious proton. @@ -29,7 +29,7 @@ can_edit=false }} {{>list_task - pk="a76e9fac-f8ca-45ca-ae57-063459443ff0" + pk="1f380d72-ecf0-454a-99c8-7fde60c4d22f" summary="Sensor at the universe was the pattern of love, empowered to a futile alien." description="The nanomachine is more admiral now than processor. senior and patiently dead. pattern at the center was the death of attitude, loved to a biological ship. @@ -42,7 +42,7 @@ can_edit=true }} {{>list_task - pk="a76e9fac-f8ca-45ca-ae57-063459443ff0" + pk="d04c3467-65a4-436e-82dd-5b81c954eb0f" summary="Flight at the ready room was the vision of alignment, empowered to a quirky vogon." description="The particle is more creature now than transformator. virtual and rudely lunar. starlight travel at the ready room was the powerdrain of faith, evacuated to a most unusual moon. diff --git a/src/views/partials/list_task.hbs b/src/views/partials/list_task.hbs index db28f79..ca36177 100644 --- a/src/views/partials/list_task.hbs +++ b/src/views/partials/list_task.hbs @@ -14,13 +14,16 @@
{{#if completed}} {{! TODO: patch-status ? }} + hx-patch="/api/v1/tasks/{{pk}}" hx-vals="js:{completed:false}" hx-swap="none" + data-task-target="{{pk}}" data-task-action="patch"> {{else}} {{! TODO: patch-status? }} + hx-patch="/api/v1/tasks/{{pk}}" hx-vals="js:{completed:true}" hx-swap="none" + data-task-target="{{pk}}" data-task-action="patch"> {{/if}} + hx-delete="/api/v1/tasks/{{pk}}" hx-target="closest tr" hx-swap="outerHTML" + data-task-target="{{pk}}" data-task-action="delete">