Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(demo): possible to try tavla without creating a user #1569

Merged
merged 15 commits into from
Jul 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ function StopPlaceList({
}) {
if (!tiles || tiles.length === 0)
return (
<Paragraph margin="none" className="mt-6">
Du har ikke lagt til noen stoppesteder enda.
<Paragraph className="!mt-6">
Du har ikke lagt til noen stoppesteder ennå.
</Paragraph>
)
return (
Expand Down
5 changes: 5 additions & 0 deletions next-tavla/app/(admin)/components/Footer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ function Footer() {
</div>
<div className="flex flex-col gap-4">
<Heading3>Informasjon</Heading3>
<div>
<EnturLink href="/demo" as={Link}>
Prøv Tavla
</EnturLink>
</div>
<div className="flex flex-row gap-1 items-center">
<EnturLink
as={Link}
Expand Down
6 changes: 3 additions & 3 deletions next-tavla/app/(admin)/components/SideNavBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,14 @@ function SideNavBar({ loggedIn }: { loggedIn: boolean }) {
open={isOpen}
onDismiss={() => setIsOpen(false)}
size="medium"
className="h-full w-9/12 fixed top-0 left-0 py-10 !max-h-full !rounded-none !p-0 overflow-visible"
className="!h-full !w-9/12 !fixed !top-0 !left-0 py-10 !max-h-full !rounded-none !p-0 overflow-visible"
>
<SideNavigation className="h-full pt-10">
<SideNavigation className="h-full !pt-10">
<div className="pl-10">
<Link href="/" aria-label="Tilbake til landingssiden">
<Image src={TavlaLogoBlue} height={22} alt="" />
</Link>
<Heading2 className="mt-16 mb-4">Meny</Heading2>
<Heading2 className="!mt-16 !mb-4">Meny</Heading2>
</div>

<div className="bg-secondary">
Expand Down
16 changes: 15 additions & 1 deletion next-tavla/app/(admin)/components/TopNavigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ import TavlaLogoBlue from 'assets/logos/Tavla-blue.svg'
import { SideNavBar } from './SideNavBar'
import { HorizontalNavBar } from './HorizontalNavBar'
import { Login } from './Login'
import { TopNavigationItem } from '@entur/menu'
import { usePathname } from 'next/navigation'

function TopNavigation({ loggedIn }: { loggedIn: boolean }) {
const pathname = usePathname()
return (
<nav className="container mx-auto flex flex-row justify-between items-center py-8">
<Link href="/" aria-label="Tilbake til landingssiden">
Expand All @@ -15,7 +18,18 @@ function TopNavigation({ loggedIn }: { loggedIn: boolean }) {
<div className="flex flex-row items-center">
<SideNavBar loggedIn={loggedIn} />
<HorizontalNavBar loggedIn={loggedIn} />
<Login loggedIn={loggedIn} />
<div className="flex flex-row sm:gap-10">
{!loggedIn && (
<TopNavigationItem
active={pathname?.includes('/demo')}
as={Link}
href="/demo"
>
Prøv Tavla
</TopNavigationItem>
)}
<Login loggedIn={loggedIn} />
</div>
</div>
</nav>
)
Expand Down
40 changes: 34 additions & 6 deletions next-tavla/app/(admin)/edit/[id]/components/TileCard/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ import { TransportIcon } from 'components/TransportIcon'
import { isArray, uniqBy } from 'lodash'
import Image from 'next/image'
import { usePostHog } from 'posthog-js/react'
import { useState } from 'react'
import { Dispatch, SetStateAction, useState } from 'react'
import { Columns, TColumn } from 'types/column'
import { TBoardID } from 'types/settings'
import { TBoard, TBoardID } from 'types/settings'
import { getBoard, getWalkingDistanceTile } from '../../actions'
import { deleteTile, getOrganizationForBoard, saveTile } from './actions'
import { useLines } from './useLines'
Expand All @@ -36,10 +36,14 @@ function TileCard({
bid,
tile,
address,
demoBoard,
setDemoBoard,
}: {
bid: TBoardID
tile: TTile
address?: TLocation
demoBoard?: TBoard
setDemoBoard?: Dispatch<SetStateAction<TBoard>>
}) {
const posthog = usePostHog()
const [isOpen, setIsOpen] = useState(false)
Expand Down Expand Up @@ -85,6 +89,24 @@ function TileCard({
else posthog.capture('EDIT_COLUMN_CHANGE')
}

const saveTileToDemoBoard = (newTile: TTile) => {
if (!demoBoard) return null
const oldTileIndex = demoBoard.tiles.findIndex(
(tile) => tile.uuid == newTile.uuid,
)
if (oldTileIndex === -1) return null
demoBoard.tiles[oldTileIndex] = newTile
setDemoBoard && setDemoBoard({ ...demoBoard })
}

const removeTileFromDemoBoard = (tile: TTile) => {
if (!demoBoard) return null
const remainingTiles = demoBoard.tiles.filter(
(t) => t.uuid !== tile.uuid,
)
setDemoBoard && setDemoBoard({ ...demoBoard, tiles: remainingTiles })
}

return (
<div>
<div
Expand All @@ -103,7 +125,9 @@ function TileCard({
<div className="flex flex-row gap-4">
<SecondarySquareButton
onClick={async () => {
await deleteTile(bid, tile)
bid === 'demo'
? removeTileFromDemoBoard(tile)
: await deleteTile(bid, tile)
}}
aria-label="Slett stoppested"
>
Expand Down Expand Up @@ -165,7 +189,10 @@ function TileCard({
),
)
}
saveTile(bid, newTile)

bid === 'demo'
? saveTileToDemoBoard(newTile)
: saveTile(bid, newTile)
}}
onSubmit={reset}
onInput={() => setChanged(true)}
Expand All @@ -178,8 +205,9 @@ function TileCard({
<div className="flex flex-col">
{!address?.name && (
<Label className="!text-error">
Du må legge til en lokasjon for å kunne skru
på gåavstand
{demoBoard
? 'Logg inn for å få tilgang til funksjonaliteten'
: 'Du må legge til en lokasjon for å kunne skru på gåavstand'}
</Label>
)}
<Switch
Expand Down
27 changes: 27 additions & 0 deletions next-tavla/app/(admin)/hooks/useLocalStorage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { useEffect, useState } from 'react'

export const useLocalStorage = <T>(key: string, defaultValue: T) => {
const [localStorageValue, setLocalStorageValue] = useState(() => {
try {
const value = localStorage.getItem(key)

if (value) {
return JSON.parse(value)
} else {
localStorage.setItem(key, JSON.stringify(defaultValue))
return defaultValue
}
} catch (error) {
localStorage.setItem(key, JSON.stringify(defaultValue))
return defaultValue
}
})

useEffect(() => {
localStorage.setItem(key, JSON.stringify(localStorageValue))
}, [key, localStorageValue])

return [localStorageValue, setLocalStorageValue]
}

export default useLocalStorage
12 changes: 1 addition & 11 deletions next-tavla/app/(admin)/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,12 @@
import { Metadata } from 'next'
import { ReactNode } from 'react'
import { cookies } from 'next/headers'
import { TopNavigation } from './components/TopNavigation'
import { verifySession } from './utils/firebase'

export const metadata: Metadata = {
title: 'Mine organisasjoner | Entur Tavla',
}

async function AdminLayout({ children }: { children: ReactNode }) {
const session = cookies().get('session')?.value
const loggedIn = (await verifySession(session)) !== null
return (
<>
<TopNavigation loggedIn={loggedIn} />
<main className="container mx-auto pt-4 pb-20">{children}</main>
</>
)
return <main className="container mx-auto pt-4 pb-20">{children}</main>
}

export default AdminLayout
32 changes: 32 additions & 0 deletions next-tavla/app/demo/components/CreateUserButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
'use client'

import { Button } from '@entur/button'
import { Heading3, Paragraph } from '@entur/typography'
import Link from 'next/link'
import { usePostHog } from 'posthog-js/react'

export const CreateUserButton = () => {
const posthog = usePostHog()

return (
<div>
<Heading3 margin="bottom">Opprett bruker</Heading3>
<Paragraph margin="none">
Det er helt gratis å bruke Tavla!
</Paragraph>
<Button
variant="success"
as={Link}
href="?login"
className="mt-2"
onClick={() => {
posthog.capture('LOGIN_BTN_DEMO_PAGE')
}}
>
Opprett bruker / Logg inn
</Button>
</div>
)
}

export default CreateUserButton
52 changes: 52 additions & 0 deletions next-tavla/app/demo/components/DemoBoard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
'use client'
import { Heading2 } from '@entur/typography'
import { TileSelector } from 'app/(admin)/components/TileSelector'
import { formDataToTile } from 'app/(admin)/components/TileSelector/utils'
import { Preview } from 'app/(admin)/edit/[id]/components/Preview'
import { TileCard } from 'app/(admin)/edit/[id]/components/TileCard'
import useLocalStorage from '../../(admin)/hooks/useLocalStorage'
import { TTile } from 'types/tile'
import { usePostHog } from 'posthog-js/react'

const emptyDemoBoard = {
id: 'demo',
meta: { title: 'Demo' },
tiles: [],
}

function DemoBoard() {
const [board, setBoard] = useLocalStorage('board', emptyDemoBoard)

const posthog = usePostHog()

return (
<>
<div className="flex flex-col gap-4">
<Heading2>Hvilke stoppesteder vil du vise i tavlen?</Heading2>
<TileSelector
action={async (data: FormData) => {
const tile = formDataToTile(data)
setBoard({ ...board, tiles: [...board.tiles, tile] })
posthog.capture('ADD_STOP_PLACE_DEMO_PAGE')
}}
col={false}
/>
{board.tiles?.map((tile: TTile) => (
<TileCard
key={tile.uuid}
tile={tile}
bid={board.id ?? 'demo'}
demoBoard={board}
setDemoBoard={setBoard}
/>
))}
</div>
<div className="flex flex-col gap-4">
<Heading2>Forhåndsvisning</Heading2>
<Preview board={board} />
</div>
</>
)
}

export { DemoBoard }
62 changes: 62 additions & 0 deletions next-tavla/app/demo/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import {
Heading1,
Heading2,
LeadParagraph,
ListItem,
Paragraph,
UnorderedList,
} from '@entur/typography'
import { verifySession } from 'app/(admin)/utils/firebase'
import { cookies } from 'next/headers'
import { DemoBoard } from './components/DemoBoard'
import CreateUserButton from './components/CreateUserButton'

async function Demo() {
const session = cookies().get('session')?.value
const loggedIn = (await verifySession(session)) !== null

return (
<main className="container mx-auto pt-8 pb-20 flex flex-col gap-10">
<div>
<Heading1>Prøv og lag din egen avgangstavle!</Heading1>
<LeadParagraph margin="none" className="lg:w-4/5">
Dette er en demo-løsning hvor du kan prøve å opprette din
egen tavle. Du må logge inn for å lagre tavlen og få tilgang
til all funksjonalitet. Tavlen du lager her blir ikke
lagret.
</LeadParagraph>
</div>
{!loggedIn && <CreateUserButton />}

<div className="flex flex-col gap-10">
<Heading1 margin="none">Lag en demo-tavle</Heading1>
<DemoBoard />
</div>
<div>
<Heading2>Innstillinger som krever innlogging</Heading2>
<Paragraph margin="none">Hvis du logger inn, kan du:</Paragraph>
<UnorderedList className="flex flex-col gap-1 pl-6">
<ListItem>Endre tekststørrelse</ListItem>
<ListItem>
Legge til en info-melding nederst i tavlen
</ListItem>
<ListItem>Endre fargetema (lys eller mørk modus)</ListItem>
<ListItem>
Legge inn adressen som tavlen står på og vise gåavstand
fra tavlen til stoppested(ene)
</ListItem>
<ListItem>
Opprette så mange tavler du vil og samle disse i ulike
organisasjoner (mapper)
</ListItem>
<ListItem>
Gi andre tilgang til å administrere tavlen
</ListItem>
</UnorderedList>
</div>
{!loggedIn && <CreateUserButton />}
</main>
)
}

export default Demo
8 changes: 7 additions & 1 deletion next-tavla/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import dynamic from 'next/dynamic'
import { EnturToastProvider, PHProvider } from './providers'
import { Footer } from './(admin)/components/Footer'
import { FloatingContact } from './components/FloatingContact'
import { TopNavigation } from './(admin)/components/TopNavigation'
import { cookies } from 'next/headers'
import { verifySession } from './(admin)/utils/firebase'

export const metadata: Metadata = {
title: 'Entur Tavla',
Expand Down Expand Up @@ -38,12 +41,15 @@ const PostHogPageView = dynamic(() => import('./components/PostHogPageView'), {
ssr: false,
})

function RootLayout({ children }: { children: ReactNode }) {
async function RootLayout({ children }: { children: ReactNode }) {
const session = cookies().get('session')?.value
const loggedIn = (await verifySession(session)) !== null
return (
<html lang="nb">
<PHProvider>
<EnturToastProvider>
<body>
<TopNavigation loggedIn={loggedIn} />
<PostHogPageView />
{children}
<FloatingContact />
Expand Down
Loading