This project was bootstrapped with Create React App.
QuickList minimalistic single page Todo App, built with React. User are able to create multiple items that they want to remember to do and be able to add, edit, and remove tasks
- Frontend: JavaScript/React/Redux
- HTML5/CSS
- Webpack
- Firebase - Storage
- DOM Manipulation
Please run the following commands:
npm install (`yarn install` for mac users)
To install all dependencies.
In the project directory, you can run:
Please run the following commands in separate tabs:
npm start (`yarn start` for mac users)
Runs the app in the development mode.
Open http://localhost:3000 to view it in the browser.
Enter task title in the Text Input and click "ADD".
Add todo first, and then you can edit details in dropdown.
Click title and edit, easy as 1,2,3.
Easily add a due date and time for your task.
Priority marking for todo.
Easily mark-off the todo's you complete.
Attach any type of file with your todo. File stores on Firebase Storage and can be downloaded again from todo dropdown.
Easily filter your tasks by incomplete/completed.
Designed with Mobile-Users in mind.
View task's on calendar view, can be toggled on/off anytime with a click. Monthly | Weekly | Daily available.
You can rename and change the color of your Sticky.
// save all tasks to local storage
export const saveToLocalStorage = (key, data) => localStorage.setItem(key, JSON.stringify(data));
// fetch all tasks from local storage
export const fetchFromLocalStorage = key => {
let todoItems = [];
const value = localStorage.getItem(key);
// if fetch was able to retrive data
if (value) {
const parsedJSON = JSON.parse(value);
if (Array.isArray(parsedJSON)) { todoItems = parsedJSON }
}
return todoItems;
}
// clear data in local storage
export const clearLocalStorage = key => localStorage.removeItem(key);
const [, forceUpdate] = React.useState(true);
const handleCompletion = (e, todo) => {
e.stopPropagation();
todo.done = !todo.done;
let element = document.getElementById(`todo#${todo.id}`);
if (todo.done) {
element.classList.add("strikethrough")
} else {
element.classList.remove("strikethrough")
}
updateTodoInLocalStorage();
// rerenders which Icon is showing for status.
forceUpdate(n => !n);
};
const handleUpload = (e) => {
const file = e.target.files[0];
const storageRef = storage.ref()
const fileRef = storageRef.child(file.name);
fileRef.put(file).then(() => {
storageRef.child(file.name).getDownloadURL()
.then((url) => {
todo.url = url;
todo.file = file.name;
setAttachment(todo.file)
updateTodoInLocalStorage();
})
})
}
const removeFromList = (todoToDelete) => {
const filteredList = todoList.filter(todo => todo.id !== todoToDelete.id );
if (todoToDelete.file) {
// delete attachment from Storage
const storageRef = storage.ref()
const fileRef = storageRef.child(todoToDelete.file);
fileRef.delete().then(() => {
setTodoList(filteredList);
saveToLocalStorage("todo_list", filteredList);
})
} else {
setTodoList(filteredList);
saveToLocalStorage("todo_list", filteredList);
}
}
const handleDetailSubmit = (e) => {
e.preventDefault();
todo.details = details;
setEditMode(false);
updateTodoInLocalStorage();
}
const detailsForm = () => {
return (
<form onSubmit={handleDetailSubmit}>
<textarea value={details} onChange={handleDetailChange}
placeholder="add a description"/>
<input type="submit" value="Submit" />
</form>
);
}
const handleKeyPress = (e) => {
if (e.key === 'Enter') {
handleSubmit(e);
}
}
<input
name="title"
type="text"
placeholder="i.e. get milk"
id="text-input"
onChange={handleChange}
value={todo}
onKeyPress={handleKeyPress}
/>
To stop the accordian to open up when editing the title of todo.
<input
onClick={e => e.stopPropagation()}
type="text"
value={title}
onChange={handleChange}
/>
To stop the accordian to open up when editing the title of todo.
// componentDidMount
useEffect(() => {
document.getElementById(`app`).style.backgroundColor = bgColor;
document.getElementById("sticky-title").textContent = stickyTitle;
}, []);