2023-09-09 23:53:20 -05:00
|
|
|
'use client';
|
|
|
|
|
|
2023-09-11 20:20:52 -05:00
|
|
|
import { useCodeMirror, useRouter } from '@/hooks';
|
2023-09-10 20:19:31 -05:00
|
|
|
import { basicDark } from '@/lib/codemirror';
|
|
|
|
|
import { useUser } from '@clerk/nextjs';
|
2023-09-10 16:02:13 -05:00
|
|
|
import { indentWithTab } from '@codemirror/commands';
|
2023-09-10 12:14:23 -05:00
|
|
|
import { markdown, markdownLanguage } from '@codemirror/lang-markdown';
|
|
|
|
|
import { languages } from '@codemirror/language-data';
|
2023-09-10 20:19:31 -05:00
|
|
|
import { Compartment, EditorState, Text } from '@codemirror/state';
|
2023-09-10 16:02:13 -05:00
|
|
|
import { EditorView, keymap } from '@codemirror/view';
|
2023-09-10 12:14:23 -05:00
|
|
|
import { basicSetup } from 'codemirror';
|
2023-09-10 20:19:31 -05:00
|
|
|
import { useMutation } from 'convex/react';
|
2023-09-11 20:02:20 -05:00
|
|
|
import { FormEvent, useState } from 'react';
|
2023-09-10 20:19:31 -05:00
|
|
|
import { api } from '../../convex/_generated/api';
|
2023-09-11 20:02:20 -05:00
|
|
|
import { Doc } from '../../convex/_generated/dataModel';
|
2023-09-10 20:19:31 -05:00
|
|
|
import PostContent from './PostContent';
|
2023-09-09 23:53:20 -05:00
|
|
|
|
2023-09-11 20:02:20 -05:00
|
|
|
export default function Editor({ post }: { post?: Doc<'posts'> }) {
|
2023-09-11 00:40:14 -05:00
|
|
|
const { user, isSignedIn } = useUser();
|
2023-09-10 16:02:13 -05:00
|
|
|
const editorTheme = new Compartment();
|
2023-09-11 20:02:20 -05:00
|
|
|
const [currentDoc, setCurrentDoc] = useState(post?.content ?? ['']);
|
|
|
|
|
const createOrUpdatePost = useMutation(api.posts.createOrUpdatePost);
|
2023-09-10 20:19:31 -05:00
|
|
|
const router = useRouter();
|
2023-09-11 20:02:20 -05:00
|
|
|
const [creatingOrUpdating, setCreatingOrUpdating] = useState(false);
|
2023-09-10 16:02:13 -05:00
|
|
|
|
2023-09-10 12:14:23 -05:00
|
|
|
const extensions = [
|
|
|
|
|
basicSetup,
|
|
|
|
|
markdown({ base: markdownLanguage, codeLanguages: languages }),
|
|
|
|
|
EditorState.tabSize.of(2),
|
2023-09-10 20:19:31 -05:00
|
|
|
editorTheme.of(basicDark),
|
2023-09-10 16:02:13 -05:00
|
|
|
keymap.of([indentWithTab]),
|
|
|
|
|
EditorView.updateListener.of(vu => {
|
2023-09-10 20:19:31 -05:00
|
|
|
setCurrentDoc(vu.state.doc.toJSON());
|
2023-09-10 16:02:13 -05:00
|
|
|
}),
|
2023-09-10 12:14:23 -05:00
|
|
|
];
|
|
|
|
|
|
2023-09-09 23:53:20 -05:00
|
|
|
const [mode, setMode] = useState<'write' | 'preview'>('write');
|
2023-09-11 20:02:20 -05:00
|
|
|
const { editorRef } = useCodeMirror({ doc: currentDoc, extensions });
|
2023-09-10 16:02:13 -05:00
|
|
|
|
2023-09-10 20:19:31 -05:00
|
|
|
async function handleSubmit(e: FormEvent<HTMLFormElement>) {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
try {
|
2023-09-11 00:40:14 -05:00
|
|
|
if (isSignedIn !== true) {
|
2023-09-10 20:19:31 -05:00
|
|
|
router.push('/login');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-11 20:02:20 -05:00
|
|
|
setCreatingOrUpdating(true);
|
2023-09-11 00:40:14 -05:00
|
|
|
|
2023-09-11 20:02:20 -05:00
|
|
|
const result = await createOrUpdatePost({
|
|
|
|
|
id: post?._id,
|
2023-09-11 00:40:14 -05:00
|
|
|
clerkUserId: user.id,
|
2023-09-10 20:19:31 -05:00
|
|
|
content: currentDoc,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
switch (result) {
|
|
|
|
|
case 'USER_NOT_FOUND':
|
|
|
|
|
case 'USER_NOT_AUTHORIZED':
|
|
|
|
|
case 'CANNOT_POST_ON_BEHALF_OF_ANOTHER_USER':
|
|
|
|
|
throw Error('Unable to create post');
|
|
|
|
|
default:
|
|
|
|
|
router.push('/');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.log(error);
|
2023-09-11 00:40:14 -05:00
|
|
|
} finally {
|
2023-09-11 20:02:20 -05:00
|
|
|
setCreatingOrUpdating(false);
|
2023-09-10 20:19:31 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-09 23:53:20 -05:00
|
|
|
return (
|
2023-09-10 20:19:31 -05:00
|
|
|
<form
|
|
|
|
|
onSubmit={handleSubmit}
|
|
|
|
|
className='flex flex-col flex-1 shadow-md rounded-md dark:bg-secondary-gray border border-gray-600'
|
|
|
|
|
>
|
2023-09-09 23:53:20 -05:00
|
|
|
<div className='flex items-center justify-between rounded-t-md p-4 pb-0 border-b border-gray-600 dark:bg-primary-gray'>
|
|
|
|
|
<div className='flex items-center'>
|
|
|
|
|
<button
|
2023-09-10 20:19:31 -05:00
|
|
|
className='flex items-center justify-center px-3 py-2 rounded-t-md -mb-[1px] disabled:bg-white disabled:border disabled:border-b-0 disabled:border-gray-600 disabled:dark:bg-secondary-gray'
|
2023-09-09 23:53:20 -05:00
|
|
|
disabled={mode === 'write'}
|
|
|
|
|
onClick={() => setMode('write')}
|
|
|
|
|
type='button'
|
|
|
|
|
>
|
|
|
|
|
Write
|
|
|
|
|
</button>
|
|
|
|
|
<button
|
2023-09-10 20:19:31 -05:00
|
|
|
className='flex items-center justify-center px-3 py-2 rounded-t-md -mb-[1px] disabled:bg-white disabled:border disabled:border-b-0 disabled:border-gray-600 disabled:dark:bg-secondary-gray'
|
2023-09-09 23:53:20 -05:00
|
|
|
disabled={mode === 'preview'}
|
|
|
|
|
onClick={() => setMode('preview')}
|
|
|
|
|
type='button'
|
|
|
|
|
>
|
|
|
|
|
Preview
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
<div></div>
|
|
|
|
|
</div>
|
2023-09-11 21:23:37 -05:00
|
|
|
<div className='flex flex-col p-4 h-0 flex-grow overflow-auto'>
|
2023-09-10 16:02:13 -05:00
|
|
|
<div
|
2023-09-10 20:19:31 -05:00
|
|
|
className={`${mode === 'write' ? '' : 'hidden'} flex-1 overflow-auto`}
|
2023-09-10 16:02:13 -05:00
|
|
|
ref={editorRef}
|
|
|
|
|
></div>
|
2023-09-11 21:23:37 -05:00
|
|
|
<div className={`${mode === 'preview' ? '' : 'hidden'} flex-1`}>
|
2023-09-10 20:19:31 -05:00
|
|
|
<PostContent content={Text.of(currentDoc).toString()} />
|
|
|
|
|
</div>
|
2023-09-10 12:14:23 -05:00
|
|
|
</div>
|
2023-09-11 21:23:37 -05:00
|
|
|
<div className='flex items-center justify-end p-4 gap-4'>
|
2023-09-11 20:02:20 -05:00
|
|
|
<button
|
|
|
|
|
onClick={() => router.back()}
|
|
|
|
|
type='button'
|
|
|
|
|
>
|
|
|
|
|
Cancel
|
|
|
|
|
</button>
|
2023-09-10 20:19:31 -05:00
|
|
|
<button
|
|
|
|
|
type='submit'
|
2023-09-11 20:02:20 -05:00
|
|
|
disabled={
|
|
|
|
|
!currentDoc.join() ||
|
|
|
|
|
!currentDoc.join().trim() ||
|
|
|
|
|
creatingOrUpdating
|
|
|
|
|
}
|
2023-09-11 00:40:14 -05:00
|
|
|
className='py-1 px-4 bg-primary-accent text-white rounded-md disabled:opacity-50 flex items-center justify-center gap-2'
|
2023-09-10 20:19:31 -05:00
|
|
|
>
|
|
|
|
|
Post
|
|
|
|
|
</button>
|
2023-09-09 23:53:20 -05:00
|
|
|
</div>
|
|
|
|
|
</form>
|
|
|
|
|
);
|
|
|
|
|
}
|