1
0

Исправления фронта

Множество оптимизаций по фронту
This commit is contained in:
2026-01-16 10:15:33 +07:00
parent cb075e56be
commit 3258fa9137
30 changed files with 1797 additions and 2584 deletions

View File

@@ -0,0 +1,166 @@
/**
* Composable для форматирования дат
* Автоматически использует таймзону сервера из serverSettings
*
* Использование:
* import { useDateFormat } from '@/composables/useDateFormat'
* const { formatShort, formatRelative, getDaysLeftText } = useDateFormat()
*/
import { serverSettings } from '../api'
// Константы месяцев
const MONTHS_SHORT = ['янв', 'фев', 'мар', 'апр', 'мая', 'июн', 'июл', 'авг', 'сен', 'окт', 'ноя', 'дек']
const MONTHS_FULL = ['января', 'февраля', 'марта', 'апреля', 'мая', 'июня', 'июля', 'августа', 'сентября', 'октября', 'ноября', 'декабря']
// Для дат типа "1 май" (именительный падеж)
const MONTHS_SHORT_NOM = ['янв', 'фев', 'мар', 'апр', 'май', 'июн', 'июл', 'авг', 'сен', 'окт', 'ноя', 'дек']
export function useDateFormat() {
/**
* Парсинг даты с учётом таймзоны сервера
*/
const parseDate = (dateStr) => {
if (!dateStr) return null
return serverSettings.parseDate(dateStr)
}
/**
* Короткий формат: "1 янв 2025"
*/
const formatShort = (dateStr) => {
const date = parseDate(dateStr)
if (!date) return ''
const day = date.getDate()
return `${day} ${MONTHS_SHORT_NOM[date.getMonth()]} ${date.getFullYear()}`
}
/**
* Полный формат: "1 января 2025"
*/
const formatFull = (dateStr) => {
const date = parseDate(dateStr)
if (!date) return ''
const day = date.getDate()
return `${day} ${MONTHS_FULL[date.getMonth()]} ${date.getFullYear()}`
}
/**
* С временем: "01 янв 2025, 14:30"
*/
const formatDateTime = (dateStr) => {
const date = parseDate(dateStr)
if (!date) return '—'
const day = date.getDate().toString().padStart(2, '0')
const year = date.getFullYear()
const hours = date.getHours().toString().padStart(2, '0')
const minutes = date.getMinutes().toString().padStart(2, '0')
return `${day} ${MONTHS_SHORT[date.getMonth()]} ${year}, ${hours}:${minutes}`
}
/**
* Расчёт дней между датами
* Положительное число = дней осталось, отрицательное = просрочено
*/
const getDaysUntil = (dateStr) => {
const target = parseDate(dateStr)
if (!target) return null
const today = new Date()
today.setHours(0, 0, 0, 0)
target.setHours(0, 0, 0, 0)
return Math.round((target - today) / (1000 * 60 * 60 * 24))
}
/**
* Расчёт дней назад
*/
const getDaysAgo = (dateStr) => {
const days = getDaysUntil(dateStr)
return days !== null ? -days : null
}
/**
* Текст для дедлайна: "Сегодня", "Завтра", "Осталось: 5 дн.", "Просрочено: 3 дн."
*/
const getDaysLeftText = (dateStr) => {
const days = getDaysUntil(dateStr)
if (days === null) return ''
if (days < 0) return `Просрочено: ${Math.abs(days)} дн.`
if (days === 0) return 'Сегодня'
if (days === 1) return 'Завтра'
return `Осталось: ${days} дн.`
}
/**
* Статус дедлайна для CSS классов: 'overdue', 'soon', ''
*/
const getDueDateStatus = (dateStr) => {
const days = getDaysUntil(dateStr)
if (days === null) return ''
if (days < 0) return 'overdue'
if (days <= 2) return 'soon'
return ''
}
/**
* Относительная дата в прошлом: "Сегодня", "Вчера", "3 дня назад", или полная дата
*/
const formatRelative = (dateStr) => {
if (!dateStr) return ''
const daysAgo = getDaysAgo(dateStr)
if (daysAgo === null) return ''
if (daysAgo === 0) return 'Сегодня'
if (daysAgo === 1) return 'Вчера'
if (daysAgo >= 2 && daysAgo <= 4) return `${daysAgo} дня назад`
if (daysAgo >= 5 && daysAgo <= 14) return `${daysAgo} дней назад`
return formatShort(dateStr)
}
/**
* Время назад для комментариев: "только что", "5 мин. назад", "2 ч. назад", "3 дн. назад"
* Для старых дат — "1 янв 14:30"
*/
const formatTimeAgo = (dateStr) => {
const date = parseDate(dateStr)
if (!date) return ''
const now = new Date()
const diff = now - date
const minutes = Math.floor(diff / 60000)
const hours = Math.floor(diff / 3600000)
const days = Math.floor(diff / 86400000)
if (minutes < 1) return 'только что'
if (minutes < 60) return `${minutes} мин. назад`
if (hours < 24) return `${hours} ч. назад`
if (days < 7) return `${days} дн. назад`
const day = date.getDate()
const time = date.toLocaleTimeString('ru-RU', { hour: '2-digit', minute: '2-digit' })
return `${day} ${MONTHS_SHORT[date.getMonth()]} ${time}`
}
return {
// Константы
MONTHS_SHORT,
MONTHS_FULL,
// Парсинг
parseDate,
// Форматирование
formatShort,
formatFull,
formatDateTime,
formatRelative,
formatTimeAgo,
// Расчёты
getDaysUntil,
getDaysAgo,
getDaysLeftText,
getDueDateStatus
}
}