ListToDo.jsx (10737B) - raw


      1 import React, { useState } from "react";
      2 import { useSelector, useDispatch } from "react-redux";
      3 import {
      4     change_done,
      5     remove_todo,
      6     edit_todo,
      7     set_sort_todo,
      8     sort_todo,
      9     refresh_filtered_todos,
     10     select_todos,
     11     select_current_sorting,
     12 } from "../features/todo/reducer";
     13 
     14 function sort_table_header(prefix, current_sorting) {
     15     if (prefix.toLowerCase().startsWith(current_sorting.substr(0, 3))) {
     16         switch (current_sorting.substr(-1)) {
     17             case "^":
     18                 // Write Prefix and an arrow pointing up.
     19                 return (
     20                     <>
     21                         {prefix} <span>&#8593;</span>
     22                     </>
     23                 );
     24             case "v":
     25                 // Write Prefix and an arrow pointing down.
     26                 return (
     27                     <>
     28                         {prefix} <span>&#8595;</span>
     29                     </>
     30                 );
     31         }
     32     } else {
     33         // Write Prefix and four dots. No sorting.
     34         return (
     35             <>
     36                 {prefix} <span>&#8283;</span>
     37             </>
     38         );
     39     }
     40 }
     41 
     42 function list_of_todos(edit_button, delete_button) {
     43     const dispatch = useDispatch();
     44     const my_todos = useSelector(select_todos);
     45     const my_sorting = useSelector(select_current_sorting);
     46 
     47     function handle_sort_todos(where_clicked) {
     48         dispatch(
     49             set_sort_todo({
     50                 where_clicked: where_clicked,
     51             })
     52         );
     53         dispatch(sort_todo());
     54         dispatch(refresh_filtered_todos());
     55     }
     56 
     57     // Table contents
     58     var table_head = (
     59         <thead>
     60             <tr>
     61                 <th scope="col">Done</th>
     62                 <th scope="col">Name</th>
     63                 <th scope="col" onClick={() => handle_sort_todos("priority")}>
     64                     {sort_table_header("Priority", my_sorting)}
     65                 </th>
     66                 <th
     67                     scope="col"
     68                     onClick={() => {
     69                         handle_sort_todos("due_date");
     70                     }}
     71                 >
     72                     {sort_table_header("Due Date", my_sorting)}
     73                 </th>
     74                 <th scope="col">Actions</th>
     75             </tr>
     76         </thead>
     77     );
     78 
     79     var table_body = (
     80         <tbody className="table-group-divider">
     81             {my_todos.map((item) => (
     82                 <tr key={item.id}>
     83                     <th scope="row">
     84                         <div className="form-check">
     85                             <input
     86                                 className="form-check-input"
     87                                 type="checkbox"
     88                                 checked={item.done}
     89                                 id={"list-todo-done-" + item.id}
     90                                 onChange={(e) => {
     91                                     dispatch(
     92                                         change_done({
     93                                             id: item.id,
     94                                             done: e.target.checked,
     95                                         })
     96                                     ),
     97                                         dispatch(refresh_filtered_todos());
     98                                 }}
     99                             ></input>
    100                         </div>
    101                     </th>
    102                     <td>{item.text}</td>
    103                     <td>{item.priority}</td>
    104                     <td>{item.due_date}</td>
    105                     <td>
    106                         <div className="btn-group btn-group-sm" role="group">
    107                             {edit_button(item)}
    108                             {delete_button(item)}
    109                         </div>
    110                     </td>
    111                 </tr>
    112             ))}
    113         </tbody>
    114     );
    115 
    116     return (
    117         <div className="container">
    118             <table className="table align-middle">
    119                 {table_head}
    120                 {table_body}
    121             </table>
    122         </div>
    123     );
    124 }
    125 
    126 function new_modal(modal_id, modal_header, modal_body, modal_footer) {
    127     return (
    128         <div className="modal fade" id={modal_id} tabIndex="-1" role="dialog">
    129             <div className="modal-dialog modal-dialog-centered" role="document">
    130                 <div className="modal-content">
    131                     {modal_header}
    132                     {modal_body}
    133                     {modal_footer}
    134                 </div>
    135             </div>
    136         </div>
    137     );
    138 }
    139 
    140 export function ListToDos() {
    141     const dispatch = useDispatch();
    142 
    143     const [edit_id, set_edit_id] = useState(-1);
    144     const [edit_text, set_edit_text] = useState("");
    145     const [edit_due_date, set_edit_due_date] = useState("");
    146     const [edit_done, set_edit_done] = useState(false);
    147     const [edit_priority, set_edit_priority] = useState("Low");
    148 
    149     function handle_open_modal(id, text, due_date, done, priority) {
    150         set_edit_id(id);
    151         set_edit_text(text);
    152         set_edit_due_date(due_date);
    153         set_edit_done(done);
    154         set_edit_priority(priority);
    155     }
    156     function handle_exit_modal() {
    157         // https://stackoverflow.com/questions/27826381/clearing-form-input-fields-in-bootstrap
    158         $("form").get(0).reset(); // Reset form
    159 
    160         set_edit_id(-1);
    161         set_edit_text("");
    162         set_edit_done(false);
    163         set_edit_priority("Low");
    164     }
    165     function handle_edit_todo() {
    166         dispatch(
    167             edit_todo({
    168                 id: edit_id,
    169                 text: edit_text,
    170                 due_date: edit_due_date,
    171                 done: edit_done,
    172                 priority: edit_priority,
    173             })
    174         );
    175         dispatch(sort_todo());
    176         dispatch(refresh_filtered_todos());
    177         handle_exit_modal();
    178     }
    179 
    180     // Define Edit and Remove buttons
    181     function edit_button(item) {
    182         return (
    183             <button
    184                 type="button"
    185                 className="btn btn-outline-dark"
    186                 data-bs-toggle="modal"
    187                 data-bs-target="#EditToDo"
    188                 onClick={() =>
    189                     handle_open_modal(
    190                         item.id,
    191                         item.text,
    192                         item.due_date,
    193                         item.done,
    194                         item.priority
    195                     )
    196                 }
    197             >
    198                 Edit
    199             </button>
    200         );
    201     }
    202     function delete_button(item) {
    203         return (
    204             <button
    205                 type="button"
    206                 className="btn btn-outline-dark"
    207                 onClick={(e) => {
    208                     dispatch(remove_todo(item.id)),
    209                         dispatch(refresh_filtered_todos());
    210                 }}
    211             >
    212                 Delete
    213             </button>
    214         );
    215     }
    216 
    217     // Define modal to edit a to do.
    218     var modal_header = (
    219         <div className="modal-header">
    220             <h5 className="modal-title">Edit a to do</h5>
    221             <button
    222                 type="button"
    223                 className="close"
    224                 data-bs-dismiss="modal"
    225                 aria-label="Close edit window"
    226                 onClick={handle_exit_modal}
    227             >
    228                 <span>&times;</span>
    229             </button>
    230         </div>
    231     );
    232     var modal_footer = (
    233         <div className="modal-footer">
    234             <button
    235                 type="button"
    236                 className="btn btn-secondary"
    237                 data-bs-dismiss="modal"
    238                 onClick={handle_exit_modal}
    239             >
    240                 Cancel
    241             </button>
    242             <button
    243                 type="button"
    244                 className="btn btn-primary"
    245                 onClick={handle_edit_todo}
    246                 data-bs-dismiss="modal"
    247             >
    248                 Edit
    249             </button>
    250         </div>
    251     );
    252     var modal_body = (
    253         <div className="modal-body">
    254             <form>
    255                 <div className="form-floating mb-3">
    256                     <input
    257                         className="form-control"
    258                         id="edit-todo-id"
    259                         value={edit_id}
    260                         disabled
    261                     />
    262                     <label htmlFor="edit-todo-id">ID</label>
    263                 </div>
    264                 <div className="form-floating mb-3">
    265                     <input
    266                         className="form-control"
    267                         placeholder="Text"
    268                         value={edit_text}
    269                         id="edit-todo-text"
    270                         onChange={(e) => set_edit_text(e.target.value)}
    271                     />
    272                     <label htmlFor="edit-todo-text">Text</label>
    273                 </div>
    274                 <div className="input-group mb-3">
    275                     <div className="form-floating">
    276                         <input
    277                             className="form-control"
    278                             type="date"
    279                             id="edit-todo-due-date"
    280                             placeholder="Due date"
    281                             value={edit_due_date}
    282                             onChange={(e) => {
    283                                 set_edit_due_date(e.target.value);
    284                             }}
    285                         />
    286                         <label htmlFor="edit-todo-due-date">Due Date</label>
    287                     </div>
    288                 </div>
    289                 <div className="form-check mb-3">
    290                     <input
    291                         className="form-check-input"
    292                         type="checkbox"
    293                         id="edit-todo-done"
    294                         onClick={(e) => set_edit_done(e.target.checked)}
    295                         checked={edit_done}
    296                     />
    297                     <label
    298                         className="form-check-label"
    299                         htmlFor="edit-todo-done"
    300                     >
    301                         Completed
    302                     </label>
    303                 </div>
    304                 <div className="form-floating mb-3">
    305                     <select
    306                         className="form-select"
    307                         id="edit-todo-priority"
    308                         value={edit_priority}
    309                         onChange={(e) => set_edit_priority(e.target.value)}
    310                     >
    311                         <option value="Low">Low</option>
    312                         <option value="Medium">Medium</option>
    313                         <option value="High">High</option>
    314                     </select>
    315                     <label htmlFor="edit-todo-priority">Priority</label>
    316                 </div>
    317             </form>
    318         </div>
    319     );
    320 
    321     return (
    322         <>
    323             {list_of_todos(edit_button, delete_button)}
    324             {new_modal("EditToDo", modal_header, modal_body, modal_footer)}
    325         </>
    326     );
    327 }