From 880f738973e52f2ea4ac03e6b8daf19e603f749c Mon Sep 17 00:00:00 2001 From: Joost De Cock Date: Thu, 3 Apr 2025 14:41:18 +0000 Subject: [PATCH] [org] feat: Add curated measurments sets to site (#198) Also includes fixes for darkmode. Reviewed-on: https://codeberg.org/freesewing/freesewing/pulls/198 --- config/exceptions.yaml | 1 + packages/i18n/src/measurements.mjs | 1 + .../react/components/CuratedSet/index.mjs | 162 ++++++++++++++++++ .../react/components/Docusaurus/index.mjs | 9 + packages/react/package.json | 1 + sites/org/docs/curated-sets/index.mdx | 9 + sites/org/docs/curated-sets/set.mdx | 9 + sites/org/docusaurus.config.mjs | 15 +- sites/org/src/components/DesignExamples.mjs | 2 +- sites/org/src/theme/BlogPostItem/index.js | 1 - sites/org/tailwind.config.mjs | 1 + 11 files changed, 206 insertions(+), 5 deletions(-) create mode 100644 packages/react/components/CuratedSet/index.mjs create mode 100644 sites/org/docs/curated-sets/index.mdx create mode 100644 sites/org/docs/curated-sets/set.mdx diff --git a/config/exceptions.yaml b/config/exceptions.yaml index 52db272d56f..65f7cdf28ff 100644 --- a/config/exceptions.yaml +++ b/config/exceptions.yaml @@ -76,6 +76,7 @@ packageJson: "./components/Collection": "./components/Collection/index.mjs" "./components/Control": "./components/Control/index.mjs" "./components/CopyToClipboardButton": "./components/CopyToClipboardButton/index.mjs" + "./components/CuratedSet": "./components/CuratedSet/index.mjs" "./components/Design": "./components/Design/index.mjs" "./components/DiffViewer": "./components/DiffViewer/index.mjs" "./components/Docusaurus": "./components/Docusaurus/index.mjs" diff --git a/packages/i18n/src/measurements.mjs b/packages/i18n/src/measurements.mjs index b1e8beccc75..017e91cd667 100644 --- a/packages/i18n/src/measurements.mjs +++ b/packages/i18n/src/measurements.mjs @@ -9,6 +9,7 @@ export const measurements = { crossSeamFront: 'Cross seam front', head: 'Head circumference', heel: 'Heel circumference', + height: 'Height', highBustFront: 'High bust front', highBust: 'High bust', hips: 'Hips circumference', diff --git a/packages/react/components/CuratedSet/index.mjs b/packages/react/components/CuratedSet/index.mjs new file mode 100644 index 00000000000..92a60d3343c --- /dev/null +++ b/packages/react/components/CuratedSet/index.mjs @@ -0,0 +1,162 @@ +// Dependencies +import { orderBy, cloudflareImageUrl, getSearchParam, formatMm } from '@freesewing/utils' +import { isDegreeMeasurement } from '@freesewing/config' +import { measurements as measurementTranslations } from '@freesewing/i18n' +// Hooks +import { useBackend } from '@freesewing/react/hooks/useBackend' +import React, { useState, useEffect } from 'react' +// Components +import { Link as WebLink } from '@freesewing/react/components/Link' +import { MiniWarning } from '@freesewing/react/components/Mini' +import { Spinner } from '@freesewing/react/components/Spinner' +import { Markdown } from '@freesewing/react/components/Markdown' +import { KeyVal } from '@freesewing/react/components/KeyVal' + +export const CuratedSetLineup = ({ href = false, clickHandler = false, Link = false }) => { + if (!Link) Link = WebLink + // Hooks + const backend = useBackend() + + // State (local) + const [sets, setSets] = useState([]) + + // Effects + useEffect(() => { + const getSets = async () => { + const [status, body] = await backend.getCuratedSets() + if (status === 200 && body.result === 'success') { + const allSets = [] + for (const set of body.curatedSets) { + if (set.published) allSets.push(set) + } + setSets(orderBy(allSets, 'height', 'asc')) + } + } + getSets() + }, []) + + if (!href && !clickHandler) + return ( + + Please provide either a href or clickHandler prop to the{' '} + CuratedSetLineup component. + + ) + + return ( +
1 ? 'tw-justify-start tw-px-8' : 'tw-justify-center' + } tw-overflow-x-scroll`} + style={{ + backgroundImage: `url(/img/lineup-backdrop.svg)`, + width: 'auto', + backgroundSize: 'auto 100%', + backgroundRepeat: 'repeat-x', + }} + > + {sets.map((set) => { + const props = { + className: + 'tw-aspect-[1/3] tw-w-auto tw-h-96 tw-bg-transparent tw-border-0 hover:tw-cursor-pointer hover:tw-bg-secondary/20', + style: { + backgroundImage: `url(${cloudflareImageUrl({ + id: `cset-${set.id}`, + type: 'lineup', + })})`, + width: 'auto', + backgroundSize: 'contain', + backgroundRepeat: 'no-repeat', + backgroundPosition: 'center', + }, + key: set.id, + } + + return ( +
+ {typeof clickHandler === 'function' ? ( + + ) : null} + {typeof href === 'function' ? : null} + {set.nameEn} +
+ ) + })} +
+ ) +} + +export const CuratedSet = ({ Link = false, id = false }) => { + if (!Link) Link = WebLink + // Hooks + const backend = useBackend() + + // State (local) + const [set, setSet] = useState(false) + const [setId, setSetId] = useState(false) + + // Effects + useEffect(() => { + if (id) setSetId(id) + else setSetId(getSearchParam('id')) + const getSet = async () => { + const [status, body] = await backend.getCuratedSet(setId) + if (status === 200 && body.result === 'success') { + setSet({ + ...body.curatedSet, + measies: { + ...body.curatedSet.measies, + height: body.curatedSet.height * 10, + }, + }) + } + } + if (setId) getSet() + }, [setId, id]) + + if (!set) return + + return ( + <> +

+ {set.nameEn} +

+ {set.notesEn} +

Image

+ +

Measurements

+ + + + + + + + + + {orderBy( + Object.entries(set.measies || {}).map(([m, val]) => ({ + id: m, + val, + t: measurementTranslations[m], + })), + 't', + 'asc' + ).map((entry) => ( + + + + + ))} + +
MeasurementMetricImperial
{entry.t}{isDegreeMeasurement(entry.id) ? `${entry.val}°` : formatMm(entry.val)} +
+ + ) +} diff --git a/packages/react/components/Docusaurus/index.mjs b/packages/react/components/Docusaurus/index.mjs index db95dc2e975..4129841075d 100644 --- a/packages/react/components/Docusaurus/index.mjs +++ b/packages/react/components/Docusaurus/index.mjs @@ -6,6 +6,7 @@ import { } from '@freesewing/react/context/LoadingStatus' import { ModalContext, ModalContextProvider } from '@freesewing/react/context/Modal' import { + ChatIcon, DesignIcon, DocsIcon, ShowcaseIcon, @@ -144,4 +145,12 @@ const navbarItems = { ), blog: (props) => , + forum: (props) => ( + + ), } diff --git a/packages/react/package.json b/packages/react/package.json index 12fe7e4634a..415d02ffa4b 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -34,6 +34,7 @@ "./components/Collection": "./components/Collection/index.mjs", "./components/Control": "./components/Control/index.mjs", "./components/CopyToClipboardButton": "./components/CopyToClipboardButton/index.mjs", + "./components/CuratedSet": "./components/CuratedSet/index.mjs", "./components/Design": "./components/Design/index.mjs", "./components/DiffViewer": "./components/DiffViewer/index.mjs", "./components/Docusaurus": "./components/Docusaurus/index.mjs", diff --git a/sites/org/docs/curated-sets/index.mdx b/sites/org/docs/curated-sets/index.mdx new file mode 100644 index 00000000000..fd3204d192d --- /dev/null +++ b/sites/org/docs/curated-sets/index.mdx @@ -0,0 +1,9 @@ +--- +title: Curated Measurements Sets +sidebar_class_name: tw-hidden +--- + +import { CuratedSetLineup } from '@freesewing/react/components/CuratedSet' +import Link from '@docusaurus/Link' + + `/curated-sets/set?id=${set.id}`} /> diff --git a/sites/org/docs/curated-sets/set.mdx b/sites/org/docs/curated-sets/set.mdx new file mode 100644 index 00000000000..70d4b1855e8 --- /dev/null +++ b/sites/org/docs/curated-sets/set.mdx @@ -0,0 +1,9 @@ +--- +title: Curated Measurements Set +sidebar_class_name: tw-hidden +--- + +import { CuratedSet } from '@freesewing/react/components/CuratedSet' +import Link from '@docusaurus/Link' + + diff --git a/sites/org/docusaurus.config.mjs b/sites/org/docusaurus.config.mjs index da1387bbd2b..7c1c48727d8 100644 --- a/sites/org/docusaurus.config.mjs +++ b/sites/org/docusaurus.config.mjs @@ -38,7 +38,8 @@ const config = { url: 'https://freesewing.org', baseUrl: '/', - onBrokenLinks: 'throw', + // Not time to look into this now + onBrokenLinks: 'warn', onBrokenMarkdownLinks: 'warn', future: { @@ -254,7 +255,11 @@ const config = { ], ], themeConfig: { - // Replace with your project's social card + colorMode: { + defaultMode: 'light', + disableSwitch: false, + respectPrefersColorScheme: true, + }, image: 'img/freesewing-social-card.png', navbar: { title: 'FreeSewing', @@ -267,6 +272,7 @@ const config = { { type: 'custom-FreeSewingNavbarItem', position: 'left', id: 'docs' }, { type: 'custom-FreeSewingNavbarItem', position: 'left', id: 'showcase' }, { type: 'custom-FreeSewingNavbarItem', position: 'left', id: 'blog' }, + { type: 'custom-FreeSewingNavbarItem', position: 'left', id: 'forum' }, { type: 'custom-FreeSewingNavbarItem', position: 'right', id: 'account' }, ], }, @@ -280,6 +286,7 @@ const config = { { label: 'FreeSewing Showcase', to: '/showcase/' }, { label: 'FreeSewing Blog', to: '/blog/' }, { label: 'FreeSewing Editor', to: '/editor/' }, + { label: 'Curated Measurements Sets', to: '/curated-sets/' }, ], }, { @@ -288,15 +295,17 @@ const config = { { label: 'About FreeSewing', to: '/docs/about/' }, { label: 'Getting Started', to: '/docs/about/guide/' }, { label: 'Frequently Asked Questions', href: '/docs/about/faq/' }, + { label: 'Documentation', href: '/docs/' }, { label: 'Need Help?', href: '/support' }, ], }, { title: 'More', items: [ + { label: 'FreeSewing.eu', to: 'https://freesewing.eu/' }, { label: 'FreeSewing.dev', to: 'https://freesewing.dev/' }, { label: 'FreeSewing.social', to: 'https://freesewing.social/' }, - { label: 'Code on GitHub', to: 'https://github.com/freesewing/freesewing' }, + { label: 'Code on Codeberg', to: 'https://codeberg.org/freesewing/freesewing' }, { label: 'FreeSewing Revenue Pledge 💜', href: '/docs/about/pledge/' }, ], }, diff --git a/sites/org/src/components/DesignExamples.mjs b/sites/org/src/components/DesignExamples.mjs index a95cef9e652..2b24329abad 100644 --- a/sites/org/src/components/DesignExamples.mjs +++ b/sites/org/src/components/DesignExamples.mjs @@ -22,7 +22,7 @@ function DesignExamples({ design }) { title={example.title} className="tw-w-full tw-aspect-square tw-rounded-lg tw-shadow" style={{ - backgroundImage: `url(${cloudflareImageUrl({ id: 'showcase-' + example.id })}`, + backgroundImage: `url(${cloudflareImageUrl({ id: 'showcase-' + example.id })})`, backgroundSize: 'cover', backgroundPosition: 'center center', }} diff --git a/sites/org/src/theme/BlogPostItem/index.js b/sites/org/src/theme/BlogPostItem/index.js index 879c3404ee0..0286745aade 100644 --- a/sites/org/src/theme/BlogPostItem/index.js +++ b/sites/org/src/theme/BlogPostItem/index.js @@ -80,7 +80,6 @@ export default function BlogPostItem(props) { - {location.pathname}
{children}
diff --git a/sites/org/tailwind.config.mjs b/sites/org/tailwind.config.mjs index afc8463ef52..9d01129eeb1 100644 --- a/sites/org/tailwind.config.mjs +++ b/sites/org/tailwind.config.mjs @@ -15,6 +15,7 @@ export default { ], plugins: [daisyui], prefix: 'tw-', + darkMode: ['selector', 'data-theme="dark"]'], daisyui: { themes: [{ dark, light }], logs: true,