import type { LocationQuery } from 'vue-router' import { t } from '@/i18n' import { DEFAULT_PAGE_SIZE, PAGE_SIZES, firstQueryValue, parsePositiveInteger, } from '@/lib/pageQuery' export const ENTRY_SORT_FIELDS = ['id', 'created_at', 'updated_at'] as const export type EntrySortField = (typeof ENTRY_SORT_FIELDS)[number] export type EntrySortDirection = 'asc' | 'desc' export const DEFAULT_ENTRY_SORT = 'updated_at:desc' export interface EntryListQuery { page: number size: number q: string sort: string } const SORT_PATTERN = new RegExp(`^(${ENTRY_SORT_FIELDS.join('|')}):(asc|desc)$`) export function parseEntryQuery(query: LocationQuery): EntryListQuery { const size = parsePositiveInteger(firstQueryValue(query.size)) const sort = firstQueryValue(query.sort) return { page: parsePositiveInteger(firstQueryValue(query.page)) ?? 1, size: size !== null && PAGE_SIZES.includes(size) ? size : DEFAULT_PAGE_SIZE, q: '', sort: SORT_PATTERN.test(sort) ? sort : DEFAULT_ENTRY_SORT, } } export function toEntryRouteQuery(query: EntryListQuery) { const route: Record = {} if (query.size !== DEFAULT_PAGE_SIZE) { route.size = String(query.size) } if (query.sort !== DEFAULT_ENTRY_SORT) { route.sort = query.sort } if (query.page !== 1) { route.page = String(query.page) } return route } export function sameEntryQuery(left: EntryListQuery, right: EntryListQuery) { return left.page === right.page && left.size === right.size && left.sort === right.sort } export function sortParts(sort: string) { const [field, direction] = sort.split(':') as [EntrySortField, EntrySortDirection] return { field, direction } } export function withSortField(sort: string, field: EntrySortField) { return `${field}:${sortParts(sort).direction}` } export function withOppositeDirection(sort: string) { const { field, direction } = sortParts(sort) return `${field}:${direction === 'asc' ? 'desc' : 'asc'}` } export function sortFieldLabel(field: EntrySortField) { if (field === 'id') { return t('ID') } return field === 'created_at' ? t('Created') : t('Last updated') } export function sortDirectionLabel(sort: string) { return sortParts(sort).direction === 'asc' ? t('Sort descending') : t('Sort ascending') } export function entryCaption(name: string, sort: string) { const { field, direction } = sortParts(sort) if (sort === DEFAULT_ENTRY_SORT) { return t('{0}, sorted by last updated, newest first', [name]) } const column = { id: t('id'), created_at: t('created'), updated_at: t('updated') }[field] return t('{0}, sorted by {1}, {2}', [ name, column, direction === 'desc' ? t('descending') : t('ascending'), ]) }