Compare commits
30 Commits
df9992454b
...
develop/mo
Author | SHA1 | Date | |
---|---|---|---|
![]() |
731cb7500e | ||
![]() |
d6c87e33f0 | ||
![]() |
e4b6c5e92d | ||
![]() |
03782cde24 | ||
![]() |
7cc6d939f5 | ||
![]() |
3bcb40c5ef | ||
![]() |
43a285dd2c | ||
![]() |
09a8dc539e | ||
![]() |
8f75226763 | ||
![]() |
7cfbcc1573 | ||
![]() |
5234ac06cd | ||
![]() |
aec59fb328 | ||
![]() |
7f9b4c2224 | ||
![]() |
197b006df3 | ||
![]() |
3692b2204b | ||
![]() |
3217a8d594 | ||
![]() |
d453144500 | ||
![]() |
e8d12f34e8 | ||
![]() |
56d43062c9 | ||
![]() |
c2a02cff77 | ||
![]() |
d3ef280b20 | ||
![]() |
b2e9616178 | ||
![]() |
d909805283 | ||
![]() |
8c46a93e61 | ||
![]() |
82507b4b31 | ||
![]() |
85651ff204 | ||
![]() |
9caca30e1e | ||
![]() |
d76d43d17f | ||
![]() |
dff07ddcb0 | ||
![]() |
b78709db9b |
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
|
"tabWidth": 2,
|
||||||
"semi": true,
|
"semi": true,
|
||||||
"singleQuote": true,
|
"singleQuote": true,
|
||||||
"trailingComma": "es5",
|
"trailingComma": "es5",
|
||||||
"printWidth": 100
|
"printWidth": 100
|
||||||
}
|
}
|
@@ -9,7 +9,12 @@ android {
|
|||||||
|
|
||||||
apply from: "../capacitor-cordova-android-plugins/cordova.variables.gradle"
|
apply from: "../capacitor-cordova-android-plugins/cordova.variables.gradle"
|
||||||
dependencies {
|
dependencies {
|
||||||
|
implementation project(':capacitor-barcode-scanner')
|
||||||
|
implementation project(':capacitor-clipboard')
|
||||||
|
implementation project(':capacitor-geolocation')
|
||||||
|
implementation project(':capacitor-google-maps')
|
||||||
implementation project(':capacitor-preferences')
|
implementation project(':capacitor-preferences')
|
||||||
|
implementation project(':capacitor-share')
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -2,5 +2,20 @@
|
|||||||
include ':capacitor-android'
|
include ':capacitor-android'
|
||||||
project(':capacitor-android').projectDir = new File('../node_modules/@capacitor/android/capacitor')
|
project(':capacitor-android').projectDir = new File('../node_modules/@capacitor/android/capacitor')
|
||||||
|
|
||||||
|
include ':capacitor-barcode-scanner'
|
||||||
|
project(':capacitor-barcode-scanner').projectDir = new File('../node_modules/@capacitor/barcode-scanner/android')
|
||||||
|
|
||||||
|
include ':capacitor-clipboard'
|
||||||
|
project(':capacitor-clipboard').projectDir = new File('../node_modules/@capacitor/clipboard/android')
|
||||||
|
|
||||||
|
include ':capacitor-geolocation'
|
||||||
|
project(':capacitor-geolocation').projectDir = new File('../node_modules/@capacitor/geolocation/android')
|
||||||
|
|
||||||
|
include ':capacitor-google-maps'
|
||||||
|
project(':capacitor-google-maps').projectDir = new File('../node_modules/@capacitor/google-maps/android')
|
||||||
|
|
||||||
include ':capacitor-preferences'
|
include ':capacitor-preferences'
|
||||||
project(':capacitor-preferences').projectDir = new File('../node_modules/@capacitor/preferences/android')
|
project(':capacitor-preferences').projectDir = new File('../node_modules/@capacitor/preferences/android')
|
||||||
|
|
||||||
|
include ':capacitor-share'
|
||||||
|
project(':capacitor-share').projectDir = new File('../node_modules/@capacitor/share/android')
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
while true; do
|
while true; do
|
||||||
npm i -D
|
yarn -D
|
||||||
|
|
||||||
npm run dev
|
yarn run dev
|
||||||
|
|
||||||
echo "restarting..."
|
echo "restarting..."
|
||||||
sleep 1
|
sleep 1
|
||||||
|
@@ -11,7 +11,12 @@ install! 'cocoapods', :disable_input_output_paths => true
|
|||||||
def capacitor_pods
|
def capacitor_pods
|
||||||
pod 'Capacitor', :path => '../../node_modules/@capacitor/ios'
|
pod 'Capacitor', :path => '../../node_modules/@capacitor/ios'
|
||||||
pod 'CapacitorCordova', :path => '../../node_modules/@capacitor/ios'
|
pod 'CapacitorCordova', :path => '../../node_modules/@capacitor/ios'
|
||||||
|
pod 'CapacitorBarcodeScanner', :path => '../../node_modules/@capacitor/barcode-scanner'
|
||||||
|
pod 'CapacitorClipboard', :path => '../../node_modules/@capacitor/clipboard'
|
||||||
|
pod 'CapacitorGeolocation', :path => '../../node_modules/@capacitor/geolocation'
|
||||||
|
pod 'CapacitorGoogleMaps', :path => '../../node_modules/@capacitor/google-maps'
|
||||||
pod 'CapacitorPreferences', :path => '../../node_modules/@capacitor/preferences'
|
pod 'CapacitorPreferences', :path => '../../node_modules/@capacitor/preferences'
|
||||||
|
pod 'CapacitorShare', :path => '../../node_modules/@capacitor/share'
|
||||||
end
|
end
|
||||||
|
|
||||||
target 'App' do
|
target 'App' do
|
||||||
|
6965
03_source/mobile/package-lock.json
generated
@@ -7,24 +7,36 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@capacitor/android": "7.0.1",
|
"@capacitor/android": "7.0.1",
|
||||||
|
"@capacitor/barcode-scanner": "^2.0.3",
|
||||||
|
"@capacitor/clipboard": "^7.0.1",
|
||||||
"@capacitor/core": "^7.0.0",
|
"@capacitor/core": "^7.0.0",
|
||||||
|
"@capacitor/geolocation": "^7.1.2",
|
||||||
|
"@capacitor/google-maps": "^7.0.2",
|
||||||
"@capacitor/ios": "7.0.1",
|
"@capacitor/ios": "7.0.1",
|
||||||
"@capacitor/preferences": "^7.0.0",
|
"@capacitor/preferences": "^7.0.0",
|
||||||
|
"@capacitor/share": "^7.0.1",
|
||||||
"@hookform/resolvers": "^4.1.3",
|
"@hookform/resolvers": "^4.1.3",
|
||||||
"@ionic/react": "^8.5.0",
|
"@ionic/react": "^8.5.0",
|
||||||
"@ionic/react-router": "^8.5.0",
|
"@ionic/react-router": "^8.5.0",
|
||||||
"@mdx-js/react": "^3.1.0",
|
"@mdx-js/react": "^3.1.0",
|
||||||
|
"@react-hook/window-size": "^3.1.1",
|
||||||
"@types/leaflet": "^1.9.17",
|
"@types/leaflet": "^1.9.17",
|
||||||
"@types/react-redux": "^7.1.34",
|
"@types/react-redux": "^7.1.34",
|
||||||
"axios": "^1.9.0",
|
"axios": "^1.9.0",
|
||||||
"date-fns": "^2.25.0",
|
"date-fns": "^2.25.0",
|
||||||
"ionicons": "^7.1.2",
|
"ionicons": "^7.1.2",
|
||||||
"leaflet": "^1.9.4",
|
"leaflet": "^1.9.4",
|
||||||
|
"pigeon-maps": "^0.22.1",
|
||||||
|
"pullstate": "^1",
|
||||||
"react": "19.0.0",
|
"react": "19.0.0",
|
||||||
|
"react-color": "^2.19.3",
|
||||||
|
"react-confetti": "^6.4.0",
|
||||||
"react-dom": "19.0.0",
|
"react-dom": "19.0.0",
|
||||||
"react-hook-form": "^7.55.0",
|
"react-hook-form": "^7.55.0",
|
||||||
"react-leaflet": "^5.0.0",
|
"react-leaflet": "^5.0.0",
|
||||||
"react-markdown": "^10.1.0",
|
"react-markdown": "^10.1.0",
|
||||||
|
"react-qr-code": "^2.0.15",
|
||||||
|
"react-qr-reader": "^3.0.0-beta-1",
|
||||||
"react-redux": "^9.2.0",
|
"react-redux": "^9.2.0",
|
||||||
"react-router": "^5.3.4",
|
"react-router": "^5.3.4",
|
||||||
"react-router-dom": "^5.3.4",
|
"react-router-dom": "^5.3.4",
|
||||||
@@ -32,12 +44,13 @@
|
|||||||
"react-use": "^17.6.0",
|
"react-use": "^17.6.0",
|
||||||
"reselect": "^4.0.0",
|
"reselect": "^4.0.0",
|
||||||
"sass": "^1.85.1",
|
"sass": "^1.85.1",
|
||||||
"swiper": "^9.1.1",
|
"swiper": "^11.2.8",
|
||||||
|
"use-sound": "^5.0.0",
|
||||||
"zod": "^3.24.2"
|
"zod": "^3.24.2"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "npm run dev",
|
"start": "npm run dev",
|
||||||
"dev": "vite --host 0.0.0.0 --cors",
|
"dev": "vite --force --host 0.0.0.0 --cors",
|
||||||
"ionic:serve": "vite",
|
"ionic:serve": "vite",
|
||||||
"ionic:build": "tsc && vite build",
|
"ionic:build": "tsc && vite build",
|
||||||
"build": "tsc && vite build",
|
"build": "tsc && vite build",
|
||||||
@@ -64,7 +77,7 @@
|
|||||||
"@types/react-router-dom": "^5.3.3",
|
"@types/react-router-dom": "^5.3.3",
|
||||||
"@vitejs/plugin-react": "^4.3.4",
|
"@vitejs/plugin-react": "^4.3.4",
|
||||||
"lint-staged": "^13.2.0",
|
"lint-staged": "^13.2.0",
|
||||||
"prettier": "^2.8.6",
|
"prettier": "^3.5.3",
|
||||||
"typescript": "^5.8.2",
|
"typescript": "^5.8.2",
|
||||||
"vite": "^6.2.0"
|
"vite": "^6.2.0"
|
||||||
},
|
},
|
||||||
|
BIN
03_source/mobile/public/assets/DemoBankingUi/alan.jpg
Normal file
After Width: | Height: | Size: 36 KiB |
BIN
03_source/mobile/public/assets/DemoBankingUi/chip.png
Normal file
After Width: | Height: | Size: 4.0 KiB |
BIN
03_source/mobile/public/assets/DemoBankingUi/icon/favicon.png
Normal file
After Width: | Height: | Size: 930 B |
BIN
03_source/mobile/public/assets/DemoBankingUi/icon/icon.png
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
03_source/mobile/public/assets/DemoBankingUi/mastercard.png
Normal file
After Width: | Height: | Size: 26 KiB |
1
03_source/mobile/public/assets/DemoBankingUi/shapes.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg width="350" height="140" xmlns="http://www.w3.org/2000/svg" style="background:#f6f7f9"><g fill="none" fill-rule="evenodd"><path fill="#F04141" style="mix-blend-mode:multiply" d="M61.905-34.23l96.194 54.51-66.982 54.512L22 34.887z"/><circle fill="#10DC60" style="mix-blend-mode:multiply" cx="155.5" cy="135.5" r="57.5"/><path fill="#3880FF" style="mix-blend-mode:multiply" d="M208.538 9.513l84.417 15.392L223.93 93.93z"/><path fill="#FFCE00" style="mix-blend-mode:multiply" d="M268.625 106.557l46.332-26.75 46.332 26.75v53.5l-46.332 26.75-46.332-26.75z"/><circle fill="#7044FF" style="mix-blend-mode:multiply" cx="299.5" cy="9.5" r="38.5"/><rect fill="#11D3EA" style="mix-blend-mode:multiply" transform="rotate(-60 148.47 37.886)" x="143.372" y="-7.056" width="10.196" height="89.884" rx="5.098"/><path d="M-25.389 74.253l84.86 8.107c5.498.525 9.53 5.407 9.004 10.905a10 10 0 0 1-.057.477l-12.36 85.671a10.002 10.002 0 0 1-11.634 8.42l-86.351-15.226c-5.44-.959-9.07-6.145-8.112-11.584l13.851-78.551a10 10 0 0 1 10.799-8.219z" fill="#7044FF" style="mix-blend-mode:multiply"/><circle fill="#0CD1E8" style="mix-blend-mode:multiply" cx="273.5" cy="106.5" r="20.5"/></g></svg>
|
After Width: | Height: | Size: 1.1 KiB |
BIN
03_source/mobile/public/assets/DemoBankingUi/visa.png
Normal file
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 930 B |
BIN
03_source/mobile/public/assets/DemoDictionaryApp/icon/icon.png
Normal file
After Width: | Height: | Size: 23 KiB |
@@ -0,0 +1 @@
|
|||||||
|
<svg width="350" height="140" xmlns="http://www.w3.org/2000/svg" style="background:#f6f7f9"><g fill="none" fill-rule="evenodd"><path fill="#F04141" style="mix-blend-mode:multiply" d="M61.905-34.23l96.194 54.51-66.982 54.512L22 34.887z"/><circle fill="#10DC60" style="mix-blend-mode:multiply" cx="155.5" cy="135.5" r="57.5"/><path fill="#3880FF" style="mix-blend-mode:multiply" d="M208.538 9.513l84.417 15.392L223.93 93.93z"/><path fill="#FFCE00" style="mix-blend-mode:multiply" d="M268.625 106.557l46.332-26.75 46.332 26.75v53.5l-46.332 26.75-46.332-26.75z"/><circle fill="#7044FF" style="mix-blend-mode:multiply" cx="299.5" cy="9.5" r="38.5"/><rect fill="#11D3EA" style="mix-blend-mode:multiply" transform="rotate(-60 148.47 37.886)" x="143.372" y="-7.056" width="10.196" height="89.884" rx="5.098"/><path d="M-25.389 74.253l84.86 8.107c5.498.525 9.53 5.407 9.004 10.905a10 10 0 0 1-.057.477l-12.36 85.671a10.002 10.002 0 0 1-11.634 8.42l-86.351-15.226c-5.44-.959-9.07-6.145-8.112-11.584l13.851-78.551a10 10 0 0 1 10.799-8.219z" fill="#7044FF" style="mix-blend-mode:multiply"/><circle fill="#0CD1E8" style="mix-blend-mode:multiply" cx="273.5" cy="106.5" r="20.5"/></g></svg>
|
After Width: | Height: | Size: 1.1 KiB |
BIN
03_source/mobile/public/assets/DemoQuizApp/icon/favicon.png
Normal file
After Width: | Height: | Size: 930 B |
BIN
03_source/mobile/public/assets/DemoQuizApp/icon/icon.png
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
03_source/mobile/public/assets/DemoQuizApp/main.png
Normal file
After Width: | Height: | Size: 39 KiB |
1
03_source/mobile/public/assets/DemoQuizApp/shapes.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg width="350" height="140" xmlns="http://www.w3.org/2000/svg" style="background:#f6f7f9"><g fill="none" fill-rule="evenodd"><path fill="#F04141" style="mix-blend-mode:multiply" d="M61.905-34.23l96.194 54.51-66.982 54.512L22 34.887z"/><circle fill="#10DC60" style="mix-blend-mode:multiply" cx="155.5" cy="135.5" r="57.5"/><path fill="#3880FF" style="mix-blend-mode:multiply" d="M208.538 9.513l84.417 15.392L223.93 93.93z"/><path fill="#FFCE00" style="mix-blend-mode:multiply" d="M268.625 106.557l46.332-26.75 46.332 26.75v53.5l-46.332 26.75-46.332-26.75z"/><circle fill="#7044FF" style="mix-blend-mode:multiply" cx="299.5" cy="9.5" r="38.5"/><rect fill="#11D3EA" style="mix-blend-mode:multiply" transform="rotate(-60 148.47 37.886)" x="143.372" y="-7.056" width="10.196" height="89.884" rx="5.098"/><path d="M-25.389 74.253l84.86 8.107c5.498.525 9.53 5.407 9.004 10.905a10 10 0 0 1-.057.477l-12.36 85.671a10.002 10.002 0 0 1-11.634 8.42l-86.351-15.226c-5.44-.959-9.07-6.145-8.112-11.584l13.851-78.551a10 10 0 0 1 10.799-8.219z" fill="#7044FF" style="mix-blend-mode:multiply"/><circle fill="#0CD1E8" style="mix-blend-mode:multiply" cx="273.5" cy="106.5" r="20.5"/></g></svg>
|
After Width: | Height: | Size: 1.1 KiB |
BIN
03_source/mobile/public/assets/DemoRecipeApp/bookmark.png
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
03_source/mobile/public/assets/DemoRecipeApp/icon/favicon.png
Normal file
After Width: | Height: | Size: 930 B |
BIN
03_source/mobile/public/assets/DemoRecipeApp/icon/icon.png
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
03_source/mobile/public/assets/DemoRecipeApp/placeholder.png
Normal file
After Width: | Height: | Size: 42 KiB |
1
03_source/mobile/public/assets/DemoRecipeApp/shapes.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg width="350" height="140" xmlns="http://www.w3.org/2000/svg" style="background:#f6f7f9"><g fill="none" fill-rule="evenodd"><path fill="#F04141" style="mix-blend-mode:multiply" d="M61.905-34.23l96.194 54.51-66.982 54.512L22 34.887z"/><circle fill="#10DC60" style="mix-blend-mode:multiply" cx="155.5" cy="135.5" r="57.5"/><path fill="#3880FF" style="mix-blend-mode:multiply" d="M208.538 9.513l84.417 15.392L223.93 93.93z"/><path fill="#FFCE00" style="mix-blend-mode:multiply" d="M268.625 106.557l46.332-26.75 46.332 26.75v53.5l-46.332 26.75-46.332-26.75z"/><circle fill="#7044FF" style="mix-blend-mode:multiply" cx="299.5" cy="9.5" r="38.5"/><rect fill="#11D3EA" style="mix-blend-mode:multiply" transform="rotate(-60 148.47 37.886)" x="143.372" y="-7.056" width="10.196" height="89.884" rx="5.098"/><path d="M-25.389 74.253l84.86 8.107c5.498.525 9.53 5.407 9.004 10.905a10 10 0 0 1-.057.477l-12.36 85.671a10.002 10.002 0 0 1-11.634 8.42l-86.351-15.226c-5.44-.959-9.07-6.145-8.112-11.584l13.851-78.551a10 10 0 0 1 10.799-8.219z" fill="#7044FF" style="mix-blend-mode:multiply"/><circle fill="#0CD1E8" style="mix-blend-mode:multiply" cx="273.5" cy="106.5" r="20.5"/></g></svg>
|
After Width: | Height: | Size: 1.1 KiB |
BIN
03_source/mobile/public/assets/DemoShopAppUi/cart.png
Normal file
After Width: | Height: | Size: 47 KiB |
BIN
03_source/mobile/public/assets/DemoShopAppUi/icon/favicon.png
Normal file
After Width: | Height: | Size: 930 B |
BIN
03_source/mobile/public/assets/DemoShopAppUi/icon/icon.png
Normal file
After Width: | Height: | Size: 23 KiB |
1
03_source/mobile/public/assets/DemoShopAppUi/shapes.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg width="350" height="140" xmlns="http://www.w3.org/2000/svg" style="background:#f6f7f9"><g fill="none" fill-rule="evenodd"><path fill="#F04141" style="mix-blend-mode:multiply" d="M61.905-34.23l96.194 54.51-66.982 54.512L22 34.887z"/><circle fill="#10DC60" style="mix-blend-mode:multiply" cx="155.5" cy="135.5" r="57.5"/><path fill="#3880FF" style="mix-blend-mode:multiply" d="M208.538 9.513l84.417 15.392L223.93 93.93z"/><path fill="#FFCE00" style="mix-blend-mode:multiply" d="M268.625 106.557l46.332-26.75 46.332 26.75v53.5l-46.332 26.75-46.332-26.75z"/><circle fill="#7044FF" style="mix-blend-mode:multiply" cx="299.5" cy="9.5" r="38.5"/><rect fill="#11D3EA" style="mix-blend-mode:multiply" transform="rotate(-60 148.47 37.886)" x="143.372" y="-7.056" width="10.196" height="89.884" rx="5.098"/><path d="M-25.389 74.253l84.86 8.107c5.498.525 9.53 5.407 9.004 10.905a10 10 0 0 1-.057.477l-12.36 85.671a10.002 10.002 0 0 1-11.634 8.42l-86.351-15.226c-5.44-.959-9.07-6.145-8.112-11.584l13.851-78.551a10 10 0 0 1 10.799-8.219z" fill="#7044FF" style="mix-blend-mode:multiply"/><circle fill="#0CD1E8" style="mix-blend-mode:multiply" cx="273.5" cy="106.5" r="20.5"/></g></svg>
|
After Width: | Height: | Size: 1.1 KiB |
BIN
03_source/mobile/public/assets/DemoShopAppUi/shop.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
03_source/mobile/public/assets/DemoSlidingProfile/autumn.png
Normal file
After Width: | Height: | Size: 235 KiB |
BIN
03_source/mobile/public/assets/DemoSlidingProfile/avatar.jpeg
Normal file
After Width: | Height: | Size: 52 KiB |
BIN
03_source/mobile/public/assets/DemoSlidingProfile/avatar1.png
Normal file
After Width: | Height: | Size: 358 KiB |
BIN
03_source/mobile/public/assets/DemoSlidingProfile/avatar2.png
Normal file
After Width: | Height: | Size: 424 KiB |
BIN
03_source/mobile/public/assets/DemoSlidingProfile/avatar3.png
Normal file
After Width: | Height: | Size: 56 KiB |
BIN
03_source/mobile/public/assets/DemoSlidingProfile/avatar4.png
Normal file
After Width: | Height: | Size: 133 KiB |
BIN
03_source/mobile/public/assets/DemoSlidingProfile/avatar5.png
Normal file
After Width: | Height: | Size: 264 KiB |
BIN
03_source/mobile/public/assets/DemoSlidingProfile/avatar6.png
Normal file
After Width: | Height: | Size: 67 KiB |
BIN
03_source/mobile/public/assets/DemoSlidingProfile/cover1.jpeg
Normal file
After Width: | Height: | Size: 249 KiB |
BIN
03_source/mobile/public/assets/DemoSlidingProfile/cover2.jpeg
Normal file
After Width: | Height: | Size: 216 KiB |
BIN
03_source/mobile/public/assets/DemoSlidingProfile/cover4.jpeg
Normal file
After Width: | Height: | Size: 180 KiB |
BIN
03_source/mobile/public/assets/DemoSlidingProfile/cover5.jpeg
Normal file
After Width: | Height: | Size: 110 KiB |
BIN
03_source/mobile/public/assets/DemoSlidingProfile/cover6.jpeg
Normal file
After Width: | Height: | Size: 124 KiB |
BIN
03_source/mobile/public/assets/DemoSlidingProfile/flower.jpeg
Normal file
After Width: | Height: | Size: 78 KiB |
BIN
03_source/mobile/public/assets/DemoSlidingProfile/h.jpeg
Normal file
After Width: | Height: | Size: 92 KiB |
After Width: | Height: | Size: 930 B |
BIN
03_source/mobile/public/assets/DemoSlidingProfile/icon/icon.png
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
03_source/mobile/public/assets/DemoSlidingProfile/ocean.jpeg
Normal file
After Width: | Height: | Size: 64 KiB |
@@ -0,0 +1 @@
|
|||||||
|
<svg width="350" height="140" xmlns="http://www.w3.org/2000/svg" style="background:#f6f7f9"><g fill="none" fill-rule="evenodd"><path fill="#F04141" style="mix-blend-mode:multiply" d="M61.905-34.23l96.194 54.51-66.982 54.512L22 34.887z"/><circle fill="#10DC60" style="mix-blend-mode:multiply" cx="155.5" cy="135.5" r="57.5"/><path fill="#3880FF" style="mix-blend-mode:multiply" d="M208.538 9.513l84.417 15.392L223.93 93.93z"/><path fill="#FFCE00" style="mix-blend-mode:multiply" d="M268.625 106.557l46.332-26.75 46.332 26.75v53.5l-46.332 26.75-46.332-26.75z"/><circle fill="#7044FF" style="mix-blend-mode:multiply" cx="299.5" cy="9.5" r="38.5"/><rect fill="#11D3EA" style="mix-blend-mode:multiply" transform="rotate(-60 148.47 37.886)" x="143.372" y="-7.056" width="10.196" height="89.884" rx="5.098"/><path d="M-25.389 74.253l84.86 8.107c5.498.525 9.53 5.407 9.004 10.905a10 10 0 0 1-.057.477l-12.36 85.671a10.002 10.002 0 0 1-11.634 8.42l-86.351-15.226c-5.44-.959-9.07-6.145-8.112-11.584l13.851-78.551a10 10 0 0 1 10.799-8.219z" fill="#7044FF" style="mix-blend-mode:multiply"/><circle fill="#0CD1E8" style="mix-blend-mode:multiply" cx="273.5" cy="106.5" r="20.5"/></g></svg>
|
After Width: | Height: | Size: 1.1 KiB |
BIN
03_source/mobile/public/assets/DemoSlidingProfile/spring.png
Normal file
After Width: | Height: | Size: 288 KiB |
BIN
03_source/mobile/public/assets/DemoSlidingProfile/summer.png
Normal file
After Width: | Height: | Size: 210 KiB |
BIN
03_source/mobile/public/assets/DemoSlidingProfile/van.jpeg
Normal file
After Width: | Height: | Size: 174 KiB |
BIN
03_source/mobile/public/assets/DemoSlidingProfile/winter.png
Normal file
After Width: | Height: | Size: 206 KiB |
BIN
03_source/mobile/public/assets/ScoreBoard/icon/favicon.png
Normal file
After Width: | Height: | Size: 930 B |
BIN
03_source/mobile/public/assets/ScoreBoard/icon/icon.png
Normal file
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 682 KiB |
After Width: | Height: | Size: 820 KiB |
BIN
03_source/mobile/public/assets/ScoreBoard/scoreboardheader.jpeg
Normal file
After Width: | Height: | Size: 49 KiB |
1
03_source/mobile/public/assets/ScoreBoard/shapes.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg width="350" height="140" xmlns="http://www.w3.org/2000/svg" style="background:#f6f7f9"><g fill="none" fill-rule="evenodd"><path fill="#F04141" style="mix-blend-mode:multiply" d="M61.905-34.23l96.194 54.51-66.982 54.512L22 34.887z"/><circle fill="#10DC60" style="mix-blend-mode:multiply" cx="155.5" cy="135.5" r="57.5"/><path fill="#3880FF" style="mix-blend-mode:multiply" d="M208.538 9.513l84.417 15.392L223.93 93.93z"/><path fill="#FFCE00" style="mix-blend-mode:multiply" d="M268.625 106.557l46.332-26.75 46.332 26.75v53.5l-46.332 26.75-46.332-26.75z"/><circle fill="#7044FF" style="mix-blend-mode:multiply" cx="299.5" cy="9.5" r="38.5"/><rect fill="#11D3EA" style="mix-blend-mode:multiply" transform="rotate(-60 148.47 37.886)" x="143.372" y="-7.056" width="10.196" height="89.884" rx="5.098"/><path d="M-25.389 74.253l84.86 8.107c5.498.525 9.53 5.407 9.004 10.905a10 10 0 0 1-.057.477l-12.36 85.671a10.002 10.002 0 0 1-11.634 8.42l-86.351-15.226c-5.44-.959-9.07-6.145-8.112-11.584l13.851-78.551a10 10 0 0 1 10.799-8.219z" fill="#7044FF" style="mix-blend-mode:multiply"/><circle fill="#0CD1E8" style="mix-blend-mode:multiply" cx="273.5" cy="106.5" r="20.5"/></g></svg>
|
After Width: | Height: | Size: 1.1 KiB |
BIN
03_source/mobile/public/assets/WeatherDemo/icon/favicon.png
Normal file
After Width: | Height: | Size: 930 B |
BIN
03_source/mobile/public/assets/WeatherDemo/icon/icon.png
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
03_source/mobile/public/assets/WeatherDemo/map.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
1
03_source/mobile/public/assets/WeatherDemo/shapes.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg width="350" height="140" xmlns="http://www.w3.org/2000/svg" style="background:#f6f7f9"><g fill="none" fill-rule="evenodd"><path fill="#F04141" style="mix-blend-mode:multiply" d="M61.905-34.23l96.194 54.51-66.982 54.512L22 34.887z"/><circle fill="#10DC60" style="mix-blend-mode:multiply" cx="155.5" cy="135.5" r="57.5"/><path fill="#3880FF" style="mix-blend-mode:multiply" d="M208.538 9.513l84.417 15.392L223.93 93.93z"/><path fill="#FFCE00" style="mix-blend-mode:multiply" d="M268.625 106.557l46.332-26.75 46.332 26.75v53.5l-46.332 26.75-46.332-26.75z"/><circle fill="#7044FF" style="mix-blend-mode:multiply" cx="299.5" cy="9.5" r="38.5"/><rect fill="#11D3EA" style="mix-blend-mode:multiply" transform="rotate(-60 148.47 37.886)" x="143.372" y="-7.056" width="10.196" height="89.884" rx="5.098"/><path d="M-25.389 74.253l84.86 8.107c5.498.525 9.53 5.407 9.004 10.905a10 10 0 0 1-.057.477l-12.36 85.671a10.002 10.002 0 0 1-11.634 8.42l-86.351-15.226c-5.44-.959-9.07-6.145-8.112-11.584l13.851-78.551a10 10 0 0 1 10.799-8.219z" fill="#7044FF" style="mix-blend-mode:multiply"/><circle fill="#0CD1E8" style="mix-blend-mode:multiply" cx="273.5" cy="106.5" r="20.5"/></g></svg>
|
After Width: | Height: | Size: 1.1 KiB |
BIN
03_source/mobile/public/assets/WeatherDemo/temp.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
03_source/mobile/public/assets/WeatherDemo/temp2.png
Normal file
After Width: | Height: | Size: 971 B |
BIN
03_source/mobile/public/assets/WeatherDemo/wind.png
Normal file
After Width: | Height: | Size: 896 B |
BIN
03_source/mobile/public/assets/react-shop/beds.jpeg
Normal file
After Width: | Height: | Size: 89 KiB |
BIN
03_source/mobile/public/assets/react-shop/coats3.jpeg
Normal file
After Width: | Height: | Size: 84 KiB |
BIN
03_source/mobile/public/assets/react-shop/coffee_table.jpeg
Normal file
After Width: | Height: | Size: 389 KiB |
BIN
03_source/mobile/public/assets/react-shop/dresses3.jpeg
Normal file
After Width: | Height: | Size: 28 KiB |
BIN
03_source/mobile/public/assets/react-shop/formal_shirts2.jpeg
Normal file
After Width: | Height: | Size: 101 KiB |
BIN
03_source/mobile/public/assets/react-shop/home.jpeg
Normal file
After Width: | Height: | Size: 105 KiB |
BIN
03_source/mobile/public/assets/react-shop/icon/favicon.png
Normal file
After Width: | Height: | Size: 930 B |
BIN
03_source/mobile/public/assets/react-shop/icon/icon.png
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
03_source/mobile/public/assets/react-shop/jeans.jpeg
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
03_source/mobile/public/assets/react-shop/makeup2.jpeg
Normal file
After Width: | Height: | Size: 37 KiB |
BIN
03_source/mobile/public/assets/react-shop/men.jpeg
Normal file
After Width: | Height: | Size: 47 KiB |
BIN
03_source/mobile/public/assets/react-shop/office.jpeg
Normal file
After Width: | Height: | Size: 82 KiB |
1
03_source/mobile/public/assets/react-shop/shapes.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg width="350" height="140" xmlns="http://www.w3.org/2000/svg" style="background:#f6f7f9"><g fill="none" fill-rule="evenodd"><path fill="#F04141" style="mix-blend-mode:multiply" d="M61.905-34.23l96.194 54.51-66.982 54.512L22 34.887z"/><circle fill="#10DC60" style="mix-blend-mode:multiply" cx="155.5" cy="135.5" r="57.5"/><path fill="#3880FF" style="mix-blend-mode:multiply" d="M208.538 9.513l84.417 15.392L223.93 93.93z"/><path fill="#FFCE00" style="mix-blend-mode:multiply" d="M268.625 106.557l46.332-26.75 46.332 26.75v53.5l-46.332 26.75-46.332-26.75z"/><circle fill="#7044FF" style="mix-blend-mode:multiply" cx="299.5" cy="9.5" r="38.5"/><rect fill="#11D3EA" style="mix-blend-mode:multiply" transform="rotate(-60 148.47 37.886)" x="143.372" y="-7.056" width="10.196" height="89.884" rx="5.098"/><path d="M-25.389 74.253l84.86 8.107c5.498.525 9.53 5.407 9.004 10.905a10 10 0 0 1-.057.477l-12.36 85.671a10.002 10.002 0 0 1-11.634 8.42l-86.351-15.226c-5.44-.959-9.07-6.145-8.112-11.584l13.851-78.551a10 10 0 0 1 10.799-8.219z" fill="#7044FF" style="mix-blend-mode:multiply"/><circle fill="#0CD1E8" style="mix-blend-mode:multiply" cx="273.5" cy="106.5" r="20.5"/></g></svg>
|
After Width: | Height: | Size: 1.1 KiB |
BIN
03_source/mobile/public/assets/react-shop/sportswear2.jpeg
Normal file
After Width: | Height: | Size: 108 KiB |
BIN
03_source/mobile/public/assets/react-shop/women.jpeg
Normal file
After Width: | Height: | Size: 47 KiB |
@@ -64,6 +64,39 @@ import ServiceAgreement from './pages/ServiceAgreement';
|
|||||||
import paths from './paths';
|
import paths from './paths';
|
||||||
import PrivacyAgreement from './pages/PrivacyAgreement';
|
import PrivacyAgreement from './pages/PrivacyAgreement';
|
||||||
import AppRoute from './AppRoute';
|
import AppRoute from './AppRoute';
|
||||||
|
//
|
||||||
|
// TODO: resume DemoReactShop
|
||||||
|
// import DemoReactShop from './pages/DemoReactShop';
|
||||||
|
import DemoWeatherApp from './pages/DemoWeatherApp';
|
||||||
|
import DemoClubHouse from './pages/DemoClubHouse';
|
||||||
|
import DemoScoreBoard from './pages/DemoScoreBoard';
|
||||||
|
import DemoQuoteApp from './pages/DemoQuoteApp';
|
||||||
|
import DemoQrScanner from './pages/DemoQrScanner';
|
||||||
|
// DemoShopAppUi
|
||||||
|
import DemoShopAppUi from './pages/DemoShopAppUi';
|
||||||
|
// DemoDictionaryApp
|
||||||
|
import DemoDictionaryApp from './pages/DemoDictionaryApp';
|
||||||
|
// demo-recipe-app
|
||||||
|
import DemoRecipeApp from './pages/DemoRecipeApp';
|
||||||
|
|
||||||
|
// DemoSlidingProfile
|
||||||
|
import DemoSlidingProfile from './pages/DemoSlidingProfile';
|
||||||
|
|
||||||
|
// DemoQuizApp
|
||||||
|
import DemoQuizApp from './pages/DemoQuizApp';
|
||||||
|
import DemoBlogPostUi from './pages/DemoBlogPostUi';
|
||||||
|
import DemoReactTravelApp from './pages/DemoReactTravelApp';
|
||||||
|
import DemoPinterestFloatingTabBar from './pages/DemoPinterestFloatingTabBar';
|
||||||
|
import DemoRestaurantFinder from './pages/DemoRestaurantFinder';
|
||||||
|
import DemoReactOverlayHooks from './pages/DemoReactOverlayHooks';
|
||||||
|
import DemoReactSwitchTabs from './pages/DemoReactSwitchTabs';
|
||||||
|
import DemoReactPollApp from './pages/DemoReactPollApp';
|
||||||
|
import DemoReactWhatsAppClone from './pages/DemoReactWhatsAppClone';
|
||||||
|
import Demo2FaExample from './pages/Demo2FaExample';
|
||||||
|
import DemoAccordionTutorial from './pages/DemoAccordionTutorial';
|
||||||
|
import DemoBankingUi from './pages/DemoBankingUi';
|
||||||
|
import DemoCapacitorGoogleMapsTutorial from './pages/DemoCapacitorGoogleMapsTutorial';
|
||||||
|
import DemoColorTutorial from './pages/DemoColorTutorial';
|
||||||
|
|
||||||
setupIonicReact();
|
setupIonicReact();
|
||||||
|
|
||||||
@@ -119,10 +152,100 @@ const IonicApp: React.FC<IonicAppProps> = ({
|
|||||||
|
|
||||||
<AppRoute />
|
<AppRoute />
|
||||||
|
|
||||||
{/* */}
|
|
||||||
<Route path="/tabs" render={() => <MainTabs />} />
|
<Route path="/tabs" render={() => <MainTabs />} />
|
||||||
|
<Route path={paths.DEMO_WEATHER_APP} render={() => <DemoWeatherApp />} />
|
||||||
{/* */}
|
{/* */}
|
||||||
|
{/* */}
|
||||||
|
{/* */}
|
||||||
|
{/* */}
|
||||||
|
{/* */}
|
||||||
|
{/* */}
|
||||||
|
{/* */}
|
||||||
|
{/* */}
|
||||||
|
{/* */}
|
||||||
|
|
||||||
|
<Route path={paths.DEMO_ACCORDION_TUTORIAL} render={() => <DemoAccordionTutorial />} />
|
||||||
|
{/* */}
|
||||||
|
{/* */}
|
||||||
|
{/* */}
|
||||||
|
{/* */}
|
||||||
|
{/* */}
|
||||||
|
{/* */}
|
||||||
|
|
||||||
|
<Route path={paths.DEMO_BANKING_UI} render={() => <DemoBankingUi />} />
|
||||||
|
<Route
|
||||||
|
path={paths.DEMO_CAPACITOR_GOOGLE_MAPS_TUTORIAL}
|
||||||
|
render={() => <DemoCapacitorGoogleMapsTutorial />}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Route path={paths.DEMO_COLOR_TUTORIAL} render={() => <DemoColorTutorial />} />
|
||||||
|
|
||||||
|
{/*
|
||||||
|
<Route path={paths.DEMO_ECOMMERCE_EXAMPLE} render={() => <DemoEcommerceExample />} />
|
||||||
|
<Route path={paths.DEMO_FACEBOOK_CLONE} render={() => <DemoFacebookClone />} />
|
||||||
|
<Route path={paths.DEMO_FAST_FOOD_APP} render={() => <DemoFastFoodApp />} />
|
||||||
|
<Route path={paths.DEMO_FLOATING_TABS} render={() => <DemoFloatingTabs />} />
|
||||||
|
<Route path={paths.DEMO_INSTAGRAM_CLONE} render={() => <DemoInstagramClone />} />
|
||||||
|
<Route path={paths.DEMO_KANBAN_BOARD} render={() => <DemoKanbanBoard />} />
|
||||||
|
<Route path={paths.DEMO_ORDERING_APP} render={() => <DemoOrderingApp />} />
|
||||||
|
<Route path={paths.DEMO_PROFILE_EXAMPLE} render={() => <DemoProfileExample />} />
|
||||||
|
<Route path={paths.DEMO_PULLSTATE_TUTORIAL} render={() => <DemoPullstateTutorial />} />
|
||||||
|
<Route path={paths.DEMO_REACT_ADD_TO_CART} render={() => <DemoReactAddToCart />} />
|
||||||
|
<Route path={paths.DEMO_REACT_CALCULATOR} render={() => <DemoReactCalculator />} />
|
||||||
|
<Route path={paths.DEMO_REACT_DRAWING_CANVAS} render={() => <DemoReactDrawingCanvas />} />
|
||||||
|
<Route path={paths.DEMO_REACT_HOOK_FORM_EXAMPLE} render={() => <DemoReactHookFormExample />} />
|
||||||
|
<Route path={paths.DEMO_REACT_ITEM_LIST} render={() => <DemoReactItemList />} />
|
||||||
|
<Route path={paths.DEMO_REACT_LIFECYCLES} render={() => <DemoReactLifecycles />} />
|
||||||
|
<Route path={paths.DEMO_REACT_LOGIN} render={() => <DemoReactLogin />} />
|
||||||
|
<Route path={paths.DEMO_REACT_MARVEL_APP} render={() => <DemoReactMarvelApp />} />
|
||||||
|
<Route path={paths.DEMO_REACT_MOVIE_APP_WITH_ALGOLIA} render(() => <DemoReactMovieAppWithAlgolia />} />
|
||||||
|
<Route path={paths.DEMO_REACT_NOTES} render={() => <DemoReactNotes />} />
|
||||||
|
<Route path={paths.DEMO_REACT_ONBOARDING_UI} render={() => <DemoReactOnboardingUI />} />
|
||||||
|
<Route path={paths.DEMO_REACT_PROFILE_DASHBOARD_UI} render(() => <DemoReactProfileDashboardUI />} />
|
||||||
|
<Route path={paths.DEMO_REACT_QR_CODE} render={() => <DemoReactQRCode />} />
|
||||||
|
<Route path={paths.DEMO_REACT_QUOTES} render(() => <DemoReactQuotes />} />
|
||||||
|
<Route path={paths.DEMO_REACT_SHOP_UI} render(() => <DemoReactShopUI />} />
|
||||||
|
<Route path={paths.DEMO_REACT_TABS_MENUS_CUSTOM} render(() => <DemoReactTabsMenusCustom />} />
|
||||||
|
<Route path={paths.DEMO_REACT_THEME_SWITCHER} render(() => <DemoReactThemeSwitcher />} />
|
||||||
|
<Route path={paths.DEMO_REACT_WHATSAPP_CLONE} render(() => <DemoReactWhatsAppClone />} />
|
||||||
|
<Route path={paths.DEMO_SKELETON_TEXT} render(() => <DemoSkeletonText />} />
|
||||||
|
<Route path={paths.DEMO_STICKY_BOTTOM_SHEET_EXAMPLE} render(() => <DemoStickyBottomSheetExample />} />
|
||||||
|
<Route path={paths.DEMO_STORAGE_EXAMPLE} render(() => <DemoStorageExample />} />
|
||||||
|
<Route path={paths.DEMO_SWIPERJS_TUTORIAL} render(() => <DemoSwiperjsTutorial />} />
|
||||||
|
<Route path={paths.DEMO_WEATHER_APP_UI} render(() => <DemoWeatherAppUI />} />
|
||||||
|
*/}
|
||||||
|
|
||||||
|
<Route path={paths.DEMO_2FA_EXAMPLE} render={() => <Demo2FaExample />} />
|
||||||
|
|
||||||
|
{/* have problemx` */}
|
||||||
|
{/* <Route path={paths.DEMO_REACT_WHATSAPP_CLONE} render={() => <DemoReactWhatsAppClone />} /> */}
|
||||||
|
|
||||||
|
<Route path={paths.DEMO_REACT_POLL_APP} render={() => <DemoReactPollApp />} />
|
||||||
|
|
||||||
|
<Route path={paths.DEMO_BLOG_POST_UI} render={() => <DemoBlogPostUi />} />
|
||||||
|
<Route path={paths.DEMO_CLUB_HOUSE} render={() => <DemoClubHouse />} />
|
||||||
|
<Route path={paths.DEMO_DICTIONARY_APP} render={() => <DemoDictionaryApp />} />
|
||||||
|
<Route
|
||||||
|
path={paths.DEMO_PINTEREST_FLOATING_TAB_BAR}
|
||||||
|
render={() => <DemoPinterestFloatingTabBar />}
|
||||||
|
/>
|
||||||
|
<Route path={paths.DEMO_QR_SCANNER} render={() => <DemoQrScanner />} />
|
||||||
|
<Route path={paths.DEMO_QUIZ_APP} render={() => <DemoQuizApp />} />
|
||||||
|
<Route path={paths.DEMO_QUOTE_APP} render={() => <DemoQuoteApp />} />
|
||||||
|
<Route path={paths.DEMO_REACT_OVERLAY_HOOKS} render={() => <DemoReactOverlayHooks />} />
|
||||||
|
<Route path={paths.DEMO_REACT_POLL_APP} render={() => <DemoReactPollApp />} />
|
||||||
|
|
||||||
|
{/* TODO: resume DemoReactShop */}
|
||||||
|
{/* <Route path={paths.DEMO_REACT_SHOP} render={() => <DemoReactShop />} /> */}
|
||||||
|
|
||||||
|
<Route path={paths.DEMO_REACT_SWITCH_TABS} render={() => <DemoReactSwitchTabs />} />
|
||||||
|
<Route path={paths.DEMO_REACT_TRAVEL_APP} render={() => <DemoReactTravelApp />} />
|
||||||
|
<Route path={paths.DEMO_RECIPE_APP} render={() => <DemoRecipeApp />} />
|
||||||
|
<Route path={paths.DEMO_RESTAURANT_FINDER} render={() => <DemoRestaurantFinder />} />
|
||||||
|
<Route path={paths.DEMO_SCORE_BOARD} render={() => <DemoScoreBoard />} />
|
||||||
|
<Route path={paths.DEMO_SHOP_APP_UI} render={() => <DemoShopAppUi />} />
|
||||||
|
<Route path={paths.DEMO_SLIDING_PROFILE} render={() => <DemoSlidingProfile />} />
|
||||||
|
|
||||||
<Route path="/account" component={Account} />
|
<Route path="/account" component={Account} />
|
||||||
<Route path="/login" component={Login} />
|
<Route path="/login" component={Login} />
|
||||||
<Route path="/mylogin" component={MyLogin} />
|
<Route path="/mylogin" component={MyLogin} />
|
||||||
@@ -131,7 +254,6 @@ const IonicApp: React.FC<IonicAppProps> = ({
|
|||||||
<Route path="/support" component={Support} />
|
<Route path="/support" component={Support} />
|
||||||
<Route path="/tutorial" component={Tutorial} />
|
<Route path="/tutorial" component={Tutorial} />
|
||||||
|
|
||||||
{/* */}
|
|
||||||
<Route
|
<Route
|
||||||
path="/logout"
|
path="/logout"
|
||||||
render={() => {
|
render={() => {
|
||||||
|
@@ -7,14 +7,12 @@ import NotImplemented from './pages/NotImplemented';
|
|||||||
import EventDetail from './pages/EventDetail';
|
import EventDetail from './pages/EventDetail';
|
||||||
import MemberProfile from './pages/MemberProfile';
|
import MemberProfile from './pages/MemberProfile';
|
||||||
import paths from './paths';
|
import paths from './paths';
|
||||||
import Helloworld from './pages/Helloworld';
|
|
||||||
import Settings from './pages/Settings';
|
import Settings from './pages/Settings';
|
||||||
import ChangeLanguage from './pages/ChangeLanguage';
|
import ChangeLanguage from './pages/ChangeLanguage';
|
||||||
import ServiceAgreement from './pages/ServiceAgreement';
|
import ServiceAgreement from './pages/ServiceAgreement';
|
||||||
import PrivacyAgreement from './pages/PrivacyAgreement';
|
import PrivacyAgreement from './pages/PrivacyAgreement';
|
||||||
// import OrderDetails from './pages/OrderDetail';
|
// import OrderDetails from './pages/OrderDetail';
|
||||||
import OrderDetail from './pages/OrderDetail';
|
import OrderDetail from './pages/OrderDetail';
|
||||||
import SpeakerDetail from './pages/SpeakerDetail';
|
|
||||||
|
|
||||||
const AppRoute: React.FC = () => {
|
const AppRoute: React.FC = () => {
|
||||||
return (
|
return (
|
||||||
|
@@ -10,6 +10,9 @@ import Favourites from './pages/Favourites';
|
|||||||
import MyProfile from './pages/MyProfile';
|
import MyProfile from './pages/MyProfile';
|
||||||
import EventList from './pages/EventList';
|
import EventList from './pages/EventList';
|
||||||
import Helloworld from './pages/Helloworld';
|
import Helloworld from './pages/Helloworld';
|
||||||
|
// import WeatherDemo from './pages/WeatherDemo/Tab1';
|
||||||
|
import DemoList from './pages/DemoList';
|
||||||
|
// import DemoReactShop from './pages/DemoReactShop';
|
||||||
|
|
||||||
const TabAppRoute: React.FC = () => {
|
const TabAppRoute: React.FC = () => {
|
||||||
return (
|
return (
|
||||||
@@ -33,6 +36,12 @@ const TabAppRoute: React.FC = () => {
|
|||||||
|
|
||||||
{/* */}
|
{/* */}
|
||||||
<Route path={paths.PROFILE} render={() => <MyProfile />} exact={true} />
|
<Route path={paths.PROFILE} render={() => <MyProfile />} exact={true} />
|
||||||
|
|
||||||
|
{/* */}
|
||||||
|
<Route path="/tabs/demo-list" render={() => <DemoList />} exact={true} />
|
||||||
|
|
||||||
|
{/* */}
|
||||||
|
<Route path="/tabs/helloworld" render={() => <Helloworld />} exact={true} />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@@ -15,13 +15,18 @@ import { endpoints } from '../../pages/MyLogin/endpoints';
|
|||||||
|
|
||||||
export const loadUserData = () => async (dispatch: React.Dispatch<any>) => {
|
export const loadUserData = () => async (dispatch: React.Dispatch<any>) => {
|
||||||
dispatch(setLoading(true));
|
dispatch(setLoading(true));
|
||||||
|
|
||||||
const data = await getUserData();
|
const data = await getUserData();
|
||||||
dispatch(setData(data));
|
dispatch(setData(data));
|
||||||
|
|
||||||
dispatch(setLoading(false));
|
dispatch(setLoading(false));
|
||||||
};
|
};
|
||||||
|
|
||||||
export const setLoading = (isLoading: boolean) =>
|
export const setLoading = (isLoading: boolean) =>
|
||||||
({ type: 'set-user-loading', isLoading } as const);
|
({
|
||||||
|
type: 'set-user-loading',
|
||||||
|
isLoading,
|
||||||
|
} as const);
|
||||||
|
|
||||||
export const setData = (data: Partial<UserState>) =>
|
export const setData = (data: Partial<UserState>) =>
|
||||||
({
|
({
|
||||||
@@ -30,6 +35,7 @@ export const setData = (data: Partial<UserState>) =>
|
|||||||
} as const);
|
} as const);
|
||||||
|
|
||||||
export const logoutUser = () => async (dispatch: React.Dispatch<any>) => {
|
export const logoutUser = () => async (dispatch: React.Dispatch<any>) => {
|
||||||
|
//
|
||||||
await setIsLoggedInData(false);
|
await setIsLoggedInData(false);
|
||||||
dispatch(setUsername());
|
dispatch(setUsername());
|
||||||
};
|
};
|
||||||
@@ -44,6 +50,8 @@ export const setIsLoggedIn = (loggedIn: boolean) => async (dispatch: React.Dispa
|
|||||||
|
|
||||||
export const setUsername = (username?: string) => async (dispatch: React.Dispatch<any>) => {
|
export const setUsername = (username?: string) => async (dispatch: React.Dispatch<any>) => {
|
||||||
await setUsernameData(username);
|
await setUsernameData(username);
|
||||||
|
console.log('setUsername triggered');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: 'set-username',
|
type: 'set-username',
|
||||||
username,
|
username,
|
||||||
@@ -52,6 +60,7 @@ export const setUsername = (username?: string) => async (dispatch: React.Dispatc
|
|||||||
|
|
||||||
export const setAccessToken = (token?: string) => async (dispatch: React.Dispatch<any>) => {
|
export const setAccessToken = (token?: string) => async (dispatch: React.Dispatch<any>) => {
|
||||||
await setAccessTokenData(token);
|
await setAccessTokenData(token);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: 'set-access-token',
|
type: 'set-access-token',
|
||||||
token,
|
token,
|
||||||
@@ -120,5 +129,4 @@ export type UserActions =
|
|||||||
| ActionType<typeof setHasSeenTutorial>
|
| ActionType<typeof setHasSeenTutorial>
|
||||||
| ActionType<typeof setDarkMode>
|
| ActionType<typeof setDarkMode>
|
||||||
| ActionType<typeof setAccessToken>
|
| ActionType<typeof setAccessToken>
|
||||||
// | ActionType<typeof setSession>
|
|
||||||
| ActionType<typeof checkUserSession>;
|
| ActionType<typeof checkUserSession>;
|
||||||
|
@@ -15,11 +15,9 @@ export function userReducer(state: UserState, action: UserActions): UserState {
|
|||||||
return { ...state, darkMode: action.darkMode };
|
return { ...state, darkMode: action.darkMode };
|
||||||
case 'set-is-loggedin':
|
case 'set-is-loggedin':
|
||||||
return { ...state, isLoggedin: action.loggedIn };
|
return { ...state, isLoggedin: action.loggedIn };
|
||||||
|
case 'set-access-token':
|
||||||
|
return { ...state, token: action.token };
|
||||||
case 'check-user-session':
|
case 'check-user-session':
|
||||||
return { ...state, isSessionValid: action.sessionValid };
|
return { ...state, isSessionValid: action.sessionValid };
|
||||||
// case 'set-active-session':
|
|
||||||
// return { ...state, session: action.session };
|
|
||||||
// case 'set-access-token':
|
|
||||||
// return { ...state, token: action.token };
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
export interface UserState {
|
export interface UserState {
|
||||||
isLoggedin: boolean;
|
|
||||||
username?: string;
|
|
||||||
darkMode: boolean;
|
|
||||||
hasSeenTutorial: boolean;
|
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
|
username?: string;
|
||||||
|
hasSeenTutorial: boolean;
|
||||||
|
darkMode: boolean;
|
||||||
|
isLoggedin: boolean;
|
||||||
isSessionValid: boolean;
|
isSessionValid: boolean;
|
||||||
session?: any;
|
session?: any;
|
||||||
token?: string;
|
token?: string;
|
||||||
|
96
03_source/mobile/src/pages/Demo2FaExample/AppPages/Tab1.jsx
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
import {
|
||||||
|
IonButton,
|
||||||
|
IonButtons,
|
||||||
|
IonCol,
|
||||||
|
IonContent,
|
||||||
|
IonHeader,
|
||||||
|
IonIcon,
|
||||||
|
IonPage,
|
||||||
|
IonRow,
|
||||||
|
IonTitle,
|
||||||
|
IonToolbar,
|
||||||
|
useIonRouter,
|
||||||
|
} from '@ionic/react';
|
||||||
|
|
||||||
|
import { Geolocation } from '@capacitor/geolocation';
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
import { SkeletonDashboard } from '../components/SkeletonDashboard';
|
||||||
|
import { chevronBackOutline, refreshOutline } from 'ionicons/icons';
|
||||||
|
import { CurrentWeather } from '../components/CurrentWeather';
|
||||||
|
|
||||||
|
function Tab1() {
|
||||||
|
const router = useIonRouter();
|
||||||
|
|
||||||
|
const [currentWeather, setCurrentWeather] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getCurrentPosition();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const getCurrentPosition = async () => {
|
||||||
|
setCurrentWeather(false);
|
||||||
|
const coordinates = await Geolocation.getCurrentPosition();
|
||||||
|
getAddress(coordinates.coords);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getAddress = async (coords) => {
|
||||||
|
const query = `${coords.latitude},${coords.longitude}`;
|
||||||
|
const response = await fetch(
|
||||||
|
`https://api.weatherapi.com/v1/current.json?key=f93eb660b2424258bf5155016210712&q=${query}`
|
||||||
|
);
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
console.log(data);
|
||||||
|
setCurrentWeather(data);
|
||||||
|
};
|
||||||
|
|
||||||
|
// const router = useIonRouter();
|
||||||
|
function handleBackClick() {
|
||||||
|
router.goBack();
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<IonPage>
|
||||||
|
<IonHeader>
|
||||||
|
<IonToolbar>
|
||||||
|
<IonTitle>My Weather</IonTitle>
|
||||||
|
|
||||||
|
<IonButtons slot="end">
|
||||||
|
<IonButton onClick={() => getCurrentPosition()}>
|
||||||
|
<IonIcon icon={refreshOutline} color="primary" />
|
||||||
|
</IonButton>
|
||||||
|
</IonButtons>
|
||||||
|
|
||||||
|
<IonButtons slot="start">
|
||||||
|
<IonButton onClick={() => handleBackClick()}>
|
||||||
|
<IonIcon icon={chevronBackOutline} color="primary" />
|
||||||
|
</IonButton>
|
||||||
|
</IonButtons>
|
||||||
|
</IonToolbar>
|
||||||
|
</IonHeader>
|
||||||
|
<IonContent fullscreen>
|
||||||
|
<IonHeader collapse="condense">
|
||||||
|
<IonToolbar>
|
||||||
|
<IonTitle size="large">Dashboard</IonTitle>
|
||||||
|
</IonToolbar>
|
||||||
|
</IonHeader>
|
||||||
|
|
||||||
|
<IonRow className="ion-margin-start ion-margin-end ion-justify-content-center ion-text-center">
|
||||||
|
<IonCol size="12">
|
||||||
|
<h4>Here's your location based weather</h4>
|
||||||
|
</IonCol>
|
||||||
|
</IonRow>
|
||||||
|
|
||||||
|
<div style={{ marginTop: '-1.5rem' }}>
|
||||||
|
{currentWeather ? (
|
||||||
|
<CurrentWeather currentWeather={currentWeather} />
|
||||||
|
) : (
|
||||||
|
<SkeletonDashboard />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</IonContent>
|
||||||
|
</IonPage>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Tab1;
|
81
03_source/mobile/src/pages/Demo2FaExample/AppPages/Tab2.jsx
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
import {
|
||||||
|
IonButton,
|
||||||
|
IonCol,
|
||||||
|
IonContent,
|
||||||
|
IonHeader,
|
||||||
|
IonPage,
|
||||||
|
IonRow,
|
||||||
|
IonSearchbar,
|
||||||
|
IonTitle,
|
||||||
|
IonToolbar,
|
||||||
|
} from '@ionic/react';
|
||||||
|
import { useState } from 'react';
|
||||||
|
import { CurrentWeather } from '../components/CurrentWeather';
|
||||||
|
|
||||||
|
function Tab2() {
|
||||||
|
const [search, setSearch] = useState('');
|
||||||
|
const [currentWeather, setCurrentWeather] = useState(false);
|
||||||
|
|
||||||
|
const performSearch = async () => {
|
||||||
|
getAddress(search);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getAddress = async (city) => {
|
||||||
|
const response = await fetch(
|
||||||
|
`https://api.weatherapi.com/v1/current.json?key=f93eb660b2424258bf5155016210712&q=${city}&aqi=no`
|
||||||
|
);
|
||||||
|
const data = await response.json();
|
||||||
|
|
||||||
|
if (data && data.current && data.location) {
|
||||||
|
setCurrentWeather(data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<IonPage>
|
||||||
|
<IonHeader>
|
||||||
|
<IonToolbar>
|
||||||
|
<IonTitle>Search</IonTitle>
|
||||||
|
</IonToolbar>
|
||||||
|
</IonHeader>
|
||||||
|
<IonContent fullscreen>
|
||||||
|
<IonHeader collapse="condense">
|
||||||
|
<IonToolbar>
|
||||||
|
<IonTitle size="large">Search</IonTitle>
|
||||||
|
</IonToolbar>
|
||||||
|
</IonHeader>
|
||||||
|
|
||||||
|
<IonRow className="ion-justify-content-center ion-margin-top ion-align-items-center">
|
||||||
|
<IonCol size="7">
|
||||||
|
<IonSearchbar
|
||||||
|
placeholder="Try 'London'"
|
||||||
|
animated
|
||||||
|
value={search}
|
||||||
|
onIonChange={(e) => setSearch(e.target.value)}
|
||||||
|
/>
|
||||||
|
</IonCol>
|
||||||
|
|
||||||
|
<IonCol size="5">
|
||||||
|
<IonButton
|
||||||
|
expand="block"
|
||||||
|
className="ion-margin-start ion-margin-end"
|
||||||
|
onClick={performSearch}
|
||||||
|
>
|
||||||
|
Search
|
||||||
|
</IonButton>
|
||||||
|
</IonCol>
|
||||||
|
</IonRow>
|
||||||
|
|
||||||
|
<div style={{ marginTop: '-0.8rem' }}>
|
||||||
|
{currentWeather ? (
|
||||||
|
<CurrentWeather currentWeather={currentWeather} />
|
||||||
|
) : (
|
||||||
|
<h3 className="ion-text-center">Your search result will appear here</h3>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</IonContent>
|
||||||
|
</IonPage>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Tab2;
|
@@ -0,0 +1,62 @@
|
|||||||
|
import { IonCardSubtitle, IonCol, IonIcon, IonNote, IonRow } from '@ionic/react';
|
||||||
|
import { pulseOutline, sunnyOutline, thermometerOutline } from 'ionicons/icons';
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
|
export const WeatherProperty = ({ type, currentWeather }: { type: any; currentWeather: any }) => {
|
||||||
|
const [property, setProperty] = useState(false);
|
||||||
|
|
||||||
|
const properties = {
|
||||||
|
wind: {
|
||||||
|
isIcon: false,
|
||||||
|
icon: '/assets/WeatherDemo/wind.png',
|
||||||
|
alt: 'wind',
|
||||||
|
label: 'Wind',
|
||||||
|
value: `${currentWeather.current.wind_mph}mph`,
|
||||||
|
},
|
||||||
|
feelsLike: {
|
||||||
|
isIcon: true,
|
||||||
|
icon: thermometerOutline,
|
||||||
|
alt: 'feels like',
|
||||||
|
label: 'Feels like',
|
||||||
|
value: `${currentWeather.current.feelslike_c}°C`,
|
||||||
|
},
|
||||||
|
indexUV: {
|
||||||
|
isIcon: true,
|
||||||
|
icon: sunnyOutline,
|
||||||
|
alt: 'index uv',
|
||||||
|
label: 'Index UV',
|
||||||
|
value: currentWeather.current.uv,
|
||||||
|
},
|
||||||
|
pressure: {
|
||||||
|
isIcon: true,
|
||||||
|
icon: pulseOutline,
|
||||||
|
alt: 'pressure',
|
||||||
|
label: 'Pressure',
|
||||||
|
value: `${currentWeather.current.pressure_mb} mbar`,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setProperty(properties[type]);
|
||||||
|
}, [type]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<IonCol size="6">
|
||||||
|
<IonRow className="ion-justify-content-center ion-align-items-center">
|
||||||
|
<IonCol size="3">
|
||||||
|
{!property.isIcon && (
|
||||||
|
<img alt={property.alt} src={property.icon} height="32" width="32" />
|
||||||
|
)}
|
||||||
|
{property.isIcon && (
|
||||||
|
<IonIcon icon={property.icon} color="medium" style={{ fontSize: '2rem' }} />
|
||||||
|
)}
|
||||||
|
</IonCol>
|
||||||
|
|
||||||
|
<IonCol size="9">
|
||||||
|
<IonCardSubtitle>{property.label}</IonCardSubtitle>
|
||||||
|
<IonNote>{property.value}</IonNote>
|
||||||
|
</IonCol>
|
||||||
|
</IonRow>
|
||||||
|
</IonCol>
|
||||||
|
);
|
||||||
|
};
|
@@ -0,0 +1,48 @@
|
|||||||
|
import { IonCard, IonCardContent, IonGrid, IonRow, IonText, IonCardTitle } from '@ionic/react';
|
||||||
|
import { WeatherProperty } from './WeatherProperty';
|
||||||
|
|
||||||
|
export const CurrentWeather = ({ currentWeather }: { currentWeather: any }) => (
|
||||||
|
<IonGrid>
|
||||||
|
<IonCard>
|
||||||
|
<IonCardContent className="ion-text-center">
|
||||||
|
<IonText color="primary">
|
||||||
|
<h1>
|
||||||
|
{currentWeather.location.region},{' '}
|
||||||
|
<span style={{ color: 'gray' }}>{currentWeather.location.country}</span>
|
||||||
|
</h1>
|
||||||
|
</IonText>
|
||||||
|
|
||||||
|
<div className="ion-margin-top">
|
||||||
|
<img
|
||||||
|
alt="condition"
|
||||||
|
src={currentWeather.current.condition.icon.replace('//', 'https://')}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<IonText color="dark">
|
||||||
|
<h1 style={{ fontWeight: 'bold' }}>{currentWeather.current.condition.text}</h1>
|
||||||
|
</IonText>
|
||||||
|
|
||||||
|
<IonText color="medium">
|
||||||
|
<p>{new Date(currentWeather.location.localtime).toDateString()}</p>
|
||||||
|
</IonText>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<IonCardTitle style={{ fontSize: '3rem' }} className="ion-margin-top">
|
||||||
|
{currentWeather.current.temp_c}℃
|
||||||
|
</IonCardTitle>
|
||||||
|
|
||||||
|
<IonGrid className="ion-margin-top">
|
||||||
|
<IonRow>
|
||||||
|
<WeatherProperty type="wind" currentWeather={currentWeather} />
|
||||||
|
<WeatherProperty type="feelsLike" currentWeather={currentWeather} />
|
||||||
|
</IonRow>
|
||||||
|
|
||||||
|
<IonRow className="ion-margin-top">
|
||||||
|
<WeatherProperty type="indexUV" currentWeather={currentWeather} />
|
||||||
|
<WeatherProperty type="pressure" currentWeather={currentWeather} />
|
||||||
|
</IonRow>
|
||||||
|
</IonGrid>
|
||||||
|
</IonCardContent>
|
||||||
|
</IonCard>
|
||||||
|
</IonGrid>
|
||||||
|
);
|
@@ -0,0 +1,117 @@
|
|||||||
|
import {
|
||||||
|
IonCard,
|
||||||
|
IonCardContent,
|
||||||
|
IonCardSubtitle,
|
||||||
|
IonCardTitle,
|
||||||
|
IonCol,
|
||||||
|
IonGrid,
|
||||||
|
IonIcon,
|
||||||
|
IonNote,
|
||||||
|
IonRow,
|
||||||
|
IonSkeletonText,
|
||||||
|
IonText,
|
||||||
|
IonThumbnail,
|
||||||
|
} from '@ionic/react';
|
||||||
|
import { pulseOutline, sunnyOutline, thermometerOutline } from 'ionicons/icons';
|
||||||
|
|
||||||
|
export const SkeletonDashboard = () => (
|
||||||
|
<IonGrid>
|
||||||
|
<IonCard>
|
||||||
|
<IonCardContent className="ion-text-center">
|
||||||
|
<IonText color="primary">
|
||||||
|
<h1>
|
||||||
|
<IonSkeletonText animated style={{ height: '2rem', width: '90%' }} />
|
||||||
|
</h1>
|
||||||
|
</IonText>
|
||||||
|
|
||||||
|
<div className="ion-margin-top">
|
||||||
|
<IonThumbnail>
|
||||||
|
<IonSkeletonText animated style={{ width: '2rem', height: '2rem' }} />
|
||||||
|
</IonThumbnail>
|
||||||
|
|
||||||
|
<IonText color="dark">
|
||||||
|
<h1 style={{ fontWeight: 'bold' }}>
|
||||||
|
<IonSkeletonText animated style={{ height: '2rem', width: '90%' }} />
|
||||||
|
</h1>
|
||||||
|
</IonText>
|
||||||
|
|
||||||
|
<IonText color="medium">
|
||||||
|
<p>
|
||||||
|
<IonSkeletonText animated style={{ height: '2rem', width: '90%' }} />
|
||||||
|
</p>
|
||||||
|
</IonText>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<IonCardTitle style={{ fontSize: '3rem' }} className="ion-margin-top">
|
||||||
|
<IonSkeletonText animated style={{ height: '3rem', width: '30%', textAlign: 'center' }} />
|
||||||
|
</IonCardTitle>
|
||||||
|
|
||||||
|
<IonGrid className="ion-margin-top">
|
||||||
|
<IonRow>
|
||||||
|
<IonCol size="6">
|
||||||
|
<IonRow className="ion-justify-content-center ion-align-items-center">
|
||||||
|
<IonCol size="3">
|
||||||
|
<img alt="wind" src="/assets/WeatherDemo/wind.png" height="32" width="32" />
|
||||||
|
</IonCol>
|
||||||
|
|
||||||
|
<IonCol size="9">
|
||||||
|
<IonCardSubtitle>Wind</IonCardSubtitle>
|
||||||
|
<IonNote>
|
||||||
|
<IonSkeletonText animated style={{ height: '2rem', width: '90%' }} />
|
||||||
|
</IonNote>
|
||||||
|
</IonCol>
|
||||||
|
</IonRow>
|
||||||
|
</IonCol>
|
||||||
|
|
||||||
|
<IonCol size="6">
|
||||||
|
<IonRow className="ion-justify-content-center ion-align-items-center">
|
||||||
|
<IonCol size="3">
|
||||||
|
<IonIcon icon={thermometerOutline} color="medium" style={{ fontSize: '2rem' }} />
|
||||||
|
</IonCol>
|
||||||
|
|
||||||
|
<IonCol size="9">
|
||||||
|
<IonCardSubtitle>Feels like</IonCardSubtitle>
|
||||||
|
<IonNote>
|
||||||
|
<IonSkeletonText animated style={{ height: '2rem', width: '90%' }} />
|
||||||
|
</IonNote>
|
||||||
|
</IonCol>
|
||||||
|
</IonRow>
|
||||||
|
</IonCol>
|
||||||
|
</IonRow>
|
||||||
|
|
||||||
|
<IonRow className="ion-margin-top">
|
||||||
|
<IonCol size="6">
|
||||||
|
<IonRow className="ion-justify-content-center ion-align-items-center">
|
||||||
|
<IonCol size="3">
|
||||||
|
<IonIcon icon={sunnyOutline} color="medium" style={{ fontSize: '2rem' }} />
|
||||||
|
</IonCol>
|
||||||
|
|
||||||
|
<IonCol size="9">
|
||||||
|
<IonCardSubtitle>Index UV</IonCardSubtitle>
|
||||||
|
<IonNote>
|
||||||
|
<IonSkeletonText animated style={{ height: '2rem', width: '90%' }} />
|
||||||
|
</IonNote>
|
||||||
|
</IonCol>
|
||||||
|
</IonRow>
|
||||||
|
</IonCol>
|
||||||
|
|
||||||
|
<IonCol size="6">
|
||||||
|
<IonRow className="ion-justify-content-center ion-align-items-center">
|
||||||
|
<IonCol size="3">
|
||||||
|
<IonIcon icon={pulseOutline} color="medium" style={{ fontSize: '2rem' }} />
|
||||||
|
</IonCol>
|
||||||
|
|
||||||
|
<IonCol size="9">
|
||||||
|
<IonCardSubtitle>Pressure</IonCardSubtitle>
|
||||||
|
<IonNote>
|
||||||
|
<IonSkeletonText animated style={{ height: '2rem', width: '90%' }} />
|
||||||
|
</IonNote>
|
||||||
|
</IonCol>
|
||||||
|
</IonRow>
|
||||||
|
</IonCol>
|
||||||
|
</IonRow>
|
||||||
|
</IonGrid>
|
||||||
|
</IonCardContent>
|
||||||
|
</IonCard>
|
||||||
|
</IonGrid>
|
||||||
|
);
|
40
03_source/mobile/src/pages/Demo2FaExample/index.tsx
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import { IonIcon, IonLabel, IonRouterOutlet, IonTabBar, IonTabButton, IonTabs } from '@ionic/react';
|
||||||
|
|
||||||
|
import { cloudOutline, searchOutline } from 'ionicons/icons';
|
||||||
|
import { Route, Redirect } from 'react-router';
|
||||||
|
|
||||||
|
import Tab1 from './AppPages/Tab1';
|
||||||
|
import Tab2 from './AppPages/Tab2';
|
||||||
|
|
||||||
|
import './style.scss';
|
||||||
|
|
||||||
|
function Demo2FaExample() {
|
||||||
|
return (
|
||||||
|
<IonTabs>
|
||||||
|
<IonRouterOutlet>
|
||||||
|
<Route exact path="/demo-weather-app/tab1">
|
||||||
|
<Tab1 />
|
||||||
|
</Route>
|
||||||
|
<Route exact path="/demo-weather-app/tab2">
|
||||||
|
<Tab2 />
|
||||||
|
</Route>
|
||||||
|
|
||||||
|
<Redirect exact path="/demo-weather-app" to="/demo-weather-app/tab1" />
|
||||||
|
</IonRouterOutlet>
|
||||||
|
|
||||||
|
{/* */}
|
||||||
|
<IonTabBar slot="bottom">
|
||||||
|
<IonTabButton tab="tab1" href="/demo-weather-app/tab1">
|
||||||
|
<IonIcon icon={cloudOutline} />
|
||||||
|
<IonLabel>Dashboard</IonLabel>
|
||||||
|
</IonTabButton>
|
||||||
|
<IonTabButton tab="tab2" href="/demo-weather-app/tab2">
|
||||||
|
<IonIcon icon={searchOutline} />
|
||||||
|
<IonLabel>Search</IonLabel>
|
||||||
|
</IonTabButton>
|
||||||
|
</IonTabBar>
|
||||||
|
</IonTabs>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Demo2FaExample;
|
103
03_source/mobile/src/pages/Demo2FaExample/style.scss
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
#about-page {
|
||||||
|
ion-toolbar {
|
||||||
|
position: absolute;
|
||||||
|
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
|
||||||
|
--background: transparent;
|
||||||
|
--color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
ion-toolbar ion-back-button,
|
||||||
|
ion-toolbar ion-button,
|
||||||
|
ion-toolbar ion-menu-button {
|
||||||
|
--color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.about-header {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
height: 30%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.about-header .about-image {
|
||||||
|
position: absolute;
|
||||||
|
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
|
||||||
|
background-position: center;
|
||||||
|
background-size: cover;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
|
||||||
|
opacity: 0;
|
||||||
|
|
||||||
|
transition: opacity 500ms ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.about-header .madison {
|
||||||
|
background-image: url('/assets/WeatherDemo/img/about/madison.jpg');
|
||||||
|
}
|
||||||
|
|
||||||
|
.about-header .austin {
|
||||||
|
background-image: url('/assets/WeatherDemo/img/about/austin.jpg');
|
||||||
|
}
|
||||||
|
|
||||||
|
.about-header .chicago {
|
||||||
|
background-image: url('/assets/WeatherDemo/img/about/chicago.jpg');
|
||||||
|
}
|
||||||
|
|
||||||
|
.about-header .seattle {
|
||||||
|
background-image: url('/assets/WeatherDemo/img/about/seattle.jpg');
|
||||||
|
}
|
||||||
|
|
||||||
|
.about-info {
|
||||||
|
position: relative;
|
||||||
|
margin-top: -10px;
|
||||||
|
border-radius: 10px;
|
||||||
|
background: var(--ion-background-color, #fff);
|
||||||
|
z-index: 2; // display rounded border above header image
|
||||||
|
}
|
||||||
|
|
||||||
|
.about-info h3 {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.about-info ion-list {
|
||||||
|
padding-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.about-info p {
|
||||||
|
line-height: 130%;
|
||||||
|
|
||||||
|
color: var(--ion-color-dark);
|
||||||
|
}
|
||||||
|
|
||||||
|
.about-info ion-icon {
|
||||||
|
margin-inline-end: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* iOS Only
|
||||||
|
*/
|
||||||
|
|
||||||
|
.ios .about-info {
|
||||||
|
--ion-padding: 19px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ios .about-info h3 {
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#date-input-popover {
|
||||||
|
--offset-y: -var(--ion-safe-area-bottom);
|
||||||
|
|
||||||
|
--max-width: 90%;
|
||||||
|
--width: 336px;
|
||||||
|
}
|
@@ -0,0 +1,96 @@
|
|||||||
|
import {
|
||||||
|
IonButton,
|
||||||
|
IonButtons,
|
||||||
|
IonCol,
|
||||||
|
IonContent,
|
||||||
|
IonHeader,
|
||||||
|
IonIcon,
|
||||||
|
IonPage,
|
||||||
|
IonRow,
|
||||||
|
IonTitle,
|
||||||
|
IonToolbar,
|
||||||
|
useIonRouter,
|
||||||
|
} from '@ionic/react';
|
||||||
|
|
||||||
|
import { Geolocation } from '@capacitor/geolocation';
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
import { SkeletonDashboard } from '../components/SkeletonDashboard';
|
||||||
|
import { chevronBackOutline, refreshOutline } from 'ionicons/icons';
|
||||||
|
import { CurrentWeather } from '../components/CurrentWeather';
|
||||||
|
|
||||||
|
function Tab1() {
|
||||||
|
const router = useIonRouter();
|
||||||
|
|
||||||
|
const [currentWeather, setCurrentWeather] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getCurrentPosition();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const getCurrentPosition = async () => {
|
||||||
|
setCurrentWeather(false);
|
||||||
|
const coordinates = await Geolocation.getCurrentPosition();
|
||||||
|
getAddress(coordinates.coords);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getAddress = async (coords) => {
|
||||||
|
const query = `${coords.latitude},${coords.longitude}`;
|
||||||
|
const response = await fetch(
|
||||||
|
`https://api.weatherapi.com/v1/current.json?key=f93eb660b2424258bf5155016210712&q=${query}`
|
||||||
|
);
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
console.log(data);
|
||||||
|
setCurrentWeather(data);
|
||||||
|
};
|
||||||
|
|
||||||
|
// const router = useIonRouter();
|
||||||
|
function handleBackClick() {
|
||||||
|
router.goBack();
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<IonPage>
|
||||||
|
<IonHeader>
|
||||||
|
<IonToolbar>
|
||||||
|
<IonTitle>My Weather</IonTitle>
|
||||||
|
|
||||||
|
<IonButtons slot="end">
|
||||||
|
<IonButton onClick={() => getCurrentPosition()}>
|
||||||
|
<IonIcon icon={refreshOutline} color="primary" />
|
||||||
|
</IonButton>
|
||||||
|
</IonButtons>
|
||||||
|
|
||||||
|
<IonButtons slot="start">
|
||||||
|
<IonButton onClick={() => handleBackClick()}>
|
||||||
|
<IonIcon icon={chevronBackOutline} color="primary" />
|
||||||
|
</IonButton>
|
||||||
|
</IonButtons>
|
||||||
|
</IonToolbar>
|
||||||
|
</IonHeader>
|
||||||
|
<IonContent fullscreen>
|
||||||
|
<IonHeader collapse="condense">
|
||||||
|
<IonToolbar>
|
||||||
|
<IonTitle size="large">Dashboard</IonTitle>
|
||||||
|
</IonToolbar>
|
||||||
|
</IonHeader>
|
||||||
|
|
||||||
|
<IonRow className="ion-margin-start ion-margin-end ion-justify-content-center ion-text-center">
|
||||||
|
<IonCol size="12">
|
||||||
|
<h4>Here's your location based weather</h4>
|
||||||
|
</IonCol>
|
||||||
|
</IonRow>
|
||||||
|
|
||||||
|
<div style={{ marginTop: '-1.5rem' }}>
|
||||||
|
{currentWeather ? (
|
||||||
|
<CurrentWeather currentWeather={currentWeather} />
|
||||||
|
) : (
|
||||||
|
<SkeletonDashboard />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</IonContent>
|
||||||
|
</IonPage>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Tab1;
|
@@ -0,0 +1,81 @@
|
|||||||
|
import {
|
||||||
|
IonButton,
|
||||||
|
IonCol,
|
||||||
|
IonContent,
|
||||||
|
IonHeader,
|
||||||
|
IonPage,
|
||||||
|
IonRow,
|
||||||
|
IonSearchbar,
|
||||||
|
IonTitle,
|
||||||
|
IonToolbar,
|
||||||
|
} from '@ionic/react';
|
||||||
|
import { useState } from 'react';
|
||||||
|
import { CurrentWeather } from '../components/CurrentWeather';
|
||||||
|
|
||||||
|
function Tab2() {
|
||||||
|
const [search, setSearch] = useState('');
|
||||||
|
const [currentWeather, setCurrentWeather] = useState(false);
|
||||||
|
|
||||||
|
const performSearch = async () => {
|
||||||
|
getAddress(search);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getAddress = async (city) => {
|
||||||
|
const response = await fetch(
|
||||||
|
`https://api.weatherapi.com/v1/current.json?key=f93eb660b2424258bf5155016210712&q=${city}&aqi=no`
|
||||||
|
);
|
||||||
|
const data = await response.json();
|
||||||
|
|
||||||
|
if (data && data.current && data.location) {
|
||||||
|
setCurrentWeather(data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<IonPage>
|
||||||
|
<IonHeader>
|
||||||
|
<IonToolbar>
|
||||||
|
<IonTitle>Search</IonTitle>
|
||||||
|
</IonToolbar>
|
||||||
|
</IonHeader>
|
||||||
|
<IonContent fullscreen>
|
||||||
|
<IonHeader collapse="condense">
|
||||||
|
<IonToolbar>
|
||||||
|
<IonTitle size="large">Search</IonTitle>
|
||||||
|
</IonToolbar>
|
||||||
|
</IonHeader>
|
||||||
|
|
||||||
|
<IonRow className="ion-justify-content-center ion-margin-top ion-align-items-center">
|
||||||
|
<IonCol size="7">
|
||||||
|
<IonSearchbar
|
||||||
|
placeholder="Try 'London'"
|
||||||
|
animated
|
||||||
|
value={search}
|
||||||
|
onIonChange={(e) => setSearch(e.target.value)}
|
||||||
|
/>
|
||||||
|
</IonCol>
|
||||||
|
|
||||||
|
<IonCol size="5">
|
||||||
|
<IonButton
|
||||||
|
expand="block"
|
||||||
|
className="ion-margin-start ion-margin-end"
|
||||||
|
onClick={performSearch}
|
||||||
|
>
|
||||||
|
Search
|
||||||
|
</IonButton>
|
||||||
|
</IonCol>
|
||||||
|
</IonRow>
|
||||||
|
|
||||||
|
<div style={{ marginTop: '-0.8rem' }}>
|
||||||
|
{currentWeather ? (
|
||||||
|
<CurrentWeather currentWeather={currentWeather} />
|
||||||
|
) : (
|
||||||
|
<h3 className="ion-text-center">Your search result will appear here</h3>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</IonContent>
|
||||||
|
</IonPage>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Tab2;
|
@@ -0,0 +1,29 @@
|
|||||||
|
import { IonAccordion, IonAccordionGroup, IonIcon, IonItem, IonLabel, IonList } from '@ionic/react';
|
||||||
|
import { topics } from '../data';
|
||||||
|
|
||||||
|
export const Accordion = () => {
|
||||||
|
return (
|
||||||
|
<IonAccordionGroup>
|
||||||
|
{topics.map((topic, index) => {
|
||||||
|
return (
|
||||||
|
<IonAccordion key={`accordion_${index}`} value={topic.header.toLowerCase()}>
|
||||||
|
<IonItem slot="header">
|
||||||
|
<IonIcon icon={topic.icon} color={topic.color} />
|
||||||
|
<IonLabel className="ion-padding-start">{topic.header}</IonLabel>
|
||||||
|
</IonItem>
|
||||||
|
|
||||||
|
<IonList slot="content">
|
||||||
|
{topic.options.map((option, index2) => {
|
||||||
|
return (
|
||||||
|
<IonItem key={`option_${index}_${index2}`} routerLink={`/topics/${option.label}`}>
|
||||||
|
<IonLabel>{option.label}</IonLabel>
|
||||||
|
</IonItem>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</IonList>
|
||||||
|
</IonAccordion>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</IonAccordionGroup>
|
||||||
|
);
|
||||||
|
};
|
@@ -0,0 +1,30 @@
|
|||||||
|
import { IonAccordion, IonAccordionGroup, IonIcon, IonItem, IonLabel, IonList } from '@ionic/react';
|
||||||
|
import { topics } from '../data';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
export const Accordion: React.FC = () => {
|
||||||
|
return (
|
||||||
|
<IonAccordionGroup>
|
||||||
|
{topics.map((topic: any, index: number) => {
|
||||||
|
return (
|
||||||
|
<IonAccordion key={`accordion_${index}`} value={topic.header.toLowerCase()}>
|
||||||
|
<IonItem slot="header">
|
||||||
|
<IonIcon icon={topic.icon} color={topic.color} />
|
||||||
|
<IonLabel className="ion-padding-start">{topic.header}</IonLabel>
|
||||||
|
</IonItem>
|
||||||
|
|
||||||
|
<IonList slot="content">
|
||||||
|
{topic.options.map((option: any, index2: number) => {
|
||||||
|
return (
|
||||||
|
<IonItem key={`option_${index}_${index2}`} routerLink={`/topics/${option.label}`}>
|
||||||
|
<IonLabel>{option.label}</IonLabel>
|
||||||
|
</IonItem>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</IonList>
|
||||||
|
</IonAccordion>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</IonAccordionGroup>
|
||||||
|
);
|
||||||
|
};
|
@@ -0,0 +1,62 @@
|
|||||||
|
import { IonCardSubtitle, IonCol, IonIcon, IonNote, IonRow } from '@ionic/react';
|
||||||
|
import { pulseOutline, sunnyOutline, thermometerOutline } from 'ionicons/icons';
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
|
export const WeatherProperty = ({ type, currentWeather }: { type: any; currentWeather: any }) => {
|
||||||
|
const [property, setProperty] = useState(false);
|
||||||
|
|
||||||
|
const properties = {
|
||||||
|
wind: {
|
||||||
|
isIcon: false,
|
||||||
|
icon: '/assets/WeatherDemo/wind.png',
|
||||||
|
alt: 'wind',
|
||||||
|
label: 'Wind',
|
||||||
|
value: `${currentWeather.current.wind_mph}mph`,
|
||||||
|
},
|
||||||
|
feelsLike: {
|
||||||
|
isIcon: true,
|
||||||
|
icon: thermometerOutline,
|
||||||
|
alt: 'feels like',
|
||||||
|
label: 'Feels like',
|
||||||
|
value: `${currentWeather.current.feelslike_c}°C`,
|
||||||
|
},
|
||||||
|
indexUV: {
|
||||||
|
isIcon: true,
|
||||||
|
icon: sunnyOutline,
|
||||||
|
alt: 'index uv',
|
||||||
|
label: 'Index UV',
|
||||||
|
value: currentWeather.current.uv,
|
||||||
|
},
|
||||||
|
pressure: {
|
||||||
|
isIcon: true,
|
||||||
|
icon: pulseOutline,
|
||||||
|
alt: 'pressure',
|
||||||
|
label: 'Pressure',
|
||||||
|
value: `${currentWeather.current.pressure_mb} mbar`,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setProperty(properties[type]);
|
||||||
|
}, [type]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<IonCol size="6">
|
||||||
|
<IonRow className="ion-justify-content-center ion-align-items-center">
|
||||||
|
<IonCol size="3">
|
||||||
|
{!property.isIcon && (
|
||||||
|
<img alt={property.alt} src={property.icon} height="32" width="32" />
|
||||||
|
)}
|
||||||
|
{property.isIcon && (
|
||||||
|
<IonIcon icon={property.icon} color="medium" style={{ fontSize: '2rem' }} />
|
||||||
|
)}
|
||||||
|
</IonCol>
|
||||||
|
|
||||||
|
<IonCol size="9">
|
||||||
|
<IonCardSubtitle>{property.label}</IonCardSubtitle>
|
||||||
|
<IonNote>{property.value}</IonNote>
|
||||||
|
</IonCol>
|
||||||
|
</IonRow>
|
||||||
|
</IonCol>
|
||||||
|
);
|
||||||
|
};
|