/*
* Copyright (c) 2021 - 2024, Ludvig Lundgren and the autobrr contributors.
* SPDX-License-Identifier: GPL-2.0-or-later
*/
import { Fragment } from "react";
import { Field, FieldProps } from "formik";
import { Listbox, ListboxButton, Label, ListboxOption, ListboxOptions, Transition } from "@headlessui/react";
import { CheckIcon, ChevronUpDownIcon } from "@heroicons/react/24/solid";
import { MultiSelect as RMSC } from "react-multi-select-component";
import { classNames, COL_WIDTHS } from "@utils";
import { DocsTooltip } from "@components/tooltips/DocsTooltip";
export interface MultiSelectOption {
value: string | number;
label: string;
key?: string;
disabled?: boolean;
}
interface MultiSelectProps {
name: string;
label?: string;
options: MultiSelectOption[];
columns?: COL_WIDTHS;
creatable?: boolean;
disabled?: boolean;
tooltip?: JSX.Element;
}
export const MultiSelect = ({
name,
label,
options,
columns,
creatable,
tooltip,
disabled
}: MultiSelectProps) => {
const handleNewField = (value: string) => ({
value: value.toUpperCase(),
label: value.toUpperCase(),
key: value
});
return (
{({
field,
form: { setFieldValue }
}: FieldProps) => (
({
value: item.value ? item.value : item,
label: item.label ? item.label : item
}))}
onChange={(values: Array) => {
const am = values && values.map((i) => i.value);
setFieldValue(field.name, am);
}}
/>
)}
);
};
interface IndexerMultiSelectOption {
id: number;
name: string;
}
export const IndexerMultiSelect = ({
name,
label,
options,
columns
}: MultiSelectProps) => (
{({
field,
meta,
form: { setFieldValue }
}: FieldProps) => (
<>
({
value: item.id, label: item.name
}))}
onChange={(values: MultiSelectOption[]) => {
const item = values && values.map((i) => ({ id: i.value, name: i.label }));
setFieldValue(field.name, item);
}}
/>
{meta.touched && meta.error && (
* {meta.error}
)}
>
)}
);
interface DownloadClientSelectProps {
name: string;
action: Action;
clients: DownloadClient[];
}
export function DownloadClientSelect({
name,
action,
clients
}: DownloadClientSelectProps) {
return (
{({
field,
meta,
form: { setFieldValue }
}: FieldProps) => (
setFieldValue(field?.name, value)}
>
{({ open }) => (
<>
{field.value
? clients.find((c) => c.id === field.value)?.name
: "Choose a client"}
{clients
.filter((c) => c.type === action.type)
.map((client) => (
classNames(
active
? "text-white dark:text-gray-100 bg-blue-600 dark:bg-gray-950"
: "text-gray-900 dark:text-gray-300",
"cursor-default select-none relative py-2 pl-3 pr-9"
)}
value={client.id}
>
{({ selected, active }) => (
<>
{client.name}
{selected ? (
) : null}
>
)}
))}
{meta.touched && meta.error && (
* {meta.error}
)}
>
)}
)}
);
}
export interface SelectFieldOption {
label: string;
value: string | number | null;
}
export interface SelectFieldProps {
name: string;
label: string;
optionDefaultText: string;
options: SelectFieldOption[];
columns?: COL_WIDTHS;
tooltip?: JSX.Element;
className?: string;
}
export const Select = ({
name,
label,
tooltip,
optionDefaultText,
options,
columns = 6,
className
}: SelectFieldProps) => {
return (
{({
field,
form: { setFieldValue }
}: FieldProps) => (
setFieldValue(field.name, value)}
>
{({ open }) => (
{field.value
? options.find((c) => c.value === field.value)?.label
: optionDefaultText
}
{options.map((opt) => (
classNames(
selected
? "font-bold text-black dark:text-white bg-gray-300 dark:bg-gray-950"
: (
hovered
? "text-black dark:text-gray-100 font-normal"
: "text-gray-700 dark:text-gray-300 font-normal"
),
hovered ? "bg-gray-200 dark:bg-gray-800" : "",
"transition-colors cursor-default select-none relative py-2 pl-3 pr-9"
)
}
value={opt.value}
>
{({ selected }) => (
<>
{opt.label}
>
)}
))}
)}
)}
);
};
export const SelectWide = ({
name,
label,
optionDefaultText,
options
}: SelectFieldProps) => {
return (
{({
field,
form: { setFieldValue }
}: FieldProps) => (
setFieldValue(field?.name, value)}
>
{({ open }) => (
{field.value
? options.find((c) => c.value === field.value)?.label
: optionDefaultText
}
{options.map((opt) => (
classNames(
active
? "text-white dark:text-gray-100 bg-blue-600 dark:bg-gray-800"
: "text-gray-900 dark:text-gray-300",
"cursor-default select-none relative py-2 pl-3 pr-9"
)
}
value={opt.value}
>
{({ selected, active }) => (
<>
{opt.label}
{selected ? (
) : null}
>
)}
))}
)}
)}
);
};
export const AgeSelect = ({
duration,
setDuration,
setParsedDuration,
columns = 6
}: {
duration: string;
setDuration: (value: string) => void;
setParsedDuration: (value: number) => void;
columns?: number;
}) => {
const options = [
{ value: '1', label: '1 hour' },
{ value: '12', label: '12 hours' },
{ value: '24', label: '1 day' },
{ value: '168', label: '1 week' },
{ value: '720', label: '1 month' },
{ value: '2160', label: '3 months' },
{ value: '4320', label: '6 months' },
{ value: '8760', label: '1 year' },
{ value: '0', label: 'Delete everything' }
];
return (
{
const parsedValue = parseInt(value, 10);
setParsedDuration(parsedValue);
setDuration(value);
}}>
{({ open }) => (
<>
{duration ? options.find(opt => opt.value === duration)?.label : 'Select...'}
{options.map((option) => (
`relative cursor-default select-none py-2 pl-3 pr-9 ${selected ? "font-bold text-black dark:text-white bg-gray-300 dark:bg-gray-950" : active ? "text-black dark:text-gray-100 font-normal bg-gray-200 dark:bg-gray-800" : "text-gray-700 dark:text-gray-300 font-normal"
}`
}
value={option.value}
>
{({ selected }) => (
<>
{option.label}
{selected && (
)}
>
)}
))}
>
)}
);
};