manifold/web/pages/date-docs/create.tsx
James Grugett b21daa1248
Date docs on Manifold (#941)
* Date docs

* Create date doc

* Create and show a date market as well

* Move url to date-docs

* Date doc individual page

* Add share button

* Edit date docs

* Layout

* Add comments for create-post

* Add comments and back nav

* Fix urls

* Tweaks
2022-09-27 17:30:07 -05:00

180 lines
5.4 KiB
TypeScript

import Router from 'next/router'
import { useEffect, useState } from 'react'
import Textarea from 'react-expanding-textarea'
import { DateDoc } from 'common/post'
import { useTextEditor, TextEditor } from 'web/components/editor'
import { Page } from 'web/components/page'
import { Title } from 'web/components/title'
import { useUser } from 'web/hooks/use-user'
import { createPost } from 'web/lib/firebase/api'
import { Row } from 'web/components/layout/row'
import { Button } from 'web/components/button'
import dayjs from 'dayjs'
import { MINUTE_MS } from 'common/util/time'
import { Col } from 'web/components/layout/col'
import { uploadImage } from 'web/lib/firebase/storage'
import { LoadingIndicator } from 'web/components/loading-indicator'
import { MAX_QUESTION_LENGTH } from 'common/contract'
export default function CreateDateDocPage() {
const user = useUser()
useEffect(() => {
if (user === null) Router.push('/date')
})
const title = `${user?.name}'s Date Doc`
const [birthday, setBirthday] = useState<undefined | string>(undefined)
const [photoUrl, setPhotoUrl] = useState('')
const [avatarLoading, setAvatarLoading] = useState(false)
const [question, setQuestion] = useState(
'Will I find a partner in the next 3 months?'
)
const [isSubmitting, setIsSubmitting] = useState(false)
const { editor, upload } = useTextEditor({
disabled: isSubmitting,
})
const birthdayTime = birthday ? dayjs(birthday).valueOf() : undefined
const isValid =
user &&
birthday &&
photoUrl &&
editor &&
editor.isEmpty === false &&
question
const fileHandler = async (event: any) => {
if (!user) return
const file = event.target.files[0]
setAvatarLoading(true)
await uploadImage(user.username, file)
.then(async (url) => {
setPhotoUrl(url)
setAvatarLoading(false)
})
.catch(() => {
setAvatarLoading(false)
setPhotoUrl('')
})
}
async function saveDateDoc() {
if (!user || !editor || !birthdayTime) return
const newPost: Omit<
DateDoc,
'id' | 'creatorId' | 'createdTime' | 'slug' | 'contractSlug'
> & { question: string } = {
title,
content: editor.getJSON(),
bounty: 0,
birthday: birthdayTime,
photoUrl,
type: 'date-doc',
question,
}
const result = await createPost(newPost)
if (result.post) {
await Router.push(`/date-docs/${user.username}`)
}
}
return (
<Page>
<div className="mx-auto w-full max-w-3xl">
<div className="rounded-lg px-6 py-4 pb-4 sm:py-0">
<Row className="mb-8 items-center justify-between">
<Title className="!my-0 text-blue-500" text="Your Date Doc" />
<Button
type="submit"
disabled={isSubmitting || !isValid || upload.isLoading}
onClick={async () => {
setIsSubmitting(true)
await saveDateDoc()
setIsSubmitting(false)
}}
color="blue"
>
{isSubmitting ? 'Publishing...' : 'Publish'}
</Button>
</Row>
<Col className="gap-8">
<Col className="max-w-[160px] justify-start gap-4">
<div className="">Birthday</div>
<input
type={'date'}
className="input input-bordered"
onClick={(e) => e.stopPropagation()}
onChange={(e) => setBirthday(e.target.value)}
max={Math.round(Date.now() / MINUTE_MS) * MINUTE_MS}
disabled={isSubmitting}
value={birthday}
/>
</Col>
<Col className="gap-4">
<div className="">Photo</div>
<Row className="items-center gap-4">
{avatarLoading ? (
<LoadingIndicator />
) : (
<>
{photoUrl && (
<img
src={photoUrl}
width={80}
height={80}
className="flex h-[80px] w-[80px] items-center justify-center rounded-lg bg-gray-400 object-cover"
/>
)}
<input
className="text-sm text-gray-500"
type="file"
name="file"
accept="image/*"
onChange={fileHandler}
/>
</>
)}
</Row>
</Col>
<Col className="gap-4">
<div className="">
Tell us about you! What are you looking for?
</div>
<TextEditor editor={editor} upload={upload} />
</Col>
<Col className="gap-4">
<div className="">
Finally, we'll create an (unlisted) prediction market!
</div>
<Col className="gap-2">
<Textarea
className="input input-bordered resize-none"
maxLength={MAX_QUESTION_LENGTH}
value={question}
onChange={(e) => setQuestion(e.target.value || '')}
/>
<div className="ml-2 text-gray-500">Cost: M$100</div>
</Col>
</Col>
</Col>
</div>
</div>
</Page>
)
}