mirror of
https://github.com/Steffo99/festa.git
synced 2024-12-22 14:44:21 +00:00
Rework PageEvent to not use editables
This commit is contained in:
parent
b94b28853e
commit
729f136eb7
4 changed files with 108 additions and 89 deletions
42
components/events/actions/edit.tsx
Normal file
42
components/events/actions/edit.tsx
Normal file
|
@ -0,0 +1,42 @@
|
|||
import { Event } from "@prisma/client"
|
||||
import { useMemo } from "react"
|
||||
import { KeyedMutator } from "swr"
|
||||
import { ViewContent } from "../../generic/views/content"
|
||||
|
||||
|
||||
export type EventsActionViewProps = {
|
||||
data: Event,
|
||||
mutate: KeyedMutator<Event>,
|
||||
}
|
||||
|
||||
|
||||
export const EventsActionEdit = ({ data, mutate }: EventsActionViewProps) => {
|
||||
return (
|
||||
<ViewContent
|
||||
title={
|
||||
useMemo(
|
||||
() => (
|
||||
<input
|
||||
type="text"
|
||||
value={data.name}
|
||||
onChange={e => mutate({ ...data, name: e.target.value }, { revalidate: false })}
|
||||
/>
|
||||
),
|
||||
[data.name]
|
||||
)
|
||||
}
|
||||
content={<>
|
||||
{useMemo(
|
||||
() => (
|
||||
<textarea
|
||||
rows={12}
|
||||
value={data.description}
|
||||
onChange={e => mutate({ ...data, description: e.target.value }, { revalidate: false })}
|
||||
/>
|
||||
),
|
||||
[data.description]
|
||||
)}
|
||||
</>}
|
||||
/>
|
||||
)
|
||||
}
|
24
components/events/actions/view.tsx
Normal file
24
components/events/actions/view.tsx
Normal file
|
@ -0,0 +1,24 @@
|
|||
import { Event } from "@prisma/client"
|
||||
import { memo } from "react"
|
||||
import { FestaMarkdownRenderer } from "../../generic/renderers/markdown"
|
||||
import { ViewContent } from "../../generic/views/content"
|
||||
|
||||
|
||||
export type EventsActionViewProps = {
|
||||
data: Event,
|
||||
}
|
||||
|
||||
|
||||
export const EventsActionView = memo(({ data }: EventsActionViewProps) => {
|
||||
return (
|
||||
<ViewContent
|
||||
title={<div style={{ padding: "10px" }}>
|
||||
{data.name}
|
||||
</div>}
|
||||
content={<div>
|
||||
<FestaMarkdownRenderer code={data.description} />
|
||||
</div>}
|
||||
/>
|
||||
)
|
||||
})
|
||||
EventsActionView.displayName = "EventsActionView"
|
|
@ -1,29 +1,27 @@
|
|||
import { faAsterisk, faPencil, faSave } from "@fortawesome/free-solid-svg-icons"
|
||||
import { useTranslation } from "next-i18next"
|
||||
import { useDefinedContext } from "../../../utils/definedContext"
|
||||
import { EditingContext, EditingMode } from "../../generic/editable/base"
|
||||
import { usePromise, UsePromiseStatus } from "../../generic/loading/promise"
|
||||
import { FestaIcon } from "../../generic/renderers/fontawesome"
|
||||
import { Tool } from "../../generic/toolbar/tool"
|
||||
import cursor from "../../../styles/cursor.module.css"
|
||||
import mood from "../../../styles/mood.module.css"
|
||||
import { Dispatch } from "react"
|
||||
|
||||
|
||||
export type ToolToggleEditingProps = {
|
||||
editing: boolean,
|
||||
setEditing: Dispatch<boolean>,
|
||||
save: () => Promise<void>,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ToolBar {@link Tool} which switches between {@link EditingMode}s of the surrounding context.
|
||||
*
|
||||
* It calls an async function to save data when switching from edit mode to view mode, preventing the user from switching back again until the data is saved, but allowing them to view the updated resource.
|
||||
* ToolBar {@link Tool} which allows the user to start editing an event and then save their changes.
|
||||
*/
|
||||
export function ToolToggleEditing(props: ToolToggleEditingProps) {
|
||||
export function ToolToggleEditing({ editing, setEditing, save: upperSave }: ToolToggleEditingProps) {
|
||||
const { t } = useTranslation()
|
||||
const [editing, setEditing] = useDefinedContext(EditingContext)
|
||||
|
||||
const { run: save, status: saveStatus } = usePromise<void, void>(props.save)
|
||||
const { run: save, status: saveStatus } = usePromise<void, void>(upperSave)
|
||||
|
||||
if (saveStatus === UsePromiseStatus.PENDING) {
|
||||
return (
|
||||
|
@ -36,13 +34,13 @@ export function ToolToggleEditing(props: ToolToggleEditingProps) {
|
|||
</Tool>
|
||||
)
|
||||
}
|
||||
else if (editing === EditingMode.EDIT) {
|
||||
else if (editing) {
|
||||
return (
|
||||
<Tool
|
||||
aria-label={t("toolToggleEditingSave")}
|
||||
onClick={() => {
|
||||
save()
|
||||
setEditing(EditingMode.VIEW)
|
||||
setEditing(false)
|
||||
}}
|
||||
className={mood.positive}
|
||||
>
|
||||
|
@ -55,7 +53,7 @@ export function ToolToggleEditing(props: ToolToggleEditingProps) {
|
|||
<Tool
|
||||
aria-label={t("toolToggleEditingEdit")}
|
||||
onClick={() => {
|
||||
setEditing(EditingMode.EDIT)
|
||||
setEditing(true)
|
||||
}}
|
||||
>
|
||||
<FestaIcon icon={faPencil} />
|
||||
|
|
|
@ -6,8 +6,6 @@ import defaultPostcard from "../../public/postcards/adi-goldstein-Hli3R6LKibo-un
|
|||
import { Postcard } from '../../components/postcard/changer'
|
||||
import useSWR from 'swr'
|
||||
import { Event } from '@prisma/client'
|
||||
import { EditableMarkdown, EditableText } from '../../components/generic/editable/inputs'
|
||||
import { EditingContext, EditingMode } from '../../components/generic/editable/base'
|
||||
import { useCallback, useState } from 'react'
|
||||
import { ToolBar } from '../../components/generic/toolbar/bar'
|
||||
import { ToolToggleEditing } from '../../components/events/toolbar/toolToggleEditing'
|
||||
|
@ -15,17 +13,10 @@ import { ToolToggleVisibility } from '../../components/postcard/toolbar/toolTogg
|
|||
import { WIPBanner } from '../../components/generic/wip/banner'
|
||||
import { AuthContext } from '../../components/auth/base'
|
||||
import { useDefinedContext } from '../../utils/definedContext'
|
||||
import { ViewContent } from '../../components/generic/views/content'
|
||||
import { useAxios } from '../../components/auth/requests'
|
||||
import { faAsterisk } from '@fortawesome/free-solid-svg-icons'
|
||||
import { FestaIcon } from '../../components/generic/renderers/fontawesome'
|
||||
import { promiseMultiplexer, usePromise, UsePromiseStatus } from '../../components/generic/loading/promise'
|
||||
import { EditingContextProvider } from '../../components/generic/editable/provider'
|
||||
import { swrMultiplexer } from '../../components/generic/loading/swr'
|
||||
import { LoadingMain, LoadingInline } from '../../components/generic/loading/renderers'
|
||||
import { ViewNotice } from '../../components/generic/views/notice'
|
||||
import { ErrorBlock } from '../../components/generic/errors/renderers'
|
||||
import { database } from '../../utils/prismaClient'
|
||||
import { EventsActionEdit } from '../../components/events/actions/edit'
|
||||
import { EventsActionView } from '../../components/events/actions/view'
|
||||
|
||||
|
||||
export async function getServerSideProps(context: NextPageContext) {
|
||||
|
@ -34,7 +25,7 @@ export async function getServerSideProps(context: NextPageContext) {
|
|||
return {
|
||||
props: {
|
||||
slug,
|
||||
event: await database.event.findUnique({ where: { slug } }),
|
||||
fallbackData: await database.event.findUnique({ where: { slug } }),
|
||||
...(await serverSideTranslations(context.locale ?? "it-IT", ["common"]))
|
||||
}
|
||||
}
|
||||
|
@ -43,87 +34,51 @@ export async function getServerSideProps(context: NextPageContext) {
|
|||
|
||||
type PageEventProps = {
|
||||
slug: string,
|
||||
event: Event,
|
||||
fallbackData: Event,
|
||||
}
|
||||
|
||||
|
||||
const PageEvent: NextPage<PageEventProps> = ({ slug, event }) => {
|
||||
const PageEvent: NextPage<PageEventProps> = ({ slug, fallbackData }) => {
|
||||
const { t } = useTranslation()
|
||||
const swrHook = useSWR<Event>(`/api/events/${slug}`, { fallback: event })
|
||||
const [auth,] = useDefinedContext(AuthContext)
|
||||
const axios = useAxios()
|
||||
|
||||
const { data, mutate } = useSWR<Event>(`/api/events/${slug}`, { fallbackData })
|
||||
const [auth,] = useDefinedContext(AuthContext)
|
||||
const [eventEditing, eventSetEditing] = useState<boolean>(false)
|
||||
|
||||
const save = useCallback(
|
||||
async () => {
|
||||
if (swrHook.data === undefined) {
|
||||
console.warn("[PageEvent] Tried to save while no data was available.")
|
||||
return
|
||||
}
|
||||
|
||||
await axios.patch(`/api/events/${slug}`, swrHook.data)
|
||||
swrHook.mutate(swrHook.data)
|
||||
console.debug("[PageEvent] Saved updated data successfully!")
|
||||
const response = await axios.patch<Event>(`/api/events/${slug}`, data!)
|
||||
mutate(response.data, { revalidate: false })
|
||||
},
|
||||
[axios, swrHook]
|
||||
[axios, data]
|
||||
)
|
||||
|
||||
const eventName = data?.name ?? slug
|
||||
const eventPostcard = data?.postcard || defaultPostcard
|
||||
const eventCanEdit = auth && data && auth.userId === data.creatorId
|
||||
|
||||
return <>
|
||||
<Head>
|
||||
<title key="title">{swrHook.data?.name ?? slug} - {t("siteTitle")}</title>
|
||||
<title key="title">{eventName} - {t("siteTitle")}</title>
|
||||
</Head>
|
||||
<Postcard
|
||||
src={swrHook.data?.postcard || defaultPostcard}
|
||||
/>
|
||||
<Postcard src={eventPostcard} />
|
||||
<WIPBanner />
|
||||
<EditingContextProvider>
|
||||
{swrMultiplexer({
|
||||
hook: swrHook,
|
||||
loading: () => (
|
||||
<ViewNotice
|
||||
notice={
|
||||
<LoadingMain text={t("eventLoading")} />
|
||||
}
|
||||
/>
|
||||
),
|
||||
ready: (data) => (
|
||||
<ViewContent
|
||||
title={
|
||||
<EditableText
|
||||
value={data?.name ?? slug}
|
||||
onChange={e => swrHook.mutate(async state => state ? { ...state, name: e.target.value } : undefined, { revalidate: false })}
|
||||
placeholder={t("eventTitlePlaceholder")}
|
||||
/>
|
||||
}
|
||||
content={
|
||||
<EditableMarkdown
|
||||
value={data?.description ?? ""}
|
||||
onChange={e => swrHook.mutate(async state => state ? { ...state, description: e.target.value } : undefined, { revalidate: false })}
|
||||
placeholder={t("eventDescriptionPlaceholder")}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
),
|
||||
error: (error) => (
|
||||
<ViewNotice
|
||||
notice={
|
||||
<ErrorBlock
|
||||
text={t("eventError")}
|
||||
error={error}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
|
||||
<ToolBar vertical="vadapt" horizontal="right">
|
||||
<ToolToggleVisibility />
|
||||
{swrHook.data && auth?.userId === swrHook.data?.creatorId &&
|
||||
<ToolToggleEditing
|
||||
save={save}
|
||||
/>
|
||||
}
|
||||
</ToolBar>
|
||||
</EditingContextProvider>
|
||||
<ToolBar vertical="vadapt" horizontal="right">
|
||||
<ToolToggleVisibility />
|
||||
{eventCanEdit &&
|
||||
<ToolToggleEditing
|
||||
editing={eventEditing}
|
||||
setEditing={eventSetEditing}
|
||||
save={save}
|
||||
/>
|
||||
}
|
||||
</ToolBar>
|
||||
{eventEditing ?
|
||||
<EventsActionEdit data={data!} mutate={mutate} />
|
||||
:
|
||||
<EventsActionView data={data!} />
|
||||
}
|
||||
</>
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue