Skip to content

Commit 8f481e0

Browse files
committed
Improve Color Set tab UI
1 parent 994f294 commit 8f481e0

File tree

5 files changed

+79
-50
lines changed

5 files changed

+79
-50
lines changed

src/components/ColorSetChooser.tsx

+61-38
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import {
2020
AppstoreAddOutlined,
21+
CopyOutlined,
2122
DeleteOutlined,
2223
LoadingOutlined,
2324
QrcodeOutlined,
@@ -39,7 +40,6 @@ import {
3940
Row,
4041
Space,
4142
Spin,
42-
Tooltip,
4343
Typography,
4444
} from 'antd';
4545
import {QRCodeSVG} from 'qrcode.react';
@@ -59,11 +59,12 @@ import {useColors} from '~/src/hooks/useColors';
5959
import {useStandardColorSets} from '~/src/hooks/useStandardColorSets';
6060
import {hasAccessTo} from '~/src/services/auth/utils';
6161
import {MAX_COLORS_IN_MIXTURE} from '~/src/services/color/color-mixer';
62-
import {COLOR_TYPES} from '~/src/services/color/colors';
62+
import {COLOR_TYPES, compareByDate} from '~/src/services/color/colors';
6363
import type {ColorBrandDefinition, ColorSetDefinition, ColorType} from '~/src/services/color/types';
6464
import {colorSetToUrl} from '~/src/services/url/url-parser';
6565
import {useAppStore} from '~/src/stores/app-store';
6666
import {TabKey} from '~/src/tabs';
67+
import {reverseOrder} from '~/src/utils/array';
6768

6869
import {ColorBrandSelect} from './color-set/ColorBrandSelect';
6970
import {ColorSelect} from './color-set/ColorSelect';
@@ -226,15 +227,17 @@ export const ColorSetChooser = forwardRef<ChangableComponent, Props>(function Co
226227
});
227228
if (confirmed) {
228229
const {id, ...colorSet} = form.getFieldsValue();
229-
await saveColorSet(
230-
user,
231-
{
232-
...colorSet,
233-
...(id ? {id} : {}),
234-
},
235-
brands,
236-
colors,
237-
false
230+
form.setFieldsValue(
231+
await saveColorSet(
232+
user,
233+
{
234+
...colorSet,
235+
...(id ? {id} : {}),
236+
},
237+
brands,
238+
colors,
239+
false
240+
)
238241
);
239242
}
240243
setHasUnsavedChanges(false);
@@ -349,6 +352,7 @@ export const ColorSetChooser = forwardRef<ChangableComponent, Props>(function Co
349352
};
350353

351354
const handleSubmit = async (values: ColorSetDefinition) => {
355+
setHasUnsavedChanges(false);
352356
const {id, ...colorSet} = values;
353357
form.setFieldsValue(
354358
await saveColorSet(
@@ -361,13 +365,22 @@ export const ColorSetChooser = forwardRef<ChangableComponent, Props>(function Co
361365
colors
362366
)
363367
);
364-
setHasUnsavedChanges(false);
365368
};
366369

367370
const handleSubmitFailed = () => {
368371
void message.error('Fill in the required fields');
369372
};
370373

374+
const handleDuplicateButtonClick = () => {
375+
const {id: _id, name: _name, ...colorSet} = form.getFieldsValue();
376+
form.setFieldsValue({
377+
id: NEW_COLOR_SET,
378+
name: undefined,
379+
...colorSet,
380+
});
381+
setHasUnsavedChanges(true);
382+
};
383+
371384
const handleDeleteButtonClick = async () => {
372385
setHasUnsavedChanges(true);
373386
if (selectedColorSetId) {
@@ -376,7 +389,9 @@ export const ColorSetChooser = forwardRef<ChangableComponent, Props>(function Co
376389
type: selectedType,
377390
};
378391
if (selectedType) {
379-
const [latestColorSetsByType] = await loadColorSetsByType(selectedType);
392+
const [latestColorSetsByType] = (await loadColorSetsByType(selectedType)).sort(
393+
reverseOrder(compareByDate)
394+
);
380395
values = latestColorSetsByType ?? values;
381396
}
382397
form.resetFields();
@@ -633,16 +648,15 @@ export const ColorSetChooser = forwardRef<ChangableComponent, Props>(function Co
633648
<Space wrap>
634649
{!isAuthLoading &&
635650
(isAccessAllowed ? (
636-
<Tooltip title="Save the changes to the color set" trigger="focus">
637-
<Button
638-
ref={saveButtonRef}
639-
icon={<SaveOutlined />}
640-
type="primary"
641-
htmlType="submit"
642-
>
643-
Save & proceed
644-
</Button>
645-
</Tooltip>
651+
<Button
652+
ref={saveButtonRef}
653+
icon={<SaveOutlined />}
654+
title="Save the changes to this color set"
655+
type="primary"
656+
htmlType="submit"
657+
>
658+
Save & proceed
659+
</Button>
646660
) : (
647661
<>
648662
<LoginButton />
@@ -659,25 +673,34 @@ export const ColorSetChooser = forwardRef<ChangableComponent, Props>(function Co
659673
</Button>
660674
)}
661675
{!!selectedColorSetId && (
662-
<Popconfirm
663-
title="Delete the color set"
664-
description="Are you sure you want to delete this color set?"
665-
onConfirm={() => {
666-
void handleDeleteButtonClick();
667-
}}
668-
okText="Yes"
669-
cancelText="No"
670-
>
676+
<>
671677
<Button
672-
icon={<DeleteOutlined />}
678+
icon={<CopyOutlined />}
679+
title="Create a duplicate of this color set for further modification"
680+
onClick={handleDuplicateButtonClick}
681+
>
682+
Duplicate
683+
</Button>
684+
<Popconfirm
673685
title="Delete the color set"
674-
onClick={e => {
675-
e.stopPropagation();
686+
description="Are you sure you want to delete this color set?"
687+
onConfirm={() => {
688+
void handleDeleteButtonClick();
676689
}}
690+
okText="Yes"
691+
cancelText="No"
677692
>
678-
Delete
679-
</Button>
680-
</Popconfirm>
693+
<Button
694+
icon={<DeleteOutlined />}
695+
title="Delete this color set"
696+
onClick={e => {
697+
e.stopPropagation();
698+
}}
699+
>
700+
Delete
701+
</Button>
702+
</Popconfirm>
703+
</>
681704
)}
682705
</Space>
683706
</Form.Item>

src/components/color-set/ColorCascader.tsx

+7-4
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,11 @@
1616
* along with this program. If not, see <http://www.gnu.org/licenses/>.
1717
*/
1818

19-
import {Cascader, Space, Typography} from 'antd';
19+
import {Cascader, Flex, Typography} from 'antd';
2020
import type {CascaderAutoProps, DefaultOptionType as CascaderOptionType} from 'antd/es/cascader';
2121

2222
import {ColorSquare} from '~/src/components/color/ColorSquare';
23+
import {OpacityIcon} from '~/src/components/color/OpacityIcon';
2324
import {filterCascaderOptions} from '~/src/components/utils';
2425
import {formatColorLabel} from '~/src/services/color/colors';
2526
import type {Color, ColorSet} from '~/src/services/color/types';
@@ -47,14 +48,16 @@ function getColorOptions(colorSet?: ColorSet | null): CascaderOptionType[] {
4748
value: brandId,
4849
label: brand.fullName,
4950
children: [...colors.values()].map((color: Color) => {
51+
const {rgb, opacity} = color;
5052
const label: string = formatColorLabel(color, brand);
5153
return {
5254
value: color.id,
5355
label: (
54-
<Space align="center" key={label}>
55-
<ColorSquare color={color.rgb} />
56+
<Flex key={label} gap="small" align="center">
57+
<ColorSquare color={rgb} />
5658
<Typography.Text>{label}</Typography.Text>
57-
</Space>
59+
<OpacityIcon opacity={opacity} />
60+
</Flex>
5861
),
5962
};
6063
}),

src/components/color-set/ColorSelect.tsx

+7-4
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,11 @@
1717
*/
1818

1919
import type {SelectProps} from 'antd';
20-
import {Select, Space, Typography} from 'antd';
20+
import {Flex, Select, Typography} from 'antd';
2121
import type {DefaultOptionType as SelectOptionType} from 'antd/es/select';
2222

2323
import {ColorSquare} from '~/src/components/color/ColorSquare';
24+
import {OpacityIcon} from '~/src/components/color/OpacityIcon';
2425
import {filterSelectOptions} from '~/src/components/utils';
2526
import {formatColorLabel} from '~/src/services/color/colors';
2627
import type {ColorBrandDefinition, ColorDefinition} from '~/src/services/color/types';
@@ -33,14 +34,16 @@ function getColorOptions(
3334
return [];
3435
}
3536
return [...colors.values()].map((color: ColorDefinition) => {
37+
const {hex, opacity} = color;
3638
const label: string = formatColorLabel(color, brand);
3739
return {
3840
value: color.id,
3941
label: (
40-
<Space align="center" key={label}>
41-
<ColorSquare color={color.hex} />
42+
<Flex key={label} gap="small" align="center">
43+
<ColorSquare color={hex} />
4244
<Typography.Text>{label}</Typography.Text>
43-
</Space>
45+
<OpacityIcon opacity={opacity} />
46+
</Flex>
4447
),
4548
};
4649
});

src/components/color-set/ColorSetSelect.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import type {DefaultOptionType as SelectOptionType} from 'antd/es/select';
2424
import {filterSelectOptions} from '~/src/components/utils';
2525
import {compareByDate, getColorSetName} from '~/src/services/color/colors';
2626
import type {ColorBrandDefinition, ColorSetDefinition} from '~/src/services/color/types';
27+
import {reverseOrder} from '~/src/utils/array';
2728

2829
const newColorSetOption: SelectOptionType = {
2930
value: 0,
@@ -45,8 +46,7 @@ function getColorSetOptions(
4546
newColorSetOption,
4647
...colorSets
4748
.slice()
48-
.sort(compareByDate)
49-
.reverse()
49+
.sort(reverseOrder(compareByDate))
5050
.map(({id, name, brands: brandIds, colors}: ColorSetDefinition) => ({
5151
value: id,
5252
label: name || getColorSetName(brandIds, colors, brands),

src/components/color-set/CustomColorBrandSelect.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import type {DefaultOptionType as SelectOptionType} from 'antd/es/select';
2424
import {filterSelectOptions} from '~/src/components/utils';
2525
import {compareByDate} from '~/src/services/color/colors';
2626
import type {CustomColorBrandDefinition} from '~/src/services/color/types';
27+
import {reverseOrder} from '~/src/utils/array';
2728

2829
const newCustomColorBrandOption: SelectOptionType = {
2930
value: 0,
@@ -44,8 +45,7 @@ function getCustomColorBrandOptions(
4445
newCustomColorBrandOption,
4546
...customColorBrands
4647
.slice()
47-
.sort(compareByDate)
48-
.reverse()
48+
.sort(reverseOrder(compareByDate))
4949
.map(({id, name}: CustomColorBrandDefinition) => ({
5050
value: id,
5151
label: name,

0 commit comments

Comments
 (0)