1
Fork 0
mirror of https://github.com/Steffo99/festa.git synced 2024-10-16 15:07:27 +00:00
festa/components/landing/actions/events.tsx

148 lines
No EOL
4.6 KiB
TypeScript

import { faPlus } from "@fortawesome/free-solid-svg-icons"
import { Event } from "@prisma/client"
import classNames from "classnames"
import { useTranslation } from "next-i18next"
import Link from "next/link"
import { useRouter } from "next/router"
import { useState } from "react"
import { default as useSWR } from "swr"
import { useAxiosRequest } from "../../auth/requests"
import { ErrorBlock } from "../../generic/errors/renderers"
import { promiseMultiplexer } from "../../generic/loading/promise"
import { swrMultiplexer } from "../../generic/loading/swr"
import { LoadingInline } from "../../generic/loading/renderers"
import { FestaIcon } from "../../generic/renderers/fontawesome"
import style from "./events.module.css"
import mood from "../../../styles/mood.module.css"
/**
* Displayed if the user has never created an event on Festa.
*/
const LandingActionEventsFirst = () => {
const { t } = useTranslation()
return (
<p>
<label htmlFor="festa-landing-action-events-form-create-name">
{t("landingEventsFirstDescription")}
</label>
</p>
)
}
/**
* Displayed if the user has one or more events created on Festa.
*/
const LandingActionEventsList = ({ data }: { data: Event[] }) => {
const { t } = useTranslation()
return (
<>
<p>
{t("landingEventsDescription")}
</p>
<p>
<ul className={style.landingActionEventsList}>
{data.map(e => (
<li key={e.slug}>
<Link href={`/events/${e.slug}`}>
{e.name}
</Link>
</li>
))}
</ul>
</p>
<p>
<label htmlFor="festa-landing-action-events-form-create-name">
{t("landingEventsCreateDescription")}
</label>
</p>
</>
)
}
/**
* One-line form to create a new event on Festa.
*/
const LandingActionEventsFormCreate = () => {
const { t } = useTranslation()
const router = useRouter()
const [name, setName] = useState<string>("")
const createHook = useAxiosRequest<Event, Partial<Event>>({ method: "POST", url: "/api/events/" })
return promiseMultiplexer({
hook: createHook,
ready: ({ run }) => (
<form className={style.landingActionEventsFormCreate}>
<input
type="text"
placeholder={t("landingEventsCreatePlaceholder")}
value={name}
onChange={e => setName(e.target.value)}
required
id="festa-landing-action-events-form-create-name"
className={style.landingActionEventsFormCreateName}
/>
<button
aria-label={t("landingEventsCreateSubmitLabel")}
disabled={!name}
className={classNames(style.landingActionEventsFormCreateSubmit, mood.positive)}
onClick={e => {
e.preventDefault()
run({ data: { name } })
}}
>
<FestaIcon icon={faPlus} />
</button>
</form>
),
pending: ({ }) => (
<p>
<LoadingInline text={t("landingEventsCreatePending")} />
</p>
),
rejected: ({ error }) => (
<p>
<ErrorBlock text={t("landingEventsCreateRejected")} error={error} />
</p>
),
fulfilled: ({ result }) => {
return (
<p>
<LoadingInline text={t("landingEventsCreateFulfilled", name)} />
</p>
)
},
})
}
export const LandingActionEvents = () => {
const { t } = useTranslation()
const apiHook = useSWR<Event[], Error>("/api/events/mine")
return swrMultiplexer({
hook: apiHook,
loading: () => (
<p>
<LoadingInline text={t("landingEventsLoading")} />
</p>
),
ready: (data) => (<>
{data.length === 0 ?
<LandingActionEventsFirst />
:
<LandingActionEventsList data={data} />
}
<LandingActionEventsFormCreate />
</>),
error: (error) => (
<p>
<ErrorBlock text={t("landingEventsError")} error={error} />
</p>
)
})
}