initial commit
2
.bundle/config
Normal file
@ -0,0 +1,2 @@
|
||||
BUNDLE_PATH: "vendor/bundle"
|
||||
BUNDLE_FORCE_RUBY_PLATFORM: 1
|
||||
9
.eslintrc.js
Normal file
@ -0,0 +1,9 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
extends: '@react-native',
|
||||
rules: {
|
||||
'react-hooks/exhaustive-deps': 'off',
|
||||
'prettier/prettier': 0,
|
||||
'@typescript-eslint/no-unused-vars': 'warn',
|
||||
},
|
||||
};
|
||||
66
.gitignore
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
# OSX
|
||||
#
|
||||
.DS_Store
|
||||
|
||||
# Xcode
|
||||
#
|
||||
build/
|
||||
*.pbxuser
|
||||
!default.pbxuser
|
||||
*.mode1v3
|
||||
!default.mode1v3
|
||||
*.mode2v3
|
||||
!default.mode2v3
|
||||
*.perspectivev3
|
||||
!default.perspectivev3
|
||||
xcuserdata
|
||||
*.xccheckout
|
||||
*.moved-aside
|
||||
DerivedData
|
||||
*.hmap
|
||||
*.ipa
|
||||
*.xcuserstate
|
||||
ios/.xcode.env.local
|
||||
|
||||
# Android/IntelliJ
|
||||
#
|
||||
build/
|
||||
.idea
|
||||
.gradle
|
||||
local.properties
|
||||
*.iml
|
||||
*.hprof
|
||||
.cxx/
|
||||
*.keystore
|
||||
!debug.keystore
|
||||
|
||||
# node.js
|
||||
#
|
||||
node_modules/
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
|
||||
# fastlane
|
||||
#
|
||||
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
|
||||
# screenshots whenever they are needed.
|
||||
# For more information about the recommended setup visit:
|
||||
# https://docs.fastlane.tools/best-practices/source-control/
|
||||
|
||||
**/fastlane/report.xml
|
||||
**/fastlane/Preview.html
|
||||
**/fastlane/screenshots
|
||||
**/fastlane/test_output
|
||||
|
||||
# Bundle artifact
|
||||
*.jsbundle
|
||||
|
||||
# Ruby / CocoaPods
|
||||
/ios/Pods/
|
||||
/vendor/bundle/
|
||||
|
||||
# Temporary files created by Metro to check the health of the file watcher
|
||||
.metro-health-check*
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
7
.prettierrc.js
Normal file
@ -0,0 +1,7 @@
|
||||
module.exports = {
|
||||
arrowParens: 'avoid',
|
||||
bracketSameLine: true,
|
||||
bracketSpacing: true,
|
||||
singleQuote: true,
|
||||
trailingComma: 'all',
|
||||
};
|
||||
1
.watchmanconfig
Normal file
@ -0,0 +1 @@
|
||||
{}
|
||||
81
App.tsx
Normal file
@ -0,0 +1,81 @@
|
||||
import 'react-native-gesture-handler';
|
||||
import React, { useEffect } from 'react';
|
||||
import { NavigationContainer } from '@react-navigation/native';
|
||||
import { createNativeStackNavigator } from '@react-navigation/native-stack';
|
||||
import { Provider } from 'react-redux';
|
||||
|
||||
import store from './src/store';
|
||||
|
||||
import Splash from './src/screens/Splash';
|
||||
import Main from './src/screens/Main';
|
||||
import Login from './src/screens/Login';
|
||||
import Help from './src/screens/Help';
|
||||
import Register from './src/screens/Register';
|
||||
import { PermissionsAndroid } from 'react-native';
|
||||
|
||||
const Stack = createNativeStackNavigator();
|
||||
|
||||
const App = (): JSX.Element => {
|
||||
const requestPermission = async () => {
|
||||
try {
|
||||
console.log('asking for permission');
|
||||
const granted = await PermissionsAndroid.requestMultiple([
|
||||
PermissionsAndroid.PERMISSIONS.CAMERA,
|
||||
PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,
|
||||
]);
|
||||
if (
|
||||
granted['android.permission.CAMERA'] &&
|
||||
granted['android.permission.WRITE_EXTERNAL_STORAGE']
|
||||
) {
|
||||
console.log('You can use the camera');
|
||||
} else {
|
||||
console.log('Camera permission denied');
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('permission error', error);
|
||||
}
|
||||
};
|
||||
useEffect(() => {
|
||||
requestPermission();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Provider store={store}>
|
||||
<NavigationContainer>
|
||||
<Stack.Navigator initialRouteName="Splash">
|
||||
<Stack.Screen
|
||||
name="Splash"
|
||||
component={Splash}
|
||||
options={{
|
||||
headerShown: false,
|
||||
}}
|
||||
/>
|
||||
<Stack.Screen
|
||||
name="Main"
|
||||
component={Main}
|
||||
options={{
|
||||
headerShown: false,
|
||||
}}
|
||||
/>
|
||||
<Stack.Screen
|
||||
name="Login"
|
||||
component={Login}
|
||||
options={{
|
||||
headerShown: false,
|
||||
}}
|
||||
/>
|
||||
<Stack.Screen name="Help" component={Help} />
|
||||
<Stack.Screen
|
||||
name="Register"
|
||||
component={Register}
|
||||
options={{
|
||||
headerShown: false,
|
||||
}}
|
||||
/>
|
||||
</Stack.Navigator>
|
||||
</NavigationContainer>
|
||||
</Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
||||
7
Gemfile
Normal file
@ -0,0 +1,7 @@
|
||||
source 'https://rubygems.org'
|
||||
|
||||
# You may use http://rbenv.org/ or https://rvm.io/ to install and use this version
|
||||
ruby ">= 2.6.10"
|
||||
|
||||
gem 'cocoapods', '~> 1.13'
|
||||
gem 'activesupport', '>= 6.1.7.3', '< 7.1.0'
|
||||
79
README.md
Normal file
@ -0,0 +1,79 @@
|
||||
This is a new [**React Native**](https://reactnative.dev) project, bootstrapped using [`@react-native-community/cli`](https://github.com/react-native-community/cli).
|
||||
|
||||
# Getting Started
|
||||
|
||||
>**Note**: Make sure you have completed the [React Native - Environment Setup](https://reactnative.dev/docs/environment-setup) instructions till "Creating a new application" step, before proceeding.
|
||||
|
||||
## Step 1: Start the Metro Server
|
||||
|
||||
First, you will need to start **Metro**, the JavaScript _bundler_ that ships _with_ React Native.
|
||||
|
||||
To start Metro, run the following command from the _root_ of your React Native project:
|
||||
|
||||
```bash
|
||||
# using npm
|
||||
npm start
|
||||
|
||||
# OR using Yarn
|
||||
yarn start
|
||||
```
|
||||
|
||||
## Step 2: Start your Application
|
||||
|
||||
Let Metro Bundler run in its _own_ terminal. Open a _new_ terminal from the _root_ of your React Native project. Run the following command to start your _Android_ or _iOS_ app:
|
||||
|
||||
### For Android
|
||||
|
||||
```bash
|
||||
# using npm
|
||||
npm run android
|
||||
|
||||
# OR using Yarn
|
||||
yarn android
|
||||
```
|
||||
|
||||
### For iOS
|
||||
|
||||
```bash
|
||||
# using npm
|
||||
npm run ios
|
||||
|
||||
# OR using Yarn
|
||||
yarn ios
|
||||
```
|
||||
|
||||
If everything is set up _correctly_, you should see your new app running in your _Android Emulator_ or _iOS Simulator_ shortly provided you have set up your emulator/simulator correctly.
|
||||
|
||||
This is one way to run your app — you can also run it directly from within Android Studio and Xcode respectively.
|
||||
|
||||
## Step 3: Modifying your App
|
||||
|
||||
Now that you have successfully run the app, let's modify it.
|
||||
|
||||
1. Open `App.tsx` in your text editor of choice and edit some lines.
|
||||
2. For **Android**: Press the <kbd>R</kbd> key twice or select **"Reload"** from the **Developer Menu** (<kbd>Ctrl</kbd> + <kbd>M</kbd> (on Window and Linux) or <kbd>Cmd ⌘</kbd> + <kbd>M</kbd> (on macOS)) to see your changes!
|
||||
|
||||
For **iOS**: Hit <kbd>Cmd ⌘</kbd> + <kbd>R</kbd> in your iOS Simulator to reload the app and see your changes!
|
||||
|
||||
## Congratulations! :tada:
|
||||
|
||||
You've successfully run and modified your React Native App. :partying_face:
|
||||
|
||||
### Now what?
|
||||
|
||||
- If you want to add this new React Native code to an existing application, check out the [Integration guide](https://reactnative.dev/docs/integration-with-existing-apps).
|
||||
- If you're curious to learn more about React Native, check out the [Introduction to React Native](https://reactnative.dev/docs/getting-started).
|
||||
|
||||
# Troubleshooting
|
||||
|
||||
If you can't get this to work, see the [Troubleshooting](https://reactnative.dev/docs/troubleshooting) page.
|
||||
|
||||
# Learn More
|
||||
|
||||
To learn more about React Native, take a look at the following resources:
|
||||
|
||||
- [React Native Website](https://reactnative.dev) - learn more about React Native.
|
||||
- [Getting Started](https://reactnative.dev/docs/environment-setup) - an **overview** of React Native and how setup your environment.
|
||||
- [Learn the Basics](https://reactnative.dev/docs/getting-started) - a **guided tour** of the React Native **basics**.
|
||||
- [Blog](https://reactnative.dev/blog) - read the latest official React Native **Blog** posts.
|
||||
- [`@facebook/react-native`](https://github.com/facebook/react-native) - the Open Source; GitHub **repository** for React Native.
|
||||
17
__tests__/App.test.tsx
Normal file
@ -0,0 +1,17 @@
|
||||
/**
|
||||
* @format
|
||||
*/
|
||||
|
||||
import 'react-native';
|
||||
import React from 'react';
|
||||
import App from '../App';
|
||||
|
||||
// Note: import explicitly to use the types shiped with jest.
|
||||
import {it} from '@jest/globals';
|
||||
|
||||
// Note: test renderer must be required after react-native.
|
||||
import renderer from 'react-test-renderer';
|
||||
|
||||
it('renders correctly', () => {
|
||||
renderer.create(<App />);
|
||||
});
|
||||
130
android/app/build.gradle
Normal file
@ -0,0 +1,130 @@
|
||||
apply plugin: "com.android.application"
|
||||
apply plugin: "com.facebook.react"
|
||||
|
||||
/**
|
||||
* This is the configuration block to customize your React Native Android app.
|
||||
* By default you don't need to apply any configuration, just uncomment the lines you need.
|
||||
*/
|
||||
react {
|
||||
/* Folders */
|
||||
// The root of your project, i.e. where "package.json" lives. Default is '..'
|
||||
// root = file("../")
|
||||
// The folder where the react-native NPM package is. Default is ../node_modules/react-native
|
||||
// reactNativeDir = file("../node_modules/react-native")
|
||||
// The folder where the react-native Codegen package is. Default is ../node_modules/@react-native/codegen
|
||||
// codegenDir = file("../node_modules/@react-native/codegen")
|
||||
// The cli.js file which is the React Native CLI entrypoint. Default is ../node_modules/react-native/cli.js
|
||||
// cliFile = file("../node_modules/react-native/cli.js")
|
||||
|
||||
/* Variants */
|
||||
// The list of variants to that are debuggable. For those we're going to
|
||||
// skip the bundling of the JS bundle and the assets. By default is just 'debug'.
|
||||
// If you add flavors like lite, prod, etc. you'll have to list your debuggableVariants.
|
||||
// debuggableVariants = ["liteDebug", "prodDebug"]
|
||||
|
||||
/* Bundling */
|
||||
// A list containing the node command and its flags. Default is just 'node'.
|
||||
// nodeExecutableAndArgs = ["node"]
|
||||
//
|
||||
// The command to run when bundling. By default is 'bundle'
|
||||
// bundleCommand = "ram-bundle"
|
||||
//
|
||||
// The path to the CLI configuration file. Default is empty.
|
||||
// bundleConfig = file(../rn-cli.config.js)
|
||||
//
|
||||
// The name of the generated asset file containing your JS bundle
|
||||
// bundleAssetName = "MyApplication.android.bundle"
|
||||
//
|
||||
// The entry file for bundle generation. Default is 'index.android.js' or 'index.js'
|
||||
// entryFile = file("../js/MyApplication.android.js")
|
||||
//
|
||||
// A list of extra flags to pass to the 'bundle' commands.
|
||||
// See https://github.com/react-native-community/cli/blob/main/docs/commands.md#bundle
|
||||
// extraPackagerArgs = []
|
||||
|
||||
/* Hermes Commands */
|
||||
// The hermes compiler command to run. By default it is 'hermesc'
|
||||
// hermesCommand = "$rootDir/my-custom-hermesc/bin/hermesc"
|
||||
//
|
||||
// The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map"
|
||||
// hermesFlags = ["-O", "-output-source-map"]
|
||||
}
|
||||
|
||||
/**
|
||||
* Set this to true to Run Proguard on Release builds to minify the Java bytecode.
|
||||
*/
|
||||
def enableProguardInReleaseBuilds = false
|
||||
|
||||
/**
|
||||
* The preferred build flavor of JavaScriptCore (JSC)
|
||||
*
|
||||
* For example, to use the international variant, you can use:
|
||||
* `def jscFlavor = 'org.webkit:android-jsc-intl:+'`
|
||||
*
|
||||
* The international variant includes ICU i18n library and necessary data
|
||||
* allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that
|
||||
* give correct results when using with locales other than en-US. Note that
|
||||
* this variant is about 6MiB larger per architecture than default.
|
||||
*/
|
||||
def jscFlavor = 'org.webkit:android-jsc:+'
|
||||
|
||||
android {
|
||||
ndkVersion rootProject.ext.ndkVersion
|
||||
|
||||
compileSdkVersion rootProject.ext.compileSdkVersion
|
||||
|
||||
namespace "com.medappdoctor"
|
||||
defaultConfig {
|
||||
applicationId "com.medappdoctor"
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
}
|
||||
signingConfigs {
|
||||
debug {
|
||||
storeFile file('debug.keystore')
|
||||
storePassword 'android'
|
||||
keyAlias 'androiddebugkey'
|
||||
keyPassword 'android'
|
||||
}
|
||||
release {
|
||||
storeFile file('your_key_name.keystore')
|
||||
storePassword MYAPP_UPLOAD_STORE_PASSWORD
|
||||
keyAlias MYAPP_UPLOAD_KEY_ALIAS
|
||||
keyPassword MYAPP_UPLOAD_KEY_PASSWORD
|
||||
}
|
||||
}
|
||||
buildTypes {
|
||||
debug {
|
||||
signingConfig signingConfigs.debug
|
||||
}
|
||||
release {
|
||||
// Caution! In production, you need to generate your own keystore file.
|
||||
// see https://reactnative.dev/docs/signed-apk-android.
|
||||
signingConfig signingConfigs.release
|
||||
minifyEnabled enableProguardInReleaseBuilds
|
||||
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// The version of react-native is set by the React Native Gradle Plugin
|
||||
implementation("com.facebook.react:react-android")
|
||||
|
||||
debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}")
|
||||
debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") {
|
||||
exclude group:'com.squareup.okhttp3', module:'okhttp'
|
||||
}
|
||||
|
||||
debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}")
|
||||
if (hermesEnabled.toBoolean()) {
|
||||
implementation("com.facebook.react:hermes-android")
|
||||
} else {
|
||||
implementation jscFlavor
|
||||
}
|
||||
}
|
||||
|
||||
apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
|
||||
apply from: file("../../node_modules/react-native-vector-icons/fonts.gradle")
|
||||
BIN
android/app/debug.keystore
Normal file
10
android/app/proguard-rules.pro
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt
|
||||
# You can edit the include path and order by changing the proguardFiles
|
||||
# directive in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# Add any project specific keep options here:
|
||||
13
android/app/src/debug/AndroidManifest.xml
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
|
||||
|
||||
<application
|
||||
android:usesCleartextTraffic="true"
|
||||
tools:targetApi="28"
|
||||
tools:ignore="GoogleAppIndexingWarning">
|
||||
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" android:exported="false" />
|
||||
</application>
|
||||
</manifest>
|
||||
@ -0,0 +1,75 @@
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* <p>This source code is licensed under the MIT license found in the LICENSE file in the root
|
||||
* directory of this source tree.
|
||||
*/
|
||||
package com.medappdoctor;
|
||||
|
||||
import android.content.Context;
|
||||
import com.facebook.flipper.android.AndroidFlipperClient;
|
||||
import com.facebook.flipper.android.utils.FlipperUtils;
|
||||
import com.facebook.flipper.core.FlipperClient;
|
||||
import com.facebook.flipper.plugins.crashreporter.CrashReporterPlugin;
|
||||
import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin;
|
||||
import com.facebook.flipper.plugins.fresco.FrescoFlipperPlugin;
|
||||
import com.facebook.flipper.plugins.inspector.DescriptorMapping;
|
||||
import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin;
|
||||
import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor;
|
||||
import com.facebook.flipper.plugins.network.NetworkFlipperPlugin;
|
||||
import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin;
|
||||
import com.facebook.react.ReactInstanceEventListener;
|
||||
import com.facebook.react.ReactInstanceManager;
|
||||
import com.facebook.react.bridge.ReactContext;
|
||||
import com.facebook.react.modules.network.NetworkingModule;
|
||||
import okhttp3.OkHttpClient;
|
||||
|
||||
/**
|
||||
* Class responsible of loading Flipper inside your React Native application. This is the debug
|
||||
* flavor of it. Here you can add your own plugins and customize the Flipper setup.
|
||||
*/
|
||||
public class ReactNativeFlipper {
|
||||
public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) {
|
||||
if (FlipperUtils.shouldEnableFlipper(context)) {
|
||||
final FlipperClient client = AndroidFlipperClient.getInstance(context);
|
||||
|
||||
client.addPlugin(new InspectorFlipperPlugin(context, DescriptorMapping.withDefaults()));
|
||||
client.addPlugin(new DatabasesFlipperPlugin(context));
|
||||
client.addPlugin(new SharedPreferencesFlipperPlugin(context));
|
||||
client.addPlugin(CrashReporterPlugin.getInstance());
|
||||
|
||||
NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin();
|
||||
NetworkingModule.setCustomClientBuilder(
|
||||
new NetworkingModule.CustomClientBuilder() {
|
||||
@Override
|
||||
public void apply(OkHttpClient.Builder builder) {
|
||||
builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin));
|
||||
}
|
||||
});
|
||||
client.addPlugin(networkFlipperPlugin);
|
||||
client.start();
|
||||
|
||||
// Fresco Plugin needs to ensure that ImagePipelineFactory is initialized
|
||||
// Hence we run if after all native modules have been initialized
|
||||
ReactContext reactContext = reactInstanceManager.getCurrentReactContext();
|
||||
if (reactContext == null) {
|
||||
reactInstanceManager.addReactInstanceEventListener(
|
||||
new ReactInstanceEventListener() {
|
||||
@Override
|
||||
public void onReactContextInitialized(ReactContext reactContext) {
|
||||
reactInstanceManager.removeReactInstanceEventListener(this);
|
||||
reactContext.runOnNativeModulesQueueThread(
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
client.addPlugin(new FrescoFlipperPlugin());
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
client.addPlugin(new FrescoFlipperPlugin());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
28
android/app/src/main/AndroidManifest.xml
Normal file
@ -0,0 +1,28 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
|
||||
<application
|
||||
android:name=".MainApplication"
|
||||
android:label="@string/app_name"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:allowBackup="false"
|
||||
android:theme="@style/AppTheme"
|
||||
android:usesCleartextTraffic="true">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:label="@string/app_name"
|
||||
android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode"
|
||||
android:launchMode="singleTask"
|
||||
android:windowSoftInputMode="adjustResize"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
</manifest>
|
||||
1005
android/app/src/main/assets/index.android.bundle
Normal file
@ -0,0 +1,38 @@
|
||||
package com.medappdoctor;
|
||||
|
||||
import android.os.Bundle;
|
||||
import com.facebook.react.ReactActivity;
|
||||
import com.facebook.react.ReactActivityDelegate;
|
||||
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint;
|
||||
import com.facebook.react.defaults.DefaultReactActivityDelegate;
|
||||
|
||||
public class MainActivity extends ReactActivity {
|
||||
|
||||
/**
|
||||
* Returns the name of the main component registered from JavaScript. This is used to schedule
|
||||
* rendering of the component.
|
||||
*/
|
||||
@Override
|
||||
protected String getMainComponentName() {
|
||||
return "medappdoctor";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the instance of the {@link ReactActivityDelegate}. Here we use a util class {@link
|
||||
* DefaultReactActivityDelegate} which allows you to easily enable Fabric and Concurrent React
|
||||
* (aka React 18) with two boolean flags.
|
||||
*/
|
||||
@Override
|
||||
protected ReactActivityDelegate createReactActivityDelegate() {
|
||||
return new DefaultReactActivityDelegate(
|
||||
this,
|
||||
getMainComponentName(),
|
||||
// If you opted-in for the New Architecture, we enable the Fabric Renderer.
|
||||
DefaultNewArchitectureEntryPoint.getFabricEnabled());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(null);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,62 @@
|
||||
package com.medappdoctor;
|
||||
|
||||
import android.app.Application;
|
||||
import com.facebook.react.PackageList;
|
||||
import com.facebook.react.ReactApplication;
|
||||
import com.facebook.react.ReactNativeHost;
|
||||
import com.facebook.react.ReactPackage;
|
||||
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint;
|
||||
import com.facebook.react.defaults.DefaultReactNativeHost;
|
||||
import com.facebook.soloader.SoLoader;
|
||||
import java.util.List;
|
||||
|
||||
public class MainApplication extends Application implements ReactApplication {
|
||||
|
||||
private final ReactNativeHost mReactNativeHost =
|
||||
new DefaultReactNativeHost(this) {
|
||||
@Override
|
||||
public boolean getUseDeveloperSupport() {
|
||||
return BuildConfig.DEBUG;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<ReactPackage> getPackages() {
|
||||
@SuppressWarnings("UnnecessaryLocalVariable")
|
||||
List<ReactPackage> packages = new PackageList(this).getPackages();
|
||||
// Packages that cannot be autolinked yet can be added manually here, for example:
|
||||
// packages.add(new MyReactNativePackage());
|
||||
return packages;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getJSMainModuleName() {
|
||||
return "index";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isNewArchEnabled() {
|
||||
return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Boolean isHermesEnabled() {
|
||||
return BuildConfig.IS_HERMES_ENABLED;
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public ReactNativeHost getReactNativeHost() {
|
||||
return mReactNativeHost;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
SoLoader.init(this, /* native exopackage */ false);
|
||||
if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
|
||||
// If you opted-in for the New Architecture, we load the native entry point for this app.
|
||||
DefaultNewArchitectureEntryPoint.load();
|
||||
}
|
||||
ReactNativeFlipper.initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
|
||||
}
|
||||
}
|
||||
36
android/app/src/main/res/drawable/rn_edit_text_material.xml
Normal file
@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2014 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<inset xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:insetLeft="@dimen/abc_edit_text_inset_horizontal_material"
|
||||
android:insetRight="@dimen/abc_edit_text_inset_horizontal_material"
|
||||
android:insetTop="@dimen/abc_edit_text_inset_top_material"
|
||||
android:insetBottom="@dimen/abc_edit_text_inset_bottom_material">
|
||||
|
||||
<selector>
|
||||
<!--
|
||||
This file is a copy of abc_edit_text_material (https://bit.ly/3k8fX7I).
|
||||
The item below with state_pressed="false" and state_focused="false" causes a NullPointerException.
|
||||
NullPointerException:tempt to invoke virtual method 'android.graphics.drawable.Drawable android.graphics.drawable.Drawable$ConstantState.newDrawable(android.content.res.Resources)'
|
||||
|
||||
<item android:state_pressed="false" android:state_focused="false" android:drawable="@drawable/abc_textfield_default_mtrl_alpha"/>
|
||||
|
||||
For more info, see https://bit.ly/3CdLStv (react-native/pull/29452) and https://bit.ly/3nxOMoR.
|
||||
-->
|
||||
<item android:state_enabled="false" android:drawable="@drawable/abc_textfield_default_mtrl_alpha"/>
|
||||
<item android:drawable="@drawable/abc_textfield_activated_mtrl_alpha"/>
|
||||
</selector>
|
||||
|
||||
</inset>
|
||||
BIN
android/app/src/main/res/mipmap-hdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
BIN
android/app/src/main/res/mipmap-mdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 4.5 KiB |
BIN
android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
Normal file
|
After Width: | Height: | Size: 6.9 KiB |
BIN
android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 6.3 KiB |
BIN
android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
|
After Width: | Height: | Size: 7.7 KiB |
BIN
android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
3
android/app/src/main/res/values/strings.xml
Normal file
@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<string name="app_name">Medical App - Doctor</string>
|
||||
</resources>
|
||||
9
android/app/src/main/res/values/styles.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<resources>
|
||||
|
||||
<!-- Base application theme. -->
|
||||
<style name="AppTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
|
||||
<!-- Customize your theme here. -->
|
||||
<item name="android:editTextBackground">@drawable/rn_edit_text_material</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* <p>This source code is licensed under the MIT license found in the LICENSE file in the root
|
||||
* directory of this source tree.
|
||||
*/
|
||||
package com.medappdoctor;
|
||||
|
||||
import android.content.Context;
|
||||
import com.facebook.react.ReactInstanceManager;
|
||||
|
||||
/**
|
||||
* Class responsible of loading Flipper inside your React Native application. This is the release
|
||||
* flavor of it so it's empty as we don't want to load Flipper.
|
||||
*/
|
||||
public class ReactNativeFlipper {
|
||||
public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) {
|
||||
// Do nothing as we don't want to initialize Flipper on Release.
|
||||
}
|
||||
}
|
||||
21
android/build.gradle
Normal file
@ -0,0 +1,21 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
ext {
|
||||
buildToolsVersion = "33.0.0"
|
||||
minSdkVersion = 21
|
||||
compileSdkVersion = 33
|
||||
targetSdkVersion = 33
|
||||
|
||||
// We use NDK 23 which has both M1 support and is the side-by-side NDK version from AGP.
|
||||
ndkVersion = "23.1.7779620"
|
||||
}
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath("com.android.tools.build:gradle")
|
||||
classpath("com.facebook.react:react-native-gradle-plugin")
|
||||
}
|
||||
}
|
||||
49
android/gradle.properties
Normal file
@ -0,0 +1,49 @@
|
||||
# Project-wide Gradle settings.
|
||||
|
||||
# IDE (e.g. Android Studio) users:
|
||||
# Gradle settings configured through the IDE *will override*
|
||||
# any settings specified in this file.
|
||||
|
||||
# For more details on how to configure your build environment visit
|
||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||
|
||||
# Specifies the JVM arguments used for the daemon process.
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
# Default value: -Xmx512m -XX:MaxMetaspaceSize=256m
|
||||
org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m
|
||||
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
# This option should only be used with decoupled projects. More details, visit
|
||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||
# org.gradle.parallel=true
|
||||
|
||||
# AndroidX package structure to make it clearer which packages are bundled with the
|
||||
# Android operating system, and which are packaged with your app's APK
|
||||
# https://developer.android.com/topic/libraries/support-library/androidx-rn
|
||||
android.useAndroidX=true
|
||||
# Automatically convert third-party libraries to use AndroidX
|
||||
android.enableJetifier=true
|
||||
|
||||
# Version of flipper SDK to use with React Native
|
||||
FLIPPER_VERSION=0.182.0
|
||||
|
||||
# Use this property to specify which architecture you want to build.
|
||||
# You can also override it from the CLI using
|
||||
# ./gradlew <task> -PreactNativeArchitectures=x86_64
|
||||
reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64
|
||||
|
||||
# Use this property to enable support to the new architecture.
|
||||
# This will allow you to use TurboModules and the Fabric render in
|
||||
# your application. You should enable this flag either if you want
|
||||
# to write custom TurboModules/Fabric components OR use libraries that
|
||||
# are providing them.
|
||||
newArchEnabled=false
|
||||
|
||||
# Use this property to enable or disable the Hermes JS engine.
|
||||
# If set to false, you will be using JSC instead.
|
||||
hermesEnabled=true
|
||||
|
||||
MYAPP_UPLOAD_STORE_FILE=your_key_name.keystore
|
||||
MYAPP_UPLOAD_KEY_ALIAS=your_key_alias
|
||||
MYAPP_UPLOAD_STORE_PASSWORD=asdfASDF1234!@#$
|
||||
MYAPP_UPLOAD_KEY_PASSWORD=asdfASDF1234!@#$
|
||||
BIN
android/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
6
android/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.1-all.zip
|
||||
networkTimeout=10000
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
244
android/gradlew
vendored
Executable file
@ -0,0 +1,244 @@
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Copyright © 2015-2021 the original authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# Gradle start up script for POSIX generated by Gradle.
|
||||
#
|
||||
# Important for running:
|
||||
#
|
||||
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||
# noncompliant, but you have some other compliant shell such as ksh or
|
||||
# bash, then to run this script, type that shell name before the whole
|
||||
# command line, like:
|
||||
#
|
||||
# ksh Gradle
|
||||
#
|
||||
# Busybox and similar reduced shells will NOT work, because this script
|
||||
# requires all of these POSIX shell features:
|
||||
# * functions;
|
||||
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||
# * compound commands having a testable exit status, especially «case»;
|
||||
# * various built-in commands including «command», «set», and «ulimit».
|
||||
#
|
||||
# Important for patching:
|
||||
#
|
||||
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||
#
|
||||
# The "traditional" practice of packing multiple parameters into a
|
||||
# space-separated string is a well documented source of bugs and security
|
||||
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||
# options in "$@", and eventually passing that to Java.
|
||||
#
|
||||
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||
# see the in-line comments for details.
|
||||
#
|
||||
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
|
||||
# Resolve links: $0 may be a link
|
||||
app_path=$0
|
||||
|
||||
# Need this for daisy-chained symlinks.
|
||||
while
|
||||
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||
[ -h "$app_path" ]
|
||||
do
|
||||
ls=$( ls -ld "$app_path" )
|
||||
link=${ls#*' -> '}
|
||||
case $link in #(
|
||||
/*) app_path=$link ;; #(
|
||||
*) app_path=$APP_HOME$link ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# This is normally unused
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
} >&2
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
} >&2
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "$( uname )" in #(
|
||||
CYGWIN* ) cygwin=true ;; #(
|
||||
Darwin* ) darwin=true ;; #(
|
||||
MSYS* | MINGW* ) msys=true ;; #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||
else
|
||||
JAVACMD=$JAVA_HOME/bin/java
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD=java
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
case $MAX_FD in #(
|
||||
max*)
|
||||
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC3045
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
case $MAX_FD in #(
|
||||
'' | soft) :;; #(
|
||||
*)
|
||||
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC3045
|
||||
ulimit -n "$MAX_FD" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
esac
|
||||
fi
|
||||
|
||||
# Collect all arguments for the java command, stacking in reverse order:
|
||||
# * args from the command line
|
||||
# * the main class name
|
||||
# * -classpath
|
||||
# * -D...appname settings
|
||||
# * --module-path (only if needed)
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if "$cygwin" || "$msys" ; then
|
||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||
|
||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
for arg do
|
||||
if
|
||||
case $arg in #(
|
||||
-*) false ;; # don't mess with options #(
|
||||
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||
[ -e "$t" ] ;; #(
|
||||
*) false ;;
|
||||
esac
|
||||
then
|
||||
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||
fi
|
||||
# Roll the args list around exactly as many times as the number of
|
||||
# args, so each arg winds up back in the position where it started, but
|
||||
# possibly modified.
|
||||
#
|
||||
# NB: a `for` loop captures its iteration list before it begins, so
|
||||
# changing the positional parameters here affects neither the number of
|
||||
# iterations, nor the values presented in `arg`.
|
||||
shift # remove old arg
|
||||
set -- "$@" "$arg" # push replacement arg
|
||||
done
|
||||
fi
|
||||
|
||||
# Collect all arguments for the java command;
|
||||
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
||||
# shell script including quotes and variable substitutions, so put them in
|
||||
# double quotes to make sure that they get re-expanded; and
|
||||
# * put everything else in single quotes, so that it's not re-expanded.
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-classpath "$CLASSPATH" \
|
||||
org.gradle.wrapper.GradleWrapperMain \
|
||||
"$@"
|
||||
|
||||
# Stop when "xargs" is not available.
|
||||
if ! command -v xargs >/dev/null 2>&1
|
||||
then
|
||||
die "xargs is not available"
|
||||
fi
|
||||
|
||||
# Use "xargs" to parse quoted args.
|
||||
#
|
||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||
#
|
||||
# In Bash we could simply go:
|
||||
#
|
||||
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||
# set -- "${ARGS[@]}" "$@"
|
||||
#
|
||||
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||
# character that might be a shell metacharacter, then use eval to reverse
|
||||
# that process (while maintaining the separation between arguments), and wrap
|
||||
# the whole thing up as a single "set" statement.
|
||||
#
|
||||
# This will of course break if any of these variables contains a newline or
|
||||
# an unmatched quote.
|
||||
#
|
||||
|
||||
eval "set -- $(
|
||||
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||
xargs -n1 |
|
||||
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||
tr '\n' ' '
|
||||
)" '"$@"'
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
92
android/gradlew.bat
vendored
Normal file
@ -0,0 +1,92 @@
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
@rem This is normally unused
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||
exit /b %EXIT_CODE%
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
4
android/link-assets-manifest.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"migIndex": 1,
|
||||
"data": []
|
||||
}
|
||||
4
android/settings.gradle
Normal file
@ -0,0 +1,4 @@
|
||||
rootProject.name = 'medappdoctor'
|
||||
apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
|
||||
include ':app'
|
||||
includeBuild('../node_modules/@react-native/gradle-plugin')
|
||||
4
app.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"name": "medappdoctor",
|
||||
"displayName": "Medical App - Doctor"
|
||||
}
|
||||
7
babel.config.js
Normal file
@ -0,0 +1,7 @@
|
||||
module.exports = function (api) {
|
||||
api.cache(true);
|
||||
return {
|
||||
presets: ['module:metro-react-native-babel-preset'],
|
||||
plugins: ['react-native-reanimated/plugin'],
|
||||
};
|
||||
};
|
||||
10
build-apk.sh
Executable file
@ -0,0 +1,10 @@
|
||||
rm -rf android/app/src/main/res/drawable-*
|
||||
npx react-native bundle \
|
||||
--platform android \
|
||||
--dev false \
|
||||
--entry-file index.js \
|
||||
--bundle-output android/app/src/main/assets/index.android.bundle \
|
||||
--assets-dest android/app/build/intermediates/res/merged/release/
|
||||
cd android
|
||||
./gradlew assembleRelease
|
||||
cd ..
|
||||
9
index.js
Normal file
@ -0,0 +1,9 @@
|
||||
/**
|
||||
* @format
|
||||
*/
|
||||
|
||||
import {AppRegistry} from 'react-native';
|
||||
import App from './App';
|
||||
import {name as appName} from './app.json';
|
||||
|
||||
AppRegistry.registerComponent(appName, () => App);
|
||||
11
ios/.xcode.env
Normal file
@ -0,0 +1,11 @@
|
||||
# This `.xcode.env` file is versioned and is used to source the environment
|
||||
# used when running script phases inside Xcode.
|
||||
# To customize your local environment, you can create an `.xcode.env.local`
|
||||
# file that is not versioned.
|
||||
|
||||
# NODE_BINARY variable contains the PATH to the node executable.
|
||||
#
|
||||
# Customize the NODE_BINARY variable here.
|
||||
# For example, to use nvm with brew, add the following line
|
||||
# . "$(brew --prefix nvm)/nvm.sh" --no-use
|
||||
export NODE_BINARY=$(command -v node)
|
||||
62
ios/Podfile
Normal file
@ -0,0 +1,62 @@
|
||||
# Resolve react_native_pods.rb with node to allow for hoisting
|
||||
require Pod::Executable.execute_command('node', ['-p',
|
||||
'require.resolve(
|
||||
"react-native/scripts/react_native_pods.rb",
|
||||
{paths: [process.argv[1]]},
|
||||
)', __dir__]).strip
|
||||
|
||||
platform :ios, min_ios_version_supported
|
||||
prepare_react_native_project!
|
||||
|
||||
# If you are using a `react-native-flipper` your iOS build will fail when `NO_FLIPPER=1` is set.
|
||||
# because `react-native-flipper` depends on (FlipperKit,...) that will be excluded
|
||||
#
|
||||
# To fix this you can also exclude `react-native-flipper` using a `react-native.config.js`
|
||||
# ```js
|
||||
# module.exports = {
|
||||
# dependencies: {
|
||||
# ...(process.env.NO_FLIPPER ? { 'react-native-flipper': { platforms: { ios: null } } } : {}),
|
||||
# ```
|
||||
flipper_config = ENV['NO_FLIPPER'] == "1" ? FlipperConfiguration.disabled : FlipperConfiguration.enabled
|
||||
|
||||
linkage = ENV['USE_FRAMEWORKS']
|
||||
if linkage != nil
|
||||
Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green
|
||||
use_frameworks! :linkage => linkage.to_sym
|
||||
end
|
||||
|
||||
target 'medappdoctor' do
|
||||
config = use_native_modules!
|
||||
|
||||
# Flags change depending on the env values.
|
||||
flags = get_default_flags()
|
||||
|
||||
use_react_native!(
|
||||
:path => config[:reactNativePath],
|
||||
# Hermes is now enabled by default. Disable by setting this flag to false.
|
||||
:hermes_enabled => flags[:hermes_enabled],
|
||||
:fabric_enabled => flags[:fabric_enabled],
|
||||
# Enables Flipper.
|
||||
#
|
||||
# Note that if you have use_frameworks! enabled, Flipper will not work and
|
||||
# you should disable the next line.
|
||||
:flipper_configuration => flipper_config,
|
||||
# An absolute path to your application root.
|
||||
:app_path => "#{Pod::Config.instance.installation_root}/.."
|
||||
)
|
||||
|
||||
target 'medappdoctorTests' do
|
||||
inherit! :complete
|
||||
# Pods for testing
|
||||
end
|
||||
|
||||
post_install do |installer|
|
||||
# https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202
|
||||
react_native_post_install(
|
||||
installer,
|
||||
config[:reactNativePath],
|
||||
:mac_catalyst_enabled => false
|
||||
)
|
||||
__apply_Xcode_12_5_M1_post_install_workaround(installer)
|
||||
end
|
||||
end
|
||||
702
ios/blockchainrecapapp.xcodeproj/project.pbxproj
Normal file
@ -0,0 +1,702 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 54;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
00E356F31AD99517003FC87E /* medappdoctorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* medappdoctorTests.m */; };
|
||||
0C80B921A6F3F58F76C31292 /* libPods-medappdoctor.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5DCACB8F33CDC322A6C60F78 /* libPods-medappdoctor.a */; };
|
||||
13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.mm */; };
|
||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
|
||||
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
|
||||
7699B88040F8A987B510C191 /* libPods-medappdoctor-medappdoctorTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 19F6CBCC0A4E27FBF8BF4A61 /* libPods-medappdoctor-medappdoctorTests.a */; };
|
||||
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
00E356F41AD99517003FC87E /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 13B07F861A680F5B00A75B9A;
|
||||
remoteInfo = medappdoctor;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
00E356EE1AD99517003FC87E /* medappdoctorTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = medappdoctorTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
00E356F21AD99517003FC87E /* medappdoctorTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = medappdoctorTests.m; sourceTree = "<group>"; };
|
||||
13B07F961A680F5B00A75B9A /* medappdoctor.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = medappdoctor.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = medappdoctor/AppDelegate.h; sourceTree = "<group>"; };
|
||||
13B07FB01A68108700A75B9A /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = medappdoctor/AppDelegate.mm; sourceTree = "<group>"; };
|
||||
13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = medappdoctor/Images.xcassets; sourceTree = "<group>"; };
|
||||
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = medappdoctor/Info.plist; sourceTree = "<group>"; };
|
||||
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = medappdoctor/main.m; sourceTree = "<group>"; };
|
||||
19F6CBCC0A4E27FBF8BF4A61 /* libPods-medappdoctor-medappdoctorTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-medappdoctor-medappdoctorTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
3B4392A12AC88292D35C810B /* Pods-medappdoctor.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-medappdoctor.debug.xcconfig"; path = "Target Support Files/Pods-medappdoctor/Pods-medappdoctor.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
5709B34CF0A7D63546082F79 /* Pods-medappdoctor.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-medappdoctor.release.xcconfig"; path = "Target Support Files/Pods-medappdoctor/Pods-medappdoctor.release.xcconfig"; sourceTree = "<group>"; };
|
||||
5B7EB9410499542E8C5724F5 /* Pods-medappdoctor-medappdoctorTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-medappdoctor-medappdoctorTests.debug.xcconfig"; path = "Target Support Files/Pods-medappdoctor-medappdoctorTests/Pods-medappdoctor-medappdoctorTests.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
5DCACB8F33CDC322A6C60F78 /* libPods-medappdoctor.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-medappdoctor.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = medappdoctor/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
89C6BE57DB24E9ADA2F236DE /* Pods-medappdoctor-medappdoctorTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-medappdoctor-medappdoctorTests.release.xcconfig"; path = "Target Support Files/Pods-medappdoctor-medappdoctorTests/Pods-medappdoctor-medappdoctorTests.release.xcconfig"; sourceTree = "<group>"; };
|
||||
ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
00E356EB1AD99517003FC87E /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
7699B88040F8A987B510C191 /* libPods-medappdoctor-medappdoctorTests.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
13B07F8C1A680F5B00A75B9A /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
0C80B921A6F3F58F76C31292 /* libPods-medappdoctor.a in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
00E356EF1AD99517003FC87E /* medappdoctorTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
00E356F21AD99517003FC87E /* medappdoctorTests.m */,
|
||||
00E356F01AD99517003FC87E /* Supporting Files */,
|
||||
);
|
||||
path = medappdoctorTests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
00E356F01AD99517003FC87E /* Supporting Files */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
00E356F11AD99517003FC87E /* Info.plist */,
|
||||
);
|
||||
name = "Supporting Files";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
13B07FAE1A68108700A75B9A /* medappdoctor */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
13B07FAF1A68108700A75B9A /* AppDelegate.h */,
|
||||
13B07FB01A68108700A75B9A /* AppDelegate.mm */,
|
||||
13B07FB51A68108700A75B9A /* Images.xcassets */,
|
||||
13B07FB61A68108700A75B9A /* Info.plist */,
|
||||
81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */,
|
||||
13B07FB71A68108700A75B9A /* main.m */,
|
||||
);
|
||||
name = medappdoctor;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
2D16E6871FA4F8E400B85C8A /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
ED297162215061F000B7C4FE /* JavaScriptCore.framework */,
|
||||
5DCACB8F33CDC322A6C60F78 /* libPods-medappdoctor.a */,
|
||||
19F6CBCC0A4E27FBF8BF4A61 /* libPods-medappdoctor-medappdoctorTests.a */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
832341AE1AAA6A7D00B99B32 /* Libraries */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
);
|
||||
name = Libraries;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
83CBB9F61A601CBA00E9B192 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
13B07FAE1A68108700A75B9A /* medappdoctor */,
|
||||
832341AE1AAA6A7D00B99B32 /* Libraries */,
|
||||
00E356EF1AD99517003FC87E /* medappdoctorTests */,
|
||||
83CBBA001A601CBA00E9B192 /* Products */,
|
||||
2D16E6871FA4F8E400B85C8A /* Frameworks */,
|
||||
BBD78D7AC51CEA395F1C20DB /* Pods */,
|
||||
);
|
||||
indentWidth = 2;
|
||||
sourceTree = "<group>";
|
||||
tabWidth = 2;
|
||||
usesTabs = 0;
|
||||
};
|
||||
83CBBA001A601CBA00E9B192 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
13B07F961A680F5B00A75B9A /* medappdoctor.app */,
|
||||
00E356EE1AD99517003FC87E /* medappdoctorTests.xctest */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
BBD78D7AC51CEA395F1C20DB /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
3B4392A12AC88292D35C810B /* Pods-medappdoctor.debug.xcconfig */,
|
||||
5709B34CF0A7D63546082F79 /* Pods-medappdoctor.release.xcconfig */,
|
||||
5B7EB9410499542E8C5724F5 /* Pods-medappdoctor-medappdoctorTests.debug.xcconfig */,
|
||||
89C6BE57DB24E9ADA2F236DE /* Pods-medappdoctor-medappdoctorTests.release.xcconfig */,
|
||||
);
|
||||
path = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
00E356ED1AD99517003FC87E /* medappdoctorTests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "medappdoctorTests" */;
|
||||
buildPhases = (
|
||||
A55EABD7B0C7F3A422A6CC61 /* [CP] Check Pods Manifest.lock */,
|
||||
00E356EA1AD99517003FC87E /* Sources */,
|
||||
00E356EB1AD99517003FC87E /* Frameworks */,
|
||||
00E356EC1AD99517003FC87E /* Resources */,
|
||||
C59DA0FBD6956966B86A3779 /* [CP] Embed Pods Frameworks */,
|
||||
F6A41C54EA430FDDC6A6ED99 /* [CP] Copy Pods Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
00E356F51AD99517003FC87E /* PBXTargetDependency */,
|
||||
);
|
||||
name = medappdoctorTests;
|
||||
productName = medappdoctorTests;
|
||||
productReference = 00E356EE1AD99517003FC87E /* medappdoctorTests.xctest */;
|
||||
productType = "com.apple.product-type.bundle.unit-test";
|
||||
};
|
||||
13B07F861A680F5B00A75B9A /* medappdoctor */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "medappdoctor" */;
|
||||
buildPhases = (
|
||||
C38B50BA6285516D6DCD4F65 /* [CP] Check Pods Manifest.lock */,
|
||||
FD10A7F022414F080027D42C /* Start Packager */,
|
||||
13B07F871A680F5B00A75B9A /* Sources */,
|
||||
13B07F8C1A680F5B00A75B9A /* Frameworks */,
|
||||
13B07F8E1A680F5B00A75B9A /* Resources */,
|
||||
00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
|
||||
00EEFC60759A1932668264C0 /* [CP] Embed Pods Frameworks */,
|
||||
E235C05ADACE081382539298 /* [CP] Copy Pods Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = medappdoctor;
|
||||
productName = medappdoctor;
|
||||
productReference = 13B07F961A680F5B00A75B9A /* medappdoctor.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
83CBB9F71A601CBA00E9B192 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 1210;
|
||||
TargetAttributes = {
|
||||
00E356ED1AD99517003FC87E = {
|
||||
CreatedOnToolsVersion = 6.2;
|
||||
TestTargetID = 13B07F861A680F5B00A75B9A;
|
||||
};
|
||||
13B07F861A680F5B00A75B9A = {
|
||||
LastSwiftMigration = 1120;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "medappdoctor" */;
|
||||
compatibilityVersion = "Xcode 12.0";
|
||||
developmentRegion = en;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 83CBB9F61A601CBA00E9B192;
|
||||
productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
13B07F861A680F5B00A75B9A /* medappdoctor */,
|
||||
00E356ED1AD99517003FC87E /* medappdoctorTests */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
00E356EC1AD99517003FC87E /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
13B07F8E1A680F5B00A75B9A /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */,
|
||||
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"$(SRCROOT)/.xcode.env.local",
|
||||
"$(SRCROOT)/.xcode.env",
|
||||
);
|
||||
name = "Bundle React Native code and images";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "set -e\n\nWITH_ENVIRONMENT=\"../node_modules/react-native/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"../node_modules/react-native/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT $REACT_NATIVE_XCODE\"\n";
|
||||
};
|
||||
00EEFC60759A1932668264C0 /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-medappdoctor/Pods-medappdoctor-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-medappdoctor/Pods-medappdoctor-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-medappdoctor/Pods-medappdoctor-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
A55EABD7B0C7F3A422A6CC61 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-medappdoctor-medappdoctorTests-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
C38B50BA6285516D6DCD4F65 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-medappdoctor-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
C59DA0FBD6956966B86A3779 /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-medappdoctor-medappdoctorTests/Pods-medappdoctor-medappdoctorTests-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-medappdoctor-medappdoctorTests/Pods-medappdoctor-medappdoctorTests-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-medappdoctor-medappdoctorTests/Pods-medappdoctor-medappdoctorTests-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
E235C05ADACE081382539298 /* [CP] Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-medappdoctor/Pods-medappdoctor-resources-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Copy Pods Resources";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-medappdoctor/Pods-medappdoctor-resources-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-medappdoctor/Pods-medappdoctor-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
F6A41C54EA430FDDC6A6ED99 /* [CP] Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-medappdoctor-medappdoctorTests/Pods-medappdoctor-medappdoctorTests-resources-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Copy Pods Resources";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-medappdoctor-medappdoctorTests/Pods-medappdoctor-medappdoctorTests-resources-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-medappdoctor-medappdoctorTests/Pods-medappdoctor-medappdoctorTests-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
FD10A7F022414F080027D42C /* Start Packager */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Start Packager";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "export RCT_METRO_PORT=\"${RCT_METRO_PORT:=8081}\"\necho \"export RCT_METRO_PORT=${RCT_METRO_PORT}\" > \"${SRCROOT}/../node_modules/react-native/scripts/.packager.env\"\nif [ -z \"${RCT_NO_LAUNCH_PACKAGER+xxx}\" ] ; then\n if nc -w 5 -z localhost ${RCT_METRO_PORT} ; then\n if ! curl -s \"http://localhost:${RCT_METRO_PORT}/status\" | grep -q \"packager-status:running\" ; then\n echo \"Port ${RCT_METRO_PORT} already in use, packager is either not running or not running correctly\"\n exit 2\n fi\n else\n open \"$SRCROOT/../node_modules/react-native/scripts/launchPackager.command\" || echo \"Can't start packager automatically\"\n fi\nfi\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
00E356EA1AD99517003FC87E /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
00E356F31AD99517003FC87E /* medappdoctorTests.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
13B07F871A680F5B00A75B9A /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */,
|
||||
13B07FC11A68108700A75B9A /* main.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
00E356F51AD99517003FC87E /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 13B07F861A680F5B00A75B9A /* medappdoctor */;
|
||||
targetProxy = 00E356F41AD99517003FC87E /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
00E356F61AD99517003FC87E /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 5B7EB9410499542E8C5724F5 /* Pods-medappdoctor-medappdoctorTests.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
INFOPLIST_FILE = medappdoctorTests/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.4;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
OTHER_LDFLAGS = (
|
||||
"-ObjC",
|
||||
"-lc++",
|
||||
"$(inherited)",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/medappdoctor.app/medappdoctor";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
00E356F71AD99517003FC87E /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 89C6BE57DB24E9ADA2F236DE /* Pods-medappdoctor-medappdoctorTests.release.xcconfig */;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
INFOPLIST_FILE = medappdoctorTests/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.4;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
"@loader_path/Frameworks",
|
||||
);
|
||||
OTHER_LDFLAGS = (
|
||||
"-ObjC",
|
||||
"-lc++",
|
||||
"$(inherited)",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/medappdoctor.app/medappdoctor";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
13B07F941A680F5B00A75B9A /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 3B4392A12AC88292D35C810B /* Pods-medappdoctor.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = medappdoctor/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-ObjC",
|
||||
"-lc++",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
|
||||
PRODUCT_NAME = medappdoctor;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
13B07F951A680F5B00A75B9A /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 5709B34CF0A7D63546082F79 /* Pods-medappdoctor.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
INFOPLIST_FILE = medappdoctor/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0;
|
||||
OTHER_LDFLAGS = (
|
||||
"$(inherited)",
|
||||
"-ObjC",
|
||||
"-lc++",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)";
|
||||
PRODUCT_NAME = medappdoctor;
|
||||
SWIFT_VERSION = 5.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
83CBBA201A601CBA00E9B192 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "c++17";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "";
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.4;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
/usr/lib/swift,
|
||||
"$(inherited)",
|
||||
);
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"\"$(SDKROOT)/usr/lib/swift\"",
|
||||
"\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"",
|
||||
"\"$(inherited)\"",
|
||||
);
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
OTHER_CPLUSPLUSFLAGS = (
|
||||
"$(OTHER_CFLAGS)",
|
||||
"-DFOLLY_NO_CONFIG",
|
||||
"-DFOLLY_MOBILE=1",
|
||||
"-DFOLLY_USE_LIBCPP=1",
|
||||
);
|
||||
SDKROOT = iphoneos;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
83CBBA211A601CBA00E9B192 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "c++17";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_COMMA = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = YES;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "";
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.4;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
/usr/lib/swift,
|
||||
"$(inherited)",
|
||||
);
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"\"$(SDKROOT)/usr/lib/swift\"",
|
||||
"\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"",
|
||||
"\"$(inherited)\"",
|
||||
);
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
OTHER_CPLUSPLUSFLAGS = (
|
||||
"$(OTHER_CFLAGS)",
|
||||
"-DFOLLY_NO_CONFIG",
|
||||
"-DFOLLY_MOBILE=1",
|
||||
"-DFOLLY_USE_LIBCPP=1",
|
||||
);
|
||||
SDKROOT = iphoneos;
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "medappdoctorTests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
00E356F61AD99517003FC87E /* Debug */,
|
||||
00E356F71AD99517003FC87E /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "medappdoctor" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
13B07F941A680F5B00A75B9A /* Debug */,
|
||||
13B07F951A680F5B00A75B9A /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "medappdoctor" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
83CBBA201A601CBA00E9B192 /* Debug */,
|
||||
83CBBA211A601CBA00E9B192 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */;
|
||||
}
|
||||
@ -0,0 +1,88 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1210"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
|
||||
BuildableName = "medappdoctor.app"
|
||||
BlueprintName = "medappdoctor"
|
||||
ReferencedContainer = "container:medappdoctor.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "00E356ED1AD99517003FC87E"
|
||||
BuildableName = "medappdoctorTests.xctest"
|
||||
BlueprintName = "medappdoctorTests"
|
||||
ReferencedContainer = "container:medappdoctor.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
|
||||
BuildableName = "medappdoctor.app"
|
||||
BlueprintName = "medappdoctor"
|
||||
ReferencedContainer = "container:medappdoctor.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
|
||||
BuildableName = "medappdoctor.app"
|
||||
BlueprintName = "medappdoctor"
|
||||
ReferencedContainer = "container:medappdoctor.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
||||
6
ios/blockchainrecapapp/AppDelegate.h
Normal file
@ -0,0 +1,6 @@
|
||||
#import <RCTAppDelegate.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface AppDelegate : RCTAppDelegate
|
||||
|
||||
@end
|
||||
26
ios/blockchainrecapapp/AppDelegate.mm
Normal file
@ -0,0 +1,26 @@
|
||||
#import "AppDelegate.h"
|
||||
|
||||
#import <React/RCTBundleURLProvider.h>
|
||||
|
||||
@implementation AppDelegate
|
||||
|
||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
|
||||
{
|
||||
self.moduleName = @"medappdoctor";
|
||||
// You can add your custom initial props in the dictionary below.
|
||||
// They will be passed down to the ViewController used by React Native.
|
||||
self.initialProps = @{};
|
||||
|
||||
return [super application:application didFinishLaunchingWithOptions:launchOptions];
|
||||
}
|
||||
|
||||
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
|
||||
{
|
||||
#if DEBUG
|
||||
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"];
|
||||
#else
|
||||
return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
|
||||
#endif
|
||||
}
|
||||
|
||||
@end
|
||||
@ -0,0 +1,53 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "2x",
|
||||
"size" : "60x60"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"scale" : "3x",
|
||||
"size" : "60x60"
|
||||
},
|
||||
{
|
||||
"idiom" : "ios-marketing",
|
||||
"scale" : "1x",
|
||||
"size" : "1024x1024"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
6
ios/blockchainrecapapp/Images.xcassets/Contents.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
}
|
||||
}
|
||||
55
ios/blockchainrecapapp/Info.plist
Normal file
@ -0,0 +1,55 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>medappdoctor</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>$(MARKETING_VERSION)</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<key>NSExceptionDomains</key>
|
||||
<dict>
|
||||
<key>localhost</key>
|
||||
<dict>
|
||||
<key>NSExceptionAllowsInsecureHTTPLoads</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>NSLocationWhenInUseUsageDescription</key>
|
||||
<string></string>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</plist>
|
||||
47
ios/blockchainrecapapp/LaunchScreen.storyboard
Normal file
@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="15702" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
||||
<device id="retina4_7" orientation="portrait" appearance="light"/>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15704"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="EHf-IW-A2E">
|
||||
<objects>
|
||||
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="medappdoctor" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="GJd-Yh-RWb">
|
||||
<rect key="frame" x="0.0" y="202" width="375" height="43"/>
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="36"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Powered by React Native" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="MN2-I3-ftu">
|
||||
<rect key="frame" x="0.0" y="626" width="375" height="21"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
|
||||
<constraints>
|
||||
<constraint firstItem="Bcu-3y-fUS" firstAttribute="bottom" secondItem="MN2-I3-ftu" secondAttribute="bottom" constant="20" id="OZV-Vh-mqD"/>
|
||||
<constraint firstItem="Bcu-3y-fUS" firstAttribute="centerX" secondItem="GJd-Yh-RWb" secondAttribute="centerX" id="Q3B-4B-g5h"/>
|
||||
<constraint firstItem="MN2-I3-ftu" firstAttribute="centerX" secondItem="Bcu-3y-fUS" secondAttribute="centerX" id="akx-eg-2ui"/>
|
||||
<constraint firstItem="MN2-I3-ftu" firstAttribute="leading" secondItem="Bcu-3y-fUS" secondAttribute="leading" id="i1E-0Y-4RG"/>
|
||||
<constraint firstItem="GJd-Yh-RWb" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="bottom" multiplier="1/3" constant="1" id="moa-c2-u7t"/>
|
||||
<constraint firstItem="GJd-Yh-RWb" firstAttribute="leading" secondItem="Bcu-3y-fUS" secondAttribute="leading" symbolic="YES" id="x7j-FC-K8j"/>
|
||||
</constraints>
|
||||
<viewLayoutGuide key="safeArea" id="Bcu-3y-fUS"/>
|
||||
</view>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="52.173913043478265" y="375"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
||||
10
ios/blockchainrecapapp/main.m
Normal file
@ -0,0 +1,10 @@
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "AppDelegate.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
@autoreleasepool {
|
||||
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
|
||||
}
|
||||
}
|
||||
24
ios/blockchainrecapappTests/Info.plist
Normal file
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>BNDL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
</dict>
|
||||
</plist>
|
||||
66
ios/blockchainrecapappTests/blockchainrecapappTests.m
Normal file
@ -0,0 +1,66 @@
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#import <React/RCTLog.h>
|
||||
#import <React/RCTRootView.h>
|
||||
|
||||
#define TIMEOUT_SECONDS 600
|
||||
#define TEXT_TO_LOOK_FOR @"Welcome to React"
|
||||
|
||||
@interface medappdoctorTests : XCTestCase
|
||||
|
||||
@end
|
||||
|
||||
@implementation medappdoctorTests
|
||||
|
||||
- (BOOL)findSubviewInView:(UIView *)view matching:(BOOL (^)(UIView *view))test
|
||||
{
|
||||
if (test(view)) {
|
||||
return YES;
|
||||
}
|
||||
for (UIView *subview in [view subviews]) {
|
||||
if ([self findSubviewInView:subview matching:test]) {
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)testRendersWelcomeScreen
|
||||
{
|
||||
UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController];
|
||||
NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS];
|
||||
BOOL foundElement = NO;
|
||||
|
||||
__block NSString *redboxError = nil;
|
||||
#ifdef DEBUG
|
||||
RCTSetLogFunction(
|
||||
^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) {
|
||||
if (level >= RCTLogLevelError) {
|
||||
redboxError = message;
|
||||
}
|
||||
});
|
||||
#endif
|
||||
|
||||
while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) {
|
||||
[[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
|
||||
[[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
|
||||
|
||||
foundElement = [self findSubviewInView:vc.view
|
||||
matching:^BOOL(UIView *view) {
|
||||
if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) {
|
||||
return YES;
|
||||
}
|
||||
return NO;
|
||||
}];
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
RCTSetLogFunction(RCTDefaultLogFunction);
|
||||
#endif
|
||||
|
||||
XCTAssertNil(redboxError, @"RedBox error: %@", redboxError);
|
||||
XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS);
|
||||
}
|
||||
|
||||
@end
|
||||
4
ios/link-assets-manifest.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"migIndex": 1,
|
||||
"data": []
|
||||
}
|
||||
3
jest.config.js
Normal file
@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
preset: 'react-native',
|
||||
};
|
||||
11
metro.config.js
Normal file
@ -0,0 +1,11 @@
|
||||
const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');
|
||||
|
||||
/**
|
||||
* Metro configuration
|
||||
* https://facebook.github.io/metro/docs/configuration
|
||||
*
|
||||
* @type {import('metro-config').MetroConfig}
|
||||
*/
|
||||
const config = {};
|
||||
|
||||
module.exports = mergeConfig(getDefaultConfig(__dirname), config);
|
||||
54
package.json
Normal file
@ -0,0 +1,54 @@
|
||||
{
|
||||
"name": "medappdoctor",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"android": "react-native run-android",
|
||||
"ios": "react-native run-ios",
|
||||
"lint": "eslint .",
|
||||
"start": "react-native start",
|
||||
"test": "jest"
|
||||
},
|
||||
"dependencies": {
|
||||
"@react-native-async-storage/async-storage": "^1.19.4",
|
||||
"@react-navigation/drawer": "^6.6.6",
|
||||
"@react-navigation/native": "^6.1.9",
|
||||
"@react-navigation/native-stack": "^6.9.17",
|
||||
"@react-navigation/stack": "^6.3.20",
|
||||
"@reduxjs/toolkit": "^1.9.7",
|
||||
"@types/react-native-vector-icons": "^6.4.17",
|
||||
"axios": "0.27.2",
|
||||
"react": "18.2.0",
|
||||
"react-native": "0.72.6",
|
||||
"react-native-gesture-handler": "^2.13.4",
|
||||
"react-native-image-picker": "^7.0.2",
|
||||
"react-native-reanimated": "^3.5.4",
|
||||
"react-native-reanimated-carousel": "^3.5.1",
|
||||
"react-native-safe-area-context": "^4.7.4",
|
||||
"react-native-screens": "^3.27.0",
|
||||
"react-native-simple-toast": "^3.0.2",
|
||||
"react-native-stepper-ui": "^0.0.9",
|
||||
"react-native-vector-icons": "^10.0.2",
|
||||
"react-redux": "^8.1.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.20.0",
|
||||
"@babel/preset-env": "^7.20.0",
|
||||
"@babel/runtime": "^7.20.0",
|
||||
"@react-native/eslint-config": "^0.72.2",
|
||||
"@react-native/metro-config": "^0.72.11",
|
||||
"@tsconfig/react-native": "^3.0.0",
|
||||
"@types/react": "^18.0.24",
|
||||
"@types/react-test-renderer": "^18.0.0",
|
||||
"babel-jest": "^29.2.1",
|
||||
"eslint": "^8.19.0",
|
||||
"jest": "^29.2.1",
|
||||
"metro-react-native-babel-preset": "0.76.8",
|
||||
"prettier": "^2.4.1",
|
||||
"react-test-renderer": "18.2.0",
|
||||
"typescript": "4.8.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
}
|
||||
}
|
||||
7
react-native.config.js
Normal file
@ -0,0 +1,7 @@
|
||||
module.exports = {
|
||||
project: {
|
||||
ios: {},
|
||||
android: {}
|
||||
},
|
||||
assets: ['./src/assets/'],
|
||||
};
|
||||
11
src/common/await-to-error.ts
Normal file
@ -0,0 +1,11 @@
|
||||
const awaitToError = async <E = Error, T = unknown>(
|
||||
p: Promise<T>
|
||||
): Promise<[E | null, T | null]> => {
|
||||
try {
|
||||
const r = await Promise.resolve<T>(p);
|
||||
return [null, r];
|
||||
} catch (e) {
|
||||
return [e as E | null, null];
|
||||
}
|
||||
};
|
||||
export default awaitToError;
|
||||
12
src/common/random.ts
Normal file
@ -0,0 +1,12 @@
|
||||
export const randString = (length: number = 32) => {
|
||||
let result = '';
|
||||
const characters =
|
||||
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||
const charactersLength = characters.length;
|
||||
let counter = 0;
|
||||
while (counter < length) {
|
||||
result += characters.charAt(Math.floor(Math.random() * charactersLength));
|
||||
counter += 1;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
72
src/components/Button/DefaultButton.tsx
Normal file
@ -0,0 +1,72 @@
|
||||
import React, { FC } from 'react';
|
||||
import Button from '.';
|
||||
import PZText from '../PZText';
|
||||
import { StyleProp, StyleSheet, ViewStyle } from 'react-native';
|
||||
import colors from '../../res/colors';
|
||||
|
||||
interface DefaultButtonInterface {
|
||||
title: string;
|
||||
white?: boolean;
|
||||
style?: StyleProp<ViewStyle>;
|
||||
onPress?: () => void;
|
||||
loading?: boolean;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
defaultButton: {
|
||||
backgroundColor: colors.defaultPurple,
|
||||
},
|
||||
defaultButtonTitle: {
|
||||
color: colors.white,
|
||||
height: 38,
|
||||
borderRadius: 6,
|
||||
paddingVertical: 10,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
whiteButton: {
|
||||
backgroundColor: colors.white,
|
||||
borderWidth: 2,
|
||||
borderColor: colors.defaultPurple,
|
||||
},
|
||||
whiteText: {
|
||||
paddingVertical: 10,
|
||||
color: colors.defaultPurple,
|
||||
},
|
||||
buttonText: {},
|
||||
buttonBody: {
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
});
|
||||
|
||||
const DefaultButton: FC<DefaultButtonInterface> = ({
|
||||
title,
|
||||
white,
|
||||
style,
|
||||
onPress,
|
||||
loading,
|
||||
disabled,
|
||||
}) => {
|
||||
return (
|
||||
<Button
|
||||
style={{
|
||||
...styles.buttonBody,
|
||||
...(white ? styles.whiteButton : styles.defaultButton),
|
||||
...(style as object),
|
||||
}}
|
||||
onPress={() => (onPress ? onPress() : undefined)}
|
||||
disabled={disabled}>
|
||||
<PZText
|
||||
style={{
|
||||
...styles.buttonText,
|
||||
...(white ? styles.whiteText : styles.defaultButtonTitle),
|
||||
}}>
|
||||
{loading ? 'Loading...' : title}
|
||||
</PZText>
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
export default DefaultButton;
|
||||
52
src/components/Button/index.tsx
Normal file
@ -0,0 +1,52 @@
|
||||
import React, { FC, PropsWithChildren } from 'react';
|
||||
import { StyleProp, StyleSheet, ViewStyle } from 'react-native';
|
||||
import { TouchableOpacity } from 'react-native-gesture-handler';
|
||||
import colors from '../../res/colors';
|
||||
|
||||
interface CustomButton {
|
||||
style?: StyleProp<ViewStyle>;
|
||||
onPress?: () => void;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
type ButtonInterface = PropsWithChildren & CustomButton;
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
button: {
|
||||
alignItems: 'flex-start',
|
||||
borderColor: colors.white,
|
||||
borderRadius: 20,
|
||||
borderWidth: 2,
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'flex-start',
|
||||
marginVertical: 5,
|
||||
paddingHorizontal: 10,
|
||||
paddingVertical: 5,
|
||||
},
|
||||
text: {
|
||||
marginHorizontal: 20,
|
||||
fontSize: 16,
|
||||
textTransform: 'capitalize',
|
||||
color: colors.white,
|
||||
},
|
||||
loader: {},
|
||||
});
|
||||
|
||||
const Button: FC<ButtonInterface> = ({
|
||||
children,
|
||||
style,
|
||||
onPress,
|
||||
disabled,
|
||||
}) => {
|
||||
return (
|
||||
<TouchableOpacity
|
||||
disabled={disabled}
|
||||
style={{ ...styles.button, ...(style as object) }}
|
||||
onPress={() => (onPress ? onPress() : undefined)}>
|
||||
{children}
|
||||
</TouchableOpacity>
|
||||
);
|
||||
};
|
||||
|
||||
export default Button;
|
||||
12
src/components/Icon/Icon.tsx
Normal file
@ -0,0 +1,12 @@
|
||||
import React from "react";
|
||||
import Icon from 'react-native-vector-icons/FontAwesome'
|
||||
|
||||
export interface IconProps {
|
||||
size: number;
|
||||
name: string;
|
||||
color: string;
|
||||
}
|
||||
|
||||
export const Icons = ({ size, name, color }: IconProps) => {
|
||||
return <Icon name={name} size={size} color={color}/>
|
||||
}
|
||||
46
src/components/PZInput/index.tsx
Normal file
@ -0,0 +1,46 @@
|
||||
import React from 'react';
|
||||
import { KeyboardTypeOptions, StyleSheet } from 'react-native';
|
||||
import PZText from '../PZText';
|
||||
import { TextInput } from 'react-native-gesture-handler';
|
||||
|
||||
interface PZInputInterface {
|
||||
label: string;
|
||||
value: string;
|
||||
disable?: boolean;
|
||||
keyboardType?: KeyboardTypeOptions;
|
||||
onChangeText?: (val: string) => void;
|
||||
}
|
||||
|
||||
const PZInput = (props: PZInputInterface) => {
|
||||
return (
|
||||
<>
|
||||
<PZText style={styles.label}>{props.label}</PZText>
|
||||
<TextInput
|
||||
editable={!props.disable}
|
||||
value={props.value}
|
||||
onChangeText={val =>
|
||||
props.onChangeText ? props.onChangeText(val) : undefined
|
||||
}
|
||||
style={styles.input}
|
||||
keyboardType={props.keyboardType}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
input: {
|
||||
height: 40,
|
||||
borderColor: '#DBDADE',
|
||||
borderWidth: 1,
|
||||
borderRadius: 5,
|
||||
paddingHorizontal: 10,
|
||||
backgroundColor: 'white',
|
||||
color: 'black',
|
||||
},
|
||||
label: {
|
||||
marginBottom: 5,
|
||||
},
|
||||
});
|
||||
|
||||
export default PZInput;
|
||||
15
src/components/PZText/index.tsx
Normal file
@ -0,0 +1,15 @@
|
||||
import React from 'react';
|
||||
import { Text, TextProps } from 'react-native';
|
||||
import styles from '../../styles/main';
|
||||
|
||||
const PZText = (props: TextProps) => {
|
||||
return (
|
||||
<Text
|
||||
{...props}
|
||||
style={{ ...styles.globalText, ...(props.style as Object) }}>
|
||||
{props.children}
|
||||
</Text>
|
||||
);
|
||||
};
|
||||
|
||||
export default PZText;
|
||||
467
src/components/Stepper/index.tsx
Normal file
@ -0,0 +1,467 @@
|
||||
/* eslint-disable react-native/no-inline-styles */
|
||||
import React from 'react';
|
||||
import {
|
||||
View,
|
||||
Text,
|
||||
StyleSheet,
|
||||
Animated,
|
||||
TouchableWithoutFeedback,
|
||||
ViewStyle,
|
||||
TextStyle,
|
||||
} from 'react-native';
|
||||
import { StepIndicatorProps } from '../../types/stepper';
|
||||
|
||||
const STEP_STATUS = {
|
||||
CURRENT: 'current',
|
||||
FINISHED: 'finished',
|
||||
UNFINISHED: 'unfinished',
|
||||
};
|
||||
|
||||
interface DefaultStepIndicatorStyles {
|
||||
stepIndicatorSize: number;
|
||||
currentStepIndicatorSize: number;
|
||||
separatorStrokeWidth: number;
|
||||
separatorStrokeUnfinishedWidth: number;
|
||||
separatorStrokeFinishedWidth: number;
|
||||
currentStepStrokeWidth: number;
|
||||
stepStrokeWidth: number;
|
||||
stepStrokeCurrentColor: string;
|
||||
stepStrokeFinishedColor: string;
|
||||
stepStrokeUnFinishedColor: string;
|
||||
separatorFinishedColor: string;
|
||||
separatorUnFinishedColor: string;
|
||||
stepIndicatorFinishedColor: string;
|
||||
stepIndicatorUnFinishedColor: string;
|
||||
stepIndicatorCurrentColor: string;
|
||||
stepIndicatorLabelFontSize: number;
|
||||
currentStepIndicatorLabelFontSize: number;
|
||||
stepIndicatorLabelCurrentColor: string;
|
||||
stepIndicatorLabelFinishedColor: string;
|
||||
stepIndicatorLabelUnFinishedColor: string;
|
||||
labelColor: string;
|
||||
labelSize: number;
|
||||
labelAlign:
|
||||
| 'center'
|
||||
| 'flex-start'
|
||||
| 'flex-end'
|
||||
| 'stretch'
|
||||
| 'baseline'
|
||||
| undefined;
|
||||
currentStepLabelColor: string;
|
||||
labelFontFamily?: string;
|
||||
}
|
||||
|
||||
const defaultStyles: DefaultStepIndicatorStyles = {
|
||||
stepIndicatorSize: 30,
|
||||
currentStepIndicatorSize: 40,
|
||||
separatorStrokeWidth: 3,
|
||||
separatorStrokeUnfinishedWidth: 0,
|
||||
separatorStrokeFinishedWidth: 0,
|
||||
currentStepStrokeWidth: 5,
|
||||
stepStrokeWidth: 0,
|
||||
stepStrokeCurrentColor: '#4aae4f',
|
||||
stepStrokeFinishedColor: '#4aae4f',
|
||||
stepStrokeUnFinishedColor: '#4aae4f',
|
||||
separatorFinishedColor: '#4aae4f',
|
||||
separatorUnFinishedColor: '#a4d4a5',
|
||||
stepIndicatorFinishedColor: '#4aae4f',
|
||||
stepIndicatorUnFinishedColor: '#a4d4a5',
|
||||
stepIndicatorCurrentColor: '#ffffff',
|
||||
stepIndicatorLabelFontSize: 15,
|
||||
currentStepIndicatorLabelFontSize: 15,
|
||||
stepIndicatorLabelCurrentColor: '#000000',
|
||||
stepIndicatorLabelFinishedColor: '#ffffff',
|
||||
stepIndicatorLabelUnFinishedColor: 'rgba(255,255,255,0.5)',
|
||||
labelColor: '#000000',
|
||||
labelSize: 13,
|
||||
labelAlign: 'center',
|
||||
currentStepLabelColor: '#4aae4f',
|
||||
};
|
||||
|
||||
const StepIndicator = ({
|
||||
currentPosition = 0,
|
||||
stepCount = 5,
|
||||
direction = 'horizontal',
|
||||
customStyles: customStylesFromProps = defaultStyles,
|
||||
labels = [],
|
||||
onPress,
|
||||
renderStepIndicator: renderCustomStepIndicator,
|
||||
renderLabel,
|
||||
}: StepIndicatorProps) => {
|
||||
const [width, setWidth] = React.useState<number>(0);
|
||||
const [height, setHeight] = React.useState<number>(0);
|
||||
const [progressBarSize, setProgressBarSize] = React.useState<number>(0);
|
||||
const [customStyles, setCustomStyles] =
|
||||
React.useState<DefaultStepIndicatorStyles>({
|
||||
...defaultStyles,
|
||||
...customStylesFromProps,
|
||||
});
|
||||
|
||||
const progressAnim = React.useRef(new Animated.Value(0)).current;
|
||||
const sizeAnim = React.useRef(
|
||||
new Animated.Value(customStyles.stepIndicatorSize),
|
||||
).current;
|
||||
const staleSizeAnim = React.useRef(
|
||||
new Animated.Value(customStyles.stepIndicatorSize),
|
||||
).current;
|
||||
const borderRadiusAnim = React.useRef(
|
||||
new Animated.Value(customStyles.stepIndicatorSize / 2),
|
||||
).current;
|
||||
|
||||
const stepPressed = (position: number) => {
|
||||
if (onPress) {
|
||||
onPress(position);
|
||||
}
|
||||
};
|
||||
|
||||
const effectCustomStyles = () => {
|
||||
setCustomStyles({ ...customStyles, ...customStylesFromProps });
|
||||
};
|
||||
React.useEffect(effectCustomStyles, [customStylesFromProps]);
|
||||
|
||||
const effectCurrentPosition = () => {
|
||||
onCurrentPositionChanged(currentPosition);
|
||||
};
|
||||
React.useEffect(effectCurrentPosition, [currentPosition, progressBarSize]);
|
||||
|
||||
const renderProgressBarBackground = () => {
|
||||
let progressBarBackgroundStyle: ViewStyle = {
|
||||
backgroundColor: customStyles.separatorUnFinishedColor,
|
||||
position: 'absolute',
|
||||
};
|
||||
if (direction === 'vertical') {
|
||||
progressBarBackgroundStyle = {
|
||||
...progressBarBackgroundStyle,
|
||||
left: (width - customStyles.separatorStrokeWidth) / 2,
|
||||
top: height / (2 * stepCount),
|
||||
bottom: height / (2 * stepCount),
|
||||
width:
|
||||
customStyles.separatorStrokeUnfinishedWidth === 0
|
||||
? customStyles.separatorStrokeWidth
|
||||
: customStyles.separatorStrokeUnfinishedWidth,
|
||||
};
|
||||
} else {
|
||||
progressBarBackgroundStyle = {
|
||||
...progressBarBackgroundStyle,
|
||||
top: (height - customStyles.separatorStrokeWidth) / 2,
|
||||
left: width / (2 * stepCount),
|
||||
right: width / (2 * stepCount),
|
||||
height:
|
||||
customStyles.separatorStrokeUnfinishedWidth === 0
|
||||
? customStyles.separatorStrokeWidth
|
||||
: customStyles.separatorStrokeUnfinishedWidth,
|
||||
};
|
||||
}
|
||||
return (
|
||||
<View
|
||||
onLayout={event => {
|
||||
if (direction === 'vertical') {
|
||||
setProgressBarSize(event.nativeEvent.layout.height);
|
||||
} else {
|
||||
setProgressBarSize(event.nativeEvent.layout.width);
|
||||
}
|
||||
}}
|
||||
style={progressBarBackgroundStyle}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const renderProgressBar = () => {
|
||||
let progressBarStyle: any = {
|
||||
backgroundColor: customStyles.separatorFinishedColor,
|
||||
position: 'absolute',
|
||||
};
|
||||
if (direction === 'vertical') {
|
||||
progressBarStyle = {
|
||||
...progressBarStyle,
|
||||
left: (width - customStyles.separatorStrokeWidth) / 2,
|
||||
top: height / (2 * stepCount),
|
||||
bottom: height / (2 * stepCount),
|
||||
width:
|
||||
customStyles.separatorStrokeFinishedWidth === 0
|
||||
? customStyles.separatorStrokeWidth
|
||||
: customStyles.separatorStrokeFinishedWidth,
|
||||
height: progressAnim,
|
||||
};
|
||||
} else {
|
||||
progressBarStyle = {
|
||||
...progressBarStyle,
|
||||
top: (height - customStyles.separatorStrokeWidth) / 2,
|
||||
left: width / (2 * stepCount),
|
||||
right: width / (2 * stepCount),
|
||||
height:
|
||||
customStyles.separatorStrokeFinishedWidth === 0
|
||||
? customStyles.separatorStrokeWidth
|
||||
: customStyles.separatorStrokeFinishedWidth,
|
||||
width: progressAnim,
|
||||
};
|
||||
}
|
||||
return <Animated.View style={progressBarStyle} />;
|
||||
};
|
||||
|
||||
const renderStepIndicator = () => {
|
||||
let steps: any[] = [];
|
||||
for (let position = 0; position < stepCount; position++) {
|
||||
steps.push(
|
||||
<TouchableWithoutFeedback
|
||||
key={position}
|
||||
onPress={() => stepPressed(position)}>
|
||||
<View
|
||||
style={[
|
||||
styles.stepContainer,
|
||||
direction === 'vertical'
|
||||
? { flexDirection: 'column' }
|
||||
: { flexDirection: 'row' },
|
||||
]}>
|
||||
{renderStep(position)}
|
||||
</View>
|
||||
</TouchableWithoutFeedback>,
|
||||
);
|
||||
}
|
||||
return (
|
||||
<View
|
||||
onLayout={event => {
|
||||
setWidth(event.nativeEvent.layout.width);
|
||||
setHeight(event.nativeEvent.layout.height);
|
||||
}}
|
||||
style={[
|
||||
styles.stepIndicatorContainer,
|
||||
direction === 'vertical'
|
||||
? {
|
||||
flexDirection: 'column',
|
||||
width: customStyles.currentStepIndicatorSize,
|
||||
}
|
||||
: {
|
||||
flexDirection: 'row',
|
||||
height: customStyles.currentStepIndicatorSize,
|
||||
},
|
||||
]}>
|
||||
{steps}
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const renderStepLabels = () => {
|
||||
if (!labels || labels.length === 0) {
|
||||
return;
|
||||
}
|
||||
var labelViews = labels.map((label, index) => {
|
||||
const selectedStepLabelStyle =
|
||||
index === currentPosition
|
||||
? { color: customStyles.currentStepLabelColor }
|
||||
: { color: customStyles.labelColor };
|
||||
return (
|
||||
<TouchableWithoutFeedback
|
||||
style={styles.stepLabelItem}
|
||||
key={index}
|
||||
onPress={() => stepPressed(index)}>
|
||||
<View style={styles.stepLabelItem}>
|
||||
{renderLabel ? (
|
||||
renderLabel({
|
||||
position: index,
|
||||
stepStatus: getStepStatus(index),
|
||||
label,
|
||||
currentPosition,
|
||||
})
|
||||
) : (
|
||||
<Text
|
||||
style={[
|
||||
styles.stepLabel,
|
||||
selectedStepLabelStyle,
|
||||
{
|
||||
fontSize: customStyles.labelSize,
|
||||
fontFamily: customStyles.labelFontFamily,
|
||||
},
|
||||
]}>
|
||||
{label}
|
||||
</Text>
|
||||
)}
|
||||
</View>
|
||||
</TouchableWithoutFeedback>
|
||||
);
|
||||
});
|
||||
|
||||
return (
|
||||
<View
|
||||
style={[
|
||||
styles.stepLabelsContainer,
|
||||
direction === 'vertical'
|
||||
? { flexDirection: 'column', paddingHorizontal: 4 }
|
||||
: { flexDirection: 'row', paddingVertical: 4 },
|
||||
{ alignItems: customStyles.labelAlign },
|
||||
]}>
|
||||
{labelViews}
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const renderStep = (position: number) => {
|
||||
let stepStyle: any;
|
||||
let indicatorLabelStyle: TextStyle = {};
|
||||
switch (getStepStatus(position)) {
|
||||
case STEP_STATUS.CURRENT: {
|
||||
stepStyle = {
|
||||
backgroundColor: customStyles.stepIndicatorCurrentColor,
|
||||
borderWidth: customStyles.currentStepStrokeWidth,
|
||||
borderColor: customStyles.stepStrokeCurrentColor,
|
||||
height: sizeAnim,
|
||||
width: sizeAnim,
|
||||
borderRadius: borderRadiusAnim,
|
||||
overflow: 'hidden',
|
||||
};
|
||||
indicatorLabelStyle = {
|
||||
overflow: 'hidden',
|
||||
fontSize: customStyles.currentStepIndicatorLabelFontSize,
|
||||
color: customStyles.stepIndicatorLabelCurrentColor,
|
||||
};
|
||||
|
||||
break;
|
||||
}
|
||||
case STEP_STATUS.FINISHED: {
|
||||
stepStyle = {
|
||||
backgroundColor: customStyles.stepIndicatorFinishedColor,
|
||||
borderWidth: customStyles.stepStrokeWidth,
|
||||
borderColor: customStyles.stepStrokeFinishedColor,
|
||||
height: staleSizeAnim,
|
||||
width: staleSizeAnim,
|
||||
borderRadius: customStyles.stepIndicatorSize / 2,
|
||||
overflow: 'hidden',
|
||||
};
|
||||
indicatorLabelStyle = {
|
||||
overflow: 'hidden',
|
||||
fontSize: customStyles.stepIndicatorLabelFontSize,
|
||||
color: customStyles.stepIndicatorLabelFinishedColor,
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
||||
case STEP_STATUS.UNFINISHED: {
|
||||
stepStyle = {
|
||||
backgroundColor: customStyles.stepIndicatorUnFinishedColor,
|
||||
borderWidth: customStyles.stepStrokeWidth,
|
||||
borderColor: customStyles.stepStrokeUnFinishedColor,
|
||||
height: staleSizeAnim,
|
||||
width: staleSizeAnim,
|
||||
borderRadius: customStyles.stepIndicatorSize / 2,
|
||||
overflow: 'hidden',
|
||||
};
|
||||
indicatorLabelStyle = {
|
||||
overflow: 'hidden',
|
||||
fontSize: customStyles.stepIndicatorLabelFontSize,
|
||||
color: customStyles.stepIndicatorLabelUnFinishedColor,
|
||||
};
|
||||
break;
|
||||
}
|
||||
default:
|
||||
}
|
||||
|
||||
return (
|
||||
<Animated.View key={'step-indicator'} style={[styles.step, stepStyle]}>
|
||||
{renderCustomStepIndicator ? (
|
||||
renderCustomStepIndicator({
|
||||
position,
|
||||
stepStatus: getStepStatus(position),
|
||||
})
|
||||
) : (
|
||||
<Text style={indicatorLabelStyle}>{`${position + 1}`}</Text>
|
||||
)}
|
||||
</Animated.View>
|
||||
);
|
||||
};
|
||||
|
||||
const getStepStatus = (stepPosition: number) => {
|
||||
if (stepPosition === currentPosition) {
|
||||
return STEP_STATUS.CURRENT;
|
||||
} else if (stepPosition < currentPosition) {
|
||||
return STEP_STATUS.FINISHED;
|
||||
} else {
|
||||
return STEP_STATUS.UNFINISHED;
|
||||
}
|
||||
};
|
||||
|
||||
const onCurrentPositionChanged = (position: number) => {
|
||||
if (position > stepCount - 1) {
|
||||
position = stepCount - 1;
|
||||
}
|
||||
const animateToPosition = (progressBarSize / (stepCount - 1)) * position;
|
||||
sizeAnim.setValue(customStyles.stepIndicatorSize);
|
||||
staleSizeAnim.setValue(customStyles.stepIndicatorSize);
|
||||
borderRadiusAnim.setValue(customStyles.stepIndicatorSize / 2);
|
||||
Animated.sequence([
|
||||
Animated.timing(progressAnim, {
|
||||
toValue: isNaN(animateToPosition) ? 0 : animateToPosition,
|
||||
duration: 200,
|
||||
useNativeDriver: false,
|
||||
}),
|
||||
Animated.parallel([
|
||||
Animated.timing(sizeAnim, {
|
||||
toValue: customStyles.currentStepIndicatorSize,
|
||||
duration: 100,
|
||||
useNativeDriver: false,
|
||||
}),
|
||||
Animated.timing(borderRadiusAnim, {
|
||||
toValue: customStyles.currentStepIndicatorSize / 2,
|
||||
duration: 100,
|
||||
useNativeDriver: false,
|
||||
}),
|
||||
]),
|
||||
]).start();
|
||||
};
|
||||
|
||||
return (
|
||||
<View
|
||||
style={[
|
||||
styles.container,
|
||||
direction === 'vertical'
|
||||
? { flexDirection: 'row', flex: 1 }
|
||||
: { flexDirection: 'column' },
|
||||
]}>
|
||||
{width !== 0 && (
|
||||
<React.Fragment>
|
||||
{renderProgressBarBackground()}
|
||||
{renderProgressBar()}
|
||||
</React.Fragment>
|
||||
)}
|
||||
{renderStepIndicator()}
|
||||
{labels && renderStepLabels()}
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
backgroundColor: 'rgba(1,0,0,0)',
|
||||
},
|
||||
stepIndicatorContainer: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-around',
|
||||
backgroundColor: 'rgba(1,0,0,0)',
|
||||
},
|
||||
stepLabelsContainer: {
|
||||
justifyContent: 'space-around',
|
||||
},
|
||||
step: {
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
zIndex: 2,
|
||||
},
|
||||
stepContainer: {
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
stepLabel: {
|
||||
fontSize: 12,
|
||||
textAlign: 'center',
|
||||
fontWeight: '500',
|
||||
},
|
||||
stepLabelItem: {
|
||||
flex: 1,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
});
|
||||
|
||||
export default React.memo(StepIndicator);
|
||||
1
src/config/auth.ts
Normal file
@ -0,0 +1 @@
|
||||
export const AUTH_URL = 'https://kpu-core-demo.staging.productzillaacademy.com';
|
||||
3
src/config/blockchain.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export const BC_AUTH_URL = 'http://62.72.45.52:4000';
|
||||
export const BC_URL = 'http://62.72.45.52:4000';
|
||||
export const PHOTO_HASH_SECRET = 'abcdefghijklmnopqrstuvwxyz123456';
|
||||
1
src/config/core.ts
Normal file
@ -0,0 +1 @@
|
||||
export const CORE_URL = 'https://kpu-core-new.staging.productzillaacademy.com';
|
||||
1
src/config/demo.ts
Normal file
@ -0,0 +1 @@
|
||||
export const DEMO_URL = 'https://kpu-core-demo.staging.productzillaacademy.com';
|
||||
4
src/config/elasticsearch.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export const ES_HOST =
|
||||
'https://elasticsearch.analytics.productzillaacademy.com';
|
||||
export const ES_BASIC_AUTH = 'Basic cHotZGV2OmFzZGZBU0RGMTIzNCFAIyQ=';
|
||||
export const ES_MONITORING_INDEX = 'mobile_app-kpu-staging';
|
||||
5
src/res/colors.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export default {
|
||||
white: '#ffffff',
|
||||
black: '#000000',
|
||||
defaultPurple: '#7367F0',
|
||||
};
|
||||
240
src/screens/DocumentInput/index.tsx
Normal file
@ -0,0 +1,240 @@
|
||||
import React, { FC, useState } from 'react';
|
||||
import { Button, ScrollView, StyleSheet, View } from 'react-native';
|
||||
import { Suara } from '../../types/suara';
|
||||
import PZInput from '../../components/PZInput';
|
||||
import PZText from '../../components/PZText';
|
||||
import { useSubmitSuara } from '../../services/suara';
|
||||
import DefaultButton from '../../components/Button/DefaultButton';
|
||||
import { useAppDispatch, useAppSelector } from '../../store';
|
||||
import { setStep } from '../../store/reducers/home';
|
||||
import awaitToError from '../../common/await-to-error';
|
||||
import { setPhotos, setSuara } from '../../store/reducers/document';
|
||||
|
||||
interface DocumentInputInterface {
|
||||
finished?: boolean;
|
||||
}
|
||||
|
||||
const DocumentInput: FC<DocumentInputInterface> = ({ finished = false }) => {
|
||||
const dispatch = useAppDispatch();
|
||||
const { suara, photos } = useAppSelector(state => state.document ?? {});
|
||||
const useError = (initial = '') => useState(initial);
|
||||
const {
|
||||
error: errorSubmit,
|
||||
loading: loadingSubmit,
|
||||
submit,
|
||||
} = useSubmitSuara();
|
||||
const {
|
||||
sah,
|
||||
tidakSah,
|
||||
pasangan01,
|
||||
pasangan02,
|
||||
dikembalikan,
|
||||
diterima,
|
||||
tidakDigunakan,
|
||||
tps,
|
||||
} = suara;
|
||||
|
||||
const setSuaraPartial = (obj: Partial<Suara>) => {
|
||||
dispatch(setSuara({ ...suara, ...obj }));
|
||||
};
|
||||
|
||||
const [errorMessage, setErrorMessage] = useError();
|
||||
const validate = () => {
|
||||
if (!diterima) {
|
||||
setErrorMessage('Suara Diterima harus diisi');
|
||||
return false;
|
||||
}
|
||||
if (!dikembalikan) {
|
||||
setErrorMessage('Suara Dikembalikan harus diisi');
|
||||
return false;
|
||||
}
|
||||
if (!tidakDigunakan) {
|
||||
setErrorMessage('Suara Tidak Digunakan harus diisi');
|
||||
return false;
|
||||
}
|
||||
if (!sah) {
|
||||
setErrorMessage('Suara sah harus diisi');
|
||||
return false;
|
||||
}
|
||||
if (!tidakSah) {
|
||||
setErrorMessage('Suara tidak sah harus diisi');
|
||||
return false;
|
||||
}
|
||||
if (!pasangan01) {
|
||||
setErrorMessage('Suara Pasangan 01 harus diisi');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!pasangan02) {
|
||||
setErrorMessage('Suara Pasangan 02 harus diisi');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
const onBackPressed = async () => {
|
||||
dispatch(setStep(0));
|
||||
};
|
||||
|
||||
const pressSubmit = async () => {
|
||||
if (!validate()) {
|
||||
return;
|
||||
}
|
||||
const [err] = await awaitToError(submit(suara, photos));
|
||||
if (!err) {
|
||||
dispatch(setStep(2));
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<ScrollView>
|
||||
<View style={styles.inputWrapper}>
|
||||
<PZInput
|
||||
label="Nomor TPS"
|
||||
value={tps}
|
||||
onChangeText={_tps => setSuaraPartial({ tps: _tps })}
|
||||
disable={finished}
|
||||
/>
|
||||
</View>
|
||||
<View style={styles.inputWrapper}>
|
||||
<PZInput
|
||||
label="Suara diterima"
|
||||
value={diterima}
|
||||
onChangeText={_diterima => setSuaraPartial({ diterima: _diterima })}
|
||||
keyboardType="number-pad"
|
||||
disable={finished}
|
||||
/>
|
||||
</View>
|
||||
<View style={styles.inputWrapper}>
|
||||
<PZInput
|
||||
label="Suara dikembalikan"
|
||||
value={dikembalikan}
|
||||
onChangeText={_dikembalikan =>
|
||||
setSuaraPartial({ dikembalikan: _dikembalikan })
|
||||
}
|
||||
keyboardType="number-pad"
|
||||
disable={finished}
|
||||
/>
|
||||
</View>
|
||||
<View style={styles.inputWrapper}>
|
||||
<PZInput
|
||||
label="Suara tidak digunakan"
|
||||
value={tidakDigunakan}
|
||||
onChangeText={_tidakDigunakan =>
|
||||
setSuaraPartial({ tidakDigunakan: _tidakDigunakan })
|
||||
}
|
||||
keyboardType="number-pad"
|
||||
disable={finished}
|
||||
/>
|
||||
</View>
|
||||
<View style={styles.inputWrapper}>
|
||||
<PZInput
|
||||
label="Suara Pasangan 01"
|
||||
value={pasangan01}
|
||||
onChangeText={_pasangan01 =>
|
||||
setSuaraPartial({ pasangan01: _pasangan01 })
|
||||
}
|
||||
keyboardType="number-pad"
|
||||
disable={finished}
|
||||
/>
|
||||
</View>
|
||||
<View style={styles.inputWrapper}>
|
||||
<PZInput
|
||||
label="Suara Pasangan 02"
|
||||
value={pasangan02}
|
||||
onChangeText={_pasangan02 =>
|
||||
setSuaraPartial({ pasangan02: _pasangan02 })
|
||||
}
|
||||
keyboardType="number-pad"
|
||||
disable={finished}
|
||||
/>
|
||||
</View>
|
||||
<View style={styles.inputWrapper}>
|
||||
<PZInput
|
||||
label="Jumlah Suara Sah"
|
||||
value={sah}
|
||||
onChangeText={_sah => setSuaraPartial({ sah: _sah })}
|
||||
keyboardType="number-pad"
|
||||
disable={finished}
|
||||
/>
|
||||
</View>
|
||||
<View style={styles.inputWrapper}>
|
||||
<PZInput
|
||||
label="Jumlah Suara Tidak Sah"
|
||||
value={tidakSah}
|
||||
onChangeText={_tidakSah => setSuaraPartial({ tidakSah: _tidakSah })}
|
||||
keyboardType="number-pad"
|
||||
disable={finished}
|
||||
/>
|
||||
</View>
|
||||
<View style={styles.inputWrapper}>
|
||||
<PZInput
|
||||
disable
|
||||
label="Total Suara Sah dan Tidak Sah"
|
||||
value={(parseInt(sah, 10) + parseInt(tidakSah, 10) || '').toString()}
|
||||
keyboardType="number-pad"
|
||||
/>
|
||||
</View>
|
||||
<View style={styles.inputWrapper}>
|
||||
<PZText style={{ color: '#f00' }}>{errorMessage || errorSubmit}</PZText>
|
||||
</View>
|
||||
<View style={styles.inputWrapper}>
|
||||
{!finished ? (
|
||||
<>
|
||||
<Button
|
||||
color="#7367F0"
|
||||
onPress={pressSubmit}
|
||||
title="Submit"
|
||||
loading={loadingSubmit}
|
||||
disabled={loadingSubmit}
|
||||
/>
|
||||
<PZText
|
||||
style={{ color: '#7367F0', textAlign: 'center', marginTop: 7 }}
|
||||
onPress={onBackPressed}>
|
||||
Kembali
|
||||
</PZText>
|
||||
</>
|
||||
) : (
|
||||
<Button
|
||||
color="#7367F0"
|
||||
title="Selesai"
|
||||
onPress={() => {
|
||||
dispatch(setStep(0));
|
||||
dispatch(setPhotos([]));
|
||||
dispatch(setSuara({} as Suara));
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
<View style={{ height: 100 }} />
|
||||
</ScrollView>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
title: {
|
||||
fontSize: 20,
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
separator: {
|
||||
marginVertical: 30,
|
||||
height: 1,
|
||||
width: '80%',
|
||||
},
|
||||
input: {
|
||||
height: 40,
|
||||
borderColor: '#DBDADE',
|
||||
borderWidth: 1,
|
||||
borderRadius: 5,
|
||||
paddingHorizontal: 10,
|
||||
backgroundColor: 'white',
|
||||
},
|
||||
inputWrapper: { padding: 10 },
|
||||
});
|
||||
|
||||
export default DocumentInput;
|
||||
57
src/screens/DocumentUpload/PhotoList.tsx
Normal file
@ -0,0 +1,57 @@
|
||||
import React, { FC } from 'react';
|
||||
import { Image, StyleSheet, View } from 'react-native';
|
||||
import PZText from '../../components/PZText';
|
||||
import { Asset } from 'react-native-image-picker';
|
||||
import colors from '../../res/colors';
|
||||
import DefaultButton from '../../components/Button/DefaultButton';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
imageListWrapper: {
|
||||
flexDirection: 'row', // Arrange children horizontally
|
||||
alignItems: 'center', // Center children vertically
|
||||
justifyContent: 'space-between',
|
||||
width: '100%',
|
||||
height: 100,
|
||||
paddingVertical: 10,
|
||||
paddingHorizontal: 10,
|
||||
borderRadius: 8,
|
||||
borderColor: '#CACFD4',
|
||||
borderWidth: 1,
|
||||
marginBottom: 10,
|
||||
},
|
||||
imageInfoContainer: {
|
||||
flexDirection: 'row', // This will make image and name side by side
|
||||
alignItems: 'center', // Center vertically
|
||||
// You can add additional styles for spacing and alignment as needed
|
||||
},
|
||||
imageThumbnail: {
|
||||
width: 70,
|
||||
height: 90,
|
||||
},
|
||||
imageName: {
|
||||
marginLeft: 10, // Add some space between the image and text
|
||||
},
|
||||
removeButton: {
|
||||
color: colors.black,
|
||||
width: 60,
|
||||
},
|
||||
});
|
||||
|
||||
interface PhotoListInterface {
|
||||
photo: Asset;
|
||||
onRemove: () => void;
|
||||
}
|
||||
|
||||
const PhotoList: FC<PhotoListInterface> = ({ photo, onRemove }) => {
|
||||
return (
|
||||
<View style={styles.imageListWrapper}>
|
||||
<View style={styles.imageInfoContainer}>
|
||||
<Image source={{ uri: photo.uri }} style={styles.imageThumbnail} />
|
||||
<PZText style={styles.imageName}>{photo.fileName}</PZText>
|
||||
</View>
|
||||
<DefaultButton white title="Remove" onPress={() => onRemove()} />
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export default PhotoList;
|
||||
210
src/screens/DocumentUpload/index.tsx
Normal file
@ -0,0 +1,210 @@
|
||||
import React, { useState } from 'react';
|
||||
import {
|
||||
Alert,
|
||||
Button,
|
||||
PermissionsAndroid,
|
||||
Platform,
|
||||
StyleSheet,
|
||||
View,
|
||||
} from 'react-native';
|
||||
import PZText from '../../components/PZText';
|
||||
import DefaultButton from '../../components/Button/DefaultButton';
|
||||
import {
|
||||
launchImageLibrary,
|
||||
launchCamera,
|
||||
ImagePickerResponse,
|
||||
} from 'react-native-image-picker';
|
||||
import awaitToError from '../../common/await-to-error';
|
||||
import PhotoList from './PhotoList';
|
||||
import { useAppDispatch, useAppSelector } from '../../store';
|
||||
import { addPhotos, removePhoto } from '../../store/reducers/document';
|
||||
import { coreRequest } from '../../services/request/core';
|
||||
import { C1Document } from '../../types/upload';
|
||||
import { request } from '../../services/request/request';
|
||||
import { randString } from '../../common/random';
|
||||
import { setStep } from '../../store/reducers/home';
|
||||
|
||||
const DocumentUpload = () => {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const dispatch = useAppDispatch();
|
||||
const { photos } = useAppSelector(state => state.document ?? {});
|
||||
|
||||
const appendPhotos = async (photo: ImagePickerResponse) => {
|
||||
if (!photo.assets) {
|
||||
return;
|
||||
}
|
||||
dispatch(addPhotos({ ...photo.assets[0], hashedName: randString() }));
|
||||
};
|
||||
|
||||
const handleChoosePhoto = async () => {
|
||||
const [err, result] = await awaitToError(
|
||||
launchImageLibrary({ mediaType: 'photo' }),
|
||||
);
|
||||
if (err) {
|
||||
console.log(err);
|
||||
return;
|
||||
}
|
||||
appendPhotos(result as ImagePickerResponse);
|
||||
};
|
||||
|
||||
const handleTakePhoto = async () => {
|
||||
const cameraPermission = await PermissionsAndroid.check(
|
||||
PermissionsAndroid.PERMISSIONS.CAMERA,
|
||||
);
|
||||
if (!cameraPermission) {
|
||||
const granted = await PermissionsAndroid.request(
|
||||
PermissionsAndroid.PERMISSIONS.CAMERA,
|
||||
);
|
||||
if (granted !== PermissionsAndroid.RESULTS.GRANTED) {
|
||||
Alert.alert('Anda harus memberi izin untuk membuka kamera');
|
||||
return;
|
||||
}
|
||||
}
|
||||
const [err, result] = await awaitToError(
|
||||
launchCamera({
|
||||
mediaType: 'photo',
|
||||
saveToPhotos: true,
|
||||
}),
|
||||
);
|
||||
if (err) {
|
||||
console.log(err);
|
||||
return;
|
||||
}
|
||||
appendPhotos(result as ImagePickerResponse);
|
||||
};
|
||||
|
||||
const handleRemovePhoto = (index: number) => {
|
||||
dispatch(removePhoto(index));
|
||||
};
|
||||
|
||||
const uploadProcess = async (photo: C1Document) => {
|
||||
let err = null,
|
||||
res = null;
|
||||
[err, res] = await awaitToError(
|
||||
coreRequest().post('/s3', {
|
||||
path: `kpu/blockchain/dokumen-c1/${photo.hashedName}.jpg`,
|
||||
method: 'PUT',
|
||||
}),
|
||||
);
|
||||
if (err) {
|
||||
console.log('S3 Request error', err);
|
||||
throw err;
|
||||
}
|
||||
const data = new FormData();
|
||||
|
||||
data.append('file', {
|
||||
name: photo.hashedName,
|
||||
type: photo.type,
|
||||
uri:
|
||||
Platform.OS === 'ios' ? photo?.uri?.replace('file://', '') : photo.uri,
|
||||
});
|
||||
data.append('Content-Type', photo.type);
|
||||
[err, res] = await awaitToError(
|
||||
request().put(res?.data.url, data, {
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
},
|
||||
}),
|
||||
);
|
||||
if (err) {
|
||||
console.log('S3 Upload error', err);
|
||||
throw err;
|
||||
}
|
||||
return photo.hashedName;
|
||||
};
|
||||
|
||||
const handleUpload = async () => {
|
||||
if (photos.length < 1) {
|
||||
Alert.alert('Silakan pilih foto atau ambil foto 1 lembar C1');
|
||||
return;
|
||||
}
|
||||
setLoading(true);
|
||||
const p = [];
|
||||
for (const photo of photos) {
|
||||
p.push(uploadProcess(photo));
|
||||
}
|
||||
const result = await Promise.allSettled(p);
|
||||
if (result.find(d => d.status === 'rejected')) {
|
||||
Alert.alert('Bukti Foto gagal di upload, ulangi proses upload!');
|
||||
} else {
|
||||
Alert.alert('Bukti Foto berhasil di upload');
|
||||
dispatch(setStep(1));
|
||||
}
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<View style={styles.page}>
|
||||
{photos.length < 1 && (
|
||||
<PZText style={styles.instructionText}>
|
||||
Pilih atau ambil foto dokumen C1 disini
|
||||
</PZText>
|
||||
)}
|
||||
<PZText style={styles.helperText}>
|
||||
Format foto harus berbentuk JPG/JPEG untuk diunggah
|
||||
</PZText>
|
||||
{photos.length > 0 &&
|
||||
photos.map((d, i) => (
|
||||
<PhotoList
|
||||
key={i + '' + d.fileName}
|
||||
photo={d}
|
||||
onRemove={() => {
|
||||
handleRemovePhoto(i);
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
{photos.length < 1 && (
|
||||
<>
|
||||
<Button
|
||||
color="#7367F0"
|
||||
onPress={() => handleTakePhoto()}
|
||||
title={`Foto Langsung Dokumen C1 (${photos.length}/1)`}
|
||||
/>
|
||||
<PZText style={styles.helperText}>atau</PZText>
|
||||
<Button
|
||||
color="#7367F0"
|
||||
style={{ color: 'black' }}
|
||||
onPress={() => handleChoosePhoto()}
|
||||
title={`Pilih Foto Dokumen C1 (${photos.length}/1)`}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
<View style={{ marginTop: 100 }}></View>
|
||||
<Button
|
||||
color="#7367F0"
|
||||
onPress={() => handleUpload()}
|
||||
title={`Unggah Dokumen`}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
page: {
|
||||
alignItems: 'center',
|
||||
width: '100%',
|
||||
},
|
||||
instructionText: {
|
||||
textAlign: 'center',
|
||||
fontSize: 18,
|
||||
fontFamily: 'Public Sans',
|
||||
fontWeight: '600',
|
||||
marginBottom: 12,
|
||||
},
|
||||
helperText: {
|
||||
marginVertical: 12,
|
||||
textAlign: 'center',
|
||||
fontSize: 13,
|
||||
fontFamily: 'Public Sans',
|
||||
fontWeight: '400',
|
||||
},
|
||||
uploadButton: {
|
||||
marginTop: 60,
|
||||
},
|
||||
fixedRatio: {
|
||||
flex: 1,
|
||||
height: '100%',
|
||||
},
|
||||
});
|
||||
|
||||
export default DocumentUpload;
|
||||
18
src/screens/Help/index.tsx
Normal file
@ -0,0 +1,18 @@
|
||||
import React from 'react';
|
||||
import {View} from 'react-native';
|
||||
import PZText from '../../components/PZText';
|
||||
|
||||
const Help = ({navigation}: any) => {
|
||||
return (
|
||||
<View
|
||||
style={{
|
||||
flex: 1,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
}}>
|
||||
<PZText>Help</PZText>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export default Help;
|
||||
86
src/screens/Home/index.tsx
Normal file
@ -0,0 +1,86 @@
|
||||
import React from 'react';
|
||||
import { ScrollView, StyleSheet, View } from 'react-native';
|
||||
import Stepper from '../../components/Stepper';
|
||||
import { StepIndicatorStyles } from '../../types/stepper';
|
||||
import DocumentUpload from '../DocumentUpload';
|
||||
import DocumentInput from '../DocumentInput';
|
||||
import { useAppDispatch, useAppSelector } from '../../store';
|
||||
|
||||
const labels = [
|
||||
'Unggah Suara',
|
||||
'Detail Perhitungan Suara',
|
||||
'Sukses Unggah Suara',
|
||||
];
|
||||
const customStyles: StepIndicatorStyles = {
|
||||
stepIndicatorSize: 25,
|
||||
currentStepIndicatorSize: 30,
|
||||
separatorStrokeWidth: 2,
|
||||
currentStepStrokeWidth: 2,
|
||||
stepStrokeCurrentColor: '#4ba75e',
|
||||
stepStrokeWidth: 3,
|
||||
stepStrokeFinishedColor: '#4ba75e',
|
||||
stepStrokeUnFinishedColor: '#aaaaaa',
|
||||
separatorFinishedColor: '#4ba75e',
|
||||
separatorUnFinishedColor: '#aaaaaa',
|
||||
stepIndicatorFinishedColor: '#4ba75e',
|
||||
stepIndicatorUnFinishedColor: '#ffffff',
|
||||
stepIndicatorCurrentColor: '#ffffff',
|
||||
stepIndicatorLabelFontSize: 14,
|
||||
currentStepIndicatorLabelFontSize: 14,
|
||||
stepIndicatorLabelCurrentColor: '#4ba75e',
|
||||
stepIndicatorLabelFinishedColor: '#ffffff',
|
||||
stepIndicatorLabelUnFinishedColor: '#000000',
|
||||
labelColor: '#999999',
|
||||
labelSize: 16,
|
||||
currentStepLabelColor: '#4ba75e',
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
homeView: {
|
||||
flex: 1,
|
||||
paddingHorizontal: 10,
|
||||
paddingVertical: 20,
|
||||
},
|
||||
stepsView: {
|
||||
paddingHorizontal: 20,
|
||||
paddingVertical: 10,
|
||||
backgroundColor: '#FFFFFF',
|
||||
height: '85%',
|
||||
shadowColor: '#171717',
|
||||
shadowOffset: { width: -2, height: 4 },
|
||||
shadowOpacity: 0.2,
|
||||
shadowRadius: 3,
|
||||
},
|
||||
});
|
||||
|
||||
const Steps = ({ step = 0 }: { step: number }) => {
|
||||
switch (step) {
|
||||
case 0:
|
||||
return <DocumentUpload />;
|
||||
case 1:
|
||||
return <DocumentInput />;
|
||||
case 2:
|
||||
return <DocumentInput finished />;
|
||||
}
|
||||
};
|
||||
|
||||
const Home = ({ navigation }: any) => {
|
||||
const { step } = useAppSelector(state => state.home ?? {});
|
||||
return (
|
||||
<View style={styles.homeView}>
|
||||
<Stepper
|
||||
customStyles={customStyles}
|
||||
currentPosition={step}
|
||||
stepCount={3}
|
||||
labels={labels}
|
||||
/>
|
||||
<View style={styles.stepsView}>
|
||||
<ScrollView>
|
||||
<Steps step={step} />
|
||||
</ScrollView>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export default Home;
|
||||
245
src/screens/Login/index.tsx
Normal file
@ -0,0 +1,245 @@
|
||||
import React, { useState } from 'react';
|
||||
import { View, StyleSheet, TextInput, Button, TouchableOpacity } from 'react-native';
|
||||
import PZText from '../../components/PZText';
|
||||
import awaitToError from '../../common/await-to-error';
|
||||
import { blockchainRequest } from '../../services/request/blockchain';
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
import { authRequest } from '../../services/request/auth';
|
||||
import { BC_AUTH_URL } from '../../config/blockchain';
|
||||
import { Icons } from '../../components/Icon/Icon';
|
||||
|
||||
const Login = ({ navigation }: any) => {
|
||||
const [username, setUsername] = useState('');
|
||||
const [password, setPassword] = useState('');
|
||||
const [errMessage, setErrMessage] = useState('');
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [visiblePassword, setVisiblePassword] = useState(false);
|
||||
|
||||
const checkField = (username, password) => {
|
||||
if (!username || !password) {
|
||||
setErrMessage('Silahkan isi data yang kosong! yaa');
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
const loginProcess = async (body: any) => {
|
||||
let errStorage = null;
|
||||
if (!checkField(username, password)) return;
|
||||
setLoading(true);
|
||||
|
||||
const [errAuth, auth] = await awaitToError(
|
||||
authRequest().post('/users/auth/login', body),
|
||||
);
|
||||
[errStorage] = await awaitToError(
|
||||
AsyncStorage.setItem('username', body.username),
|
||||
);
|
||||
if (errStorage) {
|
||||
console.log('errStorage', errStorage);
|
||||
}
|
||||
|
||||
console.log(errAuth);
|
||||
if (errAuth && errAuth.code === 'ERR_BAD_REQUEST') {
|
||||
setErrMessage('Username/password salah! ');
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
const [err, data] = await awaitToError(
|
||||
blockchainRequest({ baseURL: BC_AUTH_URL }).post('/users/login', {
|
||||
...body,
|
||||
orgName: 'Kpu',
|
||||
}),
|
||||
);
|
||||
|
||||
if (err) {
|
||||
console.log('Login Error: ', err.response);
|
||||
setErrMessage('Terjadi Kesalahan, Silakan Coba Lagi');
|
||||
} else if (data?.data.succes === false) {
|
||||
setErrMessage(data.data.message);
|
||||
} else {
|
||||
[errStorage] = await awaitToError(
|
||||
AsyncStorage.setItem('token', data?.data.message.token),
|
||||
);
|
||||
if (errStorage) {
|
||||
console.log('errStorage', errStorage);
|
||||
return;
|
||||
}
|
||||
|
||||
setLoading(false);
|
||||
navigation.navigate('Main');
|
||||
}
|
||||
};
|
||||
|
||||
const toggleChangeIcon = () => {
|
||||
setVisiblePassword(!visiblePassword)
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<View style={styles.card}>
|
||||
<View style={styles.heading}>
|
||||
<PZText style={styles.title}>Welcome to e-Voting</PZText>
|
||||
<PZText style={styles.titleDescription}>
|
||||
please sign-in to your account and start your adventure
|
||||
</PZText>
|
||||
</View>
|
||||
<View style={styles.badge}>
|
||||
<View
|
||||
style={{
|
||||
...styles.badgeBackground,
|
||||
backgroundColor: errMessage ? 'red' : '#7367F0',
|
||||
}}></View>
|
||||
<View style={styles.badgeDescription}>
|
||||
<PZText style={{ color: errMessage ? 'red' : '#7367F0' }}>
|
||||
{errMessage
|
||||
? errMessage
|
||||
: 'Masukkan email dan password yang sudah diberikan petugas sebelumnya'}
|
||||
</PZText>
|
||||
</View>
|
||||
</View>
|
||||
<View style={styles.formContainer}>
|
||||
<View>
|
||||
<PZText>Username</PZText>
|
||||
<TextInput
|
||||
multiline={false}
|
||||
style={styles.textInput}
|
||||
placeholder="Masukkan username yang terdaftar"
|
||||
onChangeText={newText => setUsername(newText)}
|
||||
defaultValue={username}
|
||||
/>
|
||||
</View>
|
||||
<View>
|
||||
<PZText>Password</PZText>
|
||||
<View style={{ display: 'flex', position: 'relative'}}>
|
||||
<TextInput
|
||||
multiline={false}
|
||||
style={styles.textInput}
|
||||
placeholder="Masukkan password"
|
||||
onChangeText={newText => setPassword(newText)}
|
||||
defaultValue={password}
|
||||
secureTextEntry={!visiblePassword}
|
||||
/>
|
||||
<TouchableOpacity
|
||||
onPress={() => toggleChangeIcon()}
|
||||
style={styles.passwordIcon}
|
||||
>
|
||||
<Icons
|
||||
name={ visiblePassword ? 'eye' : 'eye-slash'}
|
||||
color='#000'
|
||||
size={15}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
<View style={styles.loginButtonContainer}>
|
||||
<Button
|
||||
disabled={loading}
|
||||
color="#7367F0"
|
||||
onPress={() => loginProcess({ username, password })}
|
||||
title={loading ? 'Memproses' : `Login`}
|
||||
/>
|
||||
<PZText
|
||||
style={{ color: '#7367F0', textAlign: 'center', marginTop: 7 }}
|
||||
onPress={() => navigation.navigate('Register')}>
|
||||
Belum punya akun? Register
|
||||
</PZText>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
card: {
|
||||
backgroundColor: 'white',
|
||||
padding: 16,
|
||||
borderRadius: 8,
|
||||
shadowColor: '#000',
|
||||
shadowOffset: {
|
||||
width: 0,
|
||||
height: 2,
|
||||
},
|
||||
shadowOpacity: 0.2,
|
||||
shadowRadius: 3.84,
|
||||
elevation: 5,
|
||||
width: 320,
|
||||
},
|
||||
title: {
|
||||
alignSelf: 'stretch',
|
||||
textAlign: 'center',
|
||||
fontSize: 22,
|
||||
fontStyle: 'normal',
|
||||
fontWeight: '600',
|
||||
lineHeight: 30,
|
||||
},
|
||||
titleDescription: {
|
||||
textAlign: 'center',
|
||||
fontSize: 13,
|
||||
lineHeight: 14,
|
||||
},
|
||||
heading: {
|
||||
display: 'flex',
|
||||
gap: 4,
|
||||
},
|
||||
badge: {
|
||||
display: 'flex',
|
||||
borderRadius: 6,
|
||||
position: 'relative',
|
||||
marginTop: 20,
|
||||
},
|
||||
badgeBackground: {
|
||||
height: 50,
|
||||
opacity: 0.16,
|
||||
borderRadius: 6,
|
||||
},
|
||||
badgeDescription: {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
padding: 8,
|
||||
},
|
||||
textInput: {
|
||||
height: 40,
|
||||
borderColor: '#DBDADE',
|
||||
borderWidth: 1,
|
||||
borderRadius: 5,
|
||||
paddingHorizontal: 10,
|
||||
color: 'black',
|
||||
},
|
||||
formContainer: {
|
||||
display: 'flex',
|
||||
gap: 15,
|
||||
marginTop: 20,
|
||||
},
|
||||
loginButtonContainer: {
|
||||
display: 'flex',
|
||||
gap: 4,
|
||||
marginTop: 20,
|
||||
},
|
||||
loginButton: {
|
||||
backgroundColor: '#7367F0',
|
||||
borderRadius: 6,
|
||||
height: 50,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
marginTop: 5,
|
||||
},
|
||||
buttonText: {
|
||||
color: 'white',
|
||||
fontSize: 16,
|
||||
},
|
||||
passwordIcon: {
|
||||
position: 'absolute',
|
||||
top: 10,
|
||||
right: 10,
|
||||
}
|
||||
});
|
||||
|
||||
export default Login;
|
||||
67
src/screens/Main/index.tsx
Normal file
@ -0,0 +1,67 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
DrawerContentScrollView,
|
||||
DrawerItem,
|
||||
DrawerItemList,
|
||||
createDrawerNavigator,
|
||||
} from '@react-navigation/drawer';
|
||||
import { CommonActions } from '@react-navigation/native';
|
||||
import Home from '../Home';
|
||||
import Help from '../Help';
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
import awaitToError from '../../common/await-to-error';
|
||||
import { useAppDispatch } from '../../store';
|
||||
import { setPhotos, setSuara } from '../../store/reducers/document';
|
||||
import { Suara } from '../../types/suara';
|
||||
import { setStep } from '../../store/reducers/home';
|
||||
|
||||
const Drawer = createDrawerNavigator();
|
||||
const CustomDrawerContent = (props: any) => {
|
||||
const { navigation } = props;
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const doLogout = async () => {
|
||||
const [errToken] = await awaitToError(AsyncStorage.removeItem('token'));
|
||||
if (errToken) {
|
||||
console.log('errToken', errToken);
|
||||
throw errToken;
|
||||
}
|
||||
const [errUsername] = await awaitToError(
|
||||
AsyncStorage.removeItem('username'),
|
||||
);
|
||||
if (errUsername) {
|
||||
console.log('errUsername', errUsername);
|
||||
throw errUsername;
|
||||
}
|
||||
navigation.dispatch(
|
||||
CommonActions.reset({
|
||||
index: 0,
|
||||
routes: [{ name: 'Login' }],
|
||||
}),
|
||||
);
|
||||
dispatch(setPhotos([]));
|
||||
dispatch(setSuara({} as Suara));
|
||||
dispatch(setStep(0));
|
||||
};
|
||||
|
||||
return (
|
||||
<DrawerContentScrollView {...props}>
|
||||
<DrawerItemList {...props} />
|
||||
<DrawerItem label="Log Out" onPress={() => doLogout()} />
|
||||
</DrawerContentScrollView>
|
||||
);
|
||||
};
|
||||
const passPropsToCustomDrawer = (props: any) => {
|
||||
return <CustomDrawerContent {...props} />;
|
||||
};
|
||||
const Main = () => {
|
||||
return (
|
||||
<Drawer.Navigator
|
||||
drawerContent={(props: any) => passPropsToCustomDrawer(props)}>
|
||||
<Drawer.Screen name="Home" component={Home} />
|
||||
<Drawer.Screen name="Help" component={Help} />
|
||||
</Drawer.Navigator>
|
||||
);
|
||||
};
|
||||
|
||||
export default Main;
|
||||
285
src/screens/Register/index.tsx
Normal file
@ -0,0 +1,285 @@
|
||||
import React, { useState } from 'react';
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
import Toast from 'react-native-simple-toast';
|
||||
import {
|
||||
View,
|
||||
StyleSheet,
|
||||
TextInput,
|
||||
Button,
|
||||
TouchableOpacity,
|
||||
} from 'react-native';
|
||||
import PZText from '../../components/PZText';
|
||||
import awaitToError from '../../common/await-to-error';
|
||||
import { blockchainRequest } from '../../services/request/blockchain';
|
||||
import { authRequest } from '../../services/request/auth';
|
||||
import { BC_AUTH_URL } from '../../config/blockchain';
|
||||
import { Icons } from '../../components/Icon/Icon';
|
||||
|
||||
const Register = ({ navigation }: any) => {
|
||||
const [username, setUsername] = useState('');
|
||||
const [password, setPassword] = useState('');
|
||||
const [confirmPassword, setConfirmPassword] = useState('');
|
||||
const [errMessage, setErrMessage] = useState('');
|
||||
const [visiblePassword, setVisiblePassword] = useState(false);
|
||||
const [visibleConfirmPassword, setVisibleConfirmPassword] = useState(false);
|
||||
|
||||
const checkPassword = (password, confirmPassword) => {
|
||||
if (password !== confirmPassword) {
|
||||
setErrMessage('Konfirmasi password harus sama! yaa');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
const checkField = (username, password, confirmPassword) => {
|
||||
if (!username || !password || !confirmPassword) {
|
||||
setErrMessage('Silahkan isi data yang kosong! yaa');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
const registerProcces = async (body: Register) => {
|
||||
if (!checkField(username, password, confirmPassword)) return;
|
||||
if (!checkPassword(password, confirmPassword)) return;
|
||||
|
||||
const [errAuth] = await awaitToError(
|
||||
authRequest().post('/users/auth/register', body),
|
||||
);
|
||||
|
||||
if (errAuth && errAuth.code === 'ERR_BAD_REQUEST') {
|
||||
setErrMessage(
|
||||
`An identity for the user ${body.username} already exists in the wallet`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const [err, data] = await awaitToError(
|
||||
blockchainRequest({ baseURL: BC_AUTH_URL }).post('/users', {
|
||||
...body,
|
||||
orgName: 'Kpu',
|
||||
}),
|
||||
);
|
||||
|
||||
if (err) {
|
||||
console.log('Register Error', err);
|
||||
setErrMessage(data?.data.message);
|
||||
} else if (data.data.success === false) {
|
||||
setErrMessage(data?.data.message);
|
||||
} else {
|
||||
const [errStorage] = await awaitToError(
|
||||
AsyncStorage.setItem('token', data?.data.token),
|
||||
);
|
||||
if (errStorage) {
|
||||
console.log('errStorage', errStorage);
|
||||
throw errStorage;
|
||||
}
|
||||
|
||||
Toast.showWithGravity(
|
||||
'Akun berhasil dibuat, silahkan login!',
|
||||
Toast.LONG,
|
||||
Toast.TOP,
|
||||
);
|
||||
navigation.navigate('Login');
|
||||
}
|
||||
};
|
||||
|
||||
const toggleChangePasswordIcon = () => {
|
||||
setVisiblePassword(!visiblePassword);
|
||||
};
|
||||
|
||||
const toggleChangeConfirmPasswordIcon = () => {
|
||||
setVisibleConfirmPassword(!visibleConfirmPassword);
|
||||
};
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<View style={styles.card}>
|
||||
<View style={styles.heading}>
|
||||
<PZText style={styles.title}>Welcome to e-Voting</PZText>
|
||||
<PZText style={styles.titleDescription}>
|
||||
Register your account and start your adventure
|
||||
</PZText>
|
||||
</View>
|
||||
<View style={styles.badge}>
|
||||
<View
|
||||
style={{
|
||||
...styles.badgeBackground,
|
||||
backgroundColor: errMessage ? 'red' : '#7367F0',
|
||||
}}></View>
|
||||
<View style={styles.badgeDescription}>
|
||||
<PZText style={{ color: errMessage ? 'red' : '#7367F0' }}>
|
||||
{errMessage
|
||||
? errMessage
|
||||
: 'Masukkan email, password, dan konfirmasi password untuk melakukan registrasi yaa rekan'}
|
||||
</PZText>
|
||||
</View>
|
||||
</View>
|
||||
<View style={styles.formContainer}>
|
||||
<View>
|
||||
<PZText>Username or Email</PZText>
|
||||
<View>
|
||||
<TextInput
|
||||
multiline={false}
|
||||
style={styles.textInput}
|
||||
placeholder="Masukkan username/email"
|
||||
onChangeText={newText => setUsername(newText)}
|
||||
defaultValue={username}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
<View>
|
||||
<PZText>Password</PZText>
|
||||
<View style={{ display: 'flex', position: 'relative' }}>
|
||||
<TextInput
|
||||
multiline={false}
|
||||
style={styles.textInput}
|
||||
placeholder="Masukkan password"
|
||||
onChangeText={newText => setPassword(newText)}
|
||||
defaultValue={password}
|
||||
secureTextEntry={!visiblePassword}
|
||||
/>
|
||||
<TouchableOpacity
|
||||
onPress={() => toggleChangePasswordIcon()}
|
||||
style={styles.passwordIcon}>
|
||||
<Icons
|
||||
name={visiblePassword ? 'eye' : 'eye-slash'}
|
||||
size={15}
|
||||
color="#000"
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
<View>
|
||||
<PZText>Konfirmasi Password</PZText>
|
||||
<View style={{ display: 'flex', position: 'relative' }}>
|
||||
<TextInput
|
||||
multiline={false}
|
||||
style={styles.textInput}
|
||||
placeholder="Masukkan konfirmasi password"
|
||||
onChangeText={newText => setConfirmPassword(newText)}
|
||||
defaultValue={confirmPassword}
|
||||
secureTextEntry={!visibleConfirmPassword}
|
||||
/>
|
||||
<TouchableOpacity
|
||||
onPress={() => toggleChangeConfirmPasswordIcon()}
|
||||
style={styles.passwordIcon}>
|
||||
<Icons
|
||||
name={visibleConfirmPassword ? 'eye' : 'eye-slash'}
|
||||
size={15}
|
||||
color="#000"
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
<View style={styles.loginButtonContainer}>
|
||||
<Button
|
||||
color="#7367F0"
|
||||
onPress={() =>
|
||||
registerProcces({ username, password, confirmPassword })
|
||||
}
|
||||
title="Register"
|
||||
/>
|
||||
<PZText
|
||||
style={{ color: '#7367F0', textAlign: 'center', marginTop: 7 }}
|
||||
onPress={() => navigation.navigate('Login')}>
|
||||
Sudah punya akun? Login
|
||||
</PZText>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
card: {
|
||||
backgroundColor: 'white',
|
||||
padding: 16,
|
||||
borderRadius: 8,
|
||||
shadowColor: '#000',
|
||||
shadowOffset: {
|
||||
width: 0,
|
||||
height: 2,
|
||||
},
|
||||
shadowOpacity: 0.2,
|
||||
shadowRadius: 3.84,
|
||||
elevation: 5,
|
||||
width: 320,
|
||||
},
|
||||
title: {
|
||||
alignSelf: 'stretch',
|
||||
textAlign: 'center',
|
||||
fontSize: 22,
|
||||
fontStyle: 'normal',
|
||||
fontWeight: '600',
|
||||
lineHeight: 30,
|
||||
},
|
||||
titleDescription: {
|
||||
textAlign: 'center',
|
||||
fontSize: 13,
|
||||
lineHeight: 14,
|
||||
},
|
||||
heading: {
|
||||
display: 'flex',
|
||||
gap: 4,
|
||||
},
|
||||
badge: {
|
||||
display: 'flex',
|
||||
borderRadius: 6,
|
||||
position: 'relative',
|
||||
marginTop: 20,
|
||||
},
|
||||
badgeBackground: {
|
||||
height: 60,
|
||||
opacity: 0.16,
|
||||
borderRadius: 6,
|
||||
},
|
||||
badgeDescription: {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
padding: 8,
|
||||
},
|
||||
textInput: {
|
||||
height: 40,
|
||||
borderColor: '#DBDADE',
|
||||
borderWidth: 1,
|
||||
borderRadius: 5,
|
||||
paddingHorizontal: 10,
|
||||
color: 'black',
|
||||
},
|
||||
formContainer: {
|
||||
display: 'flex',
|
||||
gap: 15,
|
||||
marginTop: 20,
|
||||
},
|
||||
loginButtonContainer: {
|
||||
display: 'flex',
|
||||
gap: 4,
|
||||
marginTop: 20,
|
||||
},
|
||||
loginButton: {
|
||||
backgroundColor: '#7367F0',
|
||||
borderRadius: 6,
|
||||
height: 50,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
marginTop: 5,
|
||||
},
|
||||
buttonText: {
|
||||
color: 'white',
|
||||
fontSize: 16,
|
||||
},
|
||||
passwordIcon: {
|
||||
position: 'absolute',
|
||||
top: 10,
|
||||
right: 10,
|
||||
},
|
||||
});
|
||||
|
||||
export default Register;
|
||||
39
src/screens/Splash/index.tsx
Normal file
@ -0,0 +1,39 @@
|
||||
import React, {useEffect} from 'react';
|
||||
import {ActivityIndicator, StyleSheet, View} from 'react-native';
|
||||
import PZText from '../../components/PZText';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
main: {
|
||||
flex: 1,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
backgroundColor: '#ffffff',
|
||||
},
|
||||
splashTitle: {
|
||||
fontSize: 36,
|
||||
marginTop: 200,
|
||||
marginBottom: 50,
|
||||
textAlign: 'center',
|
||||
},
|
||||
loadingText: {
|
||||
marginTop: 70,
|
||||
fontSize: 28,
|
||||
},
|
||||
});
|
||||
|
||||
const Home = ({navigation}: any) => {
|
||||
useEffect(() => {
|
||||
setTimeout(function () {
|
||||
navigation.navigate('Login');
|
||||
}, 3000);
|
||||
}, []);
|
||||
return (
|
||||
<View style={styles.main}>
|
||||
<PZText style={styles.splashTitle}>Blockchain Recapitulation</PZText>
|
||||
<ActivityIndicator size="large" />
|
||||
<PZText style={styles.loadingText}>Loading...</PZText>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export default Home;
|
||||
4
src/services/general.ts
Normal file
@ -0,0 +1,4 @@
|
||||
import { useState } from 'react';
|
||||
|
||||
export const useLoading = (initial = false) => useState(initial);
|
||||
export const useError = (initial = '') => useState(initial);
|
||||
8
src/services/request/auth.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import { request } from './request';
|
||||
import { AUTH_URL } from '../../config/auth';
|
||||
|
||||
export const authRequest = () => {
|
||||
return request({
|
||||
baseURL: AUTH_URL,
|
||||
});
|
||||
};
|
||||
10
src/services/request/blockchain.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import { request } from './request';
|
||||
import { BC_URL } from '../../config/blockchain';
|
||||
import { AxiosRequestConfig } from 'axios';
|
||||
|
||||
export const blockchainRequest = (conf?: AxiosRequestConfig) => {
|
||||
return request({
|
||||
...conf,
|
||||
baseURL: conf?.baseURL ?? BC_URL,
|
||||
});
|
||||
};
|
||||
8
src/services/request/core.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import { request } from './request';
|
||||
import { CORE_URL } from '../../config/core';
|
||||
|
||||
export const coreRequest = () => {
|
||||
return request({
|
||||
baseURL: CORE_URL,
|
||||
});
|
||||
};
|
||||
8
src/services/request/demo.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import { request } from './request';
|
||||
import { DEMO_URL } from '../../config/demo';
|
||||
|
||||
export const demoRequest = () => {
|
||||
return request({
|
||||
baseURL: DEMO_URL,
|
||||
});
|
||||
};
|
||||
54
src/services/request/request.ts
Normal file
@ -0,0 +1,54 @@
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
import axios, { AxiosRequestConfig } from 'axios';
|
||||
import {
|
||||
ES_BASIC_AUTH,
|
||||
ES_HOST,
|
||||
ES_MONITORING_INDEX,
|
||||
} from '../../config/elasticsearch';
|
||||
import { randString } from '../../common/random';
|
||||
|
||||
const requestDetail = async () => {
|
||||
const timestamp = new Date();
|
||||
const username = await AsyncStorage.getItem('username');
|
||||
return {
|
||||
['@timestamp']: timestamp,
|
||||
username,
|
||||
};
|
||||
};
|
||||
|
||||
const recordToEs = (index: string, data: any) => {
|
||||
return axios
|
||||
.post(
|
||||
`${ES_HOST}/${ES_MONITORING_INDEX}-${index}/_create/${randString(64)}`,
|
||||
data,
|
||||
{
|
||||
headers: {
|
||||
Authorization: ES_BASIC_AUTH,
|
||||
},
|
||||
},
|
||||
)
|
||||
.catch(() => null);
|
||||
};
|
||||
|
||||
export const request = (conf: AxiosRequestConfig = {}) => {
|
||||
const x = axios.create({ ...conf });
|
||||
x.interceptors.request.use(async req => {
|
||||
const reqDetail = await requestDetail();
|
||||
await recordToEs('request', {
|
||||
type: 'req',
|
||||
detail: req,
|
||||
...reqDetail,
|
||||
});
|
||||
return req;
|
||||
});
|
||||
x.interceptors.response.use(async res => {
|
||||
const reqDetail = await requestDetail();
|
||||
await recordToEs('response', {
|
||||
type: 'res',
|
||||
detail: res,
|
||||
...reqDetail,
|
||||
});
|
||||
return res;
|
||||
});
|
||||
return x;
|
||||
};
|
||||
85
src/services/suara.ts
Normal file
@ -0,0 +1,85 @@
|
||||
import { useError, useLoading } from './general';
|
||||
import { Suara } from '../types/suara';
|
||||
import awaitToError from '../common/await-to-error';
|
||||
import { blockchainRequest } from './request/blockchain';
|
||||
import { C1Document } from '../types/upload';
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
import { demoRequest } from './request/demo';
|
||||
|
||||
export const useSubmitSuara = () => {
|
||||
const [loading, setLoading] = useLoading();
|
||||
const [error, setError] = useError();
|
||||
const submit = async (suara: Suara, photos: C1Document[]) => {
|
||||
const token = await AsyncStorage.getItem('token');
|
||||
setError('');
|
||||
setLoading(true);
|
||||
const JmlSuratDiterima = parseInt(suara.diterima, 10);
|
||||
const JmlSuratDikembalikan = parseInt(suara.dikembalikan, 10);
|
||||
const JmlSuratTidakDigunakan = parseInt(suara.tidakDigunakan, 10);
|
||||
const JmlSuratDigunakan =
|
||||
JmlSuratDiterima - JmlSuratDikembalikan - JmlSuratTidakDigunakan;
|
||||
const JmlSuaraSahCalonA = parseInt(suara.pasangan01, 10);
|
||||
const JmlSuaraSahCalonB = parseInt(suara.pasangan02, 10);
|
||||
const JmlSuaraTidakSah = parseInt(suara.tidakSah, 10);
|
||||
const JmlSuaraSahSeluruhCalon = JmlSuaraSahCalonA + JmlSuaraSahCalonB;
|
||||
const JmlSuaraSahTidakSah = JmlSuaraSahSeluruhCalon + JmlSuaraTidakSah;
|
||||
const c1Img = `https://assets.staging.productzillaacademy.com/kpu/blockchain/dokumen-c1/${photos[0].hashedName}.jpg`;
|
||||
const bcData = {
|
||||
ID: suara.tps,
|
||||
DataHash1: c1Img,
|
||||
DataHash2: '',
|
||||
JmlSuratDiterima,
|
||||
JmlSuratDikembalikan,
|
||||
JmlSuratTidakDigunakan,
|
||||
JmlSuratDigunakan,
|
||||
JmlSuaraSahCalonA,
|
||||
JmlSuaraSahCalonB,
|
||||
JmlSuaraTidakSah,
|
||||
JmlSuaraSahSeluruhCalon,
|
||||
JmlSuaraSahTidakSah,
|
||||
};
|
||||
console.log('photo name', photos[0].hashedName);
|
||||
|
||||
let [err, response] = [null, null];
|
||||
[err, response] = await awaitToError(
|
||||
blockchainRequest({
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
}).post('/channels/koja/chaincodes/voting-tps', {
|
||||
fcn: 'createData',
|
||||
channelDestination: 'jatinegara',
|
||||
args: [JSON.stringify(bcData)],
|
||||
}),
|
||||
);
|
||||
console.log('err 1', err);
|
||||
[err, response] = await awaitToError(
|
||||
demoRequest().put('/petugas/tps/suara', {
|
||||
suara_diterima: JmlSuratDiterima,
|
||||
suara_dikembalikan: JmlSuratDikembalikan,
|
||||
suara_tidak_digunakan: JmlSuratTidakDigunakan,
|
||||
suara_digunakan: JmlSuratDigunakan,
|
||||
suara_tidak_sah: JmlSuaraTidakSah,
|
||||
suara_sah: JmlSuaraSahSeluruhCalon,
|
||||
suara_nomor_urut_1: JmlSuaraSahCalonA,
|
||||
suara_nomor_urut_2: JmlSuaraSahCalonB,
|
||||
image: c1Img,
|
||||
}),
|
||||
);
|
||||
console.log('err 2', err);
|
||||
|
||||
setLoading(false);
|
||||
if (err) {
|
||||
setError('Terjadi Kesalahan Input Data. Silakan Coba Kembali.');
|
||||
throw err;
|
||||
}
|
||||
return response;
|
||||
};
|
||||
return {
|
||||
loading,
|
||||
setLoading,
|
||||
submit,
|
||||
error,
|
||||
setError,
|
||||
};
|
||||
};
|
||||
6
src/store/hooks.ts
Normal file
@ -0,0 +1,6 @@
|
||||
import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux';
|
||||
import { AppDispatch, RootState } from './redux';
|
||||
|
||||
// Use throughout your app instead of plain `useDispatch` and `useSelector`
|
||||
export const useAppDispatch = () => useDispatch<AppDispatch>();
|
||||
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
|
||||
2
src/store/index.ts
Normal file
@ -0,0 +1,2 @@
|
||||
export { store as default } from './redux';
|
||||
export * from './hooks';
|
||||
31
src/store/reducers/document.ts
Normal file
@ -0,0 +1,31 @@
|
||||
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
|
||||
import { C1Document } from '../../types/upload';
|
||||
import { Suara } from '../../types/suara';
|
||||
|
||||
const homeSlice = createSlice({
|
||||
name: 'document',
|
||||
initialState: {
|
||||
photos: [] as C1Document[],
|
||||
suara: {} as Suara,
|
||||
},
|
||||
reducers: {
|
||||
setPhotos(state, action: PayloadAction<C1Document[]>) {
|
||||
state.photos = action.payload;
|
||||
},
|
||||
addPhotos(state, action: PayloadAction<C1Document>) {
|
||||
state.photos = [...state.photos, action.payload];
|
||||
},
|
||||
removePhoto(state, action: PayloadAction<number>) {
|
||||
const p = [...state.photos];
|
||||
p.splice(action.payload, 1);
|
||||
state.photos = p;
|
||||
},
|
||||
setSuara(state, action: PayloadAction<Suara>) {
|
||||
state.suara = action.payload;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const { setPhotos, addPhotos, removePhoto, setSuara } =
|
||||
homeSlice.actions;
|
||||
export default homeSlice.reducer;
|
||||
16
src/store/reducers/home.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
|
||||
|
||||
const homeSlice = createSlice({
|
||||
name: 'home',
|
||||
initialState: {
|
||||
step: 0,
|
||||
},
|
||||
reducers: {
|
||||
setStep(state, action: PayloadAction<number>) {
|
||||
state.step = action.payload;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const { setStep } = homeSlice.actions;
|
||||
export default homeSlice.reducer;
|
||||
12
src/store/redux.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { configureStore } from '@reduxjs/toolkit';
|
||||
import homeReducer from './reducers/home';
|
||||
import documentReducer from './reducers/document';
|
||||
|
||||
export const store = configureStore({
|
||||
reducer: { home: homeReducer, document: documentReducer },
|
||||
});
|
||||
|
||||
export type AppDispatch = typeof store.dispatch;
|
||||
export type RootState = ReturnType<typeof store.getState>;
|
||||
|
||||
export default store;
|
||||
9
src/styles/main.tsx
Normal file
@ -0,0 +1,9 @@
|
||||
import { StyleSheet } from 'react-native';
|
||||
import colors from '../res/colors';
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
globalText: {
|
||||
color: colors.black,
|
||||
},
|
||||
});
|
||||
export default styles;
|
||||
5
src/types/register.ts
Normal file
@ -0,0 +1,5 @@
|
||||
interface Register {
|
||||
username: string,
|
||||
password: string,
|
||||
confirmPassword: string,
|
||||
}
|
||||
329
src/types/stepper.ts
Normal file
@ -0,0 +1,329 @@
|
||||
// Type definitions for react-native-step-indicator
|
||||
// Project: https://github.com/24ark/react-native-step-indicator
|
||||
// Definitions by: Kyle Roach <https://github.com/iRoachie>
|
||||
// TypeScript Version: 2.3.3
|
||||
|
||||
import React from 'react';
|
||||
|
||||
export interface StepIndicatorStyles {
|
||||
/**
|
||||
* Size of step indicator circle
|
||||
*
|
||||
* @default 30
|
||||
* @type {number}
|
||||
* @memberof StepIndicatorStyles
|
||||
*/
|
||||
stepIndicatorSize?: number;
|
||||
|
||||
/**
|
||||
* Size of the current step indicator circle
|
||||
*
|
||||
* @default 40
|
||||
* @type {number}
|
||||
* @memberof StepIndicatorStyles
|
||||
*/
|
||||
currentStepIndicatorSize?: number;
|
||||
|
||||
/**
|
||||
* Stroke thickness of the separator between steps
|
||||
*
|
||||
* @default 2
|
||||
* @type {number}
|
||||
* @memberof StepIndicatorStyles
|
||||
*/
|
||||
separatorStrokeWidth?: number;
|
||||
|
||||
/**
|
||||
* Stroke thickness of the separator between unifinished steps
|
||||
*
|
||||
* @default 0
|
||||
* @type {number}
|
||||
* @memberof StepIndicatorStyles
|
||||
*/
|
||||
separatorStrokeUnfinishedWidth?: number;
|
||||
|
||||
/**
|
||||
* Stroke thickness of the separator between finished steps
|
||||
*
|
||||
* @default 0
|
||||
* @type {number}
|
||||
* @memberof StepIndicatorStyles
|
||||
*/
|
||||
separatorStrokeFinishedWidth?: number;
|
||||
|
||||
/**
|
||||
* Thickness of the stroke around each step
|
||||
*
|
||||
* @default 3
|
||||
* @type {number}
|
||||
* @memberof StepIndicatorStyles
|
||||
*/
|
||||
stepStrokeWidth?: number;
|
||||
|
||||
/**
|
||||
* Thickness of the stroke around the current step
|
||||
*
|
||||
* @default 3
|
||||
* @type {number}
|
||||
* @memberof StepIndicatorStyles
|
||||
*/
|
||||
currentStepStrokeWidth?: number;
|
||||
|
||||
/**
|
||||
* Stroke color for the current step
|
||||
*
|
||||
* @default '#fe7013'
|
||||
* @type {string}
|
||||
* @memberof StepIndicatorStyles
|
||||
*/
|
||||
stepStrokeCurrentColor?: string;
|
||||
|
||||
/**
|
||||
* Stroke color for finished steps
|
||||
*
|
||||
* @default '#fe7013'
|
||||
* @type {string}
|
||||
* @memberof StepIndicatorStyles
|
||||
*/
|
||||
stepStrokeFinishedColor?: string;
|
||||
|
||||
/**
|
||||
* Stroke color for unfinished steps
|
||||
*
|
||||
* @default '#aaaaaa'
|
||||
* @type {string}
|
||||
* @memberof StepIndicatorStyles
|
||||
*/
|
||||
stepStrokeUnFinishedColor?: string;
|
||||
|
||||
/**
|
||||
* Color of separator for finished items
|
||||
*
|
||||
* @default '#fe7013'
|
||||
* @type {string}
|
||||
* @memberof StepIndicatorStyles
|
||||
*/
|
||||
separatorFinishedColor?: string;
|
||||
|
||||
/**
|
||||
* Color of separator for unfinished items
|
||||
*
|
||||
* @default '#aaaaaa'
|
||||
* @type {string}
|
||||
* @memberof StepIndicatorStyles
|
||||
*/
|
||||
separatorUnFinishedColor?: string;
|
||||
|
||||
/**
|
||||
* Color of the circle for finished steps
|
||||
*
|
||||
* @default '#fe7013'
|
||||
* @type {string}
|
||||
* @memberof StepIndicatorStyles
|
||||
*/
|
||||
stepIndicatorFinishedColor?: string;
|
||||
|
||||
/**
|
||||
* Color of the circle for unfinished steps
|
||||
*
|
||||
* @default '#ffffff'
|
||||
* @type {string}
|
||||
* @memberof StepIndicatorStyles
|
||||
*/
|
||||
stepIndicatorUnFinishedColor?: string;
|
||||
|
||||
/**
|
||||
* Color of the circle for the current step
|
||||
*
|
||||
* @default '#ffffff'
|
||||
* @type {string}
|
||||
* @memberof StepIndicatorStyles
|
||||
*/
|
||||
stepIndicatorCurrentColor?: string;
|
||||
|
||||
/**
|
||||
* Font size of the number inside the circle for each step
|
||||
*
|
||||
* @default 15
|
||||
* @type {number}
|
||||
* @memberof StepIndicatorStyles
|
||||
*/
|
||||
stepIndicatorLabelFontSize?: number;
|
||||
|
||||
/**
|
||||
* Font size of the number inside the circle for the current step
|
||||
*
|
||||
* @default 15
|
||||
* @type {number}
|
||||
* @memberof StepIndicatorStyles
|
||||
*/
|
||||
currentStepIndicatorLabelFontSize?: number;
|
||||
|
||||
/**
|
||||
* Color of label for the current step
|
||||
*
|
||||
* @default '#ffffff'
|
||||
* @type {string}
|
||||
* @memberof StepIndicatorStyles
|
||||
*/
|
||||
stepIndicatorLabelCurrentColor?: string;
|
||||
|
||||
/**
|
||||
* Color of labels that their steps are finished
|
||||
*
|
||||
* @default '#ffffff'
|
||||
* @type {string}
|
||||
* @memberof StepIndicatorStyles
|
||||
*/
|
||||
stepIndicatorLabelFinishedColor?: string;
|
||||
|
||||
/**
|
||||
* Color of labels that their steps are unfinished
|
||||
*
|
||||
* @default 'rgba(255,255,255,0.5)'
|
||||
* @type {string}
|
||||
* @memberof StepIndicatorStyles
|
||||
*/
|
||||
stepIndicatorLabelUnFinishedColor?: string;
|
||||
|
||||
/**
|
||||
* Color of the label text
|
||||
*
|
||||
* @default '#000000'
|
||||
* @type {string}
|
||||
* @memberof StepIndicatorStyles
|
||||
*/
|
||||
labelColor?: string;
|
||||
|
||||
/**
|
||||
* Color of the current step label
|
||||
*
|
||||
* @default '#4aae4f'
|
||||
* @type {string}
|
||||
* @memberof StepIndicatorStyles
|
||||
*/
|
||||
currentStepLabelColor?: string;
|
||||
|
||||
/**
|
||||
* Font size for the labels
|
||||
*
|
||||
* @default 13
|
||||
* @type {number}
|
||||
* @memberof StepIndicatorStyles
|
||||
*/
|
||||
labelSize?: number;
|
||||
|
||||
/**
|
||||
* Label alignment
|
||||
*
|
||||
* @default 'center'
|
||||
* @type {"center" | "flex-start" | "flex-end" | "stretch" | "baseline" | undefined}
|
||||
* @memberof StepIndicatorStyles
|
||||
*
|
||||
*/
|
||||
labelAlign?:
|
||||
| 'center'
|
||||
| 'flex-start'
|
||||
| 'flex-end'
|
||||
| 'stretch'
|
||||
| 'baseline'
|
||||
| undefined;
|
||||
|
||||
/**
|
||||
* Label fontFamily for custom fonts
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof StepIndicatorStyles
|
||||
*
|
||||
*/
|
||||
labelFontFamily?: string;
|
||||
}
|
||||
|
||||
export interface StepIndicatorProps {
|
||||
/**
|
||||
* Current step
|
||||
*
|
||||
* @default 0
|
||||
* @type {number}
|
||||
* @memberof StepIndicatorProps
|
||||
*/
|
||||
currentPosition?: number;
|
||||
|
||||
/**
|
||||
* Number of steps
|
||||
*
|
||||
* @default 5
|
||||
* @type {number}
|
||||
* @memberof StepIndicatorProps
|
||||
*/
|
||||
stepCount?: number;
|
||||
|
||||
/**
|
||||
* Orientation of the Steps
|
||||
*
|
||||
* @default 'horizontal'
|
||||
* @type {('horizontal' | 'vertical')}
|
||||
* @memberof StepIndicatorProps
|
||||
*/
|
||||
direction?: 'horizontal' | 'vertical';
|
||||
|
||||
/**
|
||||
* Styles for the component
|
||||
*
|
||||
* @type {StepIndicatorStyles}
|
||||
* @memberof StepIndicatorProps
|
||||
*/
|
||||
customStyles?: StepIndicatorStyles;
|
||||
|
||||
/**
|
||||
* Labels for each step
|
||||
*
|
||||
* @type {string[]}
|
||||
* @memberof StepIndicatorProps
|
||||
*/
|
||||
labels?: string[];
|
||||
|
||||
/**
|
||||
* Callback fired when tapping on a step
|
||||
*
|
||||
* @param {number} step
|
||||
*
|
||||
* @memberof StepIndicatorProps
|
||||
*/
|
||||
onPress?(step: number): void;
|
||||
|
||||
/**
|
||||
* Used to render custom content inside step at specified position
|
||||
*
|
||||
* @param {number} position
|
||||
* @param {string} stepStatus
|
||||
*
|
||||
* @memberof StepIndicatorProps
|
||||
*/
|
||||
renderStepIndicator?(args: {
|
||||
position: number;
|
||||
stepStatus: string;
|
||||
}): React.ReactNode;
|
||||
|
||||
/**
|
||||
* Use this to render custom label for each step
|
||||
*
|
||||
* @param {number} position
|
||||
* @param {string} stepStatus
|
||||
* @param {string} label
|
||||
* @param {number} currentPosition
|
||||
*
|
||||
* @memberof StepIndicatorProps
|
||||
*/
|
||||
renderLabel?(args: {
|
||||
position: number;
|
||||
stepStatus: string;
|
||||
label: string;
|
||||
currentPosition: number;
|
||||
}): React.ReactNode;
|
||||
}
|
||||
|
||||
export default class StepIndicator extends React.Component<
|
||||
StepIndicatorProps,
|
||||
{}
|
||||
> {}
|
||||