-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(svelte-ui): add collection specific page
- Loading branch information
1 parent
067449b
commit 31cc104
Showing
12 changed files
with
281 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
<script lang="ts"> | ||
let { children } = $props() | ||
</script> | ||
<header | ||
class="flex h-10 items-center gap-2 border-b border-gray-200 px-6 dark:border-gray-800 text-lg lowercase sticky top-0 bg-white/80 dark:bg-gray-950/80 backdrop-blur-xl z-10" | ||
> | ||
{@render children()} | ||
</header> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
<script lang="ts"> | ||
let { children } = $props() | ||
</script> | ||
|
||
<p class="text-gray-400 dark:text-gray-500"> | ||
{@render children()} | ||
</p> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export const { format: formatDate } = new Intl.DateTimeFormat(undefined, { | ||
dateStyle: "long", | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
export function formatLevelName(level: string): string { | ||
switch (level) { | ||
case 'BESPOKE': | ||
return 'Bespoke' | ||
case 'COUTURE': | ||
return 'Couture' | ||
case 'HANDMADE': | ||
return 'Handmade' | ||
case 'RTW': | ||
return 'RTW' | ||
default: | ||
throw new Error(`Unknown level: ${level}`) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
const LOCATION_TO_NAME: Record<string, string> = { | ||
NEW_YORK: 'New York, United States', | ||
LONDON: 'London, England', | ||
MILAN: 'Milan, Italy', | ||
PARIS: 'Paris, France', | ||
TOKYO: 'Tokyo, Japan', | ||
BERLIN: 'Berlin, Germany', | ||
FLORENCE: 'Florence, Italy', | ||
LOS_ANGELES: 'Los Angeles, United States', | ||
MADRID: 'Madrid, Spain', | ||
COPENHAGEN: 'Copenhagen, Denmark', | ||
SHANGHAI: 'Shanghai, China', | ||
AUSTRALIA: 'Australia', | ||
STOCKHOLM: 'Stockholm, Sweden', | ||
MEXICO: 'Mexico', | ||
MEXICO_CITY: 'Mexico City, Mexico', | ||
KIEV: 'Kiev, Ukraine', | ||
TBILISI: 'Tbilisi, Georgia', | ||
SEOUL: 'Seoul, South Korea', | ||
RUSSIA: 'Russia', | ||
UKRAINE: 'Ukraine', | ||
SAO_PAOLO: 'Sao Paolo, Brazil', | ||
BRIDAL: 'Bridal', | ||
} | ||
|
||
export function formatLocation(location: string): string { | ||
return LOCATION_TO_NAME[location] ?? location | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
/** | ||
* Capitalizes the first letter of each word in the given string. Lowercases all | ||
* the other letters in each string (e.g. "RESORT 2024" -> "Resort 2024"). | ||
* @param str The string to capitalize. | ||
* @returns The capitalized string. | ||
*/ | ||
function formatCaps(sentence: string): string { | ||
return sentence | ||
.split(' ') | ||
.map((w) => `${w.charAt(0).toUpperCase()}${w.slice(1).toLowerCase()}`) | ||
.join(' ') | ||
} | ||
|
||
/** | ||
* Get the user-friendly season name from a season object (e.g. "Resort 2024"). | ||
* @param season The season object. | ||
* @returns The user-friendly season name. | ||
*/ | ||
export function formatSeasonName(season: { name: string; year: number }) { | ||
const name = formatCaps(season.name.replace('_', ' ')).replace(' ', '-') | ||
return `${name} ${season.year}` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
28 changes: 28 additions & 0 deletions
28
svelte-ui/src/routes/collections/[collectionId]/+page.server.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import { eq } from "drizzle-orm" | ||
import * as tables from "$lib/server/db/schema/tables" | ||
import { db } from "$lib/server/db" | ||
|
||
export async function load({ params }) { | ||
return { | ||
collection: db.query.collection | ||
.findMany({ | ||
where: eq(tables.collection.id, params.collectionId), | ||
with: { | ||
brand: true, | ||
season: true, | ||
articles: { | ||
with: { | ||
user_authorId: true, | ||
publication: true, | ||
}, | ||
}, | ||
looks: { | ||
with: { | ||
images: true, | ||
}, | ||
}, | ||
}, | ||
}) | ||
.then((collections) => collections[0]), | ||
} | ||
} |
114 changes: 114 additions & 0 deletions
114
svelte-ui/src/routes/collections/[collectionId]/+page.svelte
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
<script lang="ts"> | ||
import { ExternalLink, ChevronRight } from "lucide-svelte" | ||
import { formatDate } from "$lib/formatDate" | ||
import { formatSeasonName } from "$lib/formatSeasonName" | ||
import { formatLevelName } from "$lib/formatLevelName" | ||
import { formatLocation } from "$lib/formatLocation" | ||
import Header from "$lib/components/Header.svelte" | ||
import Subtitle from "$lib/components/Subtitle.svelte" | ||
let { data } = $props() | ||
</script> | ||
|
||
<Header> | ||
<a href="/">Collections</a> | ||
<ChevronRight class="h-4 w-4 text-gray-200 dark:text-gray-800" /> | ||
{#await data.collection then collection} | ||
<a href="/?q={encodeURIComponent(collection.brand.name)}" | ||
>{collection.brand.name}</a | ||
> | ||
<ChevronRight class="h-4 w-4 text-gray-200 dark:text-gray-800" /> | ||
<a href="/collections/{collection.id}" | ||
>{formatSeasonName(collection.season)} | ||
{formatLevelName(collection.level)}</a | ||
> | ||
<div class="flex items-center gap-1"> | ||
{#if collection.date} | ||
<span class="text-sm text-gray-400 dark:text-gray-500" | ||
>({formatDate(new Date(collection.date))})</span | ||
> | ||
{/if} | ||
{#if collection.location} | ||
<span class="text-sm text-gray-400 dark:text-gray-500" | ||
>({formatLocation(collection.location)})</span | ||
> | ||
{/if} | ||
</div> | ||
{/await} | ||
</Header> | ||
<div class="flex h-full flex-col xl:flex-row"> | ||
<div class="flex flex-col gap-6 p-6 xl:w-0 xl:grow"> | ||
{#await data.collection} | ||
<p>Loading...</p> | ||
{:then collection} | ||
<div | ||
class="grid gap-x-2 gap-y-4 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-2 2xl:grid-cols-3" | ||
> | ||
{#each collection.looks as look (look.id)} | ||
<a | ||
href={look.images[0].url} | ||
target="_blank" | ||
rel="noopener noreferrer" | ||
class="flex flex-col gap-2 text-xs" | ||
> | ||
<div | ||
class="flex aspect-person w-full items-center justify-center bg-gray-100 dark:bg-gray-800" | ||
> | ||
{#if look.images[0]?.url} | ||
<img | ||
loading="lazy" | ||
decoding="async" | ||
src={look.images[0].url} | ||
alt="Look {look.number} of {collection.name}" | ||
class="flex h-full w-full items-center justify-center object-cover" | ||
/> | ||
{:else} | ||
<span class="text-gray-200 dark:text-gray-700" | ||
>No look images to show</span | ||
> | ||
{/if} | ||
</div> | ||
<p>Look {look.number}</p> | ||
</a> | ||
{/each} | ||
</div> | ||
{/await} | ||
</div> | ||
{#await data.collection then collection} | ||
{#if collection.articles.length} | ||
<div class="flex flex-col gap-12 p-6 xl:pr-12"> | ||
{#each collection.articles as article (article.id)} | ||
<div class="flex flex-col gap-4 text-sm"> | ||
<div> | ||
<h2 class="flex items-center gap-2"> | ||
<span | ||
>By <a | ||
href={article.user_authorId?.url} | ||
target="_blank" | ||
rel="noopener noreferrer" | ||
class="underline">{article.user_authorId?.name}</a | ||
> | ||
for | ||
<a | ||
href={article.url} | ||
target="_blank" | ||
rel="noopener noreferrer" | ||
class="underline">{article.publication.name}</a | ||
></span | ||
> | ||
<ExternalLink class="h-4 w-4" /> | ||
</h2> | ||
{#if article.writtenAt} | ||
<Subtitle>{formatDate(new Date(article.writtenAt))}</Subtitle> | ||
{/if} | ||
</div> | ||
<article class="prose prose-sm prose-zinc dark:prose-invert"> | ||
{@html article.content} | ||
</article> | ||
</div> | ||
{/each} | ||
</div> | ||
{/if} | ||
{/await} | ||
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters