Skip to content

Commit b0f6d52

Browse files
authored
Merge pull request #10 from gitpod-io/mikenikles/develop-crud-endpoints-9
Develop CRUD endpoints
2 parents e2409c5 + e75d9a3 commit b0f6d52

File tree

7 files changed

+136
-14
lines changed

7 files changed

+136
-14
lines changed

src/global.d.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,8 @@
11
/// <reference types="@sveltejs/kit" />
2+
3+
type Todo = {
4+
uid: string;
5+
created_at: Date;
6+
text: string;
7+
done: boolean;
8+
}

src/hooks.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import type { Handle } from "@sveltejs/kit";
2+
3+
export const handle: Handle = async ({ request, resolve }) => {
4+
if (request.query.has("_method")) {
5+
request.method = request.query.get("_method").toUpperCase();
6+
}
7+
8+
const response = await resolve(request);
9+
return response;
10+
};

src/lib/todo-item.svelte

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
<script lang="ts">
2+
export let todo: Todo;
3+
</script>
4+
15
<style>
26
.todo {
37
display: grid;
@@ -66,7 +70,6 @@
6670
opacity: 1;
6771
}
6872
69-
/* TODO: Uncomment when the API endpoints are available
7073
.done {
7174
transform: none;
7275
opacity: 0.4;
@@ -75,21 +78,21 @@
7578
7679
.done .toggle {
7780
background-image: url("data:image/svg+xml,%3Csvg width='22' height='16' viewBox='0 0 22 16' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M20.5 1.5L7.4375 14.5L1.5 8.5909' stroke='%23676778' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
78-
} */
81+
}
7982
</style>
8083

81-
<div class="todo">
82-
<form action="" method="">
83-
<input type="hidden" name="done" value="" />
84-
<button aria-label="Mark done/not done" class="toggle"></button>
84+
<div class="todo" class:done={todo.done}>
85+
<form action="/todos/{todo.uid}.json?_method=patch" method="post">
86+
<input type="hidden" name="done" value="{todo.done ? '' : 'true'}" />
87+
<button aria-label="Mark todo as {todo.done ? 'not done' : 'done'}" class="toggle"></button>
8588
</form>
8689

87-
<form action="" method="" class="text">
88-
<input type="text" />
90+
<form action="/todos/{todo.uid}.json?_method=patch" method="post" class="text">
91+
<input type="text" name="text" value="{todo.text}" />
8992
<button aria-label="Save todo" class="save"></button>
9093
</form>
9194

92-
<form action="" method="">
95+
<form action="/todos/{todo.uid}.json?_method=delete" method="post">
9396
<button aria-label="Delete todo" class="delete"></button>
9497
</form>
9598
</div>

src/routes/index.svelte

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,28 @@
1-
<script>
1+
<script context="module" lang="ts">
2+
import type { Load } from "@sveltejs/kit";
3+
4+
export const load: Load = async ({ fetch }) => {
5+
const res = await fetch("/todos.json");
6+
7+
if (res.ok) {
8+
const todos = await res.json();
9+
return {
10+
props: { todos }
11+
}
12+
}
13+
14+
const { message } = await res.json();
15+
return {
16+
error: new Error(message)
17+
}
18+
};
19+
</script>
20+
21+
<script lang="ts">
222
import TodoItem from "$lib/todo-item.svelte";
323
24+
export let todos: Todo[];
25+
426
const title = "Todo";
527
</script>
628

@@ -43,11 +65,11 @@
4365
<div class="todos">
4466
<h1>{title}</h1>
4567

46-
<form action="" method="" class="new">
68+
<form action="/todos.json" method="post" class="new">
4769
<input type="text" name="text" aria-label="Add a todo" placeholder="+ type to add a todo" />
4870
</form>
4971

50-
<TodoItem />
51-
<TodoItem />
52-
<TodoItem />
72+
{#each todos as todo}
73+
<TodoItem {todo} />
74+
{/each}
5375
</div>

src/routes/todos/[uid].json.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import type { RequestHandler } from "@sveltejs/kit";
2+
import { api } from "./_api";
3+
4+
export const del: RequestHandler = (request) => {
5+
return api(request);
6+
}
7+
8+
export const patch: RequestHandler<{}, FormData> = (request) => {
9+
return api(request, {
10+
text: request.body.get("text"),
11+
done: request.body.has("done") ? !!request.body.get("done") : undefined
12+
});
13+
}

src/routes/todos/_api.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import type { Request } from "@sveltejs/kit";
2+
3+
// TODO: Persist in database
4+
let todos: Todo[] = [];
5+
6+
export const api = (request: Request, data?: Record<string, unknown>) => {
7+
let body = {};
8+
let status = 500;
9+
10+
switch (request.method.toUpperCase()) {
11+
case "GET":
12+
body = todos;
13+
status = 200;
14+
break;
15+
case "POST":
16+
todos.push(data as Todo);
17+
body = data;
18+
status = 201;
19+
break;
20+
case "DELETE":
21+
todos = todos.filter(todo => todo.uid !== request.params.uid)
22+
status = 200;
23+
break;
24+
case "PATCH":
25+
todos = todos.map(todo => {
26+
if (todo.uid === request.params.uid) {
27+
if (data.text) todo.text = data.text as string;
28+
else todo.done = data.done as boolean;
29+
}
30+
return todo;
31+
});
32+
status = 200;
33+
break;
34+
35+
default:
36+
break;
37+
}
38+
39+
if (request.method.toUpperCase() !== "GET") {
40+
return {
41+
status: 303,
42+
headers: {
43+
location: "/"
44+
}
45+
};
46+
}
47+
48+
return {
49+
status,
50+
body
51+
}
52+
}

src/routes/todos/index.json.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import type { RequestHandler } from "@sveltejs/kit";
2+
import { api } from "./_api";
3+
4+
export const get: RequestHandler = (request) => {
5+
return api(request);
6+
}
7+
8+
export const post: RequestHandler<{}, FormData> = (request) => {
9+
return api(request, {
10+
uid: `${Date.now()}`, // TODO: Replace with the UID from the datbase
11+
created_at: new Date(),
12+
text: request.body.get("text"),
13+
done: false
14+
});
15+
}

0 commit comments

Comments
 (0)