diff --git a/web/components/contract/contract-description.tsx b/web/components/contract/contract-description.tsx
index b2f839e9..d9864186 100644
--- a/web/components/contract/contract-description.tsx
+++ b/web/components/contract/contract-description.tsx
@@ -2,16 +2,17 @@ import clsx from 'clsx'
import dayjs from 'dayjs'
import { useState } from 'react'
import Textarea from 'react-expanding-textarea'
-import { CATEGORY_LIST } from '../../../common/categories'
-import { Contract } from 'common/contract'
-import { parseTags, exhibitExts } from 'common/util/parse'
+import { Contract, MAX_DESCRIPTION_LENGTH } from 'common/contract'
+import { exhibitExts, parseTags } from 'common/util/parse'
import { useAdmin } from 'web/hooks/use-admin'
import { updateContract } from 'web/lib/firebase/contracts'
import { Row } from '../layout/row'
-import { TagsList } from '../tags-list'
import { Content } from '../editor'
-import { Editor } from '@tiptap/react'
+import { TextEditor, useTextEditor } from 'web/components/editor'
+import { Button } from '../button'
+import { Spacer } from '../layout/spacer'
+import { Editor, Content as ContentType } from '@tiptap/react'
export function ContractDescription(props: {
contract: Contract
@@ -19,20 +20,39 @@ export function ContractDescription(props: {
className?: string
}) {
const { contract, isCreator, className } = props
- const descriptionTimestamp = () => `${dayjs().format('MMM D, h:mma')}: `
const isAdmin = useAdmin()
+ return (
+
+ {isCreator || isAdmin ? (
+
+ ) : (
+
+ )}
+ {isAdmin && !isCreator && (
+
(👆 admin powers)
+ )}
+
+ )
+}
- const desc = contract.description ?? ''
+function editTimestamp() {
+ return `${dayjs().format('MMM D, h:mma')}: `
+}
- // Append the new description (after a newline)
- async function saveDescription(newText: string) {
- const editor = new Editor({ content: desc, extensions: exhibitExts })
- editor
- .chain()
- .focus('end')
- .insertContent('
')
- .insertContent(newText.trim())
- .run()
+function RichEditContract(props: { contract: Contract }) {
+ const { contract } = props
+ const [editing, setEditing] = useState(false)
+ const [editingQ, setEditingQ] = useState(false)
+ const [isSubmitting, setIsSubmitting] = useState(false)
+
+ const { editor, upload } = useTextEditor({
+ max: MAX_DESCRIPTION_LENGTH,
+ defaultValue: contract.description,
+ disabled: isSubmitting,
+ })
+
+ async function saveDescription() {
+ if (!editor) return
const tags = parseTags(
`${editor.getText()} ${contract.tags.map((tag) => `#${tag}`).join(' ')}`
@@ -46,76 +66,92 @@ export function ContractDescription(props: {
})
}
- const { tags } = contract
- const categories = tags.filter((tag) =>
- CATEGORY_LIST.includes(tag.toLowerCase())
- )
-
- return (
-
-
-
- {categories.length > 0 && (
-
-
-
- )}
-
-
-
- {isCreator && (
-
- )}
- {isAdmin && (
-
updateContract(contract.id, { question })}
- buttonText="ADMIN: Edit question"
- />
- )}
- {/* {isAdmin && (
-
- updateContract(contract.id, { createdTime: Number(time) })
- }
- buttonText="ADMIN: Edit createdTime"
- />
- )} */}
-
+ return editing ? (
+ <>
+
+
+
+
+
+
+ >
+ ) : (
+ <>
+
+
+
+
+
+
+
+ >
)
}
-function EditContract(props: {
- text: string
- onSave: (newText: string) => void
- buttonText: string
+function EditQuestion(props: {
+ contract: Contract
+ editing: boolean
+ setEditing: (editing: boolean) => void
}) {
- const [text, setText] = useState(props.text)
- const [editing, setEditing] = useState(false)
- const onSave = (newText: string) => {
+ const { contract, editing, setEditing } = props
+ const [text, setText] = useState(contract.question)
+
+ function questionChanged(oldQ: string, newQ: string) {
+ return `${editTimestamp()}${oldQ} → ${newQ}
`
+ }
+
+ function joinContent(oldContent: ContentType, newContent: string) {
+ const editor = new Editor({ content: oldContent, extensions: exhibitExts })
+ editor.chain().focus('end').insertContent(newContent).run()
+ return editor.getJSON()
+ }
+
+ const onSave = async (newText: string) => {
setEditing(false)
- setText(props.text) // Reset to original text
- props.onSave(newText)
+ await updateContract(contract.id, {
+ question: newText,
+ description: joinContent(
+ contract.description,
+ questionChanged(contract.question, newText)
+ ),
+ })
}
return editing ? (
- ) : (
-
-
-
- )
+ ) : null
}
diff --git a/web/components/editor.tsx b/web/components/editor.tsx
index 43d69c26..fabce934 100644
--- a/web/components/editor.tsx
+++ b/web/components/editor.tsx
@@ -21,7 +21,7 @@ import { FileUploadButton } from './file-upload-button'
import { linkClass } from './site-link'
const proseClass = clsx(
- 'prose prose-p:my-0 prose-li:my-0 prose-blockquote:not-italic max-w-none prose-quoteless font-light'
+ 'prose prose-p:my-2 prose-li:my-0 prose-blockquote:not-italic max-w-none prose-quoteless font-light'
)
export function useTextEditor(props: {
@@ -155,7 +155,9 @@ function RichContent(props: { content: JSONContent }) {
export function Content(props: { content: JSONContent | string }) {
const { content } = props
return typeof content === 'string' ? (
-
+
+
+
) : (
)