Files
flxn-app/src/features/login/components/player-prompt/index.tsx
2025-08-30 01:42:23 -05:00

130 lines
4.0 KiB
TypeScript

import { useState, FormEventHandler, useMemo } from 'react';
import { ArrowLeftIcon } from '@phosphor-icons/react';
import { Autocomplete, Divider, Flex, Text, TextInput, Title, UnstyledButton } from '@mantine/core';
import ExistingPlayerButton from './existing-player-button';
import NewPlayerButton from './new-player-button';
import { Player } from '@/features/players/types';
import toast from '@/lib/sonner'
import { useUnassociatedPlayers } from '@/features/players/queries';
import useCreateUser from '../../hooks/use-create-user';
import Button from '@/components/button';
enum PlayerPromptStage {
returning = 'returning',
new = 'new'
}
const PlayerPrompt = () => {
const [stage, setStage] = useState<PlayerPromptStage>();
const playersQuery = useUnassociatedPlayers();
const { mutate: createUser, isPending } = useCreateUser();
const players = playersQuery.data;
const [player, setPlayer] = useState<Player>();
const [value, setValue] = useState('');
const [error, setError] = useState('');
const parsedPlayers = useMemo(() => players?.map(p => ({ label: `${p.first_name} ${p.last_name}`, value: p})), [players])
const autocompleteOptions = [...new Set(parsedPlayers?.map(p => p.label))]
const formSubmitHandler = (callback: () => void): FormEventHandler<HTMLFormElement> => {
return async (event) => {
event.preventDefault();
await callback();
}
}
const handleNewPlayerSubmit = () => {
const first_name = value.split(' ').slice(0, -1).join(' ');
const last_name = value.split(' ').slice(-1).join(' ');
// check if player already exists
if (!!parsedPlayers?.find(p => p.label === value)) {
toast.error("Player already exists");
return;
}
createUser({
first_name,
last_name
});
}
const handlePlayerSubmit = () => {
if (player) {
setError('');
createUser(player.id!);
} else {
setError('You must select a player from the dropdown. If you don\'t see yourself, please go back and select \'New Player\'');
}
}
const handleNewPlayerChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setValue(event.target.value);
}
const handleReturningPlayerChange = (player: string) => {
const selected = parsedPlayers?.find(p => p.label === player);
if (selected) {
setError('');
setPlayer(selected.value);
} else {
setPlayer(undefined);
}
}
if (!stage) {
return <>
<Title order={3}>Have you played before?</Title>
<Text size='xs' mb='sm'>If this is your first time participating, please select <i>New Player</i>, otherwise select <i>Returning Player</i></Text>
<Flex justify='space-around'>
<ExistingPlayerButton onClick={() => setStage(PlayerPromptStage.returning)} />
<Divider orientation='vertical' variant="dashed" />
<NewPlayerButton onClick={() => setStage(PlayerPromptStage.new)} />
</Flex>
</>
}
return <>
<UnstyledButton
onClick={() => setStage(undefined)}
style={{
position: 'absolute',
top: 24,
left: 24,
}}
>
<Flex align='center' gap='xs'>
<ArrowLeftIcon size={24} />
</Flex>
</UnstyledButton>
{
stage === PlayerPromptStage.new ?
<>
<form onSubmit={formSubmitHandler(handleNewPlayerSubmit)}>
<TextInput
label='Enter your name'
placeholder='Salah Atiyeh'
value={value}
onChange={handleNewPlayerChange}
/>
<Button type='submit' mt='10px' color='green' variant='filled'>Submit</Button>
</form>
</> :
<form onSubmit={formSubmitHandler(handlePlayerSubmit)}>
<Autocomplete
label='Enter your name'
placeholder='Salah Atiyeh'
data={autocompleteOptions}
onChange={handleReturningPlayerChange}
error={error}
/>
<Button type='submit' mt='10px' color='green' variant='filled'>Submit</Button>
</form>
}
</>
};
export default PlayerPrompt;