diff --git a/src/components/Credits.astro b/src/components/Credits.astro index 2b4be01..bab05d9 100644 --- a/src/components/Credits.astro +++ b/src/components/Credits.astro @@ -31,11 +31,9 @@ const { getLocalizedMatch } = await getI18n(Astro.locals.currentLocale); div { display: grid; gap: 2em; - margin-block: 2em; @media (max-width: 35rem) { - gap: 3.5em; - margin-block: 3.5em; + gap: 3em; } } diff --git a/src/components/Lightbox.astro b/src/components/Lightbox.astro index 6ff11e3..09e6a70 100644 --- a/src/components/Lightbox.astro +++ b/src/components/Lightbox.astro @@ -5,12 +5,12 @@ import { type PayloadImage, type RichTextContent, } from "src/shared/payload/payload-sdk"; -import RichText from "./RichText/RichText.astro"; import TagGroups from "./TagGroups.astro"; import Credits from "./Credits.astro"; import DownloadButton from "./DownloadButton.astro"; import AppLayoutTitle from "./AppLayout/components/AppLayoutTitle.astro"; import type { ComponentProps } from "astro/types"; +import AppLayoutDescription from "./AppLayout/components/AppLayoutDescription.astro"; interface Props { previousImageHref?: string | undefined; @@ -65,15 +65,16 @@ const smallTitle = !subtitle && !pretitle; complex: (tagGroups && tagGroups.length > 0) || (credits && credits.length > 0) || description, }}> - { - smallTitle ? ( -

{title}

- ) : ( - - ) - } - - {description && } +
+ { + smallTitle ? ( +

{title}

+ ) : ( + + ) + } + {description && } +
{tagGroups && tagGroups.length > 0 && } {credits && credits.length > 0 && } {filename && } @@ -113,12 +114,16 @@ const smallTitle = !subtitle && !pretitle; & > #info { display: flex; flex-direction: column; - gap: 1em; - align-items: center; + gap: 4em; + align-items: start; - &.complex { + @media (max-width: 35rem) { + gap: 6em; + } + + &:not(.complex) { + align-items: center; gap: 2em; - align-items: start; } & > h1 { diff --git a/src/components/TagGroups.astro b/src/components/TagGroups.astro index f66a328..e4a2c36 100644 --- a/src/components/TagGroups.astro +++ b/src/components/TagGroups.astro @@ -41,13 +41,12 @@ const groups = tagGroups.map((group) => { diff --git a/src/i18n/wordings-keys.ts b/src/i18n/wordings-keys.ts index 2cdd5ac..0f9b50c 100644 --- a/src/i18n/wordings-keys.ts +++ b/src/i18n/wordings-keys.ts @@ -144,4 +144,7 @@ export type WordingKey = | "global.media.attributes.duration" | "global.media.attributes.filesize" | "global.media.attributes.createdAt" - | "global.media.attributes.updatedAt"; + | "global.media.attributes.updatedAt" + | "global.media.attributes.updatedBy" + | "collectibles.nature" + | "collectibles.languages"; diff --git a/src/pages/[locale]/api/pages/partial.astro b/src/pages/[locale]/api/pages/partial.astro index c283700..a543854 100644 --- a/src/pages/[locale]/api/pages/partial.astro +++ b/src/pages/[locale]/api/pages/partial.astro @@ -22,13 +22,38 @@ interface Props { const reqUrl = new URL(Astro.request.url); const lang = Astro.props.lang ?? reqUrl.searchParams.get("lang")!; const slug = Astro.props.slug ?? reqUrl.searchParams.get("slug")!; -const { translations, thumbnail, tagGroups } = Astro.props.page ?? (await payload.getPage(slug)); +const { translations, thumbnail, tagGroups, createdAt, updatedAt, updatedBy } = + Astro.props.page ?? (await payload.getPage(slug)); -const { getLocalizedUrl } = await getI18n(Astro.locals.currentLocale); +const { getLocalizedUrl, t, formatDate } = await getI18n(Astro.locals.currentLocale); const { getLocalizedMatch } = await getI18n(lang); const { pretitle, title, subtitle, summary, content, credits, toc, language, sourceLanguage } = getLocalizedMatch(translations); + +const attributes = [ + { + title: t("global.media.attributes.createdAt"), + icon: "material-symbols:calendar-add-on-outline", + values: [formatDate(new Date(createdAt))], + withBorder: false, + }, + { + title: t("global.media.attributes.updatedAt"), + icon: "material-symbols:edit-calendar", + values: [formatDate(new Date(updatedAt))], + withBorder: false, + }, +]; + +if (updatedBy) { + attributes.push({ + title: t("global.media.attributes.updatedBy"), + icon: "material-symbols:person-edit-outline", + values: [updatedBy?.username], + withBorder: true, + }); +} --- {/* ------------------------------------------- HTML ------------------------------------------- */} @@ -56,27 +81,37 @@ const { pretitle, title, subtitle, summary, content, credits, toc, language, sou {summary && } - {tagGroups.length > 0 && } - - - { - translations.length > 1 && ( - language)} - getPartialUrl={(lang) => - getLocalizedUrl(`/api/pages/partial?lang=${lang}&slug=${slug}`) - } - /> + tagGroups.length > 0 && ( +
+ +
) } +
- {credits.length > 0 && } +
+
+ { + translations.length > 1 && ( + language)} + getPartialUrl={(lang) => + getLocalizedUrl(`/api/pages/partial?lang=${lang}&slug=${slug}`) + } + /> + ) + } + + {credits.length > 0 && } +
+ + {attributes.length > 0 && } {toc.length > 0 && } - +

@@ -94,6 +129,39 @@ const { pretitle, title, subtitle, summary, content, credits, toc, language, sou margin-block: 3em; } + #aside { + display: flex; + flex-direction: column; + gap: 4em; + + @media (max-width: 35rem) { + gap: 6em; + } + } + + #tags { + margin-block: 2em; + + @media (max-width: 1280.5px) { + margin-bottom: 4em; + } + + @media (max-width: 35rem) { + margin-top: 4em; + margin-bottom: 6em; + } + } + + #credits { + display: flex; + flex-direction: column; + gap: 1em; + + @media (max-width: 35rem) { + gap: 2em; + } + } + #thumbnail { max-width: 35rem; max-height: 60vh; diff --git a/src/pages/[locale]/audios/[id].astro b/src/pages/[locale]/audios/[id].astro index 85a727b..61e031b 100644 --- a/src/pages/[locale]/audios/[id].astro +++ b/src/pages/[locale]/audios/[id].astro @@ -36,8 +36,7 @@ const { pretitle, title, subtitle, description } = getLocalizedMatch(translation const smallTitle = !subtitle && !pretitle; -const tagsAndAttributes = [ - ...tagGroups, +const attributes = [ ...(filename && title !== filename ? [ { @@ -81,7 +80,7 @@ const tagsAndAttributes = [
-
+
{ smallTitle ? (

{title}

@@ -90,10 +89,9 @@ const tagsAndAttributes = [ ) } {description && } -
- {tagsAndAttributes.length > 0 && } - {credits.length > 0 && } -
+ {tagGroups.length > 0 && } + {credits.length > 0 && } + {attributes.length > 0 && }
@@ -117,18 +115,14 @@ const tagsAndAttributes = [ max-width: 35em; } - & > div { + & > #info { display: flex; flex-direction: column; - gap: 2em; + gap: 4em; align-items: start; - & > div { - display: flex; - flex-wrap: wrap; - justify-content: space-between; - gap: 2em 6em; - width: 100%; + @media (max-width: 35rem) { + gap: 6em; } } } diff --git a/src/pages/[locale]/collectibles/[slug]/_components/PriceInfo.astro b/src/pages/[locale]/collectibles/[slug]/_components/PriceInfo.astro deleted file mode 100644 index c9cf82e..0000000 --- a/src/pages/[locale]/collectibles/[slug]/_components/PriceInfo.astro +++ /dev/null @@ -1,70 +0,0 @@ ---- -import { Icon } from "astro-icon/components"; -import { getI18n } from "src/i18n/i18n"; -import { convert } from "src/utils/currencies"; - -interface Props { - price: { - amount: number; - currency: string; - }; -} - -const { price } = Astro.props; - -const { formatPrice, t } = await getI18n(Astro.locals.currentLocale); - -const preferredCurrency = Astro.locals.currentCurrency; - -const convertedPrice: Props["price"] = { - amount: convert(price.currency, preferredCurrency, price.amount), - currency: preferredCurrency, -}; - -let priceText = price.amount === 0 ? t("collectibles.price.free") : formatPrice(price); - -if (price.amount > 0 && price.currency !== convertedPrice.currency) { - priceText += ` (${formatPrice(convertedPrice)})`; -} ---- - -{/* ------------------------------------------- HTML ------------------------------------------- */} - -
-
- -

{t("collectibles.price")}

-
- - {(

{priceText}

)} -
- -{/* ------------------------------------------- CSS -------------------------------------------- */} - - diff --git a/src/pages/[locale]/collectibles/[slug]/_components/ReleaseDateInfo.astro b/src/pages/[locale]/collectibles/[slug]/_components/ReleaseDateInfo.astro deleted file mode 100644 index f2b0fa8..0000000 --- a/src/pages/[locale]/collectibles/[slug]/_components/ReleaseDateInfo.astro +++ /dev/null @@ -1,53 +0,0 @@ ---- -import { Icon } from "astro-icon/components"; -import { getI18n } from "src/i18n/i18n"; - -interface Props { - releaseDate: string; -} - -const { releaseDate } = Astro.props; - -const { formatDate, t } = await getI18n(Astro.locals.currentLocale); ---- - -{/* ------------------------------------------- HTML ------------------------------------------- */} - -
-
- -

{t("collectibles.releaseDate")}

-
- -

{formatDate(new Date(releaseDate))}

-
- -{/* ------------------------------------------- CSS -------------------------------------------- */} - - diff --git a/src/pages/[locale]/collectibles/[slug]/index.astro b/src/pages/[locale]/collectibles/[slug]/index.astro index 0fec2a1..24c1b21 100644 --- a/src/pages/[locale]/collectibles/[slug]/index.astro +++ b/src/pages/[locale]/collectibles/[slug]/index.astro @@ -3,23 +3,24 @@ import AppLayout from "components/AppLayout/AppLayout.astro"; import AppLayoutTitle from "components/AppLayout/components/AppLayoutTitle.astro"; import TagGroups from "components/TagGroups.astro"; import { getI18n } from "src/i18n/i18n"; -import { payload } from "src/shared/payload/payload-sdk"; +import { CollectibleNature, payload } from "src/shared/payload/payload-sdk"; import { fetchOr404 } from "src/utils/responses"; import ImageTile from "./_components/ImageTile.astro"; -import PriceInfo from "./_components/PriceInfo.astro"; import SizeInfo from "./_components/SizeInfo.astro"; -import ReleaseDateInfo from "./_components/ReleaseDateInfo.astro"; import PageInfo from "./_components/PageInfo.astro"; import AvailabilityInfo from "./_components/AvailabilityInfo.astro"; import WeightInfo from "./_components/WeightInfo.astro"; import SubitemSection from "./_components/SubitemSection.astro"; import ContentsSection from "./_components/ContentsSection/ContentsSection.astro"; -import { formatInlineTitle, formatRichTextToString } from "src/utils/format"; +import { formatInlineTitle, formatLocale, formatRichTextToString } from "src/utils/format"; import AsideLayout from "components/AppLayout/AsideLayout.astro"; import AppLayoutDescription from "components/AppLayout/components/AppLayoutDescription.astro"; +import { convert } from "src/utils/currencies"; const { slug } = Astro.params; -const { getLocalizedMatch, getLocalizedUrl, t } = await getI18n(Astro.locals.currentLocale); +const { getLocalizedMatch, getLocalizedUrl, t, formatDate, formatPrice } = await getI18n( + Astro.locals.currentLocale +); const collectible = await fetchOr404(() => payload.getCollectible(slug!)); if (collectible instanceof Response) { @@ -42,9 +43,89 @@ const { parentPages, tagGroups, contents, + createdAt, + updatedAt, + updatedBy, + languages, + nature, } = collectible; const translation = getLocalizedMatch(translations); +const { pretitle, title, subtitle, description } = translation; + +const attributes = [ + { + title: t("global.media.attributes.createdAt"), + icon: "material-symbols:calendar-add-on-outline", + values: [formatDate(new Date(createdAt))], + withBorder: false, + }, + { + title: t("global.media.attributes.updatedAt"), + icon: "material-symbols:edit-calendar", + values: [formatDate(new Date(updatedAt))], + withBorder: false, + }, +]; + +if (updatedBy) { + attributes.push({ + title: t("global.media.attributes.updatedBy"), + icon: "material-symbols:person-edit-outline", + values: [updatedBy?.username], + withBorder: true, + }); +} + +const tagGroupWithAttributes = [ + ...tagGroups, + { + title: t("collectibles.nature"), + icon: "material-symbols:leaf-spark-outline", + values: [nature === CollectibleNature.Physical ? "Physical" : "Digital"], + withBorder: true, + }, +]; + +if (releaseDate) { + tagGroupWithAttributes.push({ + title: t("collectibles.releaseDate"), + icon: "material-symbols:calendar-month-outline", + values: [formatDate(new Date(releaseDate))], + withBorder: false, + }); +} + +if (languages.length > 0) { + tagGroupWithAttributes.push({ + title: t("collectibles.languages"), + icon: "material-symbols:translate", + values: languages.map((lang) => formatLocale(lang)), + withBorder: true, + }); +} + +if (price) { + const preferredCurrency = Astro.locals.currentCurrency; + + const convertedPrice = { + amount: convert(price.currency, preferredCurrency, price.amount), + currency: preferredCurrency, + }; + + let priceText = price.amount === 0 ? t("collectibles.price.free") : formatPrice(price); + + if (price.amount > 0 && price.currency !== convertedPrice.currency) { + priceText += ` (${formatPrice(convertedPrice)})`; + } + + tagGroupWithAttributes.push({ + title: t("collectibles.price"), + icon: "material-symbols:sell-outline", + values: [priceText], + withBorder: false, + }); +} --- {/* ------------------------------------------- HTML ------------------------------------------- */} @@ -52,18 +133,14 @@ const translation = getLocalizedMatch(translations); - + @@ -107,21 +184,31 @@ const translation = getLocalizedMatch(translations);
- {translation.description && } + + { + attributes.length > 0 && ( +
+ +
+ ) + } +
- - {releaseDate && } + + {description && } - {price && } +
+ + - + {size && } - {size && } + {weight && } - {weight && } - - {pageInfo && } - + {pageInfo && } + +
+
{subitems.length > 0 && } @@ -195,4 +282,24 @@ const translation = getLocalizedMatch(translations); } } } + + #tags { + margin-block: 2em; + + @media (max-width: 1280.5px) { + margin-bottom: 4em; + } + + @media (max-width: 35rem) { + margin-top: 4em; + margin-bottom: 6em; + } + } + + #attributes { + @media (min-width: 1280.5px) { + margin-left: 12em; + margin-top: 3em; + } + } diff --git a/src/pages/[locale]/index.astro b/src/pages/[locale]/index.astro index 893f7e7..4859b30 100644 --- a/src/pages/[locale]/index.astro +++ b/src/pages/[locale]/index.astro @@ -33,7 +33,7 @@ const { t, getLocalizedUrl } = await getI18n(Astro.locals.currentLocale); - +