1
Fork 0
mirror of https://github.com/Steffo99/festa.git synced 2024-12-22 22:54:22 +00:00

Capture onSubmit to save the form

This commit is contained in:
Steffo 2022-07-20 13:26:34 +02:00
parent 8f934e70f2
commit 2e69a0f963
Signed by: steffo
GPG key ID: 6965406171929D01
4 changed files with 56 additions and 46 deletions

View file

@ -1,45 +1,54 @@
import { Event } from "@prisma/client" import { Event } from "@prisma/client"
import { useCallback, useMemo } from "react" import { Dispatch, useMemo } from "react"
import { KeyedMutator } from "swr" import { KeyedMutator } from "swr"
import { UsePromise } from "../../generic/loading/promise"
import { ViewContent } from "../../generic/views/content" import { ViewContent } from "../../generic/views/content"
export type EventsActionViewProps = { export type EventsActionViewProps = {
data: Event, data: Event,
mutate: KeyedMutator<Event>, mutate: KeyedMutator<Event>,
save: UsePromise<void, void>,
setEditing: Dispatch<boolean>,
} }
export const EventsActionEdit = ({ data, mutate }: EventsActionViewProps) => { export const EventsActionEdit = ({ data, mutate, save, setEditing }: EventsActionViewProps) => {
const name = data.name const name = data.name
const description = data.description const description = data.description
return ( return (
<ViewContent <form onSubmit={e => {
title={ e.preventDefault()
useMemo( save.run()
() => ( setEditing(false)
<input }}>
type="text" <ViewContent
value={name} title={
onChange={e => mutate((prev) => ({ ...prev!, name: e.target.value }), { revalidate: false })} useMemo(
/> () => (
), <input
[mutate, name] type="text"
) value={name}
} onChange={e => mutate((prev) => ({ ...prev!, name: e.target.value }), { revalidate: false })}
content={<> />
{useMemo( ),
() => ( [mutate, name]
<textarea )
rows={12} }
value={description} content={<>
onChange={e => mutate((prev) => ({ ...prev!, description: e.target.value }), { revalidate: false })} {useMemo(
/> () => (
), <textarea
[mutate, description] rows={12}
)} value={description}
</>} onChange={e => mutate((prev) => ({ ...prev!, description: e.target.value }), { revalidate: false })}
/> />
),
[mutate, description]
)}
</>}
/>
</form>
) )
} }

View file

@ -11,14 +11,16 @@ export type EventsActionViewProps = {
export const EventsActionView = memo(({ data }: EventsActionViewProps) => { export const EventsActionView = memo(({ data }: EventsActionViewProps) => {
return ( return (
<ViewContent <form>
title={<div style={{ padding: "10px" }}> <ViewContent
{data.name} title={<div style={{ padding: "10px" }}>
</div>} {data.name}
content={<div> </div>}
<FestaMarkdownRenderer code={data.description} /> content={<div>
</div>} <FestaMarkdownRenderer code={data.description} />
/> </div>}
/>
</form>
) )
}) })
EventsActionView.displayName = "EventsActionView" EventsActionView.displayName = "EventsActionView"

View file

@ -1,6 +1,6 @@
import { faAsterisk, faPencil, faSave } from "@fortawesome/free-solid-svg-icons" import { faAsterisk, faPencil, faSave } from "@fortawesome/free-solid-svg-icons"
import { useTranslation } from "next-i18next" import { useTranslation } from "next-i18next"
import { usePromise, UsePromiseStatus } from "../../generic/loading/promise" import { UsePromise, usePromise, UsePromiseStatus } from "../../generic/loading/promise"
import { FestaIcon } from "../../generic/renderers/fontawesome" import { FestaIcon } from "../../generic/renderers/fontawesome"
import { Tool } from "../../generic/toolbar/tool" import { Tool } from "../../generic/toolbar/tool"
import cursor from "../../../styles/cursor.module.css" import cursor from "../../../styles/cursor.module.css"
@ -11,19 +11,17 @@ import { Dispatch } from "react"
export type ToolToggleEditingProps = { export type ToolToggleEditingProps = {
editing: boolean, editing: boolean,
setEditing: Dispatch<boolean>, setEditing: Dispatch<boolean>,
save: () => Promise<void>, save: UsePromise<void, void>,
} }
/** /**
* ToolBar {@link Tool} which allows the user to start editing an event and then save their changes. * ToolBar {@link Tool} which allows the user to start editing an event and then save their changes.
*/ */
export function ToolToggleEditing({ editing, setEditing, save: upperSave }: ToolToggleEditingProps) { export function ToolToggleEditing({ editing, setEditing, save }: ToolToggleEditingProps) {
const { t } = useTranslation() const { t } = useTranslation()
const { run: save, status: saveStatus } = usePromise<void, void>(upperSave) if (save.status === UsePromiseStatus.PENDING) {
if (saveStatus === UsePromiseStatus.PENDING) {
return ( return (
<Tool <Tool
aria-label={t("toolToggleEditingSaving")} aria-label={t("toolToggleEditingSaving")}
@ -39,7 +37,7 @@ export function ToolToggleEditing({ editing, setEditing, save: upperSave }: Tool
<Tool <Tool
aria-label={t("toolToggleEditingSave")} aria-label={t("toolToggleEditingSave")}
onClick={() => { onClick={() => {
save() save.run()
setEditing(false) setEditing(false)
}} }}
className={mood.positive} className={mood.positive}

View file

@ -17,6 +17,7 @@ import { useAxios } from '../../components/auth/requests'
import { database } from '../../utils/prismaClient' import { database } from '../../utils/prismaClient'
import { EventsActionEdit } from '../../components/events/actions/edit' import { EventsActionEdit } from '../../components/events/actions/edit'
import { EventsActionView } from '../../components/events/actions/view' import { EventsActionView } from '../../components/events/actions/view'
import { usePromise } from '../../components/generic/loading/promise'
export async function getServerSideProps(context: NextPageContext) { export async function getServerSideProps(context: NextPageContext) {
@ -46,13 +47,13 @@ const PageEvent: NextPage<PageEventProps> = ({ slug, fallbackData }) => {
const { data, mutate } = useSWR<Event>(`/api/events/${slug}`, { fallbackData, revalidateOnFocus: eventEditing, revalidateOnReconnect: eventEditing, refreshInterval: eventEditing ? 0 : 30000 }) const { data, mutate } = useSWR<Event>(`/api/events/${slug}`, { fallbackData, revalidateOnFocus: eventEditing, revalidateOnReconnect: eventEditing, refreshInterval: eventEditing ? 0 : 30000 })
const [auth,] = useDefinedContext(AuthContext) const [auth,] = useDefinedContext(AuthContext)
const save = useCallback( const save = usePromise<void, void>(useCallback(
async () => { async () => {
const response = await axios.patch<Event>(`/api/events/${slug}`, data!) const response = await axios.patch<Event>(`/api/events/${slug}`, data!)
mutate(response.data, { revalidate: false }) mutate(response.data, { revalidate: false })
}, },
[axios, data, mutate, slug] [axios, data, mutate, slug]
) ))
const eventName = data?.name ?? slug const eventName = data?.name ?? slug
const eventPostcard = data?.postcard || defaultPostcard const eventPostcard = data?.postcard || defaultPostcard
@ -75,7 +76,7 @@ const PageEvent: NextPage<PageEventProps> = ({ slug, fallbackData }) => {
} }
</ToolBar> </ToolBar>
{eventEditing ? {eventEditing ?
<EventsActionEdit data={data!} mutate={mutate} /> <EventsActionEdit data={data!} mutate={mutate} save={save} setEditing={eventSetEditing} />
: :
<EventsActionView data={data!} /> <EventsActionView data={data!} />
} }