Compare commits

...

14 Commits

Author SHA1 Message Date
Mekan1206
ceabc0079c Refactor ProfileScreen to improve account deletion UI; update styles for danger items and remove alert for app information. 2025-09-17 18:11:30 +05:00
Mekan1206
9b26ddaa37 Add PDF download button to CardRequisiteOrderDetailsScreen for enhanced functionality. 2025-09-17 15:05:31 +05:00
Mekan1206
0d12a01812 Refactor multiple screens to replace SafeAreaView imports with react-native-safe-area-context, enhancing layout consistency across the application. 2025-09-17 14:55:18 +05:00
388d5e9a82 Remove card year validation logic from EditProfileModal for simplification and future refactoring. 2025-09-11 16:28:20 +05:00
99bdb01644 Update VerificationScreen to use react-native-confirmation-code-field for enhanced OTP input; add bundleIdentifier in app.json and include new dependency in package.json and package-lock.json. 2025-09-11 15:37:38 +05:00
a41851dfcc Refactor VerificationScreen to include KeyboardAvoidingView for improved keyboard handling; update text in CardTransactionOrderDetailsScreen for better localization. 2025-09-11 15:28:40 +05:00
Mekan1206
27f43a77fd Update app.json to change splash screen background color to white; refactor MainNavigator and screens to utilize dynamic padding with useSafeAreaInsets, enhancing layout consistency across Home, Menu, and Profile screens. 2025-09-11 13:11:19 +05:00
Mekan1206
27f16f3c38 Refactor MenuScreen to use useSafeAreaInsets for dynamic padding, replacing SafeAreaView with View for improved layout handling. 2025-09-11 12:45:47 +05:00
Mekan1206
2eb41db2e5 AAA Refactor app structure to use SafeAreaProvider, update StatusBar configuration, and enhance tab navigator styles. Add expo-system-ui dependency for improved status bar handling. 2025-09-11 12:39:19 +05:00
Mekan1206
61bcb6aa3f Remove dark mode configuration from splash screen settings in app.json 2025-09-11 12:12:56 +05:00
66f5271640 Add expo-splash-screen dependency and configure splash screen settings in app.json 2025-09-11 10:47:38 +05:00
db6a9e2bc0 wip 2025-09-11 10:42:07 +05:00
14db29ab61 wip 2025-09-11 10:40:42 +05:00
5ca3bb4f17 Update .gitignore to include .android and .ios directories for better build management 2025-09-11 10:32:51 +05:00
38 changed files with 456 additions and 131 deletions

2
.gitignore vendored
View File

@@ -38,3 +38,5 @@ yarn-error.*
android/ android/
ios/ ios/
.android/
.ios/

17
App.js
View File

@@ -2,15 +2,18 @@ import React from 'react';
import { AuthProvider } from './src/contexts/AuthContext'; import { AuthProvider } from './src/contexts/AuthContext';
import RootNavigator from './src/navigation/RootNavigator'; import RootNavigator from './src/navigation/RootNavigator';
import { BaseEnumsProvider } from './src/contexts/BaseEnumsContext'; import { BaseEnumsProvider } from './src/contexts/BaseEnumsContext';
import { StatusBar } from 'react-native'; import { StatusBar } from 'expo-status-bar';
import { SafeAreaProvider } from 'react-native-safe-area-context';
export default function App() { export default function App() {
return ( return (
<AuthProvider> <SafeAreaProvider>
<BaseEnumsProvider> <AuthProvider>
<StatusBar barStyle="dark-content" backgroundColor="#fff"/> <BaseEnumsProvider>
<RootNavigator /> <StatusBar style="dark" />
</BaseEnumsProvider> <RootNavigator />
</AuthProvider> </BaseEnumsProvider>
</AuthProvider>
</SafeAreaProvider>
); );
} }

View File

@@ -10,10 +10,14 @@
"splash": { "splash": {
"image": "./assets/splash-icon.png", "image": "./assets/splash-icon.png",
"resizeMode": "contain", "resizeMode": "contain",
"backgroundColor": "#17b69b" "backgroundColor": "#ffffff"
}, },
"ios": { "ios": {
"supportsTablet": true "supportsTablet": true,
"statusBar": {
"barStyle": "dark-content"
},
"bundleIdentifier": "com.nurmuhammet.ali.tbbankonline"
}, },
"android": { "android": {
"adaptiveIcon": { "adaptiveIcon": {
@@ -21,7 +25,11 @@
"backgroundColor": "#17b69b" "backgroundColor": "#17b69b"
}, },
"edgeToEdgeEnabled": true, "edgeToEdgeEnabled": true,
"package": "com.nurmuhammet.ali.tbbankonline" "package": "com.nurmuhammet.ali.tbbankonline",
"statusBar": {
"barStyle": "dark-content",
"backgroundColor": "#ffffff"
}
}, },
"web": { "web": {
"favicon": "./assets/favicon.png" "favicon": "./assets/favicon.png"
@@ -36,15 +44,12 @@
[ [
"expo-splash-screen", "expo-splash-screen",
{ {
"backgroundColor": "#17b69b", "backgroundColor": "#ffffff",
"image": "./assets/splash-icon.png", "image": "./assets/splash-icon.png",
"dark": {
"image": "./assets/splash-icon.png",
"backgroundColor": "#232323"
},
"imageWidth": 200 "imageWidth": 200
} }
] ],
"expo-system-ui"
] ]
} }
} }

View File

Before

Width:  |  Height:  |  Size: 156 KiB

After

Width:  |  Height:  |  Size: 156 KiB

226
package-lock.json generated
View File

@@ -18,9 +18,12 @@
"expo": "53.0.22", "expo": "53.0.22",
"expo-font": "~13.3.2", "expo-font": "~13.3.2",
"expo-image-picker": "~16.1.4", "expo-image-picker": "~16.1.4",
"expo-splash-screen": "^31.0.8",
"expo-status-bar": "~2.2.3", "expo-status-bar": "~2.2.3",
"expo-system-ui": "~5.0.11",
"react": "19.0.0", "react": "19.0.0",
"react-native": "0.79.5", "react-native": "0.79.5",
"react-native-confirmation-code-field": "^8.0.1",
"react-native-gesture-handler": "~2.24.0", "react-native-gesture-handler": "~2.24.0",
"react-native-modal-datetime-picker": "^15.0.1", "react-native-modal-datetime-picker": "^15.0.1",
"react-native-safe-area-context": "5.4.0", "react-native-safe-area-context": "5.4.0",
@@ -4191,6 +4194,164 @@
"invariant": "^2.2.4" "invariant": "^2.2.4"
} }
}, },
"node_modules/expo-splash-screen": {
"version": "31.0.8",
"resolved": "https://registry.npmjs.org/expo-splash-screen/-/expo-splash-screen-31.0.8.tgz",
"integrity": "sha512-NNgNhrqkuJAt98k9CKJ9JeCInv5g/xRhe1fWbciQrqTQWPXeIGg3tn5T5HNFwfRD1aKr2uOs1Ctly8rE6i5vtQ==",
"dependencies": {
"@expo/prebuild-config": "^10.0.8"
},
"peerDependencies": {
"expo": "*"
}
},
"node_modules/expo-splash-screen/node_modules/@babel/code-frame": {
"version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
"integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
"dependencies": {
"@babel/highlight": "^7.10.4"
}
},
"node_modules/expo-splash-screen/node_modules/@expo/config": {
"version": "12.0.8",
"resolved": "https://registry.npmjs.org/@expo/config/-/config-12.0.8.tgz",
"integrity": "sha512-yFadXa5Cmja57EVOSyEYV1hF7kCaSbPnd1twx0MfvTr1Yj2abIbrEu2MUZqcvElNQOtgADnLRP0YJiuEdgoO5A==",
"dependencies": {
"@babel/code-frame": "~7.10.4",
"@expo/config-plugins": "~54.0.0",
"@expo/config-types": "^54.0.7",
"@expo/json-file": "^10.0.7",
"deepmerge": "^4.3.1",
"getenv": "^2.0.0",
"glob": "^10.4.2",
"require-from-string": "^2.0.2",
"resolve-from": "^5.0.0",
"resolve-workspace-root": "^2.0.0",
"semver": "^7.6.0",
"slugify": "^1.3.4",
"sucrase": "3.35.0"
}
},
"node_modules/expo-splash-screen/node_modules/@expo/config-plugins": {
"version": "11.0.7",
"resolved": "https://registry.npmjs.org/@expo/config-plugins/-/config-plugins-11.0.7.tgz",
"integrity": "sha512-kak5m27fPTzwmzYPbaYL6I67OFnhdrzV0h5JcoljrEC7uM3R18V/RrnEMzv10XQk+s+qmPfMkr0aK9YYgGqR6g==",
"dependencies": {
"@expo/config-types": "^54.0.7",
"@expo/json-file": "~10.0.6",
"@expo/plist": "^0.4.6",
"@expo/sdk-runtime-versions": "^1.0.0",
"chalk": "^4.1.2",
"debug": "^4.3.5",
"getenv": "^2.0.0",
"glob": "^10.4.2",
"resolve-from": "^5.0.0",
"semver": "^7.5.4",
"slash": "^3.0.0",
"slugify": "^1.6.6",
"xcode": "^3.0.1",
"xml2js": "0.6.0"
}
},
"node_modules/expo-splash-screen/node_modules/@expo/config-types": {
"version": "54.0.7",
"resolved": "https://registry.npmjs.org/@expo/config-types/-/config-types-54.0.7.tgz",
"integrity": "sha512-f0UehgPd2gUqUtQ6euHAL6MqTT/A07r847Ztw2yZYWTUr0hRZr4nCP4U+lr8/pPtsHQYMKoPB1mOeAaTO25ruw=="
},
"node_modules/expo-splash-screen/node_modules/@expo/config/node_modules/@expo/config-plugins": {
"version": "54.0.0",
"resolved": "https://registry.npmjs.org/@expo/config-plugins/-/config-plugins-54.0.0.tgz",
"integrity": "sha512-b2yFNKwaiHjDfh7K+zhMvRKA09gdaP/raqIzB112qeacVJaT66vka8m6cffYbbiXMe1srqofSJvyvr+g3H6+nA==",
"dependencies": {
"@expo/config-types": "^54.0.7",
"@expo/json-file": "~10.0.6",
"@expo/plist": "^0.4.6",
"@expo/sdk-runtime-versions": "^1.0.0",
"chalk": "^4.1.2",
"debug": "^4.3.5",
"getenv": "^2.0.0",
"glob": "^10.4.2",
"resolve-from": "^5.0.0",
"semver": "^7.5.4",
"slash": "^3.0.0",
"slugify": "^1.6.6",
"xcode": "^3.0.1",
"xml2js": "0.6.0"
}
},
"node_modules/expo-splash-screen/node_modules/@expo/image-utils": {
"version": "0.8.7",
"resolved": "https://registry.npmjs.org/@expo/image-utils/-/image-utils-0.8.7.tgz",
"integrity": "sha512-SXOww4Wq3RVXLyOaXiCCuQFguCDh8mmaHBv54h/R29wGl4jRY8GEyQEx8SypV/iHt1FbzsU/X3Qbcd9afm2W2w==",
"dependencies": {
"@expo/spawn-async": "^1.7.2",
"chalk": "^4.0.0",
"getenv": "^2.0.0",
"jimp-compact": "0.16.1",
"parse-png": "^2.1.0",
"resolve-from": "^5.0.0",
"resolve-global": "^1.0.0",
"semver": "^7.6.0",
"temp-dir": "~2.0.0",
"unique-string": "~2.0.0"
}
},
"node_modules/expo-splash-screen/node_modules/@expo/json-file": {
"version": "10.0.7",
"resolved": "https://registry.npmjs.org/@expo/json-file/-/json-file-10.0.7.tgz",
"integrity": "sha512-z2OTC0XNO6riZu98EjdNHC05l51ySeTto6GP7oSQrCvQgG9ARBwD1YvMQaVZ9wU7p/4LzSf1O7tckL3B45fPpw==",
"dependencies": {
"@babel/code-frame": "~7.10.4",
"json5": "^2.2.3"
}
},
"node_modules/expo-splash-screen/node_modules/@expo/plist": {
"version": "0.4.6",
"resolved": "https://registry.npmjs.org/@expo/plist/-/plist-0.4.6.tgz",
"integrity": "sha512-6yklhtUWohs1rBSC8dGyBBpElEbosjXN0zJN/+1/B121n7pPWvd9y/UGJm+2x7b81VnW3AHmWVnbU/u0INQsqA==",
"dependencies": {
"@xmldom/xmldom": "^0.8.8",
"base64-js": "^1.2.3",
"xmlbuilder": "^15.1.1"
}
},
"node_modules/expo-splash-screen/node_modules/@expo/prebuild-config": {
"version": "10.0.8",
"resolved": "https://registry.npmjs.org/@expo/prebuild-config/-/prebuild-config-10.0.8.tgz",
"integrity": "sha512-9ibcRuWngmMnoYe25XXfZEWcPCdx6LiyzqHqpojsvHBI+sMsyZPf4b/5y/zmeJy3PKjR4LSzMRonEitTfUSL/A==",
"dependencies": {
"@expo/config": "~12.0.7",
"@expo/config-plugins": "~11.0.7",
"@expo/config-types": "^54.0.7",
"@expo/image-utils": "^0.8.6",
"@expo/json-file": "^10.0.6",
"@react-native/normalize-colors": "0.81.1",
"debug": "^4.3.1",
"resolve-from": "^5.0.0",
"semver": "^7.6.0",
"xml2js": "0.6.0"
},
"peerDependencies": {
"expo": "*"
}
},
"node_modules/expo-splash-screen/node_modules/@react-native/normalize-colors": {
"version": "0.81.1",
"resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.81.1.tgz",
"integrity": "sha512-TsaeZlE8OYFy3PSWc+1VBmAzI2T3kInzqxmwXoGU4w1d4XFkQFg271Ja9GmDi9cqV3CnBfqoF9VPwRxVlc/l5g=="
},
"node_modules/expo-splash-screen/node_modules/semver": {
"version": "7.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
"integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/expo-status-bar": { "node_modules/expo-status-bar": {
"version": "2.2.3", "version": "2.2.3",
"resolved": "https://registry.npmjs.org/expo-status-bar/-/expo-status-bar-2.2.3.tgz", "resolved": "https://registry.npmjs.org/expo-status-bar/-/expo-status-bar-2.2.3.tgz",
@@ -4204,6 +4365,32 @@
"react-native": "*" "react-native": "*"
} }
}, },
"node_modules/expo-system-ui": {
"version": "5.0.11",
"resolved": "https://registry.npmjs.org/expo-system-ui/-/expo-system-ui-5.0.11.tgz",
"integrity": "sha512-PG5VdaG5cwBe1Rj02mJdnsihKl9Iw/w/a6+qh2mH3f2K/IvQ+Hf7aG2kavSADtkGNCNj7CEIg7Rn4DQz/SE5rQ==",
"license": "MIT",
"dependencies": {
"@react-native/normalize-colors": "0.79.6",
"debug": "^4.3.2"
},
"peerDependencies": {
"expo": "*",
"react-native": "*",
"react-native-web": "*"
},
"peerDependenciesMeta": {
"react-native-web": {
"optional": true
}
}
},
"node_modules/expo-system-ui/node_modules/@react-native/normalize-colors": {
"version": "0.79.6",
"resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.79.6.tgz",
"integrity": "sha512-0v2/ruY7eeKun4BeKu+GcfO+SHBdl0LJn4ZFzTzjHdWES0Cn+ONqKljYaIv8p9MV2Hx/kcdEvbY4lWI34jC/mQ==",
"license": "MIT"
},
"node_modules/exponential-backoff": { "node_modules/exponential-backoff": {
"version": "3.1.2", "version": "3.1.2",
"resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.2.tgz", "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.2.tgz",
@@ -4409,6 +4596,17 @@
"url": "https://github.com/sponsors/isaacs" "url": "https://github.com/sponsors/isaacs"
} }
}, },
"node_modules/global-dirs": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz",
"integrity": "sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg==",
"dependencies": {
"ini": "^1.3.4"
},
"engines": {
"node": ">=4"
}
},
"node_modules/graceful-fs": { "node_modules/graceful-fs": {
"version": "4.2.11", "version": "4.2.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
@@ -6536,6 +6734,23 @@
} }
} }
}, },
"node_modules/react-native-confirmation-code-field": {
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/react-native-confirmation-code-field/-/react-native-confirmation-code-field-8.0.1.tgz",
"integrity": "sha512-pwrhQtspFEp0y/gxZRp8hrra+UjAYfwAsW5Sn3yYtdUZVyRjAZPBnUb3rOc+z5L5o2ml03z5P3uvTK0yQwXsmA==",
"peerDependencies": {
"react": ">=16.4.0",
"react-native": ">=0.64.0"
},
"peerDependenciesMeta": {
"react": {
"optional": true
},
"react-native": {
"optional": true
}
}
},
"node_modules/react-native-edge-to-edge": { "node_modules/react-native-edge-to-edge": {
"version": "1.6.0", "version": "1.6.0",
"resolved": "https://registry.npmjs.org/react-native-edge-to-edge/-/react-native-edge-to-edge-1.6.0.tgz", "resolved": "https://registry.npmjs.org/react-native-edge-to-edge/-/react-native-edge-to-edge-1.6.0.tgz",
@@ -6855,6 +7070,17 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/resolve-global": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/resolve-global/-/resolve-global-1.0.0.tgz",
"integrity": "sha512-zFa12V4OLtT5XUX/Q4VLvTfBf+Ok0SPc1FNGM/z9ctUdiU618qwKpWnd0CHs3+RqROfyEg/DhuHbMWYqcgljEw==",
"dependencies": {
"global-dirs": "^0.1.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/resolve-workspace-root": { "node_modules/resolve-workspace-root": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/resolve-workspace-root/-/resolve-workspace-root-2.0.0.tgz", "resolved": "https://registry.npmjs.org/resolve-workspace-root/-/resolve-workspace-root-2.0.0.tgz",

View File

@@ -17,17 +17,20 @@
"@react-navigation/native": "^7.1.14", "@react-navigation/native": "^7.1.14",
"@react-navigation/stack": "^7.4.2", "@react-navigation/stack": "^7.4.2",
"expo": "53.0.22", "expo": "53.0.22",
"expo-font": "~13.3.2",
"expo-image-picker": "~16.1.4", "expo-image-picker": "~16.1.4",
"expo-splash-screen": "^31.0.8",
"expo-status-bar": "~2.2.3", "expo-status-bar": "~2.2.3",
"expo-system-ui": "~5.0.11",
"react": "19.0.0", "react": "19.0.0",
"react-native": "0.79.5", "react-native": "0.79.5",
"react-native-confirmation-code-field": "^8.0.1",
"react-native-gesture-handler": "~2.24.0",
"react-native-modal-datetime-picker": "^15.0.1", "react-native-modal-datetime-picker": "^15.0.1",
"react-native-safe-area-context": "5.4.0", "react-native-safe-area-context": "5.4.0",
"react-native-screens": "^4.11.1", "react-native-screens": "^4.11.1",
"react-native-svg": "15.11.2", "react-native-svg": "15.11.2",
"react-native-webview": "13.13.5", "react-native-webview": "13.13.5"
"expo-font": "~13.3.2",
"react-native-gesture-handler": "~2.24.0"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.20.0" "@babel/core": "^7.20.0"

View File

@@ -104,13 +104,9 @@ const EditProfileModal = ({
} }
// Card year validation (optional, 4 digits and reasonable year) // Card year validation (optional, 4 digits and reasonable year)
if (formData.card_year) { // if (formData.card_year) {
const year = parseInt(formData.card_year.trim(), 10);
const currentYear = new Date().getFullYear(); // }
if (!/^[0-9]{4}$/.test(formData.card_year.trim()) || year < currentYear - 10 || year > currentYear + 10) {
newErrors.card_year = `Ýyl ${currentYear - 10}-den ${currentYear + 10}-e çenli bolmaly`;
}
}
setErrors(newErrors); setErrors(newErrors);
return Object.keys(newErrors).length === 0; return Object.keys(newErrors).length === 0;

View File

@@ -2,7 +2,8 @@ import React from 'react';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'; import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { Ionicons } from '@expo/vector-icons'; import { Ionicons } from '@expo/vector-icons';
import { COLORS } from '../constants/colors'; import { COLORS } from '../constants/colors';
import { View, ActivityIndicator, Platform } from 'react-native'; import { View, ActivityIndicator, Platform, OS } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import HomeScreen from '../screens/Main/HomeScreen'; import HomeScreen from '../screens/Main/HomeScreen';
import MenuNavigator from './MenuNavigator'; import MenuNavigator from './MenuNavigator';
@@ -11,6 +12,8 @@ import ProfileScreen from '../screens/Main/ProfileScreen';
const Tab = createBottomTabNavigator(); const Tab = createBottomTabNavigator();
const MainNavigator = () => { const MainNavigator = () => {
const insets = useSafeAreaInsets();
return ( return (
<Tab.Navigator <Tab.Navigator
screenOptions={({ route }) => ({ screenOptions={({ route }) => ({
@@ -34,9 +37,17 @@ const MainNavigator = () => {
backgroundColor: COLORS.white, backgroundColor: COLORS.white,
borderTopWidth: 1, borderTopWidth: 1,
borderTopColor: COLORS.gray[200], borderTopColor: COLORS.gray[200],
paddingBottom: Platform.OS === 'android' ? 16 : 8, paddingBottom: (insets.bottom || 16),
paddingTop: 8, paddingTop: 8,
height: Platform.OS === 'android' ? 96 : 88, height: Platform.OS === 'ios' ? 100 : (82 + (insets.bottom || 16)),
elevation: 8,
shadowColor: COLORS.gray[900],
shadowOffset: {
width: 0,
height: -2,
},
shadowOpacity: 0.1,
shadowRadius: 4,
}, },
tabBarLabelStyle: { tabBarLabelStyle: {
fontSize: 12, fontSize: 12,
@@ -44,7 +55,7 @@ const MainNavigator = () => {
marginTop: 4, marginTop: 4,
}, },
tabBarItemStyle: { tabBarItemStyle: {
paddingVertical: 4, paddingVertical: 2,
}, },
})} })}
> >

View File

@@ -3,7 +3,6 @@ import {
View, View,
Text, Text,
StyleSheet, StyleSheet,
SafeAreaView,
KeyboardAvoidingView, KeyboardAvoidingView,
ScrollView, ScrollView,
Platform, Platform,
@@ -12,6 +11,7 @@ import {
TouchableWithoutFeedback, TouchableWithoutFeedback,
Keyboard, Keyboard,
} from 'react-native'; } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { StatusBar } from 'expo-status-bar'; import { StatusBar } from 'expo-status-bar';
import { useAuth } from '../../contexts/AuthContext'; import { useAuth } from '../../contexts/AuthContext';
import Button from '../../components/Button'; import Button from '../../components/Button';

View File

@@ -3,7 +3,6 @@ import {
View, View,
Text, Text,
StyleSheet, StyleSheet,
SafeAreaView,
KeyboardAvoidingView, KeyboardAvoidingView,
ScrollView, ScrollView,
Platform, Platform,
@@ -11,6 +10,7 @@ import {
TouchableWithoutFeedback, TouchableWithoutFeedback,
Keyboard, Keyboard,
} from 'react-native'; } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { StatusBar } from 'expo-status-bar'; import { StatusBar } from 'expo-status-bar';
import { useAuth } from '../../contexts/AuthContext'; import { useAuth } from '../../contexts/AuthContext';
import Button from '../../components/Button'; import Button from '../../components/Button';

View File

@@ -3,27 +3,40 @@ import {
View, View,
Text, Text,
StyleSheet, StyleSheet,
SafeAreaView,
Alert, Alert,
TouchableOpacity, TouchableOpacity,
TouchableWithoutFeedback, TouchableWithoutFeedback,
Keyboard, Keyboard,
BackHandler, BackHandler,
Platform, Platform,
KeyboardAvoidingView,
} from 'react-native'; } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { StatusBar } from 'expo-status-bar'; import { StatusBar } from 'expo-status-bar';
import { useFocusEffect } from '@react-navigation/native'; import { useFocusEffect } from '@react-navigation/native';
import { useAuth } from '../../contexts/AuthContext'; import { useAuth } from '../../contexts/AuthContext';
import Button from '../../components/Button'; import Button from '../../components/Button';
import Input from '../../components/Input'; import {
CodeField,
Cursor,
useBlurOnFulfill,
useClearByFocusCell,
} from 'react-native-confirmation-code-field';
import { COLORS } from '../../constants/colors'; import { COLORS } from '../../constants/colors';
const CELL_COUNT = 6;
const VerificationScreen = ({ navigation }) => { const VerificationScreen = ({ navigation }) => {
const [code, setCode] = useState(''); const [code, setCode] = useState('');
const [countdown, setCountdown] = useState(60); const [countdown, setCountdown] = useState(60);
const [canResend, setCanResend] = useState(false); const [canResend, setCanResend] = useState(false);
const { verify, isLoading, pendingVerification, clearPendingVerification } = useAuth(); const { verify, isLoading, pendingVerification, clearPendingVerification } = useAuth();
const countdownRef = useRef(null); const countdownRef = useRef(null);
const ref = useBlurOnFulfill({ value: code, cellCount: CELL_COUNT });
const [props, getCellOnLayoutHandler] = useClearByFocusCell({
value: code,
setValue: setCode,
});
useEffect(() => { useEffect(() => {
if (!pendingVerification) { if (!pendingVerification) {
@@ -73,18 +86,18 @@ const VerificationScreen = ({ navigation }) => {
}, 1000); }, 1000);
}; };
const handleVerify = async () => { const handleVerify = async (filledCode) => {
if (!code.trim()) { if (!filledCode.trim()) {
Alert.alert('Ýalňyşlyk', 'Tassyklama koduny giriziň'); Alert.alert('Ýalňyşlyk', 'Tassyklama koduny giriziň');
return; return;
} }
if (!/^\d{6}$/.test(code.trim())) { if (!/^\d{6}$/.test(filledCode.trim())) {
Alert.alert('Ýalňyşlyk', 'Tassyklama kody 6 sanly bolmaly'); Alert.alert('Ýalňyşlyk', 'Tassyklama kody 6 sanly bolmaly');
return; return;
} }
const result = await verify(code.trim()); const result = await verify(filledCode.trim());
if (result.success) { if (result.success) {
// Navigation will be handled by AuthContext // Navigation will be handled by AuthContext
@@ -93,6 +106,8 @@ const VerificationScreen = ({ navigation }) => {
} }
}; };
const handleVerifyWrapper = () => handleVerify(code);
const handleResendCode = async () => { const handleResendCode = async () => {
if (!canResend) return; if (!canResend) return;
@@ -134,54 +149,66 @@ const VerificationScreen = ({ navigation }) => {
</TouchableOpacity> </TouchableOpacity>
</View> </View>
<TouchableWithoutFeedback onPress={Keyboard.dismiss}> <KeyboardAvoidingView
<View style={styles.content}> style={{ flex: 1 }}
<View style={styles.logoContainer}> behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
<View style={styles.verificationIcon}> >
<Text style={styles.verificationIconText}></Text> <TouchableWithoutFeedback onPress={Keyboard.dismiss}>
<View style={styles.content}>
<View style={styles.logoContainer}>
<View style={styles.verificationIcon}>
<Text style={styles.verificationIconText}></Text>
</View>
<Text style={styles.title}>Tassyklama</Text>
<Text style={styles.subtitle}>
{formatPhoneNumber(pendingVerification.phone)} belgisine iberilen
6 sanly tassyklama koduny giriziň
</Text>
</View> </View>
<Text style={styles.title}>Tassyklama</Text>
<Text style={styles.subtitle}>
{formatPhoneNumber(pendingVerification.phone)} belgisine iberilen
6 sanly tassyklama koduny giriziň
</Text>
</View>
<View style={styles.formContainer}> <View style={styles.formContainer}>
<Input <CodeField
label="Tassyklama kody" ref={ref}
value={code} {...props}
onChangeText={setCode} value={code}
placeholder="123456" onChangeText={setCode}
keyboardType="numeric" cellCount={CELL_COUNT}
maxLength={6} rootStyle={styles.otpContainer}
style={styles.codeInput} keyboardType="number-pad"
textAlign="center" textContentType="oneTimeCode"
returnKeyType="done" renderCell={({ index, symbol, isFocused }) => (
onSubmitEditing={handleVerify} <Text
/> key={index}
style={[styles.otpInput, isFocused && styles.otpInputHighlight]}
onLayout={getCellOnLayoutHandler(index)}>
{symbol || (isFocused ? <Cursor/> : null)}
</Text>
)}
onSubmitEditing={handleVerifyWrapper}
/>
<Button <Button
title="Tassykla" title="Tassykla"
onPress={handleVerify} onPress={handleVerifyWrapper}
loading={isLoading} loading={isLoading}
style={styles.verifyButton} style={styles.verifyButton}
/> />
<View style={styles.resendContainer}> <View style={styles.resendContainer}>
{canResend ? ( {canResend ? (
<TouchableOpacity onPress={handleResendCode}> <TouchableOpacity onPress={handleResendCode}>
<Text style={styles.resendText}>Kodu gaýtadan iber</Text> <Text style={styles.resendText}>Kodu gaýtadan iber</Text>
</TouchableOpacity> </TouchableOpacity>
) : ( ) : (
<Text style={styles.countdownText}> <Text style={styles.countdownText}>
Gaýtadan ibermek üçin {countdown} sekunt garaşyň Gaýtadan ibermek üçin {countdown} sekunt garaşyň
</Text> </Text>
)} )}
</View>
</View> </View>
</View> </View>
</View> </TouchableWithoutFeedback>
</TouchableWithoutFeedback> </KeyboardAvoidingView>
</SafeAreaView> </SafeAreaView>
); );
}; };
@@ -251,10 +278,25 @@ const styles = StyleSheet.create({
formContainer: { formContainer: {
alignItems: 'center', alignItems: 'center',
}, },
codeInput: { otpContainer: {
width: '100%', width: '90%',
marginBottom: 32, marginBottom: 32,
}, },
otpInput: {
width: 45,
height: 60,
lineHeight: 58,
borderWidth: 1,
borderRadius: 12,
borderColor: COLORS.gray[300],
color: COLORS.textPrimary,
fontSize: 24,
fontWeight: 'bold',
textAlign: 'center',
},
otpInputHighlight: {
borderColor: COLORS.primary,
},
verifyButton: { verifyButton: {
width: '100%', width: '100%',
marginBottom: 32, marginBottom: 32,

View File

@@ -1,5 +1,6 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { View, Text, StyleSheet, ActivityIndicator, TouchableOpacity, Alert, ScrollView, SafeAreaView, Modal } from 'react-native'; import { View, Text, StyleSheet, ActivityIndicator, TouchableOpacity, Alert, ScrollView, Modal } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { Ionicons } from '@expo/vector-icons'; import { Ionicons } from '@expo/vector-icons';
import { useNavigation, useRoute } from '@react-navigation/native'; import { useNavigation, useRoute } from '@react-navigation/native';
import apiService from '../../services/apiService'; import apiService from '../../services/apiService';

View File

@@ -1,5 +1,6 @@
import React, { useState, useCallback } from 'react'; import React, { useState, useCallback } from 'react';
import { View, Text, StyleSheet, FlatList, ActivityIndicator, TouchableOpacity, RefreshControl, SafeAreaView } from 'react-native'; import { View, Text, StyleSheet, FlatList, ActivityIndicator, TouchableOpacity, RefreshControl } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { Ionicons } from '@expo/vector-icons'; import { Ionicons } from '@expo/vector-icons';
import { useNavigation, useFocusEffect } from '@react-navigation/native'; import { useNavigation, useFocusEffect } from '@react-navigation/native';
import apiService from '../../services/apiService'; import apiService from '../../services/apiService';

View File

@@ -1,5 +1,6 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { View, Text, StyleSheet, ActivityIndicator, TouchableOpacity, ScrollView, SafeAreaView, Image, Alert, Linking } from 'react-native'; import { View, Text, StyleSheet, ActivityIndicator, TouchableOpacity, ScrollView, Image, Alert, Linking } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { Ionicons } from '@expo/vector-icons'; import { Ionicons } from '@expo/vector-icons';
import { useNavigation, useRoute } from '@react-navigation/native'; import { useNavigation, useRoute } from '@react-navigation/native';
import { StatusBar } from 'expo-status-bar'; import { StatusBar } from 'expo-status-bar';

View File

@@ -1,5 +1,6 @@
import React, { useCallback, useState } from 'react'; import React, { useCallback, useState } from 'react';
import { View, Text, StyleSheet, FlatList, TouchableOpacity, ActivityIndicator, RefreshControl, SafeAreaView } from 'react-native'; import { View, Text, StyleSheet, FlatList, TouchableOpacity, ActivityIndicator, RefreshControl } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { Ionicons } from '@expo/vector-icons'; import { Ionicons } from '@expo/vector-icons';
import { useNavigation, useFocusEffect } from '@react-navigation/native'; import { useNavigation, useFocusEffect } from '@react-navigation/native';
import { StatusBar } from 'expo-status-bar'; import { StatusBar } from 'expo-status-bar';

View File

@@ -1,5 +1,6 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { View, Text, StyleSheet, ActivityIndicator, TouchableOpacity, Alert, ScrollView, SafeAreaView, Image, Linking } from 'react-native'; import { View, Text, StyleSheet, ActivityIndicator, TouchableOpacity, Alert, ScrollView, Image, Linking } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { Ionicons } from '@expo/vector-icons'; import { Ionicons } from '@expo/vector-icons';
import { useNavigation, useRoute } from '@react-navigation/native'; import { useNavigation, useRoute } from '@react-navigation/native';
import { StatusBar } from 'expo-status-bar'; import { StatusBar } from 'expo-status-bar';

View File

@@ -1,5 +1,6 @@
import React, { useState, useCallback } from 'react'; import React, { useState, useCallback } from 'react';
import { View, Text, StyleSheet, FlatList, ActivityIndicator, TouchableOpacity, RefreshControl, SafeAreaView } from 'react-native'; import { View, Text, StyleSheet, FlatList, ActivityIndicator, TouchableOpacity, RefreshControl } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { Ionicons } from '@expo/vector-icons'; import { Ionicons } from '@expo/vector-icons';
import { useNavigation, useFocusEffect } from '@react-navigation/native'; import { useNavigation, useFocusEffect } from '@react-navigation/native';
import { StatusBar } from 'expo-status-bar'; import { StatusBar } from 'expo-status-bar';

View File

@@ -1,5 +1,6 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { View, Text, StyleSheet, ActivityIndicator, TouchableOpacity, Alert, ScrollView, SafeAreaView, Image } from 'react-native'; import { View, Text, StyleSheet, ActivityIndicator, TouchableOpacity, Alert, ScrollView, Image } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { Ionicons } from '@expo/vector-icons'; import { Ionicons } from '@expo/vector-icons';
import { useNavigation, useRoute } from '@react-navigation/native'; import { useNavigation, useRoute } from '@react-navigation/native';
import { StatusBar } from 'expo-status-bar'; import { StatusBar } from 'expo-status-bar';
@@ -137,6 +138,9 @@ const CardRequisiteOrderDetailsScreen = () => {
</View> </View>
{/* Actions */} {/* Actions */}
<TouchableOpacity style={styles.actionBtn} onPress={handleDownload}>
<Text style={styles.actionText}>Ýükle (PDF)</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.deleteBtn} onPress={handleDelete}> <TouchableOpacity style={styles.deleteBtn} onPress={handleDelete}>
<Text style={styles.deleteText}>Poz</Text> <Text style={styles.deleteText}>Poz</Text>
</TouchableOpacity> </TouchableOpacity>

View File

@@ -1,5 +1,6 @@
import React, { useState, useCallback, useRef } from 'react'; import React, { useState, useCallback, useRef } from 'react';
import { View, Text, StyleSheet, FlatList, ActivityIndicator, TouchableOpacity, RefreshControl, SafeAreaView } from 'react-native'; import { View, Text, StyleSheet, FlatList, ActivityIndicator, TouchableOpacity, RefreshControl } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { Ionicons } from '@expo/vector-icons'; import { Ionicons } from '@expo/vector-icons';
import { useNavigation, useFocusEffect } from '@react-navigation/native'; import { useNavigation, useFocusEffect } from '@react-navigation/native';
import { StatusBar } from 'expo-status-bar'; import { StatusBar } from 'expo-status-bar';

View File

@@ -1,5 +1,6 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { View, Text, StyleSheet, ActivityIndicator, TouchableOpacity, Alert, ScrollView, SafeAreaView, Modal } from 'react-native'; import { View, Text, StyleSheet, ActivityIndicator, TouchableOpacity, Alert, ScrollView, Modal } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { Ionicons } from '@expo/vector-icons'; import { Ionicons } from '@expo/vector-icons';
import { useNavigation, useRoute } from '@react-navigation/native'; import { useNavigation, useRoute } from '@react-navigation/native';
import apiService from '../../services/apiService'; import apiService from '../../services/apiService';
@@ -93,7 +94,7 @@ const CardTransactionOrderDetailsScreen = () => {
if (!order) { if (!order) {
return ( return (
<View style={styles.centered}> <View style={styles.centered}>
<Text>No data</Text> <Text>Maglumat tapylmady</Text>
</View> </View>
); );
} }

View File

@@ -1,5 +1,6 @@
import React, { useState, useCallback } from 'react'; import React, { useState, useCallback } from 'react';
import { View, Text, StyleSheet, FlatList, ActivityIndicator, TouchableOpacity, RefreshControl, SafeAreaView } from 'react-native'; import { View, Text, StyleSheet, FlatList, ActivityIndicator, TouchableOpacity, RefreshControl } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { Ionicons } from '@expo/vector-icons'; import { Ionicons } from '@expo/vector-icons';
import { useNavigation, useFocusEffect } from '@react-navigation/native'; import { useNavigation, useFocusEffect } from '@react-navigation/native';
import apiService from '../../services/apiService'; import apiService from '../../services/apiService';

View File

@@ -1,5 +1,6 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { View, Text, StyleSheet, TouchableOpacity, ActivityIndicator, Alert, SafeAreaView, ScrollView } from 'react-native'; import { View, Text, StyleSheet, TouchableOpacity, ActivityIndicator, Alert, ScrollView } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { Ionicons } from '@expo/vector-icons'; import { Ionicons } from '@expo/vector-icons';
import { useNavigation } from '@react-navigation/native'; import { useNavigation } from '@react-navigation/native';
import apiService from '../../services/apiService'; import apiService from '../../services/apiService';

View File

@@ -1,5 +1,6 @@
import React, { useState, useEffect, useRef } from 'react'; import React, { useState, useEffect, useRef } from 'react';
import { View, Text, StyleSheet, TouchableOpacity, ActivityIndicator, Alert, SafeAreaView, ScrollView, Modal } from 'react-native'; import { View, Text, StyleSheet, TouchableOpacity, ActivityIndicator, Alert, ScrollView, Modal } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { Ionicons } from '@expo/vector-icons'; import { Ionicons } from '@expo/vector-icons';
import { useNavigation } from '@react-navigation/native'; import { useNavigation } from '@react-navigation/native';
import { StatusBar } from 'expo-status-bar'; import { StatusBar } from 'expo-status-bar';

View File

@@ -1,5 +1,6 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { View, Text, StyleSheet, TouchableOpacity, ActivityIndicator, Alert, SafeAreaView, ScrollView } from 'react-native'; import { View, Text, StyleSheet, TouchableOpacity, ActivityIndicator, Alert, ScrollView } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { Ionicons } from '@expo/vector-icons'; import { Ionicons } from '@expo/vector-icons';
import { useNavigation } from '@react-navigation/native'; import { useNavigation } from '@react-navigation/native';
import { StatusBar } from 'expo-status-bar'; import { StatusBar } from 'expo-status-bar';

View File

@@ -1,5 +1,6 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { View, Text, StyleSheet, TouchableOpacity, ActivityIndicator, Alert, SafeAreaView, ScrollView } from 'react-native'; import { View, Text, StyleSheet, TouchableOpacity, ActivityIndicator, Alert, ScrollView } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { Ionicons } from '@expo/vector-icons'; import { Ionicons } from '@expo/vector-icons';
import { useNavigation } from '@react-navigation/native'; import { useNavigation } from '@react-navigation/native';
import { StatusBar } from 'expo-status-bar'; import { StatusBar } from 'expo-status-bar';

View File

@@ -1,5 +1,6 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { View, Text, StyleSheet, TouchableOpacity, ActivityIndicator, Alert, SafeAreaView, ScrollView } from 'react-native'; import { View, Text, StyleSheet, TouchableOpacity, ActivityIndicator, Alert, ScrollView } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { Ionicons } from '@expo/vector-icons'; import { Ionicons } from '@expo/vector-icons';
import { useNavigation } from '@react-navigation/native'; import { useNavigation } from '@react-navigation/native';
import apiService from '../../services/apiService'; import apiService from '../../services/apiService';

View File

@@ -1,5 +1,6 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { Text, StyleSheet, TouchableOpacity, ActivityIndicator, Alert, ScrollView, SafeAreaView, View } from 'react-native'; import { Text, StyleSheet, TouchableOpacity, ActivityIndicator, Alert, ScrollView, View } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { Ionicons } from '@expo/vector-icons'; import { Ionicons } from '@expo/vector-icons';
import { useNavigation } from '@react-navigation/native'; import { useNavigation } from '@react-navigation/native';
import { COLORS } from '../../constants/colors'; import { COLORS } from '../../constants/colors';

View File

@@ -1,5 +1,6 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { Text, StyleSheet, TouchableOpacity, ActivityIndicator, Alert, ScrollView, SafeAreaView } from 'react-native'; import { Text, StyleSheet, TouchableOpacity, ActivityIndicator, Alert, ScrollView } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { Ionicons } from '@expo/vector-icons'; import { Ionicons } from '@expo/vector-icons';
import { useNavigation } from '@react-navigation/native'; import { useNavigation } from '@react-navigation/native';
import { COLORS } from '../../constants/colors'; import { COLORS } from '../../constants/colors';

View File

@@ -1,5 +1,6 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { View, Text, StyleSheet, TouchableOpacity, ActivityIndicator, Alert, SafeAreaView } from 'react-native'; import { View, Text, StyleSheet, TouchableOpacity, ActivityIndicator, Alert } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { Ionicons } from '@expo/vector-icons'; import { Ionicons } from '@expo/vector-icons';
import { useNavigation } from '@react-navigation/native'; import { useNavigation } from '@react-navigation/native';
import apiService from '../../services/apiService'; import apiService from '../../services/apiService';

View File

@@ -1,5 +1,6 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { View, Text, StyleSheet, ActivityIndicator, TouchableOpacity, Alert, ScrollView, SafeAreaView } from 'react-native'; import { View, Text, StyleSheet, ActivityIndicator, TouchableOpacity, Alert, ScrollView } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { Ionicons } from '@expo/vector-icons'; import { Ionicons } from '@expo/vector-icons';
import { useNavigation, useRoute } from '@react-navigation/native'; import { useNavigation, useRoute } from '@react-navigation/native';
import apiService from '../../services/apiService'; import apiService from '../../services/apiService';

View File

@@ -1,5 +1,6 @@
import React, { useState, useCallback } from 'react'; import React, { useState, useCallback } from 'react';
import { View, Text, StyleSheet, FlatList, ActivityIndicator, TouchableOpacity, RefreshControl, SafeAreaView, Alert } from 'react-native'; import { View, Text, StyleSheet, FlatList, ActivityIndicator, TouchableOpacity, RefreshControl, Alert } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { Ionicons } from '@expo/vector-icons'; import { Ionicons } from '@expo/vector-icons';
import { useNavigation, useFocusEffect } from '@react-navigation/native'; import { useNavigation, useFocusEffect } from '@react-navigation/native';
import apiService from '../../services/apiService'; import apiService from '../../services/apiService';

View File

@@ -1,5 +1,6 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { View, Text, StyleSheet, ActivityIndicator, TouchableOpacity, Alert, ScrollView, SafeAreaView } from 'react-native'; import { View, Text, StyleSheet, ActivityIndicator, TouchableOpacity, Alert, ScrollView } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { Ionicons } from '@expo/vector-icons'; import { Ionicons } from '@expo/vector-icons';
import { useNavigation, useRoute } from '@react-navigation/native'; import { useNavigation, useRoute } from '@react-navigation/native';
import apiService from '../../services/apiService'; import apiService from '../../services/apiService';

View File

@@ -1,5 +1,6 @@
import React, { useState, useCallback } from 'react'; import React, { useState, useCallback } from 'react';
import { View, Text, StyleSheet, FlatList, ActivityIndicator, TouchableOpacity, RefreshControl, SafeAreaView, Alert } from 'react-native'; import { View, Text, StyleSheet, FlatList, ActivityIndicator, TouchableOpacity, RefreshControl, Alert } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { Ionicons } from '@expo/vector-icons'; import { Ionicons } from '@expo/vector-icons';
import { useNavigation, useFocusEffect } from '@react-navigation/native'; import { useNavigation, useFocusEffect } from '@react-navigation/native';
import apiService from '../../services/apiService'; import apiService from '../../services/apiService';

View File

@@ -1,5 +1,6 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { View, Text, StyleSheet, ActivityIndicator, TouchableOpacity, Alert } from 'react-native'; import { View, Text, StyleSheet, ActivityIndicator, TouchableOpacity, Alert } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { Ionicons } from '@expo/vector-icons'; import { Ionicons } from '@expo/vector-icons';
import { useNavigation, useRoute } from '@react-navigation/native'; import { useNavigation, useRoute } from '@react-navigation/native';
import apiService from '../../services/apiService'; import apiService from '../../services/apiService';
@@ -63,7 +64,7 @@ const LoanRemainingOrderDetailsScreen = () => {
} }
return ( return (
<View style={styles.container}> <SafeAreaView style={styles.container}>
<TouchableOpacity style={styles.backBtn} onPress={() => navigation.goBack()}> <TouchableOpacity style={styles.backBtn} onPress={() => navigation.goBack()}>
<Ionicons name="close" size={28} color={COLORS.textPrimary} /> <Ionicons name="close" size={28} color={COLORS.textPrimary} />
</TouchableOpacity> </TouchableOpacity>
@@ -82,7 +83,7 @@ const LoanRemainingOrderDetailsScreen = () => {
<TouchableOpacity style={styles.deleteBtn} onPress={handleDelete}> <TouchableOpacity style={styles.deleteBtn} onPress={handleDelete}>
<Text style={styles.deleteText}>Poz</Text> <Text style={styles.deleteText}>Poz</Text>
</TouchableOpacity> </TouchableOpacity>
</View> </SafeAreaView>
); );
}; };

View File

@@ -1,5 +1,6 @@
import React, { useState, useCallback } from 'react'; import React, { useState, useCallback } from 'react';
import { View, Text, StyleSheet, FlatList, ActivityIndicator, TouchableOpacity, RefreshControl, Modal, ScrollView, Alert, SafeAreaView, Pressable } from 'react-native'; import { View, Text, StyleSheet, FlatList, ActivityIndicator, TouchableOpacity, RefreshControl, Modal, ScrollView, Alert, Pressable } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { Ionicons } from '@expo/vector-icons'; import { Ionicons } from '@expo/vector-icons';
import { useNavigation, useFocusEffect } from '@react-navigation/native'; import { useNavigation, useFocusEffect } from '@react-navigation/native';
import apiService from '../../services/apiService'; import apiService from '../../services/apiService';
@@ -133,7 +134,7 @@ const LoanRemainingOrdersScreen = () => {
renderItem={renderItem} renderItem={renderItem}
contentContainerStyle={orders.length === 0 && styles.emptyContainer} contentContainerStyle={orders.length === 0 && styles.emptyContainer}
refreshControl={<RefreshControl refreshing={refreshing} onRefresh={onRefresh} />} refreshControl={<RefreshControl refreshing={refreshing} onRefresh={onRefresh} />}
ListEmptyComponent={<Text style={styles.emptyText}>No orders yet</Text>} ListEmptyComponent={<Text style={styles.emptyText}>Sargyt ýok</Text>}
/> />
{/* Floating Action Button */} {/* Floating Action Button */}

View File

@@ -3,7 +3,6 @@ import {
View, View,
Text, Text,
StyleSheet, StyleSheet,
SafeAreaView,
ScrollView, ScrollView,
TouchableOpacity, TouchableOpacity,
ActivityIndicator, ActivityIndicator,
@@ -12,6 +11,7 @@ import {
} from 'react-native'; } from 'react-native';
import { StatusBar } from 'expo-status-bar'; import { StatusBar } from 'expo-status-bar';
import { Ionicons } from '@expo/vector-icons'; import { Ionicons } from '@expo/vector-icons';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { useAuth } from '../../contexts/AuthContext'; import { useAuth } from '../../contexts/AuthContext';
import { COLORS } from '../../constants/colors'; import { COLORS } from '../../constants/colors';
import MetricCard from '../../components/MetricCard'; import MetricCard from '../../components/MetricCard';
@@ -103,6 +103,7 @@ const STATIC_TRANSACTIONS = [
const HomeScreen = () => { const HomeScreen = () => {
const { user, logout } = useAuth(); const { user, logout } = useAuth();
const insets = useSafeAreaInsets();
const [metrics, setMetrics] = useState(null); const [metrics, setMetrics] = useState(null);
const [loadingMetrics, setLoadingMetrics] = useState(true); const [loadingMetrics, setLoadingMetrics] = useState(true);
const [cardBalance, setCardBalance] = useState(null); const [cardBalance, setCardBalance] = useState(null);
@@ -244,7 +245,7 @@ const HomeScreen = () => {
}; };
return ( return (
<SafeAreaView style={styles.container}> <View style={styles.container}>
<StatusBar style="dark" /> <StatusBar style="dark" />
<ScrollView <ScrollView
@@ -259,7 +260,7 @@ const HomeScreen = () => {
} }
> >
{/* Header */} {/* Header */}
<View style={styles.header}> <View style={[styles.header, { paddingTop: insets.top + 16 }]}>
<View> <View>
<Text style={styles.greeting}>Salam,</Text> <Text style={styles.greeting}>Salam,</Text>
<Text style={styles.userName}>{user?.name || 'Ulanyjy'}</Text> <Text style={styles.userName}>{user?.name || 'Ulanyjy'}</Text>
@@ -320,7 +321,7 @@ const HomeScreen = () => {
</View> </View>
)} )}
</ScrollView> </ScrollView>
</SafeAreaView> </View>
); );
}; };
@@ -337,7 +338,6 @@ const styles = StyleSheet.create({
justifyContent: 'space-between', justifyContent: 'space-between',
alignItems: 'center', alignItems: 'center',
paddingHorizontal: 24, paddingHorizontal: 24,
paddingTop: 16,
paddingBottom: 24, paddingBottom: 24,
backgroundColor: COLORS.white, backgroundColor: COLORS.white,
marginBottom: 16, marginBottom: 16,

View File

@@ -4,16 +4,17 @@ import {
View, View,
Text, Text,
StyleSheet, StyleSheet,
SafeAreaView,
ScrollView, ScrollView,
TouchableOpacity, TouchableOpacity,
} from 'react-native'; } from 'react-native';
import { StatusBar } from 'expo-status-bar'; import { StatusBar } from 'expo-status-bar';
import { Ionicons } from '@expo/vector-icons'; import { Ionicons } from '@expo/vector-icons';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { COLORS } from '../../constants/colors'; import { COLORS } from '../../constants/colors';
const MenuScreen = () => { const MenuScreen = () => {
const navigation = useNavigation(); const navigation = useNavigation();
const insets = useSafeAreaInsets();
const menuSections = [ const menuSections = [
{ {
@@ -66,10 +67,10 @@ const MenuScreen = () => {
}; };
return ( return (
<SafeAreaView style={styles.container}> <View style={styles.container}>
<StatusBar style="dark" /> <StatusBar style="dark" />
<View style={styles.header}> <View style={[styles.header, { paddingTop: insets.top + 16 }]}>
<Text style={styles.headerTitle}>Hyzmatlar</Text> <Text style={styles.headerTitle}>Hyzmatlar</Text>
</View> </View>
@@ -105,7 +106,7 @@ const MenuScreen = () => {
<View style={styles.bottomSpacing} /> <View style={styles.bottomSpacing} />
</ScrollView> </ScrollView>
</SafeAreaView> </View>
); );
}; };
@@ -116,7 +117,6 @@ const styles = StyleSheet.create({
}, },
header: { header: {
paddingHorizontal: 24, paddingHorizontal: 24,
paddingTop: 16,
paddingBottom: 24, paddingBottom: 24,
borderBottomWidth: 1, borderBottomWidth: 1,
borderBottomColor: COLORS.gray[200], borderBottomColor: COLORS.gray[200],

View File

@@ -3,7 +3,6 @@ import {
View, View,
Text, Text,
StyleSheet, StyleSheet,
SafeAreaView,
ScrollView, ScrollView,
TouchableOpacity, TouchableOpacity,
Alert, Alert,
@@ -13,6 +12,7 @@ import {
} from 'react-native'; } from 'react-native';
import { StatusBar } from 'expo-status-bar'; import { StatusBar } from 'expo-status-bar';
import { Ionicons } from '@expo/vector-icons'; import { Ionicons } from '@expo/vector-icons';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { useAuth } from '../../contexts/AuthContext'; import { useAuth } from '../../contexts/AuthContext';
import apiService from '../../services/apiService'; import apiService from '../../services/apiService';
import EditProfileModal from '../../components/EditProfileModal'; import EditProfileModal from '../../components/EditProfileModal';
@@ -20,6 +20,7 @@ import { COLORS } from '../../constants/colors';
const ProfileScreen = () => { const ProfileScreen = () => {
const { user, logout, fetchUserProfile } = useAuth(); const { user, logout, fetchUserProfile } = useAuth();
const insets = useSafeAreaInsets();
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const [isRefreshing, setIsRefreshing] = useState(false); const [isRefreshing, setIsRefreshing] = useState(false);
const [profileData, setProfileData] = useState(null); const [profileData, setProfileData] = useState(null);
@@ -81,8 +82,8 @@ const ProfileScreen = () => {
items: [ items: [
// { id: 11, title: 'Ulanmak düzgünleri', icon: 'document-text', hasArrow: true }, // { id: 11, title: 'Ulanmak düzgünleri', icon: 'document-text', hasArrow: true },
// { id: 12, title: 'Gizlinlik syýasaty', icon: 'lock-open', hasArrow: true }, // { id: 12, title: 'Gizlinlik syýasaty', icon: 'lock-open', hasArrow: true },
{ id: 13, title: 'Programma barada', icon: 'information-circle', value: 'v1.0.0', hasArrow: true }, { id: 13, title: 'Programma barada', icon: 'information-circle', value: 'v1.0.0', hasArrow: false },
{ id: 14, title: 'Hasaby poz', icon: 'trash', hasArrow: false, color: COLORS.red }, { id: 14, title: 'Hasaby poz', icon: 'trash', hasArrow: false, danger: true },
], ],
}, },
]; ];
@@ -105,7 +106,7 @@ const ProfileScreen = () => {
handleSecuritySettings(); handleSecuritySettings();
break; break;
case 13: // About App case 13: // About App
Alert.alert('Üns beriň', 'Programma barada maglumatlar açylýar...'); // Alert.alert('Üns beriň', 'Programma barada maglumatlar açylýar...');
break; break;
case 14: // Delete Account case 14: // Delete Account
handleDeleteAccount(); handleDeleteAccount();
@@ -279,10 +280,10 @@ const ProfileScreen = () => {
const currentUser = profileData || user; const currentUser = profileData || user;
return ( return (
<SafeAreaView style={styles.container}> <View style={styles.container}>
<StatusBar style="dark" /> <StatusBar style="dark" />
<View style={styles.header}> <View style={[styles.header, { paddingTop: insets.top + 16 }]}>
<Text style={styles.headerTitle}>Profil</Text> <Text style={styles.headerTitle}>Profil</Text>
</View> </View>
@@ -336,16 +337,16 @@ const ProfileScreen = () => {
> >
<View style={styles.profileItemLeft}> <View style={styles.profileItemLeft}>
<View style={styles.profileItemIcon}> <View style={styles.profileItemIcon}>
<Ionicons name={item.icon} size={20} color={item.color || COLORS.primary} /> <Ionicons name={item.icon} size={20} color={item.danger ? COLORS.error : COLORS.primary} />
</View> </View>
<Text style={styles.profileItemTitle}>{item.title}</Text> <Text style={item.danger ? styles.profileItemTitleDanger : styles.profileItemTitle}>{item.title}</Text>
</View> </View>
<View style={styles.profileItemRight}> <View style={styles.profileItemRight}>
{item.value && ( {item.value && (
<Text style={styles.profileItemValue}>{item.value}</Text> <Text style={item.danger ? styles.profileItemValueDanger : styles.profileItemValue}>{item.value}</Text>
)} )}
{item.hasArrow && ( {item.hasArrow && (
<Ionicons name="chevron-forward" size={16} color={COLORS.gray[400]} /> <Ionicons name="chevron-forward" size={16} color={item.danger ? COLORS.error : COLORS.gray[400]} />
)} )}
</View> </View>
</TouchableOpacity> </TouchableOpacity>
@@ -388,7 +389,7 @@ const ProfileScreen = () => {
initialData={profileData || user} initialData={profileData || user}
isLoading={isUpdatingProfile} isLoading={isUpdatingProfile}
/> />
</SafeAreaView> </View>
); );
}; };
@@ -400,7 +401,6 @@ const styles = StyleSheet.create({
header: { header: {
backgroundColor: COLORS.white, backgroundColor: COLORS.white,
paddingHorizontal: 24, paddingHorizontal: 24,
paddingTop: 16,
paddingBottom: 24, paddingBottom: 24,
borderBottomWidth: 1, borderBottomWidth: 1,
borderBottomColor: COLORS.gray[200], borderBottomColor: COLORS.gray[200],
@@ -550,6 +550,16 @@ const styles = StyleSheet.create({
link: { link: {
color: COLORS.primary, color: COLORS.primary,
}, },
profileItemTitleDanger: {
fontSize: 16,
color: COLORS.error,
fontWeight: 'bold',
},
profileItemValueDanger: {
fontSize: 14,
color: COLORS.error,
fontWeight: 'bold',
},
}); });
export default ProfileScreen; export default ProfileScreen;