Skip to content

Commit

Permalink
feat(demo): possible to try tavla without creating a user (#1569)
Browse files Browse the repository at this point in the history
* feat(demo): add demo board in local storage

* style(stoplist): margin top

* feat(demo): delete tiles

* refactor(nav): move nav to root level

* feat(nav): add demo to top nav

* feat(footer): add demo link

* fix(navbar): mobile view

* chore(demo): rename

* chore(demo): move logic and useLocalStorageHook

* chore(rename): misspelling

* fix(demo): add more descriptive text

* fix(demo): remove button when logged in

* fix(demo): tracking on login btn and add stopplace btn

* fix(demo): move clinet component to own file

* refactor(demo): move nav-item from login to topnav component
  • Loading branch information
emilielr authored Jul 9, 2024
1 parent be2f69e commit 9dac2c5
Show file tree
Hide file tree
Showing 15 changed files with 244 additions and 42 deletions.
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

0 comments on commit 9dac2c5

Please sign in to comment.