// Dependencies
import {
about,
collection,
tags,
techniques,
examples,
requiredMeasurements,
optionalMeasurements,
} from '@freesewing/collection'
import { capitalize, linkClasses, mutateObject } from '@freesewing/utils'
import { measurements as measurementsTranslations } from '@freesewing/i18n'
// Hooks
import React, { useState, Fragment } from 'react'
import { useFilter } from '@freesewing/react/hooks/useFilter'
// Components
import { Link as WebLink } from '@freesewing/react/components/Link'
import {
CircleIcon,
CisFemaleIcon,
DocsIcon,
FilterIcon,
NewPatternIcon,
ResetIcon,
ShowcaseIcon,
} from '@freesewing/react/components/Icon'
import {
lineDrawingsFront as lineDrawings,
lineDrawingsBack,
} from '@freesewing/react/components/LineDrawing'
import { IconButton } from '@freesewing/react/components/Button'
import { KeyVal } from '@freesewing/react/components/KeyVal'
import { MissingLinedrawing } from '../LineDrawing/missing.mjs'
/**
* A component to show the FreeSewing collection and pick a design.
*
* @component
* @param {object} props - All component props
* @param {React.Component} [props.Link = false] - A framework specific Link component for client-side routing
* @param {boolean} [props.editor = false] - Set this to true when rendering inside the FreeSewing editor
* @param {string} [props.linkTo = 'about'] - This controls where to link the design to. One of 'new', 'docs', or 'about'.
* @param {functino} [props.onClick = false] - You can pass in an onClick handler rather than using links
* @returns {JSX.Element}
*/
export const Collection = ({ Link = false, linkTo = 'about', editor = false, onClick = false }) => {
if (!Link) Link = WebLink
// State
const [filter, setFilter] = useFilter()
const [showFilters, setShowFilters] = useState(false)
/*
* Apply filter
*/
const filtered = {}
for (const d of collection) {
let skip = false
if (
filter.tag &&
filter.tag.filter((tag) => about[d].tags.includes(tag)).length < filter.tag.length
)
skip = true
if (
filter.tech &&
filter.tech.filter((tech) => about[d].techniques.includes(tech)).length < filter.tech.length
)
skip = true
if (filter.difficulty && filter.difficulty !== about[d].difficulty) skip = true
if (!skip) filtered[d] = d
}
const updateFilter = (path, val) => {
// Allow clicking the same difficulty to remove it as a filter
if (path === 'difficulty' && val === filter.difficulty) val = 'unset'
const newFilter = mutateObject({ ...filter }, path, val)
setFilter(newFilter)
}
const toggle = (type, val) => {
const current = filter[type] || []
const newSet = new Set(current)
if (newSet.has(val)) newSet.delete(val)
else newSet.add(val)
updateFilter(type, [...newSet])
}
return (
<>
)
return onClick ? (
) : (
{inner}
)
}
/*
* A helper component to show difficulety of a design
*
* @param {object} props - All React props
* @param {number} props.score - The difficulty score of the design (1-5)
*/
const Difficulty = ({ score = 0, className = '' }) => (
{[0, 1, 2, 3, 4].map((i) => (
))}
)
const linkBuilders = {
new: (design) =>
`/editor/#s={%22design%22%3A%22${design.toLowerCase()}%22%2C%22view%22%3A%22draft%22}`,
docs: (design) => `/docs/designs/${design.toLowerCase()}/`,
about: (design) => `/designs/${design.toLowerCase()}/`,
}
const noExample =
'https://images.pexels.com/photos/5626595/pexels-photo-5626595.jpeg?cs=srgb&fm=jpg&w=640&h=427'
/**
* A component to show info about a FreeSewing design
*
* @component
* @param {object} props - All component props
* @param {React.Component} props.Link - A framework specific Link component for client-side routing
* @param {string} props.design - The name/id of the design
* @param {boolean} props.noDocsLink - Set this to true to not render a link to the documentation
* @returns {JSX.Element}
*/
export const DesignInfo = ({ Link = false, design = false, noDocsLink = false }) => {
if (!Link) Link = WebLink
// State
const [back, setBack] = useState(false)
if (!design) return null
// Line drawings
const LineDrawing = lineDrawings[design] || MissingLinedrawing
const LineDrawingBack = lineDrawingsBack[design] || null
// Make sure these always hold arrays, that way we can just map() over them in the JSX output
const codeBy = Array.isArray(about[design].code) ? about[design].code : [about[design].code]
const designBy = Array.isArray(about[design].design)
? about[design].design
: [about[design].design]
const tags = about[design].tags || []
const techniques = about[design].techniques || []
const makeButton = (