chore(org): Move github components out of shared
This commit is contained in:
parent
50b6747584
commit
3da46fb672
7 changed files with 137 additions and 88 deletions
147
sites/org/components/github/inputs.mjs
Normal file
147
sites/org/components/github/inputs.mjs
Normal file
|
@ -0,0 +1,147 @@
|
|||
// Dependencies
|
||||
import { slugify, slugifyNoTrim, cloudflareImageUrl } from 'shared/utils.mjs'
|
||||
// Hooks
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useEffect, useState, useCallback } from 'react'
|
||||
import { useBackend } from 'shared/hooks/use-backend.mjs'
|
||||
import { useToast } from 'shared/hooks/use-toast.mjs'
|
||||
import { useDropzone } from 'react-dropzone'
|
||||
import { Popout } from 'shared/components/popout/index.mjs'
|
||||
import { Loading } from 'shared/components/spinner.mjs'
|
||||
|
||||
export const ns = ['account']
|
||||
|
||||
export const CaptionInput = ({ caption, setCaption }) => (
|
||||
<input
|
||||
className="input input-text input-bordered input-lg w-full"
|
||||
value={caption}
|
||||
placeholder="Type your caption here"
|
||||
onChange={(evt) => setCaption(evt.target.value)}
|
||||
/>
|
||||
)
|
||||
|
||||
export const IntroInput = ({ intro, setIntro }) => (
|
||||
<input
|
||||
className="input input-text input-bordered input-lg w-full"
|
||||
value={intro}
|
||||
placeholder="Type your intro here"
|
||||
onChange={(evt) => setIntro(evt.target.value)}
|
||||
/>
|
||||
)
|
||||
|
||||
export const BodyInput = ({ body, setBody }) => (
|
||||
<textarea
|
||||
className="input input-text input-bordered input-lg w-full h-96"
|
||||
placeholder="Type your post body here"
|
||||
onChange={(evt) => setBody(evt.target.value)}
|
||||
rows={16}
|
||||
>
|
||||
{body}
|
||||
</textarea>
|
||||
)
|
||||
|
||||
export const TitleInput = ({ title, setTitle }) => (
|
||||
<input
|
||||
className="input input-text input-bordered input-lg w-full"
|
||||
value={title}
|
||||
placeholder="Type your title here"
|
||||
onChange={(evt) => setTitle(evt.target.value)}
|
||||
/>
|
||||
)
|
||||
|
||||
export const SlugInput = ({ slug, setSlug, title }) => {
|
||||
useEffect(() => {
|
||||
if (title !== slug) setSlug(slugify(title))
|
||||
}, [title])
|
||||
|
||||
return (
|
||||
<input
|
||||
className="input input-text input-bordered input-lg w-full mb-2"
|
||||
value={slug}
|
||||
placeholder="Type your title here"
|
||||
onChange={(evt) => setSlug(slugifyNoTrim(evt.target.value))}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export const ImageInput = ({ slug = false, setImg, img, type = 'showcase', subId = false }) => {
|
||||
const backend = useBackend()
|
||||
const toast = useToast()
|
||||
const { t } = useTranslation(ns)
|
||||
const [uploading, setUploading] = useState(false)
|
||||
|
||||
const onDrop = useCallback(
|
||||
(acceptedFiles) => {
|
||||
const reader = new FileReader()
|
||||
reader.onload = async () => {
|
||||
setUploading(true)
|
||||
const result = await backend.uploadImage({ type, subId, slug, img: reader.result })
|
||||
setUploading(false)
|
||||
if (result.success) setImg(result.data.imgId)
|
||||
}
|
||||
acceptedFiles.forEach((file) => reader.readAsDataURL(file))
|
||||
},
|
||||
[slug]
|
||||
)
|
||||
|
||||
const { getRootProps, getInputProps } = useDropzone({ onDrop })
|
||||
|
||||
const removeImage = async () => {
|
||||
setUploading(true)
|
||||
const result = await backend.removeImage(img)
|
||||
setUploading(false)
|
||||
if (result.response.status === 204) setImg('')
|
||||
}
|
||||
|
||||
if (!slug)
|
||||
return (
|
||||
<Popout note compact>
|
||||
A <b>slug</b> is mandatory
|
||||
</Popout>
|
||||
)
|
||||
if (!subId)
|
||||
return (
|
||||
<Popout note compact>
|
||||
A <b>subId</b> prop is mandatory
|
||||
</Popout>
|
||||
)
|
||||
|
||||
if (uploading) return <Loading />
|
||||
|
||||
if (img)
|
||||
return (
|
||||
<div>
|
||||
<div
|
||||
className="bg-base-100 w-full h-36 mb-2"
|
||||
style={{
|
||||
backgroundImage: `url(${cloudflareImageUrl({
|
||||
id: img,
|
||||
variant: 'sq500',
|
||||
})})`,
|
||||
backgroundSize: 'contain',
|
||||
backgroundRepeat: 'no-repeat',
|
||||
}}
|
||||
></div>
|
||||
<button className="btn btn-error btn-sm" onClick={removeImage}>
|
||||
Remove Image
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div
|
||||
{...getRootProps()}
|
||||
className={`
|
||||
flex rounded-lg w-full flex-col items-center justify-center
|
||||
lg:h-64 lg:border-4 lg:border-secondary lg:border-dashed
|
||||
`}
|
||||
>
|
||||
<input {...getInputProps()} />
|
||||
<p className="hidden lg:block p-0 m-0">{t('imgDragAndDropImageHere')}</p>
|
||||
<p className="hidden lg:block p-0 my-2">{t('or')}</p>
|
||||
<button className={`btn btn-secondary btn-outline mt-4 px-8`}>{t('imgSelectImage')}</button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue