add scaffolding for entity browsing and card links

This commit is contained in:
Gauthier Roebroeck 2026-04-01 17:37:13 +08:00
parent eaf4ca9149
commit e075301821
12 changed files with 146 additions and 15 deletions

View file

@ -41,14 +41,10 @@ const intl = useIntl()
const id = useId()
const {
book,
showSeries = true,
...props
} = defineProps<
const { book, showSeries, ...props } = defineProps<
{
book: components['schemas']['BookDto']
showSeries?: boolean
showSeries: boolean
} & ItemCardProps
>()
const emit = defineEmits<ItemCardEmits>()
@ -98,17 +94,21 @@ const titleAndLines = computed<{ title: ItemCardTitle; lines: ItemCardLine[] }>(
if (book.oneshot) {
return {
title: { text: book.metadata.title, lines: 2 },
title: { text: book.metadata.title, lines: 2, routerLink: `/book/${book.id}` },
lines: [footer],
}
} else {
const numberedTitle = `${book.metadata.number} - ${book.metadata.title}`
if (showSeries)
return {
title: { text: book.seriesTitle, lines: 1 },
lines: [{ text: numberedTitle, lines: 1 }, footer],
title: { text: book.seriesTitle, lines: 1, routerLink: `/series/${book.seriesId}` },
lines: [{ text: numberedTitle, lines: 1, routerLink: `/book/${book.id}` }, footer],
}
else
return {
title: { text: numberedTitle, lines: 2, routerLink: `/book/${book.id}` },
lines: [footer],
}
else return { title: { text: numberedTitle, lines: 2 }, lines: [footer] }
}
})

View file

@ -46,7 +46,11 @@ const emit = defineEmits<ItemCardEmits>()
const bottomSheet = ref(false)
const title = computed<ItemCardTitle>(() => ({ text: collection.name, lines: 2 }))
const title = computed<ItemCardTitle>(() => ({
text: collection.name,
lines: 2,
routerLink: `/collection/${collection.id}`,
}))
const lines = computed<ItemCardLine[]>(() => [
{

View file

@ -136,8 +136,15 @@
<v-card-title
:class="['text-label-large px-2 pb-0 mb-2', { 'force-line-count text-wrap': title.lines }]"
:style="[{ '--lines': title.lines }, { '--line-height': 1.6 }]"
>{{ title.text }}</v-card-title
>
<RouterLink
v-if="title.routerLink"
:to="title.routerLink"
class="link-underline"
>{{ title.text }}</RouterLink
>
<span v-else>{{ title.text }}</span>
</v-card-title>
<template
v-for="(line, i) in lines"
@ -152,7 +159,14 @@
{ 'force-line-count text-wrap': line.lines },
]"
:style="[{ '--lines': line.lines }, { '--line-height': 1.4 }]"
>{{ line.text }}
>
<RouterLink
v-if="line.routerLink"
:to="line.routerLink"
class="link-underline"
>{{ line.text }}</RouterLink
>
<span v-else>{{ line.text }}</span>
</v-card-subtitle>
</template>
</v-card>

View file

@ -46,7 +46,11 @@ const emit = defineEmits<ItemCardEmits>()
const bottomSheet = ref(false)
const title = computed<ItemCardTitle>(() => ({ text: readList.name, lines: 2 }))
const title = computed<ItemCardTitle>(() => ({
text: readList.name,
lines: 2,
routerLink: `/readlist/${readList.id}`,
}))
const lines = computed<ItemCardLine[]>(() => [
{

View file

@ -53,7 +53,11 @@ const unreadCount = computed(() =>
series.oneshot ? undefined : series.booksUnreadCount + series.booksInProgressCount,
)
const title = computed<ItemCardTitle>(() => ({ text: series.metadata.title, lines: 2 }))
const title = computed<ItemCardTitle>(() => ({
text: series.metadata.title,
lines: 2,
routerLink: `/series/${series.id}`,
}))
const lines = computed<ItemCardLine[]>(() => {
if (series.deleted)

View file

@ -0,0 +1,11 @@
<template>Book: {{ bookId }}</template>
<script lang="ts" setup>
const route = useRoute('/book/[id]')
const bookId = computed(() => route.params.id)
</script>
<route lang="yaml">
meta:
requiresRole: USER
</route>

View file

@ -0,0 +1,11 @@
<template>Collection: {{ collectionId }}</template>
<script lang="ts" setup>
const route = useRoute('/collection/[id]')
const collectionId = computed(() => route.params.id)
</script>
<route lang="yaml">
meta:
requiresRole: USER
</route>

View file

@ -122,6 +122,7 @@
>
<template #default="{ item, isSelected, preSelect, toggleSelect }">
<BookCard
show-series
stretch-poster
:book="item"
:selected="isSelected"

View file

@ -0,0 +1,11 @@
<template>Readlist: {{ readListId }}</template>
<script lang="ts" setup>
const route = useRoute('/readlist/[id]')
const readListId = computed(() => route.params.id)
</script>
<route lang="yaml">
meta:
requiresRole: USER
</route>

View file

@ -0,0 +1,11 @@
<template>Series: {{ seriesId }}</template>
<script lang="ts" setup>
const route = useRoute('/series/[id]')
const seriesId = computed(() => route.params.id)
</script>
<route lang="yaml">
meta:
requiresRole: USER
</route>

View file

@ -69,6 +69,13 @@ declare module 'vue-router/auto-routes' {
Record<never, never>,
| never
>,
'/book/[id]': RouteRecordInfo<
'/book/[id]',
'/book/:id',
{ id: ParamValue<true> },
{ id: ParamValue<false> },
| never
>,
'/claim': RouteRecordInfo<
'/claim',
'/claim',
@ -76,6 +83,13 @@ declare module 'vue-router/auto-routes' {
Record<never, never>,
| never
>,
'/collection/[id]': RouteRecordInfo<
'/collection/[id]',
'/collection/:id',
{ id: ParamValue<true> },
{ id: ParamValue<false> },
| never
>,
'/error': RouteRecordInfo<
'/error',
'/error',
@ -192,6 +206,20 @@ declare module 'vue-router/auto-routes' {
Record<never, never>,
| never
>,
'/readlist/[id]': RouteRecordInfo<
'/readlist/[id]',
'/readlist/:id',
{ id: ParamValue<true> },
{ id: ParamValue<false> },
| never
>,
'/series/[id]': RouteRecordInfo<
'/series/[id]',
'/series/:id',
{ id: ParamValue<true> },
{ id: ParamValue<false> },
| never
>,
'/server/activity': RouteRecordInfo<
'/server/activity',
'/server/activity',
@ -297,12 +325,24 @@ declare module 'vue-router/auto-routes' {
views:
| never
}
'src/pages/book/[id].vue': {
routes:
| '/book/[id]'
views:
| never
}
'src/pages/claim.vue': {
routes:
| '/claim'
views:
| never
}
'src/pages/collection/[id].vue': {
routes:
| '/collection/[id]'
views:
| never
}
'src/pages/error.vue': {
routes:
| '/error'
@ -404,6 +444,18 @@ declare module 'vue-router/auto-routes' {
views:
| never
}
'src/pages/readlist/[id].vue': {
routes:
| '/readlist/[id]'
views:
| never
}
'src/pages/series/[id].vue': {
routes:
| '/series/[id]'
views:
| never
}
'src/pages/server/activity.vue': {
routes:
| '/server/activity'

View file

@ -38,6 +38,10 @@ export type ItemCardTitle = {
* Number of lines.
*/
lines?: number
/**
* Link.
*/
routerLink?: string | object
}
export type ItemCardLine = {
@ -57,4 +61,8 @@ export type ItemCardLine = {
* Whether the container will be shown even if `text` is empty.
*/
allowEmpty?: boolean
/**
* Link.
*/
routerLink?: string | object
}