Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 8 additions & 13 deletions src/renderer/src/AppContext.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
31 changes: 31 additions & 0 deletions src/renderer/src/components/EditModal.jsx
Original file line number Diff line number Diff line change
@@ -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 (
<div className={`${styles.modal} ${isOpen ? styles.open : ""}`}>
<div className={styles.modalContent}>
<h2>Edit Item</h2>
<input
type="text"
value={newText}
onChange={(e) => setNewText(e.target.value)}
className={styles.input}
/>
<button onClick={handleSave}>Save & Close</button>
<button onClick={onClose}>Cancel</button>
</div>
</div>
);
};

export default EditModal;
81 changes: 81 additions & 0 deletions src/renderer/src/components/EditModal.module.css
Original file line number Diff line number Diff line change
@@ -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 */
}
137 changes: 79 additions & 58 deletions src/renderer/src/components/Item.jsx
Original file line number Diff line number Diff line change
@@ -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 (
<div className={styles.item} tabIndex="0">
<div className={styles.itemname}>{text}</div>
<div
className={`${styles.buttons} ${
completed ? styles.completedButtons : ""
}`}
>
{completed && <button className={styles.empty} tabIndex="0"></button>}
<button
className={styles.delete}
onClick={deleteItem}
tabIndex="0"
></button>
{!paused && !completed && (
<button
className={styles.pause}
onClick={pauseItem}
tabIndex="0"
></button>
)}
{(paused || completed) && (
<button
className={styles.resume}
onClick={resumeItem}
tabIndex="0"
></button>
)}
{!completed && (
<button
className={styles.complete}
onClick={completeItem}
tabIndex="0"
></button>
)}
</div>
</div>
);
// Function to handle saving the edited item
function handleEditSave(newText) {
const updatedItem = { ...item, text: newText };
dispatch({ type: "UPDATE_ITEM", item: updatedItem });
}

return (
<div className={styles.item} tabIndex="0">
<div className={styles.itemname}>{text}</div>
<div
className={`${styles.buttons} ${
completed ? styles.completedButtons : ""
}`}
>
{completed && <button className={styles.empty} tabIndex="0"></button>}
<button className={styles.delete} onClick={deleteItem} tabIndex="0"></button>
{!paused && !completed && (
<button
className={styles.pause}
onClick={pauseItem}
tabIndex="0"
></button>
)}
{(paused || completed) && (
<button
className={styles.resume}
onClick={resumeItem}
tabIndex="0"
></button>
)}
{!completed && (
<button
className={styles.edit}
onClick={() => setIsModalOpen(true)} // Open the modal when editing
tabIndex="0"
>

</button>
)}
{!completed && (
<button
className={styles.complete}
onClick={completeItem}
tabIndex="0"
></button>
)}
</div>

{/* Render the modal when it's open */}
<EditModal
isOpen={isModalOpen}
onClose={() => setIsModalOpen(false)} // Close the modal
onSave={handleEditSave} // Save the new text
initialText={item.text}
/>
</div>
);
}

export default Item;
10 changes: 10 additions & 0 deletions src/renderer/src/components/Item.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
3 changes: 3 additions & 0 deletions src/renderer/src/img/edit.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/renderer/src/styles/variables.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
--green: #62dca5;
--yellow: #f7f879;
--red: #e1675a;
--orange: #f4a261;

--input-color: #2e2d33;
--item-color: #4e4d5c;
Expand Down