Skip to content

Commit

Permalink
Merge pull request #176 from ZeroGachis/task/sdet-223-appliquer-les-s…
Browse files Browse the repository at this point in the history
…tyles-derreur-quand-il-faut

Task/sdet 223 appliquer les styles derreur quand il faut
  • Loading branch information
AdrienCasta authored Jan 30, 2024
2 parents 9640c7e + 9604d03 commit feb686d
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 115 deletions.
31 changes: 9 additions & 22 deletions Storybook/components/DateSelector/DateSelector.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,27 @@
import React from 'react';
import { DateSelector } from '../../../src/components/dateSelector/DateSelector';
import { DateSelector } from '../../../src';
import type { ComponentMeta, ComponentStory } from '@storybook/react-native';
import { StyleSheet, View } from 'react-native';
import { action } from '@storybook/addon-actions';
import { View } from 'react-native';

export default {
title: 'components/DateSelector',
component: DateSelector,
argTypes: {
prefilled: { control: { type: 'date' } },
errorMessage: { control: { type: 'text' } },
},
args: {
prefilled: new Date(2023, 0, 8),
onUpdatedDate: (date: Date) => {
action('onChange')(date.toDateString());
},
errorMessage: undefined,
},
decorators: [
(Story) => {
const styles = StyleSheet.create({
container: { paddingTop: 16 },
});
return (
<View style={styles.container}>
<View style={{ paddingTop: 16 }}>
<Story />
</View>
);
Expand All @@ -28,20 +30,5 @@ export default {
} as ComponentMeta<typeof DateSelector>;

export const Base: ComponentStory<typeof DateSelector> = (args) => {
const handleChange = (date: Date) => {
action('onChange')(date.toDateString());
};
return <DateSelector {...args} onChange={handleChange} />;
};
export const WithErrorMessage: ComponentStory<typeof DateSelector> = (args) => {
const handleChange = (date: Date) => {
action('onChange')(date.toDateString());
};
return (
<DateSelector
{...args}
onChange={handleChange}
errorMessage='Date non valide. Veuillez respecter le format attendu (JJ/MM/AA). '
/>
);
return <DateSelector {...args} />;
};
4 changes: 2 additions & 2 deletions src/__tests__/components/DateSelector.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ beforeEach(() => {
tree = render(
<DateSelector
prefilled={new Date(2003, 1, 1)}
onChange={mockOnChange}
onUpdatedDate={mockOnChange}
testID={mockedTestID}
/>,
);
Expand Down Expand Up @@ -73,7 +73,7 @@ describe('MODULE | DateField', () => {
tree.rerender(
<DateSelector
prefilled={new Date(2003, 1, 1)}
onChange={mockOnChange}
onUpdatedDate={mockOnChange}
testID={mockedTestID}
errorMessage='an error'
/>,
Expand Down
191 changes: 104 additions & 87 deletions src/components/dateSelector/DateField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,90 +8,15 @@ import {
import { TextInput } from 'react-native';
import { Theme, useTheme } from '../../styles/themes';

type State =
| 'readonly'
| 'filled'
| 'empty'
| 'filled-focused'
| 'empty-focused'
| 'error';

export interface DateFieldProps extends TextInputProps {
hasError?: boolean;
}

function getColorsStyle(theme: Theme, state: State) {
let backgroundColor, borderColor, textColor;

switch (state) {
case 'filled-focused':
textColor = theme.sw.colors.neutral[800];
backgroundColor = theme.sw.colors.neutral[50];
borderColor = theme.sw.colors.primary.main;
break;
case 'empty-focused':
textColor = theme.sw.colors.primary.main;
borderColor = theme.sw.colors.primary.main;
backgroundColor =
theme.sw.colors.primary.main + theme.sw.transparency[16];
break;
case 'filled':
textColor = theme.sw.colors.neutral[800];
backgroundColor =
theme.sw.colors.neutral[500] + theme.sw.transparency[8];
break;
case 'error':
textColor = theme.sw.colors.error.main;
backgroundColor =
theme.sw.colors.error.main + theme.sw.transparency[8];
break;
default:
textColor = theme.sw.colors.neutral[500];
backgroundColor =
theme.sw.colors.neutral[500] + theme.sw.transparency[8];
break;
}
return { backgroundColor, borderColor, textColor };
}

function getStyle(theme: Theme, state: State) {
const { backgroundColor, borderColor, textColor } = getColorsStyle(
theme,
state,
);

const style = StyleSheet.create({
main: {
borderRadius: 18,
height: 48,
borderWidth: borderColor !== undefined ? 1 : 0,
borderColor: borderColor,
width: 72,
color: textColor,
fontFamily: 'PublicSans-Bold',
fontSize: 20,
lineHeight: 23.5,
backgroundColor: backgroundColor,
paddingVertical: 0,
marginVertical: 0,
},
placeholder: {
color:
state === 'empty-focused'
? theme.sw.colors.primary.main
: theme.sw.colors.neutral[500],
},
});
return style;
}

export const DateField = forwardRef<TextInput, DateFieldProps>(
({ value = '', hasError, ...props }, ref) => {
const theme = useTheme();
const [isFocused, setIsFocused] = useState(false);
const state = getState(hasError, isFocused, value);

const style = getStyle(theme, state);
const { style, theme } = useDateFieldStyle(hasError, isFocused, value);

const onFocus = (e: NativeSyntheticEvent<TextInputFocusEventData>) => {
setIsFocused(true);
Expand Down Expand Up @@ -138,28 +63,120 @@ export const DateField = forwardRef<TextInput, DateFieldProps>(

DateField.displayName = 'DateFieldRef';

function getState(
function useDateFieldStyle(
hasError: boolean | undefined,
isFocused: boolean,
value: string,
): State {
if (hasError) {
return 'error';
) {
type State =
| 'readonly'
| 'filled'
| 'empty'
| 'filled-focused'
| 'empty-focused'
| 'error';

const theme = useTheme();

function getState(
hasError: boolean | undefined,
isFocused: boolean,
value: string,
): State {
if (hasError) {
return 'error';
}

if (!isFocused && value === '') {
return 'empty';
}

if (isFocused && value === '') {
return 'empty-focused';
}

if (!isFocused) {
return 'filled';
}

return 'filled-focused';
}

if (!isFocused && value === '') {
return 'empty';
function getPlaceholderColorsStyle(theme: Theme, state: State) {
return {
textColor:
state === 'empty-focused'
? theme.sw.colors.primary.main
: theme.sw.colors.neutral[500],
};
}

if (isFocused && value === '') {
return 'empty-focused';
function getTextInputStyle(theme: Theme, state: State) {
let backgroundColor, borderColor, textColor;

switch (state) {
case 'filled-focused':
textColor = theme.sw.colors.neutral[800];
backgroundColor = theme.sw.colors.neutral[50];
borderColor = theme.sw.colors.primary.main;
break;
case 'empty-focused':
textColor = theme.sw.colors.primary.main;
borderColor = theme.sw.colors.primary.main;
backgroundColor =
theme.sw.colors.primary.main + theme.sw.transparency[16];
break;
case 'filled':
textColor = theme.sw.colors.neutral[800];
backgroundColor =
theme.sw.colors.neutral[500] + theme.sw.transparency[8];
break;
case 'error':
textColor = theme.sw.colors.error.main;
backgroundColor =
theme.sw.colors.error.main + theme.sw.transparency[8];
break;
default:
textColor = theme.sw.colors.neutral[500];
backgroundColor =
theme.sw.colors.neutral[500] + theme.sw.transparency[8];
break;
}
return { backgroundColor, borderColor, textColor };
}

if (!isFocused) {
return 'filled';
function getStyle(theme: Theme, state: State) {
const { backgroundColor, borderColor, textColor } = getTextInputStyle(
theme,
state,
);

const placeholderColorsStyle = getPlaceholderColorsStyle(theme, state);

return StyleSheet.create({
main: {
borderRadius: 18,
height: 48,
borderWidth: borderColor !== undefined ? 1 : 0,
borderColor: borderColor,
width: 72,
color: textColor,
fontFamily: 'PublicSans-Bold',
fontSize: 20,
lineHeight: 23.5,
backgroundColor: backgroundColor,
paddingVertical: 0,
marginVertical: 0,
},
placeholder: {
color: placeholderColorsStyle.textColor,
},
});
}

return 'filled-focused';
const state = getState(hasError, isFocused, value);

return { style: getStyle(theme, state), theme };
}

function removeNonNumeric(str: string): string {
Expand Down
11 changes: 7 additions & 4 deletions src/components/dateSelector/DateSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
type DateSelectorProps = WithTestID<{
prefilled: Date;
errorMessage?: string;
onChange: (date: Date) => void;
onUpdatedDate: (date: Date) => void;
}>;

interface FieldsValues {
Expand All @@ -27,7 +27,7 @@ const MAX_DATE_FIELD_LENGTH = 2;
export const DateSelector = ({
prefilled,
errorMessage,
onChange,
onUpdatedDate,
testID,
}: DateSelectorProps) => {
const theme = useTheme();
Expand Down Expand Up @@ -55,8 +55,8 @@ export const DateSelector = ({
setMonthField(completeFields.monthField);
setYearField(completeFields.yearField);

onChange(fromFieldsToDate(completeFields));
}, [prefilledFields, dayField, monthField, yearField, onChange]);
onUpdatedDate(fromFieldsToDate(completeFields));
}, [prefilledFields, dayField, monthField, yearField, onUpdatedDate]);

useListenerOnKeyboardHiding(leaveDateSelector);

Expand Down Expand Up @@ -102,6 +102,7 @@ export const DateSelector = ({
testID={testID + '/day'}
placeholder={prefilledFields.dayField}
value={dayField}
hasError={!!errorMessage}
onBlur={handleBlurPrefixWith0(setDayField)}
onChangeText={handleDayChange}
/>
Expand All @@ -115,6 +116,7 @@ export const DateSelector = ({
testID={testID + '/month'}
placeholder={prefilledFields.monthField}
value={monthField}
hasError={!!errorMessage}
onBlur={handleBlurPrefixWith0(setMonthField)}
onChangeText={handleMonthChange}
/>
Expand All @@ -128,6 +130,7 @@ export const DateSelector = ({
testID={testID + '/year'}
placeholder={prefilledFields.yearField}
value={yearField}
hasError={!!errorMessage}
onBlur={handleBlurPrefixWith0(setYearField)}
onChangeText={handleYearChange}
/>
Expand Down

0 comments on commit feb686d

Please sign in to comment.