Skip to content

Commit

Permalink
update frontend
Browse files Browse the repository at this point in the history
  • Loading branch information
sansx committed Apr 12, 2024
1 parent 4a1f239 commit ec0bbd9
Show file tree
Hide file tree
Showing 2 changed files with 244 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import React from 'react'
import reactLogo from '../images/logo.svg'
import rustLogo from '../images/logo2.svg'
import plus from '../images/plus.svg'

export const Home = () => {
return (
<div>
<div style={{ display: 'flex', justifyContent: 'center' }}>
<img src={rustLogo} className="App-logo" alt="rust-logo" />
<img src={plus} alt="plus" />
<img src={reactLogo} className="App-logo" alt="react-logo" />
</div>
<p>
Edit <code>frontend/src/App.tsx</code> and save to reload.
</p>

<div style={{ display: 'flex', justifyContent: 'center' }}>
<a
className="App-link"
href="https://create-rust-app.dev"
target="_blank"
rel="noopener noreferrer"
>
Docs
</a>
&nbsp;
<a
className="App-link"
href="https://github.com/Wulf/create-rust-app"
target="_blank"
rel="noopener noreferrer"
>
Repo
</a>
</div>
</div>
)
}
205 changes: 205 additions & 0 deletions create-rust-app_cli/template-plugin-redis/frontend/containers/Todo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
import React, { useEffect, useState } from "react";

const TodoAPI = {
get: async (page: number, size: number) =>
await (await fetch(`/api/todos?page=${page}&page_size=${size}`)).json(),

getRedis: async (page: number = 1, size: number = 10) =>
await (
await fetch(`/api/redis_todos?page=${page}&page_size=${size}`)
).json(),
create: async (todo: string) =>
await (
await fetch("/api/todos", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ text: todo }),
})
).json(),
createRedis: async (todo: string) =>
await (
await fetch("/api/redis_todos", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
text: todo,
created_at: new Date().toISOString(),
updated_at: new Date().toISOString(),
}),
})
).json(),
delete: async (id: number) =>
await fetch(`/api/todos/${id}`, { method: "DELETE" }),
update: async (id: number, todo: string) =>
await fetch(`/api/todos/${id}`, {
method: "PUT",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ text: todo }),
}),
};

export const Todos = () => {
const [text, setText] = useState<string>("");
const [selectedTodo, editTodo] = useState<Todo | null>(null);
const [todos, setTodos] = useState<PaginationResult<Todo>>();
const [createdTodo, setCreatedTodo] = useState<Todo>();
const pageSize = 5;
const [page, setPage] = useState<number>(0);
const [numPages, setPages] = useState<number>(1);
const [processing, setProcessing] = useState<boolean>(false);

const createTodo = async (todo: string) => {
setProcessing(true);
let createdTodo = await TodoAPI.createRedis(todo);
let todos = await TodoAPI.get(page, pageSize);
await TodoAPI.getRedis(page, pageSize);
setTodos(todos);
setCreatedTodo(createdTodo);
setText("");
setProcessing(false);
};

const updateTodo = async (todo: Todo) => {
setProcessing(true);
await TodoAPI.update(todo.id, text);
setTodos(await TodoAPI.get(page, pageSize));
setText("");
editTodo(null);
setProcessing(false);
};

const deleteTodo = async (todo: Todo) => {
setProcessing(true);
await TodoAPI.delete(todo.id);
setTodos(await TodoAPI.get(page, pageSize));
setProcessing(false);
};

useEffect(() => {
TodoAPI.getRedis();
}, []);

useEffect(() => {
setText(selectedTodo?.text || "");
}, [selectedTodo]);

// fetch on page change
useEffect(() => {
setProcessing(true);
TodoAPI.get(page, pageSize).then((todos) => {
setTodos(todos);
setProcessing(false);
});
}, [page]);

// update total number of pages
useEffect(() => {
if (todos) setPages(todos?.num_pages);
}, [todos]);

useEffect(() => {
editTodo(null);
if (page < 0) setPage(0);
if (numPages != 0 && page >= numPages) setPage(numPages - 1);
}, [page, numPages]);

useEffect(() => {
// go to the latest page when a new todo is created
setPage(numPages - 1);
setCreatedTodo(undefined);
}, [createdTodo]);

return (
<div style={{ display: "flex", flexFlow: "column", textAlign: "left" }}>
<h1>Todos</h1>
{(!todos || todos.total_items === 0) && "No todos, create one!"}
{todos?.items.map((todo) =>
todo.id === selectedTodo?.id ? (
<div key="form" className="Form">
<div style={{ display: "flex" }}>
<input
style={{ flex: 1 }}
value={text}
onChange={(e) => setText(e.target.value)}
/>
<button
disabled={processing}
style={{ height: "40px" }}
onClick={() => updateTodo(todo)}
>
Save
</button>
<button
disabled={processing}
style={{ height: "40px" }}
onClick={() => editTodo(null)}
>
Cancel
</button>
</div>
</div>
) : (
<div className="Form">
<div style={{ flex: 1 }}>
#{todo.id} {todo.text}
</div>
<div>
<a href="#" className="App-link" onClick={() => editTodo(todo)}>
edit
</a>
&nbsp;
<a href="#" className="App-link" onClick={() => deleteTodo(todo)}>
delete
</a>
</div>
</div>
)
)}
{selectedTodo === null && (
<div className="Form">
<div style={{ display: "flex" }}>
<input
style={{ flex: 1 }}
placeholder="New todo..."
value={text}
onChange={(e) => setText(e.target.value)}
onKeyDown={(e) => {
if (e.key === "Enter") {
createTodo(text);
}
}}
/>
<button
disabled={processing}
style={{ height: "40px" }}
onClick={() => createTodo(text)}
>
Add
</button>
</div>
</div>
)}
<div className="Form">
<div style={{ display: "flex" }}>
<button
disabled={processing || page === 0}
onClick={() => setPage(page - 1)}
>{`<<`}</button>
<span style={{ flex: 1, textAlign: "center" }}>
Page {page + 1} of {numPages}
</span>
<button
disabled={processing || page === numPages - 1}
onClick={() => setPage(page + 1)}
>{`>>`}</button>
</div>
</div>
</div>
);
};

0 comments on commit ec0bbd9

Please sign in to comment.