diff --git a/.github/workflows/cd.yaml b/.github/workflows/cd.yaml
index 2e23564..92430e0 100644
--- a/.github/workflows/cd.yaml
+++ b/.github/workflows/cd.yaml
@@ -28,8 +28,8 @@ jobs:
restore-keys: |
${{ runner.os }}-gems-
- - name: Install Fastlane 🏎️
- run: gem install fastlane
+ - name: Install Dependencies via Bundler 📦
+ run: bundle install
ios_beta_deploy:
name: "Deployment: Deploying iOS Beta 🖥️✈️"
@@ -39,13 +39,7 @@ jobs:
- name: Checkout Code 🛒
uses: actions/checkout@v2
- # Repeat the setup steps, including restoring the cache
- - name: Set up Ruby 💎
- uses: ruby/setup-ruby@v1
- with:
- ruby-version: '2.7'
-
- - name: Restore Cache
+ - name: Restore Ruby Cache 💎
uses: actions/cache@v2
with:
path: vendor/bundle
@@ -54,7 +48,7 @@ jobs:
${{ runner.os }}-gems-
- name: iOS Beta Deployment 🖥️✈️
- run: fastlane ios beta
+ run: bundle exec fastlane ios beta
env:
FASTLANE_PASSWORD: ${{ secrets.FASTLANE_PASSWORD }}
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
@@ -67,13 +61,7 @@ jobs:
- name: Checkout Code 🛒
uses: actions/checkout@v2
- # Repeat the setup steps, including restoring the cache
- - name: Set up Ruby 💎
- uses: ruby/setup-ruby@v1
- with:
- ruby-version: '2.7'
-
- - name: Restore Cache
+ - name: Restore Ruby Cache 💎
uses: actions/cache@v2
with:
path: vendor/bundle
@@ -82,7 +70,7 @@ jobs:
${{ runner.os }}-gems-
- name: Android Beta Deployment 🤖✈️
- run: fastlane android beta
+ run: bundle exec fastlane android beta
env:
FASTLANE_PASSWORD: ${{ secrets.FASTLANE_PASSWORD }}
JSON_KEY_DATA: ${{ secrets.JSON_KEY_DATA }}
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
index 96bec6b..c3f3c72 100644
--- a/.github/workflows/release.yaml
+++ b/.github/workflows/release.yaml
@@ -20,8 +20,16 @@ jobs:
with:
ruby-version: '2.7'
- - name: Install Fastlane 🏎️
- run: gem install fastlane
+ - name: Cache Ruby Gems
+ uses: actions/cache@v2
+ with:
+ path: vendor/bundle
+ key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}
+ restore-keys: |
+ ${{ runner.os }}-gems-
+
+ - name: Install Dependencies via Bundler 📦
+ run: bundle install
ios_production:
name: "Deployment: Deploying iOS Production Release 🖥️🚀"
@@ -31,16 +39,16 @@ jobs:
- name: Checkout Code 🛒
uses: actions/checkout@v2
- - name: Set up Ruby 💎
- uses: ruby/setup-ruby@v1
+ - name: Restore Ruby Cache 💎
+ uses: actions/cache@v2
with:
- ruby-version: '2.7'
-
- - name: Install Fastlane 🏎️
- run: gem install fastlane
+ path: vendor/bundle
+ key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}
+ restore-keys: |
+ ${{ runner.os }}-gems-
- name: iOS Production Deployment 🖥️🚀
- run: fastlane ios release
+ run: bundle exec fastlane ios release
env:
FASTLANE_PASSWORD: ${{ secrets.FASTLANE_PASSWORD }}
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
@@ -53,16 +61,16 @@ jobs:
- name: Checkout Code 🛒
uses: actions/checkout@v2
- - name: Set up Ruby 💎
- uses: ruby/setup-ruby@v1
+ - name: Restore Ruby Cache 💎
+ uses: actions/cache@v2
with:
- ruby-version: '2.7'
-
- - name: Install Fastlane 🏎️
- run: gem install fastlane
+ path: vendor/bundle
+ key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}
+ restore-keys: |
+ ${{ runner.os }}-gems-
- name: Android Production Deployment 🤖🚀
- run: fastlane android release
+ run: bundle exec fastlane android release
env:
FASTLANE_PASSWORD: ${{ secrets.FASTLANE_PASSWORD }}
JSON_KEY_DATA: ${{ secrets.JSON_KEY_DATA }}
diff --git a/android.sh b/android.sh
new file mode 100755
index 0000000..ef78c7b
--- /dev/null
+++ b/android.sh
@@ -0,0 +1,53 @@
+#!/bin/bash
+
+# Name of the Emulator
+DEFAULT_EMULATOR_NAME="Pixel_7_Pro_API_33_1"
+
+# Path to your Android SDK tools
+ANDROID_SDK_PATH="$HOME/Library/Android/sdk"
+
+# Path to your React Native project
+PROJECT_PATH=""
+
+# List available Android simulators
+echo "Available Emulators:"
+$ANDROID_SDK_PATH/emulator/emulator -list-avds
+
+# Ask the user to choose an Emulator
+read -p "Please choose an emulator (default = $DEFAULT_EMULATOR_NAME): " EMULATOR_NAME
+
+# If no emulator is entered, use the default
+if [ -z "$EMULATOR_NAME" ]; then
+ EMULATOR_NAME="$DEFAULT_EMULATOR_NAME"
+fi
+
+echo "Using emulator: $EMULATOR_NAME"
+
+# Start the Emulator
+$ANDROID_SDK_PATH/emulator/emulator -avd $EMULATOR_NAME &
+
+# Wait for the emulator to finish booting
+$ANDROID_SDK_PATH/platform-tools/adb wait-for-device shell 'while [[ -z $(getprop sys.boot_completed) ]]; do sleep 1; done;'
+
+# Navigate to your project directory
+#cd $PROJECT_PATH
+
+# Default port
+PORT=8081
+
+# Check if port 8081 is in use, and if so, use port 8082
+if lsof -Pi :8081 -sTCP:LISTEN -t >/dev/null ; then
+ PORT=8082
+fi
+
+echo "Starting the React Native development server on port $PORT"
+
+# Start the React Native development server on the selected port
+npx react-native start --port $PORT &
+
+# Wait for a few seconds to ensure that the development server has started
+sleep 5
+
+# Run your React Native app
+REACT_NATIVE_PACKAGER_HOSTNAME="127.0.0.1:$PORT"
+npx react-native run-android
diff --git a/ios.sh b/ios.sh
new file mode 100755
index 0000000..eb161fe
--- /dev/null
+++ b/ios.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+
+# Default port
+PORT=8081
+
+# Check if port 8081 is in use, and if so, use port 8082
+if lsof -Pi :8081 -sTCP:LISTEN -t >/dev/null ; then
+ PORT=8082
+fi
+
+echo "Using port $PORT"
+
+# List available devices
+echo "Available devices:"
+xcrun simctl list devices
+
+DEFAULT_SIMULATOR_NAME="iPhone 15 Pro Max"
+
+# Ask the user to enter the device they want to use
+read -p "Enter the device you want to use (default: $DEFAULT_SIMULATOR_NAME): " SIMULATOR_NAME
+
+# If the user didn't enter anything, use the default simulator name
+if [ -z "$SIMULATOR_NAME" ]; then
+ SIMULATOR_NAME="$DEFAULT_SIMULATOR_NAME"
+fi
+
+echo "Using simulator: $SIMULATOR_NAME"
+
+# Open the iOS simulator
+xcrun simctl boot "$SIMULATOR_NAME" || echo "Failed to launch simulator"
+
+# Wait for a few seconds to ensure that the simulator has started
+sleep 5
+
+# Navigate to your project directory
+#cd $PROJECT_PATH
+
+# Start the React Native development server on the specified port
+npx react-native start --port $PORT &
+
+# Wait for a few seconds to ensure that the development server has started
+sleep 5
+
+# Run your React Native app on the simulator, specifying the port
+REACT_NATIVE_PACKAGER_HOSTNAME="127.0.0.1:$PORT" npx react-native run-ios --simulator="$SIMULATOR_NAME"
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index 2faff5f..6b61c86 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -375,6 +375,8 @@ PODS:
- React-jsinspector (0.72.6)
- React-logger (0.72.6):
- glog
+ - react-native-safe-area-context (4.7.4):
+ - React-Core
- React-NativeModulesApple (0.72.6):
- hermes-engine
- React-callinvoker
@@ -485,6 +487,43 @@ PODS:
- React-jsi (= 0.72.6)
- React-logger (= 0.72.6)
- React-perflogger (= 0.72.6)
+ - RNCMaskedView (0.1.11):
+ - React
+ - RNGestureHandler (2.13.4):
+ - RCT-Folly (= 2021.07.22.00)
+ - React-Core
+ - RNReanimated (3.5.4):
+ - DoubleConversion
+ - FBLazyVector
+ - glog
+ - hermes-engine
+ - RCT-Folly
+ - RCTRequired
+ - RCTTypeSafety
+ - React-callinvoker
+ - React-Core
+ - React-Core/DevSupport
+ - React-Core/RCTWebSocket
+ - React-CoreModules
+ - React-cxxreact
+ - React-hermes
+ - React-jsi
+ - React-jsiexecutor
+ - React-jsinspector
+ - React-RCTActionSheet
+ - React-RCTAnimation
+ - React-RCTAppDelegate
+ - React-RCTBlob
+ - React-RCTImage
+ - React-RCTLinking
+ - React-RCTNetwork
+ - React-RCTSettings
+ - React-RCTText
+ - ReactCommon/turbomodule/core
+ - Yoga
+ - RNScreens (3.27.0):
+ - RCT-Folly (= 2021.07.22.00)
+ - React-Core
- RNSVG (13.14.0):
- React-Core
- SocketRocket (0.6.1)
@@ -538,6 +577,7 @@ DEPENDENCIES:
- React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`)
- React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector`)
- React-logger (from `../node_modules/react-native/ReactCommon/logger`)
+ - react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`)
- React-NativeModulesApple (from `../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios`)
- React-perflogger (from `../node_modules/react-native/ReactCommon/reactperflogger`)
- React-RCTActionSheet (from `../node_modules/react-native/Libraries/ActionSheetIOS`)
@@ -555,6 +595,10 @@ DEPENDENCIES:
- React-runtimescheduler (from `../node_modules/react-native/ReactCommon/react/renderer/runtimescheduler`)
- React-utils (from `../node_modules/react-native/ReactCommon/react/utils`)
- ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`)
+ - "RNCMaskedView (from `../node_modules/@react-native-community/masked-view`)"
+ - RNGestureHandler (from `../node_modules/react-native-gesture-handler`)
+ - RNReanimated (from `../node_modules/react-native-reanimated`)
+ - RNScreens (from `../node_modules/react-native-screens`)
- RNSVG (from `../node_modules/react-native-svg`)
- Yoga (from `../node_modules/react-native/ReactCommon/yoga`)
@@ -619,6 +663,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon/jsinspector"
React-logger:
:path: "../node_modules/react-native/ReactCommon/logger"
+ react-native-safe-area-context:
+ :path: "../node_modules/react-native-safe-area-context"
React-NativeModulesApple:
:path: "../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios"
React-perflogger:
@@ -653,6 +699,14 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon/react/utils"
ReactCommon:
:path: "../node_modules/react-native/ReactCommon"
+ RNCMaskedView:
+ :path: "../node_modules/@react-native-community/masked-view"
+ RNGestureHandler:
+ :path: "../node_modules/react-native-gesture-handler"
+ RNReanimated:
+ :path: "../node_modules/react-native-reanimated"
+ RNScreens:
+ :path: "../node_modules/react-native-screens"
RNSVG:
:path: "../node_modules/react-native-svg"
Yoga:
@@ -692,6 +746,7 @@ SPEC CHECKSUMS:
React-jsiexecutor: 3bf18ff7cb03cd8dfdce08fbbc0d15058c1d71ae
React-jsinspector: 194e32c6aab382d88713ad3dd0025c5f5c4ee072
React-logger: cebf22b6cf43434e471dc561e5911b40ac01d289
+ react-native-safe-area-context: 2cd91d532de12acdb0a9cbc8d43ac72a8e4c897c
React-NativeModulesApple: 02e35e9a51e10c6422f04f5e4076a7c02243fff2
React-perflogger: e3596db7e753f51766bceadc061936ef1472edc3
React-RCTActionSheet: 17ab132c748b4471012abbcdcf5befe860660485
@@ -709,6 +764,10 @@ SPEC CHECKSUMS:
React-runtimescheduler: f23e337008403341177fc52ee4ca94e442c17ede
React-utils: fa59c9a3375fb6f4aeb66714fd3f7f76b43a9f16
ReactCommon: dd03c17275c200496f346af93a7b94c53f3093a4
+ RNCMaskedView: 0e1bc4bfa8365eba5fbbb71e07fbdc0555249489
+ RNGestureHandler: 6e46dde1f87e5f018a54fe5d40cd0e0b942b49ee
+ RNReanimated: ab2e96c6d5591c3dfbb38a464f54c8d17fb34a87
+ RNScreens: 3c2d122f5e08c192e254c510b212306da97d2581
RNSVG: d00c8f91c3cbf6d476451313a18f04d220d4f396
SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17
Yoga: b76f1acfda8212aa16b7e26bcce3983230c82603
diff --git a/metadata/en-US/description.txt b/metadata/en-US/description.txt
new file mode 100644
index 0000000..e69de29
diff --git a/metadata/en-US/title.txt b/metadata/en-US/title.txt
new file mode 100644
index 0000000..e69de29
diff --git a/package-lock.json b/package-lock.json
index 5ef6d1f..f41bec7 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,9 +8,19 @@
"name": "@jigsaw-innovations/jigsaw",
"version": "0.1.10",
"dependencies": {
+ "@react-native-community/masked-view": "^0.1.11",
+ "@react-navigation/bottom-tabs": "^6.5.11",
+ "@react-navigation/native": "^6.1.9",
+ "@react-navigation/stack": "^6.3.20",
+ "formik": "^2.4.5",
"react": "latest",
"react-native": "latest",
- "react-native-svg": "^13.14.0"
+ "react-native-gesture-handler": "^2.13.4",
+ "react-native-reanimated": "^3.5.4",
+ "react-native-safe-area-context": "^4.7.4",
+ "react-native-screens": "^3.27.0",
+ "react-native-svg": "^13.14.0",
+ "yup": "^1.3.2"
},
"devDependencies": {
"@babel/core": "^7.20.0",
@@ -1265,6 +1275,20 @@
"@babel/core": "^7.0.0-0"
}
},
+ "node_modules/@babel/plugin-transform-object-assign": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-assign/-/plugin-transform-object-assign-7.22.5.tgz",
+ "integrity": "sha512-iDhx9ARkXq4vhZ2CYOSnQXkmxkDgosLi3J8Z17mKz7LyzthtkdVchLD7WZ3aXeCuvJDOW3+1I5TpJmwIbF9MKQ==",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
"node_modules/@babel/plugin-transform-object-rest-spread": {
"version": "7.22.15",
"license": "MIT",
@@ -1860,6 +1884,17 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@egjs/hammerjs": {
+ "version": "2.0.17",
+ "resolved": "https://registry.npmjs.org/@egjs/hammerjs/-/hammerjs-2.0.17.tgz",
+ "integrity": "sha512-XQsZgjm2EcVUiZQf11UBJQfmZeEmOW8DpI1gsFeln6w0ae0ii4dMQEQ0kjl6DspdWX1aGY1/loyXnP0JS06e/A==",
+ "dependencies": {
+ "@types/hammerjs": "^2.0.36"
+ },
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
"node_modules/@eslint-community/eslint-utils": {
"version": "4.4.0",
"dev": true,
@@ -3672,6 +3707,16 @@
"version": "4.0.0",
"license": "ISC"
},
+ "node_modules/@react-native-community/masked-view": {
+ "version": "0.1.11",
+ "resolved": "https://registry.npmjs.org/@react-native-community/masked-view/-/masked-view-0.1.11.tgz",
+ "integrity": "sha512-rQfMIGSR/1r/SyN87+VD8xHHzDYeHaJq6elOSCAD+0iLagXkSI2pfA0LmSXP21uw5i3em7GkkRjfJ8wpqWXZNw==",
+ "deprecated": "Repository was moved to @react-native-masked-view/masked-view",
+ "peerDependencies": {
+ "react": ">=16.0",
+ "react-native": ">=0.57"
+ }
+ },
"node_modules/@react-native/assets-registry": {
"version": "0.72.0",
"license": "MIT"
@@ -4588,6 +4633,118 @@
"react-native": "*"
}
},
+ "node_modules/@react-navigation/bottom-tabs": {
+ "version": "6.5.11",
+ "resolved": "https://registry.npmjs.org/@react-navigation/bottom-tabs/-/bottom-tabs-6.5.11.tgz",
+ "integrity": "sha512-CBN/NOdxnMvmjw+AJQI1kltOYaClTZmGec5pQ3ZNTPX86ytbIOylDIITKMfTgHZcIEFQDymx1SHeS++PIL3Szw==",
+ "dependencies": {
+ "@react-navigation/elements": "^1.3.21",
+ "color": "^4.2.3",
+ "warn-once": "^0.1.0"
+ },
+ "peerDependencies": {
+ "@react-navigation/native": "^6.0.0",
+ "react": "*",
+ "react-native": "*",
+ "react-native-safe-area-context": ">= 3.0.0",
+ "react-native-screens": ">= 3.0.0"
+ }
+ },
+ "node_modules/@react-navigation/core": {
+ "version": "6.4.10",
+ "resolved": "https://registry.npmjs.org/@react-navigation/core/-/core-6.4.10.tgz",
+ "integrity": "sha512-oYhqxETRHNHKsipm/BtGL0LI43Hs2VSFoWMbBdHK9OqgQPjTVUitslgLcPpo4zApCcmBWoOLX2qPxhsBda644A==",
+ "dependencies": {
+ "@react-navigation/routers": "^6.1.9",
+ "escape-string-regexp": "^4.0.0",
+ "nanoid": "^3.1.23",
+ "query-string": "^7.1.3",
+ "react-is": "^16.13.0",
+ "use-latest-callback": "^0.1.7"
+ },
+ "peerDependencies": {
+ "react": "*"
+ }
+ },
+ "node_modules/@react-navigation/core/node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@react-navigation/core/node_modules/react-is": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
+ },
+ "node_modules/@react-navigation/elements": {
+ "version": "1.3.21",
+ "resolved": "https://registry.npmjs.org/@react-navigation/elements/-/elements-1.3.21.tgz",
+ "integrity": "sha512-eyS2C6McNR8ihUoYfc166O1D8VYVh9KIl0UQPI8/ZJVsStlfSTgeEEh+WXge6+7SFPnZ4ewzEJdSAHH+jzcEfg==",
+ "peerDependencies": {
+ "@react-navigation/native": "^6.0.0",
+ "react": "*",
+ "react-native": "*",
+ "react-native-safe-area-context": ">= 3.0.0"
+ }
+ },
+ "node_modules/@react-navigation/native": {
+ "version": "6.1.9",
+ "resolved": "https://registry.npmjs.org/@react-navigation/native/-/native-6.1.9.tgz",
+ "integrity": "sha512-AMuJDpwXE7UlfyhIXaUCCynXmv69Kb8NzKgKJO7v0k0L+u6xUTbt6xvshmJ79vsvaFyaEH9Jg5FMzek5/S5qNw==",
+ "dependencies": {
+ "@react-navigation/core": "^6.4.10",
+ "escape-string-regexp": "^4.0.0",
+ "fast-deep-equal": "^3.1.3",
+ "nanoid": "^3.1.23"
+ },
+ "peerDependencies": {
+ "react": "*",
+ "react-native": "*"
+ }
+ },
+ "node_modules/@react-navigation/native/node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@react-navigation/routers": {
+ "version": "6.1.9",
+ "resolved": "https://registry.npmjs.org/@react-navigation/routers/-/routers-6.1.9.tgz",
+ "integrity": "sha512-lTM8gSFHSfkJvQkxacGM6VJtBt61ip2XO54aNfswD+KMw6eeZ4oehl7m0me3CR9hnDE4+60iAZR8sAhvCiI3NA==",
+ "dependencies": {
+ "nanoid": "^3.1.23"
+ }
+ },
+ "node_modules/@react-navigation/stack": {
+ "version": "6.3.20",
+ "resolved": "https://registry.npmjs.org/@react-navigation/stack/-/stack-6.3.20.tgz",
+ "integrity": "sha512-vE6mgZzOgoa5Uy7ayT97Cj+ZIK7DK+JBYVuKUViILlWZy6IWK7HFDuqoChSbZ1ajTIfAxj/acVGg1jkbAKsToA==",
+ "dependencies": {
+ "@react-navigation/elements": "^1.3.21",
+ "color": "^4.2.3",
+ "warn-once": "^0.1.0"
+ },
+ "peerDependencies": {
+ "@react-navigation/native": "^6.0.0",
+ "react": "*",
+ "react-native": "*",
+ "react-native-gesture-handler": ">= 1.0.0",
+ "react-native-safe-area-context": ">= 3.0.0",
+ "react-native-screens": ">= 3.0.0"
+ }
+ },
"node_modules/@sideway/address": {
"version": "4.1.4",
"license": "BSD-3-Clause",
@@ -4671,6 +4828,20 @@
"@types/node": "*"
}
},
+ "node_modules/@types/hammerjs": {
+ "version": "2.0.43",
+ "resolved": "https://registry.npmjs.org/@types/hammerjs/-/hammerjs-2.0.43.tgz",
+ "integrity": "sha512-wqxfwHk83RS7+6OpytGdo5wqkqtvx+bGaIs1Rwm5NrtQHUfL4OgWs/5p0OipmjmT+fexePh37Ek+mqIpdNjQKA=="
+ },
+ "node_modules/@types/hoist-non-react-statics": {
+ "version": "3.3.4",
+ "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.4.tgz",
+ "integrity": "sha512-ZchYkbieA+7tnxwX/SCBySx9WwvWR8TaP5tb2jRAzwvLb/rWchGw3v0w3pqUbUvj0GCwW2Xz/AVPSk6kUGctXQ==",
+ "dependencies": {
+ "@types/react": "*",
+ "hoist-non-react-statics": "^3.3.0"
+ }
+ },
"node_modules/@types/istanbul-lib-coverage": {
"version": "2.0.5",
"license": "MIT"
@@ -4703,12 +4874,10 @@
},
"node_modules/@types/prop-types": {
"version": "15.7.9",
- "dev": true,
"license": "MIT"
},
"node_modules/@types/react": {
"version": "18.2.29",
- "dev": true,
"license": "MIT",
"dependencies": {
"@types/prop-types": "*",
@@ -4727,7 +4896,6 @@
},
"node_modules/@types/scheduler": {
"version": "0.16.4",
- "dev": true,
"license": "MIT"
},
"node_modules/@types/semver": {
@@ -5874,6 +6042,18 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/color": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
+ "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==",
+ "dependencies": {
+ "color-convert": "^2.0.1",
+ "color-string": "^1.9.0"
+ },
+ "engines": {
+ "node": ">=12.5.0"
+ }
+ },
"node_modules/color-convert": {
"version": "1.9.3",
"license": "MIT",
@@ -5885,6 +6065,31 @@
"version": "1.1.3",
"license": "MIT"
},
+ "node_modules/color-string": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
+ "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
+ "dependencies": {
+ "color-name": "^1.0.0",
+ "simple-swizzle": "^0.2.2"
+ }
+ },
+ "node_modules/color/node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color/node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+ },
"node_modules/colorette": {
"version": "1.4.0",
"license": "MIT"
@@ -6166,7 +6371,6 @@
},
"node_modules/csstype": {
"version": "3.1.2",
- "dev": true,
"license": "MIT"
},
"node_modules/dayjs": {
@@ -6195,6 +6399,14 @@
"node": ">=0.10.0"
}
},
+ "node_modules/decode-uri-component": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz",
+ "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==",
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
"node_modules/dedent": {
"version": "1.5.1",
"dev": true,
@@ -7153,7 +7365,6 @@
},
"node_modules/fast-deep-equal": {
"version": "3.1.3",
- "dev": true,
"license": "MIT"
},
"node_modules/fast-diff": {
@@ -7253,6 +7464,14 @@
"node": ">=8"
}
},
+ "node_modules/filter-obj": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz",
+ "integrity": "sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/finalhandler": {
"version": "1.1.2",
"license": "MIT",
@@ -7419,6 +7638,38 @@
"is-callable": "^1.1.3"
}
},
+ "node_modules/formik": {
+ "version": "2.4.5",
+ "resolved": "https://registry.npmjs.org/formik/-/formik-2.4.5.tgz",
+ "integrity": "sha512-Gxlht0TD3vVdzMDHwkiNZqJ7Mvg77xQNfmBRrNtvzcHZs72TJppSTDKHpImCMJZwcWPBJ8jSQQ95GJzXFf1nAQ==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://opencollective.com/formik"
+ }
+ ],
+ "dependencies": {
+ "@types/hoist-non-react-statics": "^3.3.1",
+ "deepmerge": "^2.1.1",
+ "hoist-non-react-statics": "^3.3.0",
+ "lodash": "^4.17.21",
+ "lodash-es": "^4.17.21",
+ "react-fast-compare": "^2.0.1",
+ "tiny-warning": "^1.0.2",
+ "tslib": "^2.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0"
+ }
+ },
+ "node_modules/formik/node_modules/deepmerge": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz",
+ "integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/fresh": {
"version": "0.5.2",
"license": "MIT",
@@ -7733,6 +7984,19 @@
"node": ">= 8"
}
},
+ "node_modules/hoist-non-react-statics": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
+ "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
+ "dependencies": {
+ "react-is": "^16.7.0"
+ }
+ },
+ "node_modules/hoist-non-react-statics/node_modules/react-is": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
+ },
"node_modules/html-escaper": {
"version": "2.0.2",
"dev": true,
@@ -10045,9 +10309,13 @@
},
"node_modules/lodash": {
"version": "4.17.21",
- "dev": true,
"license": "MIT"
},
+ "node_modules/lodash-es": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
+ "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
+ },
"node_modules/lodash.debounce": {
"version": "4.0.8",
"license": "MIT"
@@ -11100,6 +11368,23 @@
"version": "2.1.2",
"license": "MIT"
},
+ "node_modules/nanoid": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
+ "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
"node_modules/natural-compare": {
"version": "1.4.0",
"dev": true,
@@ -11700,6 +11985,11 @@
"version": "16.13.1",
"license": "MIT"
},
+ "node_modules/property-expr": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.6.tgz",
+ "integrity": "sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA=="
+ },
"node_modules/punycode": {
"version": "2.3.0",
"dev": true,
@@ -11723,6 +12013,23 @@
],
"license": "MIT"
},
+ "node_modules/query-string": {
+ "version": "7.1.3",
+ "resolved": "https://registry.npmjs.org/query-string/-/query-string-7.1.3.tgz",
+ "integrity": "sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==",
+ "dependencies": {
+ "decode-uri-component": "^0.2.2",
+ "filter-obj": "^1.1.0",
+ "split-on-first": "^1.0.0",
+ "strict-uri-encode": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/queue": {
"version": "6.0.2",
"license": "MIT",
@@ -11775,6 +12082,22 @@
"ws": "^7"
}
},
+ "node_modules/react-fast-compare": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz",
+ "integrity": "sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw=="
+ },
+ "node_modules/react-freeze": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/react-freeze/-/react-freeze-1.0.3.tgz",
+ "integrity": "sha512-ZnXwLQnGzrDpHBHiC56TXFXvmolPeMjTn1UOm610M4EXGzbEDR7oOIyS2ZiItgbs6eZc4oU/a0hpk8PrcKvv5g==",
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "react": ">=17.0.0"
+ }
+ },
"node_modules/react-is": {
"version": "18.2.0",
"license": "MIT"
@@ -11831,6 +12154,65 @@
"react": "18.2.0"
}
},
+ "node_modules/react-native-gesture-handler": {
+ "version": "2.13.4",
+ "resolved": "https://registry.npmjs.org/react-native-gesture-handler/-/react-native-gesture-handler-2.13.4.tgz",
+ "integrity": "sha512-smpYOVbvWABpq2H+lmDnfOLCTH934aUPO1w2/pQXvm1j+M/vmGQmvgRDJOpXcks17HLtNNKXD6tcODf3aPqDfA==",
+ "dependencies": {
+ "@egjs/hammerjs": "^2.0.17",
+ "hoist-non-react-statics": "^3.3.0",
+ "invariant": "^2.2.4",
+ "lodash": "^4.17.21",
+ "prop-types": "^15.7.2"
+ },
+ "peerDependencies": {
+ "react": "*",
+ "react-native": "*"
+ }
+ },
+ "node_modules/react-native-reanimated": {
+ "version": "3.5.4",
+ "resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-3.5.4.tgz",
+ "integrity": "sha512-8we9LLDO1o4Oj9/DICeEJ2K1tjfqkJagqQUglxeUAkol/HcEJ6PGxIrpBcNryLqCDYEcu6FZWld/FzizBIw6bg==",
+ "dependencies": {
+ "@babel/plugin-transform-object-assign": "^7.16.7",
+ "@babel/preset-typescript": "^7.16.7",
+ "convert-source-map": "^2.0.0",
+ "invariant": "^2.2.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0",
+ "@babel/plugin-proposal-nullish-coalescing-operator": "^7.0.0-0",
+ "@babel/plugin-proposal-optional-chaining": "^7.0.0-0",
+ "@babel/plugin-transform-arrow-functions": "^7.0.0-0",
+ "@babel/plugin-transform-shorthand-properties": "^7.0.0-0",
+ "@babel/plugin-transform-template-literals": "^7.0.0-0",
+ "react": "*",
+ "react-native": "*"
+ }
+ },
+ "node_modules/react-native-safe-area-context": {
+ "version": "4.7.4",
+ "resolved": "https://registry.npmjs.org/react-native-safe-area-context/-/react-native-safe-area-context-4.7.4.tgz",
+ "integrity": "sha512-3LR3DCq9pdzlbq6vsHGWBFehXAKDh2Ljug6jWhLWs1QFuJHM6AS2+mH2JfKlB2LqiSFZOBcZfHQFz0sGaA3uqg==",
+ "peerDependencies": {
+ "react": "*",
+ "react-native": "*"
+ }
+ },
+ "node_modules/react-native-screens": {
+ "version": "3.27.0",
+ "resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-3.27.0.tgz",
+ "integrity": "sha512-FzSUygZ7yLQyhDJZsl7wU68LwRpVtVdqOPWribmEU3Tf26FohFGGcfJx1D8lf2V2Teb8tI+IaLnXCKbyh2xffA==",
+ "dependencies": {
+ "react-freeze": "^1.0.0",
+ "warn-once": "^0.1.0"
+ },
+ "peerDependencies": {
+ "react": "*",
+ "react-native": "*"
+ }
+ },
"node_modules/react-native-svg": {
"version": "13.14.0",
"resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-13.14.0.tgz",
@@ -12422,6 +12804,19 @@
"version": "3.0.7",
"license": "ISC"
},
+ "node_modules/simple-swizzle": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
+ "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==",
+ "dependencies": {
+ "is-arrayish": "^0.3.1"
+ }
+ },
+ "node_modules/simple-swizzle/node_modules/is-arrayish": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
+ "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="
+ },
"node_modules/sisteransi": {
"version": "1.0.5",
"license": "MIT"
@@ -12461,6 +12856,14 @@
"source-map": "^0.6.0"
}
},
+ "node_modules/split-on-first": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz",
+ "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/sprintf-js": {
"version": "1.0.3",
"license": "BSD-3-Clause"
@@ -12510,6 +12913,14 @@
"node": ">= 0.6"
}
},
+ "node_modules/strict-uri-encode": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz",
+ "integrity": "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/string_decoder": {
"version": "1.3.0",
"license": "MIT",
@@ -12798,6 +13209,16 @@
"safe-buffer": "~5.1.0"
}
},
+ "node_modules/tiny-case": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/tiny-case/-/tiny-case-1.0.3.tgz",
+ "integrity": "sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q=="
+ },
+ "node_modules/tiny-warning": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz",
+ "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA=="
+ },
"node_modules/tmpl": {
"version": "1.0.5",
"license": "BSD-3-Clause"
@@ -12826,6 +13247,11 @@
"node": ">=0.6"
}
},
+ "node_modules/toposort": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz",
+ "integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg=="
+ },
"node_modules/tr46": {
"version": "0.0.3",
"license": "MIT"
@@ -13085,6 +13511,14 @@
"punycode": "^2.1.0"
}
},
+ "node_modules/use-latest-callback": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/use-latest-callback/-/use-latest-callback-0.1.7.tgz",
+ "integrity": "sha512-Hlrl0lskgZZpo2vIpZ4rA7qA/rAGn2PcDvDH1M47AogqMPB0qlGEdsa66AVkIUiEEDpfxA9/N6hY6MqtaNoqWA==",
+ "peerDependencies": {
+ "react": ">=16.8"
+ }
+ },
"node_modules/use-sync-external-store": {
"version": "1.2.0",
"license": "MIT",
@@ -13134,6 +13568,11 @@
"makeerror": "1.0.12"
}
},
+ "node_modules/warn-once": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/warn-once/-/warn-once-0.1.1.tgz",
+ "integrity": "sha512-VkQZJbO8zVImzYFteBXvBOZEl1qL175WH8VmZcxF2fZAoudNhNDvHi+doCaAEdU2l2vtcIwa2zn0QK5+I1HQ3Q=="
+ },
"node_modules/wcwidth": {
"version": "1.0.1",
"license": "MIT",
@@ -13380,6 +13819,28 @@
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
+ },
+ "node_modules/yup": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/yup/-/yup-1.3.2.tgz",
+ "integrity": "sha512-6KCM971iQtJ+/KUaHdrhVr2LDkfhBtFPRnsG1P8F4q3uUVQ2RfEM9xekpha9aA4GXWJevjM10eDcPQ1FfWlmaQ==",
+ "dependencies": {
+ "property-expr": "^2.0.5",
+ "tiny-case": "^1.0.3",
+ "toposort": "^2.0.2",
+ "type-fest": "^2.19.0"
+ }
+ },
+ "node_modules/yup/node_modules/type-fest": {
+ "version": "2.19.0",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz",
+ "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==",
+ "engines": {
+ "node": ">=12.20"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
}
}
}
diff --git a/package.json b/package.json
index 1063418..730a631 100644
--- a/package.json
+++ b/package.json
@@ -19,9 +19,19 @@
"test": "jest"
},
"dependencies": {
+ "@react-native-community/masked-view": "^0.1.11",
+ "@react-navigation/bottom-tabs": "^6.5.11",
+ "@react-navigation/native": "^6.1.9",
+ "@react-navigation/stack": "^6.3.20",
+ "formik": "^2.4.5",
"react": "latest",
"react-native": "latest",
- "react-native-svg": "^13.14.0"
+ "react-native-gesture-handler": "^2.13.4",
+ "react-native-reanimated": "^3.5.4",
+ "react-native-safe-area-context": "^4.7.4",
+ "react-native-screens": "^3.27.0",
+ "react-native-svg": "^13.14.0",
+ "yup": "^1.3.2"
},
"devDependencies": {
"@babel/core": "^7.20.0",
diff --git a/shutdown.sh b/shutdown.sh
new file mode 100755
index 0000000..5fa7b30
--- /dev/null
+++ b/shutdown.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+# Path to your Android SDK tools if not already exported
+export ANDROID_HOME=$HOME/Library/Android/sdk
+
+# Shutdown all iOS simulators
+echo "Shutting down all iOS simulators..."
+xcrun simctl shutdown all
+
+# Shutdown all Android emulators
+echo "Shutting down all Android emulators..."
+$ANDROID_HOME/emulator/emulator -list-avds | while read -r emulator; do
+ $ANDROID_HOME/platform-tools/adb -s "$emulator" emu kill
+done
+
+# Kill any process using ports 8081 or 8082
+# Kill any process using port 8081
+echo "Killing any processes using port 8081..."
+for pid in $(lsof -i :8081 -t); do
+ kill -9 $pid
+done
+
+# Kill any process using port 8082
+echo "Killing any processes using port 8082..."
+for pid in $(lsof -i :8082 -t); do
+ kill -9 $pid
+done
+
+echo "All simulators shut down, and relevant processes killed."
diff --git a/src/App.tsx b/src/App.tsx
index 0551729..3dd6e17 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -1,8 +1,8 @@
import React from 'react';
-import WelcomeScreen from './screens/WelcomeScreen';
+import BottomTabNavigator from './navigation/tabs/BottomTabNavigator';
const App = () => {
- return ;
+ return ;
};
export default App;
diff --git a/src/assets/icons/CalendarIcon.tsx b/src/assets/icons/CalendarIcon.tsx
new file mode 100644
index 0000000..695e215
--- /dev/null
+++ b/src/assets/icons/CalendarIcon.tsx
@@ -0,0 +1,8 @@
+import AbstractIcon from './AbstractIcon';
+
+class CalendarIcon extends AbstractIcon {
+ path() {
+ return 'M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 012.25-2.25h13.5A2.25 2.25 0 0121 7.5v11.25m-18 0A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75m-18 0v-7.5A2.25 2.25 0 015.25 9h13.5A2.25 2.25 0 0121 11.25v7.5m-9-6h.008v.008H12v-.008zM12 15h.008v.008H12V15zm0 2.25h.008v.008H12v-.008zM9.75 15h.008v.008H9.75V15zm0 2.25h.008v.008H9.75v-.008zM7.5 15h.008v.008H7.5V15zm0 2.25h.008v.008H7.5v-.008zm6.75-4.5h.008v.008h-.008v-.008zm0 2.25h.008v.008h-.008V15zm0 2.25h.008v.008h-.008v-.008zm2.25-4.5h.008v.008H16.5v-.008zm0 2.25h.008v.008H16.5V15z';
+ }
+}
+export default CalendarIcon;
diff --git a/src/assets/icons/CartIcon.tsx b/src/assets/icons/CartIcon.tsx
new file mode 100644
index 0000000..f57284e
--- /dev/null
+++ b/src/assets/icons/CartIcon.tsx
@@ -0,0 +1,8 @@
+import AbstractIcon from './AbstractIcon';
+
+class CartIcon extends AbstractIcon {
+ path() {
+ return 'M2.25 3h1.386c.51 0 .955.343 1.087.835l.383 1.437M7.5 14.25a3 3 0 00-3 3h15.75m-12.75-3h11.218c1.121-2.3 2.1-4.684 2.924-7.138a60.114 60.114 0 00-16.536-1.84M7.5 14.25L5.106 5.272M6 20.25a.75.75 0 11-1.5 0 .75.75 0 011.5 0zm12.75 0a.75.75 0 11-1.5 0 .75.75 0 011.5 0z';
+ }
+}
+export default CartIcon;
diff --git a/src/assets/icons/ClockIcon.tsx b/src/assets/icons/ClockIcon.tsx
new file mode 100644
index 0000000..22449e3
--- /dev/null
+++ b/src/assets/icons/ClockIcon.tsx
@@ -0,0 +1,8 @@
+import AbstractIcon from './AbstractIcon';
+
+class ClockIcon extends AbstractIcon {
+ path() {
+ return 'M12 6v6h4.5m4.5 0a9 9 0 11-18 0 9 9 0 0118 0z';
+ }
+}
+export default ClockIcon;
diff --git a/src/assets/icons/CloseIcon.tsx b/src/assets/icons/CloseIcon.tsx
new file mode 100644
index 0000000..a787e96
--- /dev/null
+++ b/src/assets/icons/CloseIcon.tsx
@@ -0,0 +1,8 @@
+import AbstractIcon from './AbstractIcon';
+
+class CloseIcon extends AbstractIcon {
+ path() {
+ return 'M6 18L18 6M6 6l12 12';
+ }
+}
+export default CloseIcon;
diff --git a/src/assets/icons/DownloadIcon.tsx b/src/assets/icons/DownloadIcon.tsx
new file mode 100644
index 0000000..dafdf6a
--- /dev/null
+++ b/src/assets/icons/DownloadIcon.tsx
@@ -0,0 +1,8 @@
+import AbstractIcon from './AbstractIcon';
+
+class DownloadIcon extends AbstractIcon {
+ path() {
+ return 'M3 16.5v2.25A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75V16.5M16.5 12L12 16.5m0 0L7.5 12m4.5 4.5V3';
+ }
+}
+export default DownloadIcon;
diff --git a/src/assets/icons/EditIcon.tsx b/src/assets/icons/EditIcon.tsx
new file mode 100644
index 0000000..f0de023
--- /dev/null
+++ b/src/assets/icons/EditIcon.tsx
@@ -0,0 +1,8 @@
+import AbstractIcon from './AbstractIcon';
+
+class EditIcon extends AbstractIcon {
+ path() {
+ return 'M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L10.582 16.07a4.5 4.5 0 01-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 011.13-1.897l8.932-8.931zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0115.75 21H5.25A2.25 2.25 0 013 18.75V8.25A2.25 2.25 0 015.25 6H10';
+ }
+}
+export default EditIcon;
diff --git a/src/assets/icons/EmailIcon.tsx b/src/assets/icons/EmailIcon.tsx
new file mode 100644
index 0000000..a54466d
--- /dev/null
+++ b/src/assets/icons/EmailIcon.tsx
@@ -0,0 +1,8 @@
+import AbstractIcon from './AbstractIcon';
+
+class Icon extends AbstractIcon {
+ path() {
+ return '';
+ }
+}
+export default Icon;
diff --git a/src/assets/icons/ExpandIcon.tsx b/src/assets/icons/ExpandIcon.tsx
new file mode 100644
index 0000000..94026b0
--- /dev/null
+++ b/src/assets/icons/ExpandIcon.tsx
@@ -0,0 +1,8 @@
+import AbstractIcon from './AbstractIcon';
+
+class ExpandIcon extends AbstractIcon {
+ path() {
+ return 'M3.75 3.75v4.5m0-4.5h4.5m-4.5 0L9 9M3.75 20.25v-4.5m0 4.5h4.5m-4.5 0L9 15M20.25 3.75h-4.5m4.5 0v4.5m0-4.5L15 9m5.25 11.25h-4.5m4.5 0v-4.5m0 4.5L15 15';
+ }
+}
+export default ExpandIcon;
diff --git a/src/assets/icons/FilterIcon.tsx b/src/assets/icons/FilterIcon.tsx
new file mode 100644
index 0000000..17f6d22
--- /dev/null
+++ b/src/assets/icons/FilterIcon.tsx
@@ -0,0 +1,8 @@
+import AbstractIcon from './AbstractIcon';
+
+class FilterIcon extends AbstractIcon {
+ path() {
+ return 'M10.5 6h9.75M10.5 6a1.5 1.5 0 11-3 0m3 0a1.5 1.5 0 10-3 0M3.75 6H7.5m3 12h9.75m-9.75 0a1.5 1.5 0 01-3 0m3 0a1.5 1.5 0 00-3 0m-3.75 0H7.5m9-6h3.75m-3.75 0a1.5 1.5 0 01-3 0m3 0a1.5 1.5 0 00-3 0m-9.75 0h9.75';
+ }
+}
+export default FilterIcon;
diff --git a/src/assets/icons/FolderIcon.tsx b/src/assets/icons/FolderIcon.tsx
new file mode 100644
index 0000000..741df61
--- /dev/null
+++ b/src/assets/icons/FolderIcon.tsx
@@ -0,0 +1,8 @@
+import AbstractIcon from './AbstractIcon';
+
+class FolderIcon extends AbstractIcon {
+ path() {
+ return 'M2.25 12.75V12A2.25 2.25 0 014.5 9.75h15A2.25 2.25 0 0121.75 12v.75m-8.69-6.44l-2.12-2.12a1.5 1.5 0 00-1.061-.44H4.5A2.25 2.25 0 002.25 6v12a2.25 2.25 0 002.25 2.25h15A2.25 2.25 0 0021.75 18V9a2.25 2.25 0 00-2.25-2.25h-5.379a1.5 1.5 0 01-1.06-.44z';
+ }
+}
+export default FolderIcon;
diff --git a/src/assets/icons/HeartIcon.tsx b/src/assets/icons/HeartIcon.tsx
new file mode 100644
index 0000000..ce007e8
--- /dev/null
+++ b/src/assets/icons/HeartIcon.tsx
@@ -0,0 +1,8 @@
+import AbstractIcon from './AbstractIcon';
+
+class HeartIcon extends AbstractIcon {
+ path() {
+ return 'M2.25 15.75l5.159-5.159a2.25 2.25 0 013.182 0l5.159 5.159m-1.5-1.5l1.409-1.409a2.25 2.25 0 013.182 0l2.909 2.909m-18 3.75h16.5a1.5 1.5 0 001.5-1.5V6a1.5 1.5 0 00-1.5-1.5H3.75A1.5 1.5 0 002.25 6v12a1.5 1.5 0 001.5 1.5zm10.5-11.25h.008v.008h-.008V8.25zm.375 0a.375.375 0 11-.75 0 .375.375 0 01.75 0z';
+ }
+}
+export default HeartIcon;
diff --git a/src/assets/icons/HomeIcon.tsx b/src/assets/icons/HomeIcon.tsx
index 2fd63d7..0b52f55 100644
--- a/src/assets/icons/HomeIcon.tsx
+++ b/src/assets/icons/HomeIcon.tsx
@@ -5,5 +5,4 @@ class HomeIcon extends AbstractIcon {
return 'M2.25 12l8.954-8.955c.44-.439 1.152-.439 1.591 0L21.75 12M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25';
}
}
-
export default HomeIcon;
diff --git a/src/assets/icons/ImageIcon.tsx b/src/assets/icons/ImageIcon.tsx
new file mode 100644
index 0000000..e022d43
--- /dev/null
+++ b/src/assets/icons/ImageIcon.tsx
@@ -0,0 +1,8 @@
+import AbstractIcon from './AbstractIcon';
+
+class ImageIcon extends AbstractIcon {
+ path() {
+ return 'M21 8.25c0-2.485-2.099-4.5-4.688-4.5-1.935 0-3.597 1.126-4.312 2.733-.715-1.607-2.377-2.733-4.313-2.733C5.1 3.75 3 5.765 3 8.25c0 7.22 9 12 9 12s9-4.78 9-12z';
+ }
+}
+export default ImageIcon;
diff --git a/src/assets/icons/InfoIcon.tsx b/src/assets/icons/InfoIcon.tsx
new file mode 100644
index 0000000..838b8e6
--- /dev/null
+++ b/src/assets/icons/InfoIcon.tsx
@@ -0,0 +1,8 @@
+import AbstractIcon from './AbstractIcon';
+
+class InfoIcon extends AbstractIcon {
+ path() {
+ return 'M11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008H12V8.25z';
+ }
+}
+export default InfoIcon;
diff --git a/src/assets/icons/LocationIcon.tsx b/src/assets/icons/LocationIcon.tsx
new file mode 100644
index 0000000..bdc30cf
--- /dev/null
+++ b/src/assets/icons/LocationIcon.tsx
@@ -0,0 +1,8 @@
+import AbstractIcon from './AbstractIcon';
+
+class LocationIcon extends AbstractIcon {
+ path() {
+ return 'M19.5 10.5c0 7.142-7.5 11.25-7.5 11.25S4.5 17.642 4.5 10.5a7.5 7.5 0 1115 0z M15 10.5a3 3 0 11-6 0 3 3 0 016 0z';
+ }
+}
+export default LocationIcon;
diff --git a/src/assets/icons/LockIcon.tsx b/src/assets/icons/LockIcon.tsx
new file mode 100644
index 0000000..6df47fe
--- /dev/null
+++ b/src/assets/icons/LockIcon.tsx
@@ -0,0 +1,9 @@
+import AbstractIcon from './AbstractIcon';
+
+class LockIcon extends AbstractIcon {
+ path() {
+ return 'M16.5 10.5V6.75a4.5 4.5 0 10-9 0v3.75m-.75 11.25h10.5a2.25 2.25 0 002.25-2.25v-6.75a2.25 2.25 0 00-2.25-2.25H6.75a2.25 2.25 0 00-2.25 2.25v6.75a2.25 2.25 0 002.25 2.25z';
+ }
+}
+
+export default LockIcon;
diff --git a/src/assets/icons/MenuIcon.tsx b/src/assets/icons/MenuIcon.tsx
new file mode 100644
index 0000000..a294286
--- /dev/null
+++ b/src/assets/icons/MenuIcon.tsx
@@ -0,0 +1,8 @@
+import AbstractIcon from './AbstractIcon';
+
+class MenuIcon extends AbstractIcon {
+ path() {
+ return 'M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5';
+ }
+}
+export default MenuIcon;
diff --git a/src/assets/icons/MinusIcon.tsx b/src/assets/icons/MinusIcon.tsx
new file mode 100644
index 0000000..f93944c
--- /dev/null
+++ b/src/assets/icons/MinusIcon.tsx
@@ -0,0 +1,8 @@
+import AbstractIcon from './AbstractIcon';
+
+class MinusIcon extends AbstractIcon {
+ path() {
+ return 'M19.5 12h-15';
+ }
+}
+export default MinusIcon;
diff --git a/src/assets/icons/PlusIcon.tsx b/src/assets/icons/PlusIcon.tsx
new file mode 100644
index 0000000..f793337
--- /dev/null
+++ b/src/assets/icons/PlusIcon.tsx
@@ -0,0 +1,8 @@
+import AbstractIcon from './AbstractIcon';
+
+class PlusIcon extends AbstractIcon {
+ path() {
+ return 'M12 4.5v15m7.5-7.5h-15';
+ }
+}
+export default PlusIcon;
diff --git a/src/assets/icons/ProfileIcon.tsx b/src/assets/icons/ProfileIcon.tsx
new file mode 100644
index 0000000..af3f10b
--- /dev/null
+++ b/src/assets/icons/ProfileIcon.tsx
@@ -0,0 +1,8 @@
+import AbstractIcon from './AbstractIcon';
+
+class ProfileIcon extends AbstractIcon {
+ path() {
+ return 'M15.75 6a3.75 3.75 0 11-7.5 0 3.75 3.75 0 017.5 0zM4.501 20.118a7.5 7.5 0 0114.998 0A17.933 17.933 0 0112 21.75c-2.676 0-5.216-.584-7.499-1.632z';
+ }
+}
+export default ProfileIcon;
diff --git a/src/assets/icons/RefreshIcon.tsx b/src/assets/icons/RefreshIcon.tsx
new file mode 100644
index 0000000..1bd4079
--- /dev/null
+++ b/src/assets/icons/RefreshIcon.tsx
@@ -0,0 +1,8 @@
+import AbstractIcon from './AbstractIcon';
+
+class RefreshIcon extends AbstractIcon {
+ path() {
+ return 'M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0l3.181 3.183a8.25 8.25 0 0013.803-3.7M4.031 9.865a8.25 8.25 0 0113.803-3.7l3.181 3.182m0-4.991v4.99';
+ }
+}
+export default RefreshIcon;
diff --git a/src/assets/icons/SearchIcon.tsx b/src/assets/icons/SearchIcon.tsx
new file mode 100644
index 0000000..ae8546c
--- /dev/null
+++ b/src/assets/icons/SearchIcon.tsx
@@ -0,0 +1,8 @@
+import AbstractIcon from './AbstractIcon';
+
+class SearchIcon extends AbstractIcon {
+ path() {
+ return 'M21 21l-5.197-5.197m0 0A7.5 7.5 0 105.196 5.196a7.5 7.5 0 0010.607 10.607z';
+ }
+}
+export default SearchIcon;
diff --git a/src/assets/icons/SettingsIcon.tsx b/src/assets/icons/SettingsIcon.tsx
index 2459eb0..5dcea71 100644
--- a/src/assets/icons/SettingsIcon.tsx
+++ b/src/assets/icons/SettingsIcon.tsx
@@ -5,5 +5,4 @@ class SettingsIcon extends AbstractIcon {
return 'M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.324.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 011.37.49l1.296 2.247a1.125 1.125 0 01-.26 1.431l-1.003.827c-.293.24-.438.613-.431.992a6.759 6.759 0 010 .255c-.007.378.138.75.43.99l1.005.828c.424.35.534.954.26 1.43l-1.298 2.247a1.125 1.125 0 01-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.57 6.57 0 01-.22.128c-.331.183-.581.495-.644.869l-.213 1.28c-.09.543-.56.941-1.11.941h-2.594c-.55 0-1.02-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 01-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 01-1.369-.49l-1.297-2.247a1.125 1.125 0 01.26-1.431l1.004-.827c.292-.24.437-.613.43-.992a6.932 6.932 0 010-.255c.007-.378-.138-.75-.43-.99l-1.004-.828a1.125 1.125 0 01-.26-1.43l1.297-2.247a1.125 1.125 0 011.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.087.22-.128.332-.183.582-.495.644-.869l.214-1.281z M15 12a3 3 0 11-6 0 3 3 0 016 0z';
}
}
-
export default SettingsIcon;
diff --git a/src/assets/icons/ThrashIcon.tsx b/src/assets/icons/ThrashIcon.tsx
new file mode 100644
index 0000000..df7f16e
--- /dev/null
+++ b/src/assets/icons/ThrashIcon.tsx
@@ -0,0 +1,8 @@
+import AbstractIcon from './AbstractIcon';
+
+class ThrashIcon extends AbstractIcon {
+ path() {
+ return 'M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0';
+ }
+}
+export default ThrashIcon;
diff --git a/src/assets/icons/ThumbsDownIcon.tsx b/src/assets/icons/ThumbsDownIcon.tsx
new file mode 100644
index 0000000..0ee3bb6
--- /dev/null
+++ b/src/assets/icons/ThumbsDownIcon.tsx
@@ -0,0 +1,8 @@
+import AbstractIcon from './AbstractIcon';
+
+class ThumbsDownIcon extends AbstractIcon {
+ path() {
+ return 'M7.5 15h2.25m8.024-9.75c.011.05.028.1.052.148.591 1.2.924 2.55.924 3.977a8.96 8.96 0 01-.999 4.125m.023-8.25c-.076-.365.183-.75.575-.75h.908c.889 0 1.713.518 1.972 1.368.339 1.11.521 2.287.521 3.507 0 1.553-.295 3.036-.831 4.398C20.613 14.547 19.833 15 19 15h-1.053c-.472 0-.745-.556-.5-.96a8.95 8.95 0 00.303-.54m.023-8.25H16.48a4.5 4.5 0 01-1.423-.23l-3.114-1.04a4.5 4.5 0 00-1.423-.23H6.504c-.618 0-1.217.247-1.605.729A11.95 11.95 0 002.25 12c0 .434.023.863.068 1.285C2.427 14.306 3.346 15 4.372 15h3.126c.618 0 .991.724.725 1.282A7.471 7.471 0 007.5 19.5a2.25 2.25 0 002.25 2.25.75.75 0 00.75-.75v-.633c0-.573.11-1.14.322-1.672.304-.76.93-1.33 1.653-1.715a9.04 9.04 0 002.86-2.4c.498-.634 1.226-1.08 2.032-1.08h.384';
+ }
+}
+export default ThumbsDownIcon;
diff --git a/src/assets/icons/ThumbsUpIcon.tsx b/src/assets/icons/ThumbsUpIcon.tsx
new file mode 100644
index 0000000..6c62052
--- /dev/null
+++ b/src/assets/icons/ThumbsUpIcon.tsx
@@ -0,0 +1,8 @@
+import AbstractIcon from './AbstractIcon';
+
+class ThumbsUpIcon extends AbstractIcon {
+ path() {
+ return 'M6.633 10.5c.806 0 1.533-.446 2.031-1.08a9.041 9.041 0 012.861-2.4c.723-.384 1.35-.956 1.653-1.715a4.498 4.498 0 00.322-1.672V3a.75.75 0 01.75-.75A2.25 2.25 0 0116.5 4.5c0 1.152-.26 2.243-.723 3.218-.266.558.107 1.282.725 1.282h3.126c1.026 0 1.945.694 2.054 1.715.045.422.068.85.068 1.285a11.95 11.95 0 01-2.649 7.521c-.388.482-.987.729-1.605.729H13.48c-.483 0-.964-.078-1.423-.23l-3.114-1.04a4.501 4.501 0 00-1.423-.23H5.904M14.25 9h2.25M5.904 18.75c.083.205.173.405.27.602.197.4-.078.898-.523.898h-.908c-.889 0-1.713-.518-1.972-1.368a12 12 0 01-.521-3.507c0-1.553.295-3.036.831-4.398C3.387 10.203 4.167 9.75 5 9.75h1.053c.472 0 .745.556.5.96a8.958 8.958 0 00-1.302 4.665c0 1.194.232 2.333.654 3.375z';
+ }
+}
+export default ThumbsUpIcon;
diff --git a/src/assets/icons/UnlockIcon.tsx b/src/assets/icons/UnlockIcon.tsx
new file mode 100644
index 0000000..36839b5
--- /dev/null
+++ b/src/assets/icons/UnlockIcon.tsx
@@ -0,0 +1,8 @@
+import AbstractIcon from './AbstractIcon';
+
+class UnlockIcon extends AbstractIcon {
+ path() {
+ return 'M13.5 10.5V6.75a4.5 4.5 0 119 0v3.75M3.75 21.75h10.5a2.25 2.25 0 002.25-2.25v-6.75a2.25 2.25 0 00-2.25-2.25H3.75a2.25 2.25 0 00-2.25 2.25v6.75a2.25 2.25 0 002.25 2.25z';
+ }
+}
+export default UnlockIcon;
diff --git a/src/assets/icons/UploadIcon.tsx b/src/assets/icons/UploadIcon.tsx
new file mode 100644
index 0000000..30a082a
--- /dev/null
+++ b/src/assets/icons/UploadIcon.tsx
@@ -0,0 +1,9 @@
+import AbstractIcon from './AbstractIcon';
+
+class UploadIcon extends AbstractIcon {
+ path() {
+ return 'M3 16.5v2.25A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75V16.5m-13.5-9L12 3m0 0l4.5 4.5M12 3v13.5';
+ }
+}
+
+export default UploadIcon;
diff --git a/src/assets/icons/WarningIcon.tsx b/src/assets/icons/WarningIcon.tsx
new file mode 100644
index 0000000..bbf126b
--- /dev/null
+++ b/src/assets/icons/WarningIcon.tsx
@@ -0,0 +1,9 @@
+import AbstractIcon from './AbstractIcon';
+
+class WarningIcon extends AbstractIcon {
+ path() {
+ return 'M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z';
+ }
+}
+
+export default WarningIcon;
diff --git a/src/components/explicit/forms/LoginForm.tsx b/src/components/explicit/forms/LoginForm.tsx
new file mode 100644
index 0000000..8c09eb8
--- /dev/null
+++ b/src/components/explicit/forms/LoginForm.tsx
@@ -0,0 +1,56 @@
+import React from 'react';
+import {View, Button} from 'react-native';
+import {Formik, FormikProps} from 'formik';
+import {validationSchema} from './validationSchemas/LoginSchema';
+import TextInputField from '../inputs/TextInputField';
+
+interface FormValues {
+ email: string;
+ password: string;
+}
+
+export default function LoginForm() {
+ return (
+
+ initialValues={{email: '', password: ''}}
+ validationSchema={validationSchema}
+ onSubmit={(values: FormValues) => {
+ console.log('Form values:', values);
+ }}>
+ {({
+ handleChange,
+ handleBlur,
+ handleSubmit,
+ values,
+ errors,
+ touched,
+ }: FormikProps) => (
+
+
+
+
+ )}
+
+ );
+}
diff --git a/src/components/explicit/forms/validationSchemas/LoginSchema.tsx b/src/components/explicit/forms/validationSchemas/LoginSchema.tsx
new file mode 100644
index 0000000..afca300
--- /dev/null
+++ b/src/components/explicit/forms/validationSchemas/LoginSchema.tsx
@@ -0,0 +1,30 @@
+import * as Yup from 'yup';
+// import {validateHandle} from '../../../../services/api';
+
+interface ValidationSchemaShape {
+ email: string;
+ password: string;
+}
+
+// Validation schema using Yup
+export const validationSchema = Yup.object().shape({
+ email: Yup.string().email('Invalid email').required('Email is required'),
+ password: Yup.string()
+ .min(8, 'Password must be at least 8 characters long')
+ .max(30, 'Password must not exceed 30 characters')
+ .matches(/[A-Z]/, 'Password must contain at least one uppercase character')
+ .matches(
+ /[0-9!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]+/,
+ 'Password must contain at least one special character or number',
+ )
+ // .test(
+ // 'check-username',
+ // 'User with this username or email does not exist',
+ // async function (value: string) {
+ // return new Promise(resolve => {
+ // // validateHandle(value, resolve);
+ // });
+ // },
+ // )
+ .required('Password is required'),
+});
diff --git a/src/components/explicit/inputs/TextInputField.js b/src/components/explicit/inputs/TextInputField.js
new file mode 100644
index 0000000..9306fbb
--- /dev/null
+++ b/src/components/explicit/inputs/TextInputField.js
@@ -0,0 +1,57 @@
+// todo: Update the component to take in a style prop and base style off that prop
+import React from 'react';
+import {View, TextInput, StyleSheet, Text} from 'react-native';
+
+const TextInputField = ({
+ label,
+ placeholder,
+ handleChange,
+ handleBlur,
+ value,
+ touched,
+ error,
+ autoCapitalize,
+ ...props
+}) => {
+ const capitalizedLabel = label.charAt(0).toUpperCase() + label.slice(1);
+ return (
+
+ {capitalizedLabel}
+
+ {touched && error && {error}}
+
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ marginBottom: 16,
+ },
+ label: {
+ fontSize: 14,
+ fontWeight: 'bold',
+ marginBottom: 6,
+ },
+ textInput: {
+ height: 50,
+ backgroundColor: '#F5F5F5',
+ paddingHorizontal: 10,
+ borderRadius: 10,
+ width: '100%',
+ },
+ errorText: {
+ color: 'red',
+ fontSize: 10,
+ marginTop: 4,
+ },
+});
+
+export default TextInputField;
diff --git a/src/components/explicit/loaders/AbstractLoader.tsx b/src/components/explicit/loaders/AbstractLoader.tsx
new file mode 100644
index 0000000..d845df1
--- /dev/null
+++ b/src/components/explicit/loaders/AbstractLoader.tsx
@@ -0,0 +1,87 @@
+import React, {Component, RefObject} from 'react';
+import {View, StyleSheet, Modal} from 'react-native';
+import LottieView from 'lottie-react-native';
+
+interface LoaderProps {
+ backgroundColor?: string;
+ size?: {
+ width: number;
+ height: number;
+ };
+}
+
+interface LoaderState {
+ isPlaying: boolean;
+}
+
+export default abstract class AbstractLoader extends Component<
+ LoaderProps,
+ LoaderState
+> {
+ protected animationRef: RefObject = React.createRef();
+
+ constructor(props: LoaderProps) {
+ super(props);
+ this.state = {
+ isPlaying: true, // Consider using this state if needed.
+ };
+ }
+
+ componentDidMount() {
+ const currentAnimation = this.animationRef.current;
+ if (currentAnimation) {
+ currentAnimation.play(); // Start playing the animation
+ }
+ }
+
+ abstract getLottieSource(): any;
+
+ render() {
+ const {size, backgroundColor} = this.props;
+ const customStyle = {
+ width: size?.width || 120,
+ height: size?.height || 120,
+ backgroundColor: backgroundColor || 'rgba(0, 0, 0, 0.7)',
+ };
+
+ return (
+
+
+
+
+
+
+
+ );
+ }
+}
+
+const styles = StyleSheet.create({
+ container: {
+ position: 'absolute',
+ top: 0,
+ left: 0,
+ right: 0,
+ bottom: 0,
+ justifyContent: 'center',
+ alignItems: 'center',
+ zIndex: 999,
+ },
+ lottieWrapper: {
+ backgroundColor: 'rgba(0, 0, 0, 0.7)',
+ borderRadius: 10,
+ width: 120,
+ height: 120,
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+ lottie: {
+ width: 120,
+ height: 120,
+ },
+});
diff --git a/src/components/explicit/loaders/BouncingBallsLoader.tsx b/src/components/explicit/loaders/BouncingBallsLoader.tsx
new file mode 100644
index 0000000..e4a1b33
--- /dev/null
+++ b/src/components/explicit/loaders/BouncingBallsLoader.tsx
@@ -0,0 +1,8 @@
+import AbstractLoader from './AbstractLoader';
+import lottieAnimation from '../../../assets/animations/loaders/bouncing/bouncing.json';
+
+export default class BouncingBallsLoader extends AbstractLoader {
+ getLottieSource() {
+ return lottieAnimation;
+ }
+}
diff --git a/src/components/explicit/loaders/ShapeShifterLoader.tsx b/src/components/explicit/loaders/ShapeShifterLoader.tsx
new file mode 100644
index 0000000..07f27b7
--- /dev/null
+++ b/src/components/explicit/loaders/ShapeShifterLoader.tsx
@@ -0,0 +1,8 @@
+import AbstractLoader from './AbstractLoader';
+import lottieAnimation from '../../../assets/animations/loaders/shapeshifter/shapeshifter.json';
+
+export default class BouncingBallsLoader extends AbstractLoader {
+ getLottieSource() {
+ return lottieAnimation;
+ }
+}
diff --git a/src/components/latent/grids/Grid.tsx b/src/components/latent/grids/Grid.tsx
new file mode 100644
index 0000000..8659099
--- /dev/null
+++ b/src/components/latent/grids/Grid.tsx
@@ -0,0 +1,134 @@
+// TODO: resolve border radius not working
+// todo: move animation into seperate file, also in HorizontalCarousel.tsx
+import {ReactNode} from 'react';
+import React from 'react';
+import {
+ View,
+ Animated,
+ StyleSheet,
+ TouchableWithoutFeedback,
+} from 'react-native';
+
+interface GridItemProps {
+ children: React.ReactNode;
+ size?: 'small' | 'medium' | 'large';
+ rounded?: boolean;
+ toggleAnimation?: boolean;
+}
+
+const GridItem: React.FC = ({
+ children,
+ size = 'small',
+ rounded = true,
+ toggleAnimation = true,
+}) => {
+ const scaleAnim = new Animated.Value(1);
+ const brightnessAnim = new Animated.Value(1);
+
+ const handlePressIn = () => {
+ if (!toggleAnimation) {
+ return;
+ } // Skip animation if toggleAnimation is false
+
+ Animated.parallel([
+ Animated.timing(scaleAnim, {
+ toValue: 0.98,
+ duration: 150,
+ useNativeDriver: true,
+ }),
+ Animated.timing(brightnessAnim, {
+ toValue: 0.88,
+ duration: 150,
+ useNativeDriver: false,
+ }),
+ ]).start();
+ };
+
+ const handlePressOut = () => {
+ if (!toggleAnimation) {
+ return;
+ } // Skip animation if toggleAnimation is false
+
+ Animated.parallel([
+ Animated.timing(scaleAnim, {
+ toValue: 1,
+ duration: 150,
+ useNativeDriver: true,
+ }),
+ Animated.timing(brightnessAnim, {
+ toValue: 1,
+ duration: 150,
+ useNativeDriver: false,
+ }),
+ ]).start();
+ };
+
+ let itemStyle = styles.smallItem;
+
+ if (size === 'medium') {
+ itemStyle = styles.mediumItem;
+ } else if (size === 'large') {
+ itemStyle = styles.largeItem;
+ }
+
+ const borderRadiusStyle = rounded ? {borderRadius: 10} : {};
+
+ return (
+
+
+ {children}
+
+
+ );
+};
+
+interface GridProps {
+ numOfColumns: number;
+ children: ReactNode;
+}
+
+const Grid: React.FC = ({numOfColumns, children}) => {
+ const columnWidth = (100 / numOfColumns).toString() + '%'; // to satisfy TypeScript
+
+ // Wrap each child in a View with appropriate styles
+ const wrappedChildren = React.Children.map(children, (child, index) => {
+ // @ts-ignore
+ return {child}; // now this should be fine
+ });
+
+ return {wrappedChildren};
+};
+
+export {Grid, GridItem};
+
+const styles = StyleSheet.create({
+ container: {
+ flexDirection: 'row',
+ flexWrap: 'wrap',
+ marginHorizontal: 10,
+ paddingVertical: 10,
+ },
+ item: {
+ justifyContent: 'center',
+ alignItems: 'center',
+ height: 100,
+ margin: 5,
+ },
+ smallItem: {
+ height: 80,
+ },
+ mediumItem: {
+ height: 120,
+ },
+ largeItem: {
+ height: 160,
+ },
+});
diff --git a/src/components/latent/scrollers/SnapScrollView.tsx b/src/components/latent/scrollers/SnapScrollView.tsx
new file mode 100644
index 0000000..b50f1f6
--- /dev/null
+++ b/src/components/latent/scrollers/SnapScrollView.tsx
@@ -0,0 +1,56 @@
+import React, {useRef, ReactNode} from 'react';
+import {
+ View,
+ FlatList,
+ Dimensions,
+ NativeSyntheticEvent,
+ NativeScrollEvent,
+} from 'react-native';
+
+const {height} = Dimensions.get('window');
+
+interface SnapScrollItemProps {
+ children: ReactNode;
+}
+
+const SnapScrollItem: React.FC = ({children}) => (
+ {children}
+);
+
+interface SnapScrollProps {
+ children: ReactNode[];
+}
+
+const SnapScroll: React.FC = ({children}) => {
+ const flatListRef = useRef(null);
+
+ const handleScroll = (event: NativeSyntheticEvent) => {
+ const yOffset = event.nativeEvent.contentOffset.y;
+ const index = Math.round(yOffset / height);
+ flatListRef.current?.scrollToOffset({
+ offset: index * height,
+ animated: true,
+ });
+ };
+
+ return (
+ item}
+ keyExtractor={(_, index) => index.toString()}
+ snapToInterval={height}
+ decelerationRate="fast"
+ showsVerticalScrollIndicator={false}
+ onMomentumScrollEnd={handleScroll}
+ bounces={false} // Disables the bounce effect, and thus the overscroll
+ getItemLayout={(_, index) => ({
+ length: height,
+ offset: height * index,
+ index,
+ })}
+ />
+ );
+};
+
+export {SnapScrollItem, SnapScroll};
diff --git a/src/navigation/stacks/HomeStackNavigator.tsx b/src/navigation/stacks/HomeStackNavigator.tsx
new file mode 100644
index 0000000..a4ec11b
--- /dev/null
+++ b/src/navigation/stacks/HomeStackNavigator.tsx
@@ -0,0 +1,14 @@
+import {createStackNavigator} from '@react-navigation/stack';
+import HomeScreen from '../../screens/HomeScreen';
+
+const Stack = createStackNavigator();
+
+const HomeStackNavigator = () => {
+ return (
+
+
+
+ );
+};
+
+export default HomeStackNavigator;
diff --git a/src/navigation/stacks/ProfileStackNavigator.tsx b/src/navigation/stacks/ProfileStackNavigator.tsx
new file mode 100644
index 0000000..10f4f6f
--- /dev/null
+++ b/src/navigation/stacks/ProfileStackNavigator.tsx
@@ -0,0 +1,17 @@
+import React from 'react';
+import {createStackNavigator} from '@react-navigation/stack';
+import ProfileScreen from '../../screens/ProfileScreen';
+import SettingsScreen from '../../screens/SettingsScreen';
+
+const Stack = createStackNavigator();
+
+const ProfileStackNavigator = () => {
+ return (
+
+
+
+
+ );
+};
+
+export default ProfileStackNavigator;
diff --git a/src/navigation/tabs/BottomTabNavigator.tsx b/src/navigation/tabs/BottomTabNavigator.tsx
new file mode 100644
index 0000000..b273a67
--- /dev/null
+++ b/src/navigation/tabs/BottomTabNavigator.tsx
@@ -0,0 +1,73 @@
+import React from 'react';
+import {StyleSheet} from 'react-native';
+import {NavigationContainer} from '@react-navigation/native';
+import {createBottomTabNavigator} from '@react-navigation/bottom-tabs';
+import HomeIcon from '../../assets/icons/HomeIcon';
+import ProfileIcon from '../../assets/icons/ProfileIcon';
+import HomeStackNavigator from '../stacks/HomeStackNavigator';
+import ProfileStackNavigator from '../stacks/ProfileStackNavigator';
+
+enum RouteNames {
+ Home = 'HomeStack',
+ Profile = 'ProfileStack',
+}
+
+// types.ts
+type TabParamList = {
+ [RouteNames.Home]: undefined;
+ [RouteNames.Profile]: undefined;
+};
+
+const Tab = createBottomTabNavigator();
+
+const styles = StyleSheet.create({
+ labelStyle: {
+ fontSize: 12,
+ },
+ tabBarStyle: {
+ backgroundColor: 'white',
+ opacity: 0.8,
+ },
+});
+
+const screenOptions = {
+ tabBarActiveTintColor: '#e91e63',
+ tabBarInactiveTintColor: 'gray',
+ tabBarLabelStyle: styles.labelStyle,
+ tabBarStyle: styles.tabBarStyle,
+ headerShown: false
+};
+
+const BottomTabNavigator: React.FC = () => {
+ return (
+
+
+ (
+
+ ),
+ }}
+ />
+ (
+
+ ),
+ }}
+ />
+ {/* Other Tab.Screen components */}
+
+
+ );
+};
+
+export default BottomTabNavigator;
diff --git a/src/screens/HomeScreen.tsx b/src/screens/HomeScreen.tsx
new file mode 100644
index 0000000..0103657
--- /dev/null
+++ b/src/screens/HomeScreen.tsx
@@ -0,0 +1,36 @@
+import React from 'react';
+import { View, Text, StyleSheet, ScrollView } from 'react-native';
+import HomeIcon from '../assets/icons/HomeIcon';
+import SettingsIcon from '../assets/icons/SettingsIcon';
+
+const HomeScreen = () => {
+ return (
+
+
+ Welcome to <app_name>
+
+ Hello
+
+ {/* You can add more components here and they will be scrollable */}
+
+
+ );
+};
+
+const styles = StyleSheet.create({
+ scrollContainer: {
+ flex: 1,
+ backgroundColor: '#ffffff',
+ },
+ container: {
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+ welcomeText: {
+ fontSize: 20,
+ textAlign: 'center',
+ margin: 10,
+ },
+});
+
+export default HomeScreen;
diff --git a/src/screens/LandingScreen.tsx b/src/screens/LandingScreen.tsx
new file mode 100644
index 0000000..14146ea
--- /dev/null
+++ b/src/screens/LandingScreen.tsx
@@ -0,0 +1,57 @@
+import React, {useEffect} from 'react';
+import {View, Text, Animated, StyleSheet} from 'react-native';
+import {RouteProp} from '@react-navigation/native';
+import {StackNavigationProp} from '@react-navigation/stack';
+
+type LandingScreenStackParamList = {
+ Home: undefined;
+};
+
+type LandingScreenProps = {
+ navigation: StackNavigationProp;
+ route: RouteProp;
+};
+
+const LandingScreen: React.FC = ({navigation}) => {
+ const fadeAnim = new Animated.Value(0); // Initial value for opacity: 0
+
+ useEffect(() => {
+ Animated.timing(fadeAnim, {
+ toValue: 1,
+ duration: 2000,
+ useNativeDriver: true,
+ }).start(() => {
+ navigation.navigate('Home');
+ });
+ }, [fadeAnim]);
+
+ return (
+
+
+ Welcome!
+
+
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ justifyContent: 'center',
+ alignItems: 'center',
+ backgroundColor: '#f2f2f2',
+ },
+ box: {
+ width: 200,
+ height: 200,
+ backgroundColor: 'tomato',
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+ text: {
+ fontSize: 32,
+ color: 'white',
+ },
+});
+
+export default LandingScreen;
diff --git a/src/screens/LoginScreen.tsx b/src/screens/LoginScreen.tsx
new file mode 100644
index 0000000..6fd4f9c
--- /dev/null
+++ b/src/screens/LoginScreen.tsx
@@ -0,0 +1,64 @@
+import React from 'react';
+import {View, StyleSheet, TouchableOpacity, Text} from 'react-native';
+
+const LoginScreen: React.FC = () => {
+ const handleGoogleLogin = () => {
+ // Handle Google login logic here
+ console.log('Continue with Google');
+ };
+
+ const handleAppleLogin = () => {
+ // Handle Apple login logic here
+ console.log('Continue with Apple');
+ };
+
+ return (
+
+ Login
+
+
+ Continue with Google
+
+
+
+ Continue with Apple
+
+
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+ title: {
+ fontSize: 24,
+ marginBottom: 20,
+ },
+ button: {
+ width: 200,
+ height: 50,
+ justifyContent: 'center',
+ alignItems: 'center',
+ borderRadius: 5,
+ margin: 10,
+ },
+ googleButton: {
+ backgroundColor: '#4285F4',
+ },
+ appleButton: {
+ backgroundColor: '#000',
+ },
+ buttonText: {
+ color: '#fff',
+ fontSize: 16,
+ },
+});
+
+export default LoginScreen;
diff --git a/src/screens/ProfileScreen.tsx b/src/screens/ProfileScreen.tsx
new file mode 100644
index 0000000..bcefd34
--- /dev/null
+++ b/src/screens/ProfileScreen.tsx
@@ -0,0 +1,12 @@
+import React from 'react';
+import {View, Text} from 'react-native';
+
+const ProfileScreen = () => {
+ return (
+
+ Profile Screen
+
+ );
+};
+
+export default ProfileScreen;
diff --git a/src/screens/SettingsScreen.tsx b/src/screens/SettingsScreen.tsx
new file mode 100644
index 0000000..c6c8806
--- /dev/null
+++ b/src/screens/SettingsScreen.tsx
@@ -0,0 +1,12 @@
+import React from 'react';
+import {View, Text} from 'react-native';
+
+const SettingsScreen = () => {
+ return (
+
+ Settings Screen
+
+ );
+};
+
+export default SettingsScreen;
diff --git a/src/screens/WelcomeScreen.tsx b/src/screens/WelcomeScreen.tsx
deleted file mode 100644
index 32fa0f4..0000000
--- a/src/screens/WelcomeScreen.tsx
+++ /dev/null
@@ -1,31 +0,0 @@
-import React from 'react';
-import {View, Text, StyleSheet} from 'react-native';
-import HomeIcon from '../assets/icons/HomeIcon';
-import SettingsIcon from "../assets/icons/SettingsIcon";
-
-const WelcomeScreen = () => {
- return (
-
- Welcome to <app_name>
-
- Hello
-
-
- );
-};
-
-const styles = StyleSheet.create({
- container: {
- flex: 1,
- justifyContent: 'center',
- alignItems: 'center',
- backgroundColor: '#F5FCFF',
- },
- welcomeText: {
- fontSize: 20,
- textAlign: 'center',
- margin: 10,
- },
-});
-
-export default WelcomeScreen;