fix tx isdone checkbox text size
This commit is contained in:
76
src/components/targets/TargetList.vue
Normal file
76
src/components/targets/TargetList.vue
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
|
||||||
|
import {onMounted, ref} from "vue";
|
||||||
|
import {Target} from "@/models/targets";
|
||||||
|
import {useRouter} from "vue-router";
|
||||||
|
import {useToolbarStore} from "@/stores/toolbar-store";
|
||||||
|
import {useSpaceStore} from "@/stores/spaceStore";
|
||||||
|
import {targetService} from "@/services/targets-service";
|
||||||
|
import {useToast} from "primevue/usetoast";
|
||||||
|
import {ProgressBar} from "primevue";
|
||||||
|
import {TargetTypeIcon, TargetTypeName} from "@/models/enums";
|
||||||
|
import {formatAmount} from "@/utils/utils";
|
||||||
|
|
||||||
|
const toast = useToast();
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
const toolbar = useToolbarStore()
|
||||||
|
const spaceStore = useSpaceStore()
|
||||||
|
|
||||||
|
const targets = ref<Target[]>([])
|
||||||
|
|
||||||
|
|
||||||
|
const fetchData = async () => {
|
||||||
|
try {
|
||||||
|
if (spaceStore.selectedSpaceId) {
|
||||||
|
targets.value = await targetService.fetchTargets(spaceStore.selectedSpaceId)
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e)
|
||||||
|
toast.add({
|
||||||
|
severity: 'error',
|
||||||
|
summary: 'Failed to fetch target list.',
|
||||||
|
detail: e.message
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
await fetchData()
|
||||||
|
toolbar.registerHandler('openTargetCreation', () => {
|
||||||
|
router.push('/targets/create')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="targets-list">
|
||||||
|
<div v-for="target in targets" class="card w-full">
|
||||||
|
<div class="flex flex-col items-start justify-items-start justify-start w-full px-4 pb-4">
|
||||||
|
<div class="flex flex-row items-center gap-2">
|
||||||
|
<span class="text-4xl ">{{ TargetTypeIcon[target.type] }}</span>
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<h2 class="text-2xl !font-semibold">{{ target.name }}</h2>
|
||||||
|
<span class="text-sm text-gray-200"> {{ target.description }} | {{ TargetTypeName[target.type] }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col w-full">
|
||||||
|
<div class="flex flex-row justify-between !w-full">
|
||||||
|
<span> {{formatAmount(target.currentAmount)}} ₽</span>
|
||||||
|
<span>{{formatAmount(target.amount)}} ₽</span>
|
||||||
|
</div>
|
||||||
|
<ProgressBar :value="((target.currentAmount / target.amount)*100).toFixed(0)" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.targets-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1.5rem;
|
||||||
|
padding-bottom: 2.5rem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -206,7 +206,9 @@ const deleteTransaction = async () => {
|
|||||||
if (spaceStore.selectedSpaceId && transactionId.value) {
|
if (spaceStore.selectedSpaceId && transactionId.value) {
|
||||||
await transactionService.deleteTransaction(spaceStore.selectedSpaceId, Number(transactionId.value))
|
await transactionService.deleteTransaction(spaceStore.selectedSpaceId, Number(transactionId.value))
|
||||||
await transactionStore.fetchTransactions(spaceStore.selectedSpaceId)
|
await transactionStore.fetchTransactions(spaceStore.selectedSpaceId)
|
||||||
await moveUser()
|
if (openMode && openMode === "from_bot") {
|
||||||
|
tgApp.close()
|
||||||
|
} else await moveUser()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ export enum TransactionType {
|
|||||||
INCOME = "INCOME",
|
INCOME = "INCOME",
|
||||||
EXPENSE = "EXPENSE",
|
EXPENSE = "EXPENSE",
|
||||||
}
|
}
|
||||||
|
|
||||||
export const TransactionTypeName: Record<TransactionType, string> = {
|
export const TransactionTypeName: Record<TransactionType, string> = {
|
||||||
[TransactionType.EXPENSE]: 'Расходы',
|
[TransactionType.EXPENSE]: 'Расходы',
|
||||||
[TransactionType.INCOME]: 'Поступления',
|
[TransactionType.INCOME]: 'Поступления',
|
||||||
@@ -30,9 +31,33 @@ export enum TransactionKind {
|
|||||||
PLANNING = "PLANNING",
|
PLANNING = "PLANNING",
|
||||||
INSTANT = "INSTANT",
|
INSTANT = "INSTANT",
|
||||||
}
|
}
|
||||||
|
|
||||||
export const TransactionKindName: Record<TransactionKind, string> = {
|
export const TransactionKindName: Record<TransactionKind, string> = {
|
||||||
[TransactionKind.INSTANT]: 'Текущие',
|
[TransactionKind.INSTANT]: 'Текущие',
|
||||||
[TransactionKind.PLANNING]: 'Плановые',
|
[TransactionKind.PLANNING]: 'Плановые',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export enum TargetType {
|
||||||
|
AUTO = "AUTO",
|
||||||
|
LEISURE = "LEISURE",
|
||||||
|
VACATION = "VACATION",
|
||||||
|
GOODS = "GOODS",
|
||||||
|
OTHER = "OTHER",
|
||||||
|
}
|
||||||
|
|
||||||
|
export const TargetTypeName: Record<TargetType, string> = {
|
||||||
|
[TargetType.AUTO]: 'Авто',
|
||||||
|
[TargetType.LEISURE]: 'Досуг',
|
||||||
|
[TargetType.VACATION]: 'Отпуск',
|
||||||
|
[TargetType.GOODS]: 'Покупка',
|
||||||
|
[TargetType.OTHER]: 'Другое'
|
||||||
|
}
|
||||||
|
export const TargetTypeIcon: Record<TargetType, string> = {
|
||||||
|
[TargetType.AUTO]: '🏎️',
|
||||||
|
[TargetType.LEISURE]: '💃',
|
||||||
|
[TargetType.VACATION]: '🏖',
|
||||||
|
[TargetType.GOODS]: '🛍️',
|
||||||
|
[TargetType.OTHER]: '💸'
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
63
src/models/targets.ts
Normal file
63
src/models/targets.ts
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
import {Transaction} from "@/models/transaction";
|
||||||
|
import {User} from "@/models/user";
|
||||||
|
import {TargetType} from "@/models/enums";
|
||||||
|
|
||||||
|
export interface Target {
|
||||||
|
id: number,
|
||||||
|
type: TargetType,
|
||||||
|
name: string,
|
||||||
|
description: string | null,
|
||||||
|
amount: number,
|
||||||
|
currentAmount: number,
|
||||||
|
date: Date | string,
|
||||||
|
components: TargetComponent[],
|
||||||
|
transactions: Transaction[],
|
||||||
|
createdBy: User,
|
||||||
|
createdAt: Date,
|
||||||
|
updatedBy: User | null,
|
||||||
|
updatedAt: Date | null,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export interface CreateTargetDTO {
|
||||||
|
type: TargetType,
|
||||||
|
name: string,
|
||||||
|
description: string | null,
|
||||||
|
amount: number,
|
||||||
|
date: Date | string,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UpdateTargetDTO {
|
||||||
|
type: TargetType,
|
||||||
|
name: string,
|
||||||
|
description: string | null,
|
||||||
|
amount: number,
|
||||||
|
date: Date | string,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export interface TargetComponent {
|
||||||
|
id: number,
|
||||||
|
name: string,
|
||||||
|
amount: number,
|
||||||
|
isDone: boolean,
|
||||||
|
date: Date | string,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export interface CreateTargetComponent {
|
||||||
|
name: string,
|
||||||
|
amount: number,
|
||||||
|
date: Date | string,
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UpdateTargetComponent {
|
||||||
|
name: string,
|
||||||
|
amount: number,
|
||||||
|
isDone: boolean,
|
||||||
|
date: Date | string,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -8,6 +8,7 @@ import RecurrentyCreateUpdate from "@/components/settings/RecurrentyCreateUpdate
|
|||||||
import TransactionList from "@/components/transactions/TransactionList.vue";
|
import TransactionList from "@/components/transactions/TransactionList.vue";
|
||||||
import LoginPage from "@/components/auth/LoginPage.vue";
|
import LoginPage from "@/components/auth/LoginPage.vue";
|
||||||
import TransactionCreateUpdate from "@/components/transactions/TransactionCreateUpdate.vue";
|
import TransactionCreateUpdate from "@/components/transactions/TransactionCreateUpdate.vue";
|
||||||
|
import TargetList from "@/components/targets/TargetList.vue";
|
||||||
|
|
||||||
// 📝 Расширяем тип меты роутов (типобезопасный toolbar, requiresAuth, guestOnly)
|
// 📝 Расширяем тип меты роутов (типобезопасный toolbar, requiresAuth, guestOnly)
|
||||||
declare module 'vue-router' {
|
declare module 'vue-router' {
|
||||||
@@ -32,6 +33,9 @@ export const enum RouteName {
|
|||||||
TransactionList = 'transaction-list',
|
TransactionList = 'transaction-list',
|
||||||
TransactionCreate = 'transaction-create',
|
TransactionCreate = 'transaction-create',
|
||||||
TransactionUpdate = 'transaction-update',
|
TransactionUpdate = 'transaction-update',
|
||||||
|
TargetList = 'target-list',
|
||||||
|
TargetCreate = 'target-create',
|
||||||
|
TargetUpdate = 'target-update',
|
||||||
SettingsList = 'settings-list',
|
SettingsList = 'settings-list',
|
||||||
CategoriesList = 'categories-list',
|
CategoriesList = 'categories-list',
|
||||||
CategoryCreate = 'category-create',
|
CategoryCreate = 'category-create',
|
||||||
@@ -45,7 +49,12 @@ export const enum RouteName {
|
|||||||
|
|
||||||
const routes: RouteRecordRaw[] = [
|
const routes: RouteRecordRaw[] = [
|
||||||
{path: '/login', name: RouteName.Login, component: LoginPage, meta: {requiresAuth: false, navStack: 'auth'}},
|
{path: '/login', name: RouteName.Login, component: LoginPage, meta: {requiresAuth: false, navStack: 'auth'}},
|
||||||
{path: '/', name: RouteName.Dashboard, component: DashboardView, meta: {requiresAuth: true, navStack: 'dashboard', title: "Home"}},
|
{
|
||||||
|
path: '/',
|
||||||
|
name: RouteName.Dashboard,
|
||||||
|
component: DashboardView,
|
||||||
|
meta: {requiresAuth: true, navStack: 'dashboard', title: "Home"}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/transactions',
|
path: '/transactions',
|
||||||
name: RouteName.TransactionList,
|
name: RouteName.TransactionList,
|
||||||
@@ -83,6 +92,45 @@ const routes: RouteRecordRaw[] = [
|
|||||||
title: "Edit transaction"
|
title: "Edit transaction"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
path: '/targets',
|
||||||
|
name: RouteName.TargetList,
|
||||||
|
component: TargetList,
|
||||||
|
meta: {
|
||||||
|
requiresAuth: true,
|
||||||
|
toolbar: ({spaceStore}: { spaceStore: ReturnType<typeof useSpaceStore> }) => [
|
||||||
|
|
||||||
|
{id: 'openTargetCreation', text: '', icon: 'pi pi-plus', onClickId: 'openTargetCreation'},
|
||||||
|
],
|
||||||
|
navStack: 'targets',
|
||||||
|
title: "Targets"
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// path: '/transactions/create', name: RouteName.TransactionCreate, component: TransactionCreateUpdate, meta: {
|
||||||
|
// requiresAuth: true,
|
||||||
|
// toolbar: ({spaceStore}: { spaceStore: ReturnType<typeof useSpaceStore> }) => [
|
||||||
|
// {id: 'createTransaction', text: '', icon: 'pi pi-save', onClickId: 'createTransaction'},
|
||||||
|
// ],
|
||||||
|
// navStack: 'transactions',
|
||||||
|
// title: "Create transaction"
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// path: '/transactions/:id/edit', name: RouteName.TransactionUpdate, component: TransactionCreateUpdate, meta: {
|
||||||
|
// requiresAuth: true,
|
||||||
|
// toolbar: ({spaceStore}: { spaceStore: ReturnType<typeof useSpaceStore> }) => [
|
||||||
|
//
|
||||||
|
// {id: 'deleteTransaction', text: '', icon: 'pi pi-trash', onClickId: 'deleteTransaction'},
|
||||||
|
// {id: 'updateTransaction', text: '', icon: 'pi pi-save', onClickId: 'updateTransaction'},
|
||||||
|
// ],
|
||||||
|
// navStack: 'settings',
|
||||||
|
// title: "Edit transaction"
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
|
||||||
{
|
{
|
||||||
path: '/settings',
|
path: '/settings',
|
||||||
name: RouteName.SettingsList,
|
name: RouteName.SettingsList,
|
||||||
|
|||||||
33
src/services/targets-service.ts
Normal file
33
src/services/targets-service.ts
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import {Target} from "@/models/targets";
|
||||||
|
import {TargetType} from "@/models/enums";
|
||||||
|
import {User} from "@/models/user";
|
||||||
|
|
||||||
|
async function fetchTargets(spaceId: number): Promise<Target[]> {
|
||||||
|
const targets = [];
|
||||||
|
for (var i = 0; i < 10; i++) {
|
||||||
|
const rand = Math.floor(Math.random() * 5);
|
||||||
|
const now = new Date();
|
||||||
|
const amount = Math.floor(Math.random() * 100000);
|
||||||
|
now.setDate(Math.floor(Math.random() * 30))
|
||||||
|
targets.push({
|
||||||
|
id: i,
|
||||||
|
type: rand == 1 ? TargetType.AUTO : rand == 2 ? TargetType.LEISURE : rand == 3 ? TargetType.VACATION : rand == 4 ? TargetType.GOODS : TargetType.OTHER,
|
||||||
|
name: `Target ${i}`,
|
||||||
|
description: `Target ${i} description`,
|
||||||
|
amount: amount,
|
||||||
|
currentAmount: Math.floor(Math.random() * amount),
|
||||||
|
date: now,
|
||||||
|
components: [],
|
||||||
|
transactions: [],
|
||||||
|
createdBy: {} as User,
|
||||||
|
createdAt: new Date(),
|
||||||
|
updatedBy: {} as User,
|
||||||
|
updatedAt: new Date(),
|
||||||
|
} as Target)
|
||||||
|
}
|
||||||
|
return targets;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const targetService = {
|
||||||
|
fetchTargets
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user