+ some fixes
This commit is contained in:
@@ -15,7 +15,7 @@
|
||||
<!-- Название -->
|
||||
<FloatLabel class="w-full" variant="on">
|
||||
<label for="paymentName">Название платежа</label>
|
||||
<InputText v-model="name" id="paymentName" class="!w-full"/>
|
||||
<InputText v-model="payment.name" id="paymentName" class="!w-full"/>
|
||||
</FloatLabel>
|
||||
|
||||
<!-- Категория -->
|
||||
@@ -64,7 +64,7 @@
|
||||
<!-- Описание -->
|
||||
<FloatLabel class="!w-full">
|
||||
<label for="description">Описание</label>
|
||||
<Textarea v-model="description" id="description" rows="3" class="!w-full"/>
|
||||
<Textarea v-model="payment.description" id="description" rows="3" class="!w-full"/>
|
||||
</FloatLabel>
|
||||
|
||||
<!-- Дата повторения (выпадающий список) -->
|
||||
@@ -73,7 +73,7 @@
|
||||
@click="isDaySelectorOpened = !isDaySelectorOpened">
|
||||
<div class="flex flex-row items-center pe-4 py-2 gap-4">
|
||||
<div class="flex flex-row justify-between w-full px-4">
|
||||
<p class="font-bold">Повторять каждый {{ repeatDay || 'N' }} день месяца</p>
|
||||
<p class="font-bold">Повторять каждый {{ payment.atDay || 'N' }} день месяца</p>
|
||||
</div>
|
||||
<div>
|
||||
<span :class="{'rotate-90': isDaySelectorOpened}"
|
||||
@@ -98,7 +98,7 @@
|
||||
<!-- Сумма -->
|
||||
<InputGroup class="w-full">
|
||||
<InputGroupAddon>₽</InputGroupAddon>
|
||||
<InputNumber v-model="amount" placeholder="Сумма"/>
|
||||
<InputNumber v-model="payment.amount" placeholder="Сумма"/>
|
||||
<InputGroupAddon>.00</InputGroupAddon>
|
||||
</InputGroup>
|
||||
|
||||
@@ -117,7 +117,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {ref, watch, computed, defineEmits} from 'vue';
|
||||
import {ref, watch, computed, defineEmits, nextTick} from 'vue';
|
||||
import Button from 'primevue/button';
|
||||
import InputText from 'primevue/inputtext';
|
||||
import InputNumber from 'primevue/inputnumber';
|
||||
@@ -128,14 +128,19 @@ import FloatLabel from 'primevue/floatlabel';
|
||||
import InputGroup from 'primevue/inputgroup';
|
||||
import InputGroupAddon from "primevue/inputgroupaddon";
|
||||
import SelectButton from 'primevue/selectbutton';
|
||||
import {saveRecurrentPayment} from "@/services/recurrentService";
|
||||
import {saveRecurrentPayment, updateRecurrent} from "@/services/recurrentService";
|
||||
import {Category} from "@/models/Category";
|
||||
import {RecurrentPayment} from "@/models/Recurrent";
|
||||
import {useToast} from "primevue/usetoast";
|
||||
|
||||
const toast = useToast()
|
||||
|
||||
const props = defineProps({
|
||||
show: Boolean, // Показать/скрыть модальное окно
|
||||
expenseCategories: Array, // Внешние данные для списка категорий
|
||||
incomeCategories: Array, // Внешние данные для списка категорий
|
||||
categoryTypes: Array,
|
||||
payment: Object | null // Для редактирования существующего платежа
|
||||
payment: RecurrentPayment | null // Для редактирования существующего платежа
|
||||
})
|
||||
|
||||
const emits = defineEmits(["open-edit", "save-payment", "close-modal"]);
|
||||
@@ -143,13 +148,12 @@ const emits = defineEmits(["open-edit", "save-payment", "close-modal"]);
|
||||
const loading = ref(false)
|
||||
// Поля для формы
|
||||
const name = ref('');
|
||||
const selectedCategoryType = ref(props.payment ? props.payment.type : props.categoryTypes[0]);
|
||||
console.log(props.categoryTypes)
|
||||
console.log(selectedCategoryType.value)
|
||||
console.log(props.expenseCategories)
|
||||
console.log(props.incomeCategories)
|
||||
const selectedCategory = ref(selectedCategoryType.code == 'EXPENSE' ? props.expenseCategories[0] ? props.expenseCategories[0] : props.incomeCategories[0] : props.incomeCategories[0] ? props.incomeCategories[0] : props.expenseCategories[0]);
|
||||
console.log(selectedCategory.value)
|
||||
const payment = ref(props.payment ? props.payment : new RecurrentPayment())
|
||||
const selectedCategoryType = ref(props.payment ? props.payment.category.type : props.categoryTypes[0]);
|
||||
|
||||
const selectedCategory = ref(props.payment ? props.payment.category : selectedCategoryType.code == 'EXPENSE'
|
||||
? props.expenseCategories[0]
|
||||
: props.incomeCategories[0]);
|
||||
|
||||
|
||||
const categoryTypeChanged = (code) => {
|
||||
@@ -170,12 +174,15 @@ const days = Array.from({length: 31}, (_, i) => i + 1);
|
||||
|
||||
// Выбор дня
|
||||
const selectDay = (day: number) => {
|
||||
console.log(day)
|
||||
payment.value.atDay = day;
|
||||
repeatDay.value = day;
|
||||
isDaySelectorOpened.value = false;
|
||||
};
|
||||
|
||||
// Выбор категории
|
||||
const selectCategory = (category) => {
|
||||
const selectCategory = (category: Category) => {
|
||||
payment.value.category = category;
|
||||
isCategorySelectorOpened.value = false;
|
||||
selectedCategory.value = category;
|
||||
};
|
||||
@@ -211,13 +218,32 @@ const savePayment = async () => {
|
||||
if (isEditing.value && props.payment) {
|
||||
paymentData.id = props.payment.id; // Если редактируем, сохраняем ID
|
||||
}
|
||||
try {
|
||||
await saveRecurrentPayment(paymentData)
|
||||
loading.value = false
|
||||
resetForm();
|
||||
} catch (error) {
|
||||
console.error('Error saving payment:', error);
|
||||
// try {
|
||||
if (props.payment) {
|
||||
await updateRecurrent(payment.value)
|
||||
.then(res => {
|
||||
loading.value = false;
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
toast.add({severity: 'error', summary: 'Ошибка сохранения', detail: err.response.data.message, life: 3000})
|
||||
})
|
||||
}
|
||||
else {
|
||||
await saveRecurrentPayment(payment.value)
|
||||
.then(() => {
|
||||
loading.value = false;
|
||||
})
|
||||
.catch((err) => {
|
||||
toast.add({severity: 'error', summary: 'Ошибка сохранения', detail: err.response.data.message, life: 3000})
|
||||
console.log(err)
|
||||
})
|
||||
}
|
||||
// loading.value = false
|
||||
// resetForm();
|
||||
// } catch (error) {
|
||||
// console.error('Error saving payment:', error);
|
||||
// }
|
||||
emits('save-payment', paymentData);
|
||||
resetForm();
|
||||
closeModal();
|
||||
|
||||
@@ -26,6 +26,7 @@ const loading = ref(false)
|
||||
// Поля для формы
|
||||
const name = ref('');
|
||||
const selectedCategoryType = ref(props.payment ? props.payment.type : props.categoryTypes[0]);
|
||||
console.log(selectedCategoryType.value);
|
||||
const selectedCategory = ref(selectedCategoryType.code == 'EXPESE' ? props.expenseCategories[0] : props.incomeCategories[0]);
|
||||
|
||||
const categoryTypeChanged = (code) => {
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
<!-- Заголовок -->
|
||||
<div class="flex flex-col gap-4 xl:flex-row justify-between bg-gray-100">
|
||||
<h1 class="text-4xl text-gray-800">Ежемесячные платежи</h1>
|
||||
<Button label="Добавить платеж" icon="pi pi-plus" class="text-sm !bg-blue-300 hover:!bg-blue-400 !border-blue-300" @click="toggleModal(null)"/>
|
||||
<Button label="Добавить платеж" icon="pi pi-plus"
|
||||
class="text-sm !bg-blue-300 hover:!bg-blue-400 !border-blue-300" @click="toggleModal(null)"/>
|
||||
</div>
|
||||
<div v-if="!space">Выберите сперва пространство</div>
|
||||
<!-- Список рекуррентных платежей -->
|
||||
@@ -35,6 +36,7 @@
|
||||
:expenseCategories="expenseCategories"
|
||||
:incomeCategories="incomeCategories"
|
||||
:categoryTypes="categoryTypes"
|
||||
:payment="editingPayment"
|
||||
@save-payment="savePayment"
|
||||
@close-modal="toggleModal"/>
|
||||
|
||||
@@ -49,13 +51,18 @@ import {computed, onMounted, ref, watch} from 'vue';
|
||||
import RecurrentListItem from "@/components/settings/recurrent/RecurrentListItem.vue";
|
||||
import Button from "primevue/button";
|
||||
import {RecurrentPayment} from "@/models/Recurrent";
|
||||
import {getRecurrentPayments} from "@/services/recurrentService";
|
||||
import {deleteRecurrent, getRecurrentPayments} from "@/services/recurrentService";
|
||||
import CreateRecurrentModal from "@/components/settings/recurrent/CreateRecurrentModal.vue";
|
||||
import {Category, CategoryType} from "@/models/Category";
|
||||
import {getCategories, getCategoryTypes} from "@/services/categoryService";
|
||||
import {deleteCategoryRequest, getCategories, getCategoryTypes} from "@/services/categoryService";
|
||||
import LoadingView from "@/components/LoadingView.vue";
|
||||
import {useSpaceStore} from "@/stores/spaceStore";
|
||||
import {getBudgetInfos} from "@/services/budgetsService";
|
||||
import {useConfirm} from "primevue/useconfirm";
|
||||
import {useToast} from "primevue/usetoast";
|
||||
|
||||
const confirm = useConfirm();
|
||||
const toast = useToast()
|
||||
|
||||
const spaceStore = useSpaceStore()
|
||||
|
||||
@@ -84,7 +91,9 @@ const loading = ref(true);
|
||||
|
||||
const showModal = ref(false);
|
||||
|
||||
const toggleModal = () => {
|
||||
const editingPayment = ref<RecurrentPayment | null>(null);
|
||||
const toggleModal = (payment: RecurrentPayment | null) => {
|
||||
editingPayment.value = payment
|
||||
showModal.value = !showModal.value;
|
||||
}
|
||||
|
||||
@@ -137,11 +146,39 @@ const savePayment = async () => {
|
||||
|
||||
|
||||
// Обработчики событий
|
||||
const editPayment = (payment: any) => {
|
||||
|
||||
const editPayment = (payment: RecurrentPayment) => {
|
||||
toggleModal(payment)
|
||||
};
|
||||
|
||||
const deletePayment = (payment: any) => {
|
||||
const deletePayment = (payment: RecurrentPayment) => {
|
||||
console.log('delete payment:', payment);
|
||||
confirm.require({
|
||||
message: 'Вы уверены, что хотите выполнить это действие?\n Это нельзя будет отменить.\n',
|
||||
header: `Удаление ежемесячной транзакции ${payment.name}`,
|
||||
icon: 'pi pi-info-circle',
|
||||
rejectLabel: 'Cancel',
|
||||
rejectProps: {
|
||||
label: 'Cancel',
|
||||
severity: 'secondary',
|
||||
outlined: true
|
||||
},
|
||||
acceptProps: {
|
||||
label: 'Delete',
|
||||
severity: 'danger'
|
||||
},
|
||||
accept: async () => {
|
||||
await deleteRecurrent(payment.id).then(async (result) => {
|
||||
await fetchRecurrentPayments()
|
||||
toast.add({severity: 'info', summary: 'Confirmed', detail: 'Удалено!', life: 3000});
|
||||
}).catch(((err) => {
|
||||
toast.add({severity: 'error', summary: 'Rejected', detail: 'Ошибка удаления платежа', life: 3000});
|
||||
})
|
||||
)
|
||||
},
|
||||
reject: () => {
|
||||
// toast.add({severity: 'error', summary: 'Rejected', detail: 'You have rejected', life: 3000});
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -69,6 +69,7 @@ const editPayment = () => {
|
||||
};
|
||||
|
||||
const deletePayment = () => {
|
||||
console.log('deleting payment');
|
||||
emit('delete-payment', props.payment);
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -2,6 +2,7 @@ import {Category} from "@/models/Category";
|
||||
|
||||
export class RecurrentPayment {
|
||||
public id: number;
|
||||
public space: Space;
|
||||
public atDay: number;
|
||||
public category: Category;
|
||||
public name: string;
|
||||
|
||||
@@ -12,6 +12,7 @@ export const getRecurrentPayments = async () => {
|
||||
|
||||
export const saveRecurrentPayment = async (payment: RecurrentPayment) => {
|
||||
const spaceStore = useSpaceStore()
|
||||
payment.space = spaceStore.space
|
||||
return await apiClient.post(`/spaces/${spaceStore.space?.id}/recurrents`, payment)
|
||||
}
|
||||
//
|
||||
@@ -23,10 +24,21 @@ export const saveRecurrentPayment = async (payment: RecurrentPayment) => {
|
||||
// return await apiClient.post('/categories', category);
|
||||
// };
|
||||
//
|
||||
// export const updateCategory = async (id: number, category: any) => {
|
||||
// return await apiClient.put(`/categories/${id}`, category);
|
||||
// };
|
||||
//
|
||||
// export const deleteCategory = async (id: number) => {
|
||||
// return await apiClient.delete(`/categories/${id}`);
|
||||
// };
|
||||
export const updateRecurrent = async (recurrent: RecurrentPayment) => {
|
||||
const id = recurrent.id
|
||||
const spaceStore = useSpaceStore()
|
||||
recurrent.space = spaceStore.space
|
||||
return await apiClient.put(`/spaces/${spaceStore.space?.id}/recurrents/${id}`, recurrent)
|
||||
.then(res => res.data)
|
||||
.catch(err => {
|
||||
console.log(err)
|
||||
throw err
|
||||
})
|
||||
};
|
||||
|
||||
export const deleteRecurrent = async (id: number) => {
|
||||
const spaceStore = useSpaceStore()
|
||||
return await apiClient.delete(`/spaces/${spaceStore.space?.id}/recurrents/${id}`)
|
||||
.then(res => res.data)
|
||||
.catch(err => console.log(err))
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user