Compare commits
3 Commits
a41851dfcc
...
39f63d12aa
| Author | SHA1 | Date | |
|---|---|---|---|
| 39f63d12aa | |||
| 388d5e9a82 | |||
| 99bdb01644 |
32
app.json
32
app.json
@@ -1,54 +1,30 @@
|
|||||||
{
|
{
|
||||||
"expo": {
|
"expo": {
|
||||||
"name": "TBBANK ONLINE",
|
"name": "temp-expo",
|
||||||
"slug": "tbbank-online",
|
"slug": "temp-expo",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"orientation": "portrait",
|
"orientation": "portrait",
|
||||||
"icon": "./assets/icon.png",
|
"icon": "./assets/icon.png",
|
||||||
"userInterfaceStyle": "light",
|
"userInterfaceStyle": "light",
|
||||||
"newArchEnabled": true,
|
|
||||||
"splash": {
|
"splash": {
|
||||||
"image": "./assets/splash-icon.png",
|
"image": "./assets/splash-icon.png",
|
||||||
"resizeMode": "contain",
|
"resizeMode": "contain",
|
||||||
"backgroundColor": "#ffffff"
|
"backgroundColor": "#ffffff"
|
||||||
},
|
},
|
||||||
"ios": {
|
"ios": {
|
||||||
"supportsTablet": true,
|
"supportsTablet": true
|
||||||
"statusBar": {
|
|
||||||
"barStyle": "dark-content"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"android": {
|
"android": {
|
||||||
"adaptiveIcon": {
|
"adaptiveIcon": {
|
||||||
"foregroundImage": "./assets/adaptive-icon.png",
|
"foregroundImage": "./assets/adaptive-icon.png",
|
||||||
"backgroundColor": "#17b69b"
|
|
||||||
},
|
|
||||||
"edgeToEdgeEnabled": true,
|
|
||||||
"package": "com.nurmuhammet.ali.tbbankonline",
|
|
||||||
"statusBar": {
|
|
||||||
"barStyle": "dark-content",
|
|
||||||
"backgroundColor": "#ffffff"
|
"backgroundColor": "#ffffff"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"web": {
|
"web": {
|
||||||
"favicon": "./assets/favicon.png"
|
"favicon": "./assets/favicon.png"
|
||||||
},
|
},
|
||||||
"extra": {
|
|
||||||
"eas": {
|
|
||||||
"projectId": "280bed78-9335-4b73-a686-15a9f726a7ad"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"plugins": [
|
"plugins": [
|
||||||
"expo-font",
|
"@config-plugins/react-native-pdf"
|
||||||
[
|
|
||||||
"expo-splash-screen",
|
|
||||||
{
|
|
||||||
"backgroundColor": "#ffffff",
|
|
||||||
"image": "./assets/splash-icon.png",
|
|
||||||
"imageWidth": 200
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"expo-system-ui"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
141
package-lock.json
generated
141
package-lock.json
generated
@@ -8,6 +8,7 @@
|
|||||||
"name": "temp-expo",
|
"name": "temp-expo",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@config-plugins/react-native-pdf": "^11.0.0",
|
||||||
"@expo/vector-icons": "^14.1.0",
|
"@expo/vector-icons": "^14.1.0",
|
||||||
"@react-native-async-storage/async-storage": "2.1.2",
|
"@react-native-async-storage/async-storage": "2.1.2",
|
||||||
"@react-native-community/datetimepicker": "8.4.1",
|
"@react-native-community/datetimepicker": "8.4.1",
|
||||||
@@ -16,19 +17,24 @@
|
|||||||
"@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-file-system": "~18.1.11",
|
||||||
"expo-font": "~13.3.2",
|
"expo-font": "~13.3.2",
|
||||||
"expo-image-picker": "~16.1.4",
|
"expo-image-picker": "~16.1.4",
|
||||||
|
"expo-media-library": "~17.1.7",
|
||||||
"expo-splash-screen": "^31.0.8",
|
"expo-splash-screen": "^31.0.8",
|
||||||
"expo-status-bar": "~2.2.3",
|
"expo-status-bar": "~2.2.3",
|
||||||
"expo-system-ui": "~5.0.11",
|
"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-pdf": "^6.7.7",
|
||||||
"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",
|
||||||
|
"rn-fetch-blob": "^0.12.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.20.0"
|
"@babel/core": "^7.20.0"
|
||||||
@@ -1406,6 +1412,14 @@
|
|||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@config-plugins/react-native-pdf": {
|
||||||
|
"version": "11.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@config-plugins/react-native-pdf/-/react-native-pdf-11.0.0.tgz",
|
||||||
|
"integrity": "sha512-zpGsZ2wMly37WgIJ0CVWOZHmdtM98j33VUeHAFQMM9hzxANZsG/BmoPLp0AOqIENmucxif//pESUgF8aMiiqmA==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"expo": "^53"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@egjs/hammerjs": {
|
"node_modules/@egjs/hammerjs": {
|
||||||
"version": "2.0.17",
|
"version": "2.0.17",
|
||||||
"resolved": "https://registry.npmjs.org/@egjs/hammerjs/-/hammerjs-2.0.17.tgz",
|
"resolved": "https://registry.npmjs.org/@egjs/hammerjs/-/hammerjs-2.0.17.tgz",
|
||||||
@@ -2568,6 +2582,11 @@
|
|||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@react-native/normalize-color": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@react-native/normalize-color/-/normalize-color-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-Z1jQI2NpdFJCVgpY+8Dq/Bt3d+YUi1928Q+/CZm/oh66fzM0RUl54vvuXlPJKybH4pdCZey1eDTPaLHkMPNgWA=="
|
||||||
|
},
|
||||||
"node_modules/@react-native/normalize-colors": {
|
"node_modules/@react-native/normalize-colors": {
|
||||||
"version": "0.79.5",
|
"version": "0.79.5",
|
||||||
"resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.79.5.tgz",
|
"resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.79.5.tgz",
|
||||||
@@ -3150,6 +3169,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
||||||
},
|
},
|
||||||
|
"node_modules/base-64": {
|
||||||
|
"version": "0.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/base-64/-/base-64-0.1.0.tgz",
|
||||||
|
"integrity": "sha512-Y5gU45svrR5tI2Vt/X9GPd3L0HNIKzGu202EjxrXMpuc2V2CiKgemAbUUsqYmZJvPtCXoUKjNZwBJzsNScUbXA=="
|
||||||
|
},
|
||||||
"node_modules/base64-js": {
|
"node_modules/base64-js": {
|
||||||
"version": "1.5.1",
|
"version": "1.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
|
||||||
@@ -3708,6 +3732,11 @@
|
|||||||
"node": ">= 8"
|
"node": ">= 8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/crypto-js": {
|
||||||
|
"version": "4.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz",
|
||||||
|
"integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q=="
|
||||||
|
},
|
||||||
"node_modules/crypto-random-string": {
|
"node_modules/crypto-random-string": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz",
|
||||||
@@ -3829,6 +3858,16 @@
|
|||||||
"node": ">= 0.8"
|
"node": ">= 0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/deprecated-react-native-prop-types": {
|
||||||
|
"version": "2.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/deprecated-react-native-prop-types/-/deprecated-react-native-prop-types-2.3.0.tgz",
|
||||||
|
"integrity": "sha512-pWD0voFtNYxrVqvBMYf5gq3NA2GCpfodS1yNynTPc93AYA/KEMGeWDqqeUB6R2Z9ZofVhks2aeJXiuQqKNpesA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@react-native/normalize-color": "*",
|
||||||
|
"invariant": "*",
|
||||||
|
"prop-types": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/destroy": {
|
"node_modules/destroy": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
|
||||||
@@ -4168,6 +4207,15 @@
|
|||||||
"react": "*"
|
"react": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/expo-media-library": {
|
||||||
|
"version": "17.1.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/expo-media-library/-/expo-media-library-17.1.7.tgz",
|
||||||
|
"integrity": "sha512-hLCoMvlhjtt+iYxPe71P1F6t06mYGysuNOfjQzDbbf64PCkglCZJYmywPyUSV1V5Hu9DhRj//gEg+Ki+7VWXog==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"expo": "*",
|
||||||
|
"react-native": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/expo-modules-autolinking": {
|
"node_modules/expo-modules-autolinking": {
|
||||||
"version": "2.1.14",
|
"version": "2.1.14",
|
||||||
"resolved": "https://registry.npmjs.org/expo-modules-autolinking/-/expo-modules-autolinking-2.1.14.tgz",
|
"resolved": "https://registry.npmjs.org/expo-modules-autolinking/-/expo-modules-autolinking-2.1.14.tgz",
|
||||||
@@ -6733,6 +6781,37 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-native-blob-util": {
|
||||||
|
"version": "0.22.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-native-blob-util/-/react-native-blob-util-0.22.2.tgz",
|
||||||
|
"integrity": "sha512-Czx01QMg7aLsm/4F/7+eqoRAi1q/qjLY2Kao16g+n2SRnTH1+qkD8Qhx2q9okB+VNQvZKB1LbiXhktzYQV52xQ==",
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"base-64": "0.1.0",
|
||||||
|
"glob": "^10.3.10"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "*",
|
||||||
|
"react-native": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"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",
|
||||||
@@ -6777,6 +6856,20 @@
|
|||||||
"react-native": ">=0.65.0"
|
"react-native": ">=0.65.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-native-pdf": {
|
||||||
|
"version": "6.7.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-native-pdf/-/react-native-pdf-6.7.7.tgz",
|
||||||
|
"integrity": "sha512-D0ga/eyPsVWSPEBm622sGVZLl3gibxPmfm2cxsLcUrZ4WDSGR5HyGmvvWaR/m9wXEyIbD4J6q9qzuG6yObcSXw==",
|
||||||
|
"dependencies": {
|
||||||
|
"crypto-js": "4.2.0",
|
||||||
|
"deprecated-react-native-prop-types": "^2.3.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "*",
|
||||||
|
"react-native": "*",
|
||||||
|
"react-native-blob-util": ">=0.13.7"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-native-safe-area-context": {
|
"node_modules/react-native-safe-area-context": {
|
||||||
"version": "5.4.0",
|
"version": "5.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-native-safe-area-context/-/react-native-safe-area-context-5.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-native-safe-area-context/-/react-native-safe-area-context-5.4.0.tgz",
|
||||||
@@ -7148,6 +7241,52 @@
|
|||||||
"node": "*"
|
"node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/rn-fetch-blob": {
|
||||||
|
"version": "0.12.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/rn-fetch-blob/-/rn-fetch-blob-0.12.0.tgz",
|
||||||
|
"integrity": "sha512-+QnR7AsJ14zqpVVUbzbtAjq0iI8c9tCg49tIoKO2ezjzRunN7YL6zFSFSWZm6d+mE/l9r+OeDM3jmb2tBb2WbA==",
|
||||||
|
"dependencies": {
|
||||||
|
"base-64": "0.1.0",
|
||||||
|
"glob": "7.0.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/rn-fetch-blob/node_modules/brace-expansion": {
|
||||||
|
"version": "1.1.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
||||||
|
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
|
||||||
|
"dependencies": {
|
||||||
|
"balanced-match": "^1.0.0",
|
||||||
|
"concat-map": "0.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/rn-fetch-blob/node_modules/glob": {
|
||||||
|
"version": "7.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/glob/-/glob-7.0.6.tgz",
|
||||||
|
"integrity": "sha512-f8c0rE8JiCxpa52kWPAOa3ZaYEnzofDzCQLCn3Vdk0Z5OVLq3BsRFJI4S4ykpeVW6QMGBUkMeUpoEgWnMTnw5Q==",
|
||||||
|
"deprecated": "Glob versions prior to v9 are no longer supported",
|
||||||
|
"dependencies": {
|
||||||
|
"fs.realpath": "^1.0.0",
|
||||||
|
"inflight": "^1.0.4",
|
||||||
|
"inherits": "2",
|
||||||
|
"minimatch": "^3.0.2",
|
||||||
|
"once": "^1.3.0",
|
||||||
|
"path-is-absolute": "^1.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/rn-fetch-blob/node_modules/minimatch": {
|
||||||
|
"version": "3.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||||
|
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||||
|
"dependencies": {
|
||||||
|
"brace-expansion": "^1.1.7"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/safe-buffer": {
|
"node_modules/safe-buffer": {
|
||||||
"version": "5.2.1",
|
"version": "5.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
"web": "expo start --web"
|
"web": "expo start --web"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@config-plugins/react-native-pdf": "^11.0.0",
|
||||||
"@expo/vector-icons": "^14.1.0",
|
"@expo/vector-icons": "^14.1.0",
|
||||||
"@react-native-async-storage/async-storage": "2.1.2",
|
"@react-native-async-storage/async-storage": "2.1.2",
|
||||||
"@react-native-community/datetimepicker": "8.4.1",
|
"@react-native-community/datetimepicker": "8.4.1",
|
||||||
@@ -17,19 +18,24 @@
|
|||||||
"@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-file-system": "~18.1.11",
|
||||||
"expo-font": "~13.3.2",
|
"expo-font": "~13.3.2",
|
||||||
"expo-image-picker": "~16.1.4",
|
"expo-image-picker": "~16.1.4",
|
||||||
|
"expo-media-library": "~17.1.7",
|
||||||
"expo-splash-screen": "^31.0.8",
|
"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-pdf": "^6.7.7",
|
||||||
"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-system-ui": "~5.0.11"
|
"rn-fetch-blob": "^0.12.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.20.0"
|
"@babel/core": "^7.20.0"
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import CardPinOrderDetailsScreen from '../screens/Card/CardPinOrderDetailsScreen
|
|||||||
import CardOrdersScreen from '../screens/Card/CardOrdersScreen';
|
import CardOrdersScreen from '../screens/Card/CardOrdersScreen';
|
||||||
import CreateCardOrderScreen from '../screens/Card/CreateCardOrderScreen';
|
import CreateCardOrderScreen from '../screens/Card/CreateCardOrderScreen';
|
||||||
import CardOrderDetailsScreen from '../screens/Card/CardOrderDetailsScreen';
|
import CardOrderDetailsScreen from '../screens/Card/CardOrderDetailsScreen';
|
||||||
|
import PdfViewerScreen from '../screens/Shared/PdfViewerScreen';
|
||||||
|
|
||||||
const Stack = createStackNavigator();
|
const Stack = createStackNavigator();
|
||||||
|
|
||||||
@@ -54,6 +55,11 @@ const MenuNavigator = () => (
|
|||||||
<Stack.Screen name="CardOrders" component={CardOrdersScreen} />
|
<Stack.Screen name="CardOrders" component={CardOrdersScreen} />
|
||||||
<Stack.Screen name="CreateCardOrder" component={CreateCardOrderScreen} />
|
<Stack.Screen name="CreateCardOrder" component={CreateCardOrderScreen} />
|
||||||
<Stack.Screen name="CardOrderDetails" component={CardOrderDetailsScreen} />
|
<Stack.Screen name="CardOrderDetails" component={CardOrderDetailsScreen} />
|
||||||
|
<Stack.Screen
|
||||||
|
name="PdfViewer"
|
||||||
|
component={PdfViewerScreen}
|
||||||
|
options={{ headerShown: true }}
|
||||||
|
/>
|
||||||
</Stack.Navigator>
|
</Stack.Navigator>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -16,15 +16,27 @@ 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) {
|
||||||
@@ -74,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
|
||||||
@@ -94,6 +106,8 @@ const VerificationScreen = ({ navigation }) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleVerifyWrapper = () => handleVerify(code);
|
||||||
|
|
||||||
const handleResendCode = async () => {
|
const handleResendCode = async () => {
|
||||||
if (!canResend) return;
|
if (!canResend) return;
|
||||||
|
|
||||||
@@ -153,24 +167,29 @@ const VerificationScreen = ({ navigation }) => {
|
|||||||
</View>
|
</View>
|
||||||
|
|
||||||
<View style={styles.formContainer}>
|
<View style={styles.formContainer}>
|
||||||
<Input
|
<CodeField
|
||||||
label="Tassyklama kody"
|
ref={ref}
|
||||||
|
{...props}
|
||||||
value={code}
|
value={code}
|
||||||
onChangeText={setCode}
|
onChangeText={setCode}
|
||||||
placeholder="123456"
|
cellCount={CELL_COUNT}
|
||||||
keyboardType="numeric"
|
rootStyle={styles.otpContainer}
|
||||||
maxLength={6}
|
keyboardType="number-pad"
|
||||||
style={styles.codeInput}
|
|
||||||
textAlign="center"
|
|
||||||
returnKeyType="done"
|
|
||||||
onSubmitEditing={handleVerify}
|
|
||||||
textContentType="oneTimeCode"
|
textContentType="oneTimeCode"
|
||||||
autoComplete="sms-otp"
|
renderCell={({ index, symbol, isFocused }) => (
|
||||||
|
<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}
|
||||||
/>
|
/>
|
||||||
@@ -259,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,
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ const CardTransactionOrderDetailsScreen = () => {
|
|||||||
const res = await apiService.downloadCardTransactions(orderId, startDate, endDate);
|
const res = await apiService.downloadCardTransactions(orderId, startDate, endDate);
|
||||||
setDownloading(false);
|
setDownloading(false);
|
||||||
if (res.success && res.data?.url) {
|
if (res.success && res.data?.url) {
|
||||||
Linking.openURL(res.data.url);
|
navigation.navigate('PdfViewer', { url: res.data.url, title: 'Card Transactions' });
|
||||||
setModalVisible(false);
|
setModalVisible(false);
|
||||||
} else {
|
} else {
|
||||||
Alert.alert('Ýalňyşlyk', res.data.message || 'Näsazlyk ýüze çykdy');
|
Alert.alert('Ýalňyşlyk', res.data.message || 'Näsazlyk ýüze çykdy');
|
||||||
|
|||||||
103
src/screens/Shared/PdfViewerScreen.js
Normal file
103
src/screens/Shared/PdfViewerScreen.js
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
import React, { useLayoutEffect, useState } from 'react';
|
||||||
|
import { View, TouchableOpacity, Text, StyleSheet, ActivityIndicator, Alert, Dimensions } from 'react-native';
|
||||||
|
import Pdf from 'react-native-pdf';
|
||||||
|
import { useNavigation, useRoute } from '@react-navigation/native';
|
||||||
|
import { Ionicons } from '@expo/vector-icons';
|
||||||
|
import * as MediaLibrary from 'expo-media-library';
|
||||||
|
import { COLORS } from '../../constants/colors';
|
||||||
|
|
||||||
|
const PdfViewerScreen = () => {
|
||||||
|
const navigation = useNavigation();
|
||||||
|
const route = useRoute();
|
||||||
|
const { url: pdfUrl, title = 'Document' } = route.params;
|
||||||
|
|
||||||
|
const [saving, setSaving] = useState(false);
|
||||||
|
const [cachedPdfPath, setCachedPdfPath] = useState(null);
|
||||||
|
|
||||||
|
const source = { uri: pdfUrl, cache: true };
|
||||||
|
|
||||||
|
const handleSavePdf = async () => {
|
||||||
|
if (!cachedPdfPath) {
|
||||||
|
Alert.alert('Error', 'PDF is not loaded yet. Please wait.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setSaving(true);
|
||||||
|
try {
|
||||||
|
const { status } = await MediaLibrary.requestPermissionsAsync();
|
||||||
|
if (status !== 'granted') {
|
||||||
|
Alert.alert('Permission required', 'We need permission to save files to your device.');
|
||||||
|
setSaving(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const asset = await MediaLibrary.createAssetAsync(cachedPdfPath);
|
||||||
|
const album = await MediaLibrary.getAlbumAsync('Downloads');
|
||||||
|
if (album == null) {
|
||||||
|
await MediaLibrary.createAlbumAsync('Downloads', asset, false);
|
||||||
|
} else {
|
||||||
|
await MediaLibrary.addAssetsToAlbumAsync([asset], album, false);
|
||||||
|
}
|
||||||
|
Alert.alert('Saved!', 'PDF has been saved to your Downloads folder.');
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
Alert.alert('Error', 'Could not save the PDF.');
|
||||||
|
} finally {
|
||||||
|
setSaving(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
navigation.setOptions({
|
||||||
|
title: title,
|
||||||
|
headerRight: () => (
|
||||||
|
saving ? (
|
||||||
|
<ActivityIndicator color={COLORS.primary} style={{ marginRight: 15 }}/>
|
||||||
|
) : (
|
||||||
|
<TouchableOpacity onPress={handleSavePdf} style={{ marginRight: 15 }}>
|
||||||
|
<Ionicons name="download-outline" size={24} color={COLORS.primary} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
)
|
||||||
|
),
|
||||||
|
});
|
||||||
|
}, [navigation, saving, pdfUrl, title, cachedPdfPath]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={styles.container}>
|
||||||
|
<Pdf
|
||||||
|
trustAllCerts={false}
|
||||||
|
source={source}
|
||||||
|
onLoadComplete={(numberOfPages, filePath) => {
|
||||||
|
setCachedPdfPath(filePath);
|
||||||
|
}}
|
||||||
|
onPageChanged={(page, numberOfPages) => {
|
||||||
|
// console.log(`Current page: ${page}`);
|
||||||
|
}}
|
||||||
|
onError={(error) => {
|
||||||
|
console.log(error);
|
||||||
|
Alert.alert('Error', 'Could not load the document.');
|
||||||
|
}}
|
||||||
|
onPressLink={(uri) => {
|
||||||
|
// console.log(`Link pressed: ${uri}`);
|
||||||
|
}}
|
||||||
|
style={styles.pdf}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
justifyContent: 'flex-start',
|
||||||
|
alignItems: 'center',
|
||||||
|
backgroundColor: '#f5f5f5',
|
||||||
|
},
|
||||||
|
pdf: {
|
||||||
|
flex: 1,
|
||||||
|
width: Dimensions.get('window').width,
|
||||||
|
height: Dimensions.get('window').height,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default PdfViewerScreen;
|
||||||
Reference in New Issue
Block a user