1
0
Files
TaskBoard/front_vue/src/composables/useDateFormat.js
Falknat 3258fa9137 Исправления фронта
Множество оптимизаций по фронту
2026-01-16 10:15:33 +07:00

167 lines
5.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 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
}
}