panhui hace 5 años
padre
commit
8d3b3cd7a5

+ 1 - 1
App.js

@@ -48,7 +48,7 @@ export default function App() {
           routes: [
             {
               name: initName,
-              // name: 'Search',
+              // name: 'PayOrder',
             },
           ],
         })

+ 45 - 0
Utils/SmsUtil.ts

@@ -0,0 +1,45 @@
+import request from './RequestUtils';
+import submitPhone from './FormUtils';
+
+const templateMap = new Map([
+  [
+    'changePhone',
+    {
+      name: '修改手机号',
+      key: 676939,
+    },
+  ],
+  [
+    'register',
+    {
+      name: '注册',
+      key: 674906,
+    },
+  ],
+  [
+    'forgetPsd',
+    {
+      name: '忘记密码',
+      key: '674832',
+    },
+  ],
+  [
+    'login',
+    {
+      name: '通用',
+      key: '674851',
+    },
+  ],
+]);
+
+function sendSms(phone, type) {
+  return request.get('/sms/tencentSend', {
+    params: {
+      phone: `+86${submitPhone(phone)}`,
+      templateId: templateMap.get(type).key,
+    },
+  });
+}
+
+// eslint-disable-next-line import/prefer-default-export
+export { sendSms };

+ 71 - 0
components/SmsInput.jsx

@@ -0,0 +1,71 @@
+import * as WebBrowser from 'expo-web-browser';
+import * as React from 'react';
+import { Div, Image, Text, Avatar, Input, Button } from 'react-native-magnus';
+import { Toast } from '@ant-design/react-native';
+import { useInterval } from 'ahooks';
+import { sendSms } from '../Utils/SmsUtil';
+
+export default function SmsInput({ labelWidth, phone, onCodeChange, type }) {
+  const [code, setCode] = React.useState();
+  const [interval, setInterval] = React.useState(null);
+  const [count, setCount] = React.useState(60);
+
+  useInterval(
+    () => {
+      setCount(count - 1);
+      if (count === 0) {
+        setInterval(null);
+      }
+    },
+    interval,
+    { immediate: true }
+  );
+
+  return (
+    <Div
+      row
+      alignItems="center"
+      ml={15}
+      py={10}
+      borderBottomWidth={1}
+      borderBottomColor="gray100"
+    >
+      <Text textAlign="left" fontSize="lg" mr={12} w={labelWidth || 80}>
+        验证码
+      </Text>
+      <Input
+        placeholder="输入验证码"
+        fontSize="lg"
+        // bg="gray100"
+        flex={1}
+        h={32}
+        mr={10}
+        value={code}
+        borderWidth={0}
+        onChangeText={(value) => {
+          setCode(value);
+          onCodeChange(value);
+        }}
+      />
+      <Button
+        bg="transparent"
+        color={interval ? 'gray500' : 'brand500'}
+        fontSize="sm"
+        disabled={!phone || interval}
+        onPress={() => {
+          sendSms(phone, type || 'register')
+            .then(() => {
+              setCount(60);
+              setInterval(1000);
+            })
+            .catch((e) => {
+              console.log(e);
+              Toast.info(e.response.data.error);
+            });
+        }}
+      >
+        {interval ? `已发送(${count})S` : '发送验证码'}
+      </Button>
+    </Div>
+  );
+}

+ 1 - 0
constants/ThemeMagnus.js

@@ -25,6 +25,7 @@ export default {
   fontSize: {
     xs: 10,
     sm: 12,
+    lg: 14,
     xl: 16,
     '4xl': 24,
     '5xl': 32,

+ 30 - 3
flooks/User.js

@@ -31,10 +31,37 @@ const app = (now) => ({
     const { loading, warnning, success } = now(Toast);
     loading();
     return request
-      .post('/auth/login', {
+      .post('/auth/loginByRegister', {
+        data: {
+          phone: submitPhone(phone),
+          password,
+          identity: 'USER',
+        },
+        requestType: 'form',
+      })
+      .then((res) => {
+        return addAsyncStorage('token', res);
+      })
+      .then(() => {
+        const { getUser } = now();
+        return getUser();
+      })
+      .then(() => {
+        success(i18n.t('deng-lu-cheng-gong'));
+      })
+      .catch((e) => {
+        warnning(e.error);
+      });
+  },
+  loginByCode(phone, code) {
+    const { loading, warnning, success } = now(Toast);
+    loading();
+    return request
+      .post('/auth/phoneLogin', {
         data: {
-          username: submitPhone(phone),
-          password
+          phone: `+86${submitPhone(phone)}`,
+          code,
+          identity: 'USER',
         },
         requestType: 'form',
       })

+ 8 - 1
navigation/BaseNavigator.jsx

@@ -18,6 +18,7 @@ import ComplaintNext from '../screens/Order/ComplaintNextScreen';
 import EvaluateScreen from '../screens/Order/EvaluateScreen';
 import RewardRider from '../screens/Order/RewardRiderScreen';
 import ApplayCancel from '../screens/Order/ApplayCancelScreen';
+import PayOrderScreen from '../screens/Pay/PayOrderScreen';
 
 // 用户
 import Setting from '../screens/User/SettingScreen';
@@ -87,9 +88,15 @@ export default function BasicScreens(Screen) {
       {/* 订单详情 */}
       <Screen
         name="OrderDetail"
-        initialParams={{ orderId: 1948 }}
+        initialParams={{ orderId: 2307 }}
         component={OrderDetail}
       />
+      {/* 订单详情 */}
+      <Screen
+        name="PayOrder"
+        initialParams={{ orderId: 2307 }}
+        component={PayOrderScreen}
+      />
       {/* 投诉 */}
       <Screen name="Complaint" component={Complaint} />
       {/* 投诉 2 */}

+ 35 - 0
package-lock.json

@@ -2,6 +2,15 @@
   "requires": true,
   "lockfileVersion": 1,
   "dependencies": {
+    "@ahooksjs/use-request": {
+      "version": "2.4.0",
+      "resolved": "https://registry.npmjs.org/@ahooksjs/use-request/-/use-request-2.4.0.tgz",
+      "integrity": "sha512-nrQSxYnuXSTOP29RAFPyFi6LpNc1RWcCtGvMIu7zmjEe5QmJncQXBMa7BKia+SAUnhBV1MrCGrlnOBq4gY9XWw==",
+      "requires": {
+        "lodash.debounce": "^4.0.8",
+        "lodash.throttle": "^4.1.1"
+      }
+    },
     "@ant-design/icons-react-native": {
       "version": "2.2.1",
       "resolved": "https://registry.npmjs.org/@ant-design/icons-react-native/-/icons-react-native-2.2.1.tgz",
@@ -3568,6 +3577,11 @@
         "@types/istanbul-lib-report": "*"
       }
     },
+    "@types/js-cookie": {
+      "version": "2.2.6",
+      "resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-2.2.6.tgz",
+      "integrity": "sha512-+oY0FDTO2GYKEV0YPvSshGq9t7YozVkgvXLty7zogQNuCxBhT9/3INX9Q7H1aRZ4SUDRXAKlJuA4EA5nTt7SNw=="
+    },
     "@types/json-schema": {
       "version": "7.0.5",
       "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.5.tgz",
@@ -3855,6 +3869,22 @@
       "integrity": "sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==",
       "dev": true
     },
+    "ahooks": {
+      "version": "2.4.0",
+      "resolved": "https://registry.npmjs.org/ahooks/-/ahooks-2.4.0.tgz",
+      "integrity": "sha512-aY5cV8bduCzglnedv//fjm75X2JxtmttHSLcl5Y3RHu356EMwd1y33Lp/mkCfvcIRjHpNmYz4F4Y43N300WyuQ==",
+      "requires": {
+        "@ahooksjs/use-request": "^2.3.0",
+        "@types/js-cookie": "^2.2.6",
+        "intersection-observer": "^0.7.0",
+        "js-cookie": "^2.2.1",
+        "lodash.debounce": "^4.0.8",
+        "lodash.isequal": "^4.5.0",
+        "lodash.throttle": "^4.1.1",
+        "resize-observer-polyfill": "^1.5.1",
+        "screenfull": "^5.0.0"
+      }
+    },
     "ajv": {
       "version": "6.12.2",
       "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz",
@@ -11595,6 +11625,11 @@
       "resolved": "https://registry.npmjs.org/jetifier/-/jetifier-1.6.6.tgz",
       "integrity": "sha512-JNAkmPeB/GS2tCRqUzRPsTOHpGDah7xP18vGJfIjZC+W2sxEHbxgJxetIjIqhjQ3yYbYNEELkM/spKLtwoOSUQ=="
     },
+    "js-cookie": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.1.tgz",
+      "integrity": "sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ=="
+    },
     "js-tokens": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",

+ 1 - 0
package.json

@@ -28,6 +28,7 @@
     "@umijs/hooks": "^1.9.3",
     "@umijs/use-request": "^1.4.3",
     "acorn": "^7.2.0",
+    "ahooks": "^2.4.0",
     "axios": "^0.19.2",
     "color": "^3.1.2",
     "core-js": "^3.6.5",

+ 10 - 6
screens/Detail/SubmitScreen.jsx

@@ -54,7 +54,7 @@ export default function SubmitScreen() {
     'cartMoneyInfo',
   ]);
   const { chooseAddressId } = useModel(AddressModel, ['chooseAddressId']);
-  const { submitOrder } = useModel(Order, []);
+  const { submitOrder, payOrder } = useModel(Order, []);
   const route = useRoute();
   const navigation = useNavigation();
   const { params } = route;
@@ -273,12 +273,16 @@ export default function SubmitScreen() {
             const ids = cartList.map((item) => {
               return item.shoppingCartId;
             });
-            submitOrder(ids[0], chooseAddressId, payMethod, remark).then(
-              (res) => {
+            submitOrder(ids[0], chooseAddressId, payMethod, remark)
+              .then((res) => {
                 cartRefreash();
-                navigation.replace('OrderDetail', { orderId: res.id });
-              }
-            );
+                return payOrder(res.id).then(() => {
+                  return Promise.resolve(res.id);
+                });
+              })
+              .then((id) => {
+                navigation.replace('OrderDetail', { orderId: id });
+              });
           }}
         >
           支付

+ 14 - 16
screens/Login/LoginScreen.jsx

@@ -8,6 +8,7 @@ import useModel from 'flooks';
 import Toast from '../../flooks/Toast';
 import user from '../../flooks/User';
 import Button from '../../components/Button';
+import SmsInput from '../../components/SmsInput';
 
 const Tab = createMaterialTopTabNavigator();
 
@@ -17,7 +18,7 @@ const img2 = require('../../assets/images/loginLogo.png');
 export default function LoginScreen({ navigation }) {
   const btnList = () => (
     <View style={styles.btn}>
-      <Button
+      {/* <Button
         text
         size="small"
         type="info"
@@ -26,17 +27,7 @@ export default function LoginScreen({ navigation }) {
         }}
       >
         忘记密码
-      </Button>
-      <Button
-        text
-        size="small"
-        type="info"
-        onPress={() => {
-          navigation.navigate('Register');
-        }}
-      >
-        用户注册
-      </Button>
+      </Button> */}
     </View>
   );
 
@@ -55,6 +46,7 @@ export default function LoginScreen({ navigation }) {
               <Image source={img2} style={styles.img2} resizeMode="contain" />
               <View style={styles.tab}>
                 <Tab.Navigator
+                  initialRouteName="验证码登陆"
                   tabBarOptions={{
                     activeTintColor: '#FFC750',
                     inactiveTintColor: '#000',
@@ -155,7 +147,7 @@ const LoginCode = ({ route }) => {
   const [phone, setphone] = React.useState();
   const [code, setCode] = React.useState();
   const { warnning } = useModel(Toast, []);
-  const { loginByPsd } = useModel(user, []);
+  const { loginByCode } = useModel(user, []);
   const { params } = route;
   const { btnList } = params || {};
   const submit = () => {
@@ -164,7 +156,7 @@ const LoginCode = ({ route }) => {
     } else if (!code) {
       warnning('验证码');
     } else {
-      loginByPsd(phone, code);
+      loginByCode(phone, code);
     }
   };
   return (
@@ -179,7 +171,13 @@ const LoginCode = ({ route }) => {
       >
         <Paragraph>手机号</Paragraph>
       </InputItem>
-      <InputItem
+      <SmsInput
+        labelWidth={50}
+        onCodeChange={setCode}
+        phone={phone}
+        type="login"
+      />
+      {/* <InputItem
         clear
         type="number"
         value={code}
@@ -193,7 +191,7 @@ const LoginCode = ({ route }) => {
         }}
       >
         <Paragraph>验证码</Paragraph>
-      </InputItem>
+      </InputItem> */}
       {btnList()}
       <View style={[styles.btn, styles.sub]}>
         <Button onPress={submit}>登录</Button>

+ 1 - 1
screens/Main/Home/HomeHeader.jsx

@@ -99,7 +99,7 @@ export default function Header() {
             }}
             title={t('qie-huan-yu-yan')}
           />
-          <Menu.Item onPress={() => {}} title="版本0814 聊天订单" />
+          <Menu.Item onPress={() => {}} title="版本0817 聊天订单" />
         </Menu>
       </Appbar.Header>
     </>

+ 1 - 1
screens/Order/ApplayCancelScreen.jsx

@@ -6,7 +6,7 @@ import { ScrollView } from 'react-native-gesture-handler';
 import { TextareaItem } from '@ant-design/react-native';
 import { useTranslation } from 'react-i18next';
 
-import { PullPicker } from 'teaset';
+// import { PullPicker } from 'teaset';
 
 import { useRoute } from '@react-navigation/native';
 import { useCreation } from '@umijs/hooks';

+ 23 - 1
screens/Order/OrderDetailScreen.jsx

@@ -115,6 +115,14 @@ export default function OrderScreen({ navigation }) {
     }
   }, [orderInfo]);
 
+  const isPay = useCreation(() => {
+    if (orderInfo.status === 'UNPAID') {
+      return false;
+    } else {
+      return true;
+    }
+  }, [orderInfo]);
+
   const hasRider = useCreation(() => {
     if (orderInfo.riderStatus !== 'NOT_RECEIVED' && orderInfo.riderStatus) {
       return true;
@@ -330,6 +338,20 @@ export default function OrderScreen({ navigation }) {
                   {t('lian-xi-ke-fu')}
                 </Button>
 
+                <Button
+                  fontSize="xs"
+                  flex={1}
+                  mx={5}
+                  bg="white"
+                  color="gray600"
+                  borderColor="brand500"
+                  borderWidth={1}
+                  rounded={3}
+                  onPress={() => connectKefu(orderId)}
+                >
+                  立即支付
+                </Button>
+
                 {!finish && hasRider && (
                   <Button
                     fontSize="xs"
@@ -355,7 +377,7 @@ export default function OrderScreen({ navigation }) {
                     {t('lian-xi-qi-shou')}
                   </Button>
                 )}
-                {!finish && (
+                {!finish && isPay && (
                   <Button
                     fontSize="xs"
                     flex={1}

+ 14 - 0
screens/Order/OrderScreen.jsx

@@ -148,6 +148,20 @@ function Item({
           info={info}
         />
         <Flex justify="end" style={styles.btns}>
+          {info.status !== 'UNPAID' && (
+            <Button
+              w={100}
+              fontSize="xs"
+              bg="white"
+              color="gray600"
+              borderColor="brand500"
+              borderWidth={1}
+              rounded={3}
+              onPress={() => goNext('PayOrder')}
+            >
+              去支付
+            </Button>
+          )}
           {finish && !Allfinish ? (
             <Button
               w={100}

+ 17 - 0
screens/Order/model.js

@@ -135,6 +135,23 @@ const OrderModel = (now) => ({
     success('打赏成功');
     return Promise.resolve();
   },
+  payOrder(orderId) {
+    const { loading, warnning, success } = now(Toast);
+    loading();
+    return request
+      .get(`/orderInfo/toCompleted`, {
+        params: {
+          orderId,
+        },
+      })
+      .then(() => {
+        success('提交成功');
+        return Promise.resolve();
+      })
+      .catch((e) => {
+        warnning(e.error);
+      });
+  },
 });
 
 export default OrderModel;

+ 263 - 0
screens/Pay/PayOrderScreen.jsx

@@ -0,0 +1,263 @@
+/* eslint-disable react/jsx-props-no-spreading */
+/* eslint-disable no-underscore-dangle */
+import * as WebBrowser from 'expo-web-browser';
+import * as React from 'react';
+import {
+  StyleSheet,
+  View,
+  Clipboard,
+  Dimensions,
+  Animated,
+  PanResponder,
+  findNodeHandle,
+  UIManager,
+  TouchableOpacity,
+  RefreshControl,
+} from 'react-native';
+import { Div, Button, Image, Text } from 'react-native-magnus';
+import { Appbar, Menu } from 'react-native-paper';
+import Constants from 'expo-constants';
+
+import { Flex } from '@ant-design/react-native';
+import { ScrollView } from 'react-native-gesture-handler';
+
+import { useRequest, useCreation, useMount } from '@umijs/hooks';
+import { useTranslation } from 'react-i18next';
+
+import { useRoute } from '@react-navigation/native';
+import { useAnimation } from 'react-native-animation-hooks';
+import useModel from 'flooks';
+import Toast from '../../flooks/Toast';
+
+import Header from '../Order/Header'; // 头部
+import PayCom from './PayCom';
+
+import OrderModel from '../Order/model';
+
+import { connectKefu } from '../../Utils/TotastUtils';
+import {
+  merchantStatusMap,
+  orderStatusMap,
+  RiderStatusMap,
+  payMap,
+  reasonMap,
+} from '../../Utils/OrderUtils';
+import Time from '../../Utils/TimeUtils';
+
+import MapScreen from '../Map/MapScreen';
+
+export default function PayOrderScreen({ navigation }) {
+  const { t } = useTranslation();
+  const [orderInfo, setorderInfo] = React.useState({
+    merchant: {},
+    orderGoodsSpecs: [],
+  });
+
+  const { payOrder } = useModel(OrderModel, []);
+
+  const { loading, success, warnning, clearLoading } = useModel(Toast, []);
+
+  const route = useRoute();
+  const { params } = route;
+  const { orderId } = params || 0;
+
+  const orderRequest = useRequest(`/orderInfo/get/${orderId}`, {
+    refreshDeps: [orderId],
+    onSuccess: (result) => {
+      setorderInfo(result);
+    },
+  });
+
+  const { merchant, orderGoodsSpecs } = orderInfo;
+
+  return (
+    <Div bg="gray200" w="100%" flex={1}>
+      <Header title="收银台" orderId={orderId} />
+      <ScrollView
+        contentContainerStyle={{ flexGrow: 1, backgroundColor: '#eee' }}
+        refreshControl={
+          <RefreshControl
+            refreshing={orderRequest.loading}
+            onRefresh={orderRequest.run}
+          />
+        }
+      >
+        <Div pt={10} pb={10} px={15}>
+          <View style={[styles.card]}>
+            <Text fontSize="xl">
+              {t('yu-ji')}
+              {new Time(
+                orderInfo.timeOfArrival,
+                'yyyy-MM-DD HH:mm:ss'
+              ).getFormat('HH:mm')}
+              {t('song-da')}
+            </Text>
+          </View>
+          <View style={[styles.card]}>
+            <Div row pb={10}>
+              <Text fontSize="xl" fontWeight="bold">
+                {orderInfo.merShowName}
+              </Text>
+            </Div>
+            <Div>
+              {orderGoodsSpecs.map((item) => {
+                return (
+                  <GoodsItem info={item} goods={item.goods} key={item.id} />
+                );
+              })}
+            </Div>
+            <Flex style={styles.info}>
+              <Flex.Item>
+                <Flex>
+                  <Text fontSize="xs" color="gray300" textAlign="left">
+                    {t('bao-zhuang-fei')}
+                  </Text>
+                  <Text fontSize="xs" color="gray300" textAlign="left">
+                    {t('can-he')}
+                  </Text>
+                </Flex>
+              </Flex.Item>
+              <Text fontSize="xs" color="gray300" textAlign="left">
+                ¥{orderInfo.packingPrice}
+              </Text>
+            </Flex>
+            <Flex style={styles.info}>
+              <Flex.Item>
+                <Text fontSize="xs" color="gray300" textAlign="left">
+                  {t('pei-song-fei-ding-dong-zhuan-song')}
+                </Text>
+              </Flex.Item>
+              <Text fontSize="xs" color="gray300" textAlign="left">
+                ¥{orderInfo.deliveryAmount}
+              </Text>
+            </Flex>
+            <Flex style={styles.info}>
+              <Flex.Item>
+                <Text fontSize="xs" color="gray300" textAlign="left">
+                  {t('man-jian')}
+                </Text>
+              </Flex.Item>
+              <Text fontSize="xs" color="red500" textAlign="left">
+                -¥{orderInfo.fullReduction}
+              </Text>
+            </Flex>
+            {!!orderInfo.firstBuy && (
+              <Flex style={styles.info}>
+                <Flex.Item>
+                  <Text fontSize="xs" color="gray300" textAlign="left">
+                    {t('shou-dan')}
+                  </Text>
+                </Flex.Item>
+                <Text fontSize="xs" color="red500" textAlign="left">
+                  ¥{orderInfo.firstBuy}
+                </Text>
+              </Flex>
+            )}
+
+            <Flex style={styles.info}>
+              <Flex.Item>
+                <Text fontSize="xs" color="gray300" textAlign="left">
+                  {t('hong-bao')}
+                </Text>
+              </Flex.Item>
+              <Text fontSize="xs" color="red500" textAlign="left">
+                -¥{orderInfo.redBag || 0}
+              </Text>
+            </Flex>
+            <Flex style={styles.total} justify="end">
+              <Text size="s1">
+                {t('xiao-ji')} ¥{orderInfo.realAmount}
+              </Text>
+            </Flex>
+          </View>
+        </Div>
+        <Div pt={10} pb={10} px={15}>
+          <Div bg="white" p={15}>
+            <PayCom />
+          </Div>
+
+          <Button
+            block
+            bg="brand500"
+            mt={20}
+            onPress={() => {
+              payOrder(orderId).then(() => {
+                navigation.replace('OrderDetail', { orderId });
+              });
+            }}
+          >
+            立即支付
+          </Button>
+        </Div>
+      </ScrollView>
+    </Div>
+  );
+}
+
+const GoodsItem = ({ info, goods }) => {
+  return (
+    <Div row>
+      <Image w={33} h={33} rounded={3} source={{ uri: goods.img }} />
+      <Div flex={1} ml={10}>
+        <Div row>
+          <Text fontSize="sm" flex={1}>
+            {goods.name}
+          </Text>
+          <Text fontSize="sm">X {info.num}</Text>
+          <Text ml={10}>¥{info.goodsRealPrice}</Text>
+        </Div>
+        <Text fontSize="xs" color="gray400">
+          {info.specification}
+        </Text>
+      </Div>
+    </Div>
+  );
+};
+
+const styles = StyleSheet.create({
+  scroll: {
+    flexGrow: 1,
+  },
+  card: {
+    borderRadius: 3,
+    backgroundColor: '#fff',
+    marginBottom: 5,
+    padding: 15,
+  },
+  item: {
+    paddingVertical: 5,
+  },
+  icon: {
+    width: 33,
+    height: 33,
+    borderRadius: 3,
+  },
+  goodsMain: {
+    marginLeft: 10,
+  },
+  type: {
+    // marginTop:3,
+  },
+  main: {
+    marginTop: 10,
+    paddingVertical: 5,
+    borderColor: '#E5E5E5',
+    borderTopWidth: 1,
+  },
+  info: {
+    marginTop: 10,
+  },
+  total: {
+    paddingTop: 10,
+    marginTop: 10,
+    borderColor: '#E5E5E5',
+    borderTopWidth: 1,
+  },
+  address: {
+    minWidth: 50,
+    marginRight: 30,
+  },
+  info2: {
+    marginTop: 10,
+  },
+});

+ 2 - 2
screens/User/UserScreen.jsx

@@ -32,8 +32,8 @@ export default function UserScreen({ navigation }) {
   }, [nickname]);
 
   const showUser = useCreation(() => {
-    const name = username.substring(4, 7);
-    if (name) {
+    if (username) {
+      const name = username.substring(4, 7);
       return username.replace(name, '****');
     } else {
       return username;