import {useState} from 'react'; import {useTranslation} from 'react-i18next'; import {ArrowDown, ArrowUp, Check, EyeOff, Loader2, Plus, RotateCcw, X} from 'lucide-react'; import {Button} from '@/components/ui/button'; import {Card} from '@/components/ui/card'; import {cn} from '@/lib/utils'; import {SIZES, spanClass} from '../utils/tiles.js'; /** * The tiles of a page in their order, in a 12 column grid (one column on a phone). In edit mode each tile gets * move, size and hide buttons, and the hidden tiles can be added again; nothing is saved before "Done". * * @param tiles the tile table (utils/tiles.js) * @param titles tile id -> i18n key of its name in the edit mode * @param renderTile (id, size) => the tile, or null when it has nothing to show (then it is left out, and in edit * mode it shows a placeholder so it can still be moved) * @param defaultLayout offered as "Reset"; none: no reset * @param onSave (layout) => promise; the page ends the edit mode when the save worked */ export default function TileGrid({tiles, titles, layout, renderTile, editing, defaultLayout, onSave, onCancel}) { if (!editing) { return (
{layout.map((tile) => { const content = renderTile(tile.id, tile.size); return content && ( // *:h-full: the card fills the grid row, as it did as a direct grid item.
{content}
); })}
); } return ; } // Mounted per edit session, so every session starts from the saved layout. function TileEditor({tiles, titles, layout, renderTile, defaultLayout, onSave, onCancel}) { const {t} = useTranslation(); const [shown, setShown] = useState(layout); const [saving, setSaving] = useState(false); const hidden = Object.keys(tiles).filter((id) => !shown.some((tile) => tile.id === id)); const move = (index, by) => { const next = [...shown]; [next[index], next[index + by]] = [next[index + by], next[index]]; setShown(next); }; const save = async () => { setSaving(true); await onSave(shown); setSaving(false); }; return (

{t('TILES.EDIT_HINT')}

{defaultLayout && ( )}
{shown.map((tile, index) => { const name = t(titles[tile.id]); const sizes = SIZES.filter((size) => tiles[tile.id][size]); return (
{name} {sizes.length > 1 && (
{sizes.map((size) => ( ))}
)}
{/* inert: a click on a game in the tile must not leave the edit mode. */}
{renderTile(tile.id, tile.size) || ( {t('TILES.NO_DATA')} )}
); })}
{hidden.length > 0 && (

{t('TILES.HIDDEN')}

{hidden.map((id) => ( ))}
)}
); }