mirror of
https://github.com/Steffo99/festa.git
synced 2024-12-23 07:04:22 +00:00
148 lines
No EOL
4.6 KiB
TypeScript
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>
|
|
)
|
|
})
|
|
} |