crpt
This commit is contained in:
		@@ -87,7 +87,7 @@ android {
 | 
				
			|||||||
        minSdkVersion rootProject.ext.minSdkVersion
 | 
					        minSdkVersion rootProject.ext.minSdkVersion
 | 
				
			||||||
        targetSdkVersion rootProject.ext.targetSdkVersion
 | 
					        targetSdkVersion rootProject.ext.targetSdkVersion
 | 
				
			||||||
        versionCode 1
 | 
					        versionCode 1
 | 
				
			||||||
        versionName "1.1.7"
 | 
					        versionName "1.3.4"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        buildConfigField("boolean", "REACT_NATIVE_UNSTABLE_USE_RUNTIME_SCHEDULER_ALWAYS", (findProperty("reactNative.unstable_useRuntimeSchedulerAlways") ?: true).toString())
 | 
					        buildConfigField("boolean", "REACT_NATIVE_UNSTABLE_USE_RUNTIME_SCHEDULER_ALWAYS", (findProperty("reactNative.unstable_useRuntimeSchedulerAlways") ?: true).toString())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -168,6 +168,7 @@ dependencies {
 | 
				
			|||||||
        exclude group:'com.squareup.okhttp3', module:'okhttp'
 | 
					        exclude group:'com.squareup.okhttp3', module:'okhttp'
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}")
 | 
					    debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}")
 | 
				
			||||||
 | 
					    implementation(files("libs/printer-lib-2.2.4.aar"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (hermesEnabled.toBoolean()) {
 | 
					    if (hermesEnabled.toBoolean()) {
 | 
				
			||||||
        implementation("com.facebook.react:hermes-android")
 | 
					        implementation("com.facebook.react:hermes-android")
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,8 @@
 | 
				
			|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
 | 
					<manifest xmlns:android="http://schemas.android.com/apk/res/android">
 | 
				
			||||||
  <uses-permission android:name="android.permission.INTERNET"/>
 | 
					  <uses-permission android:name="android.permission.INTERNET"/>
 | 
				
			||||||
 | 
					  <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
 | 
				
			||||||
  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
 | 
					  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
 | 
				
			||||||
 | 
					  <uses-permission android:name="android.permission.RECORD_AUDIO"/>
 | 
				
			||||||
  <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
 | 
					  <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
 | 
				
			||||||
  <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
 | 
					  <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
 | 
				
			||||||
  <uses-permission android:name="android.permission.VIBRATE"/>
 | 
					  <uses-permission android:name="android.permission.VIBRATE"/>
 | 
				
			||||||
@@ -27,6 +29,7 @@
 | 
				
			|||||||
        <category android:name="android.intent.category.DEFAULT"/>
 | 
					        <category android:name="android.intent.category.DEFAULT"/>
 | 
				
			||||||
        <category android:name="android.intent.category.BROWSABLE"/>
 | 
					        <category android:name="android.intent.category.BROWSABLE"/>
 | 
				
			||||||
        <data android:scheme="com.anonymous.Assemblr"/>
 | 
					        <data android:scheme="com.anonymous.Assemblr"/>
 | 
				
			||||||
 | 
					        <data android:scheme="exp+assemblr"/>
 | 
				
			||||||
      </intent-filter>
 | 
					      </intent-filter>
 | 
				
			||||||
    </activity>
 | 
					    </activity>
 | 
				
			||||||
    <activity android:name="com.facebook.react.devsupport.DevSettingsActivity" android:exported="false"/>
 | 
					    <activity android:name="com.facebook.react.devsupport.DevSettingsActivity" android:exported="false"/>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,41 @@
 | 
				
			|||||||
 | 
					package com.anonymous.Assemblr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import android.util.Log;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import androidx.annotation.NonNull;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.facebook.react.bridge.ReactApplicationContext;
 | 
				
			||||||
 | 
					import com.facebook.react.bridge.ReactContextBaseJavaModule;
 | 
				
			||||||
 | 
					import com.facebook.react.bridge.ReactMethod;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import net.posprinter.IDeviceConnection;
 | 
				
			||||||
 | 
					import net.posprinter.POSConnect;
 | 
				
			||||||
 | 
					import net.posprinter.TSCPrinter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.HashMap;
 | 
				
			||||||
 | 
					import java.util.Map;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class AwesomeModule extends ReactContextBaseJavaModule {
 | 
				
			||||||
 | 
					    private final ReactApplicationContext context;
 | 
				
			||||||
 | 
					    private final Map<String, IDeviceConnection> printersMap = new HashMap<>();
 | 
				
			||||||
 | 
					    AwesomeModule(ReactApplicationContext context) {
 | 
				
			||||||
 | 
					        super(context);
 | 
				
			||||||
 | 
					        this.context = context;
 | 
				
			||||||
 | 
					        POSConnect.init(this.context);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public void initPrinters(){
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @NonNull
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public String getName() {
 | 
				
			||||||
 | 
					        return "AwesomeModule";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @ReactMethod
 | 
				
			||||||
 | 
					    public void test() {
 | 
				
			||||||
 | 
					        Log.d("AwesomeModule", "AwesomeModule test");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,4 +1,8 @@
 | 
				
			|||||||
package com.anonymous.Assemblr;
 | 
					package com.anonymous.Assemblr;
 | 
				
			||||||
 | 
					// @generated begin react-native-keyevent-import - expo prebuild (DO NOT MODIFY) sync-6d2345dd84c398e4e99d7d44eb792294628c7e34
 | 
				
			||||||
 | 
					import android.view.KeyEvent;
 | 
				
			||||||
 | 
					import com.github.kevinejohn.keyevent.KeyEventModule;
 | 
				
			||||||
 | 
					// @generated end react-native-keyevent-import
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import android.os.Build;
 | 
					import android.os.Build;
 | 
				
			||||||
import android.os.Bundle;
 | 
					import android.os.Bundle;
 | 
				
			||||||
@@ -11,6 +15,49 @@ import com.facebook.react.defaults.DefaultReactActivityDelegate;
 | 
				
			|||||||
import expo.modules.ReactActivityDelegateWrapper;
 | 
					import expo.modules.ReactActivityDelegateWrapper;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class MainActivity extends ReactActivity {
 | 
					public class MainActivity extends ReactActivity {
 | 
				
			||||||
 | 
					// @generated begin react-native-keyevent-body - expo prebuild (DO NOT MODIFY) sync-4ba28f58cc0b4a775aa231e380b7f40e8f34382a
 | 
				
			||||||
 | 
					@Override
 | 
				
			||||||
 | 
					public boolean onKeyDown(int keyCode, KeyEvent event) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // // Uncomment this is key events should only trigger once when key is held down
 | 
				
			||||||
 | 
					  // if (event.getRepeatCount() == 0) {
 | 
				
			||||||
 | 
					  //   KeyEventModule.getInstance().onKeyDownEvent(keyCode, event);
 | 
				
			||||||
 | 
					  // }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // // This will trigger the key repeat if the key is held down
 | 
				
			||||||
 | 
					  // // Comment this out if uncommenting the above
 | 
				
			||||||
 | 
					  KeyEventModule.getInstance().onKeyDownEvent(keyCode, event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // // Uncomment this if you want the default keyboard behavior
 | 
				
			||||||
 | 
					  // return super.onKeyDown(keyCode, event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // // The default keyboard behaviour wll be overridden
 | 
				
			||||||
 | 
					  // // This is similar to what e.preventDefault() does in a browser
 | 
				
			||||||
 | 
					  // // comment this if uncommenting the above
 | 
				
			||||||
 | 
					  super.onKeyDown(keyCode, event);
 | 
				
			||||||
 | 
					  return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Override
 | 
				
			||||||
 | 
					public boolean onKeyUp(int keyCode, KeyEvent event) {
 | 
				
			||||||
 | 
					  KeyEventModule.getInstance().onKeyUpEvent(keyCode, event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // // Uncomment this if you want the default keyboard behavior
 | 
				
			||||||
 | 
					  // return super.onKeyUp(keyCode, event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // // The default keyboard behaviour wll be overridden
 | 
				
			||||||
 | 
					  // // This is similar to what e.preventDefault() does in a browser
 | 
				
			||||||
 | 
					  // // comment this if uncommenting the above
 | 
				
			||||||
 | 
					  super.onKeyUp(keyCode, event);
 | 
				
			||||||
 | 
					  return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Override
 | 
				
			||||||
 | 
					public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
 | 
				
			||||||
 | 
					    KeyEventModule.getInstance().onKeyMultipleEvent(keyCode, repeatCount, event);
 | 
				
			||||||
 | 
					    return super.onKeyMultiple(keyCode, repeatCount, event);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					// @generated end react-native-keyevent-body
 | 
				
			||||||
  @Override
 | 
					  @Override
 | 
				
			||||||
  protected void onCreate(Bundle savedInstanceState) {
 | 
					  protected void onCreate(Bundle savedInstanceState) {
 | 
				
			||||||
    // Set the theme to AppTheme BEFORE onCreate to support 
 | 
					    // Set the theme to AppTheme BEFORE onCreate to support 
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,6 +2,7 @@ package com.anonymous.Assemblr;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import android.app.Application;
 | 
					import android.app.Application;
 | 
				
			||||||
import android.content.res.Configuration;
 | 
					import android.content.res.Configuration;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import androidx.annotation.NonNull;
 | 
					import androidx.annotation.NonNull;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.facebook.react.PackageList;
 | 
					import com.facebook.react.PackageList;
 | 
				
			||||||
@@ -20,61 +21,62 @@ import java.util.List;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
public class MainApplication extends Application implements ReactApplication {
 | 
					public class MainApplication extends Application implements ReactApplication {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private final ReactNativeHost mReactNativeHost =
 | 
					    private final ReactNativeHost mReactNativeHost =
 | 
				
			||||||
    new ReactNativeHostWrapper(this, new DefaultReactNativeHost(this) {
 | 
					            new ReactNativeHostWrapper(this, new DefaultReactNativeHost(this) {
 | 
				
			||||||
      @Override
 | 
					                @Override
 | 
				
			||||||
      public boolean getUseDeveloperSupport() {
 | 
					                public boolean getUseDeveloperSupport() {
 | 
				
			||||||
        return BuildConfig.DEBUG;
 | 
					                    return BuildConfig.DEBUG;
 | 
				
			||||||
      }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      @Override
 | 
					                @Override
 | 
				
			||||||
      protected List<ReactPackage> getPackages() {
 | 
					                protected List<ReactPackage> getPackages() {
 | 
				
			||||||
        @SuppressWarnings("UnnecessaryLocalVariable")
 | 
					                    @SuppressWarnings("UnnecessaryLocalVariable")
 | 
				
			||||||
        List<ReactPackage> packages = new PackageList(this).getPackages();
 | 
					                    List<ReactPackage> packages = new PackageList(this).getPackages();
 | 
				
			||||||
        // Packages that cannot be autolinked yet can be added manually here, for example:
 | 
					                    packages.add(new MyAppPackage());
 | 
				
			||||||
        // packages.add(new MyReactNativePackage());
 | 
					                    // Packages that cannot be autolinked yet can be added manually here, for example:
 | 
				
			||||||
        return packages;
 | 
					                    // packages.add(new MyReactNativePackage());
 | 
				
			||||||
      }
 | 
					                    return packages;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      @Override
 | 
					                @Override
 | 
				
			||||||
      protected String getJSMainModuleName() {
 | 
					                protected String getJSMainModuleName() {
 | 
				
			||||||
        return ".expo/.virtual-metro-entry";
 | 
					                    return ".expo/.virtual-metro-entry";
 | 
				
			||||||
      }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      @Override
 | 
					                @Override
 | 
				
			||||||
      protected boolean isNewArchEnabled() {
 | 
					                protected boolean isNewArchEnabled() {
 | 
				
			||||||
        return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
 | 
					                    return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
 | 
				
			||||||
      }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      @Override
 | 
					                @Override
 | 
				
			||||||
      protected Boolean isHermesEnabled() {
 | 
					                protected Boolean isHermesEnabled() {
 | 
				
			||||||
        return BuildConfig.IS_HERMES_ENABLED;
 | 
					                    return BuildConfig.IS_HERMES_ENABLED;
 | 
				
			||||||
      }
 | 
					                }
 | 
				
			||||||
  });
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @Override
 | 
					    @Override
 | 
				
			||||||
  public ReactNativeHost getReactNativeHost() {
 | 
					    public ReactNativeHost getReactNativeHost() {
 | 
				
			||||||
    return mReactNativeHost;
 | 
					        return mReactNativeHost;
 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  @Override
 | 
					 | 
				
			||||||
  public void onCreate() {
 | 
					 | 
				
			||||||
    super.onCreate();
 | 
					 | 
				
			||||||
    SoLoader.init(this, /* native exopackage */ false);
 | 
					 | 
				
			||||||
    if (!BuildConfig.REACT_NATIVE_UNSTABLE_USE_RUNTIME_SCHEDULER_ALWAYS) {
 | 
					 | 
				
			||||||
      ReactFeatureFlags.unstable_useRuntimeSchedulerAlways = 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());
 | 
					 | 
				
			||||||
    ApplicationLifecycleDispatcher.onApplicationCreate(this);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @Override
 | 
					    @Override
 | 
				
			||||||
  public void onConfigurationChanged(@NonNull Configuration newConfig) {
 | 
					    public void onCreate() {
 | 
				
			||||||
    super.onConfigurationChanged(newConfig);
 | 
					        super.onCreate();
 | 
				
			||||||
    ApplicationLifecycleDispatcher.onConfigurationChanged(this, newConfig);
 | 
					        SoLoader.init(this, /* native exopackage */ false);
 | 
				
			||||||
  }
 | 
					        if (!BuildConfig.REACT_NATIVE_UNSTABLE_USE_RUNTIME_SCHEDULER_ALWAYS) {
 | 
				
			||||||
 | 
					            ReactFeatureFlags.unstable_useRuntimeSchedulerAlways = 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());
 | 
				
			||||||
 | 
					        ApplicationLifecycleDispatcher.onApplicationCreate(this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public void onConfigurationChanged(@NonNull Configuration newConfig) {
 | 
				
			||||||
 | 
					        super.onConfigurationChanged(newConfig);
 | 
				
			||||||
 | 
					        ApplicationLifecycleDispatcher.onConfigurationChanged(this, newConfig);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					package com.anonymous.Assemblr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import androidx.annotation.NonNull;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.facebook.react.ReactPackage;
 | 
				
			||||||
 | 
					import com.facebook.react.bridge.NativeModule;
 | 
				
			||||||
 | 
					import com.facebook.react.bridge.ReactApplicationContext;
 | 
				
			||||||
 | 
					import com.facebook.react.uimanager.ViewManager;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.util.ArrayList;
 | 
				
			||||||
 | 
					import java.util.Collections;
 | 
				
			||||||
 | 
					import java.util.List;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class MyAppPackage implements ReactPackage {
 | 
				
			||||||
 | 
					    @NonNull
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
 | 
				
			||||||
 | 
					        return Collections.emptyList();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public List<NativeModule> createNativeModules(
 | 
				
			||||||
 | 
					            ReactApplicationContext reactContext) {
 | 
				
			||||||
 | 
					        List<NativeModule> modules = new ArrayList<>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        modules.add(new AwesomeModule(reactContext));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return modules;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -24,10 +24,13 @@
 | 
				
			|||||||
    "@shopify/flash-list": "1.4.3",
 | 
					    "@shopify/flash-list": "1.4.3",
 | 
				
			||||||
    "axios": "^1.5.0",
 | 
					    "axios": "^1.5.0",
 | 
				
			||||||
    "babel-plugin-module-resolver": "^5.0.0",
 | 
					    "babel-plugin-module-resolver": "^5.0.0",
 | 
				
			||||||
 | 
					    "eas-cli": "^12.5.1",
 | 
				
			||||||
    "expo": "~49.0.8",
 | 
					    "expo": "~49.0.8",
 | 
				
			||||||
    "expo-application": "~5.3.0",
 | 
					    "expo-application": "~5.3.0",
 | 
				
			||||||
 | 
					    "expo-av": "~13.4.1",
 | 
				
			||||||
    "expo-build-properties": "~0.8.3",
 | 
					    "expo-build-properties": "~0.8.3",
 | 
				
			||||||
    "expo-constants": "~14.4.2",
 | 
					    "expo-constants": "~14.4.2",
 | 
				
			||||||
 | 
					    "expo-crypto": "~12.4.1",
 | 
				
			||||||
    "expo-dev-client": "~2.4.12",
 | 
					    "expo-dev-client": "~2.4.12",
 | 
				
			||||||
    "expo-file-system": "~15.4.4",
 | 
					    "expo-file-system": "~15.4.4",
 | 
				
			||||||
    "expo-intent-launcher": "~10.7.0",
 | 
					    "expo-intent-launcher": "~10.7.0",
 | 
				
			||||||
@@ -59,13 +62,13 @@
 | 
				
			|||||||
    "react-native-webview": "13.2.2",
 | 
					    "react-native-webview": "13.2.2",
 | 
				
			||||||
    "react-redux": "^8.1.2",
 | 
					    "react-redux": "^8.1.2",
 | 
				
			||||||
    "redux": "^4.2.1",
 | 
					    "redux": "^4.2.1",
 | 
				
			||||||
    "rn-openapp": "^2.1.2",
 | 
					    "rn-openapp": "^2.1.2"
 | 
				
			||||||
    "expo-av": "~13.4.1"
 | 
					 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "devDependencies": {
 | 
					  "devDependencies": {
 | 
				
			||||||
    "@babel/core": "^7.20.0",
 | 
					    "@babel/core": "^7.20.0",
 | 
				
			||||||
    "@types/react": "~18.2.14",
 | 
					    "@types/react": "~18.2.14",
 | 
				
			||||||
    "typescript": "^5.1.3"
 | 
					    "typescript": "^5.1.3"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "private": true
 | 
					  "private": true,
 | 
				
			||||||
 | 
					  "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,7 @@
 | 
				
			|||||||
import axios from 'axios';
 | 
					import axios from 'axios';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const baseUrl = 'https://assemblr.denco.store';
 | 
					// export const baseUrl = 'https://assemblr.denco.store';
 | 
				
			||||||
// export const baseUrl = 'http://192.168.1.101:5000';
 | 
					export const baseUrl = 'http://192.168.1.101:5000';
 | 
				
			||||||
const apiClient = axios.create({
 | 
					const apiClient = axios.create({
 | 
				
			||||||
    baseURL: baseUrl
 | 
					    baseURL: baseUrl
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,15 +3,15 @@ import {Assembly} from "../types/assembly";
 | 
				
			|||||||
import {closeCancelAssemblyModal} from "../features/cancelAssemblyModal/cancelAssemblyModalSlice";
 | 
					import {closeCancelAssemblyModal} from "../features/cancelAssemblyModal/cancelAssemblyModalSlice";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const router = '/assembly';
 | 
					const router = '/assembly';
 | 
				
			||||||
 | 
					export type CreateAssemblyResponse = {
 | 
				
			||||||
 | 
					    ok: boolean,
 | 
				
			||||||
 | 
					    message: string,
 | 
				
			||||||
 | 
					    assemblyId: number,
 | 
				
			||||||
 | 
					    statusCode: AssemblyCreationStatusCode,
 | 
				
			||||||
 | 
					    userName?: string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
const assemblyApi = {
 | 
					const assemblyApi = {
 | 
				
			||||||
    create: async (orderId: number): Promise<{
 | 
					    create: async (orderId: number): Promise<CreateAssemblyResponse> => {
 | 
				
			||||||
        ok: boolean,
 | 
					 | 
				
			||||||
        message: string,
 | 
					 | 
				
			||||||
        assemblyId: number,
 | 
					 | 
				
			||||||
        statusCode: AssemblyCreationStatusCode,
 | 
					 | 
				
			||||||
        userName?: string
 | 
					 | 
				
			||||||
    }> => {
 | 
					 | 
				
			||||||
        let response = await apiClient.post(`${router}/create`, {orderId});
 | 
					        let response = await apiClient.post(`${router}/create`, {orderId});
 | 
				
			||||||
        return response.data;
 | 
					        return response.data;
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
@@ -42,6 +42,14 @@ const assemblyApi = {
 | 
				
			|||||||
    cancelById: async (assemblyId: number): Promise<{ ok: boolean, message: string }> => {
 | 
					    cancelById: async (assemblyId: number): Promise<{ ok: boolean, message: string }> => {
 | 
				
			||||||
        let response = await apiClient.post(`${router}/cancelById`, {assemblyId});
 | 
					        let response = await apiClient.post(`${router}/cancelById`, {assemblyId});
 | 
				
			||||||
        return response.data;
 | 
					        return response.data;
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    attachCrpt: async (orderProductId: number, crpt: string): Promise<{ ok: boolean, message: string }> => {
 | 
				
			||||||
 | 
					        let response = await apiClient.post(`${router}/attachCrpt`, {orderProductId, crpt});
 | 
				
			||||||
 | 
					        return response.data;
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    needCrpt: async (orderProductId: number): Promise<{ needCrpt: boolean }> => {
 | 
				
			||||||
 | 
					        let response = await apiClient.get(`${router}/needCrpt`, {params: {orderProductId}});
 | 
				
			||||||
 | 
					        return response.data;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,7 +5,7 @@ import {RFPercentage} from "react-native-responsive-fontsize";
 | 
				
			|||||||
import DText from "../DText/DText";
 | 
					import DText from "../DText/DText";
 | 
				
			||||||
import DTitle from "../DTitle/DTitle";
 | 
					import DTitle from "../DTitle/DTitle";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Props = {
 | 
					export type BasicButtonProps = {
 | 
				
			||||||
    label: string;
 | 
					    label: string;
 | 
				
			||||||
    style?: StyleProp<ViewStyle>;
 | 
					    style?: StyleProp<ViewStyle>;
 | 
				
			||||||
    containerStyle?: StyleProp<ViewStyle>;
 | 
					    containerStyle?: StyleProp<ViewStyle>;
 | 
				
			||||||
@@ -14,7 +14,7 @@ type Props = {
 | 
				
			|||||||
    disabled?: boolean
 | 
					    disabled?: boolean
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const BasicButton: FC<Props> = ({label, onPress, containerStyle, style, isUnset = false, disabled = false}) => {
 | 
					const BasicButton: FC<BasicButtonProps> = ({label, onPress, containerStyle, style, isUnset = false, disabled = false}) => {
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
        <TouchableOpacity style={containerStyle} disabled={disabled} onPress={onPress}>
 | 
					        <TouchableOpacity style={containerStyle} disabled={disabled} onPress={onPress}>
 | 
				
			||||||
            <View style={[styles.container, style, disabled ? {backgroundColor: "#A0A0A0"} : {}, containerStyle]}>
 | 
					            <View style={[styles.container, style, disabled ? {backgroundColor: "#A0A0A0"} : {}, containerStyle]}>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,13 +7,13 @@ import {responsiveHeight, responsiveWidth} from "react-native-responsive-dimensi
 | 
				
			|||||||
import DTitle from "../../DTitle/DTitle";
 | 
					import DTitle from "../../DTitle/DTitle";
 | 
				
			||||||
import BasicButton from "../../BasicButton/BasicButton";
 | 
					import BasicButton from "../../BasicButton/BasicButton";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Props = {
 | 
					export type AcceptModalProps = {
 | 
				
			||||||
    visible: boolean;
 | 
					    visible: boolean;
 | 
				
			||||||
    text: string;
 | 
					    text: string;
 | 
				
			||||||
    onAccepted: () => void;
 | 
					    onAccepted: () => void;
 | 
				
			||||||
    onRefused: () => void;
 | 
					    onRefused: () => void;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
const AcceptModal: FC<Props> = ({visible, text, onAccepted, onRefused}) => {
 | 
					const AcceptModal: FC<AcceptModalProps> = ({visible, text, onAccepted, onRefused}) => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
        <Modal isVisible={visible}>
 | 
					        <Modal isVisible={visible}>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,15 +11,16 @@ import {closeScanModal, setScannedData} from "../../features/scanModal/scanModal
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const ScanModal: FC = () => {
 | 
					const ScanModal: FC = () => {
 | 
				
			||||||
    const inputRef = useRef<TextInput | null>(null);
 | 
					    const inputRef = useRef<TextInput | null>(null);
 | 
				
			||||||
    const visible = useSelector((state: RootState) => state.scanModal.isVisible);
 | 
					    const state = useSelector((state: RootState) => state.scanModal);
 | 
				
			||||||
 | 
					    const getDefaultLabel = () => "Наведите сканер на штрихкод товара или заказа";
 | 
				
			||||||
    const dispatch = useDispatch();
 | 
					    const dispatch = useDispatch();
 | 
				
			||||||
    useEffect(() => {
 | 
					    useEffect(() => {
 | 
				
			||||||
        if (visible) inputRef.current?.focus();
 | 
					        if (state.isVisible) inputRef.current?.focus();
 | 
				
			||||||
    }, [visible]);
 | 
					    }, [state.isVisible]);
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
        <Modal isVisible={visible}>
 | 
					        <Modal isVisible={state.isVisible}>
 | 
				
			||||||
            <View style={styles.container}>
 | 
					            <View style={styles.container}>
 | 
				
			||||||
                <DText style={styles.text}>Наведите сканер на штрихкод товара или заказа</DText>
 | 
					                <DText style={styles.text}>{state.customLabel || getDefaultLabel()}</DText>
 | 
				
			||||||
                <BasicButton onPress={() => {
 | 
					                <BasicButton onPress={() => {
 | 
				
			||||||
                    dispatch(closeScanModal());
 | 
					                    dispatch(closeScanModal());
 | 
				
			||||||
                }} style={styles.cancelButton} label={"Отмена"}/>
 | 
					                }} style={styles.cancelButton} label={"Отмена"}/>
 | 
				
			||||||
@@ -31,7 +32,7 @@ const ScanModal: FC = () => {
 | 
				
			|||||||
                    style={styles.pseudoInput}
 | 
					                    style={styles.pseudoInput}
 | 
				
			||||||
                    ref={inputRef}
 | 
					                    ref={inputRef}
 | 
				
			||||||
                    autoFocus={true}
 | 
					                    autoFocus={true}
 | 
				
			||||||
                    showSoftInputOnFocus={false}
 | 
					                    // showSoftInputOnFocus={false}
 | 
				
			||||||
                />
 | 
					                />
 | 
				
			||||||
            </View>
 | 
					            </View>
 | 
				
			||||||
        </Modal>
 | 
					        </Modal>
 | 
				
			||||||
@@ -61,9 +62,9 @@ const styles = StyleSheet.create({
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
    pseudoInput: {
 | 
					    pseudoInput: {
 | 
				
			||||||
        backgroundColor: "red",
 | 
					        backgroundColor: "red",
 | 
				
			||||||
        opacity: 0,
 | 
					        // opacity: 0,
 | 
				
			||||||
        position: "absolute",
 | 
					        position: "absolute",
 | 
				
			||||||
        zIndex: -1
 | 
					        // zIndex: -1
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
export default ScanModal;
 | 
					export default ScanModal;
 | 
				
			||||||
@@ -51,7 +51,7 @@ const SearchBar: FC<Props> = ({onSearch, onProductSelected}) => {
 | 
				
			|||||||
            }} style={styles.scanButton} label={"Поиск"}/>
 | 
					            }} style={styles.scanButton} label={"Поиск"}/>
 | 
				
			||||||
            <View style={styles.scanImageWrapper}>
 | 
					            <View style={styles.scanImageWrapper}>
 | 
				
			||||||
                <TouchableOpacity onPress={() => {
 | 
					                <TouchableOpacity onPress={() => {
 | 
				
			||||||
                    dispatch(openScanModal());
 | 
					                    dispatch(openScanModal({customLabel: undefined, data: undefined}));
 | 
				
			||||||
                }}>
 | 
					                }}>
 | 
				
			||||||
                    <Image style={styles.scanImage} source={require('assets/icons/scan.png')}/>
 | 
					                    <Image style={styles.scanImage} source={require('assets/icons/scan.png')}/>
 | 
				
			||||||
                </TouchableOpacity>
 | 
					                </TouchableOpacity>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,11 +10,13 @@ export interface AssemblyState {
 | 
				
			|||||||
    assembly?: Assembly;
 | 
					    assembly?: Assembly;
 | 
				
			||||||
    selectedProductId?: number;
 | 
					    selectedProductId?: number;
 | 
				
			||||||
    localState?: ASSEMBLY_STATE;
 | 
					    localState?: ASSEMBLY_STATE;
 | 
				
			||||||
    selectedProduct?: OrderProduct
 | 
					    selectedProduct?: OrderProduct;
 | 
				
			||||||
 | 
					    acceptModalVisible: boolean;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const initialState: AssemblyState = {
 | 
					const initialState: AssemblyState = {
 | 
				
			||||||
    localState: ASSEMBLY_STATE.NOT_STARTED
 | 
					    localState: ASSEMBLY_STATE.NOT_STARTED,
 | 
				
			||||||
 | 
					    acceptModalVisible: false
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const assembly = createSlice({
 | 
					export const assembly = createSlice({
 | 
				
			||||||
@@ -31,12 +33,18 @@ export const assembly = createSlice({
 | 
				
			|||||||
            state.assembly = action.payload;
 | 
					            state.assembly = action.payload;
 | 
				
			||||||
            state.localState = action.payload.state;
 | 
					            state.localState = action.payload.state;
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					        skipCrpt: (state) => {
 | 
				
			||||||
 | 
					            if (!state.assembly) return;
 | 
				
			||||||
 | 
					            state.assembly.state = ASSEMBLY_STATE.ASSEMBLING_PRODUCTS;
 | 
				
			||||||
 | 
					            state.localState = ASSEMBLY_STATE.ASSEMBLING_PRODUCTS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
        startAssembly: (state) => {
 | 
					        startAssembly: (state) => {
 | 
				
			||||||
            if (!state.assembly) return;
 | 
					            if (!state.assembly) return;
 | 
				
			||||||
            state.assembly.createdAt = (new Date()).toDateString();
 | 
					            state.assembly.createdAt = (new Date()).toDateString();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            state.assembly.state = ASSEMBLY_STATE.ASSEMBLING_PRODUCTS;
 | 
					            state.assembly.state = ASSEMBLY_STATE.SCANNING_CRPT;
 | 
				
			||||||
            state.localState = ASSEMBLY_STATE.ASSEMBLING_PRODUCTS;
 | 
					            state.localState = ASSEMBLY_STATE.SCANNING_CRPT;
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        endAssembly: (state) => {
 | 
					        endAssembly: (state) => {
 | 
				
			||||||
            if (!state.assembly) return;
 | 
					            if (!state.assembly) return;
 | 
				
			||||||
@@ -94,6 +102,12 @@ export const assembly = createSlice({
 | 
				
			|||||||
            state.localState = ASSEMBLY_STATE.NOT_STARTED
 | 
					            state.localState = ASSEMBLY_STATE.NOT_STARTED
 | 
				
			||||||
            state.selectedProductId = undefined;
 | 
					            state.selectedProductId = undefined;
 | 
				
			||||||
            state.selectedProduct = undefined;
 | 
					            state.selectedProduct = undefined;
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        openAcceptModal: (state) => {
 | 
				
			||||||
 | 
					            state.acceptModalVisible = true;
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        closeAcceptModal: (state) => {
 | 
				
			||||||
 | 
					            state.acceptModalVisible = false;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
@@ -107,6 +121,10 @@ export const {
 | 
				
			|||||||
    endAssembly,
 | 
					    endAssembly,
 | 
				
			||||||
    confirmAssembly,
 | 
					    confirmAssembly,
 | 
				
			||||||
    setLocalState,
 | 
					    setLocalState,
 | 
				
			||||||
    reset
 | 
					    reset,
 | 
				
			||||||
 | 
					    openAcceptModal,
 | 
				
			||||||
 | 
					    closeAcceptModal,
 | 
				
			||||||
 | 
					    skipCrpt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} = assembly.actions;
 | 
					} = assembly.actions;
 | 
				
			||||||
export default assembly.reducer;
 | 
					export default assembly.reducer;
 | 
				
			||||||
@@ -1,30 +1,44 @@
 | 
				
			|||||||
import {createSlice} from "@reduxjs/toolkit";
 | 
					import {createSlice, PayloadAction} from "@reduxjs/toolkit";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface ScanModalState {
 | 
					export interface ScanModalState {
 | 
				
			||||||
    isVisible: boolean;
 | 
					    isVisible: boolean;
 | 
				
			||||||
    scannedData?: string
 | 
					    scannedData?: string;
 | 
				
			||||||
 | 
					    customLabel?: string;
 | 
				
			||||||
 | 
					    data?: any;
 | 
				
			||||||
 | 
					    uuid?: string;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const initialState: ScanModalState = {
 | 
					const initialState: ScanModalState = {
 | 
				
			||||||
    isVisible: false,
 | 
					    isVisible: false,
 | 
				
			||||||
    scannedData: undefined
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const scanModalSlice = createSlice({
 | 
					export const scanModalSlice = createSlice({
 | 
				
			||||||
    name: 'scanModal',
 | 
					    name: 'scanModal',
 | 
				
			||||||
    initialState,
 | 
					    initialState,
 | 
				
			||||||
    reducers: {
 | 
					    reducers: {
 | 
				
			||||||
        openScanModal: (state) => {
 | 
					        openScanModalFormContext(state, action: PayloadAction<{ uuid: string }>) {
 | 
				
			||||||
 | 
					            state.isVisible = true;
 | 
				
			||||||
 | 
					            state.uuid = action.payload.uuid;
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        openScanModal: (state, action: PayloadAction<{ customLabel?: string, data?: any }>) => {
 | 
				
			||||||
            state.isVisible = true
 | 
					            state.isVisible = true
 | 
				
			||||||
 | 
					            if (!action) return;
 | 
				
			||||||
 | 
					            state.customLabel = action.payload.customLabel;
 | 
				
			||||||
 | 
					            state.data = action.payload.data;
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        closeScanModal: (state) => {
 | 
					        closeScanModal: (state) => {
 | 
				
			||||||
            state.isVisible = false
 | 
					            state.isVisible = false
 | 
				
			||||||
 | 
					            state.customLabel = undefined;
 | 
				
			||||||
 | 
					            state.data = undefined;
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        setScannedData: (state, action) => {
 | 
					        setScannedData: (state, action) => {
 | 
				
			||||||
            state.scannedData = action.payload;
 | 
					            state.scannedData = action.payload;
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        resolveUuid: (state) => {
 | 
				
			||||||
 | 
					            state.uuid = undefined;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const {openScanModal, closeScanModal, setScannedData} = scanModalSlice.actions;
 | 
					export const {openScanModal, closeScanModal, setScannedData, openScanModalFormContext,resolveUuid} = scanModalSlice.actions;
 | 
				
			||||||
export default scanModalSlice.reducer;
 | 
					export default scanModalSlice.reducer;
 | 
				
			||||||
							
								
								
									
										24
									
								
								src/hooks/useScan.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/hooks/useScan.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					import {useDispatch, useSelector} from "react-redux";
 | 
				
			||||||
 | 
					import {RootState} from "../redux/store";
 | 
				
			||||||
 | 
					import {useEffect, useState} from "react";
 | 
				
			||||||
 | 
					import {openScanModal} from "../features/scanModal/scanModalSlice";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ScanProps<T> = {
 | 
				
			||||||
 | 
					    label: string;
 | 
				
			||||||
 | 
					    onScanned: (scanned: string, data: T) => void;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					type ReturnValue<T> = {
 | 
				
			||||||
 | 
					    scan: (props: ScanProps<T>) => void;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function useScan<T>(): ReturnValue<T> {
 | 
				
			||||||
 | 
					    const state = useSelector((state: RootState) => state.scanModal);
 | 
				
			||||||
 | 
					    const dispatch = useDispatch();
 | 
				
			||||||
 | 
					    const scan = (props: ScanProps<T>) => {
 | 
				
			||||||
 | 
					        dispatch(openScanModal({customLabel: props.label, data: props}));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    useEffect(() => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }, [state.scannedData]);
 | 
				
			||||||
 | 
					    return {scan}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										69
									
								
								src/providers/ScanProvider.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								src/providers/ScanProvider.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,69 @@
 | 
				
			|||||||
 | 
					import {createContext, useContext, useEffect, useState} from "react";
 | 
				
			||||||
 | 
					import {randomUUID} from "expo-crypto";
 | 
				
			||||||
 | 
					import {RootState, useAppDispatch} from "../redux/store";
 | 
				
			||||||
 | 
					import {openScanModalFormContext, resolveUuid} from "../features/scanModal/scanModalSlice";
 | 
				
			||||||
 | 
					import {useSelector} from "react-redux";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ScanCallback = (data: string) => void;
 | 
				
			||||||
 | 
					type ScanProps = {
 | 
				
			||||||
 | 
					    callback: ScanCallback;
 | 
				
			||||||
 | 
					    data?: any;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					type ScanningContextState = {
 | 
				
			||||||
 | 
					    scan: (props: ScanProps) => void;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					const ScanningContext = createContext<ScanningContextState | undefined>(undefined);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const useScanningContext = () => {
 | 
				
			||||||
 | 
					    const context = useContext(ScanningContext);
 | 
				
			||||||
 | 
					    if (!context) {
 | 
				
			||||||
 | 
					        throw new Error(
 | 
				
			||||||
 | 
					            "useScanningContext must be used within a ScanningContextProvider"
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return context;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ScanningContextProviderProps = {
 | 
				
			||||||
 | 
					    children: React.ReactNode;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type CallbacksState = {
 | 
				
			||||||
 | 
					    uuid: string;
 | 
				
			||||||
 | 
					    callback: (data: string) => void;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					type DataState = {
 | 
				
			||||||
 | 
					    uuid: string;
 | 
				
			||||||
 | 
					    data: any;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					export const ScanningContextProvider = (props: ScanningContextProviderProps) => {
 | 
				
			||||||
 | 
					    const [callbacks, setCallbacks] = useState<CallbacksState[]>([]);
 | 
				
			||||||
 | 
					    const [data, setData] = useState<DataState[]>([]);
 | 
				
			||||||
 | 
					    const dispatch = useAppDispatch();
 | 
				
			||||||
 | 
					    const state = useSelector((state: RootState) => state.scanModal);
 | 
				
			||||||
 | 
					    const scan = (props: ScanProps) => {
 | 
				
			||||||
 | 
					        const {callback, data} = props
 | 
				
			||||||
 | 
					        const uuid = randomUUID();
 | 
				
			||||||
 | 
					        setCallbacks([...callbacks, {uuid, callback}]);
 | 
				
			||||||
 | 
					        dispatch(openScanModalFormContext({uuid}));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const handleChange = () => {
 | 
				
			||||||
 | 
					        if (!state.scannedData) return;
 | 
				
			||||||
 | 
					        const uuid = state.uuid;
 | 
				
			||||||
 | 
					        if (!uuid) return;
 | 
				
			||||||
 | 
					        const callback = callbacks.find(item => item.uuid === uuid);
 | 
				
			||||||
 | 
					        if (!callback) return;
 | 
				
			||||||
 | 
					        callback.callback(state.scannedData);
 | 
				
			||||||
 | 
					        dispatch(resolveUuid());
 | 
				
			||||||
 | 
					        setCallbacks(callbacks.filter(item => item.uuid !== uuid));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    useEffect(() => {
 | 
				
			||||||
 | 
					        handleChange();
 | 
				
			||||||
 | 
					    }, [state.scannedData]);
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					        <ScanningContext.Provider value={{scan}}>
 | 
				
			||||||
 | 
					            {props.children}
 | 
				
			||||||
 | 
					        </ScanningContext.Provider>
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										61
									
								
								src/screens/AssemblyScreen/AcceptAssemblyModal.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								src/screens/AssemblyScreen/AcceptAssemblyModal.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,61 @@
 | 
				
			|||||||
 | 
					import AcceptModal, {AcceptModalProps} from "../../components/Modals/AcceptModal/AcceptModal";
 | 
				
			||||||
 | 
					import assemblyApi, {AssemblyCreationStatusCode, CreateAssemblyResponse} from "../../api/assemblyApi";
 | 
				
			||||||
 | 
					import Toast from "react-native-toast-message";
 | 
				
			||||||
 | 
					import {openCancelAssemblyModal} from "../../features/cancelAssemblyModal/cancelAssemblyModalSlice";
 | 
				
			||||||
 | 
					import React from "react";
 | 
				
			||||||
 | 
					import {RootState, useAppDispatch} from "../../redux/store";
 | 
				
			||||||
 | 
					import {closeAcceptModal} from "../../features/assembly/assemblySlice";
 | 
				
			||||||
 | 
					import {useSelector} from "react-redux";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type RestProps = {
 | 
				
			||||||
 | 
					    onCreated: (response: CreateAssemblyResponse) => void;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					type Props = RestProps;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const CreateAssemblyModal = (props: Props) => {
 | 
				
			||||||
 | 
					    const {onCreated} = props
 | 
				
			||||||
 | 
					    const {order, acceptModalVisible} = useSelector((state: RootState) => state.assembly);
 | 
				
			||||||
 | 
					    const dispatch = useAppDispatch();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const showCreateStatusToast = (ok: boolean, message: string) => {
 | 
				
			||||||
 | 
					        Toast.show({
 | 
				
			||||||
 | 
					            type: ok ? 'success' : 'error',
 | 
				
			||||||
 | 
					            text1: 'Создание сборки',
 | 
				
			||||||
 | 
					            text2: message
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const onError = (response: CreateAssemblyResponse) => {
 | 
				
			||||||
 | 
					        const {statusCode, assemblyId, userName} = response;
 | 
				
			||||||
 | 
					        if (statusCode !== AssemblyCreationStatusCode.ASSEMBLY_ALREADY_EXISTS) return;
 | 
				
			||||||
 | 
					        const message =
 | 
				
			||||||
 | 
					            `Заказ собирает ${userName}. Отменить и начать сборку на ваш аккаунт?\n\n` +
 | 
				
			||||||
 | 
					            'Удостоверьтесь, что текущая сборка ошибочна и никто другой её не выполняет.';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        dispatch(openCancelAssemblyModal({assemblyId: assemblyId, message: message}));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const onAccepted = async () => {
 | 
				
			||||||
 | 
					        if (!order) return
 | 
				
			||||||
 | 
					        const response = await assemblyApi.create(order.databaseId);
 | 
				
			||||||
 | 
					        showCreateStatusToast(response.ok, response.message);
 | 
				
			||||||
 | 
					        const handler = response.ok ? onCreated : onError;
 | 
				
			||||||
 | 
					        handler(response);
 | 
				
			||||||
 | 
					        dispatch(closeAcceptModal());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const onRefused = async () => {
 | 
				
			||||||
 | 
					        dispatch(closeAcceptModal())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					        <AcceptModal
 | 
				
			||||||
 | 
					            visible={acceptModalVisible}
 | 
				
			||||||
 | 
					            text={`Вы уверены что хотите начать сборку заказа ${order?.orderNumber}`}
 | 
				
			||||||
 | 
					            onAccepted={onAccepted}
 | 
				
			||||||
 | 
					            onRefused={onRefused}/>
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default CreateAssemblyModal;
 | 
				
			||||||
							
								
								
									
										12
									
								
								src/screens/AssemblyScreen/AssemblyController.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/screens/AssemblyScreen/AssemblyController.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					import {useEffect, useState} from "react";
 | 
				
			||||||
 | 
					import {useSelector} from "react-redux";
 | 
				
			||||||
 | 
					import {RootState} from "../../redux/store";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const useAssemblyController = () => {
 | 
				
			||||||
 | 
					    const state = useSelector((state: RootState) => state.assembly);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    useEffect(() => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }, [state.localState]);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										287
									
								
								src/screens/AssemblyScreen/AssemblyControls.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										287
									
								
								src/screens/AssemblyScreen/AssemblyControls.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,287 @@
 | 
				
			|||||||
 | 
					import {useDispatch, useSelector} from "react-redux";
 | 
				
			||||||
 | 
					import {RootState, useAppDispatch} from "../../redux/store";
 | 
				
			||||||
 | 
					import {ASSEMBLY_STATE} from "../../types/assembly";
 | 
				
			||||||
 | 
					import {StyleSheet, Text, View} from "react-native";
 | 
				
			||||||
 | 
					import BasicButton, {BasicButtonProps} from "../../components/BasicButton/BasicButton";
 | 
				
			||||||
 | 
					import {BaseButton} from "react-native-gesture-handler";
 | 
				
			||||||
 | 
					import {
 | 
				
			||||||
 | 
					    confirmAssembly, endAssembly,
 | 
				
			||||||
 | 
					    openAcceptModal,
 | 
				
			||||||
 | 
					    selectProduct,
 | 
				
			||||||
 | 
					    setAssembled,
 | 
				
			||||||
 | 
					    skipCrpt
 | 
				
			||||||
 | 
					} from "../../features/assembly/assemblySlice";
 | 
				
			||||||
 | 
					import {useScanningContext} from "../../providers/ScanProvider";
 | 
				
			||||||
 | 
					import assemblyApi from "../../api/assemblyApi";
 | 
				
			||||||
 | 
					import {OkMessageResponse} from "../../types/api";
 | 
				
			||||||
 | 
					import Toast from "react-native-toast-message";
 | 
				
			||||||
 | 
					import {useEffect, useState} from "react";
 | 
				
			||||||
 | 
					import {RFPercentage} from "react-native-responsive-fontsize";
 | 
				
			||||||
 | 
					import {responsiveHeight} from "react-native-responsive-dimensions";
 | 
				
			||||||
 | 
					import {closeLoadingModal, openLoadingModal, setLoadingText} from "../../features/loadingModal/loadingModalSlice";
 | 
				
			||||||
 | 
					import printingService from "../../utils/PrintingService";
 | 
				
			||||||
 | 
					import printingApi from "../../api/printingApi";
 | 
				
			||||||
 | 
					import {setPrinterName} from "../../features/printing/printingSlice";
 | 
				
			||||||
 | 
					import {openReprintModal} from "../../features/reprintModal/reprintModalSlice";
 | 
				
			||||||
 | 
					import {showReward} from "../../features/animations/animationsSlice";
 | 
				
			||||||
 | 
					import {fetchBalance, refreshTransactions} from "../../features/balance/balanceSlice";
 | 
				
			||||||
 | 
					import {NavigationProp, useNavigation} from "@react-navigation/native";
 | 
				
			||||||
 | 
					import {TabNavigatorParamList} from "../MainScreen/MainScreen";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const AssemblyButton = (props: BasicButtonProps) => {
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					        <BasicButton
 | 
				
			||||||
 | 
					            {...props}
 | 
				
			||||||
 | 
					            containerStyle={{flex: 1}}
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					const NotStartedButtons = () => {
 | 
				
			||||||
 | 
					    const dispatch = useDispatch();
 | 
				
			||||||
 | 
					    const onStartAssembly = () => {
 | 
				
			||||||
 | 
					        dispatch(openAcceptModal());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					        <AssemblyButton
 | 
				
			||||||
 | 
					            label={"Начать сборку"}
 | 
				
			||||||
 | 
					            onPress={onStartAssembly}
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ScanningCrptButtons = () => {
 | 
				
			||||||
 | 
					    const dispatch = useAppDispatch();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const state = useSelector((state: RootState) => state.assembly);
 | 
				
			||||||
 | 
					    const [isInitialized, setIsInitialized] = useState(false);
 | 
				
			||||||
 | 
					    const getNeedState = () => {
 | 
				
			||||||
 | 
					        if (!state.order) return {};
 | 
				
			||||||
 | 
					        return state.order.products.reduce((acc, product) => {
 | 
				
			||||||
 | 
					            acc[product.databaseId] = false;
 | 
				
			||||||
 | 
					            return acc;
 | 
				
			||||||
 | 
					        }, {} as { [key: number]: boolean })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const [crptNeedState, setCrptNeedState] = useState<{ [key: number]: boolean }>(getNeedState());
 | 
				
			||||||
 | 
					    const {scan} = useScanningContext();
 | 
				
			||||||
 | 
					    const onAttached = (response: OkMessageResponse) => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Toast.show({
 | 
				
			||||||
 | 
					            type: response.ok ? "success" : "error",
 | 
				
			||||||
 | 
					            text1: "Сканирование честного знака",
 | 
				
			||||||
 | 
					            text2: response.message,
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!response.ok) return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        setCrptNeedState(prevState => {
 | 
				
			||||||
 | 
					            if (!state.selectedProduct) return prevState;
 | 
				
			||||||
 | 
					            return {...prevState, [state.selectedProduct.databaseId]: false}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    const onScanned = (data: string) => {
 | 
				
			||||||
 | 
					        if (!state.selectedProduct) return;
 | 
				
			||||||
 | 
					        assemblyApi.attachCrpt(state.selectedProduct.databaseId, data).then(onAttached);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    const onScanClick = () => {
 | 
				
			||||||
 | 
					        scan({callback: onScanned});
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    const initialize = async () => {
 | 
				
			||||||
 | 
					        dispatch(setLoadingText('Проверка необходимости сканирования честного знака...'))
 | 
				
			||||||
 | 
					        dispatch(openLoadingModal());
 | 
				
			||||||
 | 
					        if (!state.order) return;
 | 
				
			||||||
 | 
					        const responses = await Promise.all(state.order.products.map(async (product) => {
 | 
				
			||||||
 | 
					            const response = await assemblyApi.needCrpt(product.databaseId);
 | 
				
			||||||
 | 
					            return {productId: product.databaseId, need: response.needCrpt};
 | 
				
			||||||
 | 
					        }));
 | 
				
			||||||
 | 
					        // update state
 | 
				
			||||||
 | 
					        setCrptNeedState(responses.reduce((acc, {productId, need}) => {
 | 
				
			||||||
 | 
					            acc[productId] = need;
 | 
				
			||||||
 | 
					            return acc;
 | 
				
			||||||
 | 
					        }, {} as { [key: number]: boolean }));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        setIsInitialized(true);
 | 
				
			||||||
 | 
					        dispatch(closeLoadingModal());
 | 
				
			||||||
 | 
					        ////
 | 
				
			||||||
 | 
					        ////
 | 
				
			||||||
 | 
					        dispatch(selectProduct(0))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    useEffect(() => {
 | 
				
			||||||
 | 
					        if (!isInitialized) return;
 | 
				
			||||||
 | 
					        if (Object.values(crptNeedState).every(value => !value))
 | 
				
			||||||
 | 
					            dispatch(skipCrpt())
 | 
				
			||||||
 | 
					    }, [crptNeedState]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    useEffect(() => {
 | 
				
			||||||
 | 
					        initialize();
 | 
				
			||||||
 | 
					    }, []);
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					        <>
 | 
				
			||||||
 | 
					            <AssemblyButton
 | 
				
			||||||
 | 
					                disabled={!state.selectedProduct || !crptNeedState[state.selectedProduct.databaseId]}
 | 
				
			||||||
 | 
					                onPress={onScanClick}
 | 
				
			||||||
 | 
					                label={"Сканировать честный знак"}
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
 | 
					            <AssemblyButton
 | 
				
			||||||
 | 
					                onPress={() => {
 | 
				
			||||||
 | 
					                    dispatch(skipCrpt())
 | 
				
			||||||
 | 
					                }}
 | 
				
			||||||
 | 
					                label={"Пропустить"}
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
 | 
					        </>
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const AssemblingButtons = () => {
 | 
				
			||||||
 | 
					    const dispatch = useAppDispatch();
 | 
				
			||||||
 | 
					    const state = useSelector((state: RootState) => state.assembly);
 | 
				
			||||||
 | 
					    useEffect(() => {
 | 
				
			||||||
 | 
					        dispatch(selectProduct(0));
 | 
				
			||||||
 | 
					    }, []);
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					        <AssemblyButton
 | 
				
			||||||
 | 
					            disabled={state.selectedProduct?.assembled}
 | 
				
			||||||
 | 
					            onPress={() => {
 | 
				
			||||||
 | 
					                if (!state.selectedProduct) return;
 | 
				
			||||||
 | 
					                dispatch(setAssembled({orderProductId: state.selectedProduct.databaseId}));
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
 | 
					            label={"Отметить как собранный"}
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const AllProductsAssembledButtons = () => {
 | 
				
			||||||
 | 
					    const dispatch = useAppDispatch();
 | 
				
			||||||
 | 
					    const state = useSelector((state: RootState) => state.assembly);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const [skipButtonVisible, setSkipButtonVisible] = useState(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const onConfirmClick = () => {
 | 
				
			||||||
 | 
					        if (!state.assembly) return;
 | 
				
			||||||
 | 
					        dispatch(setLoadingText('Подтверждение сборки...'))
 | 
				
			||||||
 | 
					        dispatch(openLoadingModal());
 | 
				
			||||||
 | 
					        assemblyApi.confirm(state.assembly.databaseId).then(({ok, message}) => {
 | 
				
			||||||
 | 
					            dispatch(closeLoadingModal());
 | 
				
			||||||
 | 
					            Toast.show({
 | 
				
			||||||
 | 
					                type: ok ? 'success' : 'error',
 | 
				
			||||||
 | 
					                text1: 'Подтверждение сборки',
 | 
				
			||||||
 | 
					                text2: message
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					            if (ok) {
 | 
				
			||||||
 | 
					                dispatch(confirmAssembly());
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                setSkipButtonVisible(true);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    const onSkipClick = () => {
 | 
				
			||||||
 | 
					        dispatch(confirmAssembly());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					        <>
 | 
				
			||||||
 | 
					            <AssemblyButton label={"Подтвердить сборку"} onPress={onConfirmClick}/>
 | 
				
			||||||
 | 
					            {skipButtonVisible && <AssemblyButton label={"Пропустить"} onPress={onSkipClick}/>}
 | 
				
			||||||
 | 
					        </>
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ConfirmedButtons = () => {
 | 
				
			||||||
 | 
					    const navigator = useNavigation<NavigationProp<TabNavigatorParamList, 'Barcode'>>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const dispatch = useAppDispatch();
 | 
				
			||||||
 | 
					    const order = useSelector((state: RootState) => state.assembly.order);
 | 
				
			||||||
 | 
					    const assembly = useSelector((state: RootState) => state.assembly.assembly);
 | 
				
			||||||
 | 
					    const onPrintLabel = () => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					        if (!order) return;
 | 
				
			||||||
 | 
					        let printer = printingService.getInstance().getPrinter(order.baseMarketplace);
 | 
				
			||||||
 | 
					        dispatch(setLoadingText('Идет печать этикетки...'))
 | 
				
			||||||
 | 
					        dispatch(openLoadingModal())
 | 
				
			||||||
 | 
					        printingApi.getLabel(order.databaseId).then(pdfData => {
 | 
				
			||||||
 | 
					            printingService.getInstance().printPdf(printer, pdfData).then((response) => {
 | 
				
			||||||
 | 
					                dispatch(closeLoadingModal());
 | 
				
			||||||
 | 
					                if (response) return;
 | 
				
			||||||
 | 
					                dispatch(setPrinterName({printerName: printer}));
 | 
				
			||||||
 | 
					                dispatch(openReprintModal());
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    const onEndAssembly = () => {
 | 
				
			||||||
 | 
					        if (!assembly) return;
 | 
				
			||||||
 | 
					        assemblyApi.close(assembly.databaseId).then(({ok, message, reward}) => {
 | 
				
			||||||
 | 
					            Toast.show({
 | 
				
			||||||
 | 
					                type: ok ? 'success' : 'error',
 | 
				
			||||||
 | 
					                text1: 'Завершение сборки',
 | 
				
			||||||
 | 
					                text2: message
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					            if (ok) {
 | 
				
			||||||
 | 
					                dispatch(showReward({reward}));
 | 
				
			||||||
 | 
					                dispatch(fetchBalance())
 | 
				
			||||||
 | 
					                dispatch(refreshTransactions())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            dispatch(endAssembly());
 | 
				
			||||||
 | 
					            navigator.navigate('Barcode');
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    useEffect(() => {
 | 
				
			||||||
 | 
					        onPrintLabel();
 | 
				
			||||||
 | 
					    }, []);
 | 
				
			||||||
 | 
					    return (<>
 | 
				
			||||||
 | 
					        <AssemblyButton
 | 
				
			||||||
 | 
					            onPress={onPrintLabel}
 | 
				
			||||||
 | 
					            label={"Печать этикетки"}/>
 | 
				
			||||||
 | 
					        <AssemblyButton
 | 
				
			||||||
 | 
					            onPress={onEndAssembly}
 | 
				
			||||||
 | 
					            label={"Завершить сборку"}/>
 | 
				
			||||||
 | 
					    </>)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const EndedButtons = () => {
 | 
				
			||||||
 | 
					    return (<></>)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const AssemblyControls = () => {
 | 
				
			||||||
 | 
					    const state = useSelector((state: RootState) => state.assembly);
 | 
				
			||||||
 | 
					    const getButtons = () => {
 | 
				
			||||||
 | 
					        if (state.localState === undefined) return (<BasicButton
 | 
				
			||||||
 | 
					            label={"Ошибка"}
 | 
				
			||||||
 | 
					            disabled={true}
 | 
				
			||||||
 | 
					        />)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        switch (state.localState) {
 | 
				
			||||||
 | 
					            case ASSEMBLY_STATE.NOT_STARTED:
 | 
				
			||||||
 | 
					                return <NotStartedButtons/>
 | 
				
			||||||
 | 
					            case ASSEMBLY_STATE.SCANNING_CRPT:
 | 
				
			||||||
 | 
					                return <ScanningCrptButtons/>
 | 
				
			||||||
 | 
					            case ASSEMBLY_STATE.ASSEMBLING_PRODUCTS:
 | 
				
			||||||
 | 
					                return <AssemblingButtons/>
 | 
				
			||||||
 | 
					            case ASSEMBLY_STATE.ALL_PRODUCTS_ASSEMBLED:
 | 
				
			||||||
 | 
					                return <AllProductsAssembledButtons/>
 | 
				
			||||||
 | 
					            case ASSEMBLY_STATE.CONFIRMED:
 | 
				
			||||||
 | 
					                return <ConfirmedButtons/>
 | 
				
			||||||
 | 
					            case ASSEMBLY_STATE.ENDED:
 | 
				
			||||||
 | 
					                return <EndedButtons/>
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return (<>{getButtons()}</>)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const styles = StyleSheet.create({
 | 
				
			||||||
 | 
					    buttonsContainer: {
 | 
				
			||||||
 | 
					        backgroundColor: "white",
 | 
				
			||||||
 | 
					        padding: RFPercentage(2),
 | 
				
			||||||
 | 
					        flex: 0.5,
 | 
				
			||||||
 | 
					        borderRadius: RFPercentage(3),
 | 
				
			||||||
 | 
					        rowGap: responsiveHeight(2)
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					export default AssemblyControls;
 | 
				
			||||||
							
								
								
									
										39
									
								
								src/screens/AssemblyScreen/AssemblyProductSelect.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								src/screens/AssemblyScreen/AssemblyProductSelect.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
				
			|||||||
 | 
					import {Order} from "../../types/order";
 | 
				
			||||||
 | 
					import React from "react";
 | 
				
			||||||
 | 
					import {RFPercentage} from "react-native-responsive-fontsize";
 | 
				
			||||||
 | 
					import OrderProductsList from "../../components/OrderCard/OrderProductsList";
 | 
				
			||||||
 | 
					import {StyleSheet, View} from "react-native";
 | 
				
			||||||
 | 
					import {useAppDispatch} from "../../redux/store";
 | 
				
			||||||
 | 
					import {selectProduct} from "../../features/assembly/assemblySlice";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Props = {
 | 
				
			||||||
 | 
					    order: Order;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					const AssemblyProductSelect = (props: Props) => {
 | 
				
			||||||
 | 
					    const dispatch = useAppDispatch();
 | 
				
			||||||
 | 
					    const onSelected = (productId: number) => {
 | 
				
			||||||
 | 
					        dispatch(selectProduct(productId));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					        <View style={styles.wrapper}>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            <OrderProductsList
 | 
				
			||||||
 | 
					                products={props.order.products}
 | 
				
			||||||
 | 
					                onSelected={onSelected}
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
 | 
					        </View>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const styles = StyleSheet.create({
 | 
				
			||||||
 | 
					    wrapper: {
 | 
				
			||||||
 | 
					        flex: 0.5,
 | 
				
			||||||
 | 
					        backgroundColor: "white",
 | 
				
			||||||
 | 
					        borderRadius: RFPercentage(3),
 | 
				
			||||||
 | 
					        padding: RFPercentage(2),
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default AssemblyProductSelect;
 | 
				
			||||||
							
								
								
									
										14
									
								
								src/screens/AssemblyScreen/AssemblyScreen.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/screens/AssemblyScreen/AssemblyScreen.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					import {useSelector} from "react-redux";
 | 
				
			||||||
 | 
					import {RootState} from "../../redux/store";
 | 
				
			||||||
 | 
					import {NoOrderScreen} from "../NoOrderScreen/NoOrderScreen";
 | 
				
			||||||
 | 
					import AssemblyView from "./AssemblyView";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const AssemblyScreen = () => {
 | 
				
			||||||
 | 
					    const order = useSelector((state: RootState) => state.assembly.order);
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					        order ? <AssemblyView order={order}/> : <NoOrderScreen/>
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default AssemblyScreen;
 | 
				
			||||||
							
								
								
									
										92
									
								
								src/screens/AssemblyScreen/AssemblyView.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								src/screens/AssemblyScreen/AssemblyView.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,92 @@
 | 
				
			|||||||
 | 
					import {Order} from "../../types/order";
 | 
				
			||||||
 | 
					import {RootState, useAppDispatch} from "../../redux/store";
 | 
				
			||||||
 | 
					import {useSelector} from "react-redux";
 | 
				
			||||||
 | 
					import {StyleSheet, View} from "react-native";
 | 
				
			||||||
 | 
					import {responsiveHeight, responsiveWidth} from "react-native-responsive-dimensions";
 | 
				
			||||||
 | 
					import {RFPercentage} from "react-native-responsive-fontsize";
 | 
				
			||||||
 | 
					import AssemblyProductSelect from "./AssemblyProductSelect";
 | 
				
			||||||
 | 
					import ProductImageView from "./ProductImageView";
 | 
				
			||||||
 | 
					import OrderInfoView from "./OrderInfoView";
 | 
				
			||||||
 | 
					import AssemblyControls from "./AssemblyControls";
 | 
				
			||||||
 | 
					import AcceptAssemblyModal from "./AcceptAssemblyModal";
 | 
				
			||||||
 | 
					import assemblyApi, {CreateAssemblyResponse} from "../../api/assemblyApi";
 | 
				
			||||||
 | 
					import {setAssembly, startAssembly} from "../../features/assembly/assemblySlice";
 | 
				
			||||||
 | 
					import {ScanCrptContextProvider} from "./contexts/ScanCrptContext";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Props = {
 | 
				
			||||||
 | 
					    order: Order;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					const AssemblyView = (props: Props) => {
 | 
				
			||||||
 | 
					    const {order} = props;
 | 
				
			||||||
 | 
					    const dispatch = useAppDispatch();
 | 
				
			||||||
 | 
					    const state = useSelector((state: RootState) => state.assembly);
 | 
				
			||||||
 | 
					    const onCreated = (_: CreateAssemblyResponse) => {
 | 
				
			||||||
 | 
					        assemblyApi.getActive().then(assembly => {
 | 
				
			||||||
 | 
					            dispatch(setAssembly(assembly));
 | 
				
			||||||
 | 
					            dispatch(startAssembly());
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					        <View style={styles.viewContainer}>
 | 
				
			||||||
 | 
					            <View style={styles.topSection}>
 | 
				
			||||||
 | 
					                <AssemblyProductSelect order={order}/>
 | 
				
			||||||
 | 
					                <ProductImageView imageUrl={state.selectedProduct?.imageUrl}/>
 | 
				
			||||||
 | 
					            </View>
 | 
				
			||||||
 | 
					            <View style={styles.bottomSection}>
 | 
				
			||||||
 | 
					                <OrderInfoView
 | 
				
			||||||
 | 
					                    order={order}
 | 
				
			||||||
 | 
					                    selectedProduct={state.selectedProduct}
 | 
				
			||||||
 | 
					                />
 | 
				
			||||||
 | 
					                <View style={styles.buttonsWrapper}>
 | 
				
			||||||
 | 
					                    <AssemblyControls/>
 | 
				
			||||||
 | 
					                </View>
 | 
				
			||||||
 | 
					            </View>
 | 
				
			||||||
 | 
					            <AcceptAssemblyModal
 | 
				
			||||||
 | 
					                onCreated={response => onCreated(response)}
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
 | 
					        </View>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const styles = StyleSheet.create({
 | 
				
			||||||
 | 
					    viewContainer: {
 | 
				
			||||||
 | 
					        width: "100%",
 | 
				
			||||||
 | 
					        height: "100%",
 | 
				
			||||||
 | 
					        display: "flex",
 | 
				
			||||||
 | 
					        paddingHorizontal: responsiveWidth(5),
 | 
				
			||||||
 | 
					        paddingBottom: responsiveHeight(10),
 | 
				
			||||||
 | 
					        rowGap: responsiveHeight(2),
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    topSection: {
 | 
				
			||||||
 | 
					        display: "flex",
 | 
				
			||||||
 | 
					        flexDirection: "row",
 | 
				
			||||||
 | 
					        columnGap: responsiveWidth(3),
 | 
				
			||||||
 | 
					        height: responsiveHeight(30),
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    productSelectWrapper: {
 | 
				
			||||||
 | 
					        flex: 0.5,
 | 
				
			||||||
 | 
					        backgroundColor: "white",
 | 
				
			||||||
 | 
					        borderRadius: RFPercentage(3),
 | 
				
			||||||
 | 
					        padding: RFPercentage(2),
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    bottomSection: {
 | 
				
			||||||
 | 
					        backgroundColor: "red",
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        flex: 1,
 | 
				
			||||||
 | 
					        borderRadius: RFPercentage(3),
 | 
				
			||||||
 | 
					        flexDirection: "row",
 | 
				
			||||||
 | 
					        columnGap: responsiveWidth(3),
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    buttonsWrapper: {
 | 
				
			||||||
 | 
					        backgroundColor: "white",
 | 
				
			||||||
 | 
					        padding: RFPercentage(2),
 | 
				
			||||||
 | 
					        flex: 0.5,
 | 
				
			||||||
 | 
					        borderRadius: RFPercentage(3),
 | 
				
			||||||
 | 
					        rowGap: responsiveHeight(2)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					export default AssemblyView;
 | 
				
			||||||
							
								
								
									
										55
									
								
								src/screens/AssemblyScreen/OrderInfoView.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								src/screens/AssemblyScreen/OrderInfoView.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,55 @@
 | 
				
			|||||||
 | 
					import {Order, OrderProduct} from "../../types/order";
 | 
				
			||||||
 | 
					import {ScrollView, StyleSheet, View} from "react-native";
 | 
				
			||||||
 | 
					import DTitle from "../../components/DTitle/DTitle";
 | 
				
			||||||
 | 
					import DText from "../../components/DText/DText";
 | 
				
			||||||
 | 
					import {OrderStatus, OrderStatusDictionary} from "../../features/ordersFilter/ordersFilterSlice";
 | 
				
			||||||
 | 
					import React from "react";
 | 
				
			||||||
 | 
					import {RFPercentage} from "react-native-responsive-fontsize";
 | 
				
			||||||
 | 
					import {responsiveWidth} from "react-native-responsive-dimensions";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Props = {
 | 
				
			||||||
 | 
					    order: Order;
 | 
				
			||||||
 | 
					    selectedProduct?: OrderProduct
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					const OrderInfoView = (props: Props) => {
 | 
				
			||||||
 | 
					    const {order, selectedProduct} = props;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <View style={styles.dataContainer}>
 | 
				
			||||||
 | 
					            <ScrollView>
 | 
				
			||||||
 | 
					                <DTitle style={styles.contentTitle}>Заказ</DTitle>
 | 
				
			||||||
 | 
					                <DText>Номер заказа: {order.orderNumber}</DText>
 | 
				
			||||||
 | 
					                <DText>Маркетплейс: {order.marketplaceName}</DText>
 | 
				
			||||||
 | 
					                <DText>Селлер: {order.sellerName}</DText>
 | 
				
			||||||
 | 
					                <DText>Создан: {order.createdOn}</DText>
 | 
				
			||||||
 | 
					                <DText>Отгрузка: {order.shipmentDate}</DText>
 | 
				
			||||||
 | 
					                <DText>Статус: {OrderStatusDictionary[order.status as OrderStatus]}</DText>
 | 
				
			||||||
 | 
					                <DText>Склад отгрузки: {order.shippingWarehouse}</DText>
 | 
				
			||||||
 | 
					                <DText>Город: {order.city}</DText>
 | 
				
			||||||
 | 
					                <DText>{""}</DText>
 | 
				
			||||||
 | 
					                <DTitle style={styles.contentTitle}>Товар</DTitle>
 | 
				
			||||||
 | 
					                <DText>Арт. DENCO: {selectedProduct?.dencoArticle}</DText>
 | 
				
			||||||
 | 
					                <DText>Арт. поставщика: {selectedProduct?.supplierArticle}</DText>
 | 
				
			||||||
 | 
					                <DText>Фасовка: {selectedProduct?.inBlock} шт.</DText>
 | 
				
			||||||
 | 
					                <DText>Поставщик: {selectedProduct?.supplierName}</DText>
 | 
				
			||||||
 | 
					            </ScrollView>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        </View>
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const styles = StyleSheet.create({
 | 
				
			||||||
 | 
					    dataContainer: {
 | 
				
			||||||
 | 
					        backgroundColor: "white",
 | 
				
			||||||
 | 
					        padding: RFPercentage(2),
 | 
				
			||||||
 | 
					        flex: 0.5,
 | 
				
			||||||
 | 
					        borderRadius: RFPercentage(3),
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    contentTitle: {
 | 
				
			||||||
 | 
					        alignSelf: "center"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default OrderInfoView;
 | 
				
			||||||
							
								
								
									
										38
									
								
								src/screens/AssemblyScreen/ProductImageView.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								src/screens/AssemblyScreen/ProductImageView.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
				
			|||||||
 | 
					import {Image, StyleSheet, TouchableOpacity, View} from "react-native";
 | 
				
			||||||
 | 
					import {openImageZoomModal, setImages} from "../../features/imageZoomModal/loadingModalSlice";
 | 
				
			||||||
 | 
					import React from "react";
 | 
				
			||||||
 | 
					import {RFPercentage} from "react-native-responsive-fontsize";
 | 
				
			||||||
 | 
					import {useAppDispatch} from "../../redux/store";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Props = {
 | 
				
			||||||
 | 
					    imageUrl?: string;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					const ProductImageView = (props: Props) => {
 | 
				
			||||||
 | 
					    const {imageUrl} = props;
 | 
				
			||||||
 | 
					    const dispatch = useAppDispatch()
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					        <TouchableOpacity style={styles.imageWrapper} onPress={() => {
 | 
				
			||||||
 | 
					            if (!imageUrl) return;
 | 
				
			||||||
 | 
					            dispatch(setImages([imageUrl]));
 | 
				
			||||||
 | 
					            dispatch(openImageZoomModal());
 | 
				
			||||||
 | 
					        }}>
 | 
				
			||||||
 | 
					            <View style={{flex: 1}}>
 | 
				
			||||||
 | 
					                <Image style={styles.image} source={{uri: imageUrl}}/>
 | 
				
			||||||
 | 
					            </View>
 | 
				
			||||||
 | 
					        </TouchableOpacity>
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const styles = StyleSheet.create({
 | 
				
			||||||
 | 
					    imageWrapper: {
 | 
				
			||||||
 | 
					        flex: 0.5,
 | 
				
			||||||
 | 
					        backgroundColor: "white",
 | 
				
			||||||
 | 
					        padding: RFPercentage(2),
 | 
				
			||||||
 | 
					        borderRadius: RFPercentage(3)
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    image: {
 | 
				
			||||||
 | 
					        flex: 1,
 | 
				
			||||||
 | 
					        resizeMode: "contain"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					export default ProductImageView
 | 
				
			||||||
							
								
								
									
										3
									
								
								src/screens/AssemblyScreen/ScanCrptModal.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/screens/AssemblyScreen/ScanCrptModal.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					const ScanCrptModal = () => {
 | 
				
			||||||
 | 
					    return (<ScanBa)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										42
									
								
								src/screens/AssemblyScreen/contexts/AssemblyContext.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								src/screens/AssemblyScreen/contexts/AssemblyContext.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,42 @@
 | 
				
			|||||||
 | 
					// based on ScanCrptContext.tsx (src/screens/AssemblyScreen/contexts/ScanCrptContext.tsx) create new context
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import {createContext, FC} from "react";
 | 
				
			||||||
 | 
					import {OrderProduct} from "../../../types/order";
 | 
				
			||||||
 | 
					import {useDispatch} from "react-redux";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ScanCrptProps = {
 | 
				
			||||||
 | 
					    orderProduct: OrderProduct;
 | 
				
			||||||
 | 
					    onScanned: (data: string) => void;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type AssemblyContextState = {
 | 
				
			||||||
 | 
					    scanCrpt: (props: ScanCrptProps) => void;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					const AssemblyContext = createContext<AssemblyContextState | undefined>(
 | 
				
			||||||
 | 
					    undefined
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const useAssemblyContextState = () => {
 | 
				
			||||||
 | 
					    const dispatch = useDispatch();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const scanCrpt = (props: ScanCrptProps) => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return {scanCrpt}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type AssemblyContextProviderProps = {
 | 
				
			||||||
 | 
					    children: React.ReactNode;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const AssemblyContextProvider: FC<AssemblyContextProviderProps> = ({
 | 
				
			||||||
 | 
					                                                                              children,
 | 
				
			||||||
 | 
					                                                                          }) => {
 | 
				
			||||||
 | 
					    const state = useAssemblyContextState();
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					        <AssemblyContext.Provider value={state}>
 | 
				
			||||||
 | 
					            {children}
 | 
				
			||||||
 | 
					        </AssemblyContext.Provider>
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										39
									
								
								src/screens/AssemblyScreen/contexts/ScanCrptContext.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								src/screens/AssemblyScreen/contexts/ScanCrptContext.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
				
			|||||||
 | 
					import {OrderProduct} from "../../../types/order";
 | 
				
			||||||
 | 
					import {createContext, useContext, useState} from "react";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ScanCrptContextState = {
 | 
				
			||||||
 | 
					    currentOrderProduct?: OrderProduct;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ScanCrptContext = createContext<ScanCrptContextState>({});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const useScanCrptContextState = () => {
 | 
				
			||||||
 | 
					    const [currentOrderProduct, setCurrentOrderProduct] = useState<OrderProduct | undefined>(undefined);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
 | 
					        currentOrderProduct,
 | 
				
			||||||
 | 
					        setCurrentOrderProduct
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					type ScanCrptContextProviderProps = {
 | 
				
			||||||
 | 
					    children: React.ReactNode;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const ScanCrptContextProvider = ({children}: ScanCrptContextProviderProps) => {
 | 
				
			||||||
 | 
					    const state = useScanCrptContextState();
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					        <ScanCrptContext.Provider value={state}>
 | 
				
			||||||
 | 
					            {children}
 | 
				
			||||||
 | 
					        </ScanCrptContext.Provider>
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const useScanCrptContext = () => {
 | 
				
			||||||
 | 
					    const context = useContext(ScanCrptContext);
 | 
				
			||||||
 | 
					    if (!context) {
 | 
				
			||||||
 | 
					        throw new Error(
 | 
				
			||||||
 | 
					            "useScanCrptContext must be used within a ScanCrptContextProvider"
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return context;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										14
									
								
								src/screens/AssemblyScreen/useCrptState.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/screens/AssemblyScreen/useCrptState.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					// Честный знак
 | 
				
			||||||
 | 
					import {useEffect, useState} from "react";
 | 
				
			||||||
 | 
					import {useSelector} from "react-redux";
 | 
				
			||||||
 | 
					import {RootState} from "../../redux/store";
 | 
				
			||||||
 | 
					import {ASSEMBLY_STATE} from "../../types/assembly";
 | 
				
			||||||
 | 
					import assemblyApi from "../../api/assemblyApi";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const useCrptState = () => {
 | 
				
			||||||
 | 
					    const assemblyState = useSelector((state: RootState) => state.assembly);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -34,7 +34,7 @@ function BarcodeScreen() {
 | 
				
			|||||||
        if (!navigationState.history) return;
 | 
					        if (!navigationState.history) return;
 | 
				
			||||||
        // @ts-ignore
 | 
					        // @ts-ignore
 | 
				
			||||||
        let currentTabKey: string = navigationState.history[navigationState.history.length - 1].key;
 | 
					        let currentTabKey: string = navigationState.history[navigationState.history.length - 1].key;
 | 
				
			||||||
        if (currentTabKey.startsWith("Barcode")) if (!isScanModalVisible) dispatch(openScanModal());
 | 
					        if (currentTabKey.startsWith("Barcode")) if (!isScanModalVisible) dispatch(openScanModal({}));
 | 
				
			||||||
    }, [navigationState]);
 | 
					    }, [navigationState]);
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
        <View style={styles.container}>
 | 
					        <View style={styles.container}>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -32,6 +32,7 @@ import CancelAssemblyModal from "../../components/Modals/CancelAssemblyModal/Can
 | 
				
			|||||||
import {AxiosHeaders} from "axios";
 | 
					import {AxiosHeaders} from "axios";
 | 
				
			||||||
import apiClient from "../../api/apiClient";
 | 
					import apiClient from "../../api/apiClient";
 | 
				
			||||||
import AnimationsView from "../../components/Animations/AnimationsView";
 | 
					import AnimationsView from "../../components/Animations/AnimationsView";
 | 
				
			||||||
 | 
					import {ScanningContextProvider} from "../../providers/ScanProvider";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function CommonPage() {
 | 
					function CommonPage() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -65,6 +66,7 @@ function CommonPage() {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const checkUpdates = async () => {
 | 
					    const checkUpdates = async () => {
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
        const currentVersion = Constants.manifest2?.extra?.expoClient?.version || Constants.manifest?.version;
 | 
					        const currentVersion = Constants.manifest2?.extra?.expoClient?.version || Constants.manifest?.version;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        applicationApi.getVersion('assemblr').then(({latest_version}) => {
 | 
					        applicationApi.getVersion('assemblr').then(({latest_version}) => {
 | 
				
			||||||
@@ -119,20 +121,20 @@ function CommonPage() {
 | 
				
			|||||||
    }, []);
 | 
					    }, []);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
 | 
					        <ScanningContextProvider>
 | 
				
			||||||
        <View style={styles.main}>
 | 
					            <View style={styles.main}>
 | 
				
			||||||
            {isAuthorized ? <MainScreen/> : <LoginScreen/>}
 | 
					                {isAuthorized ? <MainScreen/> : <LoginScreen/>}
 | 
				
			||||||
            <AnimationsView/>
 | 
					                <AnimationsView/>
 | 
				
			||||||
            <View style={[styles.overlay, {display: dim ? 'flex' : 'none'}]}/>
 | 
					                <View style={[styles.overlay, {display: dim ? 'flex' : 'none'}]}/>
 | 
				
			||||||
            <LoadingModal/>
 | 
					                <LoadingModal/>
 | 
				
			||||||
            <ScanModal/>
 | 
					                <ScanModal/>
 | 
				
			||||||
            <ReprintModal/>
 | 
					                <ReprintModal/>
 | 
				
			||||||
            <CancelAssemblyModal/>
 | 
					                <CancelAssemblyModal/>
 | 
				
			||||||
            <ImageZoomModal/>
 | 
					                <ImageZoomModal/>
 | 
				
			||||||
            <SortingModal/>
 | 
					                <SortingModal/>
 | 
				
			||||||
            <Toast config={toastConfig}/>
 | 
					                <Toast config={toastConfig}/>
 | 
				
			||||||
        </View>
 | 
					            </View>
 | 
				
			||||||
 | 
					        </ScanningContextProvider>
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,6 +9,7 @@ import {RFPercentage} from "react-native-responsive-fontsize";
 | 
				
			|||||||
import {OrderScreenController} from "../OrderScreen/OrderScreen";
 | 
					import {OrderScreenController} from "../OrderScreen/OrderScreen";
 | 
				
			||||||
import OrdersScreen from "../OrdersScreen/OrdersScreen";
 | 
					import OrdersScreen from "../OrdersScreen/OrdersScreen";
 | 
				
			||||||
import {background} from "../../css/colors";
 | 
					import {background} from "../../css/colors";
 | 
				
			||||||
 | 
					import AssemblyScreen from "../AssemblyScreen/AssemblyScreen";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export  type TabNavigatorParamList = {
 | 
					export  type TabNavigatorParamList = {
 | 
				
			||||||
@@ -50,7 +51,7 @@ function MainScreen() {
 | 
				
			|||||||
    const tabScreens: CustomTabProps[] = [
 | 
					    const tabScreens: CustomTabProps[] = [
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            name: "Home",
 | 
					            name: "Home",
 | 
				
			||||||
            component: OrderScreenController,
 | 
					            component: AssemblyScreen,
 | 
				
			||||||
            icon: require('assets/icons/home.png'),
 | 
					            icon: require('assets/icons/home.png'),
 | 
				
			||||||
            hidden: false
 | 
					            hidden: false
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,13 +1,24 @@
 | 
				
			|||||||
import {Button, Text, View} from "react-native";
 | 
					import {NativeModules, Text, View} from "react-native";
 | 
				
			||||||
import {useAppDispatch} from "../../redux/store";
 | 
					import BasicButton from "../../components/BasicButton/BasicButton";
 | 
				
			||||||
import {logoutUser, useGetPokemonByNameQuery} from "../../features/auth/authSlice.ts.back";
 | 
					import {randomUUID} from "expo-crypto";
 | 
				
			||||||
import * as process from "process";
 | 
					import {useScanningContext} from "../../providers/ScanProvider";
 | 
				
			||||||
 | 
					import {dampingFor} from "react-native-toast-message/lib/src/components/AnimatedContainer";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const {AwesomeModule} = NativeModules;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function MoneyScreen() {
 | 
					function MoneyScreen() {
 | 
				
			||||||
 | 
					    const {scan} = useScanningContext();
 | 
				
			||||||
 | 
					    const a = "123";
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
        <View>
 | 
					        <View>
 | 
				
			||||||
            <Text style={{fontSize: 36}}>Money</Text>
 | 
					            <Text style={{fontSize: 36}}>Money</Text>
 | 
				
			||||||
 | 
					            <BasicButton
 | 
				
			||||||
 | 
					                onPress={() => {
 | 
				
			||||||
 | 
					                    console.log("Button pressed");
 | 
				
			||||||
 | 
					                }}
 | 
				
			||||||
 | 
					                label={"Press me"}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
        </View>
 | 
					        </View>
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										28
									
								
								src/screens/NoOrderScreen/NoOrderScreen.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								src/screens/NoOrderScreen/NoOrderScreen.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
				
			|||||||
 | 
					import React, {FC} from "react";
 | 
				
			||||||
 | 
					import {StyleSheet, View} from "react-native";
 | 
				
			||||||
 | 
					import DText from "../../components/DText/DText";
 | 
				
			||||||
 | 
					import {responsiveHeight, responsiveWidth} from "react-native-responsive-dimensions";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const NoOrderScreen: FC = () => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					        <View style={noOrderStyles.container}>
 | 
				
			||||||
 | 
					            <DText style={noOrderStyles.title}>Заказ не выбран!</DText>
 | 
				
			||||||
 | 
					        </View>
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					const noOrderStyles = StyleSheet.create({
 | 
				
			||||||
 | 
					    container: {
 | 
				
			||||||
 | 
					        justifyContent: "center",
 | 
				
			||||||
 | 
					        flex: 1,
 | 
				
			||||||
 | 
					        rowGap: responsiveHeight(5)
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    title: {
 | 
				
			||||||
 | 
					        textAlign: "center",
 | 
				
			||||||
 | 
					        fontSize: responsiveWidth(5)
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    buttonWrapper: {
 | 
				
			||||||
 | 
					        paddingHorizontal: responsiveWidth(20),
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
@@ -33,43 +33,19 @@ import {OrderStatus, OrderStatusDictionary} from "../../features/ordersFilter/or
 | 
				
			|||||||
import {openCancelAssemblyModal} from "../../features/cancelAssemblyModal/cancelAssemblyModalSlice";
 | 
					import {openCancelAssemblyModal} from "../../features/cancelAssemblyModal/cancelAssemblyModalSlice";
 | 
				
			||||||
import {fetchBalance, refreshTransactions} from "../../features/balance/balanceSlice";
 | 
					import {fetchBalance, refreshTransactions} from "../../features/balance/balanceSlice";
 | 
				
			||||||
import {showReward} from "../../features/animations/animationsSlice";
 | 
					import {showReward} from "../../features/animations/animationsSlice";
 | 
				
			||||||
 | 
					import {NoOrderScreen} from "../NoOrderScreen/NoOrderScreen";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type AssemblyPeriod = {
 | 
					 | 
				
			||||||
    started: Date;
 | 
					 | 
				
			||||||
    ended: Date;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const NoOrderScreen: FC = () => {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return (
 | 
					 | 
				
			||||||
        <View style={noOrderStyles.container}>
 | 
					 | 
				
			||||||
            <DText style={noOrderStyles.title}>Заказ не выбран!</DText>
 | 
					 | 
				
			||||||
        </View>
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
const noOrderStyles = StyleSheet.create({
 | 
					 | 
				
			||||||
    container: {
 | 
					 | 
				
			||||||
        justifyContent: "center",
 | 
					 | 
				
			||||||
        flex: 1,
 | 
					 | 
				
			||||||
        rowGap: responsiveHeight(5)
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    title: {
 | 
					 | 
				
			||||||
        textAlign: "center",
 | 
					 | 
				
			||||||
        fontSize: responsiveWidth(5)
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    buttonWrapper: {
 | 
					 | 
				
			||||||
        paddingHorizontal: responsiveWidth(20),
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type OrderScreenProps = {
 | 
					type OrderScreenProps = {
 | 
				
			||||||
    order: Order;
 | 
					    order: Order;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
const OrderScreen: FC<OrderScreenProps> = ({order}) => {
 | 
					const OrderScreen: FC<OrderScreenProps> = ({order}) => {
 | 
				
			||||||
    const navigator = useNavigation<NavigationProp<TabNavigatorParamList, 'Barcode'>>();
 | 
					    const navigator = useNavigation<NavigationProp<TabNavigatorParamList, 'Barcode'>>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const [orderProductCrpt, setOrderProductCrpt] = useState<Map<number, boolean>>({} as Map<number, boolean>);
 | 
				
			||||||
 | 
					    const scanState = useSelector((state: RootState) => state.scanModal);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const dispatch = useAppDispatch();
 | 
					    const dispatch = useAppDispatch();
 | 
				
			||||||
    const assembly = useSelector((state: RootState) => state.assembly.assembly);
 | 
					    const assembly = useSelector((state: RootState) => state.assembly.assembly);
 | 
				
			||||||
    const assemblyState = useSelector((state: RootState) => state.assembly.localState);
 | 
					    const assemblyState = useSelector((state: RootState) => state.assembly.localState);
 | 
				
			||||||
@@ -102,6 +78,25 @@ const OrderScreen: FC<OrderScreenProps> = ({order}) => {
 | 
				
			|||||||
                return (<BasicButton containerStyle={styles.buttonContainer}
 | 
					                return (<BasicButton containerStyle={styles.buttonContainer}
 | 
				
			||||||
                                     onPress={() => setAcceptModalVisible(true)}
 | 
					                                     onPress={() => setAcceptModalVisible(true)}
 | 
				
			||||||
                                     label={"Начать сборку"}/>)
 | 
					                                     label={"Начать сборку"}/>)
 | 
				
			||||||
 | 
					            case ASSEMBLY_STATE.SCANNING_CRPT:
 | 
				
			||||||
 | 
					                return (
 | 
				
			||||||
 | 
					                    <>
 | 
				
			||||||
 | 
					                        <BasicButton
 | 
				
			||||||
 | 
					                            label={"Сканировать честный знак"}
 | 
				
			||||||
 | 
					                            disabled={selectedProduct ? orderProductCrpt.get(selectedProduct.databaseId) : true}
 | 
				
			||||||
 | 
					                            onPress={() => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            }}
 | 
				
			||||||
 | 
					                        />
 | 
				
			||||||
 | 
					                        <BasicButton
 | 
				
			||||||
 | 
					                            label={"Пропустить сканирование честного знака"}
 | 
				
			||||||
 | 
					                            onPress={() => {
 | 
				
			||||||
 | 
					                                // dispatch(startAssembly())
 | 
				
			||||||
 | 
					                            }}
 | 
				
			||||||
 | 
					                            style={{backgroundColor: 'orange'}}
 | 
				
			||||||
 | 
					                        />
 | 
				
			||||||
 | 
					                    </>
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
            case ASSEMBLY_STATE.ASSEMBLING_PRODUCTS:
 | 
					            case ASSEMBLY_STATE.ASSEMBLING_PRODUCTS:
 | 
				
			||||||
                return (<BasicButton
 | 
					                return (<BasicButton
 | 
				
			||||||
                    containerStyle={styles.buttonContainer}
 | 
					                    containerStyle={styles.buttonContainer}
 | 
				
			||||||
@@ -176,6 +171,35 @@ const OrderScreen: FC<OrderScreenProps> = ({order}) => {
 | 
				
			|||||||
                )
 | 
					                )
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const updateAssemblyState = () => {
 | 
				
			||||||
 | 
					        if (!assembly) return;
 | 
				
			||||||
 | 
					        assemblyApi.updateState(assembly.databaseId, Number(assemblyState)).then(ok => {
 | 
				
			||||||
 | 
					            if (ok) return;
 | 
				
			||||||
 | 
					            Toast.show({
 | 
				
			||||||
 | 
					                type: 'error',
 | 
				
			||||||
 | 
					                text1: 'Обновление состояния',
 | 
				
			||||||
 | 
					                text2: 'Неудалось обновить состояние текущей сборки на сервере'
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const onConfirmed = () => {
 | 
				
			||||||
 | 
					        printLabel();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    const onAssemblingProducts = () => {
 | 
				
			||||||
 | 
					        if (!selectedProduct || order.products.length > 1) return;
 | 
				
			||||||
 | 
					        dispatch(setAssembled({orderProductId: selectedProduct.databaseId}));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    const onScanCrpt = async () => {
 | 
				
			||||||
 | 
					        const result = await Promise.all(order.products.map(async product => {
 | 
				
			||||||
 | 
					            const {need} = await assemblyApi.needCrpt(product.databaseId);
 | 
				
			||||||
 | 
					            return {databaseId: product.databaseId, need};
 | 
				
			||||||
 | 
					        }))
 | 
				
			||||||
 | 
					        setOrderProductCrpt(new Map(result.map(({databaseId, need}) => [databaseId, need])));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const printLabel = () => {
 | 
					    const printLabel = () => {
 | 
				
			||||||
        if (!order) return;
 | 
					        if (!order) return;
 | 
				
			||||||
        let printer = printingService.getInstance().getPrinter(order.baseMarketplace);
 | 
					        let printer = printingService.getInstance().getPrinter(order.baseMarketplace);
 | 
				
			||||||
@@ -190,28 +214,45 @@ const OrderScreen: FC<OrderScreenProps> = ({order}) => {
 | 
				
			|||||||
            });
 | 
					            });
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    const handleOrderProductCrptChange = () => {
 | 
				
			||||||
 | 
					        const someOfProductsNeedCrpt = orderProductCrpt.entries().map(([orderProductId, need]) => {
 | 
				
			||||||
 | 
					            return need;
 | 
				
			||||||
 | 
					        }).some(need => need);
 | 
				
			||||||
 | 
					        if (!someOfProductsNeedCrpt) {
 | 
				
			||||||
 | 
					            // dispatch(startAssembly());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    const onScanned = () => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    useEffect(() => {
 | 
				
			||||||
 | 
					        if (!scanState.scannedData) return;
 | 
				
			||||||
 | 
					        onScanned();
 | 
				
			||||||
 | 
					    }, [scanState.scannedData]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    useEffect(() => {
 | 
				
			||||||
 | 
					        handleOrderProductCrptChange();
 | 
				
			||||||
 | 
					    }, [orderProductCrpt]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    useEffect(() => {
 | 
					    useEffect(() => {
 | 
				
			||||||
        if (!assembly) return;
 | 
					        if (!assembly) return;
 | 
				
			||||||
        assemblyApi.updateState(assembly.databaseId, Number(assemblyState)).then(ok => {
 | 
					        if (!assemblyState) return;
 | 
				
			||||||
            if (ok) return;
 | 
					        updateAssemblyState();
 | 
				
			||||||
            Toast.show({
 | 
					        const handlers = {
 | 
				
			||||||
                type: 'error',
 | 
					            [ASSEMBLY_STATE.CONFIRMED]: onConfirmed,
 | 
				
			||||||
                text1: 'Обновление состояния',
 | 
					            [ASSEMBLY_STATE.ASSEMBLING_PRODUCTS]: onAssemblingProducts,
 | 
				
			||||||
                text2: 'Неудалось обновить состояние текущей сборки на сервере'
 | 
					            [ASSEMBLY_STATE.SCANNING_CRPT]: onScanCrpt,
 | 
				
			||||||
            })
 | 
					            [ASSEMBLY_STATE.ALL_PRODUCTS_ASSEMBLED]: () => {
 | 
				
			||||||
        });
 | 
					            },
 | 
				
			||||||
        switch (assemblyState) {
 | 
					            [ASSEMBLY_STATE.NOT_STARTED]: () => {
 | 
				
			||||||
            case ASSEMBLY_STATE.CONFIRMED:
 | 
					            },
 | 
				
			||||||
                printLabel();
 | 
					            [ASSEMBLY_STATE.ENDED]: () => {
 | 
				
			||||||
                break;
 | 
					            }
 | 
				
			||||||
            case ASSEMBLY_STATE.ASSEMBLING_PRODUCTS:
 | 
					
 | 
				
			||||||
                if (!selectedProduct) return;
 | 
					 | 
				
			||||||
                if (order.products.length == 1) {
 | 
					 | 
				
			||||||
                    dispatch(setAssembled({orderProductId: selectedProduct.databaseId}));
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        const handler = handlers[assemblyState];
 | 
				
			||||||
 | 
					        handler();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }, [assemblyState]);
 | 
					    }, [assemblyState]);
 | 
				
			||||||
    useEffect(() => {
 | 
					    useEffect(() => {
 | 
				
			||||||
        if (!order) return;
 | 
					        if (!order) return;
 | 
				
			||||||
@@ -250,7 +291,7 @@ const OrderScreen: FC<OrderScreenProps> = ({order}) => {
 | 
				
			|||||||
                        <DText>Статус: {OrderStatusDictionary[order.status as OrderStatus]}</DText>
 | 
					                        <DText>Статус: {OrderStatusDictionary[order.status as OrderStatus]}</DText>
 | 
				
			||||||
                        <DText>Склад отгрузки: {order.shippingWarehouse}</DText>
 | 
					                        <DText>Склад отгрузки: {order.shippingWarehouse}</DText>
 | 
				
			||||||
                        <DText>Город: {order.city}</DText>
 | 
					                        <DText>Город: {order.city}</DText>
 | 
				
			||||||
                        <DText>{}</DText>
 | 
					                        <DText>{""}</DText>
 | 
				
			||||||
                        <DTitle style={styles.contentTitle}>Товар</DTitle>
 | 
					                        <DTitle style={styles.contentTitle}>Товар</DTitle>
 | 
				
			||||||
                        <DText>Арт. DENCO: {selectedProduct?.dencoArticle}</DText>
 | 
					                        <DText>Арт. DENCO: {selectedProduct?.dencoArticle}</DText>
 | 
				
			||||||
                        <DText>Арт. поставщика: {selectedProduct?.supplierArticle}</DText>
 | 
					                        <DText>Арт. поставщика: {selectedProduct?.supplierArticle}</DText>
 | 
				
			||||||
@@ -380,4 +421,3 @@ const styles = StyleSheet.create({
 | 
				
			|||||||
        textDecorationLine: 'underline'
 | 
					        textDecorationLine: 'underline'
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
export default OrderScreen;
 | 
					 | 
				
			||||||
							
								
								
									
										4
									
								
								src/types/api.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								src/types/api.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					export type OkMessageResponse = {
 | 
				
			||||||
 | 
					    ok: boolean,
 | 
				
			||||||
 | 
					    message: string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,5 +1,6 @@
 | 
				
			|||||||
export enum ASSEMBLY_STATE {
 | 
					export enum ASSEMBLY_STATE {
 | 
				
			||||||
    NOT_STARTED,
 | 
					    NOT_STARTED,
 | 
				
			||||||
 | 
					    SCANNING_CRPT,
 | 
				
			||||||
    ASSEMBLING_PRODUCTS,
 | 
					    ASSEMBLING_PRODUCTS,
 | 
				
			||||||
    ALL_PRODUCTS_ASSEMBLED,
 | 
					    ALL_PRODUCTS_ASSEMBLED,
 | 
				
			||||||
    CONFIRMED,
 | 
					    CONFIRMED,
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user