feat: Refactor car color and body selection with type-safe enums

- Updated Car.Color to use TypeScript enum for better type safety
- Modified car color and body selection components to use new enum types
- Updated order view and stub data to support enum-based color representation
- Exported color and body select options from respective components
- Improved localization handling for car color and body selections
This commit is contained in:
RustamRu 2025-03-12 01:18:58 +03:00
parent b87d012e34
commit a18a26fcaf
10 changed files with 61 additions and 29 deletions

View File

@ -1 +1,2 @@
export { CarBodySelect } from './car-body-select';
export { CarBodySelect } from './car-body-select';
export { carBodySelectOptions } from './helper';

View File

@ -2,7 +2,9 @@ import React, { forwardRef, useState } from 'react';
import { Input, Box, Stack, Text, Flex } from '@chakra-ui/react';
import { useTranslation } from 'react-i18next';
import { CAR_COLORS } from './helper';
import { Car } from '../../../../models';
import { carColorSelectOptions } from './helper';
interface CarColorSelectProps {
value?: string;
@ -16,7 +18,7 @@ export const CarColorSelect = forwardRef<HTMLInputElement, CarColorSelectProps>(
const [customColor, setCustomColor] = useState('');
const [isCustom, setIsCustom] = useState(false);
const handleColorChange = (value: string) => {
const handleColorChange = (value: Car.Color | string) => {
if (value === 'custom') {
setIsCustom(true);
return;
@ -46,13 +48,13 @@ export const CarColorSelect = forwardRef<HTMLInputElement, CarColorSelectProps>(
return (
<Stack spacing={4} width='100%' ref={ref}>
<Flex gap={2} wrap='wrap' pb={2}>
{CAR_COLORS.map(({ name, code }) => (
{carColorSelectOptions.map(({ value, labelTKey, code }) => (
<Box
key={name}
key={value}
flexShrink={0}
as='button'
type='button'
onClick={() => handleColorChange(name)}
onClick={() => handleColorChange(value)}
>
<Flex
align='center'
@ -68,7 +70,7 @@ export const CarColorSelect = forwardRef<HTMLInputElement, CarColorSelectProps>(
}}
justify='center'
transition='all 0.2s'
{...(currentValue === name && {
{...(currentValue === value && {
borderColor: 'primary.500',
bg: 'primary.50',
paddingInlineEnd: 3,
@ -87,14 +89,14 @@ export const CarColorSelect = forwardRef<HTMLInputElement, CarColorSelectProps>(
borderColor='gray.200'
transition='all 0.2s'
boxShadow='none'
{...(currentValue === name && {
{...(currentValue === value && {
borderColor: 'primary.500',
boxShadow: 'sm',
})}
/>
{currentValue === name && (
{currentValue === value && (
<Text fontSize='xs' color='primary.700' fontWeight='medium'>
{t(`colors.${name}`)}
{t(`colors.${labelTKey}`)}
</Text>
)}
</Flex>

View File

@ -1,34 +1,44 @@
export const CAR_COLORS = [
import { Car } from "../../../../models";
export const carColorSelectOptions: { value: Car.Color | string; labelTKey: 'white' | 'black' | 'silver' | 'gray' | 'beige-brown' | 'red' | 'blue' | 'green'; code: string }[] = [
{
name: 'white',
value: Car.Color.WHITE,
labelTKey: 'white',
code: '#ffffff'
},
{
name: 'black',
value: Car.Color.BLACK,
labelTKey: 'black',
code: '#000000'
},
{
name: 'silver',
value: Car.Color.SILVER,
labelTKey: 'silver',
code: '#c0c0c0'
},
{
name: 'gray',
value: Car.Color.GRAY,
labelTKey: 'gray',
code: '#808080'
},
{
name: 'beige-brown',
value: Car.Color.BEIGE_BROWN,
labelTKey: 'beige-brown',
code: '#796745'
},
{
name: 'red',
value: Car.Color.RED,
labelTKey: 'red',
code: '#b90000'
},
{
name: 'blue',
value: Car.Color.BLUE,
labelTKey: 'blue',
code: '#003B62'
},
{
name: 'green',
value: Car.Color.GREEN,
labelTKey: 'green',
code: '#078d51'
},
] as const satisfies { name: string; code: string }[];
];

View File

@ -1 +1,2 @@
export { CarColorSelect } from './car-color-select';
export { CarColorSelect } from './car-color-select';
export { carColorSelectOptions } from './helper';

View File

@ -1,2 +1,4 @@
export type { OrderFormValues, OrderFormProps } from './types';
export { OrderForm } from './order-form';
export { OrderForm } from './order-form';
export { carBodySelectOptions } from './car-body';
export { carColorSelectOptions } from './car-color';

View File

@ -17,7 +17,10 @@ import 'dayjs/locale/en';
import { Order } from '../../../models/landing';
import { formatDatetime } from '../../../lib';
import { carBodySelectOptions } from '../../order-form/form/car-body/helper';
import {
carBodySelectOptions,
carColorSelectOptions,
} from '../../order-form';
import { OrderStatus } from './status';
@ -54,6 +57,10 @@ export const OrderDetails: FC<OrderDetailsProps> = ({
const { t: tCarBody } = useTranslation('~', {
keyPrefix: 'dry-wash.order-create.car-body-select.options',
});
const { t: tCarColor } = useTranslation('~', {
keyPrefix: 'dry-wash.order-create.car-color-select.colors',
});
const carColorTKey = carColorSelectOptions.find(({ value }) => value === carColor)?.labelTKey;
return (
<>
@ -82,7 +89,7 @@ export const OrderDetails: FC<OrderDetailsProps> = ({
tCarBody(
`${carBodySelectOptions.find(({ value }) => value === carBody)?.labelTKey}`,
),
carColor,
carColorTKey ? tCarColor(carColorTKey) : carColor,
]
.filter((v) => v)
.join(', '),

View File

@ -1,6 +1,15 @@
export type RegistrationNumber = string; // А012ВЕ16
export type Color = string; // #000000
export const enum Color {
WHITE,
BLACK,
SILVER,
GRAY,
BEIGE_BROWN,
RED,
BLUE,
GREEN,
}
export const enum BodyStyle {
UNKNOWN = 0,

View File

@ -18,7 +18,7 @@ export type Create = {
car: {
number: Car.RegistrationNumber;
body: Car.BodyStyle;
color: Car.Color;
color: Car.Color | string;
};
washing: {
location: Washing.Location;
@ -33,7 +33,7 @@ export type View = {
phone: Customer.PhoneNumber;
carNumber: Car.RegistrationNumber;
carBody: Car.BodyStyle;
carColor?: Car.Color;
carColor?: Car.Color | string;
location: Washing.Location;
startWashTime: Washing.AvailableBeginDateTime;
endWashTime: Washing.AvailableEndDateTime;

View File

@ -4,7 +4,7 @@
"phone": "+79876543210",
"carNumber": "А123АА16",
"carBody": 2,
"carColor": "#ffffff",
"carColor": 5,
"startWashTime": "2025-01-19T14:03:00.000Z",
"endWashTime": "2025-01-19T14:03:00.000Z",
"location": "55.793833888711006,49.19037910644527 Республика Татарстан (Татарстан), Казань, жилой район Седьмое Небо",

View File

@ -4,7 +4,7 @@
"phone": "+79876543210",
"carNumber": "А123АА16",
"carBody": 2,
"carColor": "#ffffff",
"carColor": "мокрый асфальт",
"startWashTime": "2025-01-19T14:03:00.000Z",
"endWashTime": "2025-01-19T14:03:00.000Z",
"location": "55.793833888711006,49.19037910644527 Республика Татарстан (Татарстан), Казань, жилой район Седьмое Небо",