CoastalCommitsPastes/client/components/new-post/index.tsx

157 lines
5.6 KiB
TypeScript
Raw Normal View History

import Button from '@geist-ui/core/dist/button'
import useToasts from '@geist-ui/core/dist/use-toasts'
import ButtonDropdown from '@geist-ui/core/dist/button-dropdown'
2022-03-06 19:46:59 -05:00
import { useRouter } from 'next/router';
import { useCallback, useState } from 'react'
2022-03-12 23:40:28 -05:00
import generateUUID from '@lib/generate-uuid';
2022-03-21 06:28:06 -04:00
import DocumentComponent from '../document';
import FileDropzone from './drag-and-drop';
2022-03-06 19:46:59 -05:00
import styles from './post.module.css'
import Title from './title';
2022-03-15 15:15:54 -04:00
import Cookies from 'js-cookie'
2022-03-21 06:28:06 -04:00
import type { PostVisibility, Document as DocumentType } from '@lib/types';
import PasswordModal from './password';
import getPostPath from '@lib/get-post-path';
2022-03-06 19:46:59 -05:00
const Post = () => {
const { setToast } = useToasts()
const router = useRouter();
const [title, setTitle] = useState<string>()
2022-03-21 06:28:06 -04:00
const [docs, setDocs] = useState<DocumentType[]>([{
2022-03-06 19:46:59 -05:00
title: '',
content: '',
id: generateUUID()
}])
2022-03-21 06:28:06 -04:00
const [passwordModalVisible, setPasswordModalVisible] = useState(false)
const sendRequest = useCallback(async (url: string, data: { visibility?: PostVisibility, title?: string, files?: DocumentType[], password?: string, userId: string }) => {
const res = await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${Cookies.get('drift-token')}`
},
body: JSON.stringify({
title,
files: docs,
...data,
})
})
if (res.ok) {
const json = await res.json()
router.push(getPostPath(json.visibility, json.id))
2022-03-21 06:28:06 -04:00
} else {
const json = await res.json()
setToast({
2022-03-21 21:51:19 -04:00
text: json.error.message,
2022-03-21 06:28:06 -04:00
type: 'error'
})
2022-03-21 21:51:19 -04:00
setPasswordModalVisible(false)
setSubmitting(false)
2022-03-21 06:28:06 -04:00
}
}, [docs, router, setToast, title])
2022-03-06 19:46:59 -05:00
const [isSubmitting, setSubmitting] = useState(false)
const remove = (id: string) => {
setDocs(docs.filter((doc) => doc.id !== id))
}
2022-03-21 06:28:06 -04:00
const onSubmit = async (visibility: PostVisibility, password?: string) => {
2022-03-21 21:51:19 -04:00
console.log(visibility, password, passwordModalVisible)
2022-03-21 06:28:06 -04:00
if (visibility === 'protected' && !password) {
setPasswordModalVisible(true)
return
}
2022-03-21 21:51:19 -04:00
setSubmitting(true)
2022-03-21 06:28:06 -04:00
await sendRequest('/server-api/posts/create', {
title,
files: docs,
visibility,
password,
userId: Cookies.get('drift-userid') || ''
2022-03-06 19:46:59 -05:00
})
2022-03-21 06:28:06 -04:00
}
const onClosePasswordModal = () => {
setPasswordModalVisible(false)
2022-03-21 21:51:19 -04:00
setSubmitting(false)
2022-03-06 19:46:59 -05:00
}
const updateTitle = useCallback((title: string, id: string) => {
setDocs(docs.map((doc) => doc.id === id ? { ...doc, title } : doc))
}, [docs])
const updateContent = useCallback((content: string, id: string) => {
setDocs(docs.map((doc) => doc.id === id ? { ...doc, content } : doc))
}, [docs])
2022-03-21 06:28:06 -04:00
const uploadDocs = useCallback((files: DocumentType[]) => {
// if no title is set and the only document is empty,
const isFirstDocEmpty = docs.length <= 1 && (docs.length ? docs[0].title === '' : true)
const shouldSetTitle = !title && isFirstDocEmpty
if (shouldSetTitle) {
if (files.length === 1) {
setTitle(files[0].title)
} else if (files.length > 1) {
setTitle('Uploaded files')
}
}
if (isFirstDocEmpty) setDocs(files)
else setDocs([...docs, ...files])
}, [docs, title])
2022-03-06 19:46:59 -05:00
return (
<div>
<Title title={title} setTitle={setTitle} />
<FileDropzone setDocs={uploadDocs} />
2022-03-06 19:46:59 -05:00
{
docs.map(({ content, id, title }) => {
2022-03-06 19:46:59 -05:00
return (
2022-03-21 06:28:06 -04:00
<DocumentComponent
2022-03-06 19:46:59 -05:00
remove={() => remove(id)}
key={id}
editable={true}
setContent={(content) => updateContent(content, id)}
setTitle={(title) => updateTitle(title, id)}
content={content}
title={title}
2022-03-06 19:46:59 -05:00
/>
)
})
}
<div className={styles.buttons}>
<Button
className={styles.button}
onClick={() => {
setDocs([...docs, {
title: '',
content: '',
id: generateUUID()
}])
}}
style={{ flex: .5, lineHeight: '40px' }}
type="default"
>
Add a File
2022-03-06 19:46:59 -05:00
</Button>
<ButtonDropdown loading={isSubmitting} type="success">
<ButtonDropdown.Item main onClick={() => onSubmit('private')}>Create Private</ButtonDropdown.Item>
<ButtonDropdown.Item onClick={() => onSubmit('public')} >Create Public</ButtonDropdown.Item>
<ButtonDropdown.Item onClick={() => onSubmit('unlisted')} >Create Unlisted</ButtonDropdown.Item>
2022-03-21 06:28:06 -04:00
<ButtonDropdown.Item onClick={() => onSubmit('protected')} >Create with Password</ButtonDropdown.Item>
2022-03-06 19:46:59 -05:00
</ButtonDropdown>
2022-03-21 06:28:06 -04:00
<PasswordModal isOpen={passwordModalVisible} onClose={onClosePasswordModal} onSubmit={(password) => onSubmit('protected', password)} />
2022-03-06 19:46:59 -05:00
</div>
2022-03-21 18:55:21 -04:00
</div>
2022-03-06 19:46:59 -05:00
)
}
2022-03-21 06:28:06 -04:00
export default Post