diff --git a/src/renderer/src/AppContext.jsx b/src/renderer/src/AppContext.jsx index eea5356..8ac2d5b 100644 --- a/src/renderer/src/AppContext.jsx +++ b/src/renderer/src/AppContext.jsx @@ -40,19 +40,14 @@ const appStateReducer = (state, action) => { saveState(newState); return newState; } - case "UPDATE_ITEM": { - const newItems = state.items.map((i) => { - if (i.key === action.item.key) { - return Object.assign({}, i, { - status: action.item.status, - }); - } - return i; - }); - const newState = { ...state, items: newItems }; - saveState(newState); - return newState; - } + case "UPDATE_ITEM": { + const newItems = state.items.map((i) => + i.key === action.item.key ? { ...i, ...action.item } : i + ); + const newState = { ...state, items: newItems }; + saveState(newState); + return newState; + } case "DELETE_ITEM": { const newState = { ...state, diff --git a/src/renderer/src/components/EditModal.jsx b/src/renderer/src/components/EditModal.jsx new file mode 100644 index 0000000..fb773dc --- /dev/null +++ b/src/renderer/src/components/EditModal.jsx @@ -0,0 +1,31 @@ +import React, { useState } from "react"; +import styles from "./EditModal.module.css"; // Import styles + +const EditModal = ({ isOpen, onClose, onSave, initialText }) => { + const [newText, setNewText] = useState(initialText); + + const handleSave = () => { + if (newText.trim() !== "") { + onSave(newText); + onClose(); + } + }; + + return ( +
+
+

Edit Item

+ setNewText(e.target.value)} + className={styles.input} + /> + + +
+
+ ); +}; + +export default EditModal; diff --git a/src/renderer/src/components/EditModal.module.css b/src/renderer/src/components/EditModal.module.css new file mode 100644 index 0000000..b682f93 --- /dev/null +++ b/src/renderer/src/components/EditModal.module.css @@ -0,0 +1,81 @@ +.modal { + display: flex; + justify-content: center; + align-items: center; + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(0, 0, 0, 0.5); /* semi-transparent overlay */ + z-index: 999; + opacity: 0; + visibility: hidden; + transition: opacity 0.3s ease, visibility 0s 0.3s; +} + +.modal.open { + opacity: 1; + visibility: visible; + transition: opacity 0.3s ease; +} + +.modalContent { + background: white; + padding: 20px; + border-radius: 8px; + width: 400px; + max-width: 100%; + box-sizing: border-box; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); +} + +h2 { + margin-bottom: 20px; + font-size: 1.5rem; + color: #333; /* Darker color for readability */ +} + +.input { + width: 100%; + padding: 20px 70px 20px 20px; + height: 70px; + background: #f0f0f0; /* Lighter background for input */ + border: 1px solid #ccc; /* Border for input field */ + border-radius: 3px; + box-sizing: border-box; + color: #333; /* Dark text color */ + font-size: 1rem; /* Fixed font size */ + outline: none; + margin-bottom: 15px; +} + +button { + position: relative; + width: 100%; + padding: 10px; + background-color: #007bff; /* Blue background for buttons */ + color: white; /* White text on buttons */ + border: none; + border-radius: 4px; + font-size: 1rem; + cursor: pointer; + transition: background-color 0.3s; + margin-bottom: 8px; +} + +button:hover { + background-color: #0056b3; /* Darker blue when hovered */ +} + +button:focus { + outline: none; +} + +button.cancel { + background-color: #ccc; /* Light grey for cancel button */ +} + +button.cancel:hover { + background-color: #bbb; /* Darker grey on hover */ +} diff --git a/src/renderer/src/components/Item.jsx b/src/renderer/src/components/Item.jsx index 9eb6d00..6839157 100644 --- a/src/renderer/src/components/Item.jsx +++ b/src/renderer/src/components/Item.jsx @@ -1,70 +1,91 @@ +import React, { useState } from "react"; import { useAppReducer } from "../AppContext.jsx"; +import EditModal from "./EditModal.jsx"; // Import the modal component import styles from "./Item.module.css"; -// Individual todo item function Item({ item }) { - const dispatch = useAppReducer(); - let text = item.text; - let paused = item.status === "paused"; - let completed = item.status === "completed"; + const dispatch = useAppReducer(); + const [isModalOpen, setIsModalOpen] = useState(false); + let text = item.text; + let paused = item.status === "paused"; + let completed = item.status === "completed"; - function deleteItem() { - dispatch({ type: "DELETE_ITEM", item }); - } + function deleteItem() { + dispatch({ type: "DELETE_ITEM", item }); + } - function pauseItem() { - const pausedItem = { ...item, status: "paused" }; - dispatch({ type: "UPDATE_ITEM", item: pausedItem }); - } + function pauseItem() { + const pausedItem = { ...item, status: "paused" }; + dispatch({ type: "UPDATE_ITEM", item: pausedItem }); + } - function resumeItem() { - const pendingItem = { ...item, status: "pending" }; - dispatch({ type: "UPDATE_ITEM", item: pendingItem }); - } + function resumeItem() { + const pendingItem = { ...item, status: "pending" }; + dispatch({ type: "UPDATE_ITEM", item: pendingItem }); + } - function completeItem() { - const completedItem = { ...item, status: "completed" }; - dispatch({ type: "UPDATE_ITEM", item: completedItem }); - } + function completeItem() { + const completedItem = { ...item, status: "completed" }; + dispatch({ type: "UPDATE_ITEM", item: completedItem }); + } - return ( -
-
{text}
-
- {completed && } - - {!paused && !completed && ( - - )} - {(paused || completed) && ( - - )} - {!completed && ( - - )} -
-
- ); + // Function to handle saving the edited item + function handleEditSave(newText) { + const updatedItem = { ...item, text: newText }; + dispatch({ type: "UPDATE_ITEM", item: updatedItem }); + } + + return ( +
+
{text}
+
+ {completed && } + + {!paused && !completed && ( + + )} + {(paused || completed) && ( + + )} + {!completed && ( + + )} + {!completed && ( + + )} +
+ + {/* Render the modal when it's open */} + setIsModalOpen(false)} // Close the modal + onSave={handleEditSave} // Save the new text + initialText={item.text} + /> +
+ ); } export default Item; diff --git a/src/renderer/src/components/Item.module.css b/src/renderer/src/components/Item.module.css index 7ff8db6..43e6cac 100644 --- a/src/renderer/src/components/Item.module.css +++ b/src/renderer/src/components/Item.module.css @@ -78,6 +78,16 @@ } } + &.edit { + width: 24px; + height: 24px; + background-color: var(--orange); + mask: url("../img/edit.svg") no-repeat center; + mask-size: contain; + -webkit-mask: url("../img/edit.svg") no-repeat center; + -webkit-mask-size: contain; + } + &.complete { width: 30px; background: no-repeat url("../img/check.svg"); diff --git a/src/renderer/src/img/edit.svg b/src/renderer/src/img/edit.svg new file mode 100644 index 0000000..59bbb2e --- /dev/null +++ b/src/renderer/src/img/edit.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/renderer/src/styles/variables.css b/src/renderer/src/styles/variables.css index b1ab8c1..18bbb21 100644 --- a/src/renderer/src/styles/variables.css +++ b/src/renderer/src/styles/variables.css @@ -3,6 +3,7 @@ --green: #62dca5; --yellow: #f7f879; --red: #e1675a; + --orange: #f4a261; --input-color: #2e2d33; --item-color: #4e4d5c;