diff options
Diffstat (limited to 'frontend/src/lib')
-rw-r--r-- | frontend/src/lib/components/ArchiveCard.svelte | 39 | ||||
-rw-r--r-- | frontend/src/lib/components/Card.svelte | 39 | ||||
-rw-r--r-- | frontend/src/lib/components/ComicCard.svelte | 75 | ||||
-rw-r--r-- | frontend/src/lib/pills/ComicPills.svelte | 37 | ||||
-rw-r--r-- | frontend/src/lib/pills/FooterPill.svelte | 15 | ||||
-rw-r--r-- | frontend/src/lib/tabs/ArchiveDetails.svelte | 7 | ||||
-rw-r--r-- | frontend/src/lib/tabs/ArchiveEdit.svelte | 8 |
7 files changed, 150 insertions, 70 deletions
diff --git a/frontend/src/lib/components/ArchiveCard.svelte b/frontend/src/lib/components/ArchiveCard.svelte new file mode 100644 index 0000000..c9d283b --- /dev/null +++ b/frontend/src/lib/components/ArchiveCard.svelte @@ -0,0 +1,39 @@ +<script lang="ts"> + import type { ArchiveFragment } from '$gql/graphql'; + import FooterPill from '$lib/pills/FooterPill.svelte'; + import { filesize } from 'filesize'; + import { type Snippet } from 'svelte'; + import Card from './Card.svelte'; + + interface Props { + archive: ArchiveFragment; + overlay?: Snippet; + onclick?: (event: MouseEvent) => void; + } + + let { archive, overlay, onclick }: Props = $props(); + + let details = $derived({ + title: archive.name, + cover: archive.cover + }); + let href = $derived(`/archives/${archive.id.toString()}`); +</script> + +<Card {details} {href} {onclick} {overlay}> + {#snippet footer()} + <div class="flex flex-wrap gap-1"> + <FooterPill text={`${archive.pageCount} pages`}> + {#snippet icon()} + <span class="icon-[material-symbols--description] mr-0.5 text-sm"></span> + {/snippet} + </FooterPill> + <div class="flex grow"></div> + <FooterPill text={filesize(archive.size, { base: 2 })}> + {#snippet icon()} + <span class="icon-[material-symbols--hard-drive] mr-0.5 text-sm"></span> + {/snippet} + </FooterPill> + </div> + {/snippet} +</Card> diff --git a/frontend/src/lib/components/Card.svelte b/frontend/src/lib/components/Card.svelte index b8e8ecf..8cfe34d 100644 --- a/frontend/src/lib/components/Card.svelte +++ b/frontend/src/lib/components/Card.svelte @@ -1,5 +1,8 @@ -<script lang="ts" module> - import type { ComicFragment, ImageFragment } from '$gql/graphql'; +<script lang="ts"> + import type { ImageFragment } from '$gql/graphql'; + import { src } from '$lib/Utils'; + import Star from '$lib/icons/Star.svelte'; + import type { Snippet } from 'svelte'; interface CardDetails { title: string; @@ -8,24 +11,6 @@ cover?: ImageFragment; } - export function comicCard(comic: ComicFragment) { - return { - href: `/comics/${comic.id.toString()}`, - details: { - title: comic.title, - subtitle: comic.originalTitle, - favourite: comic.favourite, - cover: comic.cover - } - }; - } -</script> - -<script lang="ts"> - import { src } from '$lib/Utils'; - import Star from '$lib/icons/Star.svelte'; - import type { Snippet } from 'svelte'; - interface Props { href: string; details: CardDetails; @@ -33,6 +18,7 @@ coverOnly?: boolean; overlay?: Snippet; children?: Snippet; + footer?: Snippet; onclick?: (event: MouseEvent) => void; } @@ -43,6 +29,7 @@ coverOnly = false, overlay, children, + footer, onclick }: Props = $props(); </script> @@ -66,8 +53,8 @@ /> {/if} {#if !coverOnly} - <article class="flex h-full flex-col gap-2 p-2"> - <header> + <article class="p flex h-full flex-col p-2 pb-1"> + <header class="mb-2"> <h2 class="self-center text-sm font-medium [grid-area:title]" title={details.title}> {details.title} </h2> @@ -86,9 +73,15 @@ {/if} </header> - <section class="max-h-full grow overflow-auto border-t border-slate-800/80 pt-2 text-xs"> + <section class="max-h-full grow overflow-auto border-y border-slate-800/80 pt-2 text-xs"> {@render children?.()} </section> + + {#if footer} + <div class="mt-1 text-xs"> + {@render footer()} + </div> + {/if} </article> {/if} </a> diff --git a/frontend/src/lib/components/ComicCard.svelte b/frontend/src/lib/components/ComicCard.svelte new file mode 100644 index 0000000..cb73e97 --- /dev/null +++ b/frontend/src/lib/components/ComicCard.svelte @@ -0,0 +1,75 @@ +<script lang="ts"> + import type { ComicFragment } from '$gql/graphql'; + import AssociationPill from '$lib/pills/AssociationPill.svelte'; + import FooterPill from '$lib/pills/FooterPill.svelte'; + import TagPill from '$lib/pills/TagPill.svelte'; + import { type Snippet } from 'svelte'; + import Card from './Card.svelte'; + + interface Props { + comic: ComicFragment; + overlay?: Snippet; + compact?: boolean; + coverOnly?: boolean; + onclick?: (event: MouseEvent) => void; + } + + let { comic, overlay, compact, coverOnly, onclick }: Props = $props(); + + let details = $derived({ + title: comic.title, + subtitle: comic.originalTitle, + favourite: comic.favourite, + cover: comic.cover + }); + let href = $derived(`/comics/${comic.id.toString()}`); +</script> + +<Card {details} {href} {compact} {onclick} {overlay} {coverOnly}> + <div class="flex flex-col gap-1"> + {#if comic.artists.length || comic.circles.length} + <div class="flex flex-wrap gap-1"> + {#each comic.artists as { name } (name)} + <AssociationPill {name} type="artist" /> + {/each} + {#each comic.circles as { name } (name)} + <AssociationPill {name} type="circle" /> + {/each} + </div> + {/if} + {#if comic.characters.length || comic.worlds.length} + <div class="flex flex-wrap gap-1"> + {#each comic.worlds as { name } (name)} + <AssociationPill {name} type="world" /> + {/each} + {#each comic.characters as { name } (name)} + <AssociationPill {name} type="character" /> + {/each} + </div> + {/if} + {#if comic.tags.length} + <div class="flex flex-wrap gap-1"> + {#each comic.tags as { name, description } (name)} + <TagPill {name} {description} /> + {/each} + </div> + {/if} + </div> + {#snippet footer()} + <div class="flex flex-wrap gap-1"> + <FooterPill text={`${comic.pageCount} pages`}> + {#snippet icon()} + <span class="icon-[material-symbols--description] mr-0.5 text-sm"></span> + {/snippet} + </FooterPill> + <div class="flex grow"></div> + {#if comic.date} + <FooterPill text={comic.date}> + {#snippet icon()} + <span class="icon-[material-symbols--calendar-today] mr-0.5 text-sm"></span> + {/snippet} + </FooterPill> + {/if} + </div> + {/snippet} +</Card> diff --git a/frontend/src/lib/pills/ComicPills.svelte b/frontend/src/lib/pills/ComicPills.svelte deleted file mode 100644 index 45c42fd..0000000 --- a/frontend/src/lib/pills/ComicPills.svelte +++ /dev/null @@ -1,37 +0,0 @@ -<script lang="ts"> - import type { ComicFragment } from '$gql/graphql'; - import AssociationPill from '$lib/pills/AssociationPill.svelte'; - import TagPill from '$lib/pills/TagPill.svelte'; - - let { comic }: { comic: ComicFragment } = $props(); -</script> - -<div class="flex flex-col gap-1"> - {#if comic.artists.length || comic.circles.length} - <div class="flex flex-wrap gap-1"> - {#each comic.artists as { name } (name)} - <AssociationPill {name} type="artist" /> - {/each} - {#each comic.circles as { name } (name)} - <AssociationPill {name} type="circle" /> - {/each} - </div> - {/if} - {#if comic.characters.length || comic.worlds.length} - <div class="flex flex-wrap gap-1"> - {#each comic.worlds as { name } (name)} - <AssociationPill {name} type="world" /> - {/each} - {#each comic.characters as { name } (name)} - <AssociationPill {name} type="character" /> - {/each} - </div> - {/if} - {#if comic.tags.length} - <div class="flex flex-wrap gap-1"> - {#each comic.tags as { name, description } (name)} - <TagPill {name} {description} /> - {/each} - </div> - {/if} -</div> diff --git a/frontend/src/lib/pills/FooterPill.svelte b/frontend/src/lib/pills/FooterPill.svelte new file mode 100644 index 0000000..3da1811 --- /dev/null +++ b/frontend/src/lib/pills/FooterPill.svelte @@ -0,0 +1,15 @@ +<script lang="ts"> + import type { Snippet } from 'svelte'; + + interface Props { + text: string; + icon?: Snippet; + } + + let { text, icon }: Props = $props(); +</script> + +<div class="flex items-center rounded-sm p-0.5 text-zinc-300"> + {@render icon?.()} + <span>{text}</span> +</div> diff --git a/frontend/src/lib/tabs/ArchiveDetails.svelte b/frontend/src/lib/tabs/ArchiveDetails.svelte index b3d570f..1243162 100644 --- a/frontend/src/lib/tabs/ArchiveDetails.svelte +++ b/frontend/src/lib/tabs/ArchiveDetails.svelte @@ -1,8 +1,7 @@ <script lang="ts"> import type { FullArchiveFragment } from '$gql/graphql'; import { formatListSize, joinText } from '$lib/Utils'; - import Card, { comicCard } from '$lib/components/Card.svelte'; - import ComicPills from '$lib/pills/ComicPills.svelte'; + import ComicCard from '$lib/components/ComicCard.svelte'; import { formatDistance, formatISO9075 } from 'date-fns'; import { filesize } from 'filesize'; import Header from './DetailsHeader.svelte'; @@ -40,9 +39,7 @@ <h2 class="text-base font-medium">Comics</h2> <div class="flex shrink-0 flex-col gap-4"> {#each archive.comics as comic} - <Card compact {...comicCard(comic)}> - <ComicPills {comic} /> - </Card> + <ComicCard compact {comic} /> {/each} </div> </div> diff --git a/frontend/src/lib/tabs/ArchiveEdit.svelte b/frontend/src/lib/tabs/ArchiveEdit.svelte index 83a492b..2ed0523 100644 --- a/frontend/src/lib/tabs/ArchiveEdit.svelte +++ b/frontend/src/lib/tabs/ArchiveEdit.svelte @@ -3,9 +3,8 @@ import { type FullArchiveFragment } from '$gql/graphql'; import { toastFinally } from '$lib/Toasts'; import AddButton from '$lib/components/AddButton.svelte'; - import Card, { comicCard } from '$lib/components/Card.svelte'; + import ComicCard from '$lib/components/ComicCard.svelte'; import OrganizedButton from '$lib/components/OrganizedButton.svelte'; - import ComicPills from '$lib/pills/ComicPills.svelte'; import { getSelectionContext } from '$lib/selection/Selection.svelte'; import SelectionControls from '$lib/toolbar/SelectionControls.svelte'; import { getContextClient } from '@urql/svelte'; @@ -57,12 +56,11 @@ <h2 class="text-base font-medium">Comics</h2> <div class="flex shrink-0 flex-col gap-4"> {#each archive.comics as comic} - <Card compact {...comicCard(comic)}> + <ComicCard compact {comic}> {#snippet overlay()} <AddOverlay id={comic.id} /> {/snippet} - <ComicPills {comic} /> - </Card> + </ComicCard> {/each} </div> </div> |