aboutsummaryrefslogtreecommitdiff
path: root/src/routes/todos
diff options
context:
space:
mode:
Diffstat (limited to 'src/routes/todos')
-rw-r--r--src/routes/todos/_api.ts22
-rw-r--r--src/routes/todos/index.svelte186
-rw-r--r--src/routes/todos/index.ts52
3 files changed, 0 insertions, 260 deletions
diff --git a/src/routes/todos/_api.ts b/src/routes/todos/_api.ts
deleted file mode 100644
index f8bcf73..0000000
--- a/src/routes/todos/_api.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- This module is used by the /todos and /todos/[uid]
- endpoints to make calls to api.svelte.dev, which stores todos
- for each user. The leading underscore indicates that this is
- a private module, _not_ an endpoint — visiting /todos/_api
- will net you a 404 response.
-
- (The data on the todo app will expire periodically; no
- guarantees are made. Don't use it to organise your life.)
-*/
-
-const base = 'https://api.svelte.dev';
-
-export async function api(request: Request, resource: string, data?: Record<string, unknown>) {
- return fetch(`${base}/${resource}`, {
- method: request.method,
- headers: {
- 'content-type': 'application/json'
- },
- body: data && JSON.stringify(data)
- });
-}
diff --git a/src/routes/todos/index.svelte b/src/routes/todos/index.svelte
deleted file mode 100644
index e23c1a1..0000000
--- a/src/routes/todos/index.svelte
+++ /dev/null
@@ -1,186 +0,0 @@
-<script lang="ts">
- import { enhance } from '$lib/form'
- import { scale } from 'svelte/transition'
- import { flip } from 'svelte/animate'
-
- type Todo = {
- uid: string
- created_at: Date
- text: string
- done: boolean
- pending_delete: boolean
- }
-
- export let todos: Todo[]
-</script>
-
-<svelte:head>
- <title>Todos</title>
-</svelte:head>
-
-<div class="todos">
- <h1>Todos</h1>
-
- <form
- class="new"
- action="/todos"
- method="post"
- use:enhance={{
- result: async ({ form }) => {
- form.reset()
- },
- }}
- >
- <input name="text" aria-label="Add todo" placeholder="+ tap to add a todo" />
- </form>
-
- {#each todos as todo (todo.uid)}
- <div
- class="todo"
- class:done={todo.done}
- transition:scale|local={{ start: 0.7 }}
- animate:flip={{ duration: 200 }}
- >
- <form
- action="/todos?_method=PATCH"
- method="post"
- use:enhance={{
- pending: ({ data }) => {
- todo.done = !!data.get('done')
- },
- }}
- >
- <input type="hidden" name="uid" value={todo.uid} />
- <input type="hidden" name="done" value={todo.done ? '' : 'true'} />
- <button class="toggle" aria-label="Mark todo as {todo.done ? 'not done' : 'done'}" />
- </form>
-
- <form class="text" action="/todos?_method=PATCH" method="post" use:enhance>
- <input type="hidden" name="uid" value={todo.uid} />
- <input aria-label="Edit todo" type="text" name="text" value={todo.text} />
- <button class="save" aria-label="Save todo" />
- </form>
-
- <form
- action="/todos?_method=DELETE"
- method="post"
- use:enhance={{
- pending: () => (todo.pending_delete = true),
- }}
- >
- <input type="hidden" name="uid" value={todo.uid} />
- <button class="delete" aria-label="Delete todo" disabled={todo.pending_delete} />
- </form>
- </div>
- {/each}
-</div>
-
-<style>
- .todos {
- width: 100%;
- max-width: var(--column-width);
- margin: var(--column-margin-top) auto 0 auto;
- line-height: 1;
- }
-
- .new {
- margin: 0 0 0.5rem 0;
- }
-
- input {
- border: 1px solid transparent;
- }
-
- input:focus-visible {
- box-shadow: inset 1px 1px 6px rgba(0, 0, 0, 0.1);
- border: 1px solid #ff3e00 !important;
- outline: none;
- }
-
- .new input {
- font-size: 28px;
- width: 100%;
- padding: 0.5em 1em 0.3em 1em;
- box-sizing: border-box;
- background: rgba(255, 255, 255, 0.05);
- border-radius: 8px;
- text-align: center;
- }
-
- .todo {
- display: grid;
- grid-template-columns: 2rem 1fr 2rem;
- grid-gap: 0.5rem;
- align-items: center;
- margin: 0 0 0.5rem 0;
- padding: 0.5rem;
- background-color: white;
- border-radius: 8px;
- filter: drop-shadow(2px 4px 6px rgba(0, 0, 0, 0.1));
- transform: translate(-1px, -1px);
- transition: filter 0.2s, transform 0.2s;
- }
-
- .done {
- transform: none;
- opacity: 0.4;
- filter: drop-shadow(0px 0px 1px rgba(0, 0, 0, 0.1));
- }
-
- form.text {
- position: relative;
- display: flex;
- align-items: center;
- flex: 1;
- }
-
- .todo input {
- flex: 1;
- padding: 0.5em 2em 0.5em 0.8em;
- border-radius: 3px;
- }
-
- .todo button {
- width: 2em;
- height: 2em;
- border: none;
- background-color: transparent;
- background-position: 50% 50%;
- background-repeat: no-repeat;
- }
-
- button.toggle {
- border: 1px solid rgba(0, 0, 0, 0.2);
- border-radius: 50%;
- box-sizing: border-box;
- background-size: 1em auto;
- }
-
- .done .toggle {
- 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");
- }
-
- .delete {
- background-image: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M4.5 5V22H19.5V5H4.5Z' fill='%23676778' stroke='%23676778' stroke-width='1.5' stroke-linejoin='round'/%3E%3Cpath d='M10 10V16.5' stroke='white' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3Cpath d='M14 10V16.5' stroke='white' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3Cpath d='M2 5H22' stroke='%23676778' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3Cpath d='M8 5L9.6445 2H14.3885L16 5H8Z' fill='%23676778' stroke='%23676778' stroke-width='1.5' stroke-linejoin='round'/%3E%3C/svg%3E%0A");
- opacity: 0.2;
- }
-
- .delete:hover,
- .delete:focus {
- transition: opacity 0.2s;
- opacity: 1;
- }
-
- .save {
- position: absolute;
- right: 0;
- opacity: 0;
- background-image: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M20.5 2H3.5C2.67158 2 2 2.67157 2 3.5V20.5C2 21.3284 2.67158 22 3.5 22H20.5C21.3284 22 22 21.3284 22 20.5V3.5C22 2.67157 21.3284 2 20.5 2Z' fill='%23676778' stroke='%23676778' stroke-width='1.5' stroke-linejoin='round'/%3E%3Cpath d='M17 2V11H7.5V2H17Z' fill='white' stroke='white' stroke-width='1.5' stroke-linejoin='round'/%3E%3Cpath d='M13.5 5.5V7.5' stroke='%23676778' stroke-width='1.5' stroke-linecap='round'/%3E%3Cpath d='M5.99844 2H18.4992' stroke='%23676778' stroke-width='1.5' stroke-linecap='round'/%3E%3C/svg%3E%0A");
- }
-
- .todo input:focus + .save,
- .save:focus {
- transition: opacity 0.2s;
- opacity: 1;
- }
-</style>
diff --git a/src/routes/todos/index.ts b/src/routes/todos/index.ts
deleted file mode 100644
index 129b60a..0000000
--- a/src/routes/todos/index.ts
+++ /dev/null
@@ -1,52 +0,0 @@
-import { api } from './_api';
-import type { RequestHandler } from '@sveltejs/kit';
-
-export const get: RequestHandler = async ({ request, locals }) => {
- // locals.userid comes from src/hooks.js
- const response = await api(request, `todos/${locals.userid}`);
-
- if (response.status === 404) {
- // user hasn't created a todo list.
- // start with an empty array
- return {
- body: {
- todos: []
- }
- };
- }
-
- if (response.ok) {
- return {
- body: {
- todos: await response.json()
- }
- };
- }
-
- return {
- status: response.status
- };
-};
-
-export const post: RequestHandler = async ({ request, locals }) => {
- const form = await request.formData();
-
- return api(request, `todos/${locals.userid}`, {
- text: form.get('text')
- });
-};
-
-export const patch: RequestHandler = async ({ request, locals }) => {
- const form = await request.formData();
-
- return api(request, `todos/${locals.userid}/${form.get('uid')}`, {
- text: form.has('text') ? form.get('text') : undefined,
- done: form.has('done') ? !!form.get('done') : undefined
- });
-};
-
-export const del: RequestHandler = async ({ request, locals }) => {
- const form = await request.formData();
-
- return api(request, `todos/${locals.userid}/${form.get('uid')}`);
-};