This commit is contained in:
Vladimir Voronin
2024-11-04 17:41:35 +03:00
parent c2b8787ed4
commit 7ae38604d2
11 changed files with 168 additions and 82 deletions

View File

@@ -10,18 +10,16 @@
<Button label="Sub" :class="checkNotif ? 'flex' : '!hidden'" @click="checkSubscribe"/> <Button label="Sub" :class="checkNotif ? 'flex' : '!hidden'" @click="checkSubscribe"/>
<router-view/> <router-view/>
</div> </div>
<OverlayView class="w-full sticky invisible lg:visible top-0 z-10"/> <!-- <OverlayView class="w-full sticky invisible lg:visible top-0 z-10"/>-->
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import MenuBar from "./components/MenuBar.vue"; import MenuBar from "./components/MenuBar.vue";
import OverlayView from "@/components/OverlayView.vue";
import ToolBar from "@/components/ToolBar.vue"; import ToolBar from "@/components/ToolBar.vue";
import Button from "primevue/button"; import Button from "primevue/button";
import axiosSetup from "@/services/axiosSetup"; import {computed, onMounted} from "vue";
import {computed, onMounted, ref} from "vue";
import {subscribeUserToPush} from "@/services/pushManager"; import {subscribeUserToPush} from "@/services/pushManager";
import apiClient from '@/services/axiosSetup'; import apiClient from '@/services/axiosSetup';

View File

@@ -17,6 +17,8 @@
height: 0.5rem !important; height: 0.5rem !important;
} }
canvas { canvas {
/*margin-top: 1rem;*/ /*margin-top: 1rem;*/
/*height: 12 8px !important*/ /*height: 12 8px !important*/

View File

@@ -42,18 +42,18 @@ import Menubar from "primevue/menubar";
const items = ref([ const items = ref([
{ {
label: 'Home', label: 'Главная',
icon: 'pi pi-home', icon: 'pi pi-home',
url: '/' url: '/'
}, },
{ {
label: 'Analytics', label: 'Аналитика',
icon: 'pi pi-star', icon: 'pi pi-star',
url: '/analytics' url: '/analytics'
}, },
{ {
label: 'Budgets', label: 'Бюджеты',
icon: 'pi pi-search', icon: 'pi pi-briefcase',
url: '/budgets' url: '/budgets'
// items: [ // items: [
// { // {
@@ -93,12 +93,12 @@ const items = ref([
// ] // ]
}, },
{ {
label: 'Transactions', label: 'Транзакции',
icon: "pi pi-star", icon: "pi pi-star",
url: '/transactions' url: '/transactions'
}, },
{ {
label: 'Settings', label: 'Настройки',
icon: 'pi pi-envelope', icon: 'pi pi-envelope',
url: '/settings', url: '/settings',
// badge: 3 // badge: 3

View File

@@ -28,6 +28,7 @@ const openDrawer = (selectedTransactionType = null, selectedCategoryType = null)
} }
const closeDrawer = () => { const closeDrawer = () => {
drawerOpened.value = false; drawerOpened.value = false;
} }
@@ -76,11 +77,8 @@ onMounted(() => {
<div v-if="loading">Loding...</div> <div v-if="loading">Loding...</div>
<div v-else> <div v-else>
<TransactionEditDrawer v-if="drawerOpened" :visible="drawerOpened" <TransactionEditDrawer v-if="drawerOpened" :visible="drawerOpened"
:transaction-type="transactionType" :transaction-type="transactionType"
:category-type="categoryType" :category-type="categoryType"
@close-drawer="closeDrawer()" @close-drawer="closeDrawer()"
/> />

View File

@@ -3,9 +3,9 @@ import Button from "primevue/button";
import InputNumber from "primevue/inputnumber"; import InputNumber from "primevue/inputnumber";
import ProgressBar from "primevue/progressbar"; import ProgressBar from "primevue/progressbar";
import { Category } from "@/models/Category"; import {Category} from "@/models/Category";
import { computed, ref, watch } from "vue"; import {computed, ref, watch} from "vue";
import { formatAmount } from "@/utils/utils"; import {formatAmount} from "@/utils/utils";
const props = defineProps({ const props = defineProps({
category: { category: {
@@ -29,7 +29,7 @@ const startEditing = () => {
const stopEditing = () => { const stopEditing = () => {
isEditing.value = false; isEditing.value = false;
emits("category-updated", { ...props.category, currentLimit: currentLimit.value }); emits("category-updated", {...props.category, currentLimit: currentLimit.value});
}; };
// Реактивное вычисление отношения затрат к плану // Реактивное вычисление отношения затрат к плану
@@ -54,34 +54,42 @@ watch(
<div class="flex flex-row justify-between w-full"> <div class="flex flex-row justify-between w-full">
<div :class="isEditing ? 'w-1/5': ''" class="min-w-1 w-4/6 justify-between "> <div :class="isEditing ? 'w-1/5': ''" class="min-w-1 w-4/6 justify-between ">
<h4 class="text-lg line-clamp-1">{{props.category.category.icon }} {{ props.category.category.name }}</h4> <h4 class="text-lg line-clamp-1">{{ props.category.category.icon }} {{ props.category.category.name }}</h4>
<!-- <p class="text-sm text-gray-500 line-clamp-1 min-w-1 ">{{ editedCategory.category.description }}</p>--> <!-- <p class="text-sm text-gray-500 line-clamp-1 min-w-1 ">{{ editedCategory.category.description }}</p>-->
</div> </div>
<div class="flex flex-row gap-2 justify-end items-center w-4/6 "> <div class="flex flex-row gap-2 justify-end items-center w-4/6 ">
<!-- Сумма, которая становится редактируемой при клике --> <!-- Сумма, которая становится редактируемой при клике -->
<button v-if="!isEditing" @click="startEditing" <button v-if="!isEditing" @click="startEditing"
class="text-lg font-bold cursor-pointer w-fit text-end line-clamp-1"> class="text-lg font-bold cursor-pointer w-fit text-end line-clamp-1">
<div class="flex flex-row gap-2 items-baseline" > <div class="flex flex-row gap-2 items-baseline">
<p class="font-light text-sm" :class="spentPlannedRatio == 0 ? 'hidden': ''">{{spentPlannedRatio.toFixed(0)}} %</p> <p class="font-light text-sm" :class="spentPlannedRatio == 0 ? 'hidden': ''">
<p class="line-clamp-1 w-fit">{{ formatAmount(props.category.currentSpent) }} / {{ spentPlannedRatio.toFixed(0) }} %</p>
{{ formatAmount(currentLimit) }} </p> <p class="line-clamp-1 w-fit">{{ formatAmount(props.category.currentSpent) }} /
{{ formatAmount(currentLimit) }} </p>
</div> </div>
</button> </button>
<InputNumber v-else ref="inputRefs" type="text" v-model="props.category.currentLimit" <InputNumber v-else ref="inputRefs" type="text" v-model="props.category.currentLimit"
class="text-lg font-bold border-b-2 border-gray-300 outline-none focus:border-blue-500 w-32 text-right" class="text-lg font-bold border-b-2 border-gray-300 outline-none focus:border-none !w-24 text-right"
:min="props.category.categoryPlannedLimit" :max="900000" :invalid="currentLimit < props.category.categoryPlannedLimit" :min="props.category.categoryPlannedLimit" :max="900000"
:invalid="currentLimit < props.category.categoryPlannedLimit"
v-tooltip.top="'Сумма не должна быть ниже суммы запланированных!'" v-tooltip.top="'Сумма не должна быть ниже суммы запланированных!'"
unstyled /> unstyled
<Button v-if="isEditing" @click="stopEditing" icon="pi pi-check" severity="success" rounded outlined />
<Button v-if="isEditing" @click="stopEditing" icon="pi pi-check" severity="success" rounded outlined
aria-label="Search"/> aria-label="Search"/>
</div> </div>
</div> </div>
<div class="flex flex-col w-full"> <div class="flex flex-col w-full">
<ProgressBar :value="Number(spentPlannedRatio.toFixed(0))" class="w-full" :show-value="false"> </ProgressBar> <ProgressBar :value="Number(spentPlannedRatio.toFixed(0))" class="w-full .your-parent-class"
<!-- <div class="z-50">{{formatAmount(spentPlannedRatio.toFixed(0))}}%</div>--> :pt=" {
value: {
style: spentPlannedRatio >=100 ?'background: red !important' : '',
}
}" :color="'red-200'" :show-value="false"></ProgressBar>
<!-- <div class="z-50">{{formatAmount(spentPlannedRatio.toFixed(0))}}%</div>-->
</div> </div>
</div> </div>

View File

@@ -7,7 +7,7 @@ import {Transaction} from "@/models/Transaction";
import TransactionEditDrawer from "@/components/budgets/TransactionEditDrawer.vue"; import TransactionEditDrawer from "@/components/budgets/TransactionEditDrawer.vue";
import {Category, CategoryType} from "@/models/Category"; import {Category, CategoryType} from "@/models/Category";
import {getCategories, getCategoryTypes} from "@/services/categoryService"; import {getCategories, getCategoryTypes} from "@/services/categoryService";
import {updateTransactionRequest} from "@/services/transactionService"; import {setTransactionDoneRequest} from "@/services/transactionService";
import {formatAmount, formatDate} from "@/utils/utils"; import {formatAmount, formatDate} from "@/utils/utils";
@@ -20,15 +20,19 @@ const props = defineProps(
isList: { isList: {
type: Boolean, type: Boolean,
required: true, required: true,
},
transactions: {
type: Array as () => Array<Transaction>,
required: false
} }
} }
) )
const emits = defineEmits(['open-drawer', 'transaction-checked', 'transaction-updated']) const emits = defineEmits(['open-drawer', 'transaction-checked', 'transaction-updated', 'delete-transaction'])
const setIsDoneTrue = async () => { const setIsDoneTrue = async () => {
setTimeout(async () => { setTimeout(async () => {
await updateTransactionRequest(props.transaction) await setTransactionDoneRequest(props.transaction)
emits('transaction-checked') emits('transaction-checked')
}, 10); }, 10);
// showedTransaction.value.isDone = !showedTransaction.value.isDone; // showedTransaction.value.isDone = !showedTransaction.value.isDone;
@@ -113,7 +117,8 @@ onMounted(async () => {
<p :class="transaction.isDone && isPlanned && !props.isList ? 'line-through' : ''" class="font-bold">{{ <p :class="transaction.isDone && isPlanned && !props.isList ? 'line-through' : ''" class="font-bold">{{
transaction.comment transaction.comment
}}</p> }}</p>
<p :class="transaction.isDone && isPlanned && !props.isList ? 'line-through' : ''" class="font-light">{{ <p :class="transaction.isDone && isPlanned && !props.isList ? 'line-through' : ''" class="font-light">
{{ isPlanned ? transaction.category.icon : '' }} {{
transaction.category.name transaction.category.name
}} | }} |
{{ formatDate(transaction.date) }}</p> {{ formatDate(transaction.date) }}</p>
@@ -128,13 +133,18 @@ onMounted(async () => {
</div> </div>
</button> </button>
<TransactionEditDrawer v-if="drawerOpened" :visible="drawerOpened" :expenseCategories="expenseCategories"
:incomeCategories="incomeCategories" :transaction="transaction"
:category-types="categoryTypes"
@transaction-updated="transactionUpdate"
@close-drawer="closeDrawer()"
/>
</div> </div>
<div>
<TransactionEditDrawer v-if="drawerOpened" :visible="drawerOpened" :expenseCategories="expenseCategories"
:incomeCategories="incomeCategories" :transaction="transaction"
:category-types="categoryTypes"
@transaction-updated="transactionUpdate"
@delete-transaction="transactionUpdate"
@create-transaction="transactionUpdate"
@close-drawer="closeDrawer()"
/>
</div>
</template> </template>
<style scoped> <style scoped>

View File

@@ -18,9 +18,9 @@
<div class="flex flex-col "> <div class="flex flex-col ">
<!-- {{ budget }}--> <!-- {{ budget }}-->
<h2 class="text-4xl font-bold">Бюджет {{ budget.name }} </h2> <h2 class="text-4xl font-bold">Бюджет {{ budget.name }} </h2>
<!-- <div class="flex flex-row gap-2 text-xl">{{ formatDate(budget.dateFrom) }} - --> <div class="flex flex-row gap-2 text-xl">{{ formatDate(budget.dateFrom) }} -
<!-- {{ formatDate(budget.dateTo) }}--> {{ formatDate(budget.dateTo) }}
<!-- </div> --> </div>
</div> </div>
<div class="flex flex-col gap-2"> <div class="flex flex-col gap-2">
<!-- Аналитика и плановые доходы/расходы --> <!-- Аналитика и плановые доходы/расходы -->
@@ -49,7 +49,8 @@
<button class="grid grid-cols-2 gap-5 items-center w-full" @click="detailedShowed = !detailedShowed"> <button class="grid grid-cols-2 gap-5 items-center w-full" @click="detailedShowed = !detailedShowed">
<div class="flex flex-col items-center font-bold "> <div class="flex flex-col items-center font-bold ">
<h4 class="text-lg font-bold">Поступления</h4> <h4 class="text-lg font-bold">Поступления</h4>
<div class="font-light bg-gray-100 p-1 rounded-lg box-shadow-inner w-full text-center">
<div class="font-bold bg-gray-100 p-1 rounded-lg box-shadow-inner w-full text-center">
+{{ formatAmount(totalIncomes) }} +{{ formatAmount(totalIncomes) }}
</div> </div>
@@ -57,8 +58,8 @@
</div> </div>
<div class="flex flex-col items-center "> <div class="flex flex-col items-center ">
<h4 class="text-lg font-bold ">Расходы</h4> <h4 class="text-lg font-bold ">Расходы</h4>
<div class="font-light bg-gray-100 p-1 rounded-lg box-shadow-inner w-full text-center"> <div class="font-bold bg-gray-100 p-1 rounded-lg box-shadow-inner w-full text-center" :class="totalExpenses > totalIncomes ? ' text-red-700' : ''">
-{{ formatAmount(totalExpenses) }} -{{ formatAmount(totalExpenses) }} ({{formatAmount(totalExpenses- totalIncomes)}})
</div> </div>
</div> </div>
@@ -107,7 +108,7 @@
</div> </div>
<div class="flex flex-col items-center "> <div class="flex flex-col items-center ">
<span class="text-sm lg:text-base">Сбережения</span> <span class="text-sm lg:text-base">Сбережения</span>
<div class="font-light bg-gray-100 p-1 rounded-lg box-shadow-inner w-full text-center"> <div class="font-light bg-gray-100 p-1 rounded-lg box-shadow-inner w-full text-center" :class="savingRatio < 30 ? '!font-bold text-red-700' : ''">
{{ savingRatio.toFixed(0) }} % {{ savingRatio.toFixed(0) }} %
</div> </div>
</div> </div>
@@ -133,21 +134,26 @@
</div> </div>
<div class=" h-full overflow-y-auto gap-4 flex-col row-span-6 hidden lg:flex"> <div class=" h-full overflow-y-auto gap-4 flex-col row-span-6 hidden lg:flex">
<div class="flex flex-row "> <div class="flex flex-row gap-4">
<h3 class="text-2xl font-bold">Транзакции</h3> <h3 class="text-2xl font-bold">Транзакции</h3>
<button @click="openDrawer('INSTANT', 'EXPENSE')">
<!-- <i class="pi pi-plus-circle text-green-500" style="font-size: 1rem;"/>-->
<span class="font-light text-sm">+ Добавить</span>
</button>
</div> </div>
<div class=" flex gap-2 overflow-x-auto "> <div class=" flex gap-2 overflow-x-auto ">
<button v-for="categorySum in transactionCategoriesSums" <button v-for="categorySum in transactionCategoriesSums"
class="rounded-xl border p-1 bg-white border-gray-300 mb-2 min-w-fit px-2"> class="rounded-xl border p-1 bg-white border-gray-300 mb-2 min-w-fit px-2">
<p> <span class="text-sm font-bold">{{ categorySum.category.name }}</span>: {{ categorySum.sum }} </p> <p><span class="text-sm font-bold">{{ categorySum.category.name }}</span>: {{ categorySum.sum }} </p>
</button> </button>
</div> </div>
<div class="grid grid-cols-1 gap-4 max-h-tlist overflow-y-auto pe-2"> <div class="grid grid-cols-1 gap-4 max-h-tlist overflow-y-auto pe-2">
<BudgetTransactionView v-for="transaction in transactions" :key="transaction.id" <BudgetTransactionView v-for="transaction in transactions" :key="transaction.id"
:transaction="transaction" :transaction="transaction"
:is-list="true" class="" :is-list="true"
@transaction-updated="updateTransactions"
/> />
</div> </div>
</div> </div>
@@ -158,9 +164,12 @@
<div class="card p-4 shadow-lg rounded-lg col-span-1 h-fit"> <div class="card p-4 shadow-lg rounded-lg col-span-1 h-fit">
<!-- Планируемые доходы --> <!-- Планируемые доходы -->
<div> <div>
<div class="flex flex-row gap-4 items-center"> <div class="flex flex-row gap-4 items-center mb-4">
<h3 class="text-xl font-bold text-green-500 mb-4 ">Плановые поступления</h3> <h3 class="text-xl font-bold text-green-500 ">Плановые поступления</h3>
<!-- <Button icon="pi pi-plus" rounded outlined size="small"/>--> <button @click="openDrawer('PLANNED', 'INCOME')">
<!-- <i class="pi pi-plus-circle text-green-500" style="font-size: 1rem;"/>-->
<span class="font-light text-sm">+ Добавить</span>
</button>
</div> </div>
<div class="grid grid-cols-2 mb-2"> <div class="grid grid-cols-2 mb-2">
<div class="font-bold bg-gray-100 p-1 rounded-lg box-shadow-inner w-full text-center"> <div class="font-bold bg-gray-100 p-1 rounded-lg box-shadow-inner w-full text-center">
@@ -185,7 +194,13 @@
<div class="card p-4 shadow-lg rounded-lg col-span-1 h-fit"> <div class="card p-4 shadow-lg rounded-lg col-span-1 h-fit">
<!-- Планируемые расходы --> <!-- Планируемые расходы -->
<div class> <div class>
<h3 class="text-xl font-bold text-red-500 mb-4">Плановые расходы</h3> <div class="flex flex-row gap-4 items-center mb-4">
<h3 class="text-xl font-bold text-red-500">Плановые расходы</h3>
<button @click="openDrawer('PLANNED', 'EXPENSE')">
<!-- <i class="pi pi-plus-circle text-green-500" style="font-size: 1rem;"/>-->
<span class="font-light text-sm">+ Добавить</span>
</button>
</div>
<div class="grid grid-cols-2 mb-2"> <div class="grid grid-cols-2 mb-2">
<div class="font-bold bg-gray-100 p-1 rounded-lg box-shadow-inner w-full text-center"> <div class="font-bold bg-gray-100 p-1 rounded-lg box-shadow-inner w-full text-center">
{{ formatAmount(totalPlannedExpenses) }} {{ formatAmount(totalPlannedExpenses) }}
@@ -219,19 +234,25 @@
</div> </div>
<div class=" h-full overflow-y-auto gap-4 flex-col row-span-6 lg:hidden "> <div class=" h-full overflow-y-auto gap-4 flex-col row-span-6 lg:hidden ">
<div class="flex flex-row "> <div class="flex flex-row ">
<h3 class="text-2xl font-bold">Транзакций</h3> <h3 class="text-2xl font-bold">Транзакции</h3>
<button @click="openDrawer('INSTANT', 'EXPENSE')">
<!-- <i class="pi pi-plus-circle text-green-500" style="font-size: 1rem;"/>-->
<span class="font-light text-sm">+ Добавить</span>
</button>
</div> </div>
<div class=" flex gap-2"> <div class=" flex gap-2">
<button v-for="categorySum in transactionCategoriesSums" <button v-for="categorySum in transactionCategoriesSums"
class="rounded-xl border p-1 bg-white border-gray-300 mb-2 min-w-fit px-2"> class="rounded-xl border p-1 bg-white border-gray-300 mb-2 min-w-fit px-2">
<p> <span class="text-sm font-bold">{{ categorySum.category.name }}</span>: {{ categorySum.sum }} </p> <p><span class="text-sm font-bold">{{ categorySum.category.name }}</span>: {{ categorySum.sum }} </p>
</button> </button>
</div> </div>
<div class="grid grid-cols-1 gap-4 max-h-tlist overflow-y-auto pe-2"> <div class="grid grid-cols-1 gap-4 max-h-tlist overflow-y-auto pe-2">
<BudgetTransactionView v-for="transaction in transactions" :key="transaction.id" <BudgetTransactionView v-for="transaction in transactions" :key="transaction.id"
:transaction="transaction" :transaction="transaction"
:is-list="true" class="" :is-list="true"
@transaction-updated="updateTransactions"
/> />
</div> </div>
</div> </div>
@@ -240,7 +261,18 @@
</div> </div>
</div> </div>
<TransactionEditDrawer v-if="drawerOpened" :visible="drawerOpened"
:transaction-type="transactionType"
:category-type="categoryType"
:transactions="transactions.slice(0,3)"
@transaction-updated="updateTransactions"
@delete-transaction="updateTransactions"
@create-transaction="updateTransactions"
@close-drawer="closeDrawer"
/>
</div> </div>
</template> </template>
@@ -256,7 +288,7 @@ import {
} from "@/services/budgetsService"; } from "@/services/budgetsService";
import {Budget, BudgetCategory, BudgetInfo} from "@/models/Budget"; import {Budget, BudgetCategory, BudgetInfo} from "@/models/Budget";
import {useRoute} from "vue-router"; import {useRoute} from "vue-router";
import {formatAmount} from "@/utils/utils"; import {formatAmount, formatDate} from "@/utils/utils";
import ProgressBar from "primevue/progressbar"; import ProgressBar from "primevue/progressbar";
import ProgressSpinner from "primevue/progressspinner"; import ProgressSpinner from "primevue/progressspinner";
import BudgetCategoryView from "@/components/budgets/BudgetCategoryView.vue"; import BudgetCategoryView from "@/components/budgets/BudgetCategoryView.vue";
@@ -267,6 +299,7 @@ import LoadingView from "@/components/LoadingView.vue";
import ChartDataLabels from 'chartjs-plugin-datalabels'; import ChartDataLabels from 'chartjs-plugin-datalabels';
import {Chart as ChartJS} from 'chart.js/auto'; import {Chart as ChartJS} from 'chart.js/auto';
import SelectButton from "primevue/selectbutton"; import SelectButton from "primevue/selectbutton";
import TransactionEditDrawer from "@/components/budgets/TransactionEditDrawer.vue";
// Зарегистрируем плагин // Зарегистрируем плагин
ChartJS.register(ChartDataLabels); ChartJS.register(ChartDataLabels);
@@ -334,7 +367,26 @@ const totalSaving = computed(() => {
return value return value
}) })
// const drawerOpened = ref(false)
const transactionType = ref('')
const categoryType = ref('')
const openDrawer = (selectedTransactionType = null, selectedCategoryType = null) => {
if (selectedTransactionType && selectedCategoryType) {
transactionType.value = selectedTransactionType;
categoryType.value = selectedCategoryType;
} else if (selectedTransactionType) {
transactionType.value = selectedTransactionType;
categoryType.value = 'EXPENSE'
}
drawerOpened.value = true;
}
const closeDrawer = async () => {
drawerOpened.value = false;
// await updateTransactions()
}
const dailyRatio = computed(() => { const dailyRatio = computed(() => {
const value = (totalExpenses.value - totalLoans.value - totalSaving.value) / totalExpenses.value const value = (totalExpenses.value - totalLoans.value - totalSaving.value) / totalExpenses.value
@@ -384,15 +436,12 @@ const fetchPlannedExpenses = async () => {
} }
const transactions = ref<Transaction[]>([]) const transactions = ref<Transaction[]>([])
const fetchBudgetTransactions = async () => { const fetchBudgetTransactions = async () => {
transactions.value = await getBudgetTransactions(route.params.id, 'INSTANT') transactions.value = await getBudgetTransactions(route.params.id, 'INSTANT')
updateLoading.value = false updateLoading.value = false
} }
const updateTransactions = async () => { const updateTransactions = async () => {
await Promise.all([fetchPlannedIncomes(), fetchPlannedExpenses(), fetchBudgetCategories(), fetchBudgetTransactions()])
await Promise.all([fetchPlannedIncomes(), fetchPlannedExpenses(), fetchBudgetCategories(),])
} }
const categories = ref<BudgetCategory[]>([]) const categories = ref<BudgetCategory[]>([])
@@ -480,8 +529,9 @@ const incomesByPeriod = computed(() => {
let incomesUntil25 = 0 let incomesUntil25 = 0
let incomesFrom25 = 0 let incomesFrom25 = 0
plannedIncomes.value.forEach((i) => { plannedIncomes.value.forEach((i) => {
console.log(i.date)
if (i.date <= budget.value?.dateFrom && i.date <= twentyFour.value) { if (i.date >= budget.value?.dateFrom && i.date <= twentyFour.value) {
console.log(i.date)
incomesUntil25 += i.amount incomesUntil25 += i.amount
} else { } else {
incomesFrom25 += i.amount incomesFrom25 += i.amount

View File

@@ -15,11 +15,12 @@ import {
createTransactionRequest, createTransactionRequest,
getTransactionTypes, getTransactionTypes,
updateTransactionRequest, updateTransactionRequest,
deleteTransactionRequest deleteTransactionRequest, getTransactions
} from "@/services/transactionService"; } from "@/services/transactionService";
import {getCategories, getCategoryTypes} from "@/services/categoryService"; import {getCategories, getCategoryTypes} from "@/services/categoryService";
import {useToast} from "primevue/usetoast"; import {useToast} from "primevue/usetoast";
import LoadingView from "@/components/LoadingView.vue"; import LoadingView from "@/components/LoadingView.vue";
import BudgetTransactionView from "@/components/budgets/BudgetTransactionView.vue";
const props = defineProps({ const props = defineProps({
visible: { visible: {
@@ -37,6 +38,10 @@ const props = defineProps({
categoryType: { categoryType: {
type: String, type: String,
required: false required: false
},
transactions: {
type: Array as () => Array<Transaction>,
required: false
} }
}); });
@@ -247,6 +252,7 @@ const closeDrawer = () => emit('close-drawer');
const keyboardOpen = ref(false); const keyboardOpen = ref(false);
const isMobile = ref(false); const isMobile = ref(false);
const userAgent = ref(null); const userAgent = ref(null);
const transactions = ref<Transaction[]>(props.transactions);
// Мониторинг при монтировании // Мониторинг при монтировании
onMounted(async () => { onMounted(async () => {
loading.value = true; loading.value = true;
@@ -254,7 +260,12 @@ onMounted(async () => {
await fetchCategoriesAndTypes(); await fetchCategoriesAndTypes();
prepareData(); prepareData();
if (!transactions.value && !isEditing.value) {
console.log()
await getTransactions('INSTANT', 'EXPENSE' ).then(transactionsResponse => transactions.value = transactionsResponse.data);
transactions.value = transactions.value.slice(0,3)
console.log(transactions.value.slice(0,3))
}
loading.value = false; loading.value = false;
const deviceInfo = platform; const deviceInfo = platform;
isMobile.value = deviceInfo.os.family === 'iOS' || deviceInfo.os.family === 'Android'; isMobile.value = deviceInfo.os.family === 'iOS' || deviceInfo.os.family === 'Android';
@@ -267,7 +278,7 @@ onMounted(async () => {
<div class="card flex justify-center h-dvh"> <div class="card flex justify-center h-dvh">
<Drawer :visible="visible" :header="isEditing ? 'Edit Transaction' : 'Create Transaction'" :showCloseIcon="false" <Drawer :visible="visible" :header="isEditing ? 'Изменить транзакцию' : 'Создать транзакцию'" :showCloseIcon="false"
position="right" @hide="closeDrawer" position="right" @hide="closeDrawer"
class="!w-128 "> class="!w-128 ">
<div v-if="result" class="absolute top-0 left-0 w-full h-full flex items-center justify-center z-50"> <div v-if="result" class="absolute top-0 left-0 w-full h-full flex items-center justify-center z-50">
@@ -363,13 +374,13 @@ onMounted(async () => {
@blur="keyboardOpen=false" @blur="keyboardOpen=false"
/> />
<label for="amount" class="">Amount</label> <label for="amount" class="">Сумма</label>
</FloatLabel> </FloatLabel>
<!-- Comment Input --> <!-- Comment Input -->
<FloatLabel variant="on" class="w-full"> <FloatLabel variant="on" class="w-full">
<label for="comment">Comment</label> <label for="comment">Комментарий</label>
<InputText class="w-full" <InputText class="w-full"
:invalid="!editedTransaction.comment" :invalid="!editedTransaction.comment"
id="comment" id="comment"
@@ -384,7 +395,7 @@ onMounted(async () => {
<!-- Date Picker --> <!-- Date Picker -->
<div class="field col-12 gap-0"> <div class="field col-12 gap-0">
<FloatLabel variant="on"> <FloatLabel variant="on">
<label for="date">Date </label> <label for="date">Дата</label>
<DatePicker class="w-full" <DatePicker class="w-full"
inline inline
@@ -401,18 +412,17 @@ onMounted(async () => {
</FloatLabel> </FloatLabel>
</div> </div>
<div>
<BudgetTransactionView v-if="!isEditing && transactions" v-for="transaction in transactions" :is-list="true"
:transaction="transaction"/>
</div>
<!-- Amount Input -->
<!-- Buttons -->
{{ keyboardOpen }}
<div class="fixed col-12 flex justify-content-end gap-4 bottom-8"> <div class="fixed col-12 flex justify-content-end gap-4 bottom-8">
<Button label="Save" icon="pi pi-check" class="p-button-success" <Button label="Сохранить" icon="pi pi-check" class="p-button-success"
@click="isEditing ? updateTransaction() : createTransaction()"/> @click="isEditing ? updateTransaction() : createTransaction()"/>
<Button label="Cancel" icon="pi pi-times" class="p-button-secondary " @click="closeDrawer"/> <Button label="Отмена" icon="pi pi-times" class="p-button-secondary " @click="closeDrawer"/>
<Button v-if="isEditing" label="Delete" icon="pi pi-times" class="p-button-success" severity="danger" <Button v-if="isEditing" label="Удалить" icon="pi pi-times" class="p-button-success" severity="danger"
@click="deleteTransaction"/> @click="deleteTransaction"/>
</div> </div>

View File

@@ -28,7 +28,7 @@ export const getBudgetTransactions = async (budgetId, transactionType, categoryT
let url = `/budgets/${budgetId}/transactions` let url = `/budgets/${budgetId}/transactions`
if (transactionType && !categoryType) { if (transactionType && !categoryType) {
url += '/?type=' + transactionType url += '?type=' + transactionType
} }
if (transactionType && categoryType) { if (transactionType && categoryType) {
url += '/'+transactionType+'/'+categoryType url += '/'+transactionType+'/'+categoryType

View File

@@ -9,7 +9,7 @@ export const getCategories = async (type = null) => {
}; };
export const getCategoryTypes = async () => { export const getCategoryTypes = async () => {
return await apiClient.get('/categories/types/'); return await apiClient.get('/categories/types');
} }
export const createCategory = async (category: Category) => { export const createCategory = async (category: Category) => {

View File

@@ -36,7 +36,7 @@ export const createTransactionRequest = async (transaction: Transaction) => {
export const updateTransactionRequest = async (transaction: Transaction) => { export const updateTransactionRequest = async (transaction: Transaction) => {
const id = transaction.id const id = transaction.id
// transaction.date = format(transaction.date, 'yyyy-MM-dd') transaction.date = format(transaction.date, 'yyyy-MM-dd')
const response = await apiClient.put(`/transactions/${id}`, transaction); const response = await apiClient.put(`/transactions/${id}`, transaction);
transaction = response.data transaction = response.data
transaction.date = new Date(transaction.date); transaction.date = new Date(transaction.date);
@@ -44,10 +44,20 @@ export const updateTransactionRequest = async (transaction: Transaction) => {
return transaction return transaction
}; };
export const setTransactionDoneRequest = async (transaction: Transaction) => {
const id = transaction.id
// transaction.date = format(transaction.date, 'yyyy-MM-dd')
const response = await apiClient.put(`/transactions/${id}/done`, transaction);
transaction = response.data
transaction.date = new Date(transaction.date);
return transaction
};
export const deleteTransactionRequest = async (id: number) => { export const deleteTransactionRequest = async (id: number) => {
return await apiClient.delete(`/transactions/${id}`); return await apiClient.delete(`/transactions/${id}`);
}; };
export const getTransactionTypes = async () => { export const getTransactionTypes = async () => {
return await apiClient.get('/transactions/types/'); return await apiClient.get('/transactions/types');
} }