1
Fork 0
mirror of https://github.com/Steffo99/festa.git synced 2024-10-16 15:07:27 +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";
export type PostcardContextValue = {
postcard: string,
setPostcard: React.Dispatch<React.SetStateAction<string>>,
visible: boolean,
setVisible: React.Dispatch<React.SetStateAction<boolean>>,
/**
* 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.
*/
export type PostcardImage = string;
/**
* 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() {
const {postcard, visible} = useDefinedContext(PostcardContext)
const { image, visibility } = useDefinedContext(PostcardContext)
console.debug("[PostcardRenderer] Re-rendering with:", image)
return (
<div
className={classNames({
"postcard": true,
"postcard-visible": visible,
})}
className={classNames("postcard", `postcard-vis-${visibility}`)}
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 { useDefinedContext } from "../../utils/definedContext"
import { FestaIcon } from "../extensions/FestaIcon"
import { PostcardContext } from "../postcard/PostcardContext"
import { PostcardContext, PostcardVisibility } from "../postcard/PostcardContext"
export function ToolToggleVisible() {
const {t} = useTranslation()
const {visible, setVisible} = useDefinedContext(PostcardContext)
const { t } = useTranslation()
const { visibility, setVisibility } = useDefinedContext(PostcardContext)
return (
<button
aria-label={visible ? t("toggleVisibleHide") : t("toggleVisibleShow")}
onClick={() => setVisible(!visible)}
className="toolbar-tool"
>
<FestaIcon icon={visible ? faEyeSlash : faEye}/>
</button>
)
if (visibility === PostcardVisibility.BACKGROUND) {
return (
<button
aria-label={t("toggleVisibleShow")}
onClick={() => setVisibility(PostcardVisibility.FOREGROUND)}
className="toolbar-tool"
>
<FestaIcon icon={faEye} />
</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 { default as Link } from "next/link";
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 errorPostcard from "../public/postcards/markus-spiske-iar-afB0QQw-unsplash-red.jpg"
@ -18,11 +18,12 @@ export async function getStaticProps(context: NextPageContext) {
export default function Page404() {
const {t} = useTranslation()
const { t } = useTranslation()
usePostcardImage(`url(${errorPostcard.src})`)
return <>
<Postcard src={errorPostcard.src}/>
<ViewNotice
<ViewNotice
notice={<>
<ErrorBlock
text={t("notFoundError")}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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