Files
ulitka-app/src/stores/issue.ts
T
vadim 0fe2c70848
Gitea Actions Demo / Deploy (push) Successful in 34s
calendar
2026-10-12 11:47:42 +03:00

133 lines
3.7 KiB
TypeScript

import { defineStore } from 'pinia'
import { ref } from 'vue'
import {
type CreateIssueInput,
type Issue,
type DailyIssueStats,
itemCreate,
itemDailyStat,
itemsCalendar,
itemDelete,
itemGetByKey,
itemsList,
itemStat,
itemUpdate,
type IssueStat,
type Meta,
type UpdateIssueInput,
} from '@/api/issue.api.ts'
export const useIssueStore = defineStore('item', () => {
const issues = ref<Issue[]>([])
const stats = ref<IssueStat>()
const dailyStats = ref<DailyIssueStats>()
const error = ref<string | null>(null)
const lastMeta = ref<Meta>({
page: 1,
totalCount: 0,
totalPages: 0,
})
async function list(params: {
page: number
limit: number
text?: string | null
status?: string | string[] | null
assigneeId?: string | null
projectId?: string | null
hasDueDate?: boolean
}) {
try {
const res = await itemsList(params)
issues.value = res.list
return res
} catch (e) {
error.value = e instanceof Error ? e.message : 'error get list of items'
return { list: [], meta: lastMeta.value }
}
}
async function calendar(params: { from: string; to: string; projectId?: string | null }) {
try {
return await itemsCalendar(params)
} catch (e) {
error.value = e instanceof Error ? e.message : 'error get calendar issues'
}
}
async function getByKey(ckey: string) {
try {
return await itemGetByKey(ckey)
} catch (e) {
error.value = e instanceof Error ? e.message : 'error get item by key'
}
}
async function create(input: CreateIssueInput) {
try {
return await itemCreate(input)
} catch (e) {
error.value = e instanceof Error ? e.message : 'error creating issue'
}
}
async function update(id: number, input: UpdateIssueInput) {
try {
return await itemUpdate(id, input)
} catch (e) {
error.value = e instanceof Error ? e.message : 'error updating issue'
}
}
async function remove(id: number) {
try {
return await itemDelete(id)
} catch (e) {
error.value = e instanceof Error ? e.message : 'error deleting issue'
return false
}
}
async function getStat(projectId?: string | null): Promise<IssueStat | undefined> {
try {
stats.value = await itemStat(projectId ?? undefined)
return stats.value
} catch (e) {
error.value = e instanceof Error ? e.message : 'error getting issue stat'
}
}
let dailyStatsRequestId = 0
/** Stats for the last `days` days including today, in the user's local time zone */
async function getDailyStat(projectId?: string | null, days = 30): Promise<DailyIssueStats | undefined> {
// Ignore responses that arrive after the project or period has changed again
const requestId = ++dailyStatsRequestId
try {
const res = await itemDailyStat({
projectId: projectId ?? undefined,
from: localDateDaysAgo(days - 1),
// Day boundaries are computed on the backend in the user's local time zone; `to` defaults to today there
timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone,
})
if (requestId !== dailyStatsRequestId) return
dailyStats.value = res
return dailyStats.value
} catch (e) {
error.value = e instanceof Error ? e.message : 'error getting daily issue stat'
}
}
return { stats, dailyStats, list, calendar, getByKey, create, update, remove, getStat, getDailyStat }
})
/** Local YYYY-MM-DD `days` days before today */
function localDateDaysAgo(days: number): string {
const date = new Date()
date.setDate(date.getDate() - days)
const pad = (value: number) => String(value).padStart(2, '0')
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`
}