118
resources/client/titles/title-select.tsx
Executable file
118
resources/client/titles/title-select.tsx
Executable file
@@ -0,0 +1,118 @@
|
||||
import {useTrans} from '@common/i18n/use-trans';
|
||||
import {useFormContext} from 'react-hook-form';
|
||||
import React, {useState} from 'react';
|
||||
import {useTitlesAutocomplete} from '@app/titles/requests/use-titles-autocomplete';
|
||||
import {FormSelect} from '@common/ui/forms/select/select';
|
||||
import {Trans} from '@common/i18n/trans';
|
||||
import {message} from '@common/i18n/message';
|
||||
import {Option} from '@common/ui/forms/combobox/combobox';
|
||||
import {Avatar} from '@common/ui/images/avatar';
|
||||
|
||||
interface Props {
|
||||
name: string;
|
||||
seasonName?: string;
|
||||
episodeName?: string;
|
||||
disableTitleField?: boolean;
|
||||
className?: string;
|
||||
}
|
||||
export function TitleSelect({
|
||||
name,
|
||||
seasonName,
|
||||
episodeName,
|
||||
disableTitleField,
|
||||
className,
|
||||
}: Props) {
|
||||
const {trans} = useTrans();
|
||||
const form = useFormContext();
|
||||
const selectedTitleId = form.watch(name);
|
||||
const [searchQuery, setSearchQuery] = useState('');
|
||||
|
||||
const selectedSeason = seasonName ? form.watch(seasonName) : undefined;
|
||||
const query = useTitlesAutocomplete({
|
||||
searchQuery,
|
||||
selectedTitleId,
|
||||
seasonNumber: selectedSeason,
|
||||
});
|
||||
const isLoading = query.isLoading || query.isPlaceholderData;
|
||||
|
||||
const selectedTitle = query.data?.titles.find(t => t.id === selectedTitleId);
|
||||
const seasonCount = selectedTitle?.seasons_count || 0;
|
||||
const episodeNumbers = selectedTitle?.episode_numbers || [];
|
||||
|
||||
return (
|
||||
<div className={className}>
|
||||
<FormSelect
|
||||
selectionMode="single"
|
||||
name={name}
|
||||
label={<Trans message="Title" />}
|
||||
placeholder={trans(message('Select a title'))}
|
||||
showSearchField
|
||||
searchPlaceholder={trans(message('Search titles'))}
|
||||
inputValue={searchQuery}
|
||||
onInputValueChange={setSearchQuery}
|
||||
isAsync
|
||||
isLoading={isLoading}
|
||||
required
|
||||
disabled={disableTitleField}
|
||||
>
|
||||
{query.data?.titles.map(title => (
|
||||
<Option
|
||||
key={title.id}
|
||||
value={title.id}
|
||||
description={title.description}
|
||||
startIcon={<Avatar src={title.image} />}
|
||||
>
|
||||
{title.name}
|
||||
</Option>
|
||||
))}
|
||||
</FormSelect>
|
||||
{seasonCount > 0 && seasonName && (
|
||||
<FormSelect
|
||||
className="mt-12"
|
||||
name={seasonName}
|
||||
placeholder={trans(message('Select a season (optional)'))}
|
||||
selectionMode="single"
|
||||
label={<Trans message="Season" />}
|
||||
>
|
||||
<Option
|
||||
key="none"
|
||||
value=""
|
||||
onSelected={() => form.resetField(seasonName)}
|
||||
>
|
||||
<Trans message="None" />
|
||||
</Option>
|
||||
{[...new Array(seasonCount).keys()].map(i => {
|
||||
const number = i + 1;
|
||||
return (
|
||||
<Option key={number} value={number}>
|
||||
<Trans message="Season :number" values={{number}} />
|
||||
</Option>
|
||||
);
|
||||
})}
|
||||
</FormSelect>
|
||||
)}
|
||||
{!!episodeNumbers.length && episodeName && (
|
||||
<FormSelect
|
||||
className="mt-12"
|
||||
name={episodeName}
|
||||
placeholder={trans(message('Select an episode (optional)'))}
|
||||
selectionMode="single"
|
||||
label={<Trans message="Episode" />}
|
||||
>
|
||||
<Option
|
||||
key="none"
|
||||
value=""
|
||||
onSelected={() => form.resetField(episodeName)}
|
||||
>
|
||||
<Trans message="None" />
|
||||
</Option>
|
||||
{episodeNumbers.map(number => (
|
||||
<Option key={number} value={number}>
|
||||
<Trans message="Episode :number" values={{number}} />
|
||||
</Option>
|
||||
))}
|
||||
</FormSelect>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user