|
1 |
| -<script setup> |
2 |
| -import { watch, reactive, toRaw } from "vue"; |
| 1 | +<script setup lang="ts"> |
3 | 2 | import { cloneDeep } from "lodash-es";
|
4 |
| -import draggable from "vuedraggable"; |
| 3 | +import { reactive, watch, toRaw } from "vue"; |
| 4 | +import type { Board, Column, Task } from "@/types"; |
5 | 5 | import { v4 as uuidv4 } from "uuid";
|
| 6 | +import draggable from "vuedraggable"; |
| 7 | +import TaskCard from "./TaskCard.vue"; |
| 8 | +import { useAlerts } from "@/stores/alerts"; |
| 9 | +const alerts = useAlerts(); |
| 10 | +// props |
| 11 | +const props = defineProps<{ |
| 12 | + board: Board; |
| 13 | + tasks: Task[]; |
| 14 | + addTask(task: Partial<Task>): Task; |
| 15 | +}>(); |
6 | 16 |
|
7 |
| -const props = defineProps({ |
8 |
| - board: Object, |
9 |
| - tasks: Array, |
10 |
| -}); |
11 |
| -
|
12 |
| -// emits |
13 |
| -const emit = defineEmits(["update"]); |
| 17 | +// events |
| 18 | +const emit = defineEmits<{ |
| 19 | + (e: "update", payload: Partial<Board>): void; |
| 20 | +}>(); |
14 | 21 |
|
15 | 22 | // local data
|
16 | 23 | const tasks = reactive(cloneDeep(props.tasks));
|
17 | 24 | const board = reactive(cloneDeep(props.board));
|
18 |
| -const columns = reactive(JSON.parse(board.order)); |
| 25 | +const columns = reactive<Column[]>(JSON.parse(board.order as string)); |
19 | 26 |
|
20 |
| -const addColumn = () => |
21 |
| - columns.push({ id: uuidv4(), title: "New column", taskIds: [] }); |
| 27 | +// methods |
| 28 | +function addColumn() { |
| 29 | + columns.push({ |
| 30 | + id: uuidv4(), |
| 31 | + title: "New Column", |
| 32 | + taskIds: [], |
| 33 | + }); |
| 34 | +} |
22 | 35 |
|
23 |
| -watch(columns, () => |
| 36 | +watch(columns, () => { |
24 | 37 | emit(
|
25 | 38 | "update",
|
26 |
| - cloneDeep({ |
27 |
| - ...props.board, |
28 |
| - order: JSON.stringify(toRaw(columns)), |
29 |
| - }) |
30 |
| - ) |
31 |
| -); |
| 39 | + cloneDeep({ ...board, order: JSON.stringify(toRaw(columns)) }) |
| 40 | + ); |
| 41 | +}); |
| 42 | +
|
| 43 | +async function addTask({ column, title }: { column: Column; title: string }) { |
| 44 | + const newTask = { title }; |
| 45 | + try { |
| 46 | + const savedTask = await props.addTask(newTask); |
| 47 | + tasks.push({ ...savedTask }); |
| 48 | + column.taskIds.push(savedTask.id); |
| 49 | + } catch (error) { |
| 50 | + alerts.error("Error creating task!"); |
| 51 | + } |
| 52 | +} |
32 | 53 | </script>
|
33 | 54 |
|
34 | 55 | <template>
|
35 |
| - <button class="text-gray-500" @click="addColumn">New Column +</button> |
36 |
| - <div class="flex items-start py-12"> |
37 |
| - <!-- //! outer block --> |
| 56 | + <div class="flex py-12 items-start"> |
38 | 57 | <draggable
|
39 | 58 | :list="columns"
|
40 | 59 | group="columns"
|
41 | 60 | item-key="id"
|
42 |
| - class="flex flex-grow-0 flex-shrink-0 overflow-x-scroll" |
| 61 | + class="flex overflow-x-scroll flex-grow-0 flex-shrink-0" |
43 | 62 | >
|
44 | 63 | <template #item="{ element: column }">
|
45 | 64 | <div
|
46 | 65 | class="column bg-gray-100 flex flex-col justify-between rounded-lg px-3 py-3 rounded mr-4 w-[300px]"
|
47 | 66 | >
|
48 |
| - <h2>{{ column.title }}</h2> |
49 |
| - <!-- //! inner block --> |
50 |
| - <draggable |
51 |
| - :list="column.taskIds" |
52 |
| - group="tasks" |
53 |
| - item-key="uid" |
54 |
| - :animation="200" |
55 |
| - ghost-class="ghost-card" |
56 |
| - class="min-h-[400px]" |
57 |
| - > |
58 |
| - <template #item="{ element: taskId }"> |
59 |
| - <task-card |
60 |
| - v-if="tasks.find((t) => t.id === taskId)" |
61 |
| - :task="tasks.find((t) => t.id === taskId)" |
62 |
| - class="mt-3 cursor-move" |
63 |
| - /> |
64 |
| - </template> |
65 |
| - </draggable> |
| 67 | + <div> |
| 68 | + <h3>{{ column.title }}</h3> |
| 69 | + <draggable |
| 70 | + :list="column.taskIds" |
| 71 | + group="tasks" |
| 72 | + item-key="uid" |
| 73 | + :animation="200" |
| 74 | + ghost-class="ghost-card" |
| 75 | + class="min-h-[400px]" |
| 76 | + > |
| 77 | + <template #item="{ element: taskId }"> |
| 78 | + <TaskCard |
| 79 | + v-if="tasks.find((t: Task) => t.id === taskId)" |
| 80 | + :task="(tasks.find((t: Task) => t.id === taskId) as Task)" |
| 81 | + class="mt-3 cursor-move" |
| 82 | + /> |
| 83 | + </template> |
| 84 | + </draggable> |
| 85 | + <TaskCreator |
| 86 | + @create=" |
| 87 | + addTask({ |
| 88 | + column, |
| 89 | + title: $event, |
| 90 | + }) |
| 91 | + " |
| 92 | + /> |
| 93 | + </div> |
66 | 94 | </div>
|
67 | 95 | </template>
|
68 | 96 | </draggable>
|
| 97 | + <button class="text-gray-500" @click="addColumn">New Column +</button> |
69 | 98 | </div>
|
70 | 99 | </template>
|
0 commit comments