wasp/examples/realworld/ext/ArticleEditorPage.js

141 lines
3.9 KiB
JavaScript
Raw Normal View History

2020-11-20 20:22:49 +03:00
import React, { useState } from 'react'
import { Link, useHistory } from 'react-router-dom'
import useAuth from '@wasp/auth/useAuth.js'
import logout from '@wasp/auth/logout.js'
import createArticle from '@wasp/actions/createArticle'
import updateArticle from '@wasp/actions/updateArticle'
import { useQuery } from '@wasp/queries'
import getArticle from '@wasp/queries/getArticle'
import Navbar from './Navbar'
const ArticleEditorPage = (props) => {
const { data: user, isError } = useAuth({ keepPreviousData: true })
// TODO: Here, as in some other places, it feels tricky to figure out what is happening regarding the state.
2020-11-24 23:10:26 +03:00
// When is article null, when not, should I look into combination of article and articleSlug, then
2020-11-20 20:22:49 +03:00
// there is this 'enabled' which I need on the other hand -> uff. And what if I get error? humpf!
2020-11-24 23:10:26 +03:00
const articleSlug = props.match.params.articleSlug
const { data: article, error: articleError } = useQuery(getArticle, { slug: articleSlug }, { enabled: articleSlug })
2020-11-20 20:22:49 +03:00
// TODO: Instead of this logic here, I wish I could use ACL via Wasp and just
// receive user via props instead of useAuth().
if (!user || isError) {
return <span> Please <Link to='/login'>log in</Link>. </span>
}
return articleError
? articleError.message || articleError
: (
<div>
<Navbar />
<ArticleEditor user={user} article={article} />
</div>
)
}
const ArticleEditor = (props) => {
const user = props.user
const article = props.article
const history = useHistory()
const [title, setTitle] = useState(article?.title || '')
const [description, setDescription] = useState(article?.description || '')
const [markdownContent, setMarkdownContent] = useState(article?.markdownContent || '')
2020-11-25 18:25:26 +03:00
const [tags, setTags] = useState(article?.tags || [])
const [newTagName, setNewTagName] = useState('')
2020-11-20 20:22:49 +03:00
const [submitError, setSubmitError] = useState(null)
const handleSubmit = async (event) => {
event.preventDefault()
setSubmitError(null)
try {
2020-11-24 23:10:26 +03:00
let articleSlug
2020-11-20 20:22:49 +03:00
if (article?.id) {
await updateArticle({
id: article.id,
title,
description,
2020-11-25 18:25:26 +03:00
markdownContent,
tags
2020-11-20 20:22:49 +03:00
})
2020-11-24 23:10:26 +03:00
articleSlug = article.slug
2020-11-20 20:22:49 +03:00
} else {
const newArticle = await createArticle({
title,
description,
2020-11-25 18:25:26 +03:00
markdownContent,
tags
2020-11-20 20:22:49 +03:00
})
2020-11-24 23:10:26 +03:00
articleSlug = newArticle.slug
2020-11-20 20:22:49 +03:00
}
2020-11-24 23:10:26 +03:00
history.push(`/article/${articleSlug}`)
2020-11-20 20:22:49 +03:00
} catch (err) {
setSubmitError(err)
}
}
return (
<div>
{ submitError && (
<p>
{ submitError.message || submitError }
</p>
) }
<form onSubmit={handleSubmit}>
<h2>Article title</h2>
<input
type='text'
value={title}
onChange={e => setTitle(e.target.value)}
/>
<h2>What's this article about?</h2>
<input
type='text'
value={description}
onChange={e => setDescription(e.target.value)}
/>
<h2>Markdown content</h2>
2020-11-24 22:39:36 +03:00
<textarea
2020-11-20 20:22:49 +03:00
value={markdownContent}
onChange={e => setMarkdownContent(e.target.value)}
/>
2020-11-25 18:25:26 +03:00
<h2>Enter tags</h2>
<input
type="text"
value={newTagName}
onChange={e => setNewTagName(e.target.value)}
onKeyPress={e => {
if (e.key === 'Enter') {
e.preventDefault()
setTags([...tags, { name: newTagName }])
setNewTagName('')
}
}}
/>
<div>
2020-11-25 20:27:41 +03:00
{ tags.map(tag => (
<div key={tag.name}>
{tag.name}
<button onClick={() => setTags(tags.filter(t => t !== tag))}> X </button>
</div>
))}
2020-11-25 18:25:26 +03:00
</div>
2020-11-20 20:22:49 +03:00
<div>
<input type='submit' value='Publish Article' />
</div>
</form>
</div>
)
}
export default ArticleEditorPage