Skip to content

Commit

Permalink
Feat: Currency selector (#2739)
Browse files Browse the repository at this point in the history
  • Loading branch information
tuul-wq authored Nov 28, 2024
1 parent c5119f8 commit 56d134e
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 41 deletions.
70 changes: 33 additions & 37 deletions src/renderer/features/currency/CurrencyForm/ui/CurrencyForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,18 @@ import { type FormEvent, useEffect } from 'react';

import { type CurrencyItem } from '@/shared/api/price-provider';
import { useI18n } from '@/shared/i18n';
import { Button, FootnoteText, HelpText, Select, Switch } from '@/shared/ui';
import { type DropdownOption } from '@/shared/ui/types';
import { nonNullable } from '@/shared/lib/utils';
import { Button, FootnoteText, HelpText, Switch } from '@/shared/ui';
import { Select } from '@/shared/ui-kit';
import { type Callbacks, currencyFormModel } from '../model/currency-form';

const getCurrencyOption = (currency: CurrencyItem): DropdownOption<CurrencyItem> => ({
id: currency.id.toString(),
value: currency,
element: [currency.code, currency.symbol, currency.name].filter(Boolean).join(' • '),
});
const getCurrencyTitle = (currency: CurrencyItem): string => {
return [currency.code, currency.symbol, currency.name].filter(nonNullable).join(' • ');
};

type Props = Callbacks;
export const CurrencyForm = ({ onSubmit }: Props) => {
const { t } = useI18n();
const isFormValid = useUnit(currencyFormModel.$isFormValid);

useEffect(() => {
currencyFormModel.events.callbacksChanged({ onSubmit });
Expand All @@ -32,34 +30,11 @@ export const CurrencyForm = ({ onSubmit }: Props) => {
fields: { fiatFlag, currency },
} = useForm(currencyFormModel.$currencyForm);

const isFormValid = useUnit(currencyFormModel.$isFormValid);
const cryptoCurrencies = useUnit(currencyFormModel.$cryptoCurrencies);
const popularFiatCurrencies = useUnit(currencyFormModel.$popularFiatCurrencies);
const unpopularFiatCurrencies = useUnit(currencyFormModel.$unpopularFiatCurrencies);

const currenciesOptions: DropdownOption<CurrencyItem>[] = [
{
id: 'crypto',
element: <HelpText className="text-text-secondary">{t('settings.currency.cryptocurrenciesLabel')}</HelpText>,
value: {} as CurrencyItem,
disabled: true,
},
...cryptoCurrencies.map(getCurrencyOption),
{
id: 'popular',
element: <HelpText className="text-text-secondary">{t('settings.currency.popularFiatLabel')}</HelpText>,
value: {} as CurrencyItem,
disabled: true,
},
...popularFiatCurrencies.map(getCurrencyOption),
{
id: 'unpopular',
element: <HelpText className="text-text-secondary">{t('settings.currency.unpopularFiatLabel')}</HelpText>,
value: {} as CurrencyItem,
disabled: true,
},
...unpopularFiatCurrencies.map(getCurrencyOption),
];

const submitForm = (event: FormEvent) => {
event.preventDefault();
submit();
Expand All @@ -76,11 +51,32 @@ export const CurrencyForm = ({ onSubmit }: Props) => {

<Select
placeholder={t('settings.currency.selectPlaceholder')}
disabled={!fiatFlag?.value}
options={currenciesOptions}
selectedId={currency?.value.toString()}
onChange={({ value }) => currency?.onChange(value.id)}
/>
disabled={!fiatFlag.value}
value={currency.value.toString()}
onChange={(value) => currency.onChange(Number(value))}
>
<Select.Group title={t('settings.currency.cryptocurrenciesLabel')}>
{cryptoCurrencies.map((currency) => (
<Select.Item key={currency.id} value={currency.id.toString()}>
{getCurrencyTitle(currency)}
</Select.Item>
))}
</Select.Group>
<Select.Group title={t('settings.currency.popularFiatLabel')}>
{popularFiatCurrencies.map((currency) => (
<Select.Item key={currency.id} value={currency.id.toString()}>
{getCurrencyTitle(currency)}
</Select.Item>
))}
</Select.Group>
<Select.Group title={t('settings.currency.unpopularFiatLabel')}>
{unpopularFiatCurrencies.map((currency) => (
<Select.Item key={currency.id} value={currency.id.toString()}>
{getCurrencyTitle(currency)}
</Select.Item>
))}
</Select.Group>
</Select>

<Button className="ml-auto w-fit" type="submit" disabled={!isFormValid}>
{t('settings.currency.save')}
Expand Down
24 changes: 21 additions & 3 deletions src/renderer/shared/ui-kit/Select/Select.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@ import { Select } from './Select';
const meta: Meta<typeof Select> = {
title: 'Design System/kit/Select',
component: Select,
parameters: {
layout: 'centered',
},
render: (params) => {
const [value, onChange] = useState('');

Expand Down Expand Up @@ -83,6 +80,27 @@ export const Disabled: Story = {
},
};

export const Groups: Story = {
render: (params) => {
const [value, onChange] = useState('');

return (
<Box width="200px">
<Select {...params} placeholder="Select a fruit" value={value} onChange={onChange}>
<Select.Group title="Group 1">
<Select.Item value="item_1">Apple</Select.Item>
<Select.Item value="item_2">Orange</Select.Item>
</Select.Group>
<Select.Group title="Group 2">
<Select.Item value="item_3">Watermelon</Select.Item>
<Select.Item value="item_4">Banana</Select.Item>
</Select.Group>
</Select>
</Box>
);
},
};

export const Dark: Story = {
decorators: [
(Story, { args }) => {
Expand Down
19 changes: 18 additions & 1 deletion src/renderer/shared/ui-kit/Select/Select.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as RadixSelect from '@radix-ui/react-select';
import { type PropsWithChildren, createContext, useContext, useMemo } from 'react';
import { Children, type PropsWithChildren, type ReactNode, createContext, useContext, useMemo } from 'react';

import { type XOR } from '@/shared/core';
import { cnTw } from '@/shared/lib/utils';
Expand Down Expand Up @@ -130,6 +130,22 @@ const Content = ({ children }: PropsWithChildren) => {
);
};

type GroupProps = {
title: ReactNode;
};
const Group = ({ title, children }: PropsWithChildren<GroupProps>) => {
if (Children.count(children) === 0) return null;

return (
<RadixSelect.Group className="mb-1 last:mb-0">
<RadixSelect.Label>
<div className="mb-1 px-3 py-1 text-help-text text-text-secondary">{title}</div>
</RadixSelect.Label>
{children}
</RadixSelect.Group>
);
};

type ItemProps = {
value: string;
};
Expand All @@ -156,5 +172,6 @@ const Item = ({ value, children }: PropsWithChildren<ItemProps>) => {
};

export const Select = Object.assign(Root, {
Group,
Item,
});

0 comments on commit 56d134e

Please sign in to comment.