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

Fix postcard quirks

This commit is contained in:
Steffo 2022-06-09 23:43:38 +02:00
parent 7f366c8f09
commit 6412472d3e
Signed by: steffo
GPG key ID: 6965406171929D01
13 changed files with 145 additions and 113 deletions

View file

@ -1,31 +0,0 @@
import { useEffect } from "react"
import { PostcardContext } from "./PostcardContext"
import { useDefinedContext } from "../../utils/definedContext"
import { StaticImageData } from "next/image"
type PostcardProps = {
src?: string | StaticImageData
}
export function Postcard({ src }: PostcardProps) {
const { setPostcard } = useDefinedContext(PostcardContext)
useEffect(
() => {
if (src) {
if (src === undefined) {
return
}
if (typeof src === "object") {
setPostcard(src.src)
}
else {
setPostcard(src)
}
}
},
[src, setPostcard]
)
return null
}

View file

@ -1,11 +1,36 @@
import { createDefinedContext } from "../../utils/definedContext"; import { createDefinedContext } from "../../utils/definedContext";
export type PostcardContextValue = { /**
postcard: string, * The string to be used as the [`background-image`](https://developer.mozilla.org/en-US/docs/Web/CSS/background-image) CSS property of the postcard.
setPostcard: React.Dispatch<React.SetStateAction<string>>, */
visible: boolean, export type PostcardImage = string;
setVisible: React.Dispatch<React.SetStateAction<boolean>>,
/**
* How the postcard is displayed on the page.
*/
export enum PostcardVisibility {
/**
* The postcard is filtered, blurred, and rendered behind all elements on the page.
*/
BACKGROUND = "background",
/**
* The postcard is fully visible and rendered above all other elements.
*/
FOREGROUND = "foreground",
}
/**
* Contents of the {@link PostcardContext}.
*/
type PostcardContextValue = {
image: PostcardImage,
setImage: React.Dispatch<React.SetStateAction<PostcardImage>>,
visibility: PostcardVisibility,
setVisibility: React.Dispatch<React.SetStateAction<PostcardVisibility>>,
} }

View file

@ -4,16 +4,15 @@ import classNames from "classnames";
export function PostcardRenderer() { export function PostcardRenderer() {
const {postcard, visible} = useDefinedContext(PostcardContext) const { image, visibility } = useDefinedContext(PostcardContext)
console.debug("[PostcardRenderer] Re-rendering with:", image)
return ( return (
<div <div
className={classNames({ className={classNames("postcard", `postcard-vis-${visibility}`)}
"postcard": true,
"postcard-visible": visible,
})}
style={{ style={{
backgroundImage: `url(${postcard})` backgroundImage: image,
}} }}
/> />
) )

View file

@ -0,0 +1,14 @@
import { useEffect } from "react"
import { useDefinedContext } from "../../utils/definedContext"
import { PostcardContext } from "./PostcardContext"
export function usePostcardImage(image: string) {
const { setImage } = useDefinedContext(PostcardContext)
useEffect(
() => {
setImage(image)
},
[image]
)
}

View file

@ -0,0 +1,14 @@
import { useState } from "react";
import { PostcardImage, PostcardVisibility } from "./PostcardContext";
export function useStatePostcard() {
const [visibility, setVisibility] = useState<PostcardVisibility>(PostcardVisibility.BACKGROUND)
const [image, setImage] = useState<PostcardImage>("none")
return {
visibility,
setVisibility,
image,
setImage,
}
}

View file

@ -2,19 +2,32 @@ import { faEye, faEyeSlash } from "@fortawesome/free-solid-svg-icons"
import { useTranslation } from "next-i18next" import { useTranslation } from "next-i18next"
import { useDefinedContext } from "../../utils/definedContext" import { useDefinedContext } from "../../utils/definedContext"
import { FestaIcon } from "../extensions/FestaIcon" import { FestaIcon } from "../extensions/FestaIcon"
import { PostcardContext } from "../postcard/PostcardContext" import { PostcardContext, PostcardVisibility } from "../postcard/PostcardContext"
export function ToolToggleVisible() { export function ToolToggleVisible() {
const {t} = useTranslation() const { t } = useTranslation()
const {visible, setVisible} = useDefinedContext(PostcardContext) const { visibility, setVisibility } = useDefinedContext(PostcardContext)
if (visibility === PostcardVisibility.BACKGROUND) {
return ( return (
<button <button
aria-label={visible ? t("toggleVisibleHide") : t("toggleVisibleShow")} aria-label={t("toggleVisibleShow")}
onClick={() => setVisible(!visible)} onClick={() => setVisibility(PostcardVisibility.FOREGROUND)}
className="toolbar-tool" className="toolbar-tool"
> >
<FestaIcon icon={visible ? faEyeSlash : faEye}/> <FestaIcon icon={faEye} />
</button> </button>
) )
}
else {
return (
<button
aria-label={t("toggleVisibleHide")}
onClick={() => setVisibility(PostcardVisibility.BACKGROUND)}
className="toolbar-tool"
>
<FestaIcon icon={faEyeSlash} />
</button>
)
}
} }

View file

@ -3,7 +3,7 @@ import { useTranslation } from "next-i18next";
import { serverSideTranslations } from "next-i18next/serverSideTranslations"; import { serverSideTranslations } from "next-i18next/serverSideTranslations";
import { default as Link } from "next/link"; import { default as Link } from "next/link";
import { ErrorBlock } from "../components/errors/ErrorBlock"; import { ErrorBlock } from "../components/errors/ErrorBlock";
import { Postcard } from "../components/postcard/Postcard"; import { usePostcardImage } from "../components/postcard/usePostcardImage";
import { ViewNotice } from "../components/view/ViewNotice"; import { ViewNotice } from "../components/view/ViewNotice";
import errorPostcard from "../public/postcards/markus-spiske-iar-afB0QQw-unsplash-red.jpg" import errorPostcard from "../public/postcards/markus-spiske-iar-afB0QQw-unsplash-red.jpg"
@ -18,10 +18,11 @@ export async function getStaticProps(context: NextPageContext) {
export default function Page404() { export default function Page404() {
const {t} = useTranslation() const { t } = useTranslation()
usePostcardImage(`url(${errorPostcard.src})`)
return <> return <>
<Postcard src={errorPostcard.src}/>
<ViewNotice <ViewNotice
notice={<> notice={<>
<ErrorBlock <ErrorBlock

View file

@ -2,7 +2,7 @@ import { NextPageContext } from "next";
import { useTranslation } from "next-i18next"; import { useTranslation } from "next-i18next";
import { serverSideTranslations } from "next-i18next/serverSideTranslations"; import { serverSideTranslations } from "next-i18next/serverSideTranslations";
import { ErrorBlock } from "../components/errors/ErrorBlock"; import { ErrorBlock } from "../components/errors/ErrorBlock";
import { Postcard } from "../components/postcard/Postcard"; import { usePostcardImage } from "../components/postcard/usePostcardImage";
import { ViewNotice } from "../components/view/ViewNotice"; import { ViewNotice } from "../components/view/ViewNotice";
import errorPostcard from "../public/postcards/markus-spiske-iar-afB0QQw-unsplash-red.jpg" import errorPostcard from "../public/postcards/markus-spiske-iar-afB0QQw-unsplash-red.jpg"
@ -17,10 +17,11 @@ export async function getStaticProps(context: NextPageContext) {
export default function Page500() { export default function Page500() {
const {t} = useTranslation() const { t } = useTranslation()
usePostcardImage(`url(${errorPostcard.src})`)
return <> return <>
<Postcard src={errorPostcard.src}/>
<ViewNotice <ViewNotice
notice={ notice={
<ErrorBlock <ErrorBlock

View file

@ -2,10 +2,8 @@ import '../styles/globals.css'
import type { AppProps } from 'next/app' import type { AppProps } from 'next/app'
import { LoginContext } from '../components/contexts/login' import { LoginContext } from '../components/contexts/login'
import { useState } from 'react' import { useState } from 'react'
import defaultPostcard from "../public/postcards/adi-goldstein-Hli3R6LKibo-unsplash.jpg"
import { PostcardRenderer } from '../components/postcard/PostcardRenderer' import { PostcardRenderer } from '../components/postcard/PostcardRenderer'
import { PostcardContext } from '../components/postcard/PostcardContext' import { PostcardContext } from '../components/postcard/PostcardContext'
import { StaticImageData } from 'next/image'
import { appWithTranslation, useTranslation } from 'next-i18next' import { appWithTranslation, useTranslation } from 'next-i18next'
import { FestaLoginData } from '../types/user' import { FestaLoginData } from '../types/user'
import { useStoredLogin } from "../hooks/useStoredLogin" import { useStoredLogin } from "../hooks/useStoredLogin"
@ -13,12 +11,13 @@ import { SWRConfig } from 'swr'
import { AxiosRequestConfig } from 'axios' import { AxiosRequestConfig } from 'axios'
import { useAxios } from '../hooks/useAxios' import { useAxios } from '../hooks/useAxios'
import { ErrorBoundary } from '../components/errors/ErrorBoundary' import { ErrorBoundary } from '../components/errors/ErrorBoundary'
import defaultPostcard from "../public/postcards/adi-goldstein-Hli3R6LKibo-unsplash.jpg"
import { useStatePostcard } from '../components/postcard/useStatePostcard'
const App = ({ Component, pageProps }: AppProps): JSX.Element => { const App = ({ Component, pageProps }: AppProps): JSX.Element => {
const {t} = useTranslation() const { t } = useTranslation()
const [postcard, setPostcard] = useState<string>(defaultPostcard.src) const postcardState = useStatePostcard()
const [postcardVisible, setPostcardVisible] = useState<boolean>(false)
const [login, setLogin] = useState<FestaLoginData | null>(null) const [login, setLogin] = useState<FestaLoginData | null>(null)
useStoredLogin(setLogin) useStoredLogin(setLogin)
@ -35,10 +34,10 @@ const App = ({ Component, pageProps }: AppProps): JSX.Element => {
return <> return <>
<ErrorBoundary text={t("genericError")}> <ErrorBoundary text={t("genericError")}>
<PostcardContext.Provider value={{postcard, setPostcard, visible: postcardVisible, setVisible: setPostcardVisible}}> <PostcardContext.Provider value={postcardState}>
<LoginContext.Provider value={[login, setLogin]}> <LoginContext.Provider value={[login, setLogin]}>
<SWRConfig value={swrConfig}> <SWRConfig value={swrConfig}>
<PostcardRenderer/> <PostcardRenderer />
<Component {...pageProps} /> <Component {...pageProps} />
</SWRConfig> </SWRConfig>
</LoginContext.Provider> </LoginContext.Provider>

View file

@ -3,7 +3,7 @@ import { NextPageContext } from "next";
import { useTranslation } from "next-i18next"; import { useTranslation } from "next-i18next";
import { serverSideTranslations } from "next-i18next/serverSideTranslations"; import { serverSideTranslations } from "next-i18next/serverSideTranslations";
import { default as Head } from "next/head"; import { default as Head } from "next/head";
import { ChangeEvent, useCallback, useState } from "react"; import { ChangeEvent, useMemo, useState } from "react";
import { ToolBar } from "../../components/tools/ToolBar"; import { ToolBar } from "../../components/tools/ToolBar";
import { EditableMarkdown } from "../../components/editable/EditableMarkdown"; import { EditableMarkdown } from "../../components/editable/EditableMarkdown";
import { EditableText } from "../../components/editable/EditableText"; import { EditableText } from "../../components/editable/EditableText";
@ -13,11 +13,9 @@ import { database } from "../../utils/prismaClient";
import { EditableFilePicker } from "../../components/editable/EditableFilePicker"; import { EditableFilePicker } from "../../components/editable/EditableFilePicker";
import { ViewEvent } from "../../components/view/ViewEvent"; import { ViewEvent } from "../../components/view/ViewEvent";
import { ToolToggleVisible } from "../../components/tools/ToolToggleVisible"; import { ToolToggleVisible } from "../../components/tools/ToolToggleVisible";
import { EditableDateRange } from "../../components/editable/EditableDateRange";
import { WorkInProgress } from "../../components/WorkInProgress"; import { WorkInProgress } from "../../components/WorkInProgress";
import { FormDateRange } from "../../components/form/FormDateRange"; import { usePostcardImage } from "../../components/postcard/usePostcardImage";
import { Postcard } from "../../components/postcard/Postcard"; import defaultPostcard from "../../public/postcards/adi-goldstein-Hli3R6LKibo-unsplash.jpg"
import { useFilePickerState } from "../../hooks/useFilePickerState";
export async function getServerSideProps(context: NextPageContext) { export async function getServerSideProps(context: NextPageContext) {
@ -26,17 +24,17 @@ export async function getServerSideProps(context: NextPageContext) {
return { notFound: true } return { notFound: true }
} }
const event = await database.event.findUnique({ const initialEvent = await database.event.findUnique({
where: { slug }, where: { slug },
include: { creator: true } include: { creator: true }
}) })
if (!event) { if (!initialEvent) {
return { notFound: true } return { notFound: true }
} }
return { return {
props: { props: {
event, initialEvent,
...(await serverSideTranslations(context.locale ?? "it-IT", ["common"])) ...(await serverSideTranslations(context.locale ?? "it-IT", ["common"]))
} }
} }
@ -44,25 +42,23 @@ export async function getServerSideProps(context: NextPageContext) {
type PageEventDetailProps = { type PageEventDetailProps = {
event: Event & { creator: User } initialEvent: Event & { creator: User }
} }
export default function PageEventDetail({ event }: PageEventDetailProps) { export default function PageEventDetail({ initialEvent }: PageEventDetailProps) {
const { t } = useTranslation() const { t } = useTranslation()
const editState = useState<boolean>(false) const editState = useState<boolean>(false)
const [title, setTitle] = useState<string>(event.name) const [event, setEvent] = useState<Event>(initialEvent)
const [description, setDescription] = useState<string>(event.description)
const [postcard, setPostcard] = useState<File | "">("") const displayedPostcard = event.postcard || defaultPostcard.src
const [startingAt, setStartingAt] = useState<string>(event.startingAt?.toISOString() ?? "") usePostcardImage(`url(${displayedPostcard})`)
const [endingAt, setEndingAt] = useState<string>(event.endingAt?.toISOString() ?? "")
return <> return <>
<Head> <Head>
<title key="title">{event.name} - {t("siteTitle")}</title> <title key="title">{initialEvent.name} - {t("siteTitle")}</title>
</Head> </Head>
<WorkInProgress /> <WorkInProgress />
<Postcard src={postcard ? URL.createObjectURL(postcard) : event.postcard ?? undefined} />
<EditingContext.Provider value={editState}> <EditingContext.Provider value={editState}>
<ToolBar vertical="vadapt" horizontal="right"> <ToolBar vertical="vadapt" horizontal="right">
<ToolToggleEditing /> <ToolToggleEditing />
@ -71,25 +67,24 @@ export default function PageEventDetail({ event }: PageEventDetailProps) {
<ViewEvent <ViewEvent
title={ title={
<EditableText <EditableText
value={title} value={event.name}
onChange={(e: ChangeEvent<HTMLInputElement>) => setTitle(e.target.value)} onChange={(e: ChangeEvent<HTMLInputElement>) => setEvent({ ...event, name: e.target.value })}
placeholder={t("eventDetailsTitlePlaceholder")} placeholder={t("eventDetailsNamePlaceholder")}
/> />
} }
postcard={ postcard={
<EditableFilePicker <EditableFilePicker
value={postcard} onChange={(e: ChangeEvent<HTMLInputElement>) => setEvent({ ...event, postcard: URL.createObjectURL(e.target.files![0]) })}
onChange={(e: ChangeEvent<HTMLInputElement>) => e.target.files ? setPostcard(e.target.files[0] ?? null) : setPostcard(null)}
placeholder={t("eventDetailsPostcardPlaceholder")} placeholder={t("eventDetailsPostcardPlaceholder")}
/> />
} }
description={<> description={
<EditableMarkdown <EditableMarkdown
value={description} value={event.description}
onChange={(e: ChangeEvent<HTMLTextAreaElement>) => setDescription(e.target.value)} onChange={(e: ChangeEvent<HTMLTextAreaElement>) => setEvent({ ...event, description: e.target.value })}
placeholder={t("eventDetailsDescriptionPlaceholder")} placeholder={t("eventDetailsDescriptionPlaceholder")}
/> />
</>} }
daterange={<></>} daterange={<></>}
/> />
</EditingContext.Provider> </EditingContext.Provider>

View file

@ -7,8 +7,8 @@ import { ActionLoginTelegram } from '../components/ActionLoginTelegram'
import { ActionEventList } from '../components/ActionEventList' import { ActionEventList } from '../components/ActionEventList'
import { default as Head } from 'next/head' import { default as Head } from 'next/head'
import defaultPostcard from "../public/postcards/adi-goldstein-Hli3R6LKibo-unsplash.jpg" import defaultPostcard from "../public/postcards/adi-goldstein-Hli3R6LKibo-unsplash.jpg"
import { Postcard } from '../components/postcard/Postcard'
import { ViewLanding } from '../components/view/ViewLanding' import { ViewLanding } from '../components/view/ViewLanding'
import { usePostcardImage } from '../components/postcard/usePostcardImage'
export async function getStaticProps(context: NextPageContext) { export async function getStaticProps(context: NextPageContext) {
@ -22,15 +22,14 @@ export async function getStaticProps(context: NextPageContext) {
export default function PageIndex() { export default function PageIndex() {
const { t } = useTranslation() const { t } = useTranslation()
const [login, ] = useDefinedContext(LoginContext) const [login,] = useDefinedContext(LoginContext)
usePostcardImage(`url(${defaultPostcard.src})`)
return <> return <>
<Head> <Head>
<title key="title">{t("siteTitle")}</title> <title key="title">{t("siteTitle")}</title>
</Head> </Head>
<Postcard
src={defaultPostcard}
/>
<ViewLanding <ViewLanding
title={t("siteTitle")} title={t("siteTitle")}
subtitle={t("siteSubtitle")} subtitle={t("siteSubtitle")}

View file

@ -28,7 +28,7 @@
"eventListCreateError": "Si è verificato il seguente errore nella creazione del tuo evento:", "eventListCreateError": "Si è verificato il seguente errore nella creazione del tuo evento:",
"eventDetailsToggleEditingEdit": "Modifica pagina", "eventDetailsToggleEditingEdit": "Modifica pagina",
"eventDetailsToggleEditingView": "Visualizza anteprima", "eventDetailsToggleEditingView": "Visualizza anteprima",
"eventDetailsTitlePlaceholder": "Titolo", "eventDetailsNamePlaceholder": "Nome evento",
"eventDetailsDescriptionPlaceholder": "Descrizione evento", "eventDetailsDescriptionPlaceholder": "Descrizione evento",
"eventDetailsPostcardPlaceholder": "Cartolina", "eventDetailsPostcardPlaceholder": "Cartolina",
"workInProgress": "Questa pagina è ancora in sviluppo e potrebbe contenere errori o testo inaspettato.", "workInProgress": "Questa pagina è ancora in sviluppo e potrebbe contenere errori o testo inaspettato.",

View file

@ -5,8 +5,6 @@
background-attachment: fixed; background-attachment: fixed;
background-size: cover; background-size: cover;
background-position: 50% 50%; background-position: 50% 50%;
z-index: -1;
filter: blur(7px) contrast(50%) brightness(50%);
position: fixed; position: fixed;
top: 0; top: 0;
@ -16,13 +14,18 @@
pointer-events: none; pointer-events: none;
} }
.postcard-vis-background {
z-index: -1;
filter: blur(7px) contrast(50%) brightness(50%);
}
@media (prefers-color-scheme: light) { @media (prefers-color-scheme: light) {
.postcard { .postcard-vis-background {
filter: blur(7px) contrast(25%) brightness(175%); filter: blur(7px) contrast(25%) brightness(175%);
} }
} }
.postcard-visible { .postcard-vis-foreground {
z-index: 1; z-index: 1;
filter: none; filter: none;
} }