2022-06-19 16:32:46 +02:00
|
|
|
import i18n from '@/i18n'
|
|
|
|
|
|
|
|
const { t, locale } = i18n.global
|
2022-02-19 07:47:54 +01:00
|
|
|
const GROUP_KEY_NONE = 'GROUP_KEY_NONE'
|
|
|
|
|
|
|
|
export function noop() {
|
|
|
|
return {
|
|
|
|
compareFn: null,
|
|
|
|
groupKeyFn: (item) => GROUP_KEY_NONE
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-04 13:54:01 +02:00
|
|
|
export function byName(field, keepSortOrder = false, defaultValue = '_') {
|
2022-02-19 07:47:54 +01:00
|
|
|
return {
|
2023-06-04 13:54:01 +02:00
|
|
|
compareFn: keepSortOrder
|
|
|
|
? null
|
|
|
|
: (a, b) => {
|
|
|
|
const fieldA = a[field] || defaultValue
|
|
|
|
const fieldB = b[field] || defaultValue
|
|
|
|
return fieldA.localeCompare(fieldB, locale.value)
|
|
|
|
},
|
2022-02-19 07:47:54 +01:00
|
|
|
|
|
|
|
groupKeyFn: (item) => {
|
2023-06-04 13:54:01 +02:00
|
|
|
const value = (item[field] || defaultValue).charAt(0)
|
|
|
|
if (value.match(/\p{Letter}/gu)) {
|
|
|
|
return value.toUpperCase()
|
|
|
|
} else if (value.match(/\p{Number}/gu)) {
|
|
|
|
return '#'
|
|
|
|
}
|
2023-11-24 15:48:29 +01:00
|
|
|
return '⌘'
|
2022-02-19 07:47:54 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-23 23:19:55 +01:00
|
|
|
export function byRating(field, { direction = 'asc', defaultValue = 0 }) {
|
|
|
|
return {
|
|
|
|
compareFn: (a, b) => {
|
|
|
|
const fieldA = a[field] || defaultValue
|
|
|
|
const fieldB = b[field] || defaultValue
|
2023-04-04 08:42:46 +02:00
|
|
|
const result = fieldA - fieldB
|
2023-03-23 23:19:55 +01:00
|
|
|
return direction === 'asc' ? result : result * -1
|
|
|
|
},
|
|
|
|
|
|
|
|
groupKeyFn: (item) => {
|
|
|
|
const fieldValue = item[field] || defaultValue
|
|
|
|
return Math.floor(fieldValue / 10)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-08 10:12:03 +01:00
|
|
|
export function byMedium(field, direction = 'asc', defaultValue = 1) {
|
|
|
|
return {
|
|
|
|
compareFn: (a, b) => {
|
|
|
|
const fieldA = a[field] || defaultValue
|
|
|
|
const fieldB = b[field] || defaultValue
|
|
|
|
const result = fieldA - fieldB
|
|
|
|
return direction === 'asc' ? result : result * -1
|
|
|
|
},
|
|
|
|
|
|
|
|
groupKeyFn: (item) => {
|
|
|
|
return item[field] || defaultValue
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-19 07:47:54 +01:00
|
|
|
export function byYear(field, { direction = 'asc', defaultValue = '0000' }) {
|
|
|
|
return {
|
|
|
|
compareFn: (a, b) => {
|
|
|
|
const fieldA = a[field] || defaultValue
|
|
|
|
const fieldB = b[field] || defaultValue
|
2022-06-19 16:32:46 +02:00
|
|
|
const result = fieldA.localeCompare(fieldB, locale.value)
|
2022-02-19 07:47:54 +01:00
|
|
|
return direction === 'asc' ? result : result * -1
|
|
|
|
},
|
|
|
|
|
|
|
|
groupKeyFn: (item) => {
|
|
|
|
const fieldValue = item[field] || defaultValue
|
|
|
|
return fieldValue.substring(0, 4)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export function byDateSinceToday(field, defaultValue = '0000') {
|
|
|
|
return {
|
|
|
|
compareFn: (a, b) => {
|
|
|
|
const fieldA = a[field] || defaultValue
|
|
|
|
const fieldB = b[field] || defaultValue
|
2022-06-19 16:32:46 +02:00
|
|
|
return fieldB.localeCompare(fieldA, locale.value)
|
2022-02-19 07:47:54 +01:00
|
|
|
},
|
|
|
|
|
|
|
|
groupKeyFn: (item) => {
|
|
|
|
const fieldValue = item[field]
|
|
|
|
if (!fieldValue) {
|
|
|
|
return defaultValue
|
|
|
|
}
|
|
|
|
const diff = new Date().getTime() - new Date(fieldValue).getTime()
|
|
|
|
if (diff < 86400000) {
|
|
|
|
// 24h
|
2022-06-19 16:32:46 +02:00
|
|
|
return t('group-by-list.today')
|
2022-02-19 07:47:54 +01:00
|
|
|
} else if (diff < 604800000) {
|
|
|
|
// 7 days
|
2022-06-19 16:32:46 +02:00
|
|
|
return t('group-by-list.last-week')
|
2022-02-19 07:47:54 +01:00
|
|
|
} else if (diff < 2592000000) {
|
|
|
|
// 30 days
|
2022-06-19 16:32:46 +02:00
|
|
|
return t('group-by-list.last-month')
|
2022-02-19 07:47:54 +01:00
|
|
|
}
|
|
|
|
return fieldValue.substring(0, 4)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-22 19:32:11 +01:00
|
|
|
export class GroupedList {
|
2022-02-19 07:47:54 +01:00
|
|
|
constructor({ items = [], total = 0, offset = 0, limit = -1 } = {}) {
|
|
|
|
this.items = items
|
|
|
|
this.total = total
|
|
|
|
this.offset = offset
|
|
|
|
this.limit = limit
|
|
|
|
this.count = items.length
|
2024-02-27 16:27:37 +01:00
|
|
|
this.indices = []
|
2022-02-19 07:47:54 +01:00
|
|
|
this.group(noop())
|
|
|
|
}
|
|
|
|
|
|
|
|
group(options, filterFns = []) {
|
2024-03-12 13:45:53 +01:00
|
|
|
const itemsFiltered = this.items.filter((item) =>
|
|
|
|
filterFns.every((fn) => fn(item))
|
|
|
|
)
|
2022-02-19 07:47:54 +01:00
|
|
|
this.count = itemsFiltered.length
|
|
|
|
// Sort item list
|
2023-11-24 15:56:04 +01:00
|
|
|
const itemsSorted = options.compareFn
|
2022-02-19 07:47:54 +01:00
|
|
|
? [...itemsFiltered].sort(options.compareFn)
|
|
|
|
: itemsFiltered
|
|
|
|
// Group item list
|
2024-03-12 13:45:53 +01:00
|
|
|
this.itemsGrouped = itemsSorted.reduce((map, item) => {
|
2022-02-19 07:47:54 +01:00
|
|
|
const groupKey = options.groupKeyFn(item)
|
2024-03-12 13:45:53 +01:00
|
|
|
map.set(groupKey, [...(map.get(groupKey) || []), item])
|
|
|
|
return map
|
|
|
|
}, new Map())
|
|
|
|
// Create index list
|
|
|
|
this.indices = Array.from(this.itemsGrouped.keys())
|
2022-02-19 07:47:54 +01:00
|
|
|
}
|
|
|
|
|
2023-12-12 21:20:41 +01:00
|
|
|
*generate() {
|
2024-03-12 13:45:53 +01:00
|
|
|
for (const [key, items] of this.itemsGrouped.entries()) {
|
2023-12-12 21:20:41 +01:00
|
|
|
if (key !== GROUP_KEY_NONE) {
|
|
|
|
yield {
|
|
|
|
groupKey: key,
|
|
|
|
itemId: key,
|
|
|
|
isItem: false,
|
|
|
|
item: {}
|
2023-11-24 15:48:29 +01:00
|
|
|
}
|
2023-12-12 21:20:41 +01:00
|
|
|
}
|
2024-03-12 13:45:53 +01:00
|
|
|
for (const item of items) {
|
2023-12-12 21:20:41 +01:00
|
|
|
yield {
|
|
|
|
groupKey: key,
|
|
|
|
itemId: item.id,
|
|
|
|
isItem: true,
|
|
|
|
item: item
|
2022-02-19 07:47:54 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-12-12 21:20:41 +01:00
|
|
|
|
|
|
|
[Symbol.iterator]() {
|
|
|
|
return this.generate()
|
|
|
|
}
|
2022-02-19 07:47:54 +01:00
|
|
|
}
|