// Dependencies import { useState, useEffect, useContext, useCallback } from 'react' import { useTranslation } from 'next-i18next' import orderBy from 'lodash.orderby' import { measurements, isDegreeMeasurement } from 'config/measurements.mjs' import { measurementAsMm, formatMm } from 'shared/utils.mjs' import { measurements as designMeasurements } from 'shared/prebuild/data/design-measurements.mjs' import { freeSewingConfig as conf } from 'shared/config/freesewing.config.mjs' // Hooks import { useDropzone } from 'react-dropzone' import { useAccount } from 'shared/hooks/use-account.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs' import { useToast } from 'shared/hooks/use-toast.mjs' import { useRouter } from 'next/router' // Context import { LoadingContext } from 'shared/context/loading-context.mjs' import { ModalContext } from 'shared/context/modal-context.mjs' // Components import { Collapse, useCollapseButton } from 'shared/components/collapse.mjs' import { BackToAccountButton, Choice } from './shared.mjs' import { PageLink } from 'shared/components/page-link.mjs' import { ModalDesignPicker } from 'shared/components/modal/design-picker.mjs' import { FilterIcon, ClearIcon, PlusIcon, OkIcon, NoIcon, TrashIcon, EditIcon, } from 'shared/components/icons.mjs' import { ModalWrapper } from 'shared/components/wrappers/modal.mjs' import Markdown from 'react-markdown' import { Tab } from './bio.mjs' import Timeago from 'react-timeago' import { Spinner } from 'shared/components/spinner.mjs' export const ns = ['account', 'patterns', 'toast'] export const StandAloneNewSet = () => { const { t } = useTranslation(['account']) const toast = useToast() const { account, token } = useAccount() const backend = useBackend(token) return (
) } export const NewSet = ({ t, account, refresh, closeCollapseButton, backend, toast, title = true, standalone = false, }) => { // Context const { startLoading, stopLoading } = useContext(LoadingContext) // Hooks const router = useRouter() // State const [name, setName] = useState('') const [mset, setMset] = useState(false) // Helper method to create a new set const createSet = async () => { startLoading() const result = await backend.createSet({ name, }) if (result.success) { toast.success({t('nailedIt')}) if (standalone) router.push('/account/sets/') else { setMset(result.data.set) refresh() closeCollapseButton() } } else toast.for.backendError() stopLoading() } return (
{title ?

{t('newSet')}

: null}
{t('name')}

{t('setNameDesc')}

setName(evt.target.value)} className="input w-full input-bordered flex flex-row" type="text" placeholder={'Georg Cantor'} />
) } const EditField = (props) => { if (props.field === 'name') return if (props.field === 'notes') return if (props.field === 'imperial') return if (props.field === 'public') return if (props.field === 'img') return return

FIXME: No edit component for this field

} export const EditRow = (props) => (
{props.title}
{props.children}
} toggle={} toggleClasses="btn btn-secondary" >
) const Mval = ({ m, val = false, imperial = false, className = '' }) => val ? ( isDegreeMeasurement(m) ? ( {val}° ) : ( ) ) : null export const MeasieRow = (props) => { const { t, m, mset } = props const isSet = typeof mset.measies?.[m] === 'undefined' ? false : true return (
{t(m)}
{isSet ? ( ) : (
)} } toggle={isSet ? : } toggleClasses={`btn ${isSet ? 'btn-secondary' : 'btn-neutral bg-opacity-50'}`} > ) } const MeasieInput = ({ m, mset, backend, toast, refresh }) => { const { t } = useTranslation(['measurements']) //const title = t(`measurements:${m}`) const isDegree = isDegreeMeasurement(m) const factor = isDegree ? 1 : mset.imperial ? 25.4 : 10 const isValValid = (val) => typeof val === 'undefined' || val === '' ? null : val != false && !isNaN(val) const isValid = (newVal) => (typeof newVal === 'undefined' ? isValValid(val) : isValValid(newVal)) const [val, setVal] = useState(mset.measies?.[m] / factor || '') const [valid, setValid] = useState(isValid(mset.measies?.[m] / factor || '')) // Update onChange const update = (evt) => { setVal(evt.target.value) let useVal = isDegree ? evt.target.value : measurementAsMm(evt.target.value, mset.imperial ? 'imperial' : 'metric') setValid(isValid(useVal)) } /* const save = async () => { startLoading() const measies = {} measies[m] = val * factor const result = await backend.updateSet(mset.id, { measies }) if (result.success) { refresh() toast.for.settingsSaved() } else toast.for.backendError() stopLoading() } */ const fraction = (i, base) => update({ target: { value: Math.floor(val) + i / base } }) if (!m) return null const fractionClasses = 'h-3 border-2 border-solid border-base-100 hover:border-secondary bg-secondary rounded bg-opacity-50 hover:bg-opacity-100' return (
{mset.imperial ? (
1/2
1/4 {[1, 2, 3].map((i) => (
1/8 {[1, 2, 3, 4, 5, 6, 7].map((i) => (
1/16 {[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15].map((i) => (
1/32 {[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, ].map((i) => (
) : null}
) } const EditImg = ({ t, mset, account, backend, toast, refresh, curated = false }) => { const [img, setImg] = useState(mset.img) const onDrop = useCallback((acceptedFiles) => { const reader = new FileReader() reader.onload = () => { setImg(reader.result) } acceptedFiles.forEach((file) => reader.readAsDataURL(file)) }, []) const { getRootProps, getInputProps } = useDropzone({ onDrop }) //const update = async (evt) => { // evt.preventDefault() // if (evt.target.value !== value) { // setValue(evt.target.value) // } //} return (
img

{t('imgDragAndDropImageHere')}

{t('or')}

) } const EditName = ({ t, mset, account, backend, toast, refresh }) => { const [value, setValue] = useState(mset.name) const { loading, startLoading, stopLoading } = useContext(LoadingContext) const update = async (evt) => { evt.preventDefault() if (evt.target.value !== value) { setValue(evt.target.value) } } const save = async () => { startLoading() const result = await backend.updateSet(mset.id, { name: value }) if (result.success) { refresh() toast.for.settingsSaved() } else toast.for.backendError() stopLoading() } return (
) } const EditNotes = ({ t, mset, account, backend, toast, refresh }) => { const [value, setValue] = useState(mset.notes) const [activeTab, setActiveTab] = useState('edit') const { loading, startLoading, stopLoading } = useContext(LoadingContext) const update = async (evt) => { evt.preventDefault() if (evt.target.value !== value) { setValue(evt.target.value) } } const save = async () => { startLoading() const result = await backend.updateSet(mset.id, { notes: value }) if (result.success) { refresh() toast.for.settingsSaved() } else toast.for.backendError() stopLoading() } // Shared props for tabs const tabProps = { activeTab, setActiveTab, t } return (
{activeTab === 'edit' ? (