Redesign profil with datafake for skills
This commit is contained in:
+201
-52
@@ -1,7 +1,20 @@
|
||||
import { Box, useBreakpointValue, useTheme } from 'native-base';
|
||||
import {
|
||||
Box,
|
||||
Column,
|
||||
Row,
|
||||
Select,
|
||||
useBreakpointValue,
|
||||
useTheme,
|
||||
Text,
|
||||
ScrollView,
|
||||
View,
|
||||
} from 'native-base';
|
||||
import { LineChart } from 'react-native-chart-kit';
|
||||
import SongHistory from '../models/SongHistory';
|
||||
import { useState } from 'react';
|
||||
import { useWindowDimensions } from 'react-native';
|
||||
import CheckboxBase from './UI/CheckboxBase';
|
||||
import { Dataset } from 'react-native-chart-kit/dist/HelperTypes';
|
||||
|
||||
type ScoreGraphProps = {
|
||||
// The result of the call to API.getSongHistory
|
||||
@@ -9,69 +22,205 @@ type ScoreGraphProps = {
|
||||
};
|
||||
|
||||
const formatScoreDate = (playDate: Date): string => {
|
||||
const pad = (n: number) => n.toString().padStart(2, '0');
|
||||
const formattedDate = `${pad(playDate.getDay())}/${pad(playDate.getMonth())}`;
|
||||
const formattedTime = `${pad(playDate.getHours())}:${pad(playDate.getMinutes())}`;
|
||||
return `${formattedDate} ${formattedTime}`;
|
||||
// const formattedDate = `${pad(playDate.getDay())}/${pad(playDate.getMonth())}`;
|
||||
// const formattedTime = `${pad(playDate.getHours())}:${pad(playDate.getMinutes())}`;
|
||||
return `${playDate.getDate()}/${playDate.getMonth()}`;
|
||||
};
|
||||
|
||||
const ScoreGraph = (props: ScoreGraphProps) => {
|
||||
const layout = useWindowDimensions();
|
||||
const [selectedRange, setSelectedRange] = useState('3days');
|
||||
const [displayScore, setDisplayScore] = useState(true);
|
||||
const [displayPedals, setDisplayPedals] = useState(false);
|
||||
const [displayRightHand, setDisplayRightHand] = useState(false);
|
||||
const [displayLeftHand, setDisplayLeftHand] = useState(false);
|
||||
const [displayAccuracy, setDisplayAccuracy] = useState(false);
|
||||
const [displayArpeges, setDisplayArpeges] = useState(false);
|
||||
const [displayChords, setDisplayChords] = useState(false);
|
||||
|
||||
const rangeOptions = [
|
||||
{ label: '3 derniers jours', value: '3days' },
|
||||
{ label: 'Dernière semaine', value: 'week' },
|
||||
{ label: 'Dernier mois', value: 'month' },
|
||||
];
|
||||
const scores = props.songHistory.history.sort((a, b) => {
|
||||
if (a.playDate < b.playDate) {
|
||||
return -1;
|
||||
} else if (a.playDate > b.playDate) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
const filterData = () => {
|
||||
const oneWeekAgo = new Date();
|
||||
const oneMonthAgo = new Date();
|
||||
const threeDaysAgo = new Date();
|
||||
switch (selectedRange) {
|
||||
case 'week':
|
||||
oneWeekAgo.setDate(oneWeekAgo.getDate() - 7);
|
||||
return scores.filter((item) => item.playDate >= oneWeekAgo);
|
||||
case 'month':
|
||||
oneMonthAgo.setMonth(oneMonthAgo.getMonth() - 1);
|
||||
return scores.filter((item) => item.playDate > oneMonthAgo);
|
||||
default:
|
||||
threeDaysAgo.setDate(threeDaysAgo.getDate() - 3);
|
||||
return scores.filter((item) => item.playDate >= threeDaysAgo);
|
||||
}
|
||||
};
|
||||
|
||||
const theme = useTheme();
|
||||
const [containerWidth, setContainerWidth] = useState(0);
|
||||
// We sort the scores by date, asc.
|
||||
// By default, the API returns them in desc.
|
||||
// const pointsToDisplay = props.width / 100;
|
||||
const isSmall = useBreakpointValue({ base: true, md: false });
|
||||
const scores = props.songHistory.history
|
||||
.sort((a, b) => {
|
||||
if (a.playDate < b.playDate) {
|
||||
return -1;
|
||||
} else if (a.playDate > b.playDate) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
})
|
||||
.slice(-10);
|
||||
|
||||
const tempDatasets: Dataset[] = [];
|
||||
|
||||
const skills = [
|
||||
{
|
||||
title: 'Score',
|
||||
value: 'score',
|
||||
data: filterData().map(({ score }) => score),
|
||||
color: '#5f74f7',
|
||||
check: displayScore,
|
||||
setCheck: setDisplayScore,
|
||||
},
|
||||
{
|
||||
title: 'Pedals',
|
||||
value: 'pedals',
|
||||
color: '#ae84fb',
|
||||
data: filterData().map(({ score }) => (score > 100 ? score - 100 : score * 1.4)),
|
||||
check: displayPedals,
|
||||
setCheck: setDisplayPedals,
|
||||
},
|
||||
{
|
||||
title: 'Right hand',
|
||||
value: 'rightHand',
|
||||
data: filterData().map(({ score }) => (score > 10 ? score - 10 : score * 0.2)),
|
||||
color: '#a61455',
|
||||
check: displayRightHand,
|
||||
setCheck: setDisplayRightHand,
|
||||
},
|
||||
{
|
||||
title: 'Left hand',
|
||||
value: 'leftHand',
|
||||
data: filterData().map(({ score }) => (score > 50 ? score - 50 : score * 0.8)),
|
||||
color: '#ed4a51',
|
||||
check: displayLeftHand,
|
||||
setCheck: setDisplayLeftHand,
|
||||
},
|
||||
{
|
||||
title: 'Accuracy',
|
||||
value: 'accuracy',
|
||||
data: filterData().map(({ score }) => (score > 40 ? score - 40 : score * 0.4)),
|
||||
color: '#ff7a72',
|
||||
check: displayAccuracy,
|
||||
setCheck: setDisplayAccuracy,
|
||||
},
|
||||
{
|
||||
title: 'Arpeges',
|
||||
value: 'arpeges',
|
||||
data: filterData().map(({ score }) => (score > 200 ? score - 200 : score * 1.2)),
|
||||
color: '#ead93c',
|
||||
check: displayArpeges,
|
||||
setCheck: setDisplayArpeges,
|
||||
},
|
||||
{
|
||||
title: 'Chords',
|
||||
value: 'chords',
|
||||
data: filterData().map(({ score }) => (score > 50 ? score - 50 : score)),
|
||||
color: '#73d697',
|
||||
check: displayChords,
|
||||
setCheck: setDisplayChords,
|
||||
},
|
||||
];
|
||||
|
||||
for (const skill of skills) {
|
||||
if (skill.check) {
|
||||
tempDatasets.push({
|
||||
data: skill.data,
|
||||
color: () => skill.color,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Box
|
||||
style={{ width: '100%' }}
|
||||
onLayout={(event) => setContainerWidth(event.nativeEvent.layout.width)}
|
||||
>
|
||||
<LineChart
|
||||
data={{
|
||||
labels: isSmall ? [] : scores.map(({ playDate }) => formatScoreDate(playDate)),
|
||||
datasets: [
|
||||
{
|
||||
data: scores.map(({ score }) => score),
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
width={containerWidth}
|
||||
height={200} // Completely arbitrary
|
||||
transparent={true}
|
||||
withDots={false}
|
||||
yAxisSuffix=" pts"
|
||||
chartConfig={{
|
||||
decimalPlaces: 0,
|
||||
color: (opacity = 1) => `rgba(255, 255, 255, ${opacity})`,
|
||||
labelColor: () => theme.colors.white,
|
||||
propsForDots: {
|
||||
r: '6',
|
||||
strokeWidth: '2',
|
||||
},
|
||||
<Column>
|
||||
<Row
|
||||
style={{
|
||||
alignItems: 'center',
|
||||
}}
|
||||
bezier
|
||||
// style={{
|
||||
// margin: 3,
|
||||
// shadowColor: theme.colors.primary[400],
|
||||
// shadowOpacity: 1,
|
||||
// shadowRadius: 20,
|
||||
// borderRadius: CardBorderRadius,
|
||||
// }}
|
||||
/>
|
||||
</Box>
|
||||
>
|
||||
<Text>Skils</Text>
|
||||
<ScrollView horizontal={true}>
|
||||
{skills.map((skill) => (
|
||||
<View key={skill.value} style={{ paddingLeft: 20 }}>
|
||||
<CheckboxBase
|
||||
title={skill.title}
|
||||
value={skill.value}
|
||||
check={skill.check}
|
||||
setCheck={skill.setCheck}
|
||||
/>
|
||||
</View>
|
||||
))}
|
||||
</ScrollView>
|
||||
<Select
|
||||
selectedValue={selectedRange}
|
||||
onValueChange={(itemValue) => setSelectedRange(itemValue)}
|
||||
defaultValue={'3days'}
|
||||
bgColor={'rgba(16,16,20,0.5)'}
|
||||
variant="filled"
|
||||
style={{ display: 'flex', justifyContent: 'center' }}
|
||||
width={layout.width > 650 ? '200' : '100'}
|
||||
>
|
||||
{rangeOptions.map((option) => (
|
||||
<Select.Item key={option.label} label={option.label} value={option.value} />
|
||||
))}
|
||||
</Select>
|
||||
</Row>
|
||||
<Box
|
||||
style={{ width: '100%', marginTop: 20 }}
|
||||
onLayout={(event) => setContainerWidth(event.nativeEvent.layout.width)}
|
||||
>
|
||||
{tempDatasets.length > 0 && (
|
||||
<LineChart
|
||||
data={{
|
||||
labels: isSmall
|
||||
? []
|
||||
: filterData().map(({ playDate }) => formatScoreDate(playDate)),
|
||||
datasets: tempDatasets,
|
||||
}}
|
||||
width={containerWidth}
|
||||
height={300} // Completely arbitrary
|
||||
transparent={true}
|
||||
yAxisSuffix=" pts"
|
||||
chartConfig={{
|
||||
propsForLabels: {
|
||||
fontFamily: 'Lexend',
|
||||
},
|
||||
propsForVerticalLabels: {
|
||||
rotation: -90,
|
||||
},
|
||||
propsForBackgroundLines: {
|
||||
strokeDasharray: '',
|
||||
strokeWidth: '1',
|
||||
color: '#fff000',
|
||||
},
|
||||
decimalPlaces: 0,
|
||||
color: (opacity = 1) => `rgba(255, 255, 255, ${opacity})`,
|
||||
labelColor: () => theme.colors.white,
|
||||
propsForDots: {
|
||||
r: '6',
|
||||
strokeWidth: '2',
|
||||
},
|
||||
}}
|
||||
bezier
|
||||
/>
|
||||
)}
|
||||
</Box>
|
||||
</Column>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -107,12 +107,15 @@ const ButtonBase: React.FC<ButtonProps> = ({
|
||||
>
|
||||
{loading ? (
|
||||
<ActivityIndicator
|
||||
style={styles.content}
|
||||
size="small"
|
||||
color={type === 'outlined' ? '#6075F9' : '#FFFFFF'}
|
||||
/>
|
||||
) : (
|
||||
<View style={styles.content}>
|
||||
{icon && <MyIcon size={'18'} color={type === 'outlined' ? '#6075F9' : '#FFFFFF'}/>}
|
||||
{icon && (
|
||||
<MyIcon size={'18'} color={type === 'outlined' ? '#6075F9' : '#FFFFFF'} />
|
||||
)}
|
||||
{iconImage && <Image source={{ uri: iconImage }} style={styles.icon} />}
|
||||
{title && <Text style={styles.text}>{title}</Text>}
|
||||
</View>
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
import React from 'react';
|
||||
import { StyleSheet, View, StyleProp, ViewStyle } from 'react-native';
|
||||
import InteractiveBase from './InteractiveBase';
|
||||
import { Checkbox } from 'native-base';
|
||||
|
||||
interface CheckboxProps {
|
||||
title: string;
|
||||
value: string;
|
||||
// color: string;
|
||||
check: boolean;
|
||||
setCheck: (value: boolean) => void;
|
||||
style?: StyleProp<ViewStyle>;
|
||||
}
|
||||
|
||||
const CheckboxBase: React.FC<CheckboxProps> = ({
|
||||
title,
|
||||
value,
|
||||
// color,
|
||||
style,
|
||||
check,
|
||||
setCheck,
|
||||
}) => {
|
||||
const styleGlassmorphism = StyleSheet.create({
|
||||
Default: {
|
||||
scale: 1,
|
||||
shadowOpacity: 0.3,
|
||||
shadowRadius: 4.65,
|
||||
elevation: 8,
|
||||
backgroundColor: 'rgba(16,16,20,0.5)',
|
||||
},
|
||||
onHover: {
|
||||
scale: 1.01,
|
||||
shadowOpacity: 0.37,
|
||||
shadowRadius: 7.49,
|
||||
elevation: 12,
|
||||
backgroundColor: 'rgba(16,16,20,0.4)',
|
||||
},
|
||||
onPressed: {
|
||||
scale: 0.99,
|
||||
shadowOpacity: 0.23,
|
||||
shadowRadius: 2.62,
|
||||
elevation: 4,
|
||||
backgroundColor: 'rgba(16,16,20,0.6)',
|
||||
},
|
||||
Disabled: {
|
||||
scale: 1,
|
||||
shadowOpacity: 0.3,
|
||||
shadowRadius: 4.65,
|
||||
elevation: 8,
|
||||
backgroundColor: 'rgba(16,16,20,0.5)',
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<InteractiveBase
|
||||
style={[styles.container, style]}
|
||||
styleAnimate={styleGlassmorphism}
|
||||
onPress={async () => {
|
||||
setCheck(!check);
|
||||
}}
|
||||
>
|
||||
<View style={{ paddingVertical: 5, paddingHorizontal: 10 }}>
|
||||
<Checkbox isChecked={check} style={styles.content} value={value}>
|
||||
{title}
|
||||
</Checkbox>
|
||||
</View>
|
||||
</InteractiveBase>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
borderRadius: 8,
|
||||
},
|
||||
content: {
|
||||
justifyContent: 'center',
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
},
|
||||
});
|
||||
|
||||
export default CheckboxBase;
|
||||
@@ -233,7 +233,7 @@ const InteractiveBase: React.FC<InteractiveBaseProps> = ({
|
||||
shadowOpacity: styleAnimate.Disabled.shadowOpacity,
|
||||
shadowRadius: styleAnimate.Disabled.shadowRadius,
|
||||
elevation: styleAnimate.Disabled.elevation,
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Animated.View style={[style, isDisabled ? disableStyle : animatedStyle]}>
|
||||
|
||||
@@ -1,73 +1,112 @@
|
||||
import { LinearGradient } from "expo-linear-gradient";
|
||||
import { Center, Flex, Stack, View, Text, Wrap, Image } from "native-base";
|
||||
import { FunctionComponent } from "react";
|
||||
import { Linking, useWindowDimensions } from "react-native";
|
||||
import ButtonBase from "./ButtonBase";
|
||||
import { translate } from "../../i18n/i18n";
|
||||
import API from "../../API";
|
||||
import SeparatorBase from "./SeparatorBase";
|
||||
import LinkBase from "./LinkBase";
|
||||
import { LinearGradient } from 'expo-linear-gradient';
|
||||
import { Center, Flex, Stack, View, Text, Wrap, Image } from 'native-base';
|
||||
import { FunctionComponent } from 'react';
|
||||
import { Linking, useWindowDimensions } from 'react-native';
|
||||
import ButtonBase from './ButtonBase';
|
||||
import { translate } from '../../i18n/i18n';
|
||||
import API from '../../API';
|
||||
import SeparatorBase from './SeparatorBase';
|
||||
import LinkBase from './LinkBase';
|
||||
import ImageBanner from '../../assets/banner.jpg';
|
||||
|
||||
interface ScaffoldAuthProps {
|
||||
title: string;
|
||||
description: string;
|
||||
form: React.ReactNode[];
|
||||
submitButton: React.ReactNode;
|
||||
link: {text: string, description: string, onPress: () => void};
|
||||
title: string;
|
||||
description: string;
|
||||
form: React.ReactNode[];
|
||||
submitButton: React.ReactNode;
|
||||
link: { text: string; description: string; onPress: () => void };
|
||||
}
|
||||
|
||||
const ScaffoldAuth: FunctionComponent<ScaffoldAuthProps> = ({title, description, form, submitButton, link}) => {
|
||||
const layout = useWindowDimensions();
|
||||
const ScaffoldAuth: FunctionComponent<ScaffoldAuthProps> = ({
|
||||
title,
|
||||
description,
|
||||
form,
|
||||
submitButton,
|
||||
link,
|
||||
}) => {
|
||||
const layout = useWindowDimensions();
|
||||
|
||||
return (
|
||||
<Flex direction='row' justifyContent="space-between" style={{ flex: 1, backgroundColor: '#101014'}}>
|
||||
<Center style={{ flex: 1}}>
|
||||
<View style={{ width: '100%', maxWidth: 420, padding: 16 }}>
|
||||
<Stack space={8} justifyContent="center" alignContent="center" alignItems="center" style={{ width: '100%', paddingBottom: 40}}>
|
||||
<Text fontSize="4xl" textAlign="center">{title}</Text>
|
||||
<Text fontSize="lg" textAlign="center">{description}</Text>
|
||||
</Stack>
|
||||
<Stack space={5} justifyContent="center" alignContent="center" alignItems="center" style={{ width: '100%'}}>
|
||||
<ButtonBase
|
||||
style={{width: '100%'}}
|
||||
type='outlined'
|
||||
iconImage='https://upload.wikimedia.org/wikipedia/commons/thumb/5/53/Google_%22G%22_Logo.svg/2008px-Google_%22G%22_Logo.svg.png'
|
||||
title={translate('continuewithgoogle')}
|
||||
onPress={() => Linking.openURL(`${API.baseUrl}/auth/login/google`)}
|
||||
/>
|
||||
<SeparatorBase>or</SeparatorBase>
|
||||
<Stack space={3} justifyContent="center" alignContent="center" alignItems="center" style={{ width: '100%'}}>
|
||||
{form}
|
||||
</Stack>
|
||||
{submitButton}
|
||||
<Wrap style={{flexDirection: 'row', justifyContent: 'center'}}>
|
||||
<Text>{link.description}</Text>
|
||||
<LinkBase onPress={link.onPress}>
|
||||
{link.text}
|
||||
</LinkBase>
|
||||
</Wrap>
|
||||
</Stack>
|
||||
</View>
|
||||
</Center>
|
||||
{
|
||||
layout.width > 650 ?
|
||||
<View style={{width: '50%', height: '100%', padding: 16}}>
|
||||
<Image
|
||||
source={ImageBanner}
|
||||
alt="banner page"
|
||||
style={{width: '100%', height: '100%', borderRadius: 8}}
|
||||
/>
|
||||
</View>
|
||||
: <></>
|
||||
}
|
||||
<LinearGradient
|
||||
start={{x: 0, y: 0}}
|
||||
end={{x: 1, y: 1}}
|
||||
colors={['#101014', '#6075F9']}
|
||||
style={{top: 0, bottom: 0, right: 0, left: 0, width: '100%', height: '100%', position: 'absolute', zIndex: -2}}
|
||||
/>
|
||||
</Flex>
|
||||
<Flex
|
||||
direction="row"
|
||||
justifyContent="space-between"
|
||||
style={{ flex: 1, backgroundColor: '#101014' }}
|
||||
>
|
||||
<Center style={{ flex: 1 }}>
|
||||
<View style={{ width: '100%', maxWidth: 420, padding: 16 }}>
|
||||
<Stack
|
||||
space={8}
|
||||
justifyContent="center"
|
||||
alignContent="center"
|
||||
alignItems="center"
|
||||
style={{ width: '100%', paddingBottom: 40 }}
|
||||
>
|
||||
<Text fontSize="4xl" textAlign="center">
|
||||
{title}
|
||||
</Text>
|
||||
<Text fontSize="lg" textAlign="center">
|
||||
{description}
|
||||
</Text>
|
||||
</Stack>
|
||||
<Stack
|
||||
space={5}
|
||||
justifyContent="center"
|
||||
alignContent="center"
|
||||
alignItems="center"
|
||||
style={{ width: '100%' }}
|
||||
>
|
||||
<ButtonBase
|
||||
style={{ width: '100%' }}
|
||||
type="outlined"
|
||||
iconImage="https://upload.wikimedia.org/wikipedia/commons/thumb/5/53/Google_%22G%22_Logo.svg/2008px-Google_%22G%22_Logo.svg.png"
|
||||
title={translate('continuewithgoogle')}
|
||||
onPress={() => Linking.openURL(`${API.baseUrl}/auth/login/google`)}
|
||||
/>
|
||||
<SeparatorBase>or</SeparatorBase>
|
||||
<Stack
|
||||
space={3}
|
||||
justifyContent="center"
|
||||
alignContent="center"
|
||||
alignItems="center"
|
||||
style={{ width: '100%' }}
|
||||
>
|
||||
{form}
|
||||
</Stack>
|
||||
{submitButton}
|
||||
<Wrap style={{ flexDirection: 'row', justifyContent: 'center' }}>
|
||||
<Text>{link.description}</Text>
|
||||
<LinkBase onPress={link.onPress}>{link.text}</LinkBase>
|
||||
</Wrap>
|
||||
</Stack>
|
||||
</View>
|
||||
</Center>
|
||||
{layout.width > 650 ? (
|
||||
<View style={{ width: '50%', height: '100%', padding: 16 }}>
|
||||
<Image
|
||||
source={ImageBanner}
|
||||
alt="banner page"
|
||||
style={{ width: '100%', height: '100%', borderRadius: 8 }}
|
||||
/>
|
||||
</View>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
<LinearGradient
|
||||
start={{ x: 0, y: 0 }}
|
||||
end={{ x: 1, y: 1 }}
|
||||
colors={['#101014', '#6075F9']}
|
||||
style={{
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
right: 0,
|
||||
left: 0,
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
position: 'absolute',
|
||||
zIndex: -2,
|
||||
}}
|
||||
/>
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -103,7 +103,13 @@ const TextFieldBase: React.FC<TextFieldBaseProps> = ({
|
||||
<InteractiveBase style={[style, { borderRadius: 12 }]} styleAnimate={styleAnimate}>
|
||||
<View style={styles.container}>
|
||||
<View style={styles.iconContainerLeft}>
|
||||
{icon && <MyIcon size={'20'} color={iconColor ? iconColor : isFocused ? '#5f74f7' : '#394694'} variant="Bold"/>}
|
||||
{icon && (
|
||||
<MyIcon
|
||||
size={'20'}
|
||||
color={iconColor ? iconColor : isFocused ? '#5f74f7' : '#394694'}
|
||||
variant="Bold"
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
<Input
|
||||
variant="unstyled"
|
||||
|
||||
@@ -12,7 +12,7 @@ const getInitials = (name: string) => {
|
||||
|
||||
type UserAvatarProps = Pick<Parameters<typeof Avatar>[0], 'size'>;
|
||||
|
||||
const UserAvatar = ({ size }: UserAvatarProps) => {
|
||||
const UserAvatar = ({ size = 'md' }: UserAvatarProps) => {
|
||||
const user = useQuery(API.getUserInfo);
|
||||
const avatarUrl = useMemo(() => {
|
||||
if (!user.data) {
|
||||
@@ -25,7 +25,9 @@ const UserAvatar = ({ size }: UserAvatarProps) => {
|
||||
|
||||
return (
|
||||
<Avatar
|
||||
borderRadius={12}
|
||||
size={size}
|
||||
_image={{ borderRadius: 12 }}
|
||||
source={avatarUrl ? { uri: avatarUrl.toString() } : undefined}
|
||||
style={{ zIndex: 0 }}
|
||||
>
|
||||
|
||||
@@ -33,7 +33,7 @@ const ChangeEmailForm = ({ onSubmit }: ChangeEmailFormProps) => {
|
||||
<TextFormField
|
||||
style={{ marginVertical: 10 }}
|
||||
isRequired
|
||||
icon={(size, color) => <Sms size={size} color={color} variant="Bold" />}
|
||||
icon={Sms}
|
||||
placeholder={translate('oldEmail')}
|
||||
value={formData.oldEmail.value}
|
||||
error={formData.oldEmail.error}
|
||||
@@ -51,7 +51,7 @@ const ChangeEmailForm = ({ onSubmit }: ChangeEmailFormProps) => {
|
||||
style={{ marginVertical: 10 }}
|
||||
isRequired
|
||||
autoComplete="off"
|
||||
icon={(size, color) => <Sms size={size} color={color} variant="Bold" />}
|
||||
icon={Sms}
|
||||
placeholder={translate('newEmail')}
|
||||
value={formData.newEmail.value}
|
||||
error={formData.newEmail.error}
|
||||
|
||||
Reference in New Issue
Block a user