147 lines
4 KiB
JavaScript
147 lines
4 KiB
JavaScript
// 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>
|
|
)
|
|
}
|