// Dependencies import { nsMerge, capitalize, cloudflareImageUrl, yyyymmdd } from 'shared/utils.mjs' // Hooks import { useState, useEffect } from 'react' 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 { useTranslation } from 'next-i18next' // Components import { Popout } from 'shared/components/popout/index.mjs' import { AuthWrapper, ns as authNs } from 'shared/components/wrappers/auth/index.mjs' import { DesignPicker } from './design-picker.mjs' import { TitleInput, SlugInput, ImageInput, CaptionInput, IntroInput, BodyInput, } from './inputs.mjs' import { Collapse } from 'shared/components/collapse.mjs' import { Tab } from 'shared/components/account/bio.mjs' import { CodeBox } from 'shared/components/code-box.mjs' import { PostArticle, ns as mdxNs } from 'site/components/mdx/posts/article.mjs' import { PageLink } from 'shared/components/page-link.mjs' import { OkIcon, WarningIcon as KoIcon } from 'shared/components/icons.mjs' export const ns = nsMerge('account', 'posts', authNs, mdxNs) const Title = ({ children }) => (

{children}

) const Tip = ({ children }) =>

{children}

const Item = ({ title, children }) => (
{title}
{children}
) const dataAsMd = ({ title, maker, caption, intro, designs, body }) => `--- title: "${title}" maker: ${maker} caption: "${caption}" date: ${yyyymmdd()} intro: "${intro}" designs: [${designs.map((design) => `"${design}"`).join(', ')}] --- ${body} ` export const CreateShowcasePost = ({ noTitle = false }) => { const { account } = useAccount() const backend = useBackend() const toast = useToast() const { t, i18n } = useTranslation(ns) const [designs, setDesigns] = useState([]) const [title, setTitle] = useState('') const [slug, setSlug] = useState(false) const [img, setImg] = useState(false) const [caption, setCaption] = useState('') const [intro, setIntro] = useState('') const [body, setBody] = useState('') const [extraImages, setExtraImages] = useState({}) const [activeTab, setActiveTab] = useState('create') // Method that submits the PR const submitPullRequest = async () => { const result = await backend.createShowcasePr({ markdown: dataAsMd({ title, maker: account.username, caption, intro, designs, body, }), slug, language: i18n.language, }) } // Shared props for tabs const tabProps = { activeTab, setActiveTab, t } const addImage = () => { const id = Object.keys(extraImages).length + 1 const newImages = { ...extraImages } newImages[id] = null setExtraImages(newImages) } const setExtraImg = (key, img) => { const newImages = { ...extraImages } newImages[key] = img setExtraImages(newImages) } const childProps = { designs, setDesigns, title, setTitle, slug, setSlug, img, setImg, caption, setCaption, intro, setIntro, body, setBody, extraImages, setExtraImages, addImage, setExtraImg, account, t, } return (
{activeTab === 'create' ? ( ) : ( )}
{!(title && slug && img && designs.length > 0) && (
You are missing the following:
    {designs.length < 1 &&
  • Design
  • } {!title &&
  • Title
  • } {!slug &&
  • Slug
  • } {!img &&
  • Main Image
  • }
)} {!account.data?.githubUser && !account.data?.githubEmail && (
Optional: Are you on GitHub?

If you configure your GitHub username{' '} , we will credit these changes to you.

)}
) } const ShowcasePreview = ({ designs, title, img, caption, intro, body, account }) => ( <>

{title}

) const ShowcaseEditor = ({ designs, setDesigns, title, setTitle, slug, setSlug, img, setImg, caption, setCaption, intro, setIntro, body, setBody, extraImages, setExtraImages, addImage, setExtraImg, t, }) => ( <>

Create a new showcase post

{t('showcaseNewInfo')} {designs.length > 0 ? ( ) : ( )} Design: {designs.length > 0 ? ( {designs.map((d) => capitalize(d)).join(', ')} ) : ( Please select at least 1 design )} } > Pick one or more designs that are featured in this post. {title.length > 10 ? ( ) : ( )} Title: {title.length > 10 ? ( {title} ) : ( Please enter a post title )} } > Give your post a title. A good title is more than just a few words. {slug.length > 3 ? ( ) : ( )} Slug: {slug.length > 3 ? ( {slug} ) : ( Please enter a slug (or post title) )} } > The slug is the part of the URL that uniquely identifies the post. We can generate one based on the title, but you can also customize it. {img.length > 3 ? ( ) : ( )} Main Image: {img.length > 3 ? ( {img} ) : ( Please provide a main image for the post )} } > The main image will be shown at the top of the post, and as the only image on the showcase index page. {caption.length > 3 ? ( ) : ( )} Main Image Caption: {caption.length > 3 ? ( {caption} ) : ( Please provide a caption for the main image )} } > The caption is the text that goes under the main image. Can include copyrights/credits. Markdown is allowed. {intro.length > 3 ? ( ) : ( )} Intro: {intro.length > 3 ? ( {intro} ) : ( Please provide an intro for link proviews )} } > A brief paragraph that will be shown on post previews on social media and so on. Additional Images: {Object.keys(extraImages).length} } > {img ? ( <> Here you can add any images you want to include in the post body. {Object.keys(extraImages).map((key) => { const markup = '![The image alt goes here](' + cloudflareImageUrl({ id: extraImages[key], variant: 'public' }) + ' "The image caption/title goes here")' return ( <> setExtraImg(key, img)} type="showcase" subId={key} img={extraImages[key]} slug={slug} /> {extraImages[key] && ( <>

To include this image in your post, use this markdown snippet:

)} ) })} ) : ( Please add a main image first )}
{body.length > 3 ? ( ) : ( )} Post body: {body.length > 3 ? ( {body.slice(0, 30) + '...'} ) : ( Please provide a post body )} } > The actual post body. Supports Markdown. )