aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrián Oliva <adrian.oliva@cimat.mx>2023-05-19 15:19:11 -0600
committerAdrián Oliva <adrian.oliva@cimat.mx>2023-05-19 15:19:11 -0600
commitff4cc46041251972634a28c1f780541fd105aadc (patch)
tree10ac8ed59e3729781604257830a3ce71c7f90dcc
parent8e274132e60b21277506df3c7b47e5f75518fb32 (diff)
downloadToDo-App-FE-ff4cc46041251972634a28c1f780541fd105aadc.tar.gz
ToDo-App-FE-ff4cc46041251972634a28c1f780541fd105aadc.zip
Edit button almost done.
Noticed some bugs. Will patch on later commits.
-rw-r--r--index.html14
-rw-r--r--src/ToDo.jsx286
-rw-r--r--src/features/todo/reducer.js15
3 files changed, 259 insertions, 56 deletions
diff --git a/index.html b/index.html
index 13bc1aa..f69b7bc 100644
--- a/index.html
+++ b/index.html
@@ -30,6 +30,20 @@
})
})
</script>
+ <script>
+ $(document).ready(function(){
+ var date_input=$('input[name="edit-todo-due-date"]');
+ var container=$('.bootstrap-iso form').length>0 ? $('.bootstrap-iso form').parent() : "body";
+ date_input.datepicker({
+ format: 'mm/dd/yyyy',
+ container: container,
+ todayHighlight: true,
+ autoclose: true,
+ maxViewMode: 3,
+ todayBtn: "linked"
+ })
+ })
+ </script>
</head>
<body>
<div id="root"></div>
diff --git a/src/ToDo.jsx b/src/ToDo.jsx
index 3644db3..f502689 100644
--- a/src/ToDo.jsx
+++ b/src/ToDo.jsx
@@ -4,6 +4,7 @@ import {
add_todo,
change_done,
remove_todo,
+ edit_todo,
select_todos,
select_last_index,
} from "./features/todo/reducer";
@@ -190,70 +191,245 @@ export function ListToDos() {
const my_todos = useSelector(select_todos);
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">#</th>
- <th scope="col">Name</th>
- <th scope="col">Priority</th>
- <th scope="col">Due Date</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">
+ <>
+ <div className="container">
+ <table className="table align-middle">
+ <thead>
+ <tr>
+ <th scope="col">#</th>
+ <th scope="col">Name</th>
+ <th scope="col">Priority</th>
+ <th scope="col">Due Date</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="flexCheckChecked"
+ 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"
+ aria-label="Basic example"
+ >
+ <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"
+ aria-labelledby="New To Do Window"
+ aria-hidden="true"
+ >
+ <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"
+ onClick={handle_exit_modal}
+ >
+ <span aria-hidden="true">&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="floatingInput">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="floatingInput">Text</label>
+ </div>
+ <div className="input-group mb-3">
+ <span className="input-group-text">
+ <i className="fa-regular fa-calendar"></i>
+ </span>
+ <div className="form-floating">
+ <input
+ className="form-control"
+ id="edit-todo-due-date"
+ name="edit-todo-due-date"
+ placeholder="Due date"
+ value={edit_due_date}
+ />
+ <label htmlFor="floatingInput">
+ Due Date
+ </label>
+ </div>
+ </div>
+ <div className="form-check mb-3">
<input
className="form-check-input"
type="checkbox"
- checked={item.done}
- id="flexCheckChecked"
+ value=""
+ id="flexCheckDefault"
onChange={(e) =>
- dispatch(
- change_done({
- id: item.id,
- done: e.target.checked,
- })
- )
+ set_edit_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"
- aria-label="Basic example"
- >
- <button
- type="button"
- className="btn btn-outline-dark"
- disabled
+ checked={edit_done}
+ />
+ <label
+ className="form-check-label"
+ htmlFor="flexCheckDefault"
>
- Edit
- </button>
- <button
- type="button"
- className="btn btn-outline-dark"
- onClick={(e) =>
- dispatch(remove_todo(item.id))
+ Done
+ </label>
+ </div>
+ <div className="form-floating mb-3">
+ <select
+ className="form-select"
+ id="floatingSelect"
+ aria-label="Floating label select example"
+ value={edit_priority}
+ onChange={(e) =>
+ set_edit_priority(e.target.value)
}
>
- Delete
- </button>
+ <option value="Low">Low</option>
+ <option value="Medium">Medium</option>
+ <option value="High">High</option>
+ </select>
+ <label htmlFor="floatingSelect">
+ Priority
+ </label>
</div>
- </td>
- </tr>
- ))}
- </tbody>
- </table>
- </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,
+ // Cannot update date on change. :'(
+ due_date:
+ document.getElementById(
+ "edit-todo-due-date"
+ ).value,
+ done: edit_done,
+ priority: edit_priority,
+ })
+ ),
+ handle_exit_modal();
+ }}
+ data-bs-dismiss="modal"
+ >
+ Add
+ </button>
+ </div>
+ </div>
+ </div>
+ </div>
+ </>
);
}
diff --git a/src/features/todo/reducer.js b/src/features/todo/reducer.js
index f12f740..a13810b 100644
--- a/src/features/todo/reducer.js
+++ b/src/features/todo/reducer.js
@@ -36,10 +36,23 @@ export const todo_slice = createSlice({
(todo) => todo.id != action.payload
);
},
+
+ edit_todo: (state, action) => {
+ let selected_todo = state.todos.findIndex(
+ (x) => x.id == action.payload.id
+ );
+ if (selected_todo == -1) return;
+
+ state.todos[selected_todo].text = action.payload.text;
+ state.todos[selected_todo].due_date = action.payload.due_date;
+ state.todos[selected_todo].done = action.payload.done;
+ state.todos[selected_todo].priority = action.payload.priority;
+ },
},
});
-export const { add_todo, change_done, remove_todo } = todo_slice.actions;
+export const { add_todo, change_done, remove_todo, edit_todo } =
+ todo_slice.actions;
export const select_todos = (state) => state.todo_list.todos;
export const select_last_index = (state) => state.todo_list.last_id;