import { freeSewingConfig as config } from 'shared/config/freesewing.config.mjs' // Context import { LoadingStatusContext } from 'shared/context/loading-status-context.mjs' // Hooks import { useTranslation } from 'next-i18next' import { useState, Fragment, useContext } from 'react' import { useAccount } from 'shared/hooks/use-account.mjs' import { useBackend } from 'shared/hooks/use-backend.mjs' // Components import { Popout } from 'shared/components/popout/index.mjs' import { HeartIcon, ChatIcon, BugIcon, SettingsIcon, DocsIcon, LockIcon, KeyIcon, DesignIcon, HelpIcon, LeftIcon, } from 'shared/components/icons.mjs' import { ActiveImageInput, ButtonFrame, DesignDropdown, StringInput, MarkdownInput, } from 'shared/components/inputs.mjs' import { cloudflareImageUrl } from 'shared/utils.mjs' import { CodeBox } from 'shared/components/code-box.mjs' import { WebLink } from 'shared/components/link.mjs' // Translation namespaces used on this page export const ns = ['support', 'designs', 'account', 'status'] const types = [ 'bugReport', 'designIssue', 'accountIssue', 'docsUpdate', 'question', 'featureRequest', 'security', 'patronSponsor', 'other', ] const userCard = (id) => `[![User ${id}](${config.backend}/users/${id}/card)](https://next.freesewing.org/users/${id})` const templates = { bugReport: { title: ({ title }) => `[bug]: ${title}`, labels: () => [':bug: bug'], }, designIssue: { title: ({ title, design }) => `[${design}]: ${title}`, labels: ({ design }) => [`:shirt: ${design}`], }, accountIssue: { title: ({ title }) => `[accounts]: ${title}`, labels: () => ['account'], }, docsUpdate: { title: ({ title }) => `[docs]: ${title}`, labels: () => [':book: documentation'], }, question: { title: ({ title }) => title, labels: () => [], }, featureRequest: { title: ({ title }) => `[featureRequest]: ${title}`, labels: () => [':gem: enhancement'], }, security: { title: ({ title }) => `[security]: ${title}`, labels: () => ['security'], }, patronSponsor: { title: ({ title }) => `[patrons]: ${title}`, labels: () => ['impacts-patron'], }, other: { title: ({ title }) => `[other]: ${title}`, labels: () => [], }, } const commonLabels = [':robot: robot', 'needs-triage'] const iconProps = { className: 'w-8 h-8 shrink-0' } const icons = { bugReport: , featureRequest: , docsUpdate: , security: , question: , other: , accountIssue: , designIssue: , patronSponsor: , } const SupportType = ({ type, active, t, update }) => ( update(type)}>
{t(type)} {icons[type]}
{t(`${type}Desc`)}
) export const SupportForm = () => { const { t } = useTranslation(ns) const { setLoadingStatus } = useContext(LoadingStatusContext) const { account } = useAccount() const backend = useBackend() const [type, setType] = useState(false) const [title, setTitle] = useState('') const [design, setDesign] = useState('') const [body, setBody] = useState('') const [images, setImages] = useState({}) const [issue, setIssue] = useState(false) const [discussion, setDiscussion] = useState(false) const addImage = () => { const id = Object.keys(images).length + 1 const newImages = { ...images } newImages[id] = null setImages(newImages) } const setSingleImage = (id, img) => { const newImages = { ...images } newImages[id] = img setImages(newImages) } const clear = () => { setIssue(false) setDiscussion(false) setType(false) setTitle('') setDesign('') setBody('') setImages({}) } const submit = async () => { setLoadingStatus([true, 'gatheringInfo']) const templateData = { title, design } const issueData = { title: templates[type].title(templateData), body: `${body}\n\n${userCard(account.id || false)}`, labels: [...commonLabels, ...templates[type].labels(templateData)], } setLoadingStatus([true, 'submittingData']) const result = type === 'question' ? await backend.createDiscussion(issueData) : await backend.createIssue(issueData) if (result.success) { setLoadingStatus([true, 'settingsSaved', true, true]) if (type === 'question') setDiscussion(result.data.discussion.data.createDiscussion.discussion.url) else setIssue(result.data.issue) } else setLoadingStatus([true, 'backendError', true, false]) } if (issue || discussion) return (
{t('requestCreated')}

We have created your request, you can find it here:

) if (!type) return ( <>
{types.map((_type) => ( ))}

) return (
setType(false)} t={t} /> val.length > 10} docs={

{t('title')}

{t('titleDocs1')}

{t('titleDocs2')}

} /> {type === 'designIssue' && ( Not related to a design} label={t('design')} update={setDesign} current={design} valid={(val) => val.length > 1} docs={

{t('design')}

{t('designDocs1')}

} /> )} val.length > 10} docs={

{t('description')}

{t('descriptionDocs1')}

} /> {Object.keys(images).map((key) => { const markup = '![Uploaded image](' + cloudflareImageUrl({ id: images[key], variant: 'public' }) + ')' return ( setSingleImage(key, val)} current={images[key]} valid={(val) => val.length > 1} docs={

{t('image')}

{t('imageDocs1')}

} imgType="support" imgSubid={key} imgSlug={Date.now()} /> {images[key] && ( {t('addImageToMd')}:

)}
) })} {Object.keys(images).length < 9 && ( )}
) }