mattermost-mobile/app/screens/edit_profile/components/field.tsx
Guillermo Vayá 0addf49021
[MM-62701] [MM-62176]Edit custom profile attributes in user profile (#8557)
* feat: Add support for custom profile attributes in edit profile form

feat: Add support for custom profile attributes in edit profile

refactor: Normalize whitespace in CustomAttribute type definition

fix: Resolve type mismatch for customAttributes in UserInfo interface

test: Add test for udpateCustomProfileAttributeValues method

fix typing, submit changes to server

missing files

test: Add tests for CustomProfileField component

fix naming

fix imports

fix

feat: Add field_refs hook for managing field references

feat: Make `setRef` ref parameter optional with default no-op implementation

refactor: Replace CustomProfileField with useFieldRefs for profile form

refactor: Optimize edit profile screen imports and custom attributes handling

refactor: Move custom attributes logic to remote actions in user.ts

address PR reviews

test: Add tests for custom attributes in edit profile

test: Add tests for EditProfile component with custom attributes

fix: Add UserModel type assertion to currentUser in edit profile tests

test: Add tests for ProfileForm custom attributes functionality

test: Add comprehensive tests for useFieldRefs hook

test: Add tests for fetchCustomAttributes and updateCustomAttributes

add tests

remove unneeded files

review changes

remove counter from hook

remove package.resolved

create interface for reuse of record

* fix signature type
2025-02-19 15:51:59 +01:00

105 lines
3.2 KiB
TypeScript

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React, {type ComponentProps, memo, useCallback} from 'react';
import {useIntl} from 'react-intl';
import {Platform, type TextInputProps, View} from 'react-native';
import FloatingTextInput from '@components/floating_text_input_label';
import {useTheme} from '@context/theme';
import {useIsTablet} from '@hooks/device';
import {changeOpacity, getKeyboardAppearanceFromTheme, makeStyleSheetFromTheme} from '@utils/theme';
export type FieldProps = TextInputProps & {
isDisabled?: boolean;
fieldKey: string;
label: string;
maxLength?: number;
onTextChange: (fieldKey: string, value: string) => void;
isOptional?: boolean;
testID: string;
error?: string;
value: string;
fieldRef: ComponentProps<typeof FloatingTextInput>['ref'];
onFocusNextField: (fieldKey: string) => void;
};
const getStyleSheet = makeStyleSheetFromTheme((theme) => {
return {
viewContainer: {
marginVertical: 8,
alignItems: 'center',
width: '100%',
},
disabledStyle: {
backgroundColor: changeOpacity(theme.centerChannelColor, 0.04),
},
};
});
const Field = ({
autoCapitalize = 'none',
autoCorrect = false,
fieldKey,
isDisabled = false,
isOptional = false,
keyboardType = 'default',
label,
maxLength,
onTextChange,
testID,
value,
fieldRef,
error,
onFocusNextField,
...props
}: FieldProps) => {
const theme = useTheme();
const intl = useIntl();
const isTablet = useIsTablet();
const onChangeText = useCallback((text: string) => onTextChange(fieldKey, text), [fieldKey, onTextChange]);
const onSubmitEditing = useCallback(() => {
onFocusNextField(fieldKey);
}, [fieldKey, onFocusNextField]);
const style = getStyleSheet(theme);
const keyboard = (Platform.OS === 'android' && keyboardType === 'url') ? 'default' : keyboardType;
const optionalText = intl.formatMessage({id: 'channel_modal.optional', defaultMessage: '(optional)'});
const formattedLabel = isOptional ? `${label} ${optionalText}` : label;
const subContainer = [style.viewContainer, {paddingHorizontal: isTablet ? 42 : 20}];
const fieldInputTestId = isDisabled ? `${testID}.input.disabled` : `${testID}.input`;
return (
<View
testID={testID}
style={subContainer}
>
<FloatingTextInput
autoCapitalize={autoCapitalize}
autoCorrect={autoCorrect}
disableFullscreenUI={true}
editable={!isDisabled}
keyboardAppearance={getKeyboardAppearanceFromTheme(theme)}
keyboardType={keyboard}
label={formattedLabel}
maxLength={maxLength}
onChangeText={onChangeText}
testID={fieldInputTestId}
theme={theme}
error={error}
value={value}
ref={fieldRef}
onSubmitEditing={onSubmitEditing}
{...props}
/>
</View>
);
};
export default memo(Field);