new typeahead

This commit is contained in:
yohlo
2025-09-25 16:11:54 -05:00
parent c0ef535001
commit b3ebf46afa
7 changed files with 314 additions and 195 deletions

View File

@@ -1,6 +1,7 @@
import { Stack, Button, Divider, Autocomplete, Group, ComboboxItem } from '@mantine/core';
import { Stack, Button, Divider, Group, ComboboxItem, Text } from '@mantine/core';
import { PlusIcon } from '@phosphor-icons/react';
import React, { useMemo, useState } from 'react';
import React, { useMemo } from 'react';
import Typeahead, { TypeaheadOption } from '@/components/typeahead';
interface TeamSelectionViewProps {
options: ComboboxItem[];
@@ -11,11 +12,39 @@ const TeamSelectionView: React.FC<TeamSelectionViewProps> = React.memo(({
options,
onSelect
}) => {
const [value, setValue] = useState<string>('');
const selectedOption = useMemo(() => options.find(option => option.label === value), [value, options])
const [selectedTeam, setSelectedTeam] = React.useState<ComboboxItem | null>(null);
const searchTeams = async (query: string): Promise<TypeaheadOption<ComboboxItem>[]> => {
if (!query.trim()) return [];
const filtered = options.filter(option =>
option.label.toLowerCase().includes(query.toLowerCase())
);
return filtered.map(option => ({
id: String(option.value),
data: option
}));
};
const handleTeamSelect = (option: TypeaheadOption<ComboboxItem>) => {
setSelectedTeam(option.data);
};
const renderTeamOption = (option: TypeaheadOption<ComboboxItem>) => {
return (
<Group py="xs" px="sm" gap="sm">
<Text fw={500}>{option.data.label}</Text>
</Group>
);
};
const formatTeam = (option: TypeaheadOption<ComboboxItem>) => {
return option.data.label;
};
const handleCreateNewTeamClicked = () => onSelect(undefined);
const handleSelectExistingTeam = () => onSelect(selectedOption?.value)
const handleSelectExistingTeam = () => onSelect(selectedTeam?.value);
return (
<Stack gap="md">
@@ -31,17 +60,17 @@ const TeamSelectionView: React.FC<TeamSelectionViewProps> = React.memo(({
<Divider my="sm" label="or" />
<Stack gap="sm">
<Autocomplete
<Typeahead
placeholder="Select one of your existing teams"
value={value}
onChange={setValue}
data={options.map(option => option.label)}
comboboxProps={{ withinPortal: false }}
onSelect={handleTeamSelect}
searchFn={searchTeams}
renderOption={renderTeamOption}
format={formatTeam}
/>
<Button
onClick={handleSelectExistingTeam}
disabled={!selectedOption}
disabled={!selectedTeam}
fullWidth
>
Enroll Selected Team