mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2024-12-01 12:24:28 +01:00
(quality) refactor selectOption
This commit is contained in:
parent
47d6f2e165
commit
9f3cbc46a3
@ -9,6 +9,7 @@ import { FabPagination } from '../../base/fab-pagination';
|
||||
import OrderAPI from '../../../api/order';
|
||||
import { Order, OrderSortOption } from '../../../models/order';
|
||||
import { User } from '../../../models/user';
|
||||
import { SelectOption } from '../../../models/select';
|
||||
|
||||
declare const Application: IApplication;
|
||||
|
||||
@ -16,11 +17,6 @@ interface OrdersDashboardProps {
|
||||
currentUser: User,
|
||||
onError: (message: string) => void
|
||||
}
|
||||
/**
|
||||
* Option format, expected by react-select
|
||||
* @see https://github.com/JedWatson/react-select
|
||||
*/
|
||||
type selectOption = { value: OrderSortOption, label: string };
|
||||
|
||||
/**
|
||||
* This component shows a list of all orders from the store for the current user
|
||||
@ -44,7 +40,7 @@ export const OrdersDashboard: React.FC<OrdersDashboardProps> = ({ currentUser, o
|
||||
/**
|
||||
* Creates sorting options to the react-select format
|
||||
*/
|
||||
const buildOptions = (): Array<selectOption> => {
|
||||
const buildOptions = (): Array<SelectOption<OrderSortOption>> => {
|
||||
return [
|
||||
{ value: 'created_at-desc', label: t('app.public.orders_dashboard.sort.newest') },
|
||||
{ value: 'created_at-asc', label: t('app.public.orders_dashboard.sort.oldest') }
|
||||
@ -53,7 +49,7 @@ export const OrdersDashboard: React.FC<OrdersDashboardProps> = ({ currentUser, o
|
||||
/**
|
||||
* Display option: sorting
|
||||
*/
|
||||
const handleSorting = (option: selectOption) => {
|
||||
const handleSorting = (option: SelectOption<OrderSortOption>) => {
|
||||
OrderAPI.index({ page: 1, sort: option.value }).then(res => {
|
||||
setCurrentPage(1);
|
||||
setOrders(res.data);
|
||||
|
@ -7,6 +7,7 @@ import { Event } from '../../models/event';
|
||||
import { EventTheme } from '../../models/event-theme';
|
||||
import { IApplication } from '../../models/application';
|
||||
import EventThemeAPI from '../../api/event-theme';
|
||||
import { SelectOption } from '../../models/select';
|
||||
|
||||
declare const Application: IApplication;
|
||||
|
||||
@ -15,12 +16,6 @@ interface EventThemesProps {
|
||||
onChange: (themes: Array<EventTheme>) => void
|
||||
}
|
||||
|
||||
/**
|
||||
* Option format, expected by react-select
|
||||
* @see https://github.com/JedWatson/react-select
|
||||
*/
|
||||
type selectOption = { value: number, label: string };
|
||||
|
||||
/**
|
||||
* This component shows a select input to edit the themes associated with the event
|
||||
*/
|
||||
@ -43,7 +38,7 @@ export const EventThemes: React.FC<EventThemesProps> = ({ event, onChange }) =>
|
||||
/**
|
||||
* Return the current theme(s) for the given event, formatted to match the react-select format
|
||||
*/
|
||||
const defaultValues = (): Array<selectOption> => {
|
||||
const defaultValues = (): Array<SelectOption<number>> => {
|
||||
const res = [];
|
||||
themes.forEach(t => {
|
||||
if (event.event_theme_ids && event.event_theme_ids.indexOf(t.id) > -1) {
|
||||
@ -57,7 +52,7 @@ export const EventThemes: React.FC<EventThemesProps> = ({ event, onChange }) =>
|
||||
* Callback triggered when the selection has changed.
|
||||
* Convert the react-select specific format to an array of EventTheme, and call the provided callback.
|
||||
*/
|
||||
const handleChange = (selectedOptions: Array<selectOption>): void => {
|
||||
const handleChange = (selectedOptions: Array<SelectOption<number>>): void => {
|
||||
const res = [];
|
||||
selectedOptions.forEach(opt => {
|
||||
res.push(themes.find(t => t.id === opt.value));
|
||||
@ -68,7 +63,7 @@ export const EventThemes: React.FC<EventThemesProps> = ({ event, onChange }) =>
|
||||
/**
|
||||
* Convert all themes to the react-select format
|
||||
*/
|
||||
const buildOptions = (): Array<selectOption> => {
|
||||
const buildOptions = (): Array<SelectOption<number>> => {
|
||||
return themes.map(t => {
|
||||
return { value: t.id, label: t.name };
|
||||
});
|
||||
|
@ -7,11 +7,7 @@ import { UnpackNestedValue } from 'react-hook-form/dist/types';
|
||||
import { FormControlledComponent } from '../../models/form-component';
|
||||
import { AbstractFormItem, AbstractFormItemProps } from './abstract-form-item';
|
||||
import { FabButton } from '../base/fab-button';
|
||||
|
||||
/**
|
||||
* Checklist Option format
|
||||
*/
|
||||
export type ChecklistOption<TOptionValue> = { value: TOptionValue, label: string };
|
||||
import { ChecklistOption } from '../../models/select';
|
||||
|
||||
interface FormChecklistProps<TFieldValues, TOptionValue, TContext extends object> extends FormControlledComponent<TFieldValues, TContext>, AbstractFormItemProps<TFieldValues> {
|
||||
defaultValue?: Array<TOptionValue>,
|
||||
|
@ -7,9 +7,10 @@ import { FieldPath } from 'react-hook-form/dist/types/path';
|
||||
import { FieldPathValue, UnpackNestedValue } from 'react-hook-form/dist/types';
|
||||
import { FormControlledComponent } from '../../models/form-component';
|
||||
import { AbstractFormItem, AbstractFormItemProps } from './abstract-form-item';
|
||||
import { SelectOption } from '../../models/select';
|
||||
|
||||
interface FormSelectProps<TFieldValues, TContext extends object, TOptionValue> extends FormControlledComponent<TFieldValues, TContext>, AbstractFormItemProps<TFieldValues> {
|
||||
options: Array<selectOption<TOptionValue>>,
|
||||
interface FormSelectProps<TFieldValues, TContext extends object, TOptionValue, TOptionLabel> extends FormControlledComponent<TFieldValues, TContext>, AbstractFormItemProps<TFieldValues> {
|
||||
options: Array<SelectOption<TOptionValue, TOptionLabel>>,
|
||||
valueDefault?: TOptionValue,
|
||||
onChange?: (value: TOptionValue) => void,
|
||||
placeholder?: string,
|
||||
@ -17,16 +18,10 @@ interface FormSelectProps<TFieldValues, TContext extends object, TOptionValue> e
|
||||
creatable?: boolean,
|
||||
}
|
||||
|
||||
/**
|
||||
* Option format, expected by react-select
|
||||
* @see https://github.com/JedWatson/react-select
|
||||
*/
|
||||
type selectOption<TOptionValue> = { value: TOptionValue, label: string };
|
||||
|
||||
/**
|
||||
* This component is a wrapper for react-select to use with react-hook-form
|
||||
*/
|
||||
export const FormSelect = <TFieldValues extends FieldValues, TContext extends object, TOptionValue>({ id, label, tooltip, className, control, placeholder, options, valueDefault, error, warning, rules, disabled = false, onChange, clearable = false, formState, creatable = false }: FormSelectProps<TFieldValues, TContext, TOptionValue>) => {
|
||||
export const FormSelect = <TFieldValues extends FieldValues, TContext extends object, TOptionValue, TOptionLabel>({ id, label, tooltip, className, control, placeholder, options, valueDefault, error, warning, rules, disabled = false, onChange, clearable = false, formState, creatable = false }: FormSelectProps<TFieldValues, TContext, TOptionValue, TOptionLabel>) => {
|
||||
const [isDisabled, setIsDisabled] = React.useState<boolean>(false);
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -12,6 +12,7 @@ import { FormSelect } from '../form/form-select';
|
||||
import MemberAPI from '../../api/member';
|
||||
import SettingAPI from '../../api/setting';
|
||||
import UserLib from '../../lib/user';
|
||||
import { SelectOption } from '../../models/select';
|
||||
|
||||
declare const Application: IApplication;
|
||||
|
||||
@ -23,12 +24,6 @@ interface ChangeGroupProps {
|
||||
className?: string,
|
||||
}
|
||||
|
||||
/**
|
||||
* Option format, expected by react-select
|
||||
* @see https://github.com/JedWatson/react-select
|
||||
*/
|
||||
type selectOption = { value: number, label: string };
|
||||
|
||||
/**
|
||||
* Component to display the group of the provided user, and allow him to change his group.
|
||||
*/
|
||||
@ -72,7 +67,7 @@ export const ChangeGroup: React.FC<ChangeGroupProps> = ({ user, onSuccess, onErr
|
||||
/**
|
||||
* Convert the provided array of items to the react-select format
|
||||
*/
|
||||
const buildGroupsOptions = (): Array<selectOption> => {
|
||||
const buildGroupsOptions = (): Array<SelectOption<number>> => {
|
||||
return groups?.map(t => {
|
||||
return { value: t.id, label: t.name };
|
||||
});
|
||||
|
@ -1,17 +1,12 @@
|
||||
import React from 'react';
|
||||
import Select from 'react-select';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { SelectOption } from '../../models/select';
|
||||
|
||||
interface MachinesFiltersProps {
|
||||
onStatusSelected: (enabled: boolean) => void,
|
||||
}
|
||||
|
||||
/**
|
||||
* Option format, expected by react-select
|
||||
* @see https://github.com/JedWatson/react-select
|
||||
*/
|
||||
type selectOption = { value: boolean, label: string };
|
||||
|
||||
/**
|
||||
* Allows filtering on machines list
|
||||
*/
|
||||
@ -23,7 +18,7 @@ export const MachinesFilters: React.FC<MachinesFiltersProps> = ({ onStatusSelect
|
||||
/**
|
||||
* Provides boolean options in the react-select format (yes/no/all)
|
||||
*/
|
||||
const buildBooleanOptions = (): Array<selectOption> => {
|
||||
const buildBooleanOptions = (): Array<SelectOption<boolean>> => {
|
||||
return [
|
||||
defaultValue,
|
||||
{ value: false, label: t('app.public.machines_filters.status_disabled') },
|
||||
@ -34,7 +29,7 @@ export const MachinesFilters: React.FC<MachinesFiltersProps> = ({ onStatusSelect
|
||||
/**
|
||||
* Callback triggered when the user selects a machine status in the dropdown list
|
||||
*/
|
||||
const handleStatusSelected = (option: selectOption): void => {
|
||||
const handleStatusSelected = (option: SelectOption<boolean>): void => {
|
||||
onStatusSelected(option.value);
|
||||
};
|
||||
|
||||
|
@ -4,6 +4,7 @@ import { useTranslation } from 'react-i18next';
|
||||
import { FabModal } from '../base/fab-modal';
|
||||
import { PaymentMethod, PaymentSchedule } from '../../models/payment-schedule';
|
||||
import PaymentScheduleAPI from '../../api/payment-schedule';
|
||||
import { SelectOption } from '../../models/select';
|
||||
|
||||
interface UpdatePaymentMeanModalProps {
|
||||
isOpen: boolean,
|
||||
@ -13,12 +14,6 @@ interface UpdatePaymentMeanModalProps {
|
||||
paymentSchedule: PaymentSchedule
|
||||
}
|
||||
|
||||
/**
|
||||
* Option format, expected by react-select
|
||||
* @see https://github.com/JedWatson/react-select
|
||||
*/
|
||||
type selectOption = { value: PaymentMethod, label: string };
|
||||
|
||||
/**
|
||||
* Component to allow the member to change his payment mean for the given payment schedule (e.g. from card to transfer)
|
||||
*/
|
||||
@ -30,7 +25,7 @@ export const UpdatePaymentMeanModal: React.FC<UpdatePaymentMeanModalProps> = ({
|
||||
/**
|
||||
* Convert all payment means to the react-select format
|
||||
*/
|
||||
const buildOptions = (): Array<selectOption> => {
|
||||
const buildOptions = (): Array<SelectOption<PaymentMethod>> => {
|
||||
return Object.keys(PaymentMethod).filter(pm => PaymentMethod[pm] !== PaymentMethod.Card).map(pm => {
|
||||
return { value: PaymentMethod[pm], label: t(`app.admin.update_payment_mean_modal.method_${pm}`) };
|
||||
});
|
||||
@ -39,7 +34,7 @@ export const UpdatePaymentMeanModal: React.FC<UpdatePaymentMeanModalProps> = ({
|
||||
/**
|
||||
* When the payment mean is changed in the select, update the state
|
||||
*/
|
||||
const handleMeanSelected = (option: selectOption): void => {
|
||||
const handleMeanSelected = (option: SelectOption<PaymentMethod>): void => {
|
||||
setPaymentMean(option.value);
|
||||
};
|
||||
|
||||
|
@ -9,16 +9,11 @@ import { CardPaymentModal } from '../card-payment-modal';
|
||||
import { PaymentSchedule } from '../../../models/payment-schedule';
|
||||
import { HtmlTranslate } from '../../base/html-translate';
|
||||
import CheckoutAPI from '../../../api/checkout';
|
||||
import { SelectOption } from '../../../models/select';
|
||||
|
||||
const ALL_SCHEDULE_METHODS = ['card', 'check', 'transfer'] as const;
|
||||
type scheduleMethod = typeof ALL_SCHEDULE_METHODS[number];
|
||||
|
||||
/**
|
||||
* Option format, expected by react-select
|
||||
* @see https://github.com/JedWatson/react-select
|
||||
*/
|
||||
type selectOption = { value: scheduleMethod, label: string };
|
||||
|
||||
/**
|
||||
* A form component to ask for confirmation before cashing a payment directly at the FabLab's reception.
|
||||
* This is intended for use by privileged users.
|
||||
@ -44,14 +39,14 @@ export const LocalPaymentForm: React.FC<GatewayFormProps> = ({ onSubmit, onSucce
|
||||
/**
|
||||
* Convert all payement methods for schedules to the react-select format
|
||||
*/
|
||||
const buildMethodOptions = (): Array<selectOption> => {
|
||||
const buildMethodOptions = (): Array<SelectOption<scheduleMethod>> => {
|
||||
return ALL_SCHEDULE_METHODS.map(i => methodToOption(i));
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert the given payment-method to the react-select format
|
||||
*/
|
||||
const methodToOption = (value: scheduleMethod): selectOption => {
|
||||
const methodToOption = (value: scheduleMethod): SelectOption<scheduleMethod> => {
|
||||
if (!value) return { value, label: '' };
|
||||
|
||||
return { value, label: t(`app.admin.local_payment_form.method_${value}`) };
|
||||
@ -60,7 +55,7 @@ export const LocalPaymentForm: React.FC<GatewayFormProps> = ({ onSubmit, onSucce
|
||||
/**
|
||||
* Callback triggered when the user selects a payment method for the current payment schedule.
|
||||
*/
|
||||
const handleUpdateMethod = (option: selectOption) => {
|
||||
const handleUpdateMethod = (option: SelectOption<scheduleMethod>) => {
|
||||
updateCart(Object.assign({}, cart, { payment_method: option.value }));
|
||||
setMethod(option.value);
|
||||
};
|
||||
|
@ -5,6 +5,7 @@ import { Group } from '../../models/group';
|
||||
import { User } from '../../models/user';
|
||||
import PlanAPI from '../../api/plan';
|
||||
import { PlansDuration } from '../../models/plan';
|
||||
import { SelectOption } from '../../models/select';
|
||||
|
||||
interface PlansFilterProps {
|
||||
user?: User,
|
||||
@ -14,12 +15,6 @@ interface PlansFilterProps {
|
||||
onDurationSelected: (plansIds: Array<number>) => void,
|
||||
}
|
||||
|
||||
/**
|
||||
* Option format, expected by react-select
|
||||
* @see https://github.com/JedWatson/react-select
|
||||
*/
|
||||
type selectOption = { value: number, label: string };
|
||||
|
||||
/**
|
||||
* Allows filtering on plans list
|
||||
*/
|
||||
@ -38,7 +33,7 @@ export const PlansFilter: React.FC<PlansFilterProps> = ({ user, groups, onGroupS
|
||||
/**
|
||||
* Convert all groups to the react-select format
|
||||
*/
|
||||
const buildGroupOptions = (): Array<selectOption> => {
|
||||
const buildGroupOptions = (): Array<SelectOption<number>> => {
|
||||
return groups.filter(g => !g.disabled && g.slug !== 'admins').map(g => {
|
||||
return { value: g.id, label: g.name };
|
||||
});
|
||||
@ -47,7 +42,7 @@ export const PlansFilter: React.FC<PlansFilterProps> = ({ user, groups, onGroupS
|
||||
/**
|
||||
* Convert all durations to the react-select format
|
||||
*/
|
||||
const buildDurationOptions = (): Array<selectOption> => {
|
||||
const buildDurationOptions = (): Array<SelectOption<number>> => {
|
||||
const options = durations.map((d, index) => {
|
||||
return { value: index, label: d.name };
|
||||
});
|
||||
@ -58,14 +53,14 @@ export const PlansFilter: React.FC<PlansFilterProps> = ({ user, groups, onGroupS
|
||||
/**
|
||||
* Callback triggered when the user selects a group in the dropdown list
|
||||
*/
|
||||
const handleGroupSelected = (option: selectOption): void => {
|
||||
const handleGroupSelected = (option: SelectOption<number>): void => {
|
||||
onGroupSelected(option.value);
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback triggered when the user selects a duration in the dropdown list
|
||||
*/
|
||||
const handleDurationSelected = (option: selectOption): void => {
|
||||
const handleDurationSelected = (option: SelectOption<number>): void => {
|
||||
onDurationSelected(durations[option.value]?.plans_ids);
|
||||
};
|
||||
|
||||
|
@ -6,6 +6,7 @@ import { useTranslation } from 'react-i18next';
|
||||
import { useImmer } from 'use-immer';
|
||||
import { FabInput } from '../../base/fab-input';
|
||||
import { IFablab } from '../../../models/fablab';
|
||||
import { SelectOption } from '../../../models/select';
|
||||
|
||||
declare let Fablab: IFablab;
|
||||
|
||||
@ -18,12 +19,6 @@ interface PackFormProps {
|
||||
const ALL_INTERVALS = ['day', 'week', 'month', 'year'] as const;
|
||||
type interval = typeof ALL_INTERVALS[number];
|
||||
|
||||
/**
|
||||
* Option format, expected by react-select
|
||||
* @see https://github.com/JedWatson/react-select
|
||||
*/
|
||||
type selectOption = { value: interval, label: string };
|
||||
|
||||
/**
|
||||
* A form component to create/edit a PrepaidPack.
|
||||
* The form validation must be created elsewhere, using the attribute form={formId}.
|
||||
@ -36,14 +31,14 @@ export const PackForm: React.FC<PackFormProps> = ({ formId, onSubmit, pack }) =>
|
||||
/**
|
||||
* Convert all validity-intervals to the react-select format
|
||||
*/
|
||||
const buildOptions = (): Array<selectOption> => {
|
||||
const buildOptions = (): Array<SelectOption<interval>> => {
|
||||
return ALL_INTERVALS.map(i => intervalToOption(i));
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert the given validity-interval to the react-select format
|
||||
*/
|
||||
const intervalToOption = (value: interval): selectOption => {
|
||||
const intervalToOption = (value: interval): SelectOption<interval> => {
|
||||
if (!value) return { value, label: '' };
|
||||
|
||||
return { value, label: t(`app.admin.pack_form.intervals.${value}`, { COUNT: packData.validity_count || 0 }) };
|
||||
@ -87,7 +82,7 @@ export const PackForm: React.FC<PackFormProps> = ({ formId, onSubmit, pack }) =>
|
||||
/**
|
||||
* Callback triggered when the user selects a type of interval for the current pack.
|
||||
*/
|
||||
const handleUpdateValidityInterval = (option: selectOption) => {
|
||||
const handleUpdateValidityInterval = (option: SelectOption<interval>) => {
|
||||
updatePackData(draft => {
|
||||
draft.validity_interval = option.value as interval;
|
||||
});
|
||||
|
@ -8,6 +8,7 @@ import { ProductCategory } from '../../../models/product-category';
|
||||
import { FabButton } from '../../base/fab-button';
|
||||
import ProductCategoryAPI from '../../../api/product-category';
|
||||
import { HtmlTranslate } from '../../base/html-translate';
|
||||
import { SelectOption } from '../../../models/select';
|
||||
|
||||
interface ProductCategoryFormProps {
|
||||
action: 'create' | 'update' | 'delete',
|
||||
@ -17,12 +18,6 @@ interface ProductCategoryFormProps {
|
||||
onError: (message: string) => void,
|
||||
}
|
||||
|
||||
/**
|
||||
* Option format, expected by react-select
|
||||
* @see https://github.com/JedWatson/react-select
|
||||
*/
|
||||
type selectOption = { value: number, label: string };
|
||||
|
||||
/**
|
||||
* Form to create/edit/delete a product category
|
||||
*/
|
||||
@ -40,7 +35,7 @@ export const ProductCategoryForm: React.FC<ProductCategoryFormProps> = ({ action
|
||||
/**
|
||||
* Convert all parents to the react-select format
|
||||
*/
|
||||
const buildOptions = (): Array<selectOption> => {
|
||||
const buildOptions = (): Array<SelectOption<number>> => {
|
||||
const options = parents.map(t => {
|
||||
return { value: t.id, label: t.name };
|
||||
});
|
||||
|
@ -7,6 +7,7 @@ import { FormSelect } from '../../form/form-select';
|
||||
import { FormInput } from '../../form/form-input';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import _ from 'lodash';
|
||||
import { SelectOption } from '../../../models/select';
|
||||
|
||||
interface StockFilterProps {
|
||||
onApplyFilters: (filters: ProductIndexFilter) => void,
|
||||
@ -14,12 +15,6 @@ interface StockFilterProps {
|
||||
openDefault?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Option format, expected by react-select
|
||||
* @see https://github.com/JedWatson/react-select
|
||||
*/
|
||||
type selectOption = { value: StockType, label: string };
|
||||
|
||||
/**
|
||||
* Component to filter the products list by stock
|
||||
*/
|
||||
@ -51,7 +46,7 @@ export const StockFilter: React.FC<StockFilterProps> = ({ onApplyFilters, curren
|
||||
};
|
||||
|
||||
/** Creates sorting options to the react-select format */
|
||||
const buildStockOptions = (): Array<selectOption> => {
|
||||
const buildStockOptions = (): Array<SelectOption<StockType>> => {
|
||||
return [
|
||||
{ value: 'internal', label: t('app.admin.store.stock_filter.stock_internal') },
|
||||
{ value: 'external', label: t('app.admin.store.stock_filter.stock_external') }
|
||||
|
@ -6,6 +6,7 @@ import OrderAPI from '../../api/order';
|
||||
import { Order } from '../../models/order';
|
||||
import FabTextEditor from '../base/text-editor/fab-text-editor';
|
||||
import { HtmlTranslate } from '../base/html-translate';
|
||||
import { SelectOption } from '../../models/select';
|
||||
|
||||
interface OrderActionsProps {
|
||||
order: Order,
|
||||
@ -13,18 +14,12 @@ interface OrderActionsProps {
|
||||
onError: (message: string) => void,
|
||||
}
|
||||
|
||||
/**
|
||||
* Option format, expected by react-select
|
||||
* @see https://github.com/JedWatson/react-select
|
||||
*/
|
||||
type selectOption = { value: string, label: string };
|
||||
|
||||
/**
|
||||
* Actions for an order
|
||||
*/
|
||||
export const OrderActions: React.FC<OrderActionsProps> = ({ order, onSuccess, onError }) => {
|
||||
const { t } = useTranslation('shared');
|
||||
const [currentAction, setCurrentAction] = useState<selectOption>();
|
||||
const [currentAction, setCurrentAction] = useState<SelectOption<string>>();
|
||||
const [modalIsOpen, setModalIsOpen] = useState<boolean>(false);
|
||||
const [readyNote, setReadyNote] = useState<string>('');
|
||||
|
||||
@ -51,7 +46,7 @@ export const OrderActions: React.FC<OrderActionsProps> = ({ order, onSuccess, on
|
||||
/**
|
||||
* Creates sorting options to the react-select format
|
||||
*/
|
||||
const buildOptions = (): Array<selectOption> => {
|
||||
const buildOptions = (): Array<SelectOption<string>> => {
|
||||
let actions = [];
|
||||
switch (order.state) {
|
||||
case 'paid':
|
||||
@ -80,7 +75,7 @@ export const OrderActions: React.FC<OrderActionsProps> = ({ order, onSuccess, on
|
||||
/**
|
||||
* Callback after selecting an action
|
||||
*/
|
||||
const handleAction = (action: selectOption) => {
|
||||
const handleAction = (action: SelectOption<string>) => {
|
||||
setCurrentAction(action);
|
||||
setModalIsOpen(true);
|
||||
};
|
||||
|
@ -16,6 +16,7 @@ import OrderAPI from '../../api/order';
|
||||
import { Order, OrderIndexFilter, OrderSortOption } from '../../models/order';
|
||||
import { FabPagination } from '../base/fab-pagination';
|
||||
import { CaretDoubleUp, X } from 'phosphor-react';
|
||||
import { ChecklistOption, SelectOption } from '../../models/select';
|
||||
|
||||
declare const Application: IApplication;
|
||||
|
||||
@ -23,16 +24,6 @@ interface OrdersProps {
|
||||
currentUser?: User,
|
||||
onError: (message: string) => void,
|
||||
}
|
||||
/**
|
||||
* Option format, expected by react-select
|
||||
* @see https://github.com/JedWatson/react-select
|
||||
*/
|
||||
type selectOption = { value: OrderSortOption, label: string };
|
||||
|
||||
/**
|
||||
* Option format, expected by checklist
|
||||
*/
|
||||
type checklistOption = { value: string, label: string };
|
||||
|
||||
const initFilters: OrderIndexFilter = {
|
||||
reference: '',
|
||||
@ -72,14 +63,7 @@ const Orders: React.FC<OrdersProps> = ({ currentUser, onError }) => {
|
||||
}).catch(onError);
|
||||
}, [filters]);
|
||||
|
||||
/**
|
||||
* Create a new order
|
||||
*/
|
||||
const newOrder = () => {
|
||||
console.log('Create new order');
|
||||
};
|
||||
|
||||
const statusOptions: checklistOption[] = [
|
||||
const statusOptions: ChecklistOption<string>[] = [
|
||||
{ value: 'cart', label: t('app.admin.store.orders.state.cart') },
|
||||
{ value: 'paid', label: t('app.admin.store.orders.state.paid') },
|
||||
{ value: 'payment_failed', label: t('app.admin.store.orders.state.payment_failed') },
|
||||
@ -174,7 +158,7 @@ const Orders: React.FC<OrdersProps> = ({ currentUser, onError }) => {
|
||||
/**
|
||||
* Creates sorting options to the react-select format
|
||||
*/
|
||||
const buildOptions = (): Array<selectOption> => {
|
||||
const buildOptions = (): Array<SelectOption<OrderSortOption>> => {
|
||||
return [
|
||||
{ value: 'created_at-desc', label: t('app.admin.store.orders.sort.newest') },
|
||||
{ value: 'created_at-asc', label: t('app.admin.store.orders.sort.oldest') }
|
||||
@ -184,7 +168,7 @@ const Orders: React.FC<OrdersProps> = ({ currentUser, onError }) => {
|
||||
/**
|
||||
* Display option: sorting
|
||||
*/
|
||||
const handleSorting = (option: selectOption) => {
|
||||
const handleSorting = (option: SelectOption<OrderSortOption>) => {
|
||||
setFilters(draft => {
|
||||
draft.sort = option.value;
|
||||
});
|
||||
@ -200,7 +184,7 @@ const Orders: React.FC<OrdersProps> = ({ currentUser, onError }) => {
|
||||
/**
|
||||
* Filter: by status
|
||||
*/
|
||||
const handleSelectStatus = (s: checklistOption, checked: boolean) => {
|
||||
const handleSelectStatus = (s: ChecklistOption<string>, checked: boolean) => {
|
||||
const list = [...states];
|
||||
checked
|
||||
? list.push(s.value)
|
||||
@ -250,11 +234,6 @@ const Orders: React.FC<OrdersProps> = ({ currentUser, onError }) => {
|
||||
<div className='orders'>
|
||||
<header>
|
||||
<h2>{t('app.admin.store.orders.heading')}</h2>
|
||||
{false &&
|
||||
<div className='grpBtn'>
|
||||
<FabButton className="main-action-btn" onClick={newOrder}>{t('app.admin.store.orders.create_order')}</FabButton>
|
||||
</div>
|
||||
}
|
||||
</header>
|
||||
|
||||
<aside className={`store-filters ${filtersPanel ? '' : 'collapsed'}`}>
|
||||
|
@ -23,6 +23,7 @@ import { CloneProductModal } from './clone-product-modal';
|
||||
import ProductLib from '../../lib/product';
|
||||
import { UnsavedFormAlert } from '../form/unsaved-form-alert';
|
||||
import { UIRouter } from '@uirouter/angularjs';
|
||||
import { SelectOption, ChecklistOption } from '../../models/select';
|
||||
|
||||
interface ProductFormProps {
|
||||
product: Product,
|
||||
@ -32,17 +33,6 @@ interface ProductFormProps {
|
||||
uiRouter: UIRouter
|
||||
}
|
||||
|
||||
/**
|
||||
* Option format, expected by react-select
|
||||
* @see https://github.com/JedWatson/react-select
|
||||
*/
|
||||
type selectOption = { value: number, label: string | JSX.Element };
|
||||
|
||||
/**
|
||||
* Option format, expected by checklist
|
||||
*/
|
||||
type checklistOption = { value: number, label: string };
|
||||
|
||||
/**
|
||||
* Form component to create or update a product
|
||||
*/
|
||||
@ -52,8 +42,8 @@ export const ProductForm: React.FC<ProductFormProps> = ({ product, title, onSucc
|
||||
const { handleSubmit, register, control, formState, setValue, reset } = useForm<Product>({ defaultValues: { ...product } });
|
||||
const output = useWatch<Product>({ control });
|
||||
const [isActivePrice, setIsActivePrice] = useState<boolean>(product.id && _.isFinite(product.amount));
|
||||
const [productCategories, setProductCategories] = useState<selectOption[]>([]);
|
||||
const [machines, setMachines] = useState<checklistOption[]>([]);
|
||||
const [productCategories, setProductCategories] = useState<SelectOption<number, string | JSX.Element>[]>([]);
|
||||
const [machines, setMachines] = useState<ChecklistOption<number>[]>([]);
|
||||
const [stockTab, setStockTab] = useState<boolean>(false);
|
||||
const [openCloneModal, setOpenCloneModal] = useState<boolean>(false);
|
||||
const [saving, setSaving] = useState<boolean>(false);
|
||||
@ -70,7 +60,7 @@ export const ProductForm: React.FC<ProductFormProps> = ({ product, title, onSucc
|
||||
/**
|
||||
* Convert the provided array of items to the react-select format
|
||||
*/
|
||||
const buildSelectOptions = (items: Array<{ id?: number, name: string, parent_id?: number }>): Array<selectOption> => {
|
||||
const buildSelectOptions = (items: Array<{ id?: number, name: string, parent_id?: number }>): Array<SelectOption<number, string | JSX.Element>> => {
|
||||
return items.map(t => {
|
||||
return {
|
||||
value: t.id,
|
||||
@ -84,7 +74,7 @@ export const ProductForm: React.FC<ProductFormProps> = ({ product, title, onSucc
|
||||
/**
|
||||
* Convert the provided array of items to the checklist format
|
||||
*/
|
||||
const buildChecklistOptions = (items: Array<{ id?: number, name: string }>): Array<checklistOption> => {
|
||||
const buildChecklistOptions = (items: Array<{ id?: number, name: string }>): Array<ChecklistOption<number>> => {
|
||||
return items.map(t => {
|
||||
return { value: t.id, label: t.name };
|
||||
});
|
||||
|
@ -28,6 +28,7 @@ import { ActiveFiltersTags } from './filters/active-filters-tags';
|
||||
import SettingAPI from '../../api/setting';
|
||||
import { UIRouter } from '@uirouter/angularjs';
|
||||
import { CaretDoubleUp } from 'phosphor-react';
|
||||
import { SelectOption } from '../../models/select';
|
||||
|
||||
declare const Application: IApplication;
|
||||
|
||||
@ -36,11 +37,6 @@ interface ProductsProps {
|
||||
onError: (message: string) => void,
|
||||
uiRouter: UIRouter,
|
||||
}
|
||||
/**
|
||||
* Option format, expected by react-select
|
||||
* @see https://github.com/JedWatson/react-select
|
||||
*/
|
||||
type selectOption = { value: ProductSortOption, label: string };
|
||||
|
||||
/** This component shows the admin view of the store */
|
||||
const Products: React.FC<ProductsProps> = ({ onSuccess, onError, uiRouter }) => {
|
||||
@ -171,7 +167,7 @@ const Products: React.FC<ProductsProps> = ({ onSuccess, onError, uiRouter }) =>
|
||||
};
|
||||
|
||||
/** Display option: sorting */
|
||||
const handleSorting = (option: selectOption) => {
|
||||
const handleSorting = (option: SelectOption<ProductSortOption>) => {
|
||||
ProductLib.updateFilter(setResources, 'sort', option.value);
|
||||
};
|
||||
|
||||
@ -183,7 +179,7 @@ const Products: React.FC<ProductsProps> = ({ onSuccess, onError, uiRouter }) =>
|
||||
};
|
||||
|
||||
/** Creates sorting options to the react-select format */
|
||||
const buildSortOptions = (): Array<selectOption> => {
|
||||
const buildSortOptions = (): Array<SelectOption<ProductSortOption>> => {
|
||||
return [
|
||||
{ value: 'name-asc', label: t('app.admin.store.products.sort.name_az') },
|
||||
{ value: 'name-desc', label: t('app.admin.store.products.sort.name_za') },
|
||||
|
@ -3,21 +3,17 @@ import { useTranslation } from 'react-i18next';
|
||||
import Select from 'react-select';
|
||||
import Switch from 'react-switch';
|
||||
import { SortOption } from '../../models/api';
|
||||
import { SelectOption } from '../../models/select';
|
||||
|
||||
interface StoreListHeaderProps {
|
||||
productsCount: number,
|
||||
selectOptions: selectOption[],
|
||||
onSelectOptionsChange: (option: selectOption) => void,
|
||||
selectOptions: SelectOption<SortOption>[],
|
||||
onSelectOptionsChange: (option: SelectOption<SortOption>) => void,
|
||||
selectValue?: SortOption,
|
||||
switchLabel?: string,
|
||||
switchChecked?: boolean,
|
||||
onSwitch?: (boolean) => void
|
||||
}
|
||||
/**
|
||||
* Option format, expected by react-select
|
||||
* @see https://github.com/JedWatson/react-select
|
||||
*/
|
||||
type selectOption = { value: SortOption, label: string };
|
||||
|
||||
/**
|
||||
* Renders an accordion item
|
||||
|
@ -28,6 +28,7 @@ import { ActiveFiltersTags } from './filters/active-filters-tags';
|
||||
import ProductLib from '../../lib/product';
|
||||
import { UIRouter } from '@uirouter/angularjs';
|
||||
import SettingAPI from '../../api/setting';
|
||||
import { SelectOption } from '../../models/select';
|
||||
|
||||
declare const Application: IApplication;
|
||||
|
||||
@ -50,11 +51,6 @@ interface StoreProps {
|
||||
currentUser: User,
|
||||
uiRouter: UIRouter,
|
||||
}
|
||||
/**
|
||||
* Option format, expected by react-select
|
||||
* @see https://github.com/JedWatson/react-select
|
||||
*/
|
||||
type selectOption = { value: ProductSortOption, label: string };
|
||||
|
||||
/**
|
||||
* This component shows public store
|
||||
@ -165,7 +161,7 @@ const Store: React.FC<StoreProps> = ({ onError, onSuccess, currentUser, uiRouter
|
||||
/**
|
||||
* Creates sorting options to the react-select format
|
||||
*/
|
||||
const buildOptions = (): Array<selectOption> => {
|
||||
const buildOptions = (): Array<SelectOption<ProductSortOption>> => {
|
||||
return [
|
||||
{ value: 'name-asc', label: t('app.public.store.products.sort.name_az') },
|
||||
{ value: 'name-desc', label: t('app.public.store.products.sort.name_za') },
|
||||
@ -176,7 +172,7 @@ const Store: React.FC<StoreProps> = ({ onError, onSuccess, currentUser, uiRouter
|
||||
/**
|
||||
* Display option: sorting
|
||||
*/
|
||||
const handleSorting = (option: selectOption) => {
|
||||
const handleSorting = (option: SelectOption<ProductSortOption>) => {
|
||||
ProductLib.updateFilter(setResources, 'sort', option.value);
|
||||
};
|
||||
|
||||
|
@ -18,6 +18,7 @@ import { PaymentScheduleSummary } from '../payment-schedule/payment-schedule-sum
|
||||
import { PaymentSchedule } from '../../models/payment-schedule';
|
||||
import PriceAPI from '../../api/price';
|
||||
import { LocalPaymentModal } from '../payment/local-payment/local-payment-modal';
|
||||
import { SelectOption } from '../../models/select';
|
||||
|
||||
declare const Application: IApplication;
|
||||
|
||||
@ -30,12 +31,6 @@ interface SubscribeModalProps {
|
||||
onError: (message: string) => void,
|
||||
}
|
||||
|
||||
/**
|
||||
* Option format, expected by react-select
|
||||
* @see https://github.com/JedWatson/react-select
|
||||
*/
|
||||
type selectOption = { value: number, label: string };
|
||||
|
||||
/**
|
||||
* Modal dialog shown to create a subscription for the given customer
|
||||
*/
|
||||
@ -91,7 +86,7 @@ export const SubscribeModal: React.FC<SubscribeModalProps> = ({ isOpen, toggleMo
|
||||
/**
|
||||
* Callback triggered when the user selects a group in the dropdown list
|
||||
*/
|
||||
const handlePlanSelect = (option: selectOption): void => {
|
||||
const handlePlanSelect = (option: SelectOption<number>): void => {
|
||||
const plan = allPlans.find(p => p.id === option.value);
|
||||
setSelectedPlan(plan);
|
||||
};
|
||||
@ -116,7 +111,7 @@ export const SubscribeModal: React.FC<SubscribeModalProps> = ({ isOpen, toggleMo
|
||||
/**
|
||||
* Convert all groups to the react-select format
|
||||
*/
|
||||
const buildOptions = (): Array<selectOption> => {
|
||||
const buildOptions = (): Array<SelectOption<number>> => {
|
||||
if (!allPlans) return [];
|
||||
|
||||
return allPlans.filter(p => !p.disabled && p.group_id === customer.group_id).map(p => {
|
||||
|
@ -4,6 +4,7 @@ import Select from 'react-select';
|
||||
import { FabInput } from '../base/fab-input';
|
||||
import { ProofOfIdentityType } from '../../models/proof-of-identity-type';
|
||||
import { Group } from '../../models/group';
|
||||
import { SelectOption } from '../../models/select';
|
||||
|
||||
interface SupportingDocumentsTypeFormProps {
|
||||
groups: Array<Group>,
|
||||
@ -11,12 +12,6 @@ interface SupportingDocumentsTypeFormProps {
|
||||
onChange: (field: string, value: string | Array<number>) => void,
|
||||
}
|
||||
|
||||
/**
|
||||
* Option format, expected by react-select
|
||||
* @see https://github.com/JedWatson/react-select
|
||||
*/
|
||||
type selectOption = { value: number, label: string };
|
||||
|
||||
/**
|
||||
* Form to set create/edit supporting documents type
|
||||
*/
|
||||
@ -26,7 +21,7 @@ export const SupportingDocumentsTypeForm: React.FC<SupportingDocumentsTypeFormPr
|
||||
/**
|
||||
* Convert all groups to the react-select format
|
||||
*/
|
||||
const buildOptions = (): Array<selectOption> => {
|
||||
const buildOptions = (): Array<SelectOption<number>> => {
|
||||
return groups.map(t => {
|
||||
return { value: t.id, label: t.name };
|
||||
});
|
||||
@ -35,7 +30,7 @@ export const SupportingDocumentsTypeForm: React.FC<SupportingDocumentsTypeFormPr
|
||||
/**
|
||||
* Return the group(s) associated with the current type, formatted to match the react-select format
|
||||
*/
|
||||
const groupsValues = (): Array<selectOption> => {
|
||||
const groupsValues = (): Array<SelectOption<number>> => {
|
||||
const res = [];
|
||||
const groupIds = proofOfIdentityType?.group_ids || [];
|
||||
if (groupIds.length > 0) {
|
||||
@ -51,7 +46,7 @@ export const SupportingDocumentsTypeForm: React.FC<SupportingDocumentsTypeFormPr
|
||||
/**
|
||||
* Callback triggered when the selection of group has changed.
|
||||
*/
|
||||
const handleGroupsChange = (selectedOptions: Array<selectOption>): void => {
|
||||
const handleGroupsChange = (selectedOptions: Array<SelectOption<number>>): void => {
|
||||
onChange('group_ids', selectedOptions.map(o => o.value));
|
||||
};
|
||||
|
||||
|
@ -3,6 +3,7 @@ import AsyncSelect from 'react-select/async';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import MemberAPI from '../../api/member';
|
||||
import { User } from '../../models/user';
|
||||
import { SelectOption } from '../../models/select';
|
||||
|
||||
interface MemberSelectProps {
|
||||
defaultUser?: User,
|
||||
@ -12,18 +13,12 @@ interface MemberSelectProps {
|
||||
hasError?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Option format, expected by react-select
|
||||
* @see https://github.com/JedWatson/react-select
|
||||
*/
|
||||
type selectOption = { value: number, label: string };
|
||||
|
||||
/**
|
||||
* This component renders the member select for manager.
|
||||
*/
|
||||
export const MemberSelect: React.FC<MemberSelectProps> = ({ defaultUser, value, onSelected, noHeader, hasError }) => {
|
||||
const { t } = useTranslation('public');
|
||||
const [option, setOption] = useState<selectOption>();
|
||||
const [option, setOption] = useState<SelectOption<number>>();
|
||||
|
||||
useEffect(() => {
|
||||
if (defaultUser) {
|
||||
@ -49,7 +44,7 @@ export const MemberSelect: React.FC<MemberSelectProps> = ({ defaultUser, value,
|
||||
/**
|
||||
* search members by name
|
||||
*/
|
||||
const loadMembers = async (inputValue: string): Promise<Array<selectOption>> => {
|
||||
const loadMembers = async (inputValue: string): Promise<Array<SelectOption<number>>> => {
|
||||
if (!inputValue) {
|
||||
return [];
|
||||
}
|
||||
@ -62,7 +57,7 @@ export const MemberSelect: React.FC<MemberSelectProps> = ({ defaultUser, value,
|
||||
/**
|
||||
* callback for handle select changed
|
||||
*/
|
||||
const onChange = (v: selectOption) => {
|
||||
const onChange = (v: SelectOption<number>) => {
|
||||
setOption(v);
|
||||
onSelected({ id: v.value, name: v.label });
|
||||
};
|
||||
|
@ -30,6 +30,7 @@ import ProfileCustomFieldAPI from '../../api/profile-custom-field';
|
||||
import { ProfileCustomField } from '../../models/profile-custom-field';
|
||||
import { SettingName } from '../../models/setting';
|
||||
import SettingAPI from '../../api/setting';
|
||||
import { SelectOption } from '../../models/select';
|
||||
|
||||
declare const Application: IApplication;
|
||||
|
||||
@ -46,12 +47,6 @@ interface UserProfileFormProps {
|
||||
showTagsInput?: boolean,
|
||||
}
|
||||
|
||||
/**
|
||||
* Option format, expected by react-select
|
||||
* @see https://github.com/JedWatson/react-select
|
||||
*/
|
||||
type selectOption = { value: number, label: string };
|
||||
|
||||
/**
|
||||
* Form component to create or update a user
|
||||
*/
|
||||
@ -67,7 +62,7 @@ export const UserProfileForm: React.FC<UserProfileFormProps> = ({ action, size,
|
||||
|
||||
const [isOrganization, setIsOrganization] = useState<boolean>(!_isNil(user.invoicing_profile_attributes.organization_attributes));
|
||||
const [isLocalDatabaseProvider, setIsLocalDatabaseProvider] = useState<boolean>(false);
|
||||
const [groups, setGroups] = useState<selectOption[]>([]);
|
||||
const [groups, setGroups] = useState<SelectOption<number>[]>([]);
|
||||
const [termsAndConditions, setTermsAndConditions] = useState<CustomAsset>(null);
|
||||
const [profileCustomFields, setProfileCustomFields] = useState<ProfileCustomField[]>([]);
|
||||
const [requiredFieldsSettings, setRequiredFieldsSettings] = useState<Map<SettingName, string>>(new Map());
|
||||
@ -107,7 +102,7 @@ export const UserProfileForm: React.FC<UserProfileFormProps> = ({ action, size,
|
||||
/**
|
||||
* Convert the provided array of items to the react-select format
|
||||
*/
|
||||
const buildOptions = (items: Array<{ id?: number, name: string }>): Array<selectOption> => {
|
||||
const buildOptions = (items: Array<{ id?: number, name: string }>): Array<SelectOption<number>> => {
|
||||
return items.map(t => {
|
||||
return { value: t.id, label: t.name };
|
||||
});
|
||||
@ -116,7 +111,7 @@ export const UserProfileForm: React.FC<UserProfileFormProps> = ({ action, size,
|
||||
/**
|
||||
* Asynchronously load the full list of enabled trainings to display in the drop-down select field
|
||||
*/
|
||||
const loadTrainings = (inputValue: string, callback: (options: Array<selectOption>) => void): void => {
|
||||
const loadTrainings = (inputValue: string, callback: (options: Array<SelectOption<number>>) => void): void => {
|
||||
TrainingAPI.index({ disabled: false }).then(data => {
|
||||
callback(buildOptions(data));
|
||||
}).catch(error => onError(error));
|
||||
@ -125,7 +120,7 @@ export const UserProfileForm: React.FC<UserProfileFormProps> = ({ action, size,
|
||||
/**
|
||||
* Asynchronously load the full list of tags to display in the drop-down select field
|
||||
*/
|
||||
const loadTags = (inputValue: string, callback: (options: Array<selectOption>) => void): void => {
|
||||
const loadTags = (inputValue: string, callback: (options: Array<SelectOption<number>>) => void): void => {
|
||||
TagAPI.index().then(data => {
|
||||
callback(buildOptions(data));
|
||||
}).catch(error => onError(error));
|
||||
|
@ -80,10 +80,6 @@ export default class ProductLib {
|
||||
let list = [...currentSelection];
|
||||
const children = allCategories
|
||||
.filter(el => el.parent_id === category.id);
|
||||
/*
|
||||
const siblings = allCategories
|
||||
.filter(el => el.parent_id === category.parent_id && el.parent_id !== null);
|
||||
*/
|
||||
|
||||
if (operation === 'add') {
|
||||
list.push(category);
|
||||
@ -91,12 +87,6 @@ export default class ProductLib {
|
||||
// if a parent category is selected, we automatically select all its children
|
||||
list = [...Array.from(new Set([...list, ...children]))];
|
||||
}
|
||||
/*
|
||||
if (siblings.length && siblings.every(el => list.includes(el))) {
|
||||
// if a child category is selected, with every sibling of it, we automatically select its parent
|
||||
list.push(allCategories.find(p => p.id === siblings[0].parent_id));
|
||||
}
|
||||
*/
|
||||
} else {
|
||||
list.splice(list.indexOf(category), 1);
|
||||
const parent = allCategories.find(p => p.id === category.parent_id);
|
||||
|
10
app/frontend/src/javascript/models/select.ts
Normal file
10
app/frontend/src/javascript/models/select.ts
Normal file
@ -0,0 +1,10 @@
|
||||
/**
|
||||
* Option format, expected by react-select
|
||||
* @see https://github.com/JedWatson/react-select
|
||||
*/
|
||||
export type SelectOption<TOptionValue, TOptionLabel = string> = { value: TOptionValue, label: TOptionLabel }
|
||||
|
||||
/**
|
||||
* Checklist Option format
|
||||
*/
|
||||
export type ChecklistOption<TOptionValue> = { value: TOptionValue, label: string };
|
Loading…
Reference in New Issue
Block a user