changeCarPageComponent.tsx 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. import { View, Text, ScrollView, Pressable, Alert } from 'react-native';
  2. import React, { useContext, useEffect, useState } from 'react';
  3. import { SafeAreaView } from 'react-native-safe-area-context';
  4. import { router } from 'expo-router';
  5. import { CrossLogoSvg } from '../global/SVG';
  6. import { AuthContext } from '../../context/AuthProvider';
  7. import NormalInput from '../global/normal_input';
  8. import NormalButton from '../global/normal_button';
  9. import { authenticationService } from '../../service/authService';
  10. import * as SecureStore from 'expo-secure-store';
  11. import { chargeStationService } from '../../service/chargeStationService';
  12. const ChangeCarPageComponent = () => {
  13. const { user, setUser } = useContext(AuthContext);
  14. const [token, setToken] = useState<string | null>(null);
  15. const [car, setCar] = useState<string | null>(null);
  16. const [isLoading, setIsLoading] = useState(false);
  17. const [error, setError] = useState<string | null>(null);
  18. useEffect(() => {
  19. const getToken = async () => {
  20. const storedToken = await SecureStore.getItemAsync('accessToken');
  21. setToken(storedToken);
  22. };
  23. getToken();
  24. }, []);
  25. const validateLicensePlate = (licensePlate: string | null): string | null => {
  26. if (!licensePlate || licensePlate.trim() === '') {
  27. return '請輸入車牌號碼';
  28. }
  29. const trimmedPlate = licensePlate.trim();
  30. if (trimmedPlate.length < 2) {
  31. return '車牌號碼至少需要2個字符';
  32. }
  33. if (trimmedPlate.length > 10) {
  34. return '車牌號碼不能超過10個字符';
  35. }
  36. // Check for special characters (allow letters, numbers, hyphen, and spaces)
  37. const validFormat = /^[A-Za-z0-9-\s]+$/;
  38. if (!validFormat.test(trimmedPlate)) {
  39. return '車牌號碼只能包含字母、數字和空格';
  40. }
  41. return null;
  42. };
  43. const saveLicensePlate = async (licensePlate: string | null) => {
  44. const validationError = validateLicensePlate(licensePlate);
  45. if (validationError) {
  46. setError(validationError);
  47. Alert.alert('錯誤', validationError);
  48. return;
  49. }
  50. try {
  51. const response = await chargeStationService.addCar(
  52. licensePlate!,
  53. '1834d087-bfc1-4f90-8f09-805e3d9422b5',
  54. 'f599470d-53a5-4026-99c0-2dab34c77f39',
  55. true
  56. );
  57. if (response === true) {
  58. setError(null);
  59. Alert.alert('成功', '車牌號碼保存成功', [
  60. {
  61. text: 'OK',
  62. onPress: () => router.replace('accountMainPage')
  63. }
  64. ]);
  65. } else {
  66. setError('無法保存車牌號碼');
  67. Alert.alert('錯誤', '無法保存車牌號碼,請稍後再試');
  68. }
  69. } catch (error) {
  70. setError('暫時無法保存車牌號碼');
  71. Alert.alert('錯誤', '暫時無法保存車牌號碼,請稍後再試');
  72. }
  73. };
  74. const handleChangeCar = async () => {
  75. if (!name) {
  76. setError('請輸入新的車牌號碼');
  77. return;
  78. }
  79. if (!token) {
  80. setError('未找到有效的登錄令牌,請重新登錄');
  81. return;
  82. }
  83. setError(null);
  84. setIsLoading(true);
  85. try {
  86. const success = await authenticationService.changeName(name, token);
  87. if (success) {
  88. if (user) {
  89. setUser({
  90. ...user,
  91. nickname: name
  92. });
  93. }
  94. router.replace('accountMainPage');
  95. } else {
  96. setError('更新暱稱失敗,請稍後再試');
  97. }
  98. } catch (error) {
  99. console.error('Error changing name:', error);
  100. setError('發生錯誤,請稍後再試');
  101. } finally {
  102. setIsLoading(false);
  103. }
  104. };
  105. return (
  106. <SafeAreaView className="flex-1 bg-white" edges={['top', 'right', 'left']}>
  107. <ScrollView className="flex-1 mx-[5%]">
  108. <View style={{ marginTop: 25 }}>
  109. <Pressable
  110. onPress={() => {
  111. if (router.canGoBack()) {
  112. router.back();
  113. } else {
  114. router.replace('/accountMainPage');
  115. }
  116. }}
  117. >
  118. <CrossLogoSvg />
  119. </Pressable>
  120. <Text style={{ fontSize: 45, marginVertical: 25 }}>更改車牌號碼</Text>
  121. <Text className="text-xl ">請輸入新車牌號碼</Text>
  122. <View className="py-2">
  123. <NormalInput
  124. placeholder={'請輸入新車牌號碼'}
  125. onChangeText={(t) => {
  126. setCar(t);
  127. setError(null); // Clear error when user types
  128. }}
  129. editable={!isLoading}
  130. />
  131. {error && <Text className="text-red-500 mt-1">{error}</Text>}
  132. </View>
  133. <NormalButton
  134. title={<Text className="text-white">{isLoading ? '更改中...' : '確認'}</Text>}
  135. disabled={isLoading}
  136. onPress={() => saveLicensePlate(car)}
  137. />
  138. </View>
  139. </ScrollView>
  140. </SafeAreaView>
  141. );
  142. };
  143. export default ChangeCarPageComponent;