mirror of
https://github.com/bookorbit/bookorbit.git
synced 2026-11-03 08:21:39 -06:00
style(books): sort search format pills and align detail cover
This commit is contained in:
@@ -29,6 +29,7 @@ import BookUploadModal from '@/features/library/components/BookUploadModal.vue'
|
||||
import { useLibraryUploadEvents } from '@/features/library/composables/useLibraryUploadEvents'
|
||||
import { useBookBucketSummary } from '@/features/book-bucket/composables/useBookBucketSummary'
|
||||
import UserAvatar from '@/components/UserAvatar.vue'
|
||||
import { DEFAULT_FORMAT_PRIORITY } from '@projectx/types'
|
||||
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
@@ -177,6 +178,18 @@ function highlightSegments(text: string | null, query: string) {
|
||||
return parts.map((part) => ({ text: part, match: part.toLowerCase() === lower }))
|
||||
}
|
||||
|
||||
function sortFormats(formats: string[]): string[] {
|
||||
return [...formats].sort((a, b) => {
|
||||
const aIndex = (DEFAULT_FORMAT_PRIORITY as readonly string[]).indexOf(a.toLowerCase())
|
||||
const bIndex = (DEFAULT_FORMAT_PRIORITY as readonly string[]).indexOf(b.toLowerCase())
|
||||
|
||||
if (aIndex === -1 && bIndex === -1) return a.localeCompare(b)
|
||||
if (aIndex === -1) return 1
|
||||
if (bIndex === -1) return -1
|
||||
return aIndex - bIndex
|
||||
})
|
||||
}
|
||||
|
||||
function formatBadgeClass(fmt: string): string {
|
||||
switch (fmt.toLowerCase()) {
|
||||
case 'epub':
|
||||
@@ -271,7 +284,7 @@ function formatBadgeClass(fmt: string): string {
|
||||
</span>
|
||||
<div v-if="result.formats.length" class="flex gap-1">
|
||||
<span
|
||||
v-for="fmt in result.formats"
|
||||
v-for="fmt in sortFormats(result.formats)"
|
||||
:key="fmt"
|
||||
:class="['text-[9px] font-semibold px-1 py-0.5 rounded border uppercase', formatBadgeClass(fmt)]"
|
||||
>
|
||||
@@ -376,7 +389,7 @@ function formatBadgeClass(fmt: string): string {
|
||||
</span>
|
||||
<div v-if="result.formats.length" class="flex gap-1">
|
||||
<span
|
||||
v-for="fmt in result.formats"
|
||||
v-for="fmt in sortFormats(result.formats)"
|
||||
:key="fmt"
|
||||
:class="['text-[9px] font-semibold px-1 py-0.5 rounded border uppercase', formatBadgeClass(fmt)]"
|
||||
>
|
||||
|
||||
@@ -668,7 +668,7 @@ watch(
|
||||
|
||||
<div class="flex flex-col md:flex-row gap-8">
|
||||
<!-- Left column: cover + actions -->
|
||||
<div class="md:w-56 shrink-0 md:sticky md:top-4 md:self-start">
|
||||
<div class="md:w-56 shrink-0 md:sticky md:top-0 md:self-start">
|
||||
<div class="max-w-48 mx-auto md:max-w-none">
|
||||
<div
|
||||
class="group relative w-full rounded-sm overflow-hidden shadow-md cursor-zoom-in"
|
||||
@@ -713,7 +713,7 @@ watch(
|
||||
:disabled="!primaryFile"
|
||||
@click="openBook"
|
||||
>
|
||||
<Headphones v-if="isPrimaryAudio" class="size-4" />
|
||||
<BookOpen v-if="isPrimaryAudio" class="size-4" />
|
||||
<BookOpen v-else class="size-4" />
|
||||
{{ isPrimaryAudio ? 'Listen' : 'Read' }}
|
||||
</button>
|
||||
@@ -843,7 +843,7 @@ watch(
|
||||
<!-- Right column -->
|
||||
<div class="flex-1 min-w-0">
|
||||
<!-- Identity block -->
|
||||
<div class="flex items-center flex-wrap gap-x-3 gap-y-2">
|
||||
<div class="flex items-center flex-wrap gap-x-3 gap-y-2 -mt-1">
|
||||
<h1 class="text-2xl font-bold leading-tight">{{ book.title ?? 'Untitled' }}</h1>
|
||||
<Popover :open="scoreBreakdownOpen" @update:open="(v) => (scoreBreakdownOpen = v)">
|
||||
<PopoverTrigger as-child>
|
||||
|
||||
Reference in New Issue
Block a user