Skip to content

Commit

Permalink
allow updating task details
Browse files Browse the repository at this point in the history
  • Loading branch information
reykjalin committed Oct 24, 2024
1 parent bbfda4e commit 5855730
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 23 deletions.
68 changes: 47 additions & 21 deletions resources/js/src/entrypoints/Tasks.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { flip } from 'svelte/animate';
import { fade } from 'svelte/transition';
import { getTasks, getTags, createTask, moveTask, deleteTask } from '../lib/api/tasks';
import { getTasks, getTags, createTask, moveTask, updateTask, deleteTask } from '../lib/api/tasks';
import Task from '../lib/components/task.svelte';
import Pill from '../lib/components/pill.svelte';
Expand All @@ -24,6 +24,9 @@
let tags: Tag[] = [];
let selectedTask: TaskType | undefined = undefined;
let selectedTaskDescription: string = '';
let selectedTaskDetails: string = '';
let fetchTasks = async () => {
if (await $user) {
$tasks = await getTasks();
Expand Down Expand Up @@ -94,27 +97,31 @@
};
}
function handleKeyPress(ev: KeyboardEvent) {
// Make sure event propagates if the modal is already open
if (dialog.open) {
return;
}
const { key } = ev;
async function createEmptyTask() {
try {
selectedTask = await createTask('', []);
if (key === 'n') {
console.log('create new task');
ev.preventDefault();
dialog.showModal();
selectedTaskDescription = '';
selectedTaskDetails = '';
$tasks = await getTasks(selectedTag);
} catch (_) {
$tasks = $tasks.filter(t => t.id !== -1);
}
}
async function createEmptyTask() {
async function updateSelectedTask() {
if (!selectedTask) {
return;
}
try {
await createTask('', []);
await updateTask(selectedTask, { description: selectedTaskDescription, details: selectedTaskDetails });
} catch (e) {
console.error(e);
} finally {
$tasks = await getTasks(selectedTag);
} catch (_) {
$tasks = $tasks.filter(t => t.id !== -1);
}
}
Expand Down Expand Up @@ -199,9 +206,28 @@
$tasks.splice(indexOfTask, 0, task);
}
}
</script>
<svelte:window on:keydown={handleKeyPress} />
function debounce(func: Function, wait: number, immediate?: boolean) {
var timeout: number | undefined;
return function(this: any) {
var context = this;
var args = arguments;
clearTimeout(timeout);
if (immediate && !timeout) {
func.apply(context, args);
}
timeout = setTimeout(function() {
timeout = undefined;
if (!immediate) {
func.apply(context, args);
}
}, wait);
};
}
</script>

<main class="container-fluid">
<div>
Expand Down Expand Up @@ -241,14 +267,14 @@
class={itemBeingDragged ? 'is-dragging' : ''}
animate:flip={{ duration: 200 }}
in:fade
on:click={() => (selectedTask = task)}
on:click={() => {selectedTask = task; selectedTaskDescription = task.description; selectedTaskDetails = task.details ?? '';}}
draggable="true"
on:dragstart={onDragStart(task.id)}
on:dragend={onDragEnd()}
on:dragenter|preventDefault={swapOnEnter(task.id)}
on:dragover|preventDefault={() => {}}
>
<Task isDragging={itemBeingDragged === task.id} {onDelete} {task} />
<Task isSelected={task.id === selectedTask?.id} isDragging={itemBeingDragged === task.id} {onDelete} {task} />
</li>
{/each}
</ul>
Expand All @@ -258,8 +284,8 @@
</div>

<div class="task-details">
<input type="text" value={selectedTask?.description ?? ''} disabled={selectedTask == undefined} />
<textarea disabled={selectedTask == undefined}>{selectedTask?.details ?? ''}</textarea>
<input type="text" bind:value={selectedTaskDescription} disabled={selectedTask == undefined} on:change={debounce(updateSelectedTask, 200)} on:input={debounce(updateSelectedTask, 1000)} />
<textarea disabled={selectedTask == undefined} bind:value={selectedTaskDetails} on:change={debounce(updateSelectedTask, 200)} on:input={debounce(updateSelectedTask, 1000)}></textarea>
</div>
</div>
</main>
Expand Down
7 changes: 6 additions & 1 deletion resources/js/src/lib/api/tasks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ async function createTask(description: string, tags?: string[]) {
return task;
}

async function updateTask(task: Task, updatedTaskData: Partial<Task>) {
const response = await axios.patch(`/api/tasks/update/${task.id}`, updatedTaskData);
return taskSchema.parse(response.data);
}

async function moveTask(task: Task, order: number) {
const response = await axios.patch(`/api/tasks/move/${task.id}`, { new_pos: order });
const updatedTask = taskSchema.parse(response.data);
Expand All @@ -65,4 +70,4 @@ async function deleteTask(task: Task) {
await axios.delete(`/api/tasks/${task.id}`);
}

export { getTasks, getTags, createTask, moveTask, deleteTask };
export { getTasks, getTags, createTask, moveTask, updateTask, deleteTask };
7 changes: 6 additions & 1 deletion resources/js/src/lib/components/task.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@
export let isDragging = false;
export let onDelete: (t: typeof task) => void;
export let isSelected = false;
function buttonHandler(_ev: MouseEvent) {
onDelete(task);
}
</script>

<article class={`${isDragging ? 'is-dragging ' : ''}task`}>
<article class={`${isDragging ? 'is-dragging ' : ''}${isSelected ? 'selected ' : ''}task`}>
<p>{task.description}</p>

<footer>
Expand Down Expand Up @@ -70,4 +71,8 @@
opacity: 0;
}
}
.selected {
outline: 3px solid var(--pico-color-violet-400);
}
</style>
27 changes: 27 additions & 0 deletions routes/api.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,33 @@
return $task;
})->middleware('auth:sanctum');

Route::patch('/tasks/update/{id}', function (Request $request, string $id) {
$request->validate([
'description' => 'required|string',
]);

$task = Task::where('user_id', $request->user()->id)->findOrFail($id);

$task->description = $request->description ?? '';
$task->details = $request->details ?? '';
$task->save();

// FIXME: This only adds new tags, need to fix this such that tags can also be removed.
$tags = $request->tags;
if ( ! empty( $tags ) ) {
foreach( $tags as $tag ) {
$tag = Tag::firstOrCreate( [
'name' => $tag,
'user_id' => $request->user()->id,
] );

$task->tags()->save( $tag );
}
}

return $task;
})->middleware('auth:sanctum');

Route::patch('/tasks/move/{id}', function (Request $request, string $id) {
$request->validate([
'new_pos' => 'required|int',
Expand Down

0 comments on commit 5855730

Please sign in to comment.