handling create update delete categories

This commit is contained in:
xds
2025-10-28 16:11:41 +03:00
parent f211f1dde6
commit 19ca34d318
3 changed files with 157 additions and 19 deletions

View File

@@ -9,6 +9,8 @@ import {useSpaceStore} from "@/stores/spaceStore";
import {CategoryType, CategoryTypeName} from "@/models/enums";
import emojiRegex from 'emoji-regex'
import {useCategoriesStore} from "@/stores/categories-store";
import {CreateCategoryDTO, UpdateCategoryDTO} from "@/models/category";
import ConfirmDialog from '@/components/ConfirmDialog.vue'
const route = useRoute()
@@ -17,14 +19,21 @@ const toolbar = useToolbarStore();
const toast = useToast();
const spaceStore = useSpaceStore();
const categoriesStore = useCategoriesStore();
const categoryId = ref<string | undefined>(route.params.id)
const tgApp = window.Telegram.WebApp
const categoryId = ref<string | undefined>(route.params.id as string)
const mode = computed(() => {
return categoryId.value ? "edit" : "create"
})
const categoryType = ref<CategoryType>(CategoryType.EXPENSE)
const categoryName = ref<string>()
const isCategoryTypeError = ref<boolean>(false)
const categoryName = ref<string>('')
const isCategoryNameError = ref<boolean>(false)
const categoryIcon = ref<string>("🛍️")
const categoryDescription = ref<string>()
const isCategoryIconError = ref<boolean>(false)
const categoryDescription = ref<string>('')
const isCategoryDescriptionError = ref<boolean>(false)
// Генерим опции: [{ label: "Расходы", value: "EXPENSE" }, ...]
@@ -82,22 +91,123 @@ function handleCompositionEnd(e: CompositionEvent) {
handleInput(e as unknown as Event)
}
const validateForm = (): boolean => {
if (!categoryType.value) {
isCategoryTypeError.value = true
return false;
}
if (categoryName.value.length == 0) {
isCategoryNameError.value = true
return false;
}
if (categoryIcon.value.length == 0) {
isCategoryIconError.value = true
return false;
}
console.log(categoryDescription.value.length)
if (categoryDescription.value.length == 0) {
isCategoryDescriptionError.value = true
return false;
}
return true;
}
const buildUpdate = (): UpdateCategoryDTO => {
if (validateForm()) {
return {
type: categoryType.value,
name: categoryName.value,
description: categoryDescription.value,
icon: categoryIcon.value,
} as UpdateCategoryDTO
} else {
throw Error("Error while validating form")
}
}
const buildCreate = (): CreateCategoryDTO => {
if (validateForm()) {
return {
type: categoryType.value,
name: categoryName.value,
description: categoryDescription.value,
icon: categoryIcon.value,
} as CreateCategoryDTO
} else {
throw Error("Error while validating form")
}
}
const moveUser = async () => {
if (window.history.length > 1) {
console.log('moved back')
router.back()
} else {
console.log('moved forward')
await router.push('/categories')
}
}
const isDeleteAlertVisible = ref(false)
const deleteAlertMessage = ref<string>('Do you really want to delete the category?')
const deleteCategory = async () => {
if (spaceStore.selectedSpaceId) {
await categoriesService.deleteCategory(spaceStore.selectedSpaceId, Number(categoryId.value))
await categoriesStore.fetchCategories(spaceStore.selectedSpaceId)
await moveUser()
}
}
onMounted(async () => {
if (mode.value === "edit") {
await fetchCategory()
toolbar.registerHandler('deleteCategory', () => {
if (tgApp.initData) {
tgApp.showConfirm(deleteAlertMessage, async (confirmed: boolean) => {
if (confirmed) {
await deleteCategory()
}
})
} else {
isDeleteAlertVisible.value = true
}
})
toolbar.registerHandler('updateCategory', async () => {
if (spaceStore.selectedSpaceId) {
// await categoriesStore.fetchCategories(spaceStore.selectedSpaceId)
router.back()
try {
let updateDTO = buildUpdate()
await categoriesService.updateCategory(spaceStore.selectedSpaceId, updateDTO)
console.log(updateDTO)
await moveUser()
} catch (e) {
toast.add({
severity: "error",
summary: "Error while updating category",
detail: e,
life: 3000,
})
}
}
})
} else {
toolbar.registerHandler('createCategory', async () => {
if (spaceStore.selectedSpaceId) {
// await categoriesStore.fetchCategories(spaceStore.selectedSpaceId)
router.back()
try {
let createDTO = buildCreate()
await categoriesService.createCategory(spaceStore.selectedSpaceId, createDTO)
console.log(createDTO)
await moveUser()
} catch (e) {
toast.add({
severity: "error",
summary: "Error while creating category",
detail: e,
life: 3000
})
}
}
})
@@ -108,7 +218,11 @@ onMounted(async () => {
<template>
<div class="flex flex-col w-full justify-items-start gap-7">
<ConfirmDialog
v-if="isDeleteAlertVisible"
:message="deleteAlertMessage"
:callback="(confirmed: boolean) => { if (confirmed) deleteCategory(); isDeleteAlertVisible = false; }"
/>
<div class="flex flex-col w-full ">
<div class=" flex-col " v-tooltip.focus.bottom="'Only emoji supported'">
<input
@@ -131,6 +245,8 @@ onMounted(async () => {
/>
<label class=" !justify-center !font-extralight text-gray-600 text-center">Category
icon</label>
<span v-if="isCategoryIconError"
class="text-sm !text-red-500 font-extralight">Icon cannot be empty or non-emoji</span>
</div>
<div class="w-full !items-center !justify-center">
@@ -141,14 +257,18 @@ onMounted(async () => {
optionValue="value"
class="!w-full !items-center !justify-center "
/>
<span v-if="isCategoryTypeError"
class="text-sm !text-red-500 font-extralight">Category type cannot be empty</span>
</div>
</div>
<div class="flex flex-col w-full justify-items-start">
<label class="!font-semibold text-gray-600 pl-2">Category name</label>
<div class="card !rounded-3xl !justify-start !items-start !p-4 !pl-5 ">
<input class="font-extralight w-full focus:outline-0" placeholder="Name" v-model="categoryName"/>
<input class="font-extralight w-full focus:outline-0" placeholder="Name" v-model="categoryName"
@input="categoryName.length !== 0 ? isCategoryNameError = false : true"/>
</div>
<span v-if="isCategoryNameError" class="text-sm !text-red-500 font-extralight">Name cannot be empty</span>
</div>
<div class="flex flex-col w-full justify-items-start">
<label class="!font-semibold text-gray-600 !pl-2">Category description</label>
@@ -156,8 +276,11 @@ onMounted(async () => {
<textarea
class="!font-extralight !text-start !pl-2 w-full focus:outline-0 !focus:border-0 !@focus:shadow-none !bg-white !border-0 min-h-36"
style="box-shadow: none !important;"
placeholder="Description" v-model="categoryDescription"/>
placeholder="Description" v-model="categoryDescription"
@input="categoryDescription.length !== 0 ? isCategoryDescriptionError = false : true"/>
</div>
<span v-if="isCategoryDescriptionError"
class="text-sm !text-red-500 font-extralight">Description cannot be empty</span>
</div>
</div>

View File

@@ -36,7 +36,6 @@ const recurrentDate = ref<number>(Math.floor(Math.random() * 31))
const isDateError = ref(false)
const fetchData = async () => {
try {
if (spaceStore.selectedSpaceId) {
@@ -172,7 +171,11 @@ const deleteAlertMessage = ref('Do you want to delete recurrent?')
const deleteRecurrent = async () => {
await recurrentsService.deleteRecurrent(spaceStore.selectedSpaceId, recurrentId.value)
await recurrentsStore.fetchRecurrents(spaceStore.selectedSpaceId)
if (window.history.length > 1) {
router.back()
} else {
await router.push('/categories')
}
}
onMounted(async () => {
@@ -190,7 +193,7 @@ onMounted(async () => {
console.log('deleteRecurrent2')
if (tgApp.initData) {
console.log('deleteRecurrent3')
tgApp.showConfirm(deleteAlertMessage.value, async (confirmed) => {
tgApp.showConfirm(deleteAlertMessage.value, async (confirmed: boolean) => {
if (confirmed) {
console.log("recurrent id is deleted")
await deleteRecurrent()

View File

@@ -1,9 +1,9 @@
import {Category} from "@/models/category";
import {Category, CreateCategoryDTO, UpdateCategoryDTO} from "@/models/category";
import {CategoryType} from "@/models/enums";
import {User} from "@/models/user";
async function fetchCategories(spaceId: number) {
let categories : Category[] = []
let categories: Category[] = []
for (let i = 0; i < 10; i++) {
categories.push({
id: i,
@@ -38,6 +38,18 @@ async function fetchCategory(spaceId: number, categoryId: number): Promise<Categ
} as Category
}
export const categoriesService = {
fetchCategories, fetchCategory
async function createCategory(spaceId: number, category: CreateCategoryDTO): Promise<number> {
return 1
}
async function updateCategory(spaceId: number, category: UpdateCategoryDTO): Promise<void> {
}
async function deleteCategory(spaceId: number, categoryId: number): Promise<void> {
}
export const categoriesService = {
fetchCategories, fetchCategory, createCategory, updateCategory, deleteCategory,
}