start of implementation of tasklist with an overlay

This commit is contained in:
Patrick 2025-10-30 16:08:36 +01:00
parent caee9f6fe9
commit d9502cb13d
6 changed files with 220 additions and 13 deletions

View File

@ -71,7 +71,7 @@
@keyframes pop {
50% {
transform: scale(1.2);
transform: translateY(-50%) translateX(-50%) scale(1.2);
}
}

View File

@ -0,0 +1,146 @@
<script module lang="ts">
import type { Task } from "@prisma/client";
export interface Props {
task: Task | null
form: string
open?: boolean
}
</script>
<script lang="ts">
let { task, form, open = $bindable() }: Props = $props();
let submitButton: HTMLButtonElement;
let topicTextArea: HTMLTextAreaElement;
let descriptionTextArea: HTMLTextAreaElement;
function cancelOverlay() {
// add change alert
open = false;
}
</script>
<svelte:window onkeydown={(event) => {
if (event instanceof KeyboardEvent) {
if (event.key === "Escape") {
cancelOverlay()
}
}
}} />
<div class="overlay" class:open={open}>
<div class="background" role="presentation" aria-hidden="true" onclick={() => { cancelOverlay() }}></div>
<div class="content">
<textarea class="topic" form={form} bind:this={topicTextArea} name="topic" placeholder="What would you like to do" rows="1">{task?.topic ?? ""}</textarea>
<textarea class="description" form={form} bind:this={descriptionTextArea} name="description" placeholder="Add a description here.">{task?.description ?? ""}</textarea>
<button
type="submit"
form={form}
bind:this={submitButton}
onclick={(event) => {
if (topicTextArea.value.length != 0) {
(event.target as HTMLButtonElement).form?.requestSubmit()
}
event.preventDefault()
}}
>Save and close</button>
</div>
</div>
<style>
.overlay {
display: none;
position: fixed;
top: 0;
left: 0;
z-index: 10;
width: 100%;
height: 100%;
overflow: auto;
}
.open {
display: block;
}
:global(body:has(.overlay.open)) {
overflow: hidden;
}
.background {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: black;
opacity: 50%;
}
.content {
position: absolute;
top: 50%;
left: 50%;
transform: translateX(-50%) translateY(-50%);
width: 75%;
min-height: 20%;
background: darkgreen;
padding: 10px;
display: flex;
flex-direction: column;
gap: 10px;
}
textarea {
box-sizing: border-box;
min-width: 100%;
background: none;
border: none;
field-sizing: content;
&:focus {
outline: none;
}
&.topic {
font-size: 24px;
&:focus {
border-bottom: 1px solid black;
}
}
&.description {
min-height: 10em;
&:focus {
border-left: 1px solid black;
}
}
}
</style>

View File

@ -22,7 +22,7 @@
</script>
<div class="container">
<div class="container" class:loaded={loaded}>
<div class="main-task">
<div class="checkbox">
<Checkbox bind:checked={checked}/>
@ -48,7 +48,6 @@
width: var(--width, 100%);
min-height: var(--min-height, 50px);
margin: 2px;
padding: 10px;
border: 1px solid gray;
@ -110,7 +109,7 @@
.loaded {
transition: none;
}
.loaded.checked {
.loaded .checked {
transition: all 0.3s ease;
}

View File

@ -1,5 +1,7 @@
import type { Actions, PageServerLoad } from "./$types"
import { fail } from "@sveltejs/kit"
export const load: PageServerLoad = async ({ locals, fetch }) => {
const response = await fetch("/api/users/tasks", {
@ -10,7 +12,7 @@ export const load: PageServerLoad = async ({ locals, fetch }) => {
}
export const actions = {
create: async ({ request, fetch }) => {
edit: async ({ request, fetch }) => {
const data = await request.formData()
@ -19,6 +21,8 @@ export const actions = {
body: data
})
console.log(data)
return { }
}
} satisfies Actions

View File

@ -1,18 +1,57 @@
<script lang="ts">
import { enhance } from '$app/forms'
import { pushState, replaceState } from '$app/navigation'
import { page } from "$app/state"
import Task from '$lib/components/task.svelte'
import TaskOverlay from '$lib/components/task-overlay.svelte'
const { data } = $props()
$inspect(data)
let open = $state(false);
let lastOpen = false
let selectedTask = $state(null)
$effect(() => {
open
selectedTask
if (open != lastOpen) {
lastOpen = open
if (open) {
//pushState(`/tasks/${data.tasks[0].id}`, {})
} else {
if (page.route.id !== "/") {
history.back()
}
}
}
})
</script>
<form id="form_edit_task" method="POST"
action="?/edit"
use:enhance={({ }) => {
return async ({ result }) => {
if (result.type === 'success') {
open = false
} else /*if (result.type === 'error' || result.type === 'failure')*/ {
console.log(result)
}
}
}}
></form>
<div class="container">
<h1>Tasks</h1>
<div class="task">
<form method="POST" action="?/create" use:enhance>
<input name="content" />
</form>
<div class="create_task">
<input form="form_edit_task" name="content" placeholder="Create task here" onclick={() => { open = true }}/>
</div>
{#each data.tasks as task}
@ -20,6 +59,10 @@
{/each}
</div>
{#if open}
<TaskOverlay task={selectedTask} bind:open={open} form="form_edit_task" />
{/if}
<style>
.container {
@ -30,13 +73,28 @@
flex-direction: column;
justify-content: center;
align-items: center;
gap: 5px;
}
.task {
.create_task {
width: 75%;
margin: 5px;
padding: 5px;
border: 1px solid black;
display: grid;
grid-template-columns: 25px auto 11ch;
grid-template-areas:
'. headerArea .';
column-gap: 10px;
align-content: stretch;
}
.create_task input {
grid-area: headerArea;
width: 100%;
}
</style>

View File

@ -1,6 +1,6 @@
body {
--primary-bg-color: white;
--primary-bg-color: darkgreen;
--primary-text-color: black;
width: 100%;