[FA-misc] Various UI updates
All checks were successful
CI / build-backend (pull_request) Successful in 1m38s
CI / build-frontend (pull_request) Successful in 37s

This commit is contained in:
gamer147
2025-12-10 20:37:30 -05:00
parent 45afb57df5
commit f0ea71e00e
13 changed files with 298 additions and 28 deletions

View File

@@ -1,20 +1,37 @@
import type { NovelDtoFilterInput, NovelStatus } from '$lib/graphql/__generated__/graphql';
import type { NovelDtoFilterInput, NovelDtoSortInput, NovelStatus, SortEnumType } from '$lib/graphql/__generated__/graphql';
export type SortField = 'lastUpdatedTime' | 'createdTime' | 'name';
export type SortDirection = SortEnumType;
export interface NovelSort {
field: SortField;
direction: SortDirection;
}
export interface NovelFilters {
search: string;
statuses: NovelStatus[];
tags: string[];
authorName: string;
sort: NovelSort;
}
export const DEFAULT_SORT: NovelSort = {
field: 'lastUpdatedTime',
direction: 'DESC'
};
export const EMPTY_FILTERS: NovelFilters = {
search: '',
statuses: [],
tags: [],
authorName: ''
authorName: '',
sort: DEFAULT_SORT
};
const VALID_STATUSES: NovelStatus[] = ['ABANDONED', 'COMPLETED', 'HIATUS', 'IN_PROGRESS', 'UNKNOWN'];
const VALID_SORT_FIELDS: SortField[] = ['lastUpdatedTime', 'createdTime', 'name'];
const VALID_SORT_DIRECTIONS: SortDirection[] = ['ASC', 'DESC'];
/**
* Parse filter state from URL search parameters
@@ -34,7 +51,15 @@ export function parseFiltersFromURL(searchParams?: URLSearchParams): NovelFilter
const authorName = params.get('author') ?? '';
return { search, statuses, tags, authorName };
// Parse sort parameters
const sortField = params.get('sortBy') as SortField | null;
const sortDir = params.get('sortDir') as SortDirection | null;
const sort: NovelSort = {
field: sortField && VALID_SORT_FIELDS.includes(sortField) ? sortField : DEFAULT_SORT.field,
direction: sortDir && VALID_SORT_DIRECTIONS.includes(sortDir) ? sortDir : DEFAULT_SORT.direction
};
return { search, statuses, tags, authorName, sort };
}
/**
@@ -59,6 +84,12 @@ export function filtersToURLParams(filters: NovelFilters): string {
params.set('author', filters.authorName.trim());
}
// Only include sort params if different from default
if (filters.sort.field !== DEFAULT_SORT.field || filters.sort.direction !== DEFAULT_SORT.direction) {
params.set('sortBy', filters.sort.field);
params.set('sortDir', filters.sort.direction);
}
return params.toString();
}
@@ -135,3 +166,10 @@ export function hasActiveFilters(filters: NovelFilters): boolean {
filters.authorName.trim().length > 0
);
}
/**
* Convert sort state to GraphQL order input
*/
export function sortToGraphQLOrder(sort: NovelSort): NovelDtoSortInput[] {
return [{ [sort.field]: sort.direction }];
}