mirror of
https://github.com/bookorbit/bookorbit.git
synced 2026-11-03 00:11:37 -06:00
feat(books): add lens with query engine, filter builder, and icon picker
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
export type BookFileRef = {
|
||||
id: number
|
||||
format: string | null
|
||||
role: string
|
||||
}
|
||||
|
||||
export type BookCard = {
|
||||
id: number
|
||||
status: string
|
||||
title: string | null
|
||||
authors: string[]
|
||||
seriesName: string | null
|
||||
seriesIndex: number | null
|
||||
files: BookFileRef[]
|
||||
}
|
||||
|
||||
export type BooksPage = {
|
||||
items: BookCard[]
|
||||
total: number
|
||||
page: number
|
||||
size: number
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
export * from "./auth";
|
||||
export * from "./book";
|
||||
export * from "./library";
|
||||
export * from "./query";
|
||||
export * from "./reader-settings";
|
||||
export * from "./scanner";
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
export type RuleField =
|
||||
| 'title'
|
||||
| 'publisher'
|
||||
| 'language'
|
||||
| 'series'
|
||||
| 'seriesIndex'
|
||||
| 'publishedYear'
|
||||
| 'pageCount'
|
||||
| 'author'
|
||||
| 'tag'
|
||||
| 'format'
|
||||
| 'addedAt'
|
||||
|
||||
export type RuleOperator =
|
||||
| 'contains'
|
||||
| 'notContains'
|
||||
| 'startsWith'
|
||||
| 'endsWith'
|
||||
| 'eq'
|
||||
| 'notEq'
|
||||
| 'isEmpty'
|
||||
| 'isNotEmpty'
|
||||
| 'gt'
|
||||
| 'gte'
|
||||
| 'lt'
|
||||
| 'lte'
|
||||
| 'between'
|
||||
| 'includesAny'
|
||||
| 'includesAll'
|
||||
| 'excludesAll'
|
||||
| 'before'
|
||||
| 'after'
|
||||
| 'withinLast'
|
||||
|
||||
export const FIELD_OPERATORS: Record<RuleField, RuleOperator[]> = {
|
||||
title: ['contains', 'notContains', 'startsWith', 'endsWith', 'eq', 'notEq', 'isEmpty', 'isNotEmpty'],
|
||||
publisher: ['contains', 'notContains', 'isEmpty', 'isNotEmpty'],
|
||||
language: ['eq', 'notEq', 'isEmpty', 'isNotEmpty'],
|
||||
series: ['contains', 'notContains', 'isEmpty', 'isNotEmpty'],
|
||||
author: ['includesAny', 'includesAll', 'excludesAll', 'isEmpty', 'isNotEmpty'],
|
||||
tag: ['includesAny', 'includesAll', 'excludesAll', 'isEmpty', 'isNotEmpty'],
|
||||
format: ['includesAny', 'excludesAll'],
|
||||
publishedYear: ['eq', 'notEq', 'gt', 'gte', 'lt', 'lte', 'between', 'isEmpty', 'isNotEmpty'],
|
||||
seriesIndex: ['eq', 'notEq', 'gt', 'gte', 'lt', 'lte', 'between', 'isEmpty', 'isNotEmpty'],
|
||||
pageCount: ['gt', 'gte', 'lt', 'lte', 'between', 'isEmpty', 'isNotEmpty'],
|
||||
addedAt: ['before', 'after', 'between', 'withinLast'],
|
||||
}
|
||||
|
||||
export const RULE_FIELDS = Object.keys(FIELD_OPERATORS) as RuleField[]
|
||||
|
||||
export const RULE_OPERATORS: RuleOperator[] = [
|
||||
'contains',
|
||||
'notContains',
|
||||
'startsWith',
|
||||
'endsWith',
|
||||
'eq',
|
||||
'notEq',
|
||||
'isEmpty',
|
||||
'isNotEmpty',
|
||||
'gt',
|
||||
'gte',
|
||||
'lt',
|
||||
'lte',
|
||||
'between',
|
||||
'includesAny',
|
||||
'includesAll',
|
||||
'excludesAll',
|
||||
'before',
|
||||
'after',
|
||||
'withinLast',
|
||||
]
|
||||
|
||||
export type Rule = {
|
||||
type: 'rule'
|
||||
field: RuleField
|
||||
operator: RuleOperator
|
||||
value?: string | number | string[] | number[]
|
||||
valueTo?: string | number
|
||||
}
|
||||
|
||||
export type GroupRule = {
|
||||
type: 'group'
|
||||
join: 'AND' | 'OR'
|
||||
rules: (Rule | GroupRule)[]
|
||||
}
|
||||
|
||||
export type SortField = 'title' | 'addedAt' | 'publishedYear' | 'pageCount' | 'seriesIndex'
|
||||
|
||||
export const SORT_FIELDS: SortField[] = ['title', 'addedAt', 'publishedYear', 'pageCount', 'seriesIndex']
|
||||
|
||||
export type SortSpec = {
|
||||
field: SortField
|
||||
dir: 'asc' | 'desc'
|
||||
}
|
||||
|
||||
export type BookQuery = {
|
||||
filter?: GroupRule
|
||||
sort: SortSpec[]
|
||||
pagination: { page: number; size: number }
|
||||
}
|
||||
Reference in New Issue
Block a user