Everywhere: More work on the todo page
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
<template>
|
||||
<Form v-slot="$form" ref="formRef" :initialValues :resolver @submit="onFormSubmit"
|
||||
class="flex flex-col gap-4 w-full sm:w-56">
|
||||
<!-- {{ $form }} -->
|
||||
<div class="flex flex-col gap-1">
|
||||
<InputText @input="initial = false;" v-model="formData.title" name="title" type="text" placeholder="Title"
|
||||
autocomplete="off" fluid />
|
||||
<Message v-if="$form.title?.invalid" severity="error" size="small" variant="simple">
|
||||
{{ $form.title.error?.message }}
|
||||
</Message>
|
||||
</div>
|
||||
<Button :disabled="initial || !$form.valid" class="fr" type="submit" severity="secondary" label="Submit" />
|
||||
</Form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useTodoStore } from "@/stores/todoStore";
|
||||
import { todoSchema } from "@/schemas/todo";
|
||||
import { zodResolver } from '@primevue/forms/resolvers/zod';
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
|
||||
import { type FormSubmitEvent } from "@primevue/forms/form";
|
||||
|
||||
const store = useTodoStore();
|
||||
const toast = useToast();
|
||||
const resolver = zodResolver(todoSchema);
|
||||
|
||||
const initial = ref(true); // makes submit button disabled
|
||||
const initialValues = ref({
|
||||
title: ""
|
||||
});
|
||||
const formRef = ref<HTMLElement | null>(null);
|
||||
const formData = ref({ ...initialValues.value }); // copy data from initialValues
|
||||
|
||||
async function onFormSubmit(e: FormSubmitEvent) {
|
||||
if (e.valid) {
|
||||
toast.add({ severity: "success", summary: "Todo added", life: 3000 });
|
||||
|
||||
store.todos.push({
|
||||
id: uuidv4(),
|
||||
title: e.values?.title || e.states?.title.value
|
||||
});
|
||||
|
||||
// Reset the form
|
||||
initial.value = true;
|
||||
formData.value = { ...initialValues.value }; // copy data from initialValues
|
||||
}
|
||||
else {
|
||||
toast.add({ severity: "error", summary: "Invalid request", life: 3000 });
|
||||
}
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.fr {
|
||||
float: right;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,87 @@
|
||||
<template>
|
||||
<div class="card">
|
||||
<ConfirmDialog></ConfirmDialog>
|
||||
<DataTable :value="computedTodos" tableStyle="min-width: 50rem" @sort="onSort" sortMode="multiple" removableSort>
|
||||
<Column field="number" header="#"></Column>
|
||||
<Column field="id" header="ID" sortable filterField="id" showFilterMenu filter="true"></Column>
|
||||
<Column field="title" header="Title" sortable filterField="title" showFilterMenu filter="true"></Column>
|
||||
<Column header="Modifier">
|
||||
<template #body="slotProps">
|
||||
<a @click="removeTodo(slotProps.data.id)">
|
||||
<span class="pi pi-trash" style="color: var(--p-red-600);"></span>
|
||||
</a>
|
||||
</template>
|
||||
</Column>
|
||||
</DataTable>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useConfirm } from "primevue/useconfirm";
|
||||
import { useToast } from "primevue/usetoast";
|
||||
import { useTodoStore } from "@/stores/todoStore";
|
||||
|
||||
import type { Todo } from "@/schemas/todo";
|
||||
|
||||
const confirm = useConfirm();
|
||||
const store = useTodoStore();
|
||||
const toast = useToast();
|
||||
|
||||
const onSort = (event: any) => {
|
||||
console.log(event);
|
||||
};
|
||||
|
||||
const sorting = ref<Record<string, string>>({
|
||||
id: "asc",
|
||||
title: "asc",
|
||||
});
|
||||
|
||||
function toggleSorting(key: string) {
|
||||
sorting.value[key] = sorting.value[key] === 'asc' ? 'desc' : 'asc';
|
||||
};
|
||||
|
||||
function sortTodos(): Todo[] {
|
||||
let todos: Todo[] = JSON.parse(JSON.stringify(store.todos)); // deep copy
|
||||
|
||||
// Number
|
||||
|
||||
// ID
|
||||
|
||||
// Title
|
||||
todos = (sorting.value.title === "desc")
|
||||
? todos.sort((a, b) => b.title.localeCompare(a.title))
|
||||
: todos.sort((a, b) => a.title.localeCompare(b.title));
|
||||
|
||||
return todos;
|
||||
}
|
||||
|
||||
const computedTodos = computed(() => {
|
||||
return sortTodos().map((todo, index) => ({
|
||||
number: index + 1,
|
||||
...todo
|
||||
}));
|
||||
});
|
||||
|
||||
const removeTodo = (id: String) => {
|
||||
confirm.require({
|
||||
message: "Do you want to delete this todo?",
|
||||
header: "Confirmation",
|
||||
icon: "pi pi-info-circle",
|
||||
rejectLabel: "Cancel",
|
||||
rejectProps: {
|
||||
label: "Cancel",
|
||||
severity: "secondary",
|
||||
outlined: true
|
||||
},
|
||||
acceptProps: {
|
||||
label: "Delete",
|
||||
severity: "danger"
|
||||
},
|
||||
accept: () => {
|
||||
toast.add({ severity: "info", summary: "Confirmed", detail: "Todo deleted", life: 3000 });
|
||||
store.todos = store.todos.filter(todo => todo.id !== id);
|
||||
},
|
||||
reject: () => {}
|
||||
});
|
||||
};
|
||||
</script>
|
||||
Reference in New Issue
Block a user