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(board): change order of tiles #1584

Merged
merged 5 commits into from
Jul 23, 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
11 changes: 11 additions & 0 deletions next-tavla/app/(admin)/edit/[id]/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { TBoard, TBoardID } from 'types/settings'
import { TTile } from 'types/tile'
import { getWalkingDistance } from 'app/(admin)/components/TileSelector/utils'
import { TLocation } from 'types/meta'
import { revalidatePath } from 'next/cache'

initializeAdminApp()

Expand Down Expand Up @@ -47,3 +48,13 @@ export async function getWalkingDistanceTile(
},
}
}
export async function saveTiles(bid: TBoardID, tiles: TTile[]) {
const access = await hasBoardEditorAccess(bid)
if (!access) return redirect('/')

await firestore().collection('boards').doc(bid).update({
tiles: tiles,
'meta.dateModified': Date.now(),
})
revalidatePath(`/edit/${bid}`)
}
142 changes: 105 additions & 37 deletions next-tavla/app/(admin)/edit/[id]/components/TileCard/index.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@
'use client'
import { BaseExpand } from '@entur/expand'
import { TTile } from 'types/tile'
import { Button, IconButton, SecondarySquareButton } from '@entur/button'
import {
Button,
IconButton,
NegativeButton,
SecondarySquareButton,
} from '@entur/button'
import { FilterChip } from '@entur/chip'
import { Switch, TextField } from '@entur/form'
import { CloseIcon, DeleteIcon, EditIcon, QuestionIcon } from '@entur/icons'
import {
CloseIcon,
DeleteIcon,
DownwardIcon,
EditIcon,
QuestionIcon,
UpwardIcon,
} from '@entur/icons'
import { Modal } from '@entur/modal'
import {
Heading3,
Expand Down Expand Up @@ -38,12 +50,18 @@ function TileCard({
address,
demoBoard,
setDemoBoard,
moveItem,
index,
totalTiles,
}: {
bid: TBoardID
tile: TTile
address?: TLocation
demoBoard?: TBoard
setDemoBoard?: Dispatch<SetStateAction<TBoard>>
moveItem: (index: number, direction: string) => void
index: number
totalTiles: number
}) {
const posthog = usePostHog()
const [isOpen, setIsOpen] = useState(false)
Expand Down Expand Up @@ -109,43 +127,75 @@ function TileCard({

return (
<div>
<div
className={`flex justify-between items-center px-6 py-4 bg-secondary ${
isOpen ? 'rounded-t' : 'rounded'
}`}
>
<div className="flex flex-row gap-4 items-center mr-2">
<Heading3 margin="none">{tile.name}</Heading3>
<div className="hidden sm:flex flex-row gap-4 h-8">
{transportModes.map((tm) => (
<TransportIcon transportMode={tm} key={tm} />
))}
<div className="flex flex-row">
<div
className={`flex justify-between items-center px-6 py-4 bg-secondary w-full ${
isOpen ? 'rounded-t' : 'rounded'
}`}
>
<div className="flex flex-row gap-4 items-center ">
<Heading3 margin="none">{tile.name}</Heading3>
<div className="hidden sm:flex flex-row gap-4 h-8">
{transportModes.map((tm) => (
<TransportIcon transportMode={tm} key={tm} />
))}
</div>
</div>

<div className="flex flex-row gap-4">
<SecondarySquareButton
onClick={() => {
if (changed) return setConfirmOpen(true)
setIsOpen(!isOpen)
}}
aria-label="Rediger stoppested"
>
{isOpen ? <CloseIcon /> : <EditIcon />}
</SecondarySquareButton>
</div>
</div>
<div className="flex flex-row gap-4">
<SecondarySquareButton
onClick={async () => {
bid === 'demo'
? removeTileFromDemoBoard(tile)
: await deleteTile(bid, tile)
}}
aria-label="Slett stoppested"
>
<DeleteIcon />
</SecondarySquareButton>
<SecondarySquareButton
onClick={() => {
if (changed) return setConfirmOpen(true)
setIsOpen(!isOpen)
}}
aria-label="Rediger stoppested"
>
{isOpen ? <CloseIcon /> : <EditIcon />}
</SecondarySquareButton>
<div
className={` flex flex-col ${
index !== 0 || index !== totalTiles - 1
? 'justify-center gap-2'
: 'justify-between'
}`}
>
{index !== 0 && (
<SecondarySquareButton
onClick={() => {
moveItem(index, 'up')
}}
aria-label="Flytt opp"
className="ml-2 *:!border-gray-300"
>
<UpwardIcon
onClick={() => {
moveItem(index, 'up')
}}
aria-label="Flytt opp"
/>
</SecondarySquareButton>
)}
{index !== totalTiles - 1 && (
<SecondarySquareButton
onClick={() => {
moveItem(index, 'down')
}}
aria-label="Flytt ned"
className="ml-2 *:!border-gray-300"
>
<DownwardIcon />
</SecondarySquareButton>
)}
</div>
</div>
<BaseExpand open={isOpen}>
<div className="bg-secondary px-6 py-4 rounded-b">
<div
className={`bg-secondary px-6 mr-14 py-4 ${
totalTiles == 1 && 'w-full'
} rounded-b`}
>
<form
id={tile.uuid}
action={async (data: FormData) => {
Expand Down Expand Up @@ -297,10 +347,28 @@ function TileCard({
value={uniqLines.length.toString()}
/>

<div className="flex flex-row justify-end mt-8">
<SubmitButton variant="primary">
Lagre endringer
<div className="flex flex-row justify-start gap-4 mt-8">
<SubmitButton
variant="primary"
aria-label="lagre valg"
>
Lagre valg
</SubmitButton>
<Button variant="secondary" aria-label="avbryt">
Avbryt
</Button>
<NegativeButton
onClick={async () => {
bid === 'demo'
? removeTileFromDemoBoard(tile)
: await deleteTile(bid, tile)
}}
aria-label="Slett stoppested"
type="button"
>
<DeleteIcon />
Fjern stoppested
</NegativeButton>
</div>
<Modal
size="small"
Expand Down
65 changes: 65 additions & 0 deletions next-tavla/app/(admin)/edit/[id]/components/TileList/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
'use client'

import { TBoard, TBoardID } from 'types/settings'
import { TileCard } from 'app/(admin)/edit/[id]/components/TileCard/index'
import { Dispatch, SetStateAction, useEffect, useState } from 'react'
import { TTile } from 'types/tile'
import { saveTiles } from '../../actions'
import { debounce } from 'lodash'

function TileList({
board,
setDemoBoard,
bid,
}: {
board: TBoard
bid?: TBoardID
setDemoBoard?: Dispatch<SetStateAction<TBoard>>
}) {
const [array, setArray] = useState<TTile[]>(board.tiles)

useEffect(() => {
setArray(board.tiles)
}, [board.tiles])

const moveItem = (index: number, direction: string) => {
const newIndex: number = direction === 'up' ? index - 1 : index + 1
if (newIndex < 0 || newIndex >= board.tiles.length) {
return
}

const newArray: TTile[] = [...board.tiles]

const oldElement = newArray[newIndex]

newArray[newIndex] = newArray[index] as TTile
newArray[index] = oldElement as TTile

setArray(newArray)
if (bid === 'demo' && setDemoBoard) {
const newBoard: TBoard = { ...board, tiles: newArray }
setDemoBoard(newBoard ?? board)
} else {
saveTiles(board.id ?? '', newArray)
}
}
const debouncedSave = debounce(moveItem, 150)
return (
<div className="flex flex-col gap-4">
{array.map((tile, index) => (
<TileCard
key={tile.uuid}
bid={bid ?? board.id ?? ''}
demoBoard={bid ? board : undefined}
tile={tile}
address={board.meta.location}
moveItem={debouncedSave}
index={index}
totalTiles={board.tiles.length}
setDemoBoard={setDemoBoard}
/>
))}
</div>
)
}
export { TileList }
16 changes: 4 additions & 12 deletions next-tavla/app/(admin)/edit/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { redirect } from 'next/navigation'
import { TBoardID } from 'types/settings'
import { addTile, getBoard, getWalkingDistanceTile } from './actions'
import { Heading1, Heading2 } from '@entur/typography'
import { TileCard } from './components/TileCard'
import { MetaSettings } from './components/MetaSettings'
import { TileSelector } from 'app/(admin)/components/TileSelector'
import { formDataToTile } from 'app/(admin)/components/TileSelector/utils'
Expand All @@ -18,8 +17,9 @@ import { DEFAULT_BOARD_NAME } from 'app/(admin)/utils/constants'
import { Preview } from './components/Preview'
import { ActionsMenu } from './components/ActionsMenu'
import { ThemeSelect } from './components/ThemeSelect'
import { TileList } from './components/TileList'

type TProps = {
export type TProps = {
params: { id: TBoardID }
}

Expand All @@ -40,7 +40,6 @@ export default async function EditPage({ params }: TProps) {

const access = await hasBoardEditorAccess(params.id)
if (!access) return redirect('/')

return (
<div className="flex flex-col gap-14">
<div className="flex flex-col md:flex-row justify-between">
Expand All @@ -65,7 +64,6 @@ export default async function EditPage({ params }: TProps) {
/>
<ThemeSelect board={board} />
</div>

<div className="flex flex-col gap-4">
<Heading2>Stoppesteder i tavlen</Heading2>
<TileSelector
Expand All @@ -84,14 +82,8 @@ export default async function EditPage({ params }: TProps) {
revalidatePath(`/edit/${params.id}`)
}}
/>
{board.tiles.map((tile) => (
<TileCard
key={tile.uuid}
bid={params.id}
tile={tile}
address={board.meta.location}
/>
))}

<TileList board={board} />
</div>

<div className="flex flex-col gap-4">
Expand Down
13 changes: 2 additions & 11 deletions next-tavla/app/demo/components/DemoBoard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@ 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'
import { TileList } from 'app/(admin)/edit/[id]/components/TileList'

const emptyDemoBoard = {
id: 'demo',
Expand All @@ -31,15 +30,7 @@ function DemoBoard() {
}}
col={false}
/>
{board.tiles?.map((tile: TTile) => (
<TileCard
key={tile.uuid}
tile={tile}
bid={board.id ?? 'demo'}
demoBoard={board}
setDemoBoard={setBoard}
/>
))}
<TileList board={board} setDemoBoard={setBoard} bid="demo" />
</div>
<div className="flex flex-col gap-4">
<Heading2>Forhåndsvisning</Heading2>
Expand Down