fix: rating type issues (#3638)
* fix: rating type issues * fix: rebase --------- Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
@ -28,6 +28,7 @@ export const useMapFieldMetadataToGraphQLQuery = () => {
|
||||
'EMAIL',
|
||||
'NUMBER',
|
||||
'BOOLEAN',
|
||||
'RATING',
|
||||
'SELECT',
|
||||
] as FieldType[]
|
||||
).includes(fieldType);
|
||||
|
||||
@ -23,7 +23,7 @@ export const useRatingField = () => {
|
||||
}),
|
||||
);
|
||||
|
||||
const rating = +(fieldValue ?? 0);
|
||||
const rating = fieldValue ?? 'RATING_1';
|
||||
|
||||
return {
|
||||
fieldDefinition,
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { FieldRatingValue } from '@/object-record/record-field/types/FieldMetadata';
|
||||
import { RatingInput } from '@/ui/field/input/components/RatingInput';
|
||||
|
||||
import { usePersistField } from '../../../hooks/usePersistField';
|
||||
@ -10,6 +11,14 @@ export type RatingFieldInputProps = {
|
||||
readonly?: boolean;
|
||||
};
|
||||
|
||||
export const RATING_VALUES = [
|
||||
'RATING_1',
|
||||
'RATING_2',
|
||||
'RATING_3',
|
||||
'RATING_4',
|
||||
'RATING_5',
|
||||
] as const;
|
||||
|
||||
export const RatingFieldInput = ({
|
||||
onSubmit,
|
||||
readonly,
|
||||
@ -18,8 +27,8 @@ export const RatingFieldInput = ({
|
||||
|
||||
const persistField = usePersistField();
|
||||
|
||||
const handleChange = (newRating: number) => {
|
||||
onSubmit?.(() => persistField(`${newRating}`));
|
||||
const handleChange = (newRating: FieldRatingValue) => {
|
||||
onSubmit?.(() => persistField(newRating));
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { RATING_VALUES } from '@/object-record/record-field/meta-types/input/components/RatingFieldInput';
|
||||
import { EntityForSelect } from '@/object-record/relation-picker/types/EntityForSelect';
|
||||
import { ThemeColor } from '@/ui/theme/constants/colors';
|
||||
|
||||
@ -119,7 +120,7 @@ export type FieldCurrencyValue = {
|
||||
amountMicros: number | null;
|
||||
};
|
||||
export type FieldFullNameValue = { firstName: string; lastName: string };
|
||||
export type FieldRatingValue = '1' | '2' | '3' | '4' | '5';
|
||||
export type FieldRatingValue = (typeof RATING_VALUES)[number];
|
||||
export type FieldSelectValue = string | null;
|
||||
|
||||
export type FieldRelationValue = EntityForSelect | null;
|
||||
|
||||
@ -1,11 +1,9 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { RATING_VALUES } from '../../meta-types/input/components/RatingFieldInput';
|
||||
import { FieldRatingValue } from '../FieldMetadata';
|
||||
|
||||
const ratingSchema = z
|
||||
.string()
|
||||
.transform((value) => +value)
|
||||
.pipe(z.number().int().min(1).max(5));
|
||||
const ratingSchema = z.string().pipe(z.enum(RATING_VALUES));
|
||||
|
||||
export const isFieldRatingValue = (
|
||||
fieldValue: unknown,
|
||||
|
||||
@ -2,6 +2,8 @@ import { useState } from 'react';
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { RATING_VALUES } from '@/object-record/record-field/meta-types/input/components/RatingFieldInput';
|
||||
import { FieldRatingValue } from '@/object-record/record-field/types/FieldMetadata';
|
||||
import { IconTwentyStarFilled } from '@/ui/display/icon/components/IconTwentyStarFilled';
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
@ -16,40 +18,40 @@ const StyledRatingIconContainer = styled.div<{ isActive?: boolean }>`
|
||||
`;
|
||||
|
||||
type RatingInputProps = {
|
||||
onChange: (newValue: number) => void;
|
||||
value: number;
|
||||
onChange: (newValue: FieldRatingValue) => void;
|
||||
value: FieldRatingValue;
|
||||
readonly?: boolean;
|
||||
};
|
||||
|
||||
const RATING_LEVELS_NB = 5;
|
||||
|
||||
export const RatingInput = ({
|
||||
onChange,
|
||||
value,
|
||||
readonly,
|
||||
}: RatingInputProps) => {
|
||||
const theme = useTheme();
|
||||
const [hoveredValue, setHoveredValue] = useState<number | null>(null);
|
||||
const [hoveredValue, setHoveredValue] = useState<FieldRatingValue | null>(
|
||||
null,
|
||||
);
|
||||
const currentValue = hoveredValue ?? value;
|
||||
|
||||
return (
|
||||
<StyledContainer
|
||||
role="slider"
|
||||
aria-label="Rating"
|
||||
aria-valuemax={RATING_LEVELS_NB}
|
||||
aria-valuemax={RATING_VALUES.length}
|
||||
aria-valuemin={1}
|
||||
aria-valuenow={value}
|
||||
aria-valuenow={RATING_VALUES.indexOf(currentValue) + 1}
|
||||
tabIndex={0}
|
||||
>
|
||||
{Array.from({ length: RATING_LEVELS_NB }, (_, index) => {
|
||||
const rating = index + 1;
|
||||
{RATING_VALUES.map((value, index) => {
|
||||
const currentIndex = RATING_VALUES.indexOf(currentValue);
|
||||
|
||||
return (
|
||||
<StyledRatingIconContainer
|
||||
key={index}
|
||||
isActive={rating <= currentValue}
|
||||
onClick={readonly ? undefined : () => onChange(rating)}
|
||||
onMouseEnter={readonly ? undefined : () => setHoveredValue(rating)}
|
||||
isActive={index <= currentIndex}
|
||||
onClick={readonly ? undefined : () => onChange(value)}
|
||||
onMouseEnter={readonly ? undefined : () => setHoveredValue(value)}
|
||||
onMouseLeave={readonly ? undefined : () => setHoveredValue(null)}
|
||||
>
|
||||
<IconTwentyStarFilled size={theme.icon.size.md} />
|
||||
|
||||
Reference in New Issue
Block a user