aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/App.jsx4
-rw-r--r--src/ToDo-UI/ListToDo.jsx320
-rw-r--r--src/ToDo-UI/NewToDo.jsx175
-rw-r--r--src/ToDo.jsx476
4 files changed, 497 insertions, 478 deletions
diff --git a/src/App.jsx b/src/App.jsx
index 80d3151..138c6b8 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -1,6 +1,6 @@
import React from "react";
-// import { Counter } from "./features/counter/Counter";
-import { NewToDo, ListToDos } from "./ToDo";
+import { NewToDo } from "./ToDo-UI/NewToDo";
+import { ListToDos } from "./ToDo-UI/ListToDo";
function App() {
return (
diff --git a/src/ToDo-UI/ListToDo.jsx b/src/ToDo-UI/ListToDo.jsx
new file mode 100644
index 0000000..eed6e02
--- /dev/null
+++ b/src/ToDo-UI/ListToDo.jsx
@@ -0,0 +1,320 @@
+import React, { useState } from "react";
+import { useSelector, useDispatch } from "react-redux";
+import {
+ change_done,
+ remove_todo,
+ edit_todo,
+ set_sort_todo,
+ sort_todo,
+ select_todos,
+ select_current_sorting,
+} from "../features/todo/reducer";
+
+function sort_table_header(prefix, current_sorting) {
+ if (prefix.toLowerCase().startsWith(current_sorting.substr(0, 3))) {
+ switch (current_sorting.substr(-1)) {
+ case "^":
+ // Write Prefix and an arrow pointing up.
+ return (
+ <>
+ {prefix} <span>&#8593;</span>
+ </>
+ );
+ case "v":
+ // Write Prefix and an arrow pointing down.
+ return (
+ <>
+ {prefix} <span>&#8595;</span>
+ </>
+ );
+ }
+ } else {
+ // Write Prefix and four dots. No sorting.
+ return (
+ <>
+ {prefix} <span>&#8283;</span>
+ </>
+ );
+ }
+}
+
+function list_of_todos(edit_button, delete_button) {
+ const dispatch = useDispatch();
+ const my_todos = useSelector(select_todos);
+ const my_sorting = useSelector(select_current_sorting);
+
+ function handle_sort_todos(where_clicked) {
+ dispatch(
+ set_sort_todo({
+ where_clicked: where_clicked,
+ })
+ );
+ dispatch(sort_todo());
+ }
+
+ // Table contents
+ var table_head = (
+ <thead>
+ <tr>
+ <th scope="col">Done</th>
+ <th scope="col">Name</th>
+ <th scope="col" onClick={() => handle_sort_todos("priority")}>
+ {sort_table_header("Priority", my_sorting)}
+ </th>
+ <th
+ scope="col"
+ onClick={() => {
+ handle_sort_todos("due_date");
+ }}
+ >
+ {sort_table_header("Due Date", my_sorting)}
+ </th>
+ <th scope="col">Actions</th>
+ </tr>
+ </thead>
+ );
+
+ var table_body = (
+ <tbody className="table-group-divider">
+ {my_todos.map((item) => (
+ <tr key={item.id}>
+ <th scope="row">
+ <div className="form-check">
+ <input
+ className="form-check-input"
+ type="checkbox"
+ checked={item.done}
+ id={"list-todo-done-" + item.id}
+ onChange={(e) =>
+ dispatch(
+ change_done({
+ id: item.id,
+ done: e.target.checked,
+ })
+ )
+ }
+ ></input>
+ </div>
+ </th>
+ <td>{item.text}</td>
+ <td>{item.priority}</td>
+ <td>{item.due_date}</td>
+ <td>
+ <div className="btn-group btn-group-sm" role="group">
+ {edit_button(item)}
+ {delete_button(item)}
+ </div>
+ </td>
+ </tr>
+ ))}
+ </tbody>
+ );
+
+ return (
+ <div className="container">
+ <table className="table align-middle">
+ {table_head}
+ {table_body}
+ </table>
+ </div>
+ );
+}
+
+function new_modal(modal_id, modal_header, modal_body, modal_footer) {
+ return (
+ <div className="modal fade" id={modal_id} tabIndex="-1" role="dialog">
+ <div className="modal-dialog modal-dialog-centered" role="document">
+ <div className="modal-content">
+ {modal_header}
+ {modal_body}
+ {modal_footer}
+ </div>
+ </div>
+ </div>
+ );
+}
+
+export function ListToDos() {
+ const dispatch = useDispatch();
+
+ const [edit_id, set_edit_id] = useState(-1);
+ const [edit_text, set_edit_text] = useState("");
+ const [edit_due_date, set_edit_due_date] = useState("");
+ const [edit_done, set_edit_done] = useState(false);
+ const [edit_priority, set_edit_priority] = useState("Low");
+
+ function handle_open_modal(id, text, due_date, done, priority) {
+ set_edit_id(id);
+ set_edit_text(text);
+ set_edit_due_date(due_date);
+ set_edit_done(done);
+ set_edit_priority(priority);
+ }
+ function handle_exit_modal() {
+ // https://stackoverflow.com/questions/27826381/clearing-form-input-fields-in-bootstrap
+ $("form").get(0).reset(); // Reset form
+
+ set_edit_id(-1);
+ set_edit_text("");
+ set_edit_done(false);
+ set_edit_priority("Low");
+ }
+ function handle_edit_todo() {
+ dispatch(
+ edit_todo({
+ id: edit_id,
+ text: edit_text,
+ due_date: edit_due_date,
+ done: edit_done,
+ priority: edit_priority,
+ })
+ );
+ dispatch(sort_todo());
+ handle_exit_modal();
+ }
+
+ // Define Edit and Remove buttons
+ function edit_button(item) {
+ return (
+ <button
+ type="button"
+ className="btn btn-outline-dark"
+ data-bs-toggle="modal"
+ data-bs-target="#EditToDo"
+ onClick={() =>
+ handle_open_modal(
+ item.id,
+ item.text,
+ item.due_date,
+ item.done,
+ item.priority
+ )
+ }
+ >
+ Edit
+ </button>
+ );
+ }
+ function delete_button(item) {
+ return (
+ <button
+ type="button"
+ className="btn btn-outline-dark"
+ onClick={(e) => dispatch(remove_todo(item.id))}
+ >
+ Delete
+ </button>
+ );
+ }
+
+ // Define modal to edit a to do.
+ var modal_header = (
+ <div className="modal-header">
+ <h5 className="modal-title">Edit a to do</h5>
+ <button
+ type="button"
+ className="close"
+ data-bs-dismiss="modal"
+ aria-label="Close edit window"
+ onClick={handle_exit_modal}
+ >
+ <span>&times;</span>
+ </button>
+ </div>
+ );
+ var modal_footer = (
+ <div className="modal-footer">
+ <button
+ type="button"
+ className="btn btn-secondary"
+ data-bs-dismiss="modal"
+ onClick={handle_exit_modal}
+ >
+ Cancel
+ </button>
+ <button
+ type="button"
+ className="btn btn-primary"
+ onClick={handle_edit_todo}
+ data-bs-dismiss="modal"
+ >
+ Edit
+ </button>
+ </div>
+ );
+ var modal_body = (
+ <div className="modal-body">
+ <form>
+ <div className="form-floating mb-3">
+ <input
+ className="form-control"
+ id="edit-todo-id"
+ value={edit_id}
+ disabled
+ />
+ <label htmlFor="edit-todo-id">ID</label>
+ </div>
+ <div className="form-floating mb-3">
+ <input
+ className="form-control"
+ placeholder="Text"
+ value={edit_text}
+ id="edit-todo-text"
+ onChange={(e) => set_edit_text(e.target.value)}
+ />
+ <label htmlFor="edit-todo-text">Text</label>
+ </div>
+ <div className="input-group mb-3">
+ <div className="form-floating">
+ <input
+ className="form-control"
+ type="date"
+ id="edit-todo-due-date"
+ placeholder="Due date"
+ value={edit_due_date}
+ onChange={(e) => {
+ set_edit_due_date(e.target.value);
+ }}
+ />
+ <label htmlFor="edit-todo-due-date">Due Date</label>
+ </div>
+ </div>
+ <div className="form-check mb-3">
+ <input
+ className="form-check-input"
+ type="checkbox"
+ id="edit-todo-done"
+ onClick={(e) => set_edit_done(e.target.checked)}
+ checked={edit_done}
+ />
+ <label
+ className="form-check-label"
+ htmlFor="edit-todo-done"
+ >
+ Completed
+ </label>
+ </div>
+ <div className="form-floating mb-3">
+ <select
+ className="form-select"
+ id="edit-todo-priority"
+ value={edit_priority}
+ onChange={(e) => set_edit_priority(e.target.value)}
+ >
+ <option value="Low">Low</option>
+ <option value="Medium">Medium</option>
+ <option value="High">High</option>
+ </select>
+ <label htmlFor="edit-todo-priority">Priority</label>
+ </div>
+ </form>
+ </div>
+ );
+
+ return (
+ <>
+ {list_of_todos(edit_button, delete_button)}
+ {new_modal("EditToDo", modal_header, modal_body, modal_footer)}
+ </>
+ );
+}
diff --git a/src/ToDo-UI/NewToDo.jsx b/src/ToDo-UI/NewToDo.jsx
new file mode 100644
index 0000000..28d80dc
--- /dev/null
+++ b/src/ToDo-UI/NewToDo.jsx
@@ -0,0 +1,175 @@
+import React, { useState } from "react";
+import { useSelector, useDispatch } from "react-redux";
+import {
+ add_todo,
+ sort_todo,
+ select_last_index,
+} from "../features/todo/reducer";
+
+function new_button(trigger_id) {
+ return (
+ <div className="container mt-3 mb-3">
+ <button
+ type="button"
+ className="btn btn-outline-dark"
+ data-bs-toggle="modal"
+ data-bs-target={trigger_id}
+ >
+ + New To Do
+ </button>
+ </div>
+ );
+}
+
+function new_modal(modal_id, modal_header, modal_body, modal_footer) {
+ return (
+ <div className="modal fade" id={modal_id} tabIndex="-1" role="dialog">
+ <div className="modal-dialog modal-dialog-centered" role="document">
+ <div className="modal-content">
+ {modal_header}
+ {modal_body}
+ {modal_footer}
+ </div>
+ </div>
+ </div>
+ );
+}
+
+export function NewToDo() {
+ const my_last_idx = useSelector(select_last_index);
+
+ const dispatch = useDispatch();
+ const [new_text, set_new_text] = useState("");
+ const [new_due_date, set_new_due_date] = useState("");
+ const [new_done, set_new_done] = useState(false);
+ const [new_priority, set_new_priority] = useState("Low");
+
+ function handle_exit_modal() {
+ // https://stackoverflow.com/questions/27826381/clearing-form-input-fields-in-bootstrap
+ $("form").get(0).reset(); // Reset form
+
+ set_new_text("");
+ set_new_due_date("");
+ set_new_done(false);
+ set_new_priority("Low");
+ }
+ function handle_add_todo() {
+ dispatch(
+ add_todo({
+ text: new_text,
+ due_date: new_due_date,
+ done: new_done,
+ priority: new_priority,
+ creation_date: new Date().toString(),
+ })
+ );
+ dispatch(sort_todo());
+ handle_exit_modal();
+ }
+
+ // Define modal to add a new to do.
+ var modal_header = (
+ <div className="modal-header">
+ <h5 className="modal-title">Add a new to do</h5>
+ <button
+ type="button"
+ className="close"
+ data-bs-dismiss="modal"
+ aria-label="Close new to do window"
+ onClick={handle_exit_modal}
+ >
+ <span>&times;</span>
+ </button>
+ </div>
+ );
+ var modal_footer = (
+ <div className="modal-footer">
+ <button
+ type="button"
+ className="btn btn-secondary"
+ data-bs-dismiss="modal"
+ onClick={handle_exit_modal}
+ >
+ Cancel
+ </button>
+ <button
+ type="button"
+ className="btn btn-primary"
+ onClick={handle_add_todo}
+ data-bs-dismiss="modal"
+ >
+ Add
+ </button>
+ </div>
+ );
+ var modal_body = (
+ <div className="modal-body">
+ <form>
+ <div className="form-floating mb-3">
+ <input
+ className="form-control"
+ id="new-todo-id"
+ value={my_last_idx + 1}
+ disabled
+ />
+ <label htmlFor="new-todo-id">ID</label>
+ </div>
+ <div className="form-floating mb-3">
+ <input
+ className="form-control"
+ placeholder="Text"
+ id="new-todo-text"
+ onChange={(e) => set_new_text(e.target.value)}
+ />
+ <label htmlFor="new-todo-text">Text</label>
+ </div>
+ <div className="input-group mb-3">
+ <div className="form-floating">
+ <input
+ className="form-control"
+ type="date"
+ id="new-todo-due-date"
+ placeholder="Due date"
+ onChange={(e) => {
+ set_new_due_date(e.target.value);
+ }}
+ />
+ <label htmlFor="new-todo-due-date">Due Date</label>
+ </div>
+ </div>
+ <div className="form-check mb-3">
+ <input
+ className="form-check-input"
+ type="checkbox"
+ id="new-todo-done"
+ onClick={(e) => set_new_done(e.target.checked)}
+ />
+ <label className="form-check-label" htmlFor="new-todo-done">
+ Completed
+ </label>
+ </div>
+ <div className="form-floating mb-3">
+ <select
+ className="form-select"
+ id="new-todo-priority"
+ onChange={(e) => set_new_priority(e.target.value)}
+ >
+ <option value="Low" defaultValue>
+ Low
+ </option>
+ <option value="Medium">Medium</option>
+ <option value="High">High</option>
+ </select>
+ <label htmlFor="new-todo-priority">Priority</label>
+ </div>
+ </form>
+ </div>
+ );
+
+ return (
+ <>
+ {new_button("#NewToDo")}
+ {new_modal("NewToDo", modal_header, modal_body, modal_footer)}
+ </>
+ );
+}
diff --git a/src/ToDo.jsx b/src/ToDo.jsx
deleted file mode 100644
index c64e073..0000000
--- a/src/ToDo.jsx
+++ /dev/null
@@ -1,476 +0,0 @@
-import React, { useState } from "react";
-import { useSelector, useDispatch } from "react-redux";
-import {
- add_todo,
- change_done,
- remove_todo,
- edit_todo,
- set_sort_todo,
- sort_todo,
- select_todos,
- select_last_index,
- select_current_sorting,
-} from "./features/todo/reducer";
-
-export function NewToDo() {
- const my_todos = useSelector(select_todos);
- const my_last_idx = useSelector(select_last_index);
-
- const dispatch = useDispatch();
- const [new_text, set_new_text] = useState("");
- const [new_due_date, set_new_due_date] = useState("");
- const [new_done, set_new_done] = useState(false);
- const [new_priority, set_new_priority] = useState("Low");
-
- function handle_exit_modal() {
- // https://stackoverflow.com/questions/27826381/clearing-form-input-fields-in-bootstrap
- $("form").get(0).reset(); // Reset form
-
- set_new_text("");
- set_new_due_date("");
- set_new_done(false);
- set_new_priority("Low");
- }
-
- return (
- <>
- <div className="container mt-3 mb-3">
- <button
- type="button"
- className="btn btn-outline-dark"
- data-bs-toggle="modal"
- data-bs-target="#NewToDo"
- >
- + New To Do
- </button>
- </div>
-
- <div
- className="modal fade"
- id="NewToDo"
- tabIndex="-1"
- role="dialog"
- >
- <div
- className="modal-dialog modal-dialog-centered"
- role="document"
- >
- <div className="modal-content">
- <div className="modal-header">
- <h5 className="modal-title" id="new-modal-title">
- Add a new to do
- </h5>
- <button
- type="button"
- className="close"
- data-bs-dismiss="modal"
- aria-label="Close new to do window"
- onClick={handle_exit_modal}
- >
- <span>&times;</span>
- </button>
- </div>
- <div className="modal-body">
- <form>
- <div className="form-floating mb-3">
- <input
- className="form-control"
- id="new-todo-id"
- value={my_last_idx + 1}
- disabled
- />
- <label htmlFor="new-todo-id">ID</label>
- </div>
- <div className="form-floating mb-3">
- <input
- className="form-control"
- placeholder="Text"
- id="new-todo-text"
- onChange={(e) =>
- set_new_text(e.target.value)
- }
- />
- <label htmlFor="new-todo-text">Text</label>
- </div>
- <div className="input-group mb-3">
- <div className="form-floating">
- <input
- className="form-control"
- type="date"
- id="new-todo-due-date"
- placeholder="Due date"
- onChange={(e) => {
- set_new_due_date(
- e.target.value
- );
- }}
- />
- <label htmlFor="new-todo-due-date">
- Due Date
- </label>
- </div>
- </div>
- <div className="form-check mb-3">
- <input
- className="form-check-input"
- type="checkbox"
- id="new-todo-done"
- onClick={(e) =>
- set_new_done(e.target.checked)
- }
- />
- <label
- className="form-check-label"
- htmlFor="new-todo-done"
- >
- Completed
- </label>
- </div>
- <div className="form-floating mb-3">
- <select
- className="form-select"
- id="new-todo-priority"
- onChange={(e) =>
- set_new_priority(e.target.value)
- }
- >
- <option value="Low" defaultValue>
- Low
- </option>
- <option value="Medium">Medium</option>
- <option value="High">High</option>
- </select>
- <label htmlFor="new-todo-priority">
- Priority
- </label>
- </div>
- </form>
- </div>
- <div className="modal-footer">
- <button
- type="button"
- className="btn btn-secondary"
- data-bs-dismiss="modal"
- onClick={handle_exit_modal}
- >
- Cancel
- </button>
- <button
- type="button"
- className="btn btn-primary"
- onClick={() => {
- dispatch(
- add_todo({
- text: new_text,
- due_date: new_due_date,
- done: new_done,
- priority: new_priority,
- creation_date:
- new Date().toString(),
- })
- ),
- dispatch(sort_todo());
- handle_exit_modal();
- }}
- data-bs-dismiss="modal"
- >
- Add
- </button>
- </div>
- </div>
- </div>
- </div>
- </>
- );
-}
-
-function sort_table_header(prefix, current_sorting) {
- if (prefix.toLowerCase().startsWith(current_sorting.substr(0, 3))) {
- switch (current_sorting.substr(-1)) {
- case "^":
- return (
- <>
- {prefix} <span>&#8593;</span>
- </>
- );
- case "v":
- return (
- <>
- {prefix} <span>&#8595;</span>
- </>
- );
- }
- } else {
- return (
- <>
- {prefix} <span>&#8283;</span>
- </>
- );
- }
-}
-
-export function ListToDos() {
- const my_todos = useSelector(select_todos);
- const my_sorting = useSelector(select_current_sorting);
- const dispatch = useDispatch();
-
- const [edit_id, set_edit_id] = useState(-1);
- const [edit_text, set_edit_text] = useState("");
- const [edit_due_date, set_edit_due_date] = useState("");
- const [edit_done, set_edit_done] = useState(false);
- const [edit_priority, set_edit_priority] = useState("Low");
-
- function handle_open_modal(id, text, due_date, done, priority) {
- set_edit_id(id);
- set_edit_text(text);
- set_edit_due_date(due_date);
- set_edit_done(done);
- set_edit_priority(priority);
- }
- function handle_exit_modal() {
- // https://stackoverflow.com/questions/27826381/clearing-form-input-fields-in-bootstrap
- $("form").get(0).reset(); // Reset form
-
- set_edit_id(-1);
- set_edit_text("");
- set_edit_done(false);
- set_edit_priority("Low");
- }
-
- return (
- <>
- <div className="container">
- <table className="table align-middle">
- <thead>
- <tr>
- <th scope="col">Done</th>
- <th scope="col">Name</th>
- <th
- scope="col"
- onClick={(e) => {
- dispatch(
- set_sort_todo({
- where_clicked: "priority",
- })
- ),
- dispatch(sort_todo());
- }}
- >
- {sort_table_header("Priority", my_sorting)}
- </th>
- <th
- scope="col"
- onClick={(e) => {
- dispatch(
- set_sort_todo({
- where_clicked: "due_date",
- })
- ),
- dispatch(sort_todo());
- }}
- >
- {sort_table_header("Due Date", my_sorting)}
- </th>
- <th scope="col">Actions</th>
- </tr>
- </thead>
- <tbody className="table-group-divider">
- {my_todos.map((item) => (
- <tr key={item.id}>
- <th scope="row">
- <div className="form-check">
- <input
- className="form-check-input"
- type="checkbox"
- checked={item.done}
- id={"list-todo-done-" + item.id}
- onChange={(e) =>
- dispatch(
- change_done({
- id: item.id,
- done: e.target.checked,
- })
- )
- }
- ></input>
- </div>
- </th>
- <td>{item.text}</td>
- <td>{item.priority}</td>
- <td>{item.due_date}</td>
- <td>
- <div
- className="btn-group btn-group-sm"
- role="group"
- >
- <button
- type="button"
- className="btn btn-outline-dark"
- data-bs-toggle="modal"
- data-bs-target="#EditToDo"
- onClick={() =>
- handle_open_modal(
- item.id,
- item.text,
- item.due_date,
- item.done,
- item.priority
- )
- }
- >
- Edit
- </button>
- <button
- type="button"
- className="btn btn-outline-dark"
- onClick={(e) =>
- dispatch(remove_todo(item.id))
- }
- >
- Delete
- </button>
- </div>
- </td>
- </tr>
- ))}
- </tbody>
- </table>
- </div>
-
- <div
- className="modal fade"
- id="EditToDo"
- tabIndex="-1"
- role="dialog"
- >
- <div
- className="modal-dialog modal-dialog-centered"
- role="document"
- >
- <div className="modal-content">
- <div className="modal-header">
- <h5 className="modal-title">Edit a to do</h5>
- <button
- type="button"
- className="close"
- data-bs-dismiss="modal"
- aria-label="Close edit window"
- onClick={handle_exit_modal}
- >
- <span>&times;</span>
- </button>
- </div>
- <div className="modal-body">
- <form>
- <div className="form-floating mb-3">
- <input
- className="form-control"
- id="edit-todo-id"
- value={edit_id}
- disabled
- />
- <label htmlFor="edit-todo-id">ID</label>
- </div>
- <div className="form-floating mb-3">
- <input
- className="form-control"
- placeholder="Text"
- value={edit_text}
- id="edit-todo-text"
- onChange={(e) =>
- set_edit_text(e.target.value)
- }
- />
- <label htmlFor="edit-todo-text">Text</label>
- </div>
- <div className="input-group mb-3">
- <div className="form-floating">
- <input
- className="form-control"
- type="date"
- id="edit-todo-due-date"
- placeholder="Due date"
- value={edit_due_date}
- onChange={(e) => {
- set_edit_due_date(
- e.target.value
- );
- }}
- />
- <label htmlFor="edit-todo-due-date">
- Due Date
- </label>
- </div>
- </div>
- <div className="form-check mb-3">
- <input
- className="form-check-input"
- type="checkbox"
- id="edit-todo-done"
- onClick={(e) =>
- set_edit_done(e.target.checked)
- }
- checked={edit_done}
- />
- <label
- className="form-check-label"
- htmlFor="edit-todo-done"
- >
- Completed
- </label>
- </div>
- <div className="form-floating mb-3">
- <select
- className="form-select"
- id="edit-todo-priority"
- value={edit_priority}
- onChange={(e) =>
- set_edit_priority(e.target.value)
- }
- >
- <option value="Low">Low</option>
- <option value="Medium">Medium</option>
- <option value="High">High</option>
- </select>
- <label htmlFor="edit-todo-priority">
- Priority
- </label>
- </div>
- </form>
- </div>
- <div className="modal-footer">
- <button
- type="button"
- className="btn btn-secondary"
- data-bs-dismiss="modal"
- onClick={handle_exit_modal}
- >
- Cancel
- </button>
- <button
- type="button"
- className="btn btn-primary"
- onClick={() => {
- dispatch(
- edit_todo({
- id: edit_id,
- text: edit_text,
- due_date: edit_due_date,
- done: edit_done,
- priority: edit_priority,
- })
- ),
- dispatch(sort_todo()),
- handle_exit_modal();
- }}
- data-bs-dismiss="modal"
- >
- Edit
- </button>
- </div>
- </div>
- </div>
- </div>
- </>
- );
-}