mirror of
https://github.com/Steffo99/festa.git
synced 2024-12-23 15:14:23 +00:00
147 lines
4.5 KiB
TypeScript
147 lines
4.5 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 { LoadingTextInline } from "../../generic/loading/textInline"
|
||
|
import { FestaIcon } from "../../generic/renderers/fontawesome"
|
||
|
import style from "./events.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, "positive")}
|
||
|
onClick={e => {
|
||
|
e.preventDefault()
|
||
|
run({ data: { name } })
|
||
|
}}
|
||
|
>
|
||
|
<FestaIcon icon={faPlus} />
|
||
|
</button>
|
||
|
</form>
|
||
|
),
|
||
|
pending: ({ }) => (
|
||
|
<p>
|
||
|
<LoadingTextInline text={t("landingEventsCreatePending")} />
|
||
|
</p>
|
||
|
),
|
||
|
rejected: ({ error }) => (
|
||
|
<p>
|
||
|
<ErrorBlock text={t("landingEventsCreateRejected")} error={error} />
|
||
|
</p>
|
||
|
),
|
||
|
fulfilled: ({ result }) => {
|
||
|
return (
|
||
|
<p>
|
||
|
<LoadingTextInline 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>
|
||
|
<LoadingTextInline text={t("landingEventsLoading")} />
|
||
|
</p>
|
||
|
),
|
||
|
ready: (data) => (<>
|
||
|
{data.length === 0 ?
|
||
|
<LandingActionEventsFirst />
|
||
|
:
|
||
|
<LandingActionEventsList data={data} />
|
||
|
}
|
||
|
<LandingActionEventsFormCreate />
|
||
|
</>),
|
||
|
error: (error) => (
|
||
|
<p>
|
||
|
<ErrorBlock text={t("landingEventsError")} error={error} />
|
||
|
</p>
|
||
|
)
|
||
|
})
|
||
|
}
|