diff --git a/src/sections/loadGame/chessComInput.tsx b/src/sections/loadGame/chessComInput.tsx index 09234bc..c67e348 100644 --- a/src/sections/loadGame/chessComInput.tsx +++ b/src/sections/loadGame/chessComInput.tsx @@ -8,19 +8,85 @@ import { ListItemButton, ListItemText, TextField, + Autocomplete, } from "@mui/material"; +import { Icon } from "@iconify/react"; import { useDebounce } from "@/hooks/useDebounce"; import { useQuery } from "@tanstack/react-query"; +import { useEffect, useMemo, useState } from "react"; interface Props { onSelect: (pgn: string, boardOrientation?: boolean) => void; } export default function ChessComInput({ onSelect }: Props) { - const [chessComUsername, setChessComUsername] = useLocalStorage( + const [rawStoredValue, setStoredValues] = useLocalStorage( "chesscom-username", "" ); + + const storedValues = useMemo(() => { + if (typeof rawStoredValue === "string") + return rawStoredValue + .split(",") + .map((s) => s.trim()) + .filter(Boolean); + else return []; + }, [rawStoredValue]); + + const [chessComUsername, setChessComUsername] = useState(""); + const [hasEdited, setHasEdited] = useState(false); + + useEffect(() => { + if ( + !hasEdited && + storedValues && + storedValues.length > 0 && + chessComUsername.trim().toLowerCase() != + storedValues[0].trim().toLowerCase() + ) { + setChessComUsername(storedValues[0].trim().toLowerCase()); + } + }, [storedValues, hasEdited, chessComUsername]); + + const updateHistory = (username: string) => { + const trimmed = username.trim(); + if (!trimmed) return; + const lower = trimmed.toLowerCase(); + + const exists = storedValues.some((u) => u.toLowerCase() === lower); + if (!exists) { + const updated = [trimmed, ...storedValues.filter((u) => u !== trimmed)]; + setStoredValues(updated.join(",")); + } + }; + + const deleteUsername = (usernameToDelete: string) => { + const updated = storedValues.filter((u) => u !== usernameToDelete); + setStoredValues(updated.join(",")); + }; + + const handleChange = (_: React.SyntheticEvent, newValue: string | null) => { + const newInputValue = newValue ?? ""; + if ( + newInputValue.trim().toLowerCase() != + chessComUsername.trim().toLowerCase() + ) + setChessComUsername(newInputValue.trim().toLowerCase()); + }; + + const handleInputChange = ( + _: React.SyntheticEvent, + newInputValue: string + ) => { + if ( + newInputValue.trim().toLowerCase() != + chessComUsername.trim().toLowerCase() + ) { + setChessComUsername(newInputValue.trim().toLowerCase()); + if (!hasEdited) setHasEdited(true); + } + }; const debouncedUsername = useDebounce(chessComUsername, 300); const { @@ -38,15 +104,48 @@ export default function ChessComInput({ onSelect }: Props) { return ( <> - setChessComUsername(e.target.value)} + { + const { key, ...rest } = props; + return ( +
  • + {option} + { + e.stopPropagation(); + deleteUsername(option); + }} + /> +
  • + ); + }} + renderInput={(params) => ( + + )} />
    - {chessComUsername && ( + {debouncedUsername && ( ( { + updateHistory(debouncedUsername); const boardOrientation = - chessComUsername.toLowerCase() !== + debouncedUsername.toLowerCase() !== game.black?.username?.toLowerCase(); onSelect(game.pgn, boardOrientation); }} diff --git a/src/sections/loadGame/lichessInput.tsx b/src/sections/loadGame/lichessInput.tsx index 8710915..13c0850 100644 --- a/src/sections/loadGame/lichessInput.tsx +++ b/src/sections/loadGame/lichessInput.tsx @@ -8,19 +8,84 @@ import { ListItemButton, ListItemText, TextField, + Autocomplete, } from "@mui/material"; +import { Icon } from "@iconify/react"; import { useDebounce } from "@/hooks/useDebounce"; import { useQuery } from "@tanstack/react-query"; +import { useEffect, useMemo, useState } from "react"; interface Props { onSelect: (pgn: string, boardOrientation?: boolean) => void; } export default function LichessInput({ onSelect }: Props) { - const [lichessUsername, setLichessUsername] = useLocalStorage( + const [rawStoredValue, setStoredValues] = useLocalStorage( "lichess-username", "" ); + + const storedValues = useMemo(() => { + if (typeof rawStoredValue === "string") + return rawStoredValue + .split(",") + .map((s) => s.trim()) + .filter(Boolean); + else return []; + }, [rawStoredValue]); + + const [lichessUsername, setLichessUsername] = useState(""); + const [hasEdited, setHasEdited] = useState(false); + + useEffect(() => { + if ( + !hasEdited && + storedValues && + storedValues.length > 0 && + lichessUsername.trim().toLowerCase() != + storedValues[0].trim().toLowerCase() + ) { + setLichessUsername(storedValues[0].trim().toLowerCase()); + } + }, [storedValues, hasEdited, lichessUsername]); + + const updateHistory = (username: string) => { + const trimmed = username.trim(); + if (!trimmed) return; + const lower = trimmed.toLowerCase(); + + const exists = storedValues.some((u) => u.toLowerCase() === lower); + if (!exists) { + const updated = [trimmed, ...storedValues.filter((u) => u !== trimmed)]; + setStoredValues(updated.join(",")); + } + }; + + const deleteUsername = (usernameToDelete: string) => { + const updated = storedValues.filter((u) => u !== usernameToDelete); + setStoredValues(updated.join(",")); + }; + + const handleChange = (_: React.SyntheticEvent, newValue: string | null) => { + const newInputValue = newValue ?? ""; + if ( + newInputValue.trim().toLowerCase() != lichessUsername.trim().toLowerCase() + ) + setLichessUsername(newInputValue.trim().toLowerCase()); + }; + + const handleInputChange = ( + _: React.SyntheticEvent, + newInputValue: string + ) => { + if ( + newInputValue.trim().toLowerCase() != lichessUsername.trim().toLowerCase() + ) { + setLichessUsername(newInputValue.trim().toLowerCase()); + if (!hasEdited) setHasEdited(true); + } + }; + const debouncedUsername = useDebounce(lichessUsername, 500); const { @@ -38,15 +103,48 @@ export default function LichessInput({ onSelect }: Props) { return ( <> - setLichessUsername(e.target.value)} + { + const { key, ...rest } = props; + return ( +
  • + {option} + { + e.stopPropagation(); + deleteUsername(option); + }} + /> +
  • + ); + }} + renderInput={(params) => ( + + )} />
    - {lichessUsername && ( + {debouncedUsername && ( ( { + updateHistory(debouncedUsername); const boardOrientation = - lichessUsername.toLowerCase() !== + debouncedUsername.toLowerCase() !== game.players?.black?.user?.name?.toLowerCase(); onSelect(game.pgn, boardOrientation); }}