mirror of
https://github.com/peter-tanner/todo-list.git
synced 2024-11-30 10:50:18 +08:00
Integrated very basic firebase database into app
This commit is contained in:
parent
be62724b91
commit
26e1b1dc2f
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -21,3 +21,6 @@
|
||||||
npm-debug.log*
|
npm-debug.log*
|
||||||
yarn-debug.log*
|
yarn-debug.log*
|
||||||
yarn-error.log*
|
yarn-error.log*
|
||||||
|
|
||||||
|
# Secret
|
||||||
|
firebaseconfig.js
|
15876
package-lock.json
generated
Normal file
15876
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
|
@ -6,6 +6,7 @@
|
||||||
"@testing-library/jest-dom": "^5.11.4",
|
"@testing-library/jest-dom": "^5.11.4",
|
||||||
"@testing-library/react": "^11.1.0",
|
"@testing-library/react": "^11.1.0",
|
||||||
"@testing-library/user-event": "^12.1.10",
|
"@testing-library/user-event": "^12.1.10",
|
||||||
|
"firebase": "^9.5.0",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
"react-scripts": "4.0.3",
|
"react-scripts": "4.0.3",
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
const RESET_ACTION = {
|
|
||||||
type: "RESET",
|
|
||||||
};
|
|
||||||
|
|
||||||
export default RESET_ACTION;
|
|
3
src/action.js
Normal file
3
src/action.js
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
export const RESET_ACTION = {
|
||||||
|
type: "RESET",
|
||||||
|
};
|
|
@ -1,5 +1,6 @@
|
||||||
import React, { useReducer, useState } from "react";
|
import React, { useReducer, useState } from "react";
|
||||||
import RESET_ACTION from "./RESET_ACTION";
|
import { RESET_ACTION } from "./action";
|
||||||
|
import { dbWriteTask, newTaskId } from "./firebase";
|
||||||
|
|
||||||
export function AddTask(props) {
|
export function AddTask(props) {
|
||||||
const [showForm, setShowForm] = useState(false);
|
const [showForm, setShowForm] = useState(false);
|
||||||
|
@ -23,12 +24,20 @@ export function AddTask(props) {
|
||||||
function AddTaskForm(props) {
|
function AddTaskForm(props) {
|
||||||
const { addTask, show, toggleForm } = props;
|
const { addTask, show, toggleForm } = props;
|
||||||
|
|
||||||
const INITIAL_STATE = { name: "", description: "", date: "" };
|
const INITIAL_STATE = {
|
||||||
|
done: false,
|
||||||
|
name: "",
|
||||||
|
description: "",
|
||||||
|
date: "",
|
||||||
|
taskId: -1,
|
||||||
|
};
|
||||||
const reducer = (state, event) => {
|
const reducer = (state, event) => {
|
||||||
if (event.type === RESET_ACTION.type) {
|
switch (event.type) {
|
||||||
return INITIAL_STATE;
|
case RESET_ACTION.type:
|
||||||
} else {
|
return INITIAL_STATE;
|
||||||
return { ...state, [event.target.name]: event.target.value };
|
default:
|
||||||
|
// Form
|
||||||
|
return { ...state, [event.target.name]: event.target.value };
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const [task, setTask] = useReducer(reducer, INITIAL_STATE);
|
const [task, setTask] = useReducer(reducer, INITIAL_STATE);
|
||||||
|
@ -38,8 +47,9 @@ function AddTaskForm(props) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleSubmit = (event) => {
|
const handleSubmit = (event) => {
|
||||||
console.log(task);
|
task.taskId = newTaskId();
|
||||||
addTask(task);
|
addTask(task);
|
||||||
|
dbWriteTask(task);
|
||||||
setTask(RESET_ACTION);
|
setTask(RESET_ACTION);
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
};
|
};
|
||||||
|
|
36
src/firebase.js
Normal file
36
src/firebase.js
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
// Import the functions you need from the SDKs you need
|
||||||
|
import { initializeApp } from "firebase/app";
|
||||||
|
import { firebaseConfig } from "./firebaseconfig";
|
||||||
|
import { getDatabase, ref, onValue, set, get, remove } from "firebase/database";
|
||||||
|
|
||||||
|
// TODO: Add SDKs for Firebase products that you want to use
|
||||||
|
// https://firebase.google.com/docs/web/setup#available-libraries
|
||||||
|
|
||||||
|
// Initialize Firebase
|
||||||
|
const app = initializeApp(firebaseConfig);
|
||||||
|
// Get a reference to the database service
|
||||||
|
const database = getDatabase(app);
|
||||||
|
|
||||||
|
const taskIdRef = ref(database, "taskId");
|
||||||
|
var currentTaskId;
|
||||||
|
onValue(taskIdRef, (snapshot) => {
|
||||||
|
currentTaskId = snapshot.val();
|
||||||
|
});
|
||||||
|
|
||||||
|
export function newTaskId() {
|
||||||
|
const value = currentTaskId;
|
||||||
|
set(taskIdRef, value + 1);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function dbWriteTask(task) {
|
||||||
|
set(ref(database, "tasks/" + task.taskId), task);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function dbDeleteTask(task) {
|
||||||
|
remove(ref(database, "tasks/" + task.taskId));
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function dbGetTasks() {
|
||||||
|
return get(ref(database, "tasks"));
|
||||||
|
}
|
66
src/index.js
66
src/index.js
|
@ -1,31 +1,63 @@
|
||||||
import React, { useState } from "react";
|
import React, { useCallback, useEffect, useState } from "react";
|
||||||
import ReactDom from "react-dom";
|
import ReactDom from "react-dom";
|
||||||
import AddTask from "./addtask";
|
import AddTask from "./addtask";
|
||||||
|
import { dbDeleteTask, dbGetTasks } from "./firebase";
|
||||||
import { Task, TaskList } from "./tasklist";
|
import { Task, TaskList } from "./tasklist";
|
||||||
|
|
||||||
// Example task
|
// Example task
|
||||||
// { name: "example task", description: "Amogus sus" };
|
// { name: "example task", description: "Amogus sus" };
|
||||||
|
|
||||||
function Root() {
|
function Root() {
|
||||||
const [taskNumber, setTaskNumber] = useState(0);
|
|
||||||
const [tasks, setTasks] = useState([]);
|
const [tasks, setTasks] = useState([]);
|
||||||
|
|
||||||
const addNewTask = (props) => {
|
const addTask = useCallback(
|
||||||
setTasks((tasks) => [
|
(props) => {
|
||||||
...tasks,
|
setTasks((tasks) => [
|
||||||
<Task
|
...tasks,
|
||||||
{...props}
|
<Task
|
||||||
key={taskNumber}
|
task={props}
|
||||||
taskId={taskNumber}
|
key={props.taskId}
|
||||||
deleteTask={deleteTask}
|
deleteTask={deleteTask}
|
||||||
/>,
|
/>,
|
||||||
]);
|
]);
|
||||||
setTaskNumber((taskNumber) => taskNumber + 1);
|
},
|
||||||
|
[setTasks]
|
||||||
|
);
|
||||||
|
|
||||||
|
const deleteTask = (task) => {
|
||||||
|
dbDeleteTask(task);
|
||||||
|
setTasks((tasks) =>
|
||||||
|
tasks.filter(
|
||||||
|
(otherTask) => otherTask.props.task.taskId !== task.taskId
|
||||||
|
)
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const deleteTask = (id) => {
|
// Run on startup - load tasks from firebase db.
|
||||||
setTasks((tasks) => tasks.filter((task) => task.props.taskId !== id));
|
useEffect(() => {
|
||||||
};
|
async function initializeTasks() {
|
||||||
|
let snapshot;
|
||||||
|
try {
|
||||||
|
snapshot = await dbGetTasks();
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
let tasks = {};
|
||||||
|
if (snapshot.exists()) {
|
||||||
|
tasks = snapshot.val();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tasks) {
|
||||||
|
// eslint-disable-next-line
|
||||||
|
for (const [_, value] of Object.entries(tasks)) {
|
||||||
|
addTask(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
initializeTasks();
|
||||||
|
}, [addTask]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="container mt-3">
|
<div className="container mt-3">
|
||||||
|
@ -33,7 +65,7 @@ function Root() {
|
||||||
<h1>Task list</h1>
|
<h1>Task list</h1>
|
||||||
</div>
|
</div>
|
||||||
<section>
|
<section>
|
||||||
<AddTask addTask={addNewTask} />
|
<AddTask addTask={addTask} />
|
||||||
<h1>Tasks</h1>
|
<h1>Tasks</h1>
|
||||||
<TaskList tasks={tasks} />
|
<TaskList tasks={tasks} />
|
||||||
</section>
|
</section>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { useState } from "react";
|
import { useReducer } from "react";
|
||||||
|
import { dbWriteTask } from "./firebase";
|
||||||
|
|
||||||
export function TaskList(props) {
|
export function TaskList(props) {
|
||||||
const { tasks } = props;
|
const { tasks } = props;
|
||||||
|
@ -23,8 +24,16 @@ export function TaskList(props) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Task(props) {
|
export function Task(props) {
|
||||||
const { taskId, name, description, date, deleteTask } = props;
|
const { task: task_, deleteTask } = props;
|
||||||
const [done, setDone] = useState(false);
|
|
||||||
|
const reducer = (state, event) => ({ ...state, [event.name]: event.value });
|
||||||
|
const [task, setTask] = useReducer(reducer, task_);
|
||||||
|
|
||||||
|
const setDone = (done) => {
|
||||||
|
setTask({ name: "done", value: done });
|
||||||
|
task.done = done; // Need to update variable as well
|
||||||
|
dbWriteTask(task);
|
||||||
|
};
|
||||||
|
|
||||||
const deleteBtn = (done) => {
|
const deleteBtn = (done) => {
|
||||||
if (done) {
|
if (done) {
|
||||||
|
@ -34,7 +43,7 @@ export function Task(props) {
|
||||||
type="button"
|
type="button"
|
||||||
className="btn btn-danger"
|
className="btn btn-danger"
|
||||||
value="Delete"
|
value="Delete"
|
||||||
onClick={() => deleteTask(taskId)}
|
onClick={() => deleteTask(task)}
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
);
|
);
|
||||||
|
@ -47,22 +56,22 @@ export function Task(props) {
|
||||||
<td>
|
<td>
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
value={done}
|
checked={task.done}
|
||||||
onClick={() => setDone(!done)}
|
onChange={() => setDone(!task.done)}
|
||||||
></input>
|
></input>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<p>{name}</p>
|
<p>{task.name}</p>
|
||||||
</td>
|
</td>
|
||||||
<td style={{ whiteSpace: "pre" }}>
|
<td style={{ whiteSpace: "pre" }}>
|
||||||
<p>{description}</p>
|
<p>{task.description}</p>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{date === ""
|
{task.date === ""
|
||||||
? ""
|
? ""
|
||||||
: new Date(Date.parse(date)).toLocaleDateString()}
|
: new Date(Date.parse(task.date)).toLocaleDateString()}
|
||||||
</td>
|
</td>
|
||||||
{deleteBtn(done)}
|
{deleteBtn(task.done)}
|
||||||
</tr>
|
</tr>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user