Compare commits

...

2 Commits

Author SHA1 Message Date
1b38306551 init project for hotfix/update-sdk-33 branch 2025-07-25 14:07:41 +07:00
5e0189f487 init project for release branch 2025-07-25 11:22:48 +07:00
91 changed files with 8019 additions and 4929 deletions

3
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"java.configuration.updateBuildConfiguration": "automatic"
}

46
App.js
View File

@ -7,21 +7,21 @@
*/
import React, { Component } from 'react'
import { Platform, StyleSheet, Text, StatusBar, TouchableOpacity, View } from 'react-native'
import { StatusBar, StyleSheet, Text, TouchableOpacity } from 'react-native'
import MainNav from './src/navigation/MainNav'
import firebase, { Notification } from 'react-native-firebase'
import { store, persistor } from './src/redux/store'
import messaging from '@react-native-firebase/messaging'
import { persistor, store } from './src/redux/store'
import { Provider } from 'react-redux'
import { registerDevice, testConnect ,news} from './src/api/UserApi'
import { appSetPushToken, appSetDevice, appCleanDevice,appSetNotification } from './src/redux/app/action'
import { setLanguage, setStore as setApiStore, setToken } from 'src/api/api'
import { registerDevice } from './src/api/UserApi'
import { appSetDevice, appSetPushToken } from './src/redux/app/action'
import { setLanguage, setToken } from 'src/api/api'
import { PersistGate } from 'redux-persist/integration/react'
import { create } from 'apisauce'
import SplashScreen from 'react-native-splash-screen'
import { setBaseUrlByServerMode } from './src/api/api'
Text.defaultProps = Text.defaultProps || {};
Text.defaultProps.allowFontScaling = false;
Text.defaultProps = Text.defaultProps || {}
Text.defaultProps.allowFontScaling = false
if (TouchableOpacity.defaultProps == null) TouchableOpacity.defaultProps = {}
TouchableOpacity.defaultProps.activeOpacity = 0.7
@ -29,7 +29,7 @@ TouchableOpacity.defaultProps.activeOpacity = 0.7
// setApiStore(store)
class App extends Component {
constructor(props) {
constructor (props) {
super(props)
this._setDataFromInitState = this._setDataFromInitState.bind(this)
}
@ -37,15 +37,15 @@ class App extends Component {
componentDidMount = () => {
SplashScreen.hide()
};
}
initNotification = async () => {
await this.setPermission()
const fcmToken = await firebase.messaging().getToken()
const fcmToken = await messaging().getAPNSToken()
if (fcmToken) {
store.dispatch(appSetPushToken(fcmToken))
const resultSendDevice = await registerDevice(fcmToken)
console.log(' re sult register_device =>',resultSendDevice);
console.log(' re sult register_device =>', resultSendDevice)
if (resultSendDevice.ok && resultSendDevice.data.success) {
store.dispatch(appSetDevice(resultSendDevice.data.device))
}
@ -55,23 +55,27 @@ class App extends Component {
setPermission = async () => {
try {
const enabled = await firebase.messaging().hasPermission()
await messaging().registerDeviceForRemoteMessages();
const authStatus = await messaging().requestPermission();
const enabled = authStatus === messaging.AuthorizationStatus.AUTHORIZED || authStatus === messaging.AuthorizationStatus.PROVISIONAL;
if (!enabled) {
await firebase.messaging().requestPermission()
await messaging().requestPermission()
}
} catch (error) {
console.log('error', error)
}
}
_setDataFromInitState() {
_setDataFromInitState () {
const appState = store.getState().app
let device = appState.device;
let device = appState.device
setBaseUrlByServerMode(appState.server_mode)
if (appState.token) {
setToken(appState.token)
}
if(appState.lang){
if (appState.lang) {
setLanguage(appState.lang)
}
@ -83,13 +87,13 @@ class App extends Component {
}
render() {
render () {
return (
<Provider store={store}>
<PersistGate persistor={persistor} loading={null} onBeforeLift={this._setDataFromInitState}>
<StatusBar barStyle="light-content"/>
<MainNav />
<MainNav/>
</PersistGate>
</Provider>
)

View File

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>csareactrn60</name>
<name>charoensin-android</name>
<comment>Project android created by Buildship.</comment>
<projects>
</projects>
@ -14,4 +14,15 @@
<natures>
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
</natures>
<filteredResources>
<filter>
<id>1689128079578</id>
<name></name>
<type>30</type>
<matcher>
<id>org.eclipse.core.resources.regexFilterMatcher</id>
<arguments>node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__</arguments>
</matcher>
</filter>
</filteredResources>
</projectDescription>

View File

@ -1,2 +1,13 @@
arguments=--init-script /var/folders/4d/cv31_tl15q381gddgqqtk94c0000gp/T/db3b08fc4a9ef609cb16b96b200fa13e563f396e9bb1ed0905fdab7bc3bc513b.gradle --init-script /var/folders/4d/cv31_tl15q381gddgqqtk94c0000gp/T/52cde0cfcf3e28b8b7510e992210d9614505e0911af0c190bd590d7158574963.gradle
auto.sync=true
build.scans.enabled=false
connection.gradle.distribution=GRADLE_DISTRIBUTION(WRAPPER)
connection.project.dir=
eclipse.preferences.version=1
gradle.user.home=
java.home=/Library/Java/JavaVirtualMachines/jdk-11.jdk/Contents/Home
jvm.arguments=
offline.mode=false
override.workspace.settings=true
show.console.view=true
show.executions.view=true

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8/"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11/"/>
<classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer"/>
<classpathentry kind="output" path="bin/default"/>
</classpath>

View File

@ -20,4 +20,15 @@
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
</natures>
<filteredResources>
<filter>
<id>1689128079519</id>
<name></name>
<type>30</type>
<matcher>
<id>org.eclipse.core.resources.regexFilterMatcher</id>
<arguments>node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__</arguments>
</matcher>
</filter>
</filteredResources>
</projectDescription>

View File

@ -131,10 +131,10 @@ android {
applicationId "th.co.csasset.mobile"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 60
versionName "2.12"
versionCode 100
versionName "2.41"
vectorDrawables.useSupportLibrary = true
}
}
splits {
abi {
reset()
@ -211,6 +211,7 @@ android {
dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation "com.facebook.react:react-native:+" // From node_modules
implementation 'com.facebook.soloader:soloader:0.10.4+'
if (enableHermes) {
def hermesPath = "../../node_modules/hermesvm/android/";
debugImplementation files(hermesPath + "hermes-debug.aar")
@ -236,4 +237,4 @@ task copyDownloadableDepsToLibs(type: Copy) {
apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
apply plugin: 'com.google.gms.google-services'
apply plugin: 'com.google.gms.google-services'

View File

@ -0,0 +1,42 @@
{
"project_info": {
"project_number": "300814322402",
"firebase_url": "https://charoensin-ec628.firebaseio.com",
"project_id": "charoensin-ec628",
"storage_bucket": "charoensin-ec628.appspot.com"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:300814322402:android:61e2ca18a6ba4174",
"android_client_info": {
"package_name": "th.co.csasset.mobile"
}
},
"oauth_client": [
{
"client_id": "300814322402-82gqcb4dte5m2tv1dr2imsf0u7regk87.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyAIXzIwPy-023B3sbDQv42LaxXaSnJcWmU"
}
],
"services": {
"analytics_service": {
"status": 1
},
"appinvite_service": {
"status": 1,
"other_platform_oauth_client": []
},
"ads_service": {
"status": 2
}
}
}
],
"configuration_version": "1"
}

View File

@ -1,42 +1,48 @@
{
"project_info": {
"project_number": "300814322402",
"firebase_url": "https://charoensin-ec628.firebaseio.com",
"project_id": "charoensin-ec628",
"storage_bucket": "charoensin-ec628.appspot.com"
"project_number": "468878476620",
"firebase_url": "https://csasset-mobile.firebaseio.com",
"project_id": "csasset-mobile",
"storage_bucket": "csasset-mobile.appspot.com"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:300814322402:android:61e2ca18a6ba4174",
"mobilesdk_app_id": "1:468878476620:android:61e2ca18a6ba4174",
"android_client_info": {
"package_name": "th.co.csasset.mobile"
}
},
"oauth_client": [
{
"client_id": "300814322402-82gqcb4dte5m2tv1dr2imsf0u7regk87.apps.googleusercontent.com",
"client_id": "468878476620-v3rqr1b2bta862r6q974csuc3rq917ni.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyAIXzIwPy-023B3sbDQv42LaxXaSnJcWmU"
"current_key": "AIzaSyB7o8KiFwABvfyYubdWTcjpm3Y6ciCrO1I"
}
],
"services": {
"analytics_service": {
"status": 1
},
"appinvite_service": {
"status": 1,
"other_platform_oauth_client": []
},
"ads_service": {
"status": 2
"other_platform_oauth_client": [
{
"client_id": "468878476620-v3rqr1b2bta862r6q974csuc3rq917ni.apps.googleusercontent.com",
"client_type": 3
},
{
"client_id": "468878476620-dn0mrhcve5jjpfst3u1vlm4k00uackb6.apps.googleusercontent.com",
"client_type": 2,
"ios_info": {
"bundle_id": "th.co.csasset.mobile",
"app_store_id": "1455804320"
}
}
]
}
}
}
],
"configuration_version": "1"
}
}

Binary file not shown.

View File

@ -1,12 +1,17 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="th.co.csasset.mobile">
xmlns:tools="http://schemas.android.com/tools"
package="th.co.csasset.mobile">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/>
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-feature android:name="android.hardware.camera" android:required="false" />
<uses-feature android:name="android.hardware.camera.front" android:required="false" />
@ -22,23 +27,26 @@
android:name=".MainActivity"
android:label="@string/app_name"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:windowSoftInputMode="adjustResize">
android:windowSoftInputMode="adjustResize"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity"/>
<service android:name="io.invertase.firebase.messaging.RNFirebaseMessagingService">
<!-- <service android:name="io.invertase.firebase.messaging.RNFirebaseMessagingService"
android:exported="true">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT"/>
</intent-filter>
</service>
<service android:name="io.invertase.firebase.messaging.RNFirebaseInstanceIdService">
<service android:name="io.invertase.firebase.messaging.RNFirebaseInstanceIdService"
android:exported="true">
<intent-filter>
<action android:name="com.google.firebase.INSTANCE_ID_EVENT"/>
</intent-filter>
</service>
</service> -->
<meta-data android:name="com.facebook.sdk.ApplicationId"
android:value="@string/facebook_app_id"/>
<activity android:name="com.facebook.FacebookActivity"

View File

@ -15,9 +15,9 @@ import com.learnium.RNDeviceInfo.RNDeviceInfo;
import com.reactnativecommunity.cameraroll.CameraRollPackage;
// Firebase
import io.invertase.firebase.messaging.RNFirebaseMessagingPackage;
import io.invertase.firebase.notifications.RNFirebaseNotificationsPackage;
import io.invertase.firebase.config.RNFirebaseRemoteConfigPackage;
//import io.invertase.firebase.messaging.RNFirebaseMessagingPackage;
//import io.invertase.firebase.notifications.RNFirebaseNotificationsPackage;
//import io.invertase.firebase.config.RNFirebaseRemoteConfigPackage;
import com.facebook.reactnative.androidsdk.FBSDKPackage;
@ -37,9 +37,9 @@ public class MainApplication extends Application implements ReactApplication {
List<ReactPackage> packages = new PackageList(this).getPackages();
// Packages that cannot be autolinked yet can be added manually here, for example:
// packages.add(new MyReactNativePackage());
packages.add(new RNFirebaseNotificationsPackage());
packages.add(new RNFirebaseMessagingPackage());
packages.add(new RNFirebaseRemoteConfigPackage());
// packages.add(new RNFirebaseNotificationsPackage());
// packages.add(new RNFirebaseMessagingPackage());
// packages.add(new RNFirebaseRemoteConfigPackage());
return packages;
}

View File

@ -5,8 +5,9 @@ buildscript {
googlePlayServiceVersion = "17.0.0"
buildToolsVersion = "28.0.3"
minSdkVersion = 21
compileSdkVersion = 28
targetSdkVersion = 28
kotlinVersion = "1.3.72"
compileSdkVersion = 33
targetSdkVersion = 34
}
repositories {
google()
@ -14,9 +15,9 @@ buildscript {
jcenter()
}
dependencies {
classpath("com.android.tools.build:gradle:3.4.1")
classpath 'com.google.gms:google-services:4.2.0'
classpath("com.android.tools.build:gradle:4.0.1")
classpath 'com.google.gms:google-services:4.3.3'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}

View File

@ -1,26 +1,21 @@
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
## For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
#
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
# Default value: -Xmx10248m -XX:MaxPermSize=256m
# Default value: -Xmx1024m -XX:MaxPermSize=256m
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
#
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
android.useAndroidX=true
android.enableJetifier=true
#Tue Jul 11 21:56:44 ICT 2023
MYAPP_RELEASE_STORE_FILE=charoensin.release.keystore
MYAPP_RELEASE_KEY_ALIAS=charoensin
MYAPP_RELEASE_KEY_PASSWORD=aabbccddee
org.gradle.jvmargs=-Xmx2048M -Dkotlin.daemon.jvm.options\="-Xmx2048M"
android.useAndroidX=true
android.enableJetifier=true
MYAPP_RELEASE_STORE_PASSWORD=aabbccddee
MYAPP_RELEASE_KEY_PASSWORD=aabbccddee
android.newArchEnabled=true

View File

@ -1,5 +1,6 @@
#Wed Nov 01 15:44:40 ICT 2023
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-bin.zip
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.5-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME

BIN
android/java_pid37388.hprof Normal file

Binary file not shown.

View File

@ -1,4 +1,10 @@
rootProject.name = 'charoensin'
include ':react-native-webview'
project(':react-native-webview').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-webview/android')
include ':react-native-webview'
project(':react-native-webview').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-webview/android')
include ':react-native-webview'
project(':react-native-webview').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-webview/android')
include ':react-native-device-info'
project(':react-native-device-info').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-device-info/android')
include ':react-native-fbsdk'

Binary file not shown.

After

Width:  |  Height:  |  Size: 579 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 675 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 702 B

BIN
assets/images/logo_5.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 549 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 487 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 575 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 574 B

BIN
assets/images/star_grey.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 590 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 669 B

View File

@ -1,3 +1,6 @@
export default {
API_BASE_URL: 'https://app.csasset.co.th/mobile',
API_BASE_URL_PROD: 'https://app.csasset.co.th/mobile',
WEB_BASE_URL_PROD: 'https://app.csasset.co.th',
API_BASE_URL_DEV: 'https://csa-test.bda.co.th/mobile',
WEB_BASE_URL_DEV: 'https://csa-test.bda.co.th',
}

3
ios/Gemfile Normal file
View File

@ -0,0 +1,3 @@
source "https://rubygems.org"
gem "fastlane"

View File

@ -1,6 +1,8 @@
platform :ios, '9.0'
platform :ios, '13.0'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
xcodeproj 'csareactrn60'
target 'csareactrn60' do
# Pods for csareactrn60
pod 'FBLazyVector', :path => "../node_modules/react-native/Libraries/FBLazyVector"
@ -26,7 +28,7 @@ target 'csareactrn60' do
pod 'React-jsi', :path => '../node_modules/react-native/ReactCommon/jsi'
pod 'React-jsiexecutor', :path => '../node_modules/react-native/ReactCommon/jsiexecutor'
pod 'React-jsinspector', :path => '../node_modules/react-native/ReactCommon/jsinspector'
pod 'ReactCommon/jscallinvoker', :path => "../node_modules/react-native/ReactCommon"
pod 'React-callinvoker', :path => "../node_modules/react-native/ReactCommon/callinvoker"
pod 'ReactCommon/turbomodule/core', :path => "../node_modules/react-native/ReactCommon"
pod 'Yoga', :path => '../node_modules/react-native/ReactCommon/yoga'
@ -41,11 +43,23 @@ target 'csareactrn60' do
pod 'FBSDKLoginKit'
pod 'FBSDKShareKit'
#Firebase
pod 'Firebase/Messaging', '~> 6.8.0'
# Required by RNFirebase
# pod 'RNFirebase', :path => '../node_modules/react-native-firebase/ios'
# pod 'Firebase/Core', '~> 6.13.0'
# pod 'Firebase/Messaging', '~> 6.13.0'
# pod 'Firebase/RemoteConfig', '~> 6.13.0'
pod 'Firebase', :modular_headers => true
pod 'FirebaseCoreInternal', :modular_headers => true
pod 'FirebaseCore', :modular_headers => true
pod 'GoogleUtilities', :modular_headers => true
pod 'react-native-view-shot', :path => '../node_modules/react-native-view-shot'
pod 'RNImageCropPicker', :path => '../node_modules/react-native-image-crop-picker'
use_native_modules!
pod 'RNDeviceInfo', :path => '../node_modules/react-native-device-info'
pod 'react-native-webview', :path => '../node_modules/react-native-webview'
end

View File

@ -1,19 +1,16 @@
PODS:
- boost-for-react-native (1.63.0)
- BVLinearGradient (2.5.6):
- React
- Crashlytics (3.14.0):
- Fabric (~> 1.10.2)
- BVLinearGradient (2.6.2):
- React-Core
- DoubleConversion (1.1.6)
- Fabric (1.10.2)
- FBLazyVector (0.61.5)
- FBReactNativeSpec (0.61.5):
- Folly (= 2018.10.22.00)
- RCTRequired (= 0.61.5)
- RCTTypeSafety (= 0.61.5)
- React-Core (= 0.61.5)
- React-jsi (= 0.61.5)
- ReactCommon/turbomodule/core (= 0.61.5)
- FBLazyVector (0.63.4)
- FBReactNativeSpec (0.63.4):
- Folly (= 2020.01.13.00)
- RCTRequired (= 0.63.4)
- RCTTypeSafety (= 0.63.4)
- React-Core (= 0.63.4)
- React-jsi (= 0.63.4)
- ReactCommon/turbomodule/core (= 0.63.4)
- FBSDKCoreKit (5.8.0):
- FBSDKCoreKit/Basics (= 5.8.0)
- FBSDKCoreKit/Core (= 5.8.0)
@ -28,271 +25,308 @@ PODS:
- FBSDKShareKit/Share (= 5.8.0)
- FBSDKShareKit/Share (5.8.0):
- FBSDKCoreKit (~> 5.0)
- Firebase/Core (6.8.1):
- Firebase (10.6.0):
- Firebase/Core (= 10.6.0)
- Firebase/Core (10.6.0):
- Firebase/CoreOnly
- FirebaseAnalytics (= 6.1.1)
- Firebase/CoreOnly (6.8.1):
- FirebaseCore (= 6.2.3)
- Firebase/Messaging (6.8.1):
- FirebaseAnalytics (~> 10.6.0)
- Firebase/CoreOnly (10.6.0):
- FirebaseCore (= 10.6.0)
- Firebase/Messaging (10.6.0):
- Firebase/CoreOnly
- FirebaseMessaging (~> 4.1.4)
- FirebaseAnalytics (6.1.1):
- FirebaseCore (~> 6.2)
- FirebaseInstanceID (~> 4.2)
- GoogleAppMeasurement (= 6.1.1)
- GoogleUtilities/AppDelegateSwizzler (~> 6.0)
- GoogleUtilities/MethodSwizzler (~> 6.0)
- GoogleUtilities/Network (~> 6.0)
- "GoogleUtilities/NSData+zlib (~> 6.0)"
- nanopb (~> 0.3)
- FirebaseAnalyticsInterop (1.5.0)
- FirebaseCore (6.2.3):
- FirebaseCoreDiagnostics (~> 1.0)
- FirebaseCoreDiagnosticsInterop (~> 1.0)
- GoogleUtilities/Environment (~> 6.2)
- GoogleUtilities/Logger (~> 6.2)
- FirebaseCoreDiagnostics (1.2.4):
- FirebaseCoreDiagnosticsInterop (~> 1.2)
- GoogleDataTransportCCTSupport (~> 3.0)
- GoogleUtilities/Environment (~> 6.5)
- GoogleUtilities/Logger (~> 6.5)
- nanopb (~> 0.3.901)
- FirebaseCoreDiagnosticsInterop (1.2.0)
- FirebaseInstanceID (4.2.7):
- FirebaseCore (~> 6.0)
- GoogleUtilities/Environment (~> 6.0)
- GoogleUtilities/UserDefaults (~> 6.0)
- FirebaseMessaging (4.1.10):
- FirebaseAnalyticsInterop (~> 1.3)
- FirebaseCore (~> 6.2)
- FirebaseInstanceID (~> 4.1)
- GoogleUtilities/AppDelegateSwizzler (~> 6.2)
- GoogleUtilities/Environment (~> 6.2)
- GoogleUtilities/Reachability (~> 6.2)
- GoogleUtilities/UserDefaults (~> 6.2)
- Protobuf (>= 3.9.2, ~> 3.9)
- Folly (2018.10.22.00):
- FirebaseMessaging (~> 10.6.0)
- FirebaseAnalytics (10.6.0):
- FirebaseAnalytics/AdIdSupport (= 10.6.0)
- FirebaseCore (~> 10.0)
- FirebaseInstallations (~> 10.0)
- GoogleUtilities/AppDelegateSwizzler (~> 7.8)
- GoogleUtilities/MethodSwizzler (~> 7.8)
- GoogleUtilities/Network (~> 7.8)
- "GoogleUtilities/NSData+zlib (~> 7.8)"
- nanopb (< 2.30910.0, >= 2.30908.0)
- FirebaseAnalytics/AdIdSupport (10.6.0):
- FirebaseCore (~> 10.0)
- FirebaseInstallations (~> 10.0)
- GoogleAppMeasurement (= 10.6.0)
- GoogleUtilities/AppDelegateSwizzler (~> 7.8)
- GoogleUtilities/MethodSwizzler (~> 7.8)
- GoogleUtilities/Network (~> 7.8)
- "GoogleUtilities/NSData+zlib (~> 7.8)"
- nanopb (< 2.30910.0, >= 2.30908.0)
- FirebaseCore (10.6.0):
- FirebaseCoreInternal (~> 10.0)
- GoogleUtilities/Environment (~> 7.8)
- GoogleUtilities/Logger (~> 7.8)
- FirebaseCoreExtension (10.6.0):
- FirebaseCore (~> 10.0)
- FirebaseCoreInternal (10.21.0):
- "GoogleUtilities/NSData+zlib (~> 7.8)"
- FirebaseInstallations (10.21.0):
- FirebaseCore (~> 10.0)
- GoogleUtilities/Environment (~> 7.8)
- GoogleUtilities/UserDefaults (~> 7.8)
- PromisesObjC (~> 2.1)
- FirebaseMessaging (10.6.0):
- FirebaseCore (~> 10.0)
- FirebaseInstallations (~> 10.0)
- GoogleDataTransport (~> 9.2)
- GoogleUtilities/AppDelegateSwizzler (~> 7.8)
- GoogleUtilities/Environment (~> 7.8)
- GoogleUtilities/Reachability (~> 7.8)
- GoogleUtilities/UserDefaults (~> 7.8)
- nanopb (< 2.30910.0, >= 2.30908.0)
- Folly (2020.01.13.00):
- boost-for-react-native
- DoubleConversion
- Folly/Default (= 2018.10.22.00)
- Folly/Default (= 2020.01.13.00)
- glog
- Folly/Default (2018.10.22.00):
- Folly/Default (2020.01.13.00):
- boost-for-react-native
- DoubleConversion
- glog
- glog (0.3.5)
- GoogleAppMeasurement (6.1.1):
- GoogleUtilities/AppDelegateSwizzler (~> 6.0)
- GoogleUtilities/MethodSwizzler (~> 6.0)
- GoogleUtilities/Network (~> 6.0)
- "GoogleUtilities/NSData+zlib (~> 6.0)"
- nanopb (~> 0.3)
- GoogleDataTransport (6.1.0)
- GoogleDataTransportCCTSupport (3.0.0):
- GoogleDataTransport (~> 6.0)
- nanopb (~> 0.3.901)
- GoogleUtilities/AppDelegateSwizzler (6.6.0):
- GoogleAppMeasurement (10.6.0):
- GoogleAppMeasurement/AdIdSupport (= 10.6.0)
- GoogleUtilities/AppDelegateSwizzler (~> 7.8)
- GoogleUtilities/MethodSwizzler (~> 7.8)
- GoogleUtilities/Network (~> 7.8)
- "GoogleUtilities/NSData+zlib (~> 7.8)"
- nanopb (< 2.30910.0, >= 2.30908.0)
- GoogleAppMeasurement/AdIdSupport (10.6.0):
- GoogleAppMeasurement/WithoutAdIdSupport (= 10.6.0)
- GoogleUtilities/AppDelegateSwizzler (~> 7.8)
- GoogleUtilities/MethodSwizzler (~> 7.8)
- GoogleUtilities/Network (~> 7.8)
- "GoogleUtilities/NSData+zlib (~> 7.8)"
- nanopb (< 2.30910.0, >= 2.30908.0)
- GoogleAppMeasurement/WithoutAdIdSupport (10.6.0):
- GoogleUtilities/AppDelegateSwizzler (~> 7.8)
- GoogleUtilities/MethodSwizzler (~> 7.8)
- GoogleUtilities/Network (~> 7.8)
- "GoogleUtilities/NSData+zlib (~> 7.8)"
- nanopb (< 2.30910.0, >= 2.30908.0)
- GoogleDataTransport (9.3.0):
- GoogleUtilities/Environment (~> 7.7)
- nanopb (< 2.30910.0, >= 2.30908.0)
- PromisesObjC (< 3.0, >= 1.2)
- GoogleUtilities (7.12.0):
- GoogleUtilities/AppDelegateSwizzler (= 7.12.0)
- GoogleUtilities/Environment (= 7.12.0)
- GoogleUtilities/ISASwizzler (= 7.12.0)
- GoogleUtilities/Logger (= 7.12.0)
- GoogleUtilities/MethodSwizzler (= 7.12.0)
- GoogleUtilities/Network (= 7.12.0)
- "GoogleUtilities/NSData+zlib (= 7.12.0)"
- GoogleUtilities/Reachability (= 7.12.0)
- GoogleUtilities/SwizzlerTestHelpers (= 7.12.0)
- GoogleUtilities/UserDefaults (= 7.12.0)
- GoogleUtilities/AppDelegateSwizzler (7.12.0):
- GoogleUtilities/Environment
- GoogleUtilities/Logger
- GoogleUtilities/Network
- GoogleUtilities/Environment (6.6.0):
- PromisesObjC (~> 1.2)
- GoogleUtilities/Logger (6.6.0):
- GoogleUtilities/Environment (7.12.0):
- PromisesObjC (< 3.0, >= 1.2)
- GoogleUtilities/ISASwizzler (7.12.0)
- GoogleUtilities/Logger (7.12.0):
- GoogleUtilities/Environment
- GoogleUtilities/MethodSwizzler (6.6.0):
- GoogleUtilities/MethodSwizzler (7.12.0):
- GoogleUtilities/Logger
- GoogleUtilities/Network (6.6.0):
- GoogleUtilities/Network (7.12.0):
- GoogleUtilities/Logger
- "GoogleUtilities/NSData+zlib"
- GoogleUtilities/Reachability
- "GoogleUtilities/NSData+zlib (6.6.0)"
- GoogleUtilities/Reachability (6.6.0):
- "GoogleUtilities/NSData+zlib (7.12.0)"
- GoogleUtilities/Reachability (7.12.0):
- GoogleUtilities/Logger
- GoogleUtilities/UserDefaults (6.6.0):
- GoogleUtilities/SwizzlerTestHelpers (7.12.0):
- GoogleUtilities/MethodSwizzler
- GoogleUtilities/UserDefaults (7.12.0):
- GoogleUtilities/Logger
- libwebp (1.1.0):
- libwebp/demux (= 1.1.0)
- libwebp/mux (= 1.1.0)
- libwebp/webp (= 1.1.0)
- libwebp/demux (1.1.0):
- libwebp (1.3.2):
- libwebp/demux (= 1.3.2)
- libwebp/mux (= 1.3.2)
- libwebp/sharpyuv (= 1.3.2)
- libwebp/webp (= 1.3.2)
- libwebp/demux (1.3.2):
- libwebp/webp
- libwebp/mux (1.1.0):
- libwebp/mux (1.3.2):
- libwebp/demux
- libwebp/webp (1.1.0)
- nanopb (0.3.9011):
- nanopb/decode (= 0.3.9011)
- nanopb/encode (= 0.3.9011)
- nanopb/decode (0.3.9011)
- nanopb/encode (0.3.9011)
- PromisesObjC (1.2.8)
- Protobuf (3.12.0)
- QBImagePickerController (3.4.0)
- RCTRequired (0.61.5)
- RCTTypeSafety (0.61.5):
- FBLazyVector (= 0.61.5)
- Folly (= 2018.10.22.00)
- RCTRequired (= 0.61.5)
- React-Core (= 0.61.5)
- React (0.61.5):
- React-Core (= 0.61.5)
- React-Core/DevSupport (= 0.61.5)
- React-Core/RCTWebSocket (= 0.61.5)
- React-RCTActionSheet (= 0.61.5)
- React-RCTAnimation (= 0.61.5)
- React-RCTBlob (= 0.61.5)
- React-RCTImage (= 0.61.5)
- React-RCTLinking (= 0.61.5)
- React-RCTNetwork (= 0.61.5)
- React-RCTSettings (= 0.61.5)
- React-RCTText (= 0.61.5)
- React-RCTVibration (= 0.61.5)
- React-Core (0.61.5):
- Folly (= 2018.10.22.00)
- libwebp/sharpyuv (1.3.2)
- libwebp/webp (1.3.2):
- libwebp/sharpyuv
- nanopb (2.30909.1):
- nanopb/decode (= 2.30909.1)
- nanopb/encode (= 2.30909.1)
- nanopb/decode (2.30909.1)
- nanopb/encode (2.30909.1)
- PromisesObjC (2.3.1)
- RCTRequired (0.63.4)
- RCTTypeSafety (0.63.4):
- FBLazyVector (= 0.63.4)
- Folly (= 2020.01.13.00)
- RCTRequired (= 0.63.4)
- React-Core (= 0.63.4)
- React (0.63.4):
- React-Core (= 0.63.4)
- React-Core/DevSupport (= 0.63.4)
- React-Core/RCTWebSocket (= 0.63.4)
- React-RCTActionSheet (= 0.63.4)
- React-RCTAnimation (= 0.63.4)
- React-RCTBlob (= 0.63.4)
- React-RCTImage (= 0.63.4)
- React-RCTLinking (= 0.63.4)
- React-RCTNetwork (= 0.63.4)
- React-RCTSettings (= 0.63.4)
- React-RCTText (= 0.63.4)
- React-RCTVibration (= 0.63.4)
- React-callinvoker (0.63.4)
- React-Core (0.63.4):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default (= 0.61.5)
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- React-Core/Default (= 0.63.4)
- React-cxxreact (= 0.63.4)
- React-jsi (= 0.63.4)
- React-jsiexecutor (= 0.63.4)
- Yoga
- React-Core/CoreModulesHeaders (0.61.5):
- Folly (= 2018.10.22.00)
- React-Core/CoreModulesHeaders (0.63.4):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- React-cxxreact (= 0.63.4)
- React-jsi (= 0.63.4)
- React-jsiexecutor (= 0.63.4)
- Yoga
- React-Core/Default (0.61.5):
- Folly (= 2018.10.22.00)
- React-Core/Default (0.63.4):
- Folly (= 2020.01.13.00)
- glog
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- React-cxxreact (= 0.63.4)
- React-jsi (= 0.63.4)
- React-jsiexecutor (= 0.63.4)
- Yoga
- React-Core/DevSupport (0.61.5):
- Folly (= 2018.10.22.00)
- React-Core/DevSupport (0.63.4):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default (= 0.61.5)
- React-Core/RCTWebSocket (= 0.61.5)
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- React-jsinspector (= 0.61.5)
- React-Core/Default (= 0.63.4)
- React-Core/RCTWebSocket (= 0.63.4)
- React-cxxreact (= 0.63.4)
- React-jsi (= 0.63.4)
- React-jsiexecutor (= 0.63.4)
- React-jsinspector (= 0.63.4)
- Yoga
- React-Core/RCTActionSheetHeaders (0.61.5):
- Folly (= 2018.10.22.00)
- React-Core/RCTActionSheetHeaders (0.63.4):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- React-cxxreact (= 0.63.4)
- React-jsi (= 0.63.4)
- React-jsiexecutor (= 0.63.4)
- Yoga
- React-Core/RCTAnimationHeaders (0.61.5):
- Folly (= 2018.10.22.00)
- React-Core/RCTAnimationHeaders (0.63.4):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- React-cxxreact (= 0.63.4)
- React-jsi (= 0.63.4)
- React-jsiexecutor (= 0.63.4)
- Yoga
- React-Core/RCTBlobHeaders (0.61.5):
- Folly (= 2018.10.22.00)
- React-Core/RCTBlobHeaders (0.63.4):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- React-cxxreact (= 0.63.4)
- React-jsi (= 0.63.4)
- React-jsiexecutor (= 0.63.4)
- Yoga
- React-Core/RCTImageHeaders (0.61.5):
- Folly (= 2018.10.22.00)
- React-Core/RCTImageHeaders (0.63.4):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- React-cxxreact (= 0.63.4)
- React-jsi (= 0.63.4)
- React-jsiexecutor (= 0.63.4)
- Yoga
- React-Core/RCTLinkingHeaders (0.61.5):
- Folly (= 2018.10.22.00)
- React-Core/RCTLinkingHeaders (0.63.4):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- React-cxxreact (= 0.63.4)
- React-jsi (= 0.63.4)
- React-jsiexecutor (= 0.63.4)
- Yoga
- React-Core/RCTNetworkHeaders (0.61.5):
- Folly (= 2018.10.22.00)
- React-Core/RCTNetworkHeaders (0.63.4):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- React-cxxreact (= 0.63.4)
- React-jsi (= 0.63.4)
- React-jsiexecutor (= 0.63.4)
- Yoga
- React-Core/RCTSettingsHeaders (0.61.5):
- Folly (= 2018.10.22.00)
- React-Core/RCTSettingsHeaders (0.63.4):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- React-cxxreact (= 0.63.4)
- React-jsi (= 0.63.4)
- React-jsiexecutor (= 0.63.4)
- Yoga
- React-Core/RCTTextHeaders (0.61.5):
- Folly (= 2018.10.22.00)
- React-Core/RCTTextHeaders (0.63.4):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- React-cxxreact (= 0.63.4)
- React-jsi (= 0.63.4)
- React-jsiexecutor (= 0.63.4)
- Yoga
- React-Core/RCTVibrationHeaders (0.61.5):
- Folly (= 2018.10.22.00)
- React-Core/RCTVibrationHeaders (0.63.4):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- React-cxxreact (= 0.63.4)
- React-jsi (= 0.63.4)
- React-jsiexecutor (= 0.63.4)
- Yoga
- React-Core/RCTWebSocket (0.61.5):
- Folly (= 2018.10.22.00)
- React-Core/RCTWebSocket (0.63.4):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default (= 0.61.5)
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- React-Core/Default (= 0.63.4)
- React-cxxreact (= 0.63.4)
- React-jsi (= 0.63.4)
- React-jsiexecutor (= 0.63.4)
- Yoga
- React-CoreModules (0.61.5):
- FBReactNativeSpec (= 0.61.5)
- Folly (= 2018.10.22.00)
- RCTTypeSafety (= 0.61.5)
- React-Core/CoreModulesHeaders (= 0.61.5)
- React-RCTImage (= 0.61.5)
- ReactCommon/turbomodule/core (= 0.61.5)
- React-cxxreact (0.61.5):
- React-CoreModules (0.63.4):
- FBReactNativeSpec (= 0.63.4)
- Folly (= 2020.01.13.00)
- RCTTypeSafety (= 0.63.4)
- React-Core/CoreModulesHeaders (= 0.63.4)
- React-jsi (= 0.63.4)
- React-RCTImage (= 0.63.4)
- ReactCommon/turbomodule/core (= 0.63.4)
- React-cxxreact (0.63.4):
- boost-for-react-native (= 1.63.0)
- DoubleConversion
- Folly (= 2018.10.22.00)
- Folly (= 2020.01.13.00)
- glog
- React-jsinspector (= 0.61.5)
- React-jsi (0.61.5):
- React-callinvoker (= 0.63.4)
- React-jsinspector (= 0.63.4)
- React-jsi (0.63.4):
- boost-for-react-native (= 1.63.0)
- DoubleConversion
- Folly (= 2018.10.22.00)
- Folly (= 2020.01.13.00)
- glog
- React-jsi/Default (= 0.61.5)
- React-jsi/Default (0.61.5):
- React-jsi/Default (= 0.63.4)
- React-jsi/Default (0.63.4):
- boost-for-react-native (= 1.63.0)
- DoubleConversion
- Folly (= 2018.10.22.00)
- Folly (= 2020.01.13.00)
- glog
- React-jsiexecutor (0.61.5):
- React-jsiexecutor (0.63.4):
- DoubleConversion
- Folly (= 2018.10.22.00)
- Folly (= 2020.01.13.00)
- glog
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsinspector (0.61.5)
- react-native-appearance (0.2.4):
- React
- react-native-cameraroll (1.6.2):
- React-cxxreact (= 0.63.4)
- React-jsi (= 0.63.4)
- React-jsinspector (0.63.4)
- react-native-cameraroll (1.8.1):
- React
- react-native-fbsdk (1.1.2):
- React
@ -308,82 +342,114 @@ PODS:
- react-native-fbsdk/Share (1.1.2):
- FBSDKShareKit (= 5.8)
- React
- react-native-splash-screen (3.2.0):
- React
- react-native-view-shot (3.1.2):
- React
- react-native-webview (9.4.0):
- React
- React-RCTActionSheet (0.61.5):
- React-Core/RCTActionSheetHeaders (= 0.61.5)
- React-RCTAnimation (0.61.5):
- React-Core/RCTAnimationHeaders (= 0.61.5)
- React-RCTBlob (0.61.5):
- React-Core/RCTBlobHeaders (= 0.61.5)
- React-Core/RCTWebSocket (= 0.61.5)
- React-jsi (= 0.61.5)
- React-RCTNetwork (= 0.61.5)
- React-RCTImage (0.61.5):
- React-Core/RCTImageHeaders (= 0.61.5)
- React-RCTNetwork (= 0.61.5)
- React-RCTLinking (0.61.5):
- React-Core/RCTLinkingHeaders (= 0.61.5)
- React-RCTNetwork (0.61.5):
- React-Core/RCTNetworkHeaders (= 0.61.5)
- React-RCTSettings (0.61.5):
- React-Core/RCTSettingsHeaders (= 0.61.5)
- React-RCTText (0.61.5):
- React-Core/RCTTextHeaders (= 0.61.5)
- React-RCTVibration (0.61.5):
- React-Core/RCTVibrationHeaders (= 0.61.5)
- ReactCommon/jscallinvoker (0.61.5):
- react-native-splash-screen (3.3.0):
- React-Core
- react-native-view-shot (3.4.0):
- React-Core
- react-native-webview (11.23.0):
- React-Core
- React-RCTActionSheet (0.63.4):
- React-Core/RCTActionSheetHeaders (= 0.63.4)
- React-RCTAnimation (0.63.4):
- FBReactNativeSpec (= 0.63.4)
- Folly (= 2020.01.13.00)
- RCTTypeSafety (= 0.63.4)
- React-Core/RCTAnimationHeaders (= 0.63.4)
- React-jsi (= 0.63.4)
- ReactCommon/turbomodule/core (= 0.63.4)
- React-RCTBlob (0.63.4):
- FBReactNativeSpec (= 0.63.4)
- Folly (= 2020.01.13.00)
- React-Core/RCTBlobHeaders (= 0.63.4)
- React-Core/RCTWebSocket (= 0.63.4)
- React-jsi (= 0.63.4)
- React-RCTNetwork (= 0.63.4)
- ReactCommon/turbomodule/core (= 0.63.4)
- React-RCTImage (0.63.4):
- FBReactNativeSpec (= 0.63.4)
- Folly (= 2020.01.13.00)
- RCTTypeSafety (= 0.63.4)
- React-Core/RCTImageHeaders (= 0.63.4)
- React-jsi (= 0.63.4)
- React-RCTNetwork (= 0.63.4)
- ReactCommon/turbomodule/core (= 0.63.4)
- React-RCTLinking (0.63.4):
- FBReactNativeSpec (= 0.63.4)
- React-Core/RCTLinkingHeaders (= 0.63.4)
- React-jsi (= 0.63.4)
- ReactCommon/turbomodule/core (= 0.63.4)
- React-RCTNetwork (0.63.4):
- FBReactNativeSpec (= 0.63.4)
- Folly (= 2020.01.13.00)
- RCTTypeSafety (= 0.63.4)
- React-Core/RCTNetworkHeaders (= 0.63.4)
- React-jsi (= 0.63.4)
- ReactCommon/turbomodule/core (= 0.63.4)
- React-RCTSettings (0.63.4):
- FBReactNativeSpec (= 0.63.4)
- Folly (= 2020.01.13.00)
- RCTTypeSafety (= 0.63.4)
- React-Core/RCTSettingsHeaders (= 0.63.4)
- React-jsi (= 0.63.4)
- ReactCommon/turbomodule/core (= 0.63.4)
- React-RCTText (0.63.4):
- React-Core/RCTTextHeaders (= 0.63.4)
- React-RCTVibration (0.63.4):
- FBReactNativeSpec (= 0.63.4)
- Folly (= 2020.01.13.00)
- React-Core/RCTVibrationHeaders (= 0.63.4)
- React-jsi (= 0.63.4)
- ReactCommon/turbomodule/core (= 0.63.4)
- ReactCommon/turbomodule/core (0.63.4):
- DoubleConversion
- Folly (= 2018.10.22.00)
- Folly (= 2020.01.13.00)
- glog
- React-cxxreact (= 0.61.5)
- ReactCommon/turbomodule/core (0.61.5):
- DoubleConversion
- Folly (= 2018.10.22.00)
- glog
- React-Core (= 0.61.5)
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- ReactCommon/jscallinvoker (= 0.61.5)
- RNDeviceInfo (5.5.8):
- React-callinvoker (= 0.63.4)
- React-Core (= 0.63.4)
- React-cxxreact (= 0.63.4)
- React-jsi (= 0.63.4)
- RNAppleAuthentication (1.1.2):
- React
- RNFastImage (8.1.5):
- RNDeviceInfo (5.6.5):
- React
- SDWebImage (~> 5.0)
- SDWebImageWebPCoder (~> 0.4.1)
- RNFirebase (5.6.0):
- Firebase/Core
- React
- RNFirebase/Crashlytics (= 5.6.0)
- RNFirebase/Crashlytics (5.6.0):
- Crashlytics
- Fabric
- Firebase/Core
- React
- RNGestureHandler (1.6.1):
- React
- RNImageCropPicker (0.25.3):
- QBImagePickerController
- RNFastImage (8.6.0):
- React-Core
- SDWebImage (~> 5.11.1)
- SDWebImageWebPCoder (~> 0.8.4)
- RNFBApp (17.3.2):
- Firebase/CoreOnly (= 10.6.0)
- React-Core
- RNFBMessaging (17.3.2):
- Firebase/Messaging (= 10.6.0)
- FirebaseCoreExtension (= 10.6.0)
- React-Core
- RNFBApp
- RNGestureHandler (1.10.3):
- React-Core
- RNImageCropPicker (0.32.3):
- React-Core
- React-RCTImage
- RSKImageCropper
- RNScreens (2.7.0):
- React
- RNImageCropPicker/QBImagePickerController (= 0.32.3)
- TOCropViewController
- RNImageCropPicker/QBImagePickerController (0.32.3):
- React-Core
- React-RCTImage
- TOCropViewController
- RNScreens (2.18.1):
- React-Core
- RNSVG (9.13.6):
- React
- RNVectorIcons (6.6.0):
- RNVectorIcons (6.7.0):
- React
- RSKImageCropper (2.2.3)
- SDWebImage (5.8.0):
- SDWebImage/Core (= 5.8.0)
- SDWebImage/Core (5.8.0)
- SDWebImageWebPCoder (0.4.1):
- SDWebImage (5.11.1):
- SDWebImage/Core (= 5.11.1)
- SDWebImage/Core (5.11.1)
- SDWebImageWebPCoder (0.8.5):
- libwebp (~> 1.0)
- SDWebImage/Core (~> 5.5)
- SDWebImage/Core (~> 5.10)
- TOCropViewController (2.6.1)
- toolbar-android (0.2.1):
- React
- Yoga (1.14.0)
DEPENDENCIES:
@ -394,12 +460,16 @@ DEPENDENCIES:
- FBSDKCoreKit
- FBSDKLoginKit
- FBSDKShareKit
- Firebase/Messaging (~> 6.8.0)
- Firebase
- FirebaseCore
- FirebaseCoreInternal
- Folly (from `../node_modules/react-native/third-party-podspecs/Folly.podspec`)
- glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`)
- GoogleUtilities
- RCTRequired (from `../node_modules/react-native/Libraries/RCTRequired`)
- RCTTypeSafety (from `../node_modules/react-native/Libraries/TypeSafety`)
- React (from `../node_modules/react-native/`)
- React-callinvoker (from `../node_modules/react-native/ReactCommon/callinvoker`)
- React-Core (from `../node_modules/react-native/`)
- React-Core/DevSupport (from `../node_modules/react-native/`)
- React-Core/RCTWebSocket (from `../node_modules/react-native/`)
@ -408,7 +478,6 @@ DEPENDENCIES:
- React-jsi (from `../node_modules/react-native/ReactCommon/jsi`)
- React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`)
- React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector`)
- react-native-appearance (from `../node_modules/react-native-appearance`)
- "react-native-cameraroll (from `../node_modules/@react-native-community/cameraroll`)"
- react-native-fbsdk (from `../node_modules/react-native-fbsdk`)
- react-native-splash-screen (from `../node_modules/react-native-splash-screen`)
@ -423,46 +492,42 @@ DEPENDENCIES:
- React-RCTSettings (from `../node_modules/react-native/Libraries/Settings`)
- React-RCTText (from `../node_modules/react-native/Libraries/Text`)
- React-RCTVibration (from `../node_modules/react-native/Libraries/Vibration`)
- ReactCommon/jscallinvoker (from `../node_modules/react-native/ReactCommon`)
- ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`)
- "RNAppleAuthentication (from `../node_modules/@invertase/react-native-apple-authentication`)"
- RNDeviceInfo (from `../node_modules/react-native-device-info`)
- RNFastImage (from `../node_modules/react-native-fast-image`)
- RNFirebase (from `../node_modules/react-native-firebase/ios`)
- "RNFBApp (from `../node_modules/@react-native-firebase/app`)"
- "RNFBMessaging (from `../node_modules/@react-native-firebase/messaging`)"
- RNGestureHandler (from `../node_modules/react-native-gesture-handler`)
- RNImageCropPicker (from `../node_modules/react-native-image-crop-picker`)
- RNScreens (from `../node_modules/react-native-screens`)
- RNSVG (from `../node_modules/react-native-svg`)
- RNVectorIcons (from `../node_modules/react-native-vector-icons`)
- "toolbar-android (from `../node_modules/@react-native-community/toolbar-android`)"
- Yoga (from `../node_modules/react-native/ReactCommon/yoga`)
SPEC REPOS:
trunk:
- boost-for-react-native
- Crashlytics
- Fabric
- FBSDKCoreKit
- FBSDKLoginKit
- FBSDKShareKit
- Firebase
- FirebaseAnalytics
- FirebaseAnalyticsInterop
- FirebaseCore
- FirebaseCoreDiagnostics
- FirebaseCoreDiagnosticsInterop
- FirebaseInstanceID
- FirebaseCoreExtension
- FirebaseCoreInternal
- FirebaseInstallations
- FirebaseMessaging
- GoogleAppMeasurement
- GoogleDataTransport
- GoogleDataTransportCCTSupport
- GoogleUtilities
- libwebp
- nanopb
- PromisesObjC
- Protobuf
- QBImagePickerController
- RSKImageCropper
- SDWebImage
- SDWebImageWebPCoder
- TOCropViewController
EXTERNAL SOURCES:
BVLinearGradient:
@ -483,6 +548,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/Libraries/TypeSafety"
React:
:path: "../node_modules/react-native/"
React-callinvoker:
:path: "../node_modules/react-native/ReactCommon/callinvoker"
React-Core:
:path: "../node_modules/react-native/"
React-CoreModules:
@ -495,8 +562,6 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon/jsiexecutor"
React-jsinspector:
:path: "../node_modules/react-native/ReactCommon/jsinspector"
react-native-appearance:
:path: "../node_modules/react-native-appearance"
react-native-cameraroll:
:path: "../node_modules/@react-native-community/cameraroll"
react-native-fbsdk:
@ -527,12 +592,16 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/Libraries/Vibration"
ReactCommon:
:path: "../node_modules/react-native/ReactCommon"
RNAppleAuthentication:
:path: "../node_modules/@invertase/react-native-apple-authentication"
RNDeviceInfo:
:path: "../node_modules/react-native-device-info"
RNFastImage:
:path: "../node_modules/react-native-fast-image"
RNFirebase:
:path: "../node_modules/react-native-firebase/ios"
RNFBApp:
:path: "../node_modules/@react-native-firebase/app"
RNFBMessaging:
:path: "../node_modules/@react-native-firebase/messaging"
RNGestureHandler:
:path: "../node_modules/react-native-gesture-handler"
RNImageCropPicker:
@ -543,77 +612,76 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native-svg"
RNVectorIcons:
:path: "../node_modules/react-native-vector-icons"
toolbar-android:
:path: "../node_modules/@react-native-community/toolbar-android"
Yoga:
:path: "../node_modules/react-native/ReactCommon/yoga"
SPEC CHECKSUMS:
boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
BVLinearGradient: e3aad03778a456d77928f594a649e96995f1c872
Crashlytics: 540b7e5f5da5a042647227a5e3ac51d85eed06df
DoubleConversion: 5805e889d232975c086db112ece9ed034df7a0b2
Fabric: 706c8b8098fff96c33c0db69cbf81f9c551d0d74
FBLazyVector: aaeaf388755e4f29cd74acbc9e3b8da6d807c37f
FBReactNativeSpec: 118d0d177724c2d67f08a59136eb29ef5943ec75
BVLinearGradient: 34a999fda29036898a09c6a6b728b0b4189e1a44
DoubleConversion: cde416483dac037923206447da6e1454df403714
FBLazyVector: 3bb422f41b18121b71783a905c10e58606f7dc3e
FBReactNativeSpec: f2c97f2529dd79c083355182cc158c9f98f4bd6e
FBSDKCoreKit: e7dcac0aabcfb09d0166998edd95fe3b05a0ce5d
FBSDKLoginKit: 1b0cf04df0370b37404213157b060d6666ede814
FBSDKShareKit: abc29e1bb4f9f59f679adf1ae191006d68455f96
Firebase: 9cbe4e5b5eaafa05dc932be58b7c8c3820d71e88
FirebaseAnalytics: 843c7f64a8f9c79f0d03281197ebe7bb1d58d477
FirebaseAnalyticsInterop: 3f86269c38ae41f47afeb43ebf32a001f58fcdae
FirebaseCore: e9d9bd1dae61c1e82bc1e0e617a9d832392086a0
FirebaseCoreDiagnostics: b59c024493a409f8aecba02c99928d0d8431d159
FirebaseCoreDiagnosticsInterop: 296e2c5f5314500a850ad0b83e9e7c10b011a850
FirebaseInstanceID: ebd2ea79ee38db0cb5f5167b17a0d387e1cc7b6e
FirebaseMessaging: 089b7a4991425783384acc8bcefcd78c0af913bd
Folly: 30e7936e1c45c08d884aa59369ed951a8e68cf51
glog: 1f3da668190260b06b429bb211bfbee5cd790c28
GoogleAppMeasurement: 86a82f0e1f20b8eedf8e20326530138fd71409de
GoogleDataTransport: f6f8eba931df03ebd2232ff4645aa85f8f47b5ab
GoogleDataTransportCCTSupport: 0f39025e8cf51f168711bd3fb773938d7e62ddb5
GoogleUtilities: 39530bc0ad980530298e9c4af8549e991fd033b1
libwebp: 946cb3063cea9236285f7e9a8505d806d30e07f3
nanopb: 18003b5e52dab79db540fe93fe9579f399bd1ccd
PromisesObjC: c119f3cd559f50b7ae681fa59dc1acd19173b7e6
Protobuf: 2793fcd0622a00b546c60e7cbbcc493e043e9bb9
QBImagePickerController: d54cf93db6decf26baf6ed3472f336ef35cae022
RCTRequired: b153add4da6e7dbc44aebf93f3cf4fcae392ddf1
RCTTypeSafety: 9aa1b91d7f9310fc6eadc3cf95126ffe818af320
React: b6a59ef847b2b40bb6e0180a97d0ca716969ac78
React-Core: 688b451f7d616cc1134ac95295b593d1b5158a04
React-CoreModules: d04f8494c1a328b69ec11db9d1137d667f916dcb
React-cxxreact: d0f7bcafa196ae410e5300736b424455e7fb7ba7
React-jsi: cb2cd74d7ccf4cffb071a46833613edc79cdf8f7
React-jsiexecutor: d5525f9ed5f782fdbacb64b9b01a43a9323d2386
React-jsinspector: fa0ecc501688c3c4c34f28834a76302233e29dc0
react-native-appearance: ea4a65c382cff00249abbeed09bda9a7b5e16ca8
react-native-cameraroll: ac69828fc43b9dbf92149714fd739577d38e4448
Firebase: f13680471b021937f2230ea8503c7809d8c29806
FirebaseAnalytics: 9f382605c5ee412b039212f054bf7a403d9850c1
FirebaseCore: fa80ad16a62d52f67274b5b88304c3a318bbf9a4
FirebaseCoreExtension: 318e5ee9ad4092b00423c2bddd51c3f5c3585973
FirebaseCoreInternal: 43c1788eaeee9d1b97caaa751af567ce11010d00
FirebaseInstallations: 390ea1d10a4d02b20c965cbfd527ee9b3b412acb
FirebaseMessaging: fd93783258c53ae5cdb9b41bf0c51606a677f2d5
Folly: b73c3869541e86821df3c387eb0af5f65addfab4
glog: 40a13f7840415b9a77023fbcae0f1e6f43192af3
GoogleAppMeasurement: 686b48c3c895f3c55c70719041913d5d150b74f6
GoogleDataTransport: 57c22343ab29bc686febbf7cbb13bad167c2d8fe
GoogleUtilities: 0759d1a57ebb953965c2dfe0ba4c82e95ccc2e34
libwebp: 1786c9f4ff8a279e4dac1e8f385004d5fc253009
nanopb: d4d75c12cd1316f4a64e3c6963f879ecd4b5e0d5
PromisesObjC: c50d2056b5253dadbd6c2bea79b0674bd5a52fa4
RCTRequired: 082f10cd3f905d6c124597fd1c14f6f2655ff65e
RCTTypeSafety: 8c9c544ecbf20337d069e4ae7fd9a377aadf504b
React: b0a957a2c44da4113b0c4c9853d8387f8e64e615
React-callinvoker: c3f44dd3cb195b6aa46621fff95ded79d59043fe
React-Core: d3b2a1ac9a2c13c3bcde712d9281fc1c8a5b315b
React-CoreModules: 0581ff36cb797da0943d424f69e7098e43e9be60
React-cxxreact: c1480d4fda5720086c90df537ee7d285d4c57ac3
React-jsi: a0418934cf48f25b485631deb27c64dc40fb4c31
React-jsiexecutor: 93bd528844ad21dc07aab1c67cb10abae6df6949
React-jsinspector: 58aef7155bc9a9683f5b60b35eccea8722a4f53a
react-native-cameraroll: e2917a5e62da9f10c3d525e157e25e694d2d6dfa
react-native-fbsdk: c35d42169e64aaf66f01713c1e18d0674f7f6519
react-native-splash-screen: 200d11d188e2e78cea3ad319964f6142b6384865
react-native-view-shot: 4475fde003fe8a210053d1f98fb9e06c1d834e1c
react-native-webview: cf5527893252b3b036eea024a1da6996f7344c74
React-RCTActionSheet: 600b4d10e3aea0913b5a92256d2719c0cdd26d76
React-RCTAnimation: 791a87558389c80908ed06cc5dfc5e7920dfa360
React-RCTBlob: d89293cc0236d9cb0933d85e430b0bbe81ad1d72
React-RCTImage: 6b8e8df449eb7c814c99a92d6b52de6fe39dea4e
React-RCTLinking: 121bb231c7503cf9094f4d8461b96a130fabf4a5
React-RCTNetwork: fb353640aafcee84ca8b78957297bd395f065c9a
React-RCTSettings: 8db258ea2a5efee381fcf7a6d5044e2f8b68b640
React-RCTText: 9ccc88273e9a3aacff5094d2175a605efa854dbe
React-RCTVibration: a49a1f42bf8f5acf1c3e297097517c6b3af377ad
ReactCommon: 198c7c8d3591f975e5431bec1b0b3b581aa1c5dd
RNDeviceInfo: 655265668063a05fff096c6819da0b7289753ef7
RNFastImage: 35ae972d6727c84ee3f5c6897e07f84d0a3445e9
RNFirebase: 37daa9a346d070f9f6ee1f3b4aaf4c8e3b1d5d1c
RNGestureHandler: 8f09cd560f8d533eb36da5a6c5a843af9f056b38
RNImageCropPicker: bfb3ea9c8622f290532e2fe63f369e0d5a52f597
RNScreens: cf198f915f8a2bf163de94ca9f5bfc8d326c3706
react-native-splash-screen: 4312f786b13a81b5169ef346d76d33bc0c6dc457
react-native-view-shot: a60a98a18c72bcaaaf2138f9aab960ae9b0d96c7
react-native-webview: e771bc375f789ebfa02a26939a57dbc6fa897336
React-RCTActionSheet: 89a0ca9f4a06c1f93c26067af074ccdce0f40336
React-RCTAnimation: 1bde3ecc0c104c55df246eda516e0deb03c4e49b
React-RCTBlob: a97d378b527740cc667e03ebfa183a75231ab0f0
React-RCTImage: c1b1f2d3f43a4a528c8946d6092384b5c880d2f0
React-RCTLinking: 35ae4ab9dc0410d1fcbdce4d7623194a27214fb2
React-RCTNetwork: 29ec2696f8d8cfff7331fac83d3e893c95ef43ae
React-RCTSettings: 60f0691bba2074ef394f95d4c2265ec284e0a46a
React-RCTText: 5c51df3f08cb9dedc6e790161195d12bac06101c
React-RCTVibration: ae4f914cfe8de7d4de95ae1ea6cc8f6315d73d9d
ReactCommon: 73d79c7039f473b76db6ff7c6b159c478acbbb3b
RNAppleAuthentication: 473b2c076f1a48a537610580a168c1fb6d0a90c6
RNDeviceInfo: c5f8f3a456adcbba405ace475254b08febc4c095
RNFastImage: 72a2d5802adef70f8e42fce486f78878f8b47dae
RNFBApp: 3bf62629c41ef65d82e763c25aeb77cdfa63bfae
RNFBMessaging: c2bf85653cdb745f60d3cc43c9ec51d4edca0c52
RNGestureHandler: a479ebd5ed4221a810967000735517df0d2db211
RNImageCropPicker: 54e5ea3d0e298ed51e1441a2fa0a0e7c90ee256d
RNScreens: f7ad633b2e0190b77b6a7aab7f914fad6f198d8d
RNSVG: 8ba35cbeb385a52fd960fd28db9d7d18b4c2974f
RNVectorIcons: 0bb4def82230be1333ddaeee9fcba45f0b288ed4
RSKImageCropper: a446db0e8444a036b34f3c43db01b2373baa4b2a
SDWebImage: 84000f962cbfa70c07f19d2234cbfcf5d779b5dc
SDWebImageWebPCoder: 36f8f47bd9879a8aea6044765c1351120fd8e3a8
Yoga: f2a7cd4280bfe2cca5a7aed98ba0eb3d1310f18b
RNVectorIcons: 368d6d8b8301224e5ffb6254191f4f8876c2be0d
SDWebImage: a7f831e1a65eb5e285e3fb046a23fcfbf08e696d
SDWebImageWebPCoder: 908b83b6adda48effe7667cd2b7f78c897e5111d
TOCropViewController: edfd4f25713d56905ad1e0b9f5be3fbe0f59c863
toolbar-android: 2a73856e98b750d7e71ce4644d3f41cc98211719
Yoga: 4bd86afe9883422a7c4028c00e34790f560923d6
PODFILE CHECKSUM: 1047c93f57a8f62051dd231435a5bc47724c02f4
PODFILE CHECKSUM: 32319a64411dce4ba1e64a703ce66a093746e5af
COCOAPODS: 1.8.4
COCOAPODS: 1.15.2

12
ios/PrivacyInfo.xcprivacy Normal file
View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<!--
PrivacyInfo.xcprivacy
csareactrn60
Created by Kumpor on 12/3/2568 BE.
Copyright (c) 2568 BE Facebook. All rights reserved.
-->
<plist version="1.0">
<dict/>
</plist>

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0940"
LastUpgradeVersion = "1120"
version = "1.3">
<BuildAction
parallelizeBuildables = "NO"
@ -55,6 +55,15 @@
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "2D02E47A1E0B4A5D006451C7"
BuildableName = "csareactrn60-tvOS.app"
BlueprintName = "csareactrn60-tvOS"
ReferencedContainer = "container:csareactrn60.xcodeproj">
</BuildableReference>
</MacroExpansion>
<Testables>
<TestableReference
skipped = "NO">
@ -67,17 +76,6 @@
</BuildableReference>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "2D02E47A1E0B4A5D006451C7"
BuildableName = "csareactrn60-tvOS.app"
BlueprintName = "csareactrn60-tvOS"
ReferencedContainer = "container:csareactrn60.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
@ -99,8 +97,6 @@
ReferencedContainer = "container:csareactrn60.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0940"
LastUpgradeVersion = "1120"
version = "1.3">
<BuildAction
parallelizeBuildables = "NO"
@ -55,6 +55,15 @@
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "csareactrn60.app"
BlueprintName = "csareactrn60"
ReferencedContainer = "container:csareactrn60.xcodeproj">
</BuildableReference>
</MacroExpansion>
<Testables>
<TestableReference
skipped = "NO">
@ -67,17 +76,6 @@
</BuildableReference>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "csareactrn60.app"
BlueprintName = "csareactrn60"
ReferencedContainer = "container:csareactrn60.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
@ -99,8 +97,6 @@
ReferencedContainer = "container:csareactrn60.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"

View File

@ -4,5 +4,9 @@
<dict>
<key>aps-environment</key>
<string>development</string>
<key>com.apple.developer.applesignin</key>
<array>
<string>Default</string>
</array>
</dict>
</plist>

8
ios/fastlane/Appfile Normal file
View File

@ -0,0 +1,8 @@
app_identifier("th.co.csasset.mobile") # The bundle identifier of your app
apple_id("btanawut@gmail.com") # Your Apple email address
itc_team_id("120264177") # App Store Connect Team ID
team_id("84F3R56BUC") # Developer Portal Team ID
# For more information about the Appfile, see:
# https://docs.fastlane.tools/advanced/#appfile

27
ios/fastlane/Fastfile Normal file
View File

@ -0,0 +1,27 @@
# This file contains the fastlane.tools configuration
# You can find the documentation at https://docs.fastlane.tools
#
# For a list of all available actions, check out
#
# https://docs.fastlane.tools/actions
#
# For a list of all available plugins, check out
#
# https://docs.fastlane.tools/plugins/available-plugins
#
# Uncomment the line if you want fastlane to automatically update itself
# update_fastlane
default_platform(:ios)
platform :ios do
desc "Push a new beta build to TestFlight"
lane :beta do
increment_build_number(xcodeproj: "csareactrn60.xcodeproj")
build_app(workspace: "csareactrn60.xcworkspace", scheme: "csareactrn60")
upload_to_testflight(
skip_waiting_for_build_processing:true
)
end
end

View File

@ -9,7 +9,9 @@
"postinstall": "sh ./fix.sh",
"prod-android": "cd android && ./gradlew assembleRelease",
"run-android": "react-native run-android",
"run-ios": "react-native run-ios --simulator \"iPhone 11\""
"run-ios": "react-native run-ios --simulator \"iPhone 14 Pro Max\"",
"run-device": "react-native run-ios --device",
"ios": "react-native run-ios --simulator \"iPhone 14 Pro Max\""
},
"rnpm": {
"assets": [
@ -18,27 +20,31 @@
]
},
"dependencies": {
"@invertase/react-native-apple-authentication": "^1.1.2",
"@react-native-community/cameraroll": "^1.2.1",
"@react-native-community/picker": "^1.8.1",
"@react-native-community/toolbar-android": "0.2.1",
"@react-native-firebase/app": "^17.3.2",
"@react-native-firebase/messaging": "^17.3.2",
"apisauce": "^1.1.0",
"deprecated-react-native-listview": "^0.0.5",
"i18n-js": "^3.5.1",
"intl": "^1.2.5",
"jetifier": "^2.0.0",
"moment": "^2.24.0",
"native-base": "^2.13.8",
"react": "16.9.0",
"react-native": "0.61.5",
"react-native": "^0.63",
"react-native-action-sheet": "^2.2.0",
"react-native-appearance": "^0.2.2",
"react-native-device-info": "^5.5.7",
"react-native-easy-grid": "^0.2.2",
"react-native-elastic-image-slider": "^1.0.0",
"react-native-elements": "^1.2.0",
"react-native-fast-image": "^8.1.5",
"react-native-fbsdk": "^1.1.2",
"react-native-firebase": "^5.5.6",
"react-native-gesture-handler": "^1.4.1",
"react-native-hyperlink": "^0.0.16",
"react-native-image-crop-picker": "0.25.3",
"react-native-image-crop-picker": "0.40.0",
"react-native-image-slider-show": "^1.0.3",
"react-native-image-slideshow": "^1.0.1",
"react-native-image-view": "^2.1.5",
@ -51,18 +57,20 @@
"react-native-screens": "^2.7.0",
"react-native-searchable-dropdown": "^1.1.1",
"react-native-signature-canvas": "^2.4.0",
"react-native-signature-pad": "^0.1.0",
"react-native-snap-carousel": "^3.8.0",
"react-native-splash-screen": "^3.2.0",
"react-native-svg": "^9.9.3",
"react-native-switch-toggle": "^1.1.0",
"react-native-vector-icons": "^6.6.0",
"react-native-view-shot": "^3.0.2",
"react-native-webview": "^9.4.0",
"react-native-webview": "11.23.1",
"react-navigation": "^3.3.0",
"react-redux": "^7.1.1",
"redux": "^4.0.4",
"redux-persist": "^5.10.0",
"redux-persist-transform-encrypt": "^2.0.1"
"redux-persist-transform-encrypt": "^2.0.1",
"rn-tooltip": "^2.0.0"
},
"devDependencies": {
"@babel/core": "^7.6.0",
@ -71,7 +79,7 @@
"babel-jest": "^24.9.0",
"eslint": "^6.3.0",
"jest": "^24.9.0",
"metro-react-native-babel-preset": "^0.56.0",
"metro-react-native-babel-preset": "^0.59.0",
"react-test-renderer": "16.8.6"
},
"jest": {

View File

@ -21,17 +21,30 @@ export const registerDevice = (pushToken) => {
}
export const register = (user) => {
return Api.post('/register',
user
);
const formData = new FormData()
for (let k in user) {
formData.append(k, user[k])
}
return Api.post('/register', formData );
}
export const login = (params) => {
params = {
...params,
uid: DeviceInfo.getUniqueId(),
brand: DeviceInfo.getBrand(),
model: DeviceInfo.getModel()
}
return Api.post('/login',
params
);
}
export const logout = () => {
return Api.post('/logout');
}
export const dashboard = (params) => {
return Api.get('/me/dashboard');
}
@ -70,9 +83,11 @@ export const roomdetail = (room_id) => {
});
}
export const payment = (user_id) => {
export const payment = (user_id, page, search='') => {
return Api.get('/payment', {
user_id: user_id
user_id,
page,
search
});
}
@ -148,8 +163,8 @@ export const getRepairList = (service_id) => {
return Api.get('/repair');
}
export const getRepairById = (repair_id) => {
return Api.get('/repair/'+repair_id);
export const getRepairById = (repair_id, type = '') => {
return Api.get(`/repair/${repair_id}?self_room=${(type === 'effect_responsible' ? 'true' : 'false')}`);
}
export const postRepair = (param) => {
@ -236,3 +251,39 @@ export const disconnectFacebook = (user) => {
user
);
}
export const getRoomParcel = (room_no) => {
return Api.get('/check_room_parcel?room_no='+room_no);
}
export const setPaymentLater = () => {
return Api.get('/set_payment_later')
}
export const setFillInMeterLater = () => {
return Api.get('/set_record_meter_later')
}
export const checkPaymentMeter = () => {
return Api.get('/me/check_payment_meter')
}
export const getRoomUser = () => {
return Api.get('/get_room_user');
}
export function cancelRepair(id) {
return Api.post('/repair/cancel', {id: id})
}
export function postEvaluateRepair(params) {
return Api.post('/repair/point', params)
}
export function setLanguage(language) {
return Api.post('/me/set_language', {language: language})
}
export function requestDeleteAccount() {
return Api.get('/me/request_delete')
}

View File

@ -1,8 +1,7 @@
import { create } from 'apisauce'
import Config from 'src/utils/Config'
import DeviceInfo from 'react-native-device-info'
import { Alert, NetInfo, Platform } from 'react-native'
import NavigationService from 'src/utils/NavigationService'
import { Alert, Platform } from 'react-native'
// import { strings as t } from '../i18n'
// import { userLogout } from 'src/redux/app/action'
@ -11,7 +10,7 @@ import NavigationService from 'src/utils/NavigationService'
let store
const Api = create({
baseURL: Config.API_BASE_URL,
baseURL: Config.API_BASE_URL_PROD,
headers: {
'X-Frame-Options': 'sameorigin',
'X-App-Version': DeviceInfo.getVersion(),
@ -20,6 +19,14 @@ const Api = create({
}
})
export function setBaseUrl (baseUrl) {
Api.setBaseURL(baseUrl)
}
export function setBaseUrlByServerMode (mode) {
Api.setBaseURL(mode === 'production' ? Config.API_BASE_URL_PROD : Config.API_BASE_URL_DEV)
}
DeviceInfo.getDeviceName().then(name => {
Api.setHeader('X-Device-Name', name)
})
@ -29,11 +36,11 @@ Api.addRequestTransform(request => {
})
if (process.env.NODE_ENV !== 'production') {
Api.addRequestTransform(request => {
console.info('--> [' + request.method + '] ' + Api.getBaseURL() + request.url,request.params, request.data)
console.info('header --' + request.url +' -- ', request.headers)
console.info('--> [' + request.method + '] ' + Api.getBaseURL() + request.url, request.params, request.data)
console.info('header --' + request.url + ' -- ', request.headers)
})
Api.addMonitor(response => {
console.info('<-- ' + response.status + ' --- ' + response.config.url,response)
console.info('<-- ' + response.status + ' --- ' + response.config.url, response)
})
}
@ -49,8 +56,7 @@ Api.addMonitor(response => {
case 'SERVER_ERROR':
case 'CANCEL_ERROR':
case 'CLIENT_ERROR': // 4XX
if (response.status === 401) {
// store.dispatch(userLogout)
/*if (response.status === 401) {
Alert.alert('Session timeout', 'Please login again to continue using application', [
{
text: 'ok',
@ -58,20 +64,20 @@ Api.addMonitor(response => {
// NavigationService.navigate('AppLoading')
}
}
], {cancelable: false})
], { cancelable: false })
return
}
}*/
// Alert.alert(null, 'error_getting_data', [{text: 'ok'}])
break
}
}
})
export function setStore(reduxStore) {
export function setStore (reduxStore) {
store = reduxStore
}
export function setToken(token) {
export function setToken (token) {
Api.setHeader('Authorization', 'Bearer ' + token)
}
@ -79,13 +85,13 @@ export function setLanguage (languageCode) {
Api.setHeader('language', languageCode)
}
export function clearToken() {
export function clearToken () {
Api.deleteHeader('Authorization')
}
export function setLocation(lat, lng) {
export function setLocation (lat, lng) {
Api.setHeader('X-Current-Latitude', lat.toString() || '0.0')
Api.setHeader('X-Current-Longitude', lng.toString() || '0.0')
}
export default Api
export default Api

View File

@ -0,0 +1,83 @@
import appleAuth, {
AppleAuthRequestOperation,
AppleAuthRequestScope,
AppleAuthCredentialState,
} from '@invertase/react-native-apple-authentication';
import { setToken } from '../api/api'
import { store } from '../redux/store'
import {appSetToken, appSetUser} from '../redux/app/action';
import {login, register} from '../api/UserApi';
import {Alert} from 'react-native';
export const signinApple = async (onSuccess) => {
try {
const requestOptions = {
requestedOperation: AppleAuthRequestOperation.LOGIN,
requestedScopes: [AppleAuthRequestScope.EMAIL, AppleAuthRequestScope.FULL_NAME],
}
// register({
// ...this.props.user,
// device_id: deviceId
// }).then((res) => {
//
// });
// login
/* const { user } = await appleAuth.performRequest(requestOptions);
console.log(user) */
// register
const appleAuthRequestResponse = await appleAuth.performRequest({
requestedOperation: AppleAuthRequestOperation.LOGIN,
requestedScopes: [AppleAuthRequestScope.EMAIL, AppleAuthRequestScope.FULL_NAME],
})
console.log(appleAuthRequestResponse)
// get current authentication state for user
// /!\ This method must be tested on a real device. On the iOS simulator it always throws an error
// use credentialState response to ensure the user is authenticated
if (AppleAuthCredentialState.AUTHORIZED) {
// user is authenticated
// sent and login
let params = {
identityToken: appleAuthRequestResponse.identityToken,
authorizationCode: appleAuthRequestResponse.authorizationCode,
email_apple: appleAuthRequestResponse.email
}
login(params)
.then(async (res) => {
if(res.status == 500){
Alert.alert('','ไม่สามารถเชื่อมต่อกับเซิฟเวอร์ได้ กรุณาลองใหม่อีกครั้ง')
return
}
if (res.ok) {
if (res.data.token) {
//Alert.alert('Connect with Facebook Success')
setToken(res.data.token)
store.dispatch(appSetToken(res.data.token))
store.dispatch(appSetUser(res.data.user))
onSuccess && onSuccess()
}
} else {
if(res.data.msg != null){
Alert.alert('',res.data.msg)
}
}
})
}
} catch (e) {
console.log(e);
if (e.code === 'ERR_CANCELED') {
// handle that the user canceled the sign-in flow
} else {
// handle other errors
}
}
}

View File

@ -5,6 +5,7 @@ import { login, disconnectFacebook } from '../api/UserApi'
import { store } from '../redux/store'
import { Alert } from 'react-native'
import NavigationService from '../utils/NavigationService';
import messaging from "@react-native-firebase/messaging";
let requestManager = new GraphRequestManager();
@ -33,10 +34,22 @@ export function loginWithFacebook(onSuccess){
);
}
function loginAccessTokenToServer(accessToken,onSuccess){
async function loginAccessTokenToServer(accessToken,onSuccess){
const fcm = messaging()
if (!await fcm.hasPermission()) {
try {
await messaging().requestPermission()
} catch (error) {
}
}
const fcmToken = await messaging().getAPNSToken()
let params = {
access_token: accessToken,
fcm_token: fcmToken
}
login(params)
.then(async (res) => {
if(res.status == 500){
@ -66,13 +79,15 @@ export function logoutFacebook() {
export function disconnectWithFacebook(onSuccess){
AccessToken.getCurrentAccessToken().then(
(data) => {
AccessToken.getCurrentAccessToken()
.then((data) => {
console.log("AccessToken.getCurrentAccessToken():")
console.log(data)
const accessToken = data.accessToken.toString()
let accessToken = null;
if(data && data.accessToken){
accessToken = data.accessToken.toString();
}
//console.log("accessToken:")
//console.log(accessToken)
@ -91,20 +106,7 @@ export function disconnectWithFacebook(onSuccess){
}
if (res.ok) {
Alert.alert('Disconnect with Facebook Success')
// if (res.data.token) {
// setToken(res.data.token)
// store.dispatch(appSetToken(res.data.token))
this.state.user.fb_token = null
this.state.user.fb_is_link = 'f'
//Alert.alert(this.state.user)
//console.log('console.log(this.state.user):')
//console.log(this.state.user)
// store.dispatch(appSetUser(this.state.user))
// store.dispatch(appSetFacebook('f'))
onSuccess && onSuccess()
// }
onSuccess && onSuccess();
} else {
if(res.data.msg != null){
Alert.alert('',res.data.msg)

View File

@ -1,7 +1,7 @@
import React from 'react'
import { TouchableOpacity, View, StyleSheet } from 'react-native'
import React, {useCallback, useRef, useState} from 'react'
import {Modal, StyleSheet, TouchableOpacity, View} from 'react-native'
import Image from 'react-native-fast-image'
import { createStackNavigator, createBottomTabNavigator } from 'react-navigation'
import {createBottomTabNavigator, createStackNavigator} from 'react-navigation'
import NewsScreen from '../screens/news/News'
import RoomScreen from '../screens/room/Room'
import ProductScreen from '../screens/product/Product'
@ -19,33 +19,33 @@ import Icon from 'src/components/Icon'
import PersonRoomReservationScreen from '../screens/room/PersonRoomReservation'
import CompanyRoomReservationScreen from '../screens/room/CompanyRoomReservation'
import RoomHeaderReservationScreen from '../screens/room/RoomHeaderReservation'
import Text from 'src/components/Text';
import { news } from '../api/UserApi';
import { bindActionCreators } from 'redux'
import { appSetNotification } from '../redux/app/action'
import { connect } from 'react-redux'
import PaymentScreen from "../screens/bill/Payment";
import MessageObject from '../screens/object/MessageObject';
import MessageObjectDetail from '../screens/object/MessageObjectDetail';
import Text from 'src/components/Text'
import {bindActionCreators} from 'redux'
import {appCleanUser, appSetNotification, setServerMode} from '../redux/app/action'
import {connect, useDispatch, useSelector} from 'react-redux'
import PaymentScreen from '../screens/bill/Payment'
import MessageObject from '../screens/object/MessageObject'
import MessageObjectDetail from '../screens/object/MessageObjectDetail'
import RegisterScreen from '../screens/login/Register'
import RegisterProfileScreen from '../screens/login/RegisterProfile'
import RegisterFormLoginScreen from '../screens/login/RegisterFormLogin'
import LoginScreen from '../screens/login/Login'
import SignaturePadScreen from '../screens/object/SignaturePadScreen';
import WaterMeter from '../screens/meters/WaterMeter';
import PEAMeter from '../screens/meters/PEAMeter';
import ZoneAreaScreen from '../screens/room/ZoneAreaScreen';
import RepairServiceDetail from '../screens/repair/RepairServiceDetail';
import RepairService from '../screens/repair/RepairService';
import RepairConfirm from '../screens/repair/RepairConfirm';
import RepairHistory from '../screens/repair/RepairHistory';
import RepairSuccess from '../screens/repair/RepairSuccess';
import RepairHistoryDetail from '../screens/repair/RepairHistoryDetail';
import RewardScreen from '../screens/reward/RewardScreen';
import RewardDetailScreen from '../screens/reward/RewardDetailScreen';
import QuestionScreen from '../screens/service/QuestionScreen';
import SignaturePadScreen from '../screens/object/SignaturePadScreen'
import WaterMeter from '../screens/meters/WaterMeter'
import PEAMeter from '../screens/meters/PEAMeter'
import ZoneAreaScreen from '../screens/room/ZoneAreaScreen'
import RepairServiceDetail from '../screens/repair/RepairServiceDetail'
import RepairService from '../screens/repair/RepairService'
import RepairConfirm from '../screens/repair/RepairConfirm'
import RepairHistory from '../screens/repair/RepairHistory'
import RepairSuccess from '../screens/repair/RepairSuccess'
import RepairHistoryDetail from '../screens/repair/RepairHistoryDetail'
import RewardScreen from '../screens/reward/RewardScreen'
import RewardDetailScreen from '../screens/reward/RewardDetailScreen'
import QuestionScreen from '../screens/service/QuestionScreen'
import TermsAndCondition from '../screens/login/TermsAndCondition'
import { locale, t } from 'src/utils/i18n'
import {locale, t} from 'src/utils/i18n'
import {store} from 'src/redux/store'
const screenConfig = (screen, title, backgroundColor = undefined) => ({
screen,
@ -56,7 +56,7 @@ const NavWithRightIcon = (title, iconName, routeName) => ({ navigation }) => ({
title: t(title),
headerStyle: {
backgroundColor: '#00420A',
height: 50,
height: 75,
elevation: 0,
shadowOpacity: 0,
},
@ -86,11 +86,11 @@ const NavWithRightIcon = (title, iconName, routeName) => ({ navigation }) => ({
<TouchableOpacity
style={{ width: '100%', height: '100%', alignItems: 'center', justifyContent: 'center', }}
onPress={() => navigation.goBack()}>
<Icon name="ic_back" size={20} color="#fff" />
<Icon name="ic_back" size={20} color="#fff"/>
</TouchableOpacity>
),
headerRight: (
<TouchableOpacity style={{paddingRight:16}} onPress={() => {navigation.navigate(routeName)}}>
<TouchableOpacity style={{ paddingRight: 16 }} onPress={() => {navigation.navigate(routeName)}}>
<Icon name={iconName} color={'white'} size={20}/>
</TouchableOpacity>
)
@ -100,7 +100,7 @@ const defaultNavOption = (title, backgroundColor) => ({ navigation }) => ({
title: t(title),
headerStyle: {
backgroundColor: backgroundColor || '#00420A',
height: 50,
height: 75,
elevation: 0,
shadowOpacity: 0,
},
@ -130,7 +130,7 @@ const defaultNavOption = (title, backgroundColor) => ({ navigation }) => ({
<TouchableOpacity
style={{ width: '100%', height: '100%', alignItems: 'center', justifyContent: 'center', }}
onPress={() => navigation.goBack()}>
<Icon name="ic_back" size={20} color="#fff" />
<Icon name="ic_back" size={20} color="#fff"/>
</TouchableOpacity>
),
headerRight: (
@ -141,104 +141,104 @@ const defaultNavOption = (title, backgroundColor) => ({ navigation }) => ({
})
const BottomTab = createBottomTabNavigator({
HomeScreen: {
screen: NewsScreen,
navigationOptions: ({ navigation }) => ({
tabBarVisible: true,
tabBarLabel: ({ focused, tintColor }) => {
if (focused) {
tintColor = '#FFCC00'
} else {
tintColor = 'rgba(255, 255, 255, 0.65)'
}
HomeScreen: {
screen: NewsScreen,
navigationOptions: ({ navigation }) => ({
tabBarVisible: true,
tabBarLabel: ({ focused, tintColor }) => {
if (focused) {
tintColor = '#FFCC00'
} else {
tintColor = 'rgba(255, 255, 255, 0.65)'
}
return <View style={{justifyContent:'center',alignItems:'center'}}>
<Icon name={'ic_newspaper'} size={20} color={tintColor} />
<Text style={[styles.textBottomTab,{color: tintColor}]}>{t('news')}</Text>
return <View style={{ justifyContent: 'center', alignItems: 'center' }}>
<Icon name={'ic_newspaper'} size={20} color={tintColor}/>
<Text style={[styles.textBottomTab, { color: tintColor }]}>{t('news')}</Text>
</View> /* 'Room' */
},
tabBarIcon: ({ focused, tintColor }) => {
if (focused) {
tintColor = '#FFCC00'
} else {
tintColor = 'rgba(255, 255, 255, 0.65)'
},
tabBarIcon: ({ focused, tintColor }) => {
if (focused) {
tintColor = '#FFCC00'
} else {
tintColor = 'rgba(255, 255, 255, 0.65)'
}
return <View></View>
}
return <View></View>
}
})
},
RoomScreen: {
screen: ZoneAreaScreen,
// screen: RoomScreen,
navigationOptions: ({ navigation }) => ({
tabBarLabel: ({ focused, tintColor }) => {
if (focused) {
tintColor = '#FFCC00'
} else {
tintColor = 'rgba(255, 255, 255, 0.65)'
})
},
RoomScreen: {
screen: ZoneAreaScreen,
// screen: RoomScreen,
navigationOptions: ({ navigation }) => ({
tabBarLabel: ({ focused, tintColor }) => {
if (focused) {
tintColor = '#FFCC00'
} else {
tintColor = 'rgba(255, 255, 255, 0.65)'
}
return <View style={{ justifyContent: 'center', alignItems: 'center' }}>
<Icon name={'ic_bed-outline'} size={22} color={tintColor}/>
<Text style={[styles.textBottomTab, { color: tintColor }]}>{t('room')}</Text>
</View> /* 'Room' */
},
tabBarIcon: ({ focused, tintColor }) => {
if (focused) {
tintColor = '#FFCC00'
} else {
tintColor = 'rgba(255, 255, 255, 0.65)'
}
}
return <View style={{justifyContent:'center',alignItems:'center'}}>
<Icon name={'ic_bed-outline'} size={22} color={tintColor} />
<Text style={[styles.textBottomTab,{color: tintColor}]}>{t('room')}</Text>
</View> /* 'Room' */
},
tabBarIcon: ({ focused, tintColor }) => {
if (focused) {
tintColor = '#FFCC00'
} else {
tintColor = 'rgba(255, 255, 255, 0.65)'
}
}
})
},
FavorsScreen: {
screen: RewardScreen,
navigationOptions: ({ navigation }) => ({
tabBarLabel: ({ focused, tintColor }) => {
if (focused) {
tintColor = '#FFCC00'
} else {
tintColor = 'rgba(255, 255, 255, 0.65)'
}
return <View style={{justifyContent:'center',alignItems:'center'}}>
<Icon name={'ic_star_sq'} size={20} color={tintColor} />
<Text style={[styles.textBottomTab,{color: tintColor}]}>{t('products')}</Text>
</View> /* 'Favaors' */
},
tabBarIcon: ({ focused, tintColor }) => {
if (focused) {
tintColor = '#FFCC00'
} else {
tintColor = 'rgba(255, 255, 255, 0.65)'
}
}
})
},
ServiceScreen: {
screen: ServiceScreen/* ServiceScreen */,
navigationOptions: ({ navigation }) => ({
tabBarLabel: ({ focused, tintColor }) => {
if (focused) {
tintColor = '#FFCC00'
} else {
tintColor = 'rgba(255, 255, 255, 0.65)'
})
},
FavorsScreen: {
screen: RewardScreen,
navigationOptions: ({ navigation }) => ({
tabBarLabel: ({ focused, tintColor }) => {
if (focused) {
tintColor = '#FFCC00'
} else {
tintColor = 'rgba(255, 255, 255, 0.65)'
}
return <View style={{ justifyContent: 'center', alignItems: 'center' }}>
<Icon name={'ic_star_sq'} size={20} color={tintColor}/>
<Text style={[styles.textBottomTab, { color: tintColor }]}>{t('products')}</Text>
</View> /* 'Favaors' */
},
tabBarIcon: ({ focused, tintColor }) => {
if (focused) {
tintColor = '#FFCC00'
} else {
tintColor = 'rgba(255, 255, 255, 0.65)'
}
}
})
},
ServiceScreen: {
screen: ServiceScreen/* ServiceScreen */,
navigationOptions: ({ navigation }) => ({
tabBarLabel: ({ focused, tintColor }) => {
if (focused) {
tintColor = '#FFCC00'
} else {
tintColor = 'rgba(255, 255, 255, 0.65)'
}
return <View style={{justifyContent:'center',alignItems:'center'}}>
<Icon name={'ic_grid'} size={20} color={tintColor} />
<Text style={[styles.textBottomTab,{color: tintColor}]}>{t('service')}</Text>
return <View style={{ justifyContent: 'center', alignItems: 'center' }}>
<Icon name={'ic_grid'} size={20} color={tintColor}/>
<Text style={[styles.textBottomTab, { color: tintColor }]}>{t('service')}</Text>
</View> /* 'Room' */
},
tabBarIcon: ({ focused, tintColor }) => {
if (focused) {
tintColor = '#FFCC00'
} else {
tintColor = 'rgba(255, 255, 255, 0.65)'
},
tabBarIcon: ({ focused, tintColor }) => {
if (focused) {
tintColor = '#FFCC00'
} else {
tintColor = 'rgba(255, 255, 255, 0.65)'
}
}
}
})
}
},
})
}
},
{
tabBarOptions: {
activeTintColor: '#FFCC00',
@ -246,72 +246,134 @@ const BottomTab = createBottomTabNavigator({
}
})
//export default LoginScreen
const mapDisPatchToProps = state => {
return state.app
const mapDisPatchToProps = state => {
return state.app
}
const setNotification = dispatch => bindActionCreators({ appSetNotification }, dispatch)
const NotificationIcon = connect(mapDisPatchToProps, setNotification)(({ count_noti, user }) => {
let count = 0
if (count_noti) {
count = count_noti
}
const setNotification = dispatch => bindActionCreators({ appSetNotification }, dispatch)
const NotificationIcon = connect(mapDisPatchToProps, setNotification)(({count_noti,user}) => {
let count = 0;
if(count_noti){
count = count_noti
}
if(count > 0){
return <View>
<View
style={{
width: 16,
height: 16,
backgroundColor: '#FF2D55',
borderRadius: 50,
justifyContent: 'center',
alignItems: 'center',
position: 'absolute',
right: '10%',
top: '-10%',
zIndex: 1
}}>
<Text style={{ color: 'white', fontSize: 8 }}>{count && count > 9 ? '9+' : count }</Text>
</View>
if (count > 0) {
return <View>
<View
style={{
width: 16,
height: 16,
backgroundColor: '#FF2D55',
borderRadius: 50,
justifyContent: 'center',
alignItems: 'center',
position: 'absolute',
right: '10%',
top: '-10%',
zIndex: 1,
roomLength: 0
}}>
<Text style={{ color: 'white', fontSize: 8 }}>{count && count > 9 ? '9+' : count}</Text>
</View>
<View style={{ marginRight: 10 }}>
<Icon name={'ic_bell'} size={20} color={'white'}/>
</View>
</View>
} else {
return (
<View>
<View style={{ marginRight: 10 }}>
<Icon name={'ic_bell'} size={20} color={'white'} />
<Icon name={'ic_bell'} size={20} color={'white'}/>
</View>
</View>;
}else{
return (
<View>
<View style={{ marginRight: 10 }}>
<Icon name={'ic_bell'} size={20} color={'white'} />
</View>
</View>
)
}
</View>
)
}
})
const MainTitle = connect(state => ({
user: state.app.user,
state_app: state.app,
}))((props) => {
let userText = '';
let room = '';
let name = '';
console.log("props.user.", props.user);
if(props.user && typeof props.user.room != 'undefined'){
room = " "+props.user.room;
let userText = ''
let room = ''
let roomPopup = ''
let name = ''
console.log('props.user.', props.user)
console.log('props.state_app:', props.state_app)
if (props.user && typeof props.user.room != 'undefined') {
room = ' ' + props.user.room
roomPopup = props.user.room
// console.log('room',room)
if (room.length >= 16) {
room = room.substring(0, 16) + '...'
}
if(props.user && typeof props.user.name != 'undefined'){
name = props.user.name.split(" ");
}
if (props.user) {
userText = `(${name[0]}${room})`
}
return <Text style={{ fontSize: 18, color: '#FFFFFF', marginLeft: 15, marginTop: 3 }}>{t('charoensin_asset')} {userText} </Text>
if (props.user && typeof props.user.name != 'undefined') {
name = props.user.name.split(' ')
}
if (props.user) {
userText = `${name[0]}`;
}
return <View>
<Text style={{ fontSize: 16, color: '#FFFFFF', marginLeft: 10, marginTop: 3, marginBottom: 5 }}>{t('charoensin_asset')} {userText}</Text>
</View>
})
const MainHeader = ({ navigation }) => {
const lastCount = useRef(0)
const counter = useRef(0)
const [showModal, setShowModal] = useState(false)
const dispatch = useDispatch()
const server_mode = useSelector(state => state.app.server_mode)
const openSecretChamber = useCallback(() => {
const t = new Date().getTime()
if (t - lastCount.current < 500) {
if (++counter.current >= 10) {
setShowModal(true)
}
} else {
counter.current = 1
}
lastCount.current = t
}, [])
const changeServer = useCallback((mode) => {
dispatch(setServerMode(mode))
setShowModal(false)
}, [])
return <View style={[{ flex: 1, alignItems: 'center', flexDirection: 'row', marginTop: 0, paddingLeft: 10, backgroundColor: server_mode === 'develop' ? '#ff0000' : 'transparent' }]}>
<TouchableOpacity
// onPress={openSecretChamber}
activeOpacity={1}>
<Image
style={{ width: 35, height: 35, }}
source={require('../../assets/images/logo_white_border.png')}
/>
</TouchableOpacity>
<MainTitle/>
<Modal transparent={true} visible={showModal}>
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<View style={{ backgroundColor: 'white', padding: 20, borderRadius: 10 }}>
<View>
<Text>งค Server</Text>
</View>
<View style={{ marginTop: 10 }}>
<TouchableOpacity style={{ padding: 10 }} onPress={() => changeServer('production')}>
<Text style={{ color: server_mode == 'production' ? '#004287' : '#aaa' }}>PRODUCTION</Text>
</TouchableOpacity>
<TouchableOpacity style={{ padding: 10 }} onPress={() => changeServer('develop')}>
<Text style={{ color: server_mode == 'develop' ? '#004287' : '#aaa' }}>DEVELOP</Text>
</TouchableOpacity>
</View>
</View>
</View>
</Modal>
</View>
}
const AppStack = createStackNavigator({
BottomTab: {
screen: BottomTab,
navigationOptions: ({ navigation }) => {
navigationOptions: ({navigation}) => {
let langIcon
switch (locale()) {
case 'th':
@ -331,7 +393,7 @@ const AppStack = createStackNavigator({
// title: 'Charoensin Condo',
headerStyle: {
backgroundColor: '#00420A',
height: 50,
height: 75,
elevation: 0,
shadowOpacity: 0,
},
@ -344,31 +406,23 @@ const AppStack = createStackNavigator({
marginLeft: 30,
},
headerRight: (
<View style={{ marginRight: 0, justifyContent: 'center', alignItems: 'center', flexDirection: 'row' }}>
<TouchableOpacity onPress={() => navigation.navigate('LanguageSelect')} style={{marginRight:8}}>
<View style={{ width: 30, height: 30, alignItems: 'center', justifyContent: 'center' }}>
<Image style={{width:25,height:25}} source={langIcon}/></View>
<View style={{marginRight: 0, justifyContent: 'center', alignItems: 'center', flexDirection: 'row'}}>
<TouchableOpacity onPress={() => navigation.navigate('LanguageSelect')} style={{marginRight: 8}}>
<View style={{width: 30, height: 30, alignItems: 'center', justifyContent: 'center'}}>
<Image style={{width: 25, height: 25}} source={langIcon}/></View>
</TouchableOpacity>
<TouchableOpacity style={{ marginRight: 6 }} onPress={() => navigation.navigate('Notification')}>
<TouchableOpacity style={{marginRight: 6}} onPress={() => navigation.navigate('Notification')}>
<NotificationIcon/>
</TouchableOpacity>
</View>
),
headerLeftContainerStyle: {
width:'80%',
width: '80%',
alignItems: 'center',
justifyContent: 'center',
},
headerLeft: (
<View style={[{ flex: 1, flexDirection: 'row', marginTop: 0, paddingLeft: 10 }]}>
<Image
style={{ width: 35, height: 35, }}
source={require('../../assets/images/logo_white_border.png')}
/>
<MainTitle/>
</View>
),
};
headerLeft: () => <MainHeader navigation={navigation}/>,
}
}
@ -381,7 +435,7 @@ const AppStack = createStackNavigator({
RoomHeaderReservation: screenConfig(RoomHeaderReservationScreen, 'book_room'),
News: {
screen: NewsScreen,
navigationOptions: ({ navigation }) => ({
navigationOptions: ({navigation}) => ({
title: t('charoensin_asset'),
headerLeft: (
<TouchableOpacity onPress={() => navigation.goBack()}>
@ -392,11 +446,11 @@ const AppStack = createStackNavigator({
},
NewsDetail: {
screen: NewsDetailScreen,
navigationOptions: ({ navigation }) => ({
navigationOptions: ({navigation}) => ({
title: '',
headerStyle: {
backgroundColor: '#00420A',
height: 50,
height: 75,
elevation: 0,
shadowOpacity: 0,
},
@ -410,14 +464,14 @@ const AppStack = createStackNavigator({
headerLeft: null,
headerRight: (
<TouchableOpacity onPress={() => navigation.goBack()}>
<Text style={{ color: '#fff', fontSize: 16 }}> {t('close')} </Text>
<Text style={{color: '#fff', fontSize: 16}}> {t('close')} </Text>
</TouchableOpacity>
)
})
},
Product: {
screen: ProductScreen,
navigationOptions: ({ navigation }) => ({
navigationOptions: ({navigation}) => ({
title: t('products'),
headerLeft: (
<TouchableOpacity onPress={() => navigation.goBack()}>
@ -440,39 +494,41 @@ const AppStack = createStackNavigator({
// }
,
Meter: screenConfig(MeterScreen, 'smart_meter'),
WaterMeter: screenConfig(WaterMeter,'save_water_meter'),
PEAMeter: screenConfig(PEAMeter,'save_electric_meter'),
WaterMeter: screenConfig(WaterMeter, 'save_water_meter'),
PEAMeter: screenConfig(PEAMeter, 'save_electric_meter'),
// Bill: screenConfig(BillScreen, 'รายละเอียดยอดค้างชำระ'),
Bill: screenConfig(BillScreen,'outstanding_balance_detail'),
Bill: screenConfig(BillScreen, 'outstanding_balance_detail'),
Payment: screenConfig(PaymentScreen, 'pay'),
SettingsNotification: screenConfig(SettingsNotificationScreen, 'noti_setting'),
Suggestion: screenConfig(SuggestionScreen, 'suggestion'),
Question: {
screen: QuestionScreen,
navigationOptions: ({ navigation }) => ({
navigationOptions: ({navigation}) => ({
title: t('faqs'),
headerStyle:{
headerStyle: {
backgroundColor: '#00420A',
},
headerTitleStyle: {
fontSize: 18,
color: '#fff',
fontFamily: 'Prompt-Regular',
fontWeight: undefined,
}, headerLeftContainerStyle: {
textAlign: 'left',
flex: 1,
marginLeft: 0
}, headerLeftContainerStyle: {
alignItems: 'center',
justifyContent: 'center',
width: '10%',
},
headerLeft: (
<TouchableOpacity onPress={() => navigation.goBack()} style={{flex:1,alignItems:'center'}}>
<TouchableOpacity onPress={() => navigation.goBack()} style={{flex: 1, alignItems: 'center'}}>
<Icon name={'ic_back'} color={'white'} size={20}/>
</TouchableOpacity>
),
headerRight:(
<TouchableOpacity onPress={() => navigation.state.params.onRefreshMessage()} style={{paddingRight:16}}>
headerRight: (
<TouchableOpacity onPress={() => navigation.state.params.onRefreshMessage()} style={{paddingRight: 16}}>
<Icon name={'ic_refresh'} color={'white'} size={20}/>
</TouchableOpacity>
)
@ -480,14 +536,54 @@ const AppStack = createStackNavigator({
},
Profile: screenConfig(ProfileScreen, 'profile', '#3AA40C'),
EditProfile: screenConfig(EditProfileScreen, 'edit_profile', '#3AA40C'),
Object: screenConfig(MessageObject, 'mail_and_parcel'),
Object: {
screen: MessageObject,
navigationOptions: ({navigation}) => ({
title: t('mail_and_parcel'),
headerStyle: {
backgroundColor: '#00420A',
height: 75,
elevation: 0,
shadowOpacity: 0,
},
headerTintColor: '#000',
headerTitleStyle: {
fontWeight: '400',
fontSize: 18,
color: '#fff',
textAlign: 'left',
flex: 1,
fontFamily: 'Prompt-Regular',
marginLeft: 0,
},
headerTitleContainerStyle: {
alignItems: 'center',
justifyContent: 'center',
},
headerLeftContainerStyle: {
alignItems: 'center',
justifyContent: 'center',
width: '10%',
},
headerTitleAllowFontScaling: false,
headerLeft: (
<TouchableOpacity
style={{ width: '100%', height: '100%', alignItems: 'center', justifyContent: 'center', }}
onPress={() => navigation.goBack()}>
<Icon name="ic_back" size={20} color="#fff"/>
</TouchableOpacity>
)
})
},
ObjectDetail: screenConfig(MessageObjectDetail, 'mail_and_parcel'),
Signature: screenConfig(SignaturePadScreen, 'please_sign'),
Login: {
screen: LoginScreen,
navigationOptions: ({ navigation }) => ({
navigationOptions: ({navigation}) => ({
title: t('login'),
headerStyle:{
headerStyle: {
backgroundColor: '#00420A',
},
headerTitleStyle: {
@ -496,7 +592,7 @@ const AppStack = createStackNavigator({
color: '#fff',
fontFamily: 'Prompt-Regular',
fontWeight: undefined,
}, headerLeftContainerStyle: {
}, headerLeftContainerStyle: {
alignItems: 'center',
justifyContent: 'center',
width: '10%',
@ -510,29 +606,124 @@ const AppStack = createStackNavigator({
})
},
//Register Screen
Register: screenConfig(RegisterScreen,'register'),
Register: screenConfig(RegisterScreen, 'register'),
RegisterFormLogin: screenConfig(RegisterFormLoginScreen, 'register'),
RegisterProfile: screenConfig(RegisterProfileScreen, 'register'),
//Repair Service
RepairService: {
screen: RepairService,
navigationOptions: NavWithRightIcon('request_repair_and_Other','ic_clock_history','RepairHistory')
navigationOptions: NavWithRightIcon('request_repair_and_Other', 'ic_clock_history', 'RepairHistory')
},
RepairDetail: screenConfig(RepairServiceDetail,'service_detail'),
RepairDetail: screenConfig(RepairServiceDetail, 'service_detail'),
RepairConfirm: screenConfig(RepairConfirm, 'confirm_info'),
RepairHistory: screenConfig(RepairHistory, 'repair_history'),
RepairSuccess: screenConfig(RepairSuccess, 'request_sent'),
RepairHistoryDetail: screenConfig(RepairHistoryDetail, 'รายละเอียดประวัติ'),
// RepairHistoryDetail: screenConfig(RepairHistoryDetail, 'repair_history_detail'),
RepairHistoryDetail: {
screen: RepairHistoryDetail,
navigationOptions: ({navigation}) => ({
title: t('repair_history_detail'),
headerStyle: {
backgroundColor: '#00420A',
height: 75,
elevation: 0,
shadowOpacity: 0,
},
headerTintColor: '#000',
headerTitleStyle: {
fontWeight: '400',
fontSize: 18,
color: '#fff',
textAlign: 'left',
flex: 1,
fontFamily: 'Prompt-Regular',
marginLeft: 0,
},
headerTitleContainerStyle: {
alignItems: 'center',
justifyContent: 'center',
},
headerLeftContainerStyle: {
alignItems: 'center',
justifyContent: 'center',
width: '10%',
},
headerTitleAllowFontScaling: false,
headerLeft: (
<TouchableOpacity
style={{ width: '100%', height: '100%', alignItems: 'center', justifyContent: 'center', }}
onPress={() => navigation.goBack()}>
<Icon name="ic_back" size={20} color="#fff"/>
</TouchableOpacity>
),
headerRight: (
navigation.state.params.statusRepair !== 'Success' && navigation.state.params.statusRepair !== 'Cancel' && navigation.state.params.type !== 'effect_repair' &&
<TouchableOpacity onPress={() => navigation.state.params.cancelRepair()} style={{marginRight: 15}}>
<Text style={{color: '#FF3B30', fontSize: 18}}>{t('cancel')}</Text>
</TouchableOpacity>
)
})
},
//Reward
Reward: screenConfig(RewardScreen, 'redeem_reward'),
RewardDetail: screenConfig(RewardDetailScreen,'product_detail'),
RewardDetail: screenConfig(RewardDetailScreen, 'product_detail'),
//Terms and Condition
Terms: screenConfig(TermsAndCondition, 'term_condition'),
Terms: {
screen: TermsAndCondition,
navigationOptions: ({navigation}) => ({
title: t('term_condition'),
headerStyle: {
backgroundColor: '#00420A',
height: 75,
elevation: 0,
shadowOpacity: 0,
},
headerTintColor: '#000',
headerTitleStyle: {
fontWeight: '400',
fontSize: 18,
color: '#fff',
textAlign: 'left',
flex: 1,
fontFamily: 'Prompt-Regular',
marginLeft: 0,
},
headerTitleContainerStyle: {
alignItems: 'center',
justifyContent: 'center',
},
headerLeftContainerStyle: {
alignItems: 'center',
justifyContent: 'center',
width: '10%',
},
headerTitleAllowFontScaling: false,
headerLeft: (
<TouchableOpacity
style={{ width: '100%', height: '100%', alignItems: 'center', justifyContent: 'center', }}
onPress={() => {
store.dispatch(appCleanUser());
navigation.goBack()
}}>
<Icon name="ic_back" size={20} color="#fff"/>
</TouchableOpacity>
),
headerRight: (
<TouchableOpacity>
{/*<Icon name="ic_back" size={20} color="#fff"/>*/}
</TouchableOpacity>
)
})
}
})
const styles = StyleSheet.create({
textBottomTab:{
fontSize:12,
textBottomTab: {
fontSize: 12,
textAlign: 'center',
}
})

View File

@ -1,5 +1,5 @@
import { switchLanguage } from 'src/utils/i18n'
import { setLanguage } from '../../api/api'
import { setBaseUrlByServerMode, setLanguage } from '../../api/api'
// action type
export const ACTION_APP_SET_TOKEN = 'APP_SET_TOKEN'
@ -14,6 +14,8 @@ export const ACTION_APP_CHANGE_NOTIFICATION = 'ACTION_APP_CHANGE_NOTIFICATION'
export const ACTION_APP_SET_PROJECT_ID = 'ACTION_APP_SET_PROJECT_ID'
export const ACTION_APP_CLEAN_PROJECT_ID = 'ACTION_APP_CLEAN_PROJECT_ID'
export const ACTION_APP_SET_LANGUAGE = 'ACTION_APP_SET_LANGUAGE'
export const ACTION_APP_SET_SERVER_MODE = 'ACTION_APP_SET_SERVER_MODE'
export const ACTION_SET_POPUP_NOTIFICATION = 'ACTION_SET_POPUP_NOTIFICATION'
// action creator
export function appSetToken (token) {
@ -96,4 +98,19 @@ export function appSetLanguage (langCode) {
type: ACTION_APP_SET_LANGUAGE,
lang: langCode
}
}
}
export function setServerMode (mode) {
setBaseUrlByServerMode(mode)
return {
type: ACTION_APP_SET_SERVER_MODE,
mode
}
}
export function setPopupNotification(data) {
return {
type: ACTION_SET_POPUP_NOTIFICATION,
popup_notification : data
}
}

View File

@ -11,6 +11,8 @@ import {
ACTION_APP_SET_PROJECT_ID,
ACTION_APP_CLEAN_PROJECT_ID,
ACTION_APP_SET_LANGUAGE,
ACTION_APP_SET_SERVER_MODE,
ACTION_SET_POPUP_NOTIFICATION
} from './action'
const initialState = {
@ -21,35 +23,40 @@ const initialState = {
notification: null,
project_id: null,
lang: null,
};
server_mode: 'production',
}
export default function (state = initialState, action) {
switch (action.type) {
case ACTION_APP_SET_LANGUAGE:
return { ...state, lang: action.lang }
case ACTION_APP_SET_TOKEN:
return { ...state, token: action.token };
return { ...state, token: action.token }
case ACTION_APP_CLEAN_TOKEN:
return { ...state, token: null };
return { ...state, token: null }
case ACTION_APP_SET_PUSH_TOKEN:
return { ...state, push_token: action.pushToken };
return { ...state, push_token: action.pushToken }
case ACTION_APP_SET_DEVICE:
return { ...state, device: action.device };
return { ...state, device: action.device }
case ACTION_APP_CLEAN_DEVICE:
return { ...state, device: null };
return { ...state, device: null }
case ACTION_APP_SET_USER:
return { ...state, user: action.user };
return { ...state, user: action.user }
case ACTION_APP_CLEAN_USER:
return { ...state, user: null };
return { ...state, user: null }
case ACTION_APP_SET_NOTIFICATION:
return { ...state, count_noti: action.count_noti };
return { ...state, count_noti: action.count_noti }
case ACTION_APP_CHANGE_NOTIFICATION:
return { ...state, notification: action.notification };
return { ...state, notification: action.notification }
case ACTION_APP_SET_PROJECT_ID:
return { ...state, project_id: action.project_id };
return { ...state, project_id: action.project_id }
case ACTION_APP_CLEAN_PROJECT_ID:
return { ...state, project_id: null };
return { ...state, project_id: null }
case ACTION_APP_SET_SERVER_MODE:
return { ...state, server_mode: action.mode }
case ACTION_SET_POPUP_NOTIFICATION:
return { ...state, popup_notification: action.popup_notification }
default:
return state
}
}
}

View File

@ -1,6 +1,6 @@
import React, { Component } from 'react'
import { bindActionCreators } from 'redux'
import { appSetDevice, appSetPushToken, appSetToken, appSetUser } from '../../redux/app/action'
import {appSetDevice, appSetPushToken, appSetToken, appSetUser} from '../../redux/app/action'
import { connect } from 'react-redux'
import { View } from 'react-native'
import { switchLanguage } from '../../utils/i18n'
@ -24,8 +24,9 @@ class AppLoading extends Component {
const mapStateToProps = state => {
return {
lang: state.app.lang
lang: state.app.lang,
user: state.app.user
}
}
const setUser = dispatch => bindActionCreators({ appSetToken, appSetPushToken, appSetDevice, appSetUser }, dispatch)
export default connect(mapStateToProps, setUser)(AppLoading)
export default connect(mapStateToProps, setUser)(AppLoading)

View File

@ -5,6 +5,7 @@ import { useDispatch } from 'react-redux'
import { appSetLanguage } from '../../redux/app/action'
import { BackgroundImage_RegisterForm } from '../../components/BackgroundImage_RegisterForm'
import LinearGradient from 'react-native-linear-gradient'
import {setLanguage} from "../../api/UserApi";
const languages = [
{ code: 'th', name: 'ภาษาไทย' },
@ -18,7 +19,18 @@ export default function ({ navigation }) {
function selectLanguage (code) {
dispatch(appSetLanguage(code))
navigation.navigate('HomeScreen')
if(code === 'th'){
code = 'th_TH';
}
setLanguage(code)
.then(res => {
if(res.success){
navigation.navigate('HomeScreen')
}else{
navigation.navigate('HomeScreen')
}
})
}
return <LinearGradient colors={['#3AA40C', '#2C7C0B']} style={{
@ -41,4 +53,4 @@ export default function ({ navigation }) {
</View>
</BackgroundImage_RegisterForm>
</LinearGradient>
}
}

View File

@ -1,4 +1,5 @@
import React, { Component } from 'react'
import IconAntDesign from 'react-native-vector-icons/AntDesign'
import Icon from '../../components/Icon'
import {
Accordion,
@ -24,8 +25,10 @@ import {appSetDevice, appSetPushToken, appSetToken, appSetUser} from "../../redu
import moment from "moment";
import IndicatorLoading from '../../components/IndicatorLoading';
import { t } from 'src/utils/i18n'
import parseDateLocale from 'src/utils/parseDateLocale';
const { height, width } = Dimensions.get('window')
import { CustomInput } from '../../components/CustomInput'
import debounce from 'lodash/debounce'
function ItemOrder({title,cost,description,type}){
@ -91,17 +94,41 @@ class BillScreen extends Component {
isCanPay: true,
all_payment : [],
room_number_array : [],
page: 1,
total_page: 1,
currentIndex: 0,
search: ''
};
this._onCarouselScroll = this._onCarouselScroll.bind(this)
this.checkDueDate = this.checkDueDate.bind(this)
this.checkstatusBill = this.checkstatusBill.bind(this)
this.debounceSearch = debounce(() => {
this.setState({
page: 1,
all_payment : [],
room_number_array : [],
payment: [],
sum_payment: [],
total_page: 1,
currentIndex: 0
}, () => {
this.getPaymentPagination()
})
}, 2500)
}
componentDidMount() {
this.setState({isLoading: true})
if(this.props.user){
payment(this.props.user.id)
this.getPaymentPagination()
}
}
getPaymentPagination () {
this.setState({
isLoading: true
}, () => {
payment(this.props.user.id, this.state.page, this.state.search)
.then(res => {
if(res.ok){
let sum_payment = [];
@ -119,6 +146,7 @@ class BillScreen extends Component {
})
}
sum_payment = this.state.sum_payment.concat(sum_payment)
let payment = res.data.payment_room_period
if(Object.keys(payment).length > 0){
Object.keys(payment).map((pay) => {
@ -128,19 +156,15 @@ class BillScreen extends Component {
array_payment.push({
room_id: pay,
period: detail,
// total_cost: payment[pay][detail].total_cost,
// details: payment[pay][detail].details,
// status: payment[pay][detail].status,
// created_at: payment[pay][detail].created_at,
// payment_id: payment[pay][detail].id,
// enable_qr: payment[pay][detail].enable_qr
...payment[pay][detail]
})
})
}
})
}
let all_payment_data = array_payment;
let all_payment_data = this.state.all_payment.concat(array_payment)
let array_room_no = this.state.room_number_array;
this.setState({
room_number_array: array_room_no.filter((item, i, ar) => ar.indexOf(item) === i)
@ -177,69 +201,26 @@ class BillScreen extends Component {
isLoading:false,
payment: array_payment,
sum_payment: sum_payment,
all_payment: all_payment_data
all_payment: all_payment_data,
page: res.data.page,
total_page: res.data.total_page
}, () => {
this.roomFilter(this.state.currentIndex)
} )
}else {
this.setState({
isLoading: false
})
}
})
}
}
getMonth(period_month){
let new_month = 'มกราคม'
switch (period_month) {
case '01':
new_month = 'มกราคม';
break;
case '02':
new_month = 'กุมภาพันธ์';
break;
case '03':
new_month = 'มีนาคม';
break;
case '04':
new_month = 'เมษายน';
break;
case '05':
new_month = 'พฤษภาคม';
break;
case '06':
new_month = 'มิถุนายน';
break;
case '07':
new_month = 'กรกฎาคม';
break;
case '08':
new_month = 'สิงหาคม';
break;
case '09':
new_month = 'กันยายน';
break;
case '10':
new_month = 'ตุลาคม';
break;
case '11':
new_month = 'พฤศจิกายน';
break;
case '12':
new_month = 'ธันวาคม';
break;
default:
new_month = 'มกราคม';
break;
}
return new_month;
})
}
getTitle (period) {
let period_month = moment(period, "MM/Y").format('MM');
let period_year = parseInt(moment(period, "MM/Y").format('Y')) + 543;
let new_month = 'มกราคม';
let new_period = new_month + ' ' + period_year;
new_month = this.getMonth(period_month)
new_period = new_month + ' ' + period_year;
let period_month = moment(period, "MM/Y").format('MMMM');
let period_year = parseInt(moment(period, "MM/Y").locale('en').format('Y'));
let new_month = '';
let new_period = period_month + ' ' + period_year;
return new_period;
}
@ -254,7 +235,7 @@ class BillScreen extends Component {
return true
}
checkstatusBill(data,boolDate){
checkstatusBill(data, isOverdue){
if(data.status == 'paid'){
return <TouchableOpacity style={{backgroundColor:data.status === 'pending' ? '#145EB3' : 'white',
height: 32,width: 103,justifyContent:'center',alignItems:'center',borderRadius:5,
@ -269,7 +250,7 @@ class BillScreen extends Component {
<Text style={{ color: data.status === 'pending' ? 'white' : 'rgba(0, 0, 0, 0.25)'}}>{data.status === 'pending' ? 'จ่ายเงิน' : 'จ่ายแล้ว'}</Text>
</TouchableOpacity>
}else{
if(!boolDate){
if(isOverdue){
return <View>
<Text style={{ color: 'red',borderWidth:1,borderColor:'#00000040',borderRadius:5,paddingHorizontal:6}}>{'เกินกำหนดชำระ'}</Text>
</View>
@ -296,14 +277,14 @@ class BillScreen extends Component {
return (
<View style={{flex:1,flexDirection:'row',backgroundColor:'#B8DAAA',height: 64,borderBottomWidth:1,borderBottomColor:'white',alignItems:'center',justifyContent:'space-between',paddingHorizontal:16}}>
<View style={{justifyContent:'center',flex:1}}>
<Text>{t('month')} {this.getTitle(data.period)}</Text>
<Text>{t('month')} {parseDateLocale(moment(data.period, 'MM/Y'), 'MMMM Y')}</Text>
<View style={{flexDirection:'row',alignItems:'center',justifyContent:'space-between'}}>
{expanded || data.status != 'pending' ? <Text /> : <Text note style={styles.colorTextPayment}>{t('outstanding_balance')} {data.total_cost}</Text>}
{expanded || <Text style={{fontSize:10,marginRight:16}}>{t('view_more')}</Text>}
</View>
</View>
{
this.checkstatusBill(data,checkBool)
this.checkstatusBill(data, data.is_overdue)
}
{/* {
checkBool ?
@ -340,7 +321,7 @@ class BillScreen extends Component {
let d = moment(data.created_at).format('D')
let m = moment(data.created_at).format('MM')
let y = parseInt(moment(data.created_at).format('Y')) + 543
date_payment = d + ' ' + this.getMonth(m) + ' ' + y
//date_payment = d + ' ' + this.getMonth(m) + ' ' + y
let descriptionRoom = '-'
let descriptionWater = '-'
@ -353,26 +334,26 @@ class BillScreen extends Component {
data.details.map((det) => {
if(det.sequence === 1){
room_cost = det.cost
room_extra_info = det.extra_info != null ? det.extra_info : ''
descriptionRoom = det.descript == '' ? '-' : det.descript
// room_extra_info = det.extra_info && det.extra_info != null ? det.extra_info : ''
descriptionRoom = det.descript && det.descript == '' ? '-' : det.descript
}
if(det.sequence === 2){
water_cost = det.cost
water_extra_info = det.extra_info != null ? det.extra_info : ''
descriptionWater = det.descript == '' ? '-' : det.descript
// water_extra_info = det.extra_info && det.extra_info != null ? det.extra_info : ''
descriptionWater = det.descript && det.descript == '' ? '-' : det.descript
}
if(det.sequence === 3){
electrict_cost = det.cost
electrict_extra_info = det.extra_info != null ? det.extra_info : ''
descriptionElec = det.descript == '' ? '-' : det.descript
// electrict_extra_info = det.extra_info && det.extra_info != null ? det.extra_info : ''
descriptionElec = det.descript && det.descript == '' ? '-' : det.descript
}
if(det.sequence === 4){
service_cost = det.cost
service_extra_info = det.extra_info != null ? det.extra_info : ''
descriptionService = det.descript == '' ? '-' : det.descript
// service_extra_info = det.extra_info && det.extra_info != null ? det.extra_info : ''
descriptionService = det.descript && det.descript == '' ? '-' : det.descript
}
})
}
@ -447,31 +428,82 @@ class BillScreen extends Component {
}
}
handlePrevious = () => {
let currentIndex = this.state.currentIndex - 1;
this.setState({
currentIndex,
activePage: currentIndex
}, () => {
this.roomFilter(this.state.currentIndex)
this.flatListRef.scrollToIndex({index: this.state.currentIndex, animated: true})
})
}
handleNext = () => {
let currentIndex = this.state.currentIndex;
let dataLength = this.state.sum_payment.length
if(dataLength > this.state.currentIndex) {
currentIndex += 1;
this.roomFilter(currentIndex)
this.setState({
currentIndex,
activePage: currentIndex
}, () => {
this.flatListRef.scrollToIndex({index: currentIndex, animated: true})
if(dataLength - 1 == this.state.currentIndex && this.state.page < this.state.total_page) {
this.setState({
page: parseInt(this.state.page) + 1
}, () => {
this.getPaymentPagination()
})
}
})
}
}
renderNativeItemImages = (item) => {
// console.log('check data item ',item)
return <View style={{width: width, alignItems: 'center', paddingTop: 10, paddingBottom: 40,height: 177,}}>
<View style={{width: '60%', height: '100%', backgroundColor: '#06ADB8', borderRadius: 5 }}>
<LinearGradient colors={['#4BAF3B', '#0e5e29']} style={{ flex:1, borderRadius: 5, height: 120,paddingBottom:10, justifyContent:'space-between'}}>
<View style={{ padding: 16,paddingBottom: 5,paddingTop:10 , borderRadius: 5}}>
<Text style={{ color: 'white', fontSize: 18 }}>{t('room')} {item.room}</Text>
<Text style={{ color: 'rgba(255, 255, 255, 0.65)', fontSize: 14 }}>{item.project && item.project.name}</Text>
<Text style={{ color: 'white' }}>{t('outstanding_balance')} <Text style={{ color: 'white' ,fontSize:18 }}>{item.total_cost} {t('baht')}</Text></Text>
return <View style={{display: 'flex', flexDirection: 'row', alignItems: 'center', position: 'relative'}}>
{
this.state.currentIndex > 0 &&
<TouchableOpacity onPress={this.handlePrevious} style={{position: 'absolute', left: 5, zIndex: 1}}>
<IconAntDesign name="left" size={35} color={'#0e5e29'}></IconAntDesign>
</TouchableOpacity>
}
<View style={{width: width, alignItems: 'center', paddingTop: 10, paddingBottom: 40,height: 177, zIndex: 0}}>
<View style={{width: '65%', height: '100%', backgroundColor: '#06ADB8', borderRadius: 5 }}>
<LinearGradient colors={['#4BAF3B', '#0e5e29']} style={{ flex:1, borderRadius: 5, height: 120,paddingBottom:10, justifyContent:'space-between'}}>
<View style={{ padding: 16,paddingBottom: 5,paddingTop:10 , borderRadius: 5}}>
<Text style={{ color: 'white', fontSize: 18 }}>{t('room')} {item.room}</Text>
<Text style={{ color: 'rgba(255, 255, 255, 0.65)', fontSize: 14 }}>{item.project && item.project.name}</Text>
<Text style={{ color: 'white' }}>{t('outstanding_balance')} <Text style={{ color: 'white' ,fontSize:18 }}>{item.total_cost} {t('baht')}</Text></Text>
</View>
{
item.due_at !== null
? (
<View style={{height:24,backgroundColor: '#FF2D55',justifyContent:'center',alignItems:'center'}}>
<Text style={{ fontSize: 12, color: 'white'}}>{t('please_pay_within')} {this.getDueDate(item.due_at)}</Text>
</View>
)
: null
}
</LinearGradient>
</View>
{
item.due_at !== null
? (
<View style={{height:24,backgroundColor: '#FF2D55',justifyContent:'center',alignItems:'center'}}>
<Text style={{ fontSize: 12, color: 'white'}}>{t('please_pay_before')} {this.getDueDate(item.due_at)}</Text>
</View>
)
: null
}
</LinearGradient>
</View>
{
this.state.currentIndex < this.state.sum_payment.length - 1 &&
<TouchableOpacity onPress={this.handleNext} style={{position: 'absolute', right: 5, zIndex: 1}}>
<IconAntDesign name="right" size={35} color={'#0e5e29'}></IconAntDesign>
</TouchableOpacity>
}
</View>
</View>
}
_onCarouselScroll(e) {
const scrollX = e.nativeEvent.contentOffset.x
this.setState({
@ -495,31 +527,55 @@ class BillScreen extends Component {
return obj.room_id === another_room
}, false);
});
this.state.payment = payment_array;
this.setState({
payment: payment_array
})
}
_keyExtractor = (item, index) => 'bill_'+index
handleSearch = (search) => {
this.setState({
search
}, () => {
this.debounceSearch()
})
}
render() {
return (
<SafeAreaView style={{flex: 1}}>
<ScrollView contentContainerStyle={styles.contentContainer}>
<View style={{ alignItems: 'center'}}>
<View>
<CustomInput
onChangeText={this.handleSearch}
inputTextAlign={'left'}
iconName={'ic_search'}
placeholder={'Search Room'}
placeholderTextColor={'#FFFFFF40'}
value={this.state.search}
style={styles.form_input} />
</View>
{
this.state.sum_payment.length == 0 &&
<View style={{margin:16,width: '90%', height: 55,backgroundColor:'#00000080',justifyContent:'center',alignItems:'center',borderRadius:5}}>
<Text style={{fontSize:14,color:'white',textAlign:'center'}}>{this.props.user.room} {t('no_outstanding_balance')}</Text>
</View>
<View style={{margin:16,width: '90%', height: 55,backgroundColor:'#00000080',justifyContent:'center',alignItems:'center',borderRadius:5}}>
<Text style={{fontSize:14,color:'white',textAlign:'center'}}>{this.state.search === '' ? t('no_outstanding_balance') : t('room_not_found')}</Text>
</View>
}
<FlatList
data={this.state.sum_payment}
renderItem={({ item }) => this.renderNativeItemImages(item)}
horizontal={true}
onScroll={this._onCarouselScroll}
onScrollEndDrag={this.roomFilter(this.state.activePage)}
pagingEnabled={true}
// onScroll={this._onCarouselScroll}
// onScrollEndDrag={this.roomFilter(this.state.activePage)}
// pagingEnabled={true}
extraData={this.state}
keyExtractor={this._keyExtractor}
scrollEnabled={false}
ref={(flatlist) => { this.flatListRef = flatlist }}
/>
<View style={{ position: 'absolute', bottom: 10, width: '100%', justifyContent: 'center', flexDirection: 'row' }}>
{this.state.sum_payment.map((item, i) => <View key={'sum_payment_'+i} style={[{ width: 10, height: 10, borderRadius: 5, backgroundColor: this.state.activePage == i ? '#269A21' : 'rgba(124, 187, 51, 0.3)', marginHorizontal: 4 }]}></View>)}
@ -528,7 +584,7 @@ class BillScreen extends Component {
<View style={{flex:1}}>
<Accordion
dataArray={ this.state.payment }
expanded={this.state.payment.length - 1}
expanded={this.state.payment && this.state.payment.length > 0 ? this.state.payment.length - 1 : []}
renderHeader={(data, expanded) => { return this._renderHeader(data, expanded) }}
renderContent={(data) => { return this._renderContent(data) }} />
</View>
@ -554,7 +610,15 @@ const styles = StyleSheet.create({
},
colorTextPayment: {
color: '#3AA40C'
}
},
form_input: {
backgroundColor: '#4BAF3B',
borderColor: '#0e5e29',
borderRadius: 30,
borderWidth: 1,
width: '80%',
marginTop: 10
},
})
const mapDisPatchToProps = state => ({

View File

@ -8,6 +8,7 @@ import ViewShot, { captureRef } from "react-native-view-shot";
import IndicatorLoading from '../../components/IndicatorLoading';
import QRCode from 'react-native-qrcode-svg';
import { t } from '../../utils/i18n';
import DeviceInfo from 'react-native-device-info'
class PaymentScreen extends Component {
constructor(props) {
@ -26,30 +27,51 @@ class PaymentScreen extends Component {
this.setState({isLoading:true})
payment_detail(this.state.payment_id)
.then( res => {
this.setState({
payment_data: res.data
},() => {
this.setState({isLoading: false})
})
if(res.data && res.data.success){
this.setState({
payment_data: res.data
},() => {
this.setState({isLoading: false})
})
}else {
Alert.alert(res.data.message, '', [{
text: 'ok',
onPress: () => {
this.setState({
isLoading: false
}, () => {
this.props.navigation.goBack()
})
}
}])
}
})
};
async snapScreen() {
try {
if(Platform.OS == 'android'){
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,
{
title: 'Cool Photo App Camera Permission',
message:
'Cool Photo App needs access to your camera ' +
'so you can take awesome pictures.',
buttonNeutral: 'Ask Me Later',
buttonNegative: 'Cancel',
buttonPositive: 'OK',
},
);
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
let deviceVersion = DeviceInfo.getSystemVersion();
let granted = PermissionsAndroid.RESULTS.DENIED;
if(deviceVersion >= 13){
granted = PermissionsAndroid.RESULTS.GRANTED;
console.log('granted >>>> ', granted)
}else{
granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE ,
{
title: 'Cool Photo App Camera Permission',
message:
'Cool Photo App needs access to your camera ' +
'so you can take awesome pictures.',
buttonNeutral: 'Ask Me Later',
buttonNegative: 'Cancel',
buttonPositive: 'OK',
},
);
}
if(granted === PermissionsAndroid.RESULTS.GRANTED) {
console.log('You can use the camera');
this.viewshot.capture()
.then(

View File

@ -1,20 +1,21 @@
import React, { Component } from 'react'
import React, {Component, useCallback} from 'react';
import { TouchableOpacity, View, Alert, ScrollView, SafeAreaView, KeyboardAvoidingView, Platform } from 'react-native'
import Image from 'react-native-fast-image'
import GetWidthHeightDevice from '../../components/GetWidthHeightDevice'
import { CustomButton } from '../../components/CustomButton'
import { CustomInput } from '../../components/CustomInput'
import { login } from '../../api/UserApi'
import {login, payment} from '../../api/UserApi'
import { setToken } from '../../api/api'
import { BackgroundImage } from '../../components/BackgroundImage'
import LinearGradient from 'react-native-linear-gradient'
import Text from '../../components/Text'
import { bindActionCreators } from 'redux'
import { appSetDevice, appSetPushToken, appSetToken, appSetUser } from '../../redux/app/action'
import {appSetDevice, appSetPushToken, appSetToken, appSetUser} from '../../redux/app/action'
import {connect} from 'react-redux'
import IndicatorLoading from '../../components/IndicatorLoading';
import { locale, t } from '../../utils/i18n'
import moment from "moment";
import messaging from "@react-native-firebase/messaging";
class LoginScreen extends Component {
@ -23,49 +24,66 @@ class LoginScreen extends Component {
this.state = {
isLoading: false,
username: null,
password: null,
password: null
}
this._login = this._login.bind(this)
}
_login() {
if (this.state.username && this.state.password) {
async _login () {
this.setState({
isLoading: true
}, async () => {
if (this.state.username && this.state.password) {
var regex = /^\d+$/;
if (regex.test(this.state.username) === true) {
console.log('true')
const fcm = messaging()
if (!await fcm.hasPermission()) {
try {
await messaging().requestPermission()
} catch (error) {
}
}
const fcmToken = await messaging().getAPNSToken()
let params = {
mobile: this.state.username,
password: this.state.password
password: this.state.password,
fcm_token: fcmToken
}
console.log('params >> ', params)
console.log('fcmToken >>>>>>>>>>>>>>>>>>>>>>>>> ', fcmToken)
this.setState({isLoading:true})
login(params)
.then((res) => {
if (res.ok) {
if (res.data.token) {
setToken(res.data.token)
this.props.appSetToken(res.data.token)
this.props.appSetUser(res.data.user)
.then((res) => {
if (res.ok) {
if (res.data.token) {
setToken(res.data.token)
this.props.appSetToken(res.data.token)
this.props.navigation.navigate('HomeScreen',{isLogin:true})
let user_data = res.data.user;
this.props.appSetUser(user_data)
}
this.setState({ isLoading: false })
} else {
setTimeout(() => {
this.setState({isLoading:false},() => {
this.props.navigation.navigate('HomeScreen',{isLogin:true})
})
}, 300);
Alert.alert(null, 'ท่านกรอก บัญชีผู้ใช้งาน หรือ รหัสผ่านผิด')
}, 600);
this.setState({isLoading:false})
}
} else {
setTimeout(() => {
Alert.alert(null, 'ท่านกรอก บัญชีผู้ใช้งาน หรือ รหัสผ่านผิด')
}, 600);
}
this.setState({isLoading:false})
})
})
} else {
Alert.alert(null, 'ท่านกรอกรูปแบบโทรศัพท์ไม่ถูกต้อง')
}
} else {
Alert.alert(null, 'กรุณากรอกข้อมูลให้ครบถ้วน')
}
}
})
};
render() {
return (

View File

@ -26,15 +26,24 @@ class RegisterScreen extends Component {
_onNextStep = async () => {
var regex = /^\d+$/;
if (this.state.user.mobile && this.state.user.password && this.state.user.password == this.state.user.password_confirm) {
if (regex.test(this.state.user.mobile) === true) {
console.log('mobile ===> ', this.state.user)
if (this.state.user.mobile && this.state.user.password && this.state.user.password && this.state.user.password_confirm) {
if (regex.test(this.state.user.mobile) === false) {
Alert.alert(null, 'ท่านกรอกรูปแบบโทรศัพท์ไม่ถูกต้อง')
} else if (this.state.user.password !== this.state.user.password_confirm){
Alert.alert(null, 'รหัสผ่านไม่ตรงกัน')
} else {
this.props.appSetUser(this.state.user)
this.props.navigation.navigate('RegisterFormLogin');
} else {
Alert.alert(null, 'ท่านกรอกรูปแบบโทรศัพท์ไม่ถูกต้อง')
}
} else {
Alert.alert(null, 'รหัสผ่านไม่ตรงกัน')
if(!this.state.user.mobile){
Alert.alert(null, 'กรุณากรอกเบอร์โทรศัพท์')
} else if(!this.state.user.password){
Alert.alert(null, 'กรุณากรอกรหัสผ่าน')
} else if(!this.state.user.password_confirm){
Alert.alert(null, 'กรุณากรอกยืนยันรหัสผ่าน')
}
}
}

View File

@ -1,28 +1,28 @@
import React, { Component } from 'react'
import { Alert, ScrollView, TouchableOpacity, View, Platform, KeyboardAvoidingView } from 'react-native'
import React, {Component} from 'react'
import {Alert, ScrollView, TouchableOpacity, View, Platform, KeyboardAvoidingView} from 'react-native'
import Image from 'react-native-fast-image'
import { CustomStepIndicator } from '../../components/StepIndicator'
import { CustomInput } from '../../components/CustomInput'
import { CustomButton } from '../../components/CustomButton'
import {CustomStepIndicator} from '../../components/StepIndicator'
import {CustomInput} from '../../components/CustomInput'
import {CustomButton} from '../../components/CustomButton'
import Icon from 'src/components/Icon'
import { bindActionCreators } from 'redux'
import { appSetUser } from '../../redux/app/action'
import { connect } from 'react-redux'
import { Picker } from 'native-base'
import {bindActionCreators} from 'redux'
import {appSetUser} from '../../redux/app/action'
import {connect} from 'react-redux'
import {Picker} from 'native-base'
import moment from 'moment'
import { BackgroundImage_RegisterForm } from '../../components/BackgroundImage_RegisterForm'
import {BackgroundImage_RegisterForm} from '../../components/BackgroundImage_RegisterForm'
import LinearGradient from 'react-native-linear-gradient'
import Text from '../../components/Text'
import { getBuildingByProjectId, project } from '../../api/UserApi'
import {getBuildingByProjectId, project} from '../../api/UserApi'
import ImagePicker from 'react-native-image-crop-picker'
import ActionSheet from 'react-native-action-sheet'
import CustomDatePicker from '../room/CustomDatePicker';
import { t } from '../../utils/i18n'
import {t} from '../../utils/i18n'
let ACTIONSHEET_BUTTONS = [
'ถ่ายรูป',
'รูปจากแกลอรี่',
t('cancel')
t('cancel')
]
let CANCEL_INDEX = 2
@ -35,12 +35,14 @@ class RegisterFormLoginScreen extends Component {
project_list: [],
building_list: [],
selected_project: 0,
project_name:t('choose_project'),
project_name: t('choose_project'),
image_url: require('../../../assets/images/profile.png'),
enableSummit: false,
checkFullname: false,
checkCitizenID: false,
checkBirthDate: null
checkBirthDate: null,
checkRoomNo: false,
is_customer: true
}
this._onNextStep = this._onNextStep.bind()
this.onImagePick = this.onImagePick.bind(this)
@ -52,7 +54,7 @@ class RegisterFormLoginScreen extends Component {
this.setDefaultUserData()
}
setDefaultUserData(){
setDefaultUserData() {
this.setState({
user: {
...this.state.user,
@ -94,7 +96,14 @@ class RegisterFormLoginScreen extends Component {
_onNextStep = async () => {
// if (this.state.user.email && this.state.user.mobile) {
if (this.state.user.mobile && this.state.user.tax_id && this.state.user.name && this.state.user.birth_date) {
// let tax_id = this.state.user && this.state.user.tax_id
// if(!tax_id && !this.state.is_customer){
// tax_id = (Math.floor(1000000000000 + Math.random() * 9000000000000)).toString();
// }
if (this.state.user.mobile
// && this.state.is_customer && this.state.user.tax_id && (this.state.user.tax_id.toString()).length > 0
// && tax_id.length > 0
&& this.state.user.name) {
/*var email_validate = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
if (email_validate.test(this.state.user.email) === true) {
this.props.appSetUser(this.state.user)
@ -102,16 +111,26 @@ class RegisterFormLoginScreen extends Component {
} else {
Alert.alert(null, 'ท่านกรอกรูปแบบอีเมลไม่ถูกต้อง')
}*/
console.log('check user data next <<<<<<<< ',this.state.user);
this.props.appSetUser(this.state.user)
// next page !!
this.props.navigation.navigate('RegisterProfile')
console.log('check user data next <<<<<<<< ', this.state.user);
this.setState({
user: {
...this.state.user,
// tax_id: !this.state.is_customer ? Math.floor(1000000000000 + Math.random() * 9000000000000) : this.state.user.tax_id,
// is_customer: this.state.is_customer
}
}, () => {
// console.log('user >>> ', this.state.user)
this.props.appSetUser(this.state.user)
// next page !!
this.props.navigation.navigate('RegisterProfile', {image_url: this.state.image_url})
})
} else {
console.log('กรุณากรอกข้อมูลให้ครบถ้วน')
Alert.alert(null, 'กรุณากรอกข้อมูลให้ครบถ้วน')
}
}
onImagePick () {
onImagePick() {
ImagePicker.openPicker({
width: 300,
height: 300,
@ -125,7 +144,7 @@ class RegisterFormLoginScreen extends Component {
name: 'image_profile.jpg',
}
this.setState({
image_url: { uri: `data:${image.mime};base64,` + image.data, width: image.width, height: image.height },
image_url: {uri: `data:${image.mime};base64,` + image.data, width: image.width, height: image.height},
images: null,
user: {
...this.state.user,
@ -135,7 +154,7 @@ class RegisterFormLoginScreen extends Component {
}).catch(e => alert(e))
}
onTakeCamera () {
onTakeCamera() {
ImagePicker.openCamera({
cropping: true,
width: 300,
@ -149,7 +168,7 @@ class RegisterFormLoginScreen extends Component {
name: 'image_profile.jpg',
}
this.setState({
image_url: { uri: image.path, width: image.width, height: image.height, mime: image.mime },
image_url: {uri: image.path, width: image.width, height: image.height, mime: image.mime},
images: null,
user: {
...this.state.user,
@ -159,27 +178,43 @@ class RegisterFormLoginScreen extends Component {
}).catch(e => alert(e))
}
handleRequired = (e,type) => {
// e = value
console.log(type + " : ", e);
switch(type) {
case 'fullname':
// code block
this.setState(() => ({ ['checkFullname']: e }));
break;
case 'citizen_id':
this.setState(() => ({ ['checkCitizenID']: e }));
break;
default:
// code block
}
validateNextStepBtn(){
if (this.state.checkFullname.length > 0 && this.state.user.project && this.state.user.building && this.state.checkRoomNo.length > 0) {
this.setState({
enableSummit: true
});
} else {
this.setState({
enableSummit: false
});
}
}
// console.log(this.state.user.birth_date);
// check all
if(this.state.checkFullname.length >= 1 && this.state.checkCitizenID.length >= 1 && typeof this.state.user.birth_date != 'undefined'){
this.setState(() => ({ ['enableSummit']: true }));
}
handleRequired = (e, type) => {
// e = value
switch (type) {
case 'fullname':
// code block
this.setState(() => ({['checkFullname']: e}), () => {
this.validateNextStepBtn()
});
break;
case 'room':
// code block
this.setState(() => ({['checkRoomNo']: e}), () => {
this.validateNextStepBtn()
});
break;
/*case 'citizen_id':
this.setState(() => ({['checkCitizenID']: e}));
break;*/
default:
this.validateNextStepBtn()
// code block
}
// console.log(this.state.user.birth_date);
// check all
}
render() {
@ -193,100 +228,111 @@ class RegisterFormLoginScreen extends Component {
resizeMode: 'cover'
}}
>
<KeyboardAvoidingView style={{flex:1}} keyboardVerticalOffset={Platform.OS == 'ios' ? 75 : 0} behavior={Platform.OS == 'ios' ? "padding" : ""} enabled>
<BackgroundImage_RegisterForm>
<ScrollView showsVerticalScrollIndicator={false} style={{ flex: 1 }}>
<View style={styles.container}>
<View style={[styles.step_indicator]}>
<CustomStepIndicator
currentStep={2}
totalStep={3}
/>
</View>
<View style={styles.logo}>
<View
style={{
flexGrow: 1,
backgroundColor: '#3AA40C',
alignItems: 'center',
paddingVertical: 20,
position: 'relative'
}}
>
<TouchableOpacity
style={{
backgroundColor: '#FFF',
borderRadius: 50,
padding: 5,
justifyContent: 'center',
alignItems: 'center',
position: 'absolute',
right: '37%',
top: '30%',
zIndex: 1
}}
onPress={() => {
ActionSheet.showActionSheetWithOptions({
options: ACTIONSHEET_BUTTONS,
cancelButtonIndex: CANCEL_INDEX,
// destructiveButtonIndex: DESTRUCTIVE_INDEX,
// tintColor: 'blue'
},
(buttonIndex) => {
// console.log('button clicked :', buttonIndex)
if (buttonIndex == 0) {
this.onTakeCamera()
} else if (buttonIndex == 1) {
this.onImagePick()
}
})
}}
>
<Icon
name={'ic_outline_camera'}
size={20}
color={'#8BC34A'}
/>
</TouchableOpacity>
<Image
style={{
width: 100,
height: 100,
borderRadius: 50,
borderColor: 'white',
borderWidth: 2
}}
source={this.state.image_url}
<KeyboardAvoidingView style={{flex: 1}} keyboardVerticalOffset={Platform.OS == 'ios' ? 75 : 0} behavior={Platform.OS == 'ios' ? "padding" : ""} enabled>
<BackgroundImage_RegisterForm>
<ScrollView showsVerticalScrollIndicator={false} style={{flex: 1}}>
<View style={styles.container}>
<View style={[styles.step_indicator]}>
<CustomStepIndicator
currentStep={2}
totalStep={3}
/>
</View>
{/*<Text> LOGO </Text>*/}
</View>
<View style={{ flex: 1 }}>
<View style={[styles.form]}>
<Text style={styles.headerTitle}> {t('profile')} </Text>
<View style={styles.row}>
<CustomInput
labelName={t('fullname')}
//New Code style
style={styles.register_input}
labelColor={'white'}
placeholderTextColor={'white'}
//New Code style
onEndEditing={e => {
let input = e.nativeEvent.text
this.setState({
user: {
...this.state.user,
name: input,
}
})
<View style={styles.logo}>
<View
style={{
flex: 1,
flexGrow: 1,
backgroundColor: '#3AA40C',
alignItems: 'center',
paddingVertical: 20,
position: 'relative'
}}
>
<TouchableOpacity
style={{
backgroundColor: '#FFF',
borderRadius: 50,
padding: 5,
justifyContent: 'center',
alignItems: 'center',
position: 'absolute',
right: '37%',
top: '30%',
zIndex: 1
}}
onChangeText={(evt) => this.handleRequired(evt, "fullname")}
placeholder={t('specific_fullname')}
placeholderTextColor={'#FFFFFF40'}
onPress={() => {
ActionSheet.showActionSheetWithOptions({
options: ACTIONSHEET_BUTTONS,
cancelButtonIndex: CANCEL_INDEX,
// destructiveButtonIndex: DESTRUCTIVE_INDEX,
// tintColor: 'blue'
},
(buttonIndex) => {
// console.log('button clicked :', buttonIndex)
if (buttonIndex == 0) {
this.onTakeCamera()
} else if (buttonIndex == 1) {
this.onImagePick()
}
})
}}
>
<Icon
name={'ic_outline_camera'}
size={20}
color={'#8BC34A'}
/>
</TouchableOpacity>
<Image
style={{
width: 100,
height: 100,
borderRadius: 50,
borderColor: 'white',
borderWidth: 2
}}
source={this.state.image_url}
/>
</View>
{/* <View style={styles.row}>
{/*<Text> LOGO </Text>*/}
</View>
<View style={{flex: 1}}>
<View style={[styles.form]}>
<Text style={styles.headerTitle}> {t('profile')} </Text>
<View style={styles.row}>
<CustomInput
labelName={t('fullname')}
//New Code style
style={styles.register_input}
labelColor={'white'}
placeholderTextColor={'white'}
//New Code style
onEndEditing={e => {
let input = e.nativeEvent.text
this.setState({
user: {
...this.state.user,
name: input,
}
})
}}
value={this.state.user.name}
onChangeText={(evt) => {
this.handleRequired(evt, "fullname")
this.setState({
user:{
...this.state.user,
name: evt.replace(/\u0020/, '\u00a0')
}
})
}}
placeholder={t('specific_fullname')}
placeholderTextColor={'#FFFFFF40'}
/>
</View>
{/* <View style={styles.row}>
<CustomInput
//New Code style
keyboardType={'email-address'}
@ -309,7 +355,7 @@ class RegisterFormLoginScreen extends Component {
placeholderTextColor={'#FFFFFF40'}
/>
</View> */}
<View style={styles.row}>
{/*<View style={styles.row}>
<View style={styles.row_grow_first}>
<View
style={{
@ -359,9 +405,9 @@ class RegisterFormLoginScreen extends Component {
</View>
</View>
</View>
</View>
{/* /// */}
<View style={styles.row}>
</View>*/}
{/* /// */}
{/*<View style={styles.row}>
<View style={styles.row_grow}>
<CustomDatePicker titleText={t('birth_date')} dateText={this.state.user.text_birth} maxDate={new Date()} handleDate={(data) => {
this.setState({
@ -371,214 +417,283 @@ class RegisterFormLoginScreen extends Component {
birth_date_show: moment(data).format('MM/DD/YYYY'),
text_birth: moment(data).add(543, 'years').format('DD-MM-YYYY')
}
})
}, () => {
this.handleRequired(data, "birth_date");
})
}}/>
</View>
</View>
<View style={styles.row}>
<CustomInput
maxLength={13}
style={styles.register_input}
labelColor={'white'}
placeholderTextColor={'white'}
labelName={t('citizen_id')}
onEndEditing={e => {
let input = e.nativeEvent.text
this.setState({
user: {
...this.state.user,
tax_id: input
}
})
}}
onChangeText={(evt) => this.handleRequired(evt, "citizen_id")}
placeholder={t('citizen_id_13')}
placeholderTextColor={'#FFFFFF40'}
/>
</View>
<View style={styles.row}>
<CustomInput
maxLength={10}
//New Code style
style={styles.register_input}
labelColor={'white'}
placeholderTextColor={'white'}
//New Code style
labelName={t('phone')}
onEndEditing={e => {
let input = e.nativeEvent.text
this.setState({
user: {
...this.state.user,
mobile: input
}
})
}}
placeholder={t('phone')}
placeholderTextColor={'#FFFFFF40'}
value={this.state.user.mobile || ''}
/>
</View>
<Text style={styles.headerTitle}> {t('accom_info')} </Text>
<View style={styles.row}>
<View
style={{
flexGrow: 1,
flexDirection: 'row',
height: 40,
paddingHorizontal: 5,
backgroundColor: 'rgba(255,255,255,0.3)',
fontFamily: 'Prompt-Regular',
borderRadius: 30
}}
>
<View
style={{
justifyContent: 'center',
paddingLeft: 5,
paddingRight: 5
}}
>
<Text
style={{
color: 'white'
}}
>
{t('project')}
</Text>
</View>
<View style={{ flex: 1 }}>
<Picker
// mode="dropdown"
style={{
height: 40,
color:'white'
}}
textStyle={{color:'white',fontFamily:'Prompt-Regular',fontSize:14}}
labelName={t('project')}
placeholder={t('choose_project')}
placeholderStyle={{color:'#FFFFFF40'}}
selectedValue={this.state.project_item}
onValueChange={e => {
// console.log('@@@@@@ project selected --------> ',e);
this.setState({
project_name: e.name,
project_item: e,
selected_project: e.id,
user: {
...this.state.user,
project: e.code,
project_name : e.name
},
}, () => {
// console.log('check project selected --------> ',this.state.project_name);
this.getBuildingList()
})
}}
>
{this.state.project_list.map((item) => {
return <Picker.Item label={item.name} value={item} key={'project_'+item}/>
})}
</Picker>
</View>
</View>
</View>
<View style={styles.row}>
<View
style={{
flexGrow: 1,
flexDirection: 'row',
height: 40,
maxHeight: 48,
minHeight: 40,
paddingHorizontal: 5,
backgroundColor: 'rgba(255,255,255,0.3)',
fontFamily: 'Prompt-Regular',
borderRadius: 30
}}
>
<View
style={{
justifyContent: 'center',
paddingLeft: 5,
paddingRight: 5
}}
>
<Text
style={{
color: 'white'
}}
>
{t('building')}
</Text>
</View>
<View style={{ flex: 1 }}>
<Picker
// mode="dropdown"
style={{
height: 40,
color:'white'
}}
textStyle={{color:'white',fontFamily:'Prompt-Regular',fontSize:14}}
labelName={t('building')}
placeholder={'เลือกอาคาร'}
placeholderStyle={{color:'#FFFFFF40'}}
selectedValue={this.state.user.building}
onValueChange={e => {
this.setState({
user: {
...this.state.user,
building: e
}
})
}}
>
{this.state.building_list.map((item) => {
return <Picker.Item label={item.room_build} value={item.room_build} key={'building_'+item.room_build}/>
})}
</Picker>
</View>
</View>
<View style={styles.row_grow}>
</View>*/}
<View style={styles.row}>
<CustomInput
maxLength={10}
//New Code style
style={styles.register_input}
labelColor={'white'}
placeholderTextColor={'white'}
//New Code style
labelName={t('room2')}
labelName={t('phone')}
onEndEditing={e => {
let input = e.nativeEvent.text
this.setState({
user: {
...this.state.user,
room: input
mobile: input
}
})
}}
placeholder={t('room_no')}
placeholder={t('phone')}
placeholderTextColor={'#FFFFFF40'}
value={this.state.user.mobile || ''}
/>
</View>
{/*<View style={styles.userTypeContainer}>
<TouchableOpacity style={styles.radioInput}
onPress={() => {this.setState({
is_customer: true }, () => {
this.handleRequired(this.state.is_customer, "user_type");
})
}}
>
{
this.state.is_customer ?
<Image source={require('../../../assets/images/radio_button_checked.png')} style={{width: 20, height: 20, marginRight: 5}} />
: <Image source={require('../../../assets/images/radio_button.png')} style={{width: 20, height: 20, marginRight: 5}} />
}
<Text style={{color: 'white'}}>{t('customer')}</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.radioInput}
onPress={() => {
this.setState({
is_customer: false,
user: {
...this.state.user,
tax_id: '',
building: '',
room: ''
},
checkCitizenID: false
}, () => {
this.handleRequired(this.state.is_customer, "user_type");
})
}}
>
{
this.state.is_customer ?
<Image source={require('../../../assets/images/radio_button.png')} style={{width: 20, height: 20, marginRight: 5}} />
: <Image source={require('../../../assets/images/radio_button_checked.png')} style={{width: 20, height: 20, marginRight: 5}} />
}
<Text style={{color: 'white'}}>{t('guest')}</Text>
</TouchableOpacity>
</View>*/}
{/*{
this.state.is_customer &&
<View style={styles.row}>
<CustomInput
maxLength={13}
style={styles.register_input}
labelColor={'white'}
placeholderTextColor={'white'}
labelName={t('citizen_id')}
onEndEditing={e => {
let input = e.nativeEvent.text
this.setState({
user: {
...this.state.user,
tax_id: input
}
})
}}
onChangeText={(evt) => this.handleRequired(evt, "citizen_id")}
placeholder={t('citizen_id_13')}
placeholderTextColor={'#FFFFFF40'}
/>
</View>
</View>
<View style={styles.buttons}>
<View style={styles.row_grow}>
<CustomButton
// disabled="true"
style={ this.state.enableSummit ? [styles.btn_next_register , styles.enableNext]: [styles.btn_next_register , styles.disableNext] } // enableNext
title={t('next')}
sizeText={14}
onPress={this._onNextStep}
/>
}*/}
<Text style={styles.headerTitle}> {t('accom_info')} </Text>
<View style={styles.row}>
<View
style={{
flexGrow: 1,
flexDirection: 'row',
height: 40,
paddingHorizontal: 5,
backgroundColor: 'rgba(255,255,255,0.3)',
fontFamily: 'Prompt-Regular',
borderRadius: 30
}}
>
<View
style={{
justifyContent: 'center',
paddingLeft: 5,
paddingRight: 5
}}
>
<Text
style={{
color: 'white'
}}
>
{t('project')}
</Text>
</View>
<View style={{flex: 1}}>
<Picker
// mode="dropdown"
style={{
height: 40,
color: 'white'
}}
textStyle={{color: 'white', fontFamily: 'Prompt-Regular', fontSize: 14}}
labelName={t('project')}
placeholder={t('choose_project')}
placeholderStyle={{color: '#FFFFFF40'}}
selectedValue={this.state.project_item}
onValueChange={e => {
// console.log('@@@@@@ project selected --------> ',e);
this.setState({
project_name: e.name,
project_item: e,
selected_project: e.id,
user: {
...this.state.user,
project: e.code,
project_name: e.name
},
}, () => {
// console.log('check project selected --------> ',this.state.project_name);
this.handleRequired(e, "project")
this.getBuildingList()
})
}}
>
{this.state.project_list.map((item) => {
return <Picker.Item label={item.name} value={item} key={'project_' + item}/>
})}
</Picker>
</View>
</View>
</View>
{
this.state.is_customer &&
<View style={styles.row}>
<View
style={{
flexGrow: 1,
flexDirection: 'row',
height: 40,
maxHeight: 48,
minHeight: 40,
paddingHorizontal: 5,
backgroundColor: 'rgba(255,255,255,0.3)',
fontFamily: 'Prompt-Regular',
borderRadius: 30
}}
>
<View
style={{
justifyContent: 'center',
paddingLeft: 5,
paddingRight: 5
}}
>
<Text
style={{
color: 'white'
}}
>
{t('building')}
</Text>
</View>
<View style={{flex: 1}}>
<Picker
// mode="dropdown"
style={{
height: 40,
color: 'white'
}}
textStyle={{color: 'white', fontFamily: 'Prompt-Regular', fontSize: 14}}
labelName={t('building')}
placeholder={'เลือกอาคาร'}
placeholderStyle={{color: '#FFFFFF40'}}
selectedValue={this.state.user.building}
onValueChange={e => {
this.setState({
user: {
...this.state.user,
building: e
}
}, () => {
this.handleRequired(e, "building")
})
}}
>
{this.state.building_list.map((item) => {
return <Picker.Item label={item.room_build} value={item.room_build} key={'building_' + item.room_build}/>
})}
</Picker>
</View>
</View>
<View style={styles.row_grow}>
<CustomInput
//New Code style
style={styles.register_input}
labelColor={'white'}
placeholderTextColor={'white'}
//New Code style
labelName={t('room2')}
onChangeText={e => {
// let input = e.nativeEvent.text
this.setState({
user: {
...this.state.user,
room: e
}
}, () => {
this.handleRequired(e, "room")
})
}}
placeholder={t('room_no')}
placeholderTextColor={'#FFFFFF40'}
/>
</View>
</View>
}
<View style={[styles.buttons, {display: this.state.enableSummit ? 'none' : 'flex'}]}>
<View style={styles.row_grow}>
<CustomButton
// disabled="true"
style={styles.disableNext} // enableNext
title={t('next')}
sizeText={14}
// onPress={this._onNextStep}
/>
</View>
</View>
<View style={[styles.buttons, {display: this.state.enableSummit ? 'flex' : 'none'}]}>
<View style={styles.row_grow}>
<CustomButton
// disabled="true"
style={styles.enableNext} // enableNext
title={t('next')}
sizeText={14}
onPress={this._onNextStep}
/>
</View>
</View>
</View>
</View>
</View>
</View>
</ScrollView>
</BackgroundImage_RegisterForm>
</ScrollView>
</BackgroundImage_RegisterForm>
</KeyboardAvoidingView>
</LinearGradient>
)
@ -592,6 +707,7 @@ const styles = {
flexDirection: 'column'
},
logo: {
flex: 1,
backgroundColor: '#3AA40C',
height: '20%',
flexDirection: 'row',
@ -613,7 +729,8 @@ const styles = {
paddingBottom: 0
},
step_indicator: {
backgroundColor: '#3AA40C'
backgroundColor: '#3AA40C',
flex: 1
},
buttons: {
flexDirection: 'row',
@ -642,22 +759,50 @@ const styles = {
fontFamily: 'Prompt-Regular',
borderRadius: 30
},
disableNext :{
disableNext: {
opacity: 0.65,
cursor: "not-allowed",
backgroundColor: '#AAAAAA'
},
enableNext :{
enableNext: {
opacity: 1,
color: '#FFFFFF',
backgroundColor: '#145EB3'
}
},
userTypeContainer: {
flex: 1,
flexDirection: 'row',
paddingTop: 5,
paddingBottom: 10
},
radioInput: {
flex: 1,
flexDirection: 'row',
alignItems: 'center'
},
custom_button_container: {
// flex:1,
// flexDirection: 'row',
height: 35,
abckgroundColor: '#FF9500',
borderRadius: 5,
width: '100%',
justifyContent: 'center',
alignItems: 'center',
},
icon: {
justifyContent: 'center',
// alignItems: '',
// flex: 1,
paddingLeft: 5,
paddingRight: 5
},
}
const mapDisPatchToProps = state => {
return state.app
}
const setUser = dispatch => bindActionCreators({ appSetUser }, dispatch)
const setUser = dispatch => bindActionCreators({appSetUser}, dispatch)
export default connect(
mapDisPatchToProps,
setUser

View File

@ -5,14 +5,15 @@ import { CustomStepIndicator } from '../../components/StepIndicator'
import GetWidthHeightDevice from '../../components/GetWidthHeightDevice'
import { CustomButton } from '../../components/CustomButton'
import { connect } from 'react-redux'
import { register, registerDevice, testConnect } from '../../api/UserApi'
import {checkPaymentMeter, register, registerDevice, testConnect} from '../../api/UserApi'
import { bindActionCreators } from 'redux'
import { appSetDevice, appSetPushToken, appSetToken, appSetUser } from '../../redux/app/action'
import firebase, { Notification } from 'react-native-firebase'
import {appSetDevice, appSetPushToken, appSetToken, appSetUser, setPopupNotification} from '../../redux/app/action'
import messaging from "@react-native-firebase/messaging";
import moment from 'moment'
import { setToken } from '../../api/api'
import { BackgroundImage_RegisterForm } from '../../components/BackgroundImage_RegisterForm'
import LinearGradient from 'react-native-linear-gradient';
import DeviceInfo from 'react-native-device-info';
import Text from '../../components/Text';
import { t } from '../../utils/i18n'
@ -23,7 +24,8 @@ class RegisterProfileScreen extends Component {
this.state = {
auth: false,
disableButton: false
disableButton: false,
image_url: require('../../../assets/images/profile.png'),
}
this._register = this._register.bind(this);
@ -36,27 +38,31 @@ class RegisterProfileScreen extends Component {
if (!this.props.push_token) {
this.initNotification();
}
this.setState({
image_url: this.props.navigation.getParam('image_url', require('../../../assets/images/profile.png'))
})
}
initNotification = async () => {
await this.setPermission()
const fcmToken = await firebase.messaging().getToken()
const fcmToken = await messaging().getToken()
console.log('fcmToken', fcmToken)
if (fcmToken) {
this.props.appSetPushToken(fcmToken)
console.log('fcmToken', this.props)
} else {
Alert.alert(null, 'Cannot get push token.', [{ text: 'ok' }])
}
}
setPermission = async () => {
try {
const enabled = await firebase.messaging().hasPermission()
const enabled = await messaging().hasPermission()
if (!enabled) {
await firebase.messaging().requestPermission()
await messaging().requestPermission()
}
} catch (error) {
console.log('error', error)
@ -64,22 +70,30 @@ class RegisterProfileScreen extends Component {
}
_register() {
async _register() {
this.setState({disableButton: true})
if (!this.props.device && this.props.push_token) {
const resultSendDevice = registerDevice(this.props.push_token)
const resultSendDevice = await registerDevice(this.props.push_token)
if (resultSendDevice.ok && resultSendDevice.data.success) {
this.props.appSetDevice(resultSendDevice.data.device)
}
}
if (!this.props.device || !this.props.push_token) {
Alert.alert(null, 'Cannot get push token or device.', [{ text: 'ok' }])
return;
}
let systemName = DeviceInfo.getSystemName();
let deviceId = null
if(systemName == "Android") {
if (!this.props.device) {
Alert.alert(null, 'Cannot get push token or device.', [{ text: 'ok' }])
return;
}
deviceId = this.props.device.id
}
register({
...this.props.user,
device_id: this.props.device.id
device_id: deviceId,
name: this.props.user.name.replace(/\u00a0/g, /\u0020/),
fcm_token: this.props.push_token
}).then(
(res) => {
if (res.ok && res.data.success) {
@ -89,8 +103,40 @@ class RegisterProfileScreen extends Component {
this.props.appSetUser(res.data.customer)
this.props.appSetToken(res.data.token)
setToken(token)
Alert.alert(null, t('register_success'), [{ text: t('ok') }])
this.props.navigation.navigate('HomeScreen')
Alert.alert(
'',
t('register_success'),
[
{ text: 'OK', onPress: () => {
/*checkPaymentMeter()
.then(result => {
if(result.data){
let data = {
pending_payment: result.data.pending_payment != null ? result.data.pending_payment : 0,
is_notified_electric: result.data.user.is_notified_electric,
is_notified_overdue: result.data.user.is_notified_overdue,
is_notified_meter: result.data.user.is_notified_meter,
payment_id: result.data.payment_id,
notified_meter_at: result.data.notified_meter_at ? result.data.notified_meter_at : moment().format('DD MMM YYYY')
}
this.props.setPopupNotification(data)
}
})*/
this.setState({isLoading:false},() => {
this.props.navigation.navigate('HomeScreen',{isLogin:true})
})
}
}
],
{ cancelable: false }
)
//Alert.alert(null, t('register_success'), [{ text: t('ok') }])
//this.props.navigation.navigate('HomeScreen')
}
} else {
this.props.appSetUser(null)
@ -125,7 +171,7 @@ class RegisterProfileScreen extends Component {
}}>
<Image
style={{ width: 100, height: 100, borderRadius: 50, borderColor: 'white', borderWidth: 2 }}
source={require('../../../assets/images/profile.png')}
source={this.state.image_url}
/>
</View>
{/*<Text> LOGO </Text>*/}
@ -138,10 +184,10 @@ class RegisterProfileScreen extends Component {
<View style={[styles.table]}>
<View style={styles.row_title}>
<Text style={styles.title_data}> </Text>
<Text style={styles.title_data}> {t('name')} </Text>
{/* <Text style={styles.title_data}> อีเมล </Text> */}
<Text style={styles.title_data}> {t('gender')} </Text>
<Text style={styles.title_data}> {t('birth_date')} </Text>
{/*<Text style={styles.title_data}> {t('gender')} </Text>*/}
{/*<Text style={styles.title_data}> {t('birth_date')} </Text>*/}
<Text style={styles.title_data}> {t('phone2')} </Text>
</View>
{
@ -149,8 +195,8 @@ class RegisterProfileScreen extends Component {
<View style={styles.row_data}>
<Text style={styles.detail_data}> {user.name} </Text>
{/* <Text style={styles.detail_data}> {user.email} </Text> */}
<Text style={styles.detail_data}> {user.gender} </Text>
<Text style={styles.detail_data}> {moment(user.birth_date_show).add(543, 'years').format('D MMMM YYYY')} </Text>
{/*<Text style={styles.detail_data}> {user.gender} </Text>*/}
{/*<Text style={styles.detail_data}> {moment(user.birth_date_show).add(543, 'years').format('D MMMM YYYY')} </Text>*/}
<Text style={styles.detail_data}> {user.mobile} </Text>
</View>
}
@ -160,8 +206,8 @@ class RegisterProfileScreen extends Component {
<View style={[styles.table]}>
<View style={styles.row_title}>
<Text style={styles.title_data}> {t('project')} </Text>
<Text style={styles.title_data}> {t('building')} </Text>
<Text style={styles.title_data}> {t('room2')} </Text>
<Text style={styles.title_data}> {t('building')} </Text>
<Text style={styles.title_data}> {t('room2')} </Text>
</View>
{
user !== null &&
@ -276,5 +322,5 @@ const styles = {
const mapDisPatchToProps = state => {
return state.app
}
const setUser = dispatch => bindActionCreators({ appSetToken, appSetPushToken, appSetDevice, appSetUser }, dispatch)
const setUser = dispatch => bindActionCreators({ appSetToken, appSetPushToken, appSetDevice, appSetUser, setPopupNotification }, dispatch)
export default connect(mapDisPatchToProps, setUser)(RegisterProfileScreen)

View File

@ -4,14 +4,25 @@ import Text from '../../components/Text';
import { Badge } from 'native-base'
import { WebView } from 'react-native-webview';
import { t } from '../../utils/i18n'
import {connect} from "react-redux";
import {bindActionCreators} from "redux";
import {appCleanUser} from "../../redux/app/action";
import I18n from "i18n-js";
export default class TermsAndCondition extends Component {
class TermsAndCondition extends Component {
constructor(props) {
super(props);
this.state = {
currentLocale: 'th'
};
}
componentDidMount(): void {
this.setState({
currentLocale : I18n.currentLocale()
})
}
render() {
return (
<ScrollView contentContainerStyle={{flex:1}}>
@ -26,7 +37,7 @@ export default class TermsAndCondition extends Component {
flex: 1,
}}
originWhitelist={['*']}
source={{ uri: 'https://www.csasset.co.th/Privacy-Policy-TH.htm'}}
source={ this.state.currentLocale === 'th' ? { uri: 'https://app.csasset.co.th/privacy-policy'} : {uri: 'https://app.csasset.co.th/privacy-policy-en'}}
javaScriptEnabled={true}
domStorageEnabled={true}
onNavigationStateChange={(event) => {
@ -41,6 +52,7 @@ export default class TermsAndCondition extends Component {
</View>
<View style={{flexDirection:'row',justifyContent:'space-around',height:60}}>
<TouchableOpacity onPress={() => {
this.props. appCleanUser();
this.props.navigation.goBack()
}}>
<View>
@ -64,3 +76,6 @@ export default class TermsAndCondition extends Component {
);
}
}
const clearUser = dispatch => bindActionCreators({appCleanUser}, dispatch);
export default connect(null, clearUser)(TermsAndCondition);

View File

@ -32,6 +32,12 @@ export default class Meter extends Component {
this.getMeter = this.getMeter.bind(this)
}
componentWillUnmount() {
if(this.props && this.props.navigation && this.props.navigation.state && this.props.navigation.state.params && this.props.navigation.state.params.getNotification){
this.props.navigation.state.params.getNotification()
}
}
getMeter(){
this.setState({
isLoading: true
@ -40,8 +46,12 @@ export default class Meter extends Component {
.then(res => {
console.log('check response meter list ----------> ',res.data);
if(res.ok){
// let room_list = [
// {id: 87576, name: 'CN1-005', project_name: 'CNK', electric: 1264, water: 0}
// ]
this.setState({
room_list: res.data.rooms,
// room_list,
cost_list: res.data.data,
})
}
@ -85,7 +95,7 @@ export default class Meter extends Component {
}, () => {
this.selectedImage(this.state.image_url)
})
}).catch(e => alert(e))
}).catch(e => {console.log('e >>>> ', e)})
}
selectedImage(image_meter){
@ -104,7 +114,7 @@ export default class Meter extends Component {
_keyExtractor = (item, index) => 'meter_room_'+index;
_renderItem = ({item}) => (
<LinearGradient colors={['#4BAF3B', '#0E5E29']} style={{ height: 120, borderColor: 'white', borderRadius: 5, height: 120,paddingBottom:10, justifyContent:'space-between'}}>
<LinearGradient colors={['#4BAF3B', '#0E5E29']} style={{ borderColor: 'white', borderRadius: 5, height: 120,paddingBottom:10, justifyContent:'space-between'}}>
<View style={{ justifyContent: 'center',padding:16 }}>
<Text style={{ color: 'white', fontSize: 16 }}>{item.name}</Text>
<Text style={{ color: 'white', fontSize: 16 }}>{item.project_name}</Text>

View File

@ -11,7 +11,8 @@ export default class PEAMeter extends Component {
constructor(props) {
super(props);
this.state = {
numberMeter: '0',
numberMeter: '',
isLoading: false,
isVisible: false,
image: this.props.navigation.getParam('image','no-image'),
image_send: {},
@ -24,7 +25,7 @@ export default class PEAMeter extends Component {
this.onOK = this.onOK.bind(this)
this.onPopup = this.onPopup.bind(this)
this.onTakeCamera = this.onTakeCamera.bind(this)
this.postImageToOCR = this.postImageToOCR.bind(this)
//this.postImageToOCR = this.postImageToOCR.bind(this)
}
componentDidMount = () => {
@ -34,12 +35,12 @@ export default class PEAMeter extends Component {
type: this.state.image.mime,
name: `image_meter_${moment()}.jpg`,
}
},() => {
this.postImageToOCR()
})
}/*,() => {
//this.postImageToOCR()
}*/)
};
postImageToOCR(){
/*postImageToOCR(){
let param = {
image: this.state.image_send
}
@ -52,7 +53,7 @@ export default class PEAMeter extends Component {
})
}
})
}
}*/
onTextChanged(text){
this.setState({
@ -90,11 +91,11 @@ export default class PEAMeter extends Component {
this.setState({
image: this.state.image_url,
image_send: image_meter
},() => {
}/*,() => {
this.postImageToOCR()
})
}*/)
})
}).catch(e => Alert.alert('Error',e))
}).catch(e => {})
}
onConfirm(){
@ -102,20 +103,39 @@ export default class PEAMeter extends Component {
}
onOK(){
let param = {
room_id: this.state.room_id,
type: 'ค่าไฟ',
cost: 0,
amount: parseInt(this.state.numberMeter),
image: this.state.image_send
}
//send api
postMeter(param)
.then(res => {
console.log('response post meter ------> ',res.data)
this.onPopup()
this.props.navigation.goBack()
if (!this.state.isLoading) {
this.setState({
isLoading: true,
isVisible: false
}, () => {
let param = {
room_id: this.state.room_id,
type: 'ค่าไฟ',
cost: 0,
amount: parseInt(this.state.numberMeter),
image: this.state.image_send
}
//send api
postMeter(param)
.then(res => {
console.log('response post meter ------> ',res.data)
if(res.data.success) {
this.setState({ isLoading: false })
this.props.navigation.goBack()
} else {
this.setState({ isLoading: false })
Alert.alert('', res.data.message, [
{
text: 'ok',
onPress: () => {
}
}
], { cancelable: false })
}
})
.catch(err => this.setState({ isLoading: false }))
})
}
}
onPopup(){
@ -130,7 +150,7 @@ export default class PEAMeter extends Component {
<View style={{flex:1}}>
<SaveViewMeter amount={this.state.numberMeter} TypeName={'ไฟฟ้า'} TextChanged={this.onTextChanged} Confirm={this.onConfirm} ImageUri={this.state.image.uri} onTakeCamera={this.onTakeCamera} canConfirm={this.state.isConfirm}/>
</View>
<PopupMeter modalVisible={this.state.isVisible} onOk={this.onOK} onCancel={this.onPopup}/>
<PopupMeter modalVisible={this.state.isVisible} onOk={!this.state.isLoading ? this.onOK : null} onCancel={this.onPopup}/>
</ImageBackground>
);
}

View File

@ -26,7 +26,7 @@ export default class PopupMeter extends Component {
<TouchableOpacity style={{paddingHorizontal:15,}} onPress={() => {this.props.onCancel()}}>
<Text style={{color:'#00000040',fontSize: 14,}}>Cancel</Text>
</TouchableOpacity>
<TouchableOpacity style={{paddingHorizontal:15}} onPress={() => {this.props.onOk()}}>
<TouchableOpacity style={{paddingHorizontal:15}} onPress={() => {this.props.onOk && this.props.onOk()}}>
<Text style={{color:'#2C7C0B',fontSize: 14,}}>OK</Text>
</TouchableOpacity>
</View>

View File

@ -20,7 +20,7 @@ export default class SaveViewMeter extends Component {
<View style={{justifyContent:'center',alignItems:'center'}}>
<Image source={{uri:this.props.ImageUri}} resizeMode={'contain'} style={{borderRadius:5,height: 184,width:'100%'}}/>
</View>
<Text style={{color:'white',fontSize:14,textAlign:'center',marginVertical: 16,}}>ายเมอวนท {moment().format('DD/MM/YYYY HH:mm')} .</Text>
<Text style={{color:'black',fontSize:14,textAlign:'center',marginVertical: 16,}}>ายเมอวนท {moment().format('DD/MM/YYYY HH:mm')} .</Text>
<TouchableOpacity style={{height: 40,width: '100%',backgroundColor:'#007AFF',justifyContent:'center',alignItems:'center',borderRadius:5,flexDirection:'row'}}
onPress={this.props.onTakeCamera}>
<Icon nane={'ic_outline_camera'} size={22} color={'#FFFFFF'}/>

View File

@ -1,5 +1,5 @@
import React, { Component } from 'react';
import { View, Text } from 'react-native';
import { View, Text, Alert } from 'react-native';
import ImageBackground from 'react-native-fast-image'
import SaveViewMeter from './SaveViewMeter';
import PopupMeter from './PopupMeter';
@ -11,7 +11,8 @@ export default class WaterMeter extends Component {
constructor(props) {
super(props);
this.state = {
numberMeter: '0',
numberMeter: '',
isLoading: false,
isVisible: false,
image: this.props.navigation.getParam('image','no-image'),
image_send: {},
@ -24,7 +25,7 @@ export default class WaterMeter extends Component {
this.onOK = this.onOK.bind(this)
this.onPopup = this.onPopup.bind(this)
this.onTakeCamera = this.onTakeCamera.bind(this)
this.postImageToOCR = this.postImageToOCR.bind(this)
//this.postImageToOCR = this.postImageToOCR.bind(this)
}
componentDidMount = () => {
@ -34,12 +35,12 @@ export default class WaterMeter extends Component {
type: this.state.image.mime,
name: `image_meter_${moment()}.jpg`,
}
},() => {
this.postImageToOCR()
})
}/*,() => {
//this.postImageToOCR()
}*/)
};
postImageToOCR(){
/*postImageToOCR(){
let param = {
image: this.state.image_send
}
@ -52,7 +53,7 @@ export default class WaterMeter extends Component {
})
}
})
}
}*/
onTextChanged(text){
this.setState({
@ -90,32 +91,54 @@ export default class WaterMeter extends Component {
this.setState({
image: this.state.image_url,
image_send: image_meter
},() => {
this.postImageToOCR()
})
}/*,() => {
//this.postImageToOCR()
}*/)
})
}).catch(e => Alert.alert('Error',e))
}).catch(e => {})
}
onConfirm(){
this.onPopup()
}
onOK(){
let param = {
room_id: this.state.room_id,
type: 'ค่าน้ำ',
cost: 0,
amount: parseInt(this.state.numberMeter),
image: this.state.image_send
onOK() {
if (!this.state.isLoading) {
this.setState({
isLoading: true,
isVisible: false
}, () => {
let param = {
room_id: this.state.room_id,
type: 'ค่าน้ำ',
cost: 0,
amount: parseInt(this.state.numberMeter),
image: this.state.image_send
}
//send api
postMeter(param)
.then(res => {
console.log('response post meter ------> ',res.data)
if(res.data.success) {
this.setState({ isLoading: false })
this.props.navigation.goBack()
} else {
this.setState({
isLoading: false
}, () => {
Alert.alert('', res.data.message, [
{
text: 'ok',
onPress: () => {
}
}
], { cancelable: false })
})
}
})
.catch(err => this.setState({ isLoading: false }))
})
}
//send api
postMeter(param)
.then(res => {
console.log('response post meter ------> ',res.data)
this.onPopup()
this.props.navigation.goBack()
})
}
onPopup(){
@ -130,7 +153,7 @@ export default class WaterMeter extends Component {
<View style={{flex:1,padding:16}}>
<SaveViewMeter amount={this.state.numberMeter} TypeName={'น้ำ'} TextChanged={this.onTextChanged} Confirm={this.onConfirm} ImageUri={this.state.image.uri} onTakeCamera={this.onTakeCamera} canConfirm={this.state.isConfirm}/>
</View>
<PopupMeter modalVisible={this.state.isVisible} onOk={this.onOK} onCancel={this.onPopup}/>
<PopupMeter modalVisible={this.state.isVisible} onOk={!this.state.isLoading ? this.onOK : null} onCancel={this.onPopup}/>
</ImageBackground>
);
}

View File

@ -1,6 +1,6 @@
import React, { Component, Fragment } from 'react'
import {
View, ScrollView, Dimensions, TouchableOpacity, StyleSheet, FlatList, RefreshControl, Animated, ActivityIndicator, Alert
View, ScrollView, Dimensions, TouchableOpacity, StyleSheet, FlatList, RefreshControl, Animated, ActivityIndicator, Platform, Alert, Modal
} from 'react-native'
import Image from 'react-native-fast-image'
import ImageBackground from 'react-native-fast-image'
@ -11,7 +11,17 @@ import LinearGradient from 'react-native-linear-gradient'
import { BackgroundImage } from '../../components/BackgroundImage'
import Text from '../../components/Text'
import { NavigationEvents } from 'react-navigation'
import { getNews, getNewsPage, getUserProfile, getNewsByProject, login } from '../../api/UserApi'
import {
getNews,
getNewsPage,
getUserProfile,
getNewsByProject,
login,
registerDevice,
setPaymentLater,
setFillInMeterLater,
checkPaymentMeter } from '../../api/UserApi';
import { clearToken } from '../../api/api'
import { bindActionCreators } from 'redux'
import {
appSetDevice,
@ -21,19 +31,118 @@ import {
appCleanToken,
appCleanUser,
appSetNotification,
appSetProjectID
appSetProjectID,
appCleanProjectID
} from '../../redux/app/action'
import { connect } from 'react-redux'
import moment from 'moment'
import IndicatorLoading from '../../components/IndicatorLoading'
import { loginWithFacebook } from '../../components/FacebookUtils'
import { signinApple } from '../../components/AppleAuth'
import parseDateLocale from '../../utils/parseDateLocale'
import { from } from 'rxjs'
//import Slideshow from 'react-native-image-slider-show';
import appleAuth, {
AppleButton,
} from '@invertase/react-native-apple-authentication';
import { t, locale } from '../../utils/i18n'
import messaging from "@react-native-firebase/messaging";
import {store} from '../../redux/store';
const { height, width } = Dimensions.get('window')
console.disableYellowBox = true
function PopupNotiElectric({isVisible, onPress, onCancel, onPressLater, pending_payment, due_at_payment}) {
return <Modal visible={isVisible} transparent={true} animationType="none" key="popup-noti-electric">
<View style={styles.popupNotiContainer}>
<View style={styles.popupNoti}>
<View style={{width: '100%', alignItems: 'center'}}>
<Icon name='ic_shop_receive' color='#FF9500' size={70} style={{marginBottom: 10, width: '100%', textAlign: 'center'}}/>
<Text style={[{color: '#FF9500', marginBottom: 10, fontSize: 16}, styles.TextFont]}>ณมยอดคางชำระเง</Text>
<View style={styles.costText}>
<Text style={[{fontSize: 25, fontWeight: '500', textAlign: 'center'}, styles.TextFont]}>{pending_payment}</Text>
<Text style={[{color: '#8A8A8F', fontSize: 18, fontWeight: '400', position: 'absolute', right: 15, bottom: 8}, styles.TextFont]}>บาท</Text>
</View>
<Text style={[{color: '#FF9500', marginBottom: 10, textAlign: 'center' , fontSize: 14}, styles.TextFont]}>{t('please_pay_within')} {moment(due_at_payment).add('543', 'y').format('DD/MM/YYYY')}</Text>
<TouchableOpacity onPress={onPress} style={{width: '100%', marginTop: 10}}>
<Badge style={styles.badgeSubmit}>
<Text style={[{color: 'white', paddingVertical: 10, fontSize: 16}, styles.TextFont]}>ชำระเงนตอนน</Text>
</Badge>
</TouchableOpacity>
<TouchableOpacity onPress={onPressLater} style={{width: '100%'}}>
<Badge style={[styles.badgeCancel, {paddingTop: 5}]}>
<Text style={[{color: 'rgba(0, 0, 0, 0.5)', fontSize: 16}, styles.TextFont]}>ภายหล</Text>
</Badge>
</TouchableOpacity>
</View>
</View>
</View>
</Modal>
}
function PopupOverDue({isVisible, onPress, onCancel, onPressLater, pending_payment}) {
return <Modal visible={isVisible} transparent={true} animationType="none">
<View style={styles.popupNotiContainer}>
<View style={styles.popupNoti}>
<View style={{width: '100%', alignItems: 'center', position: 'relative'}}>
<Icon name='ic_shop_receive' color='#FF2D55' size={70} style={{marginBottom: 10}}/>
<TouchableOpacity onPress={onPressLater} style={{position: 'absolute', right: 0, top: -10}}>
<Text style={[{color: 'rgba(0, 0, 0, 0.5)', fontSize: 20}, styles.TextFont]}>{t('close')}</Text>
</TouchableOpacity>
<Text style={[{color: '#FF2D55', marginBottom: 10, fontSize: 16}, styles.TextFont]}>หนางชำระเกนกำหนด</Text>
<View style={styles.costText}>
<Text style={[{fontSize: 25, fontWeight: '500', textAlign: 'center'}, styles.TextFont]}>{pending_payment}</Text>
<Text style={[{color: '#8A8A8F', fontSize: 18, fontWeight: '400', position: 'absolute', right: 15, bottom: 8}, styles.TextFont]}>บาท</Text>
</View>
<Text style={[{color: '#FF2D55', fontSize: 14, textAlign: 'center'}, styles.TextFont]}>ณมหนางชำระเกนกำหนดแล</Text>
{/*<Text style={[{color: '#FF2D55', fontSize: 14, textAlign: 'center'}, styles.TextFont]}>กรุณาดำเนินการชำระหนี้ตอนนี้</Text>*/}
<Text style={[{color: '#FF2D55', marginBottom: 15, fontSize: 14, textAlign: 'center'}, styles.TextFont]}>กรณาตดตอเจาหนาท</Text>
<TouchableOpacity onPress={onPress} style={{width: '100%'}}>
<Badge style={styles.badgeSubmit}>
<Text style={[{color: 'white', paddingVertical: 10, fontSize: 16}, styles.TextFont]}>{t('ok')}</Text>
</Badge>
</TouchableOpacity>
{/* <TouchableOpacity onPress={onPressLater}>
<Badge style={[styles.badgeCancel, {paddingTop: 5}]}>
<Text style={[{color: 'rgba(0, 0, 0, 0.5)', fontSize: 16}, styles.TextFont]}>ภายหล</Text>
</Badge>
</TouchableOpacity>*/}
</View>
</View>
</View>
</Modal>
}
function PopupNotiFillInMeter({isVisible, onPress, onCancel, onPressLater, notified_meter_at}) {
return <Modal visible={isVisible} transparent={true} animationType="none" key="popup-noti-meter">
<View style={styles.popupNotiContainer}>
<View style={[styles.popupNoti, {paddingHorizontal: 15}]}>
<View style={{width: '100%', alignItems: 'center'}}>
{/*<Icon name='ic_shop_receive' color='#00420A' size={60} style={{marginBottom: 10}}/>*/}
<Image source={require('../../../assets/images/meter_noti_image.png')} style={{width: 70, height: 70 }} resizeMode={'contain'}/>
<Text style={[{color: '#00420A', marginVertical: 5, fontSize: 16}, styles.TextFont]}>กรณาแนบรปและกรอกเลขมเตอรำไฟ</Text>
<Text style={[{color: '#00420A', marginVertical: 5, fontSize: 13, textAlign: 'center'}, styles.TextFont]}>ภายในวนท {notified_meter_at}</Text>
<Text style={[{color: '#00420A', marginVertical: 5, fontSize: 13, textAlign: 'center', marginBottom: 15}, styles.TextFont]}>ขออภยหากลกคาไดงขอมลเรยบรอยแล</Text>
<TouchableOpacity onPress={onPress} style={{width: '100%'}}>
<Badge style={styles.badgeSubmit}>
<Text style={[{color: 'white', paddingVertical: 10, fontSize: 16}, styles.TextFont]}>กรอกขอม</Text>
</Badge>
</TouchableOpacity>
<TouchableOpacity onPress={onPressLater}>
<Badge style={[styles.badgeCancel, {paddingTop: 5}]}>
<Text style={[{color: 'rgba(0, 0, 0, 0.5)', fontSize: 16}, styles.TextFont]}>ภายหล</Text>
</Badge>
</TouchableOpacity>
</View>
</View>
</View>
</Modal>
}
class NewsScreen extends Component {
constructor (props) {
super(props)
@ -59,7 +168,7 @@ class NewsScreen extends Component {
is_new: false
}],
due_at: '',
pending_payment: '',
pending_payment: 0,
noti_count: 0,
isFirstTime: true,
user_point: 0,
@ -70,9 +179,20 @@ class NewsScreen extends Component {
scrollY: new Animated.Value(0),
loadMore: false,
loadPage: 1,
last_page: 1,
isLoadmore: false,
fb_is_link: false,
email: '',
visibleNotiElectric: false,
visibleNotiOverDue: false,
visibleNotiMeter: false,
payment_id: null,
is_notified_electric: false,
is_notified_before_due:false,
is_notified_overdue: false,
is_notified_meter: false,
notified_meter_at: moment().format('DD MMM YYYY'),
due_at_payment: moment().format('DD/MM/YYYY')
}
this._onCarouselScroll = this._onCarouselScroll.bind(this)
@ -80,18 +200,47 @@ class NewsScreen extends Component {
}
componentDidMount () {
this.initData()
// this.initData()
// this.checkNotifiedPopup()
}
checkNotifiedPopup = () => {
if (this.props.user) {
checkPaymentMeter()
.then(res => {
if (res.data) {
this.setState({
is_notified_electric: res.data.is_notified_electric,
is_notified_meter: res.data.is_notified_meter,
is_notified_overdue: res.data.is_notified_overdue,
notified_meter_at: res.data.notified_meter_at,
payment_id: res.data.payment_id,
pending_payment: res.data.pending_payment != null ? res.data.pending_payment : 0,
due_at_payment: res.data.payment && res.data.payment.due_at ? res.data.payment.due_at : null,
}, () => {
setTimeout(() => {
console.log('pending payment >>> ', parseInt(this.state.pending_payment))
this.setState({
visibleNotiElectric: this.state.is_notified_overdue ? false : this.state.is_notified_electric && parseInt(this.state.pending_payment) > 0,
visibleNotiMeter: ((this.state.is_notified_electric && parseInt(this.state.pending_payment) > 0) || this.state.is_notified_overdue) === true ? false : this.state.is_notified_meter,
visibleNotiOverDue: this.state.is_notified_overdue,
})
}, 1000)
})
}
})
}
}
async getUser () {
if (this.props.token != null) {
return await getUserProfile()
.then(res => {
if (res.ok) {
console.log("News:: res.data:")
if (res.ok && res.data?.success) {
console.log("User:: res.data:")
console.log(res.data)
this.checkNotifiedPopup()
this.setState({
pending_payment: res.data.pending_payment != null ? res.data.pending_payment : 0,
noti_count: res.data.count_noti,
user_point: res.data.point_balance,
user_project_id: res.data.project_id,
@ -106,26 +255,32 @@ class NewsScreen extends Component {
}
})
} else {
setTimeout(() => {
this.setState({
isLoading: false
}, () => {
this.props.appCleanUser()
this.props.appCleanToken()
})
}, 600)
// this.setState({
// isLoading: false
// }, () => {
clearToken();
setTimeout(() => {
this.props.appCleanUser();
this.props.appCleanToken();
this.props.appCleanProjectID();
this.initData()
}, 500)
// })
}
})
}
return true
}
async getAllNewsList () {
// return getNews()
return getNewsPage(this.state.loadPage)
.then(res => {
if ((res.data.data).length > 5) {
if (res.data.data && (res.data.data).length > 5) {
console.log('data >>>>> ', res)
var cut = []
for (let index = 0; index < 5; index++) {
cut.push(res.data.data[index])
@ -136,71 +291,116 @@ class NewsScreen extends Component {
news_head: cut,
new_all: res.data.data,
refreshing: false,
isLoading: false
isLoading: false,
last_page: res.data.last_page
})
} else {
this.setState({
news_head: res.data.data,
new_all: res.data.data,
refreshing: false,
isLoading: false
isLoading: false,
last_page: res.data.last_page
})
}
})
}
initData () {
this.setState({ isLoading: true })
Promise.all([
this.getUser(),
this.getAllNewsList()
])
.then(() => {
let user_id = 0
let user_noti_id = 0
if (this.props.token != null) {
if (this.state.isFirstTime) {
this.props.appSetNotification(this.state.noti_count)
this.props.appSetProjectID(this.state.user_project_id)
this.setState({ isFirstTime: false })
console.log('initData >>> ')
this.setState({
isLoading: true,
loadPage: 1,
last_page: 1,
news_head: [{
title: 'กำลังโหลดข้อมูลข่าว',
content: 'กำลังโหลดข้อมูลข่าว',
date: 'กำลังโหลดข้อมูลข่าว',
is_new: false
}],
new_all: [{
title: 'กำลังโหลดข้อมูลข่าว',
content: 'กำลังโหลดข้อมูลข่าว',
date: 'กำลังโหลดข้อมูลข่าว',
is_new: false
}],
}, () => {
Promise.all([
this.getUser(),
this.getAllNewsList()
])
.then(() => {
let user_id = 0
let user_noti_id = 0
if (this.props.token != null) {
if (this.state.isFirstTime) {
this.props.appSetNotification(this.state.noti_count)
this.props.appSetProjectID(this.state.user_project_id)
this.setState({ isFirstTime: false })
}
}
}
if (this.props.user && this.props.user.id) {
user_id = this.props.user.id
user_noti_id = this.props.user.id
} else if (this.props.device && this.props.device.customer_id) {
user_noti_id = this.props.device.customer_id
}
if (this.props.user && this.props.user.id) {
user_id = this.props.user.id
user_noti_id = this.props.user.id
} else if (this.props.device && this.props.device.customer_id) {
user_noti_id = this.props.device.customer_id
}
if (this.props.token != null && this.props.user != null) {
this.setState({
auth: true,
})
} else {
this.setState({
auth: false
})
}
if (this.props.token != null && this.props.user != null) {
this.setState({
auth: true,
})
} else {
this.setState({
auth: false
})
}
this.setState({ isLoading: false })
})
.catch(() => {
// console.log('catch ------------------>');
// this.setState({isLoading:false})
// this.props.appCleanUser()
// this.props.appCleanToken()
this.setState({ isLoading: false })
})
.catch(() => {
// console.log('catch ------------------>');
// this.setState({isLoading:false})
// this.props.appCleanUser()
// this.props.appCleanToken()
setTimeout(() => {
this.setState({
isLoading: false
}, () => {
//this.props.appCleanUser()
//this.props.appCleanToken()
})
}, 600)
// this.initData()
})
})
}
setPermission = async () => {
try {
const enabled = await messaging().hasPermission()
if (!enabled) {
await messaging().requestPermission()
}
} catch (error) {
console.log('error', error)
}
}
initNotification = async () => {
await this.setPermission()
const fcmToken = await messaging().getAPNSToken()
if (fcmToken) {
store.dispatch(appSetPushToken(fcmToken))
const resultSendDevice = await registerDevice(fcmToken)
console.log(' re sult register_device =>', resultSendDevice)
if (resultSendDevice.ok && resultSendDevice.data.success) {
store.dispatch(appSetDevice(resultSendDevice.data.device))
}
}
setTimeout(() => {
this.setState({
isLoading: false
}, () => {
this.props.appCleanUser()
this.props.appCleanToken()
})
}, 600)
this.initData()
})
}
_onRefresh = () => {
@ -208,21 +408,59 @@ class NewsScreen extends Component {
refreshing: true, loadPage: 1, loadMore: false
}, () => {
this.initData()
this.initNotification()
// this.checkNotifiedPopup()
})
}
setPaymentLater = () => {
// setPaymentLater()
// .then(res => {
// if(res && res.data && res.data.success){
this.setState({
visibleNotiElectric: false,
visibleNotiOverDue: false
})
if(this.state.is_notified_meter === true){
this.setState({
visibleNotiMeter: true
}, () => {
setTimeout(() => {
this.forceUpdate()
}, 100)
})
}
// }
// })
}
setFillInMeterLater = () => {
// setFillInMeterLater()
// .then(res => {
// if(res && res.data && res.data.success){
this.setState({
visibleNotiMeter: false
})
// }
// })
}
renderNativeItem = ({ item }) => (
<TouchableOpacity style={{ padding: 8, backgroundColor: '#FFFFFF33', height: 85, borderWidth: 1, borderColor: 'white', borderRadius: 5, flexDirection: 'row' }}
onPress={() => {this.props.navigation.navigate('NewsDetail', { news_id: item.id })}}>
<Image source={{ uri: item.url }} defaultSource={require('../../../assets/images/default_small.png')} style={styles.image_style} resizeMode={'contain'}/>
<Image source={item.url ? { uri: item.url } : require('../../../assets/images/default_small.png')} defaultSource={require('../../../assets/images/default_small.png')} style={styles.image_style} resizeMode={'contain'}/>
<View style={{ flex: 1, marginLeft: 8, justifyContent: 'space-between' }}>
<Text style={{ fontSize: 14, color: 'white', width: '100%', }} ellipsizeMode={'tail'} numberOfLines={2}>{item.title}</Text>
<View style={{ flexDirection: 'row' }}>
<Icon name="ic_calendar_alt" size={16} color="white"/>
<Text style={{ flex: 1, fontSize: 12, color: 'white', marginLeft: 5 }}>{item.date}</Text>
<Text style={{ flex: 1, fontSize: 12, color: 'white', marginLeft: 5 }}>{parseDateLocale(item.date)}</Text>
{
item.is_new == true &&
<View style={{ backgroundColor: '#FF9500', height: 20, paddingHorizontal: 10, borderRadius: 10, justifyContent: 'center', alignItems: 'center' }}>
<Text style={{ fontSize: 12, color: 'white' }}>{item.type == "promotion" ? t('latest_promotion') : t('latest_news')}</Text>
</View>
}
</View>
</View>
</TouchableOpacity>
@ -232,17 +470,21 @@ class NewsScreen extends Component {
return <TouchableOpacity onPress={() => {
this.props.navigation.navigate('NewsDetail', { news_id: item.id })
}}>
<ImageBackground source={{ uri: item.url }} onError={(e) => { this.props.source = require('../../../assets/images/default_big.png') }} style={styles.imgBg}>
<ImageBackground source={item.url ? { uri: item.url } : require('../../../assets/images/default_big.png')} onError={(e) => { this.props.source = require('../../../assets/images/default_big.png') }} style={styles.imgBg}>
<LinearGradient colors={['rgba(0, 0, 0, 0)', '#000000']}>
<View style={{ padding: 15, }}>
{item.is_new == true ?
<View style={{ backgroundColor: '#FF9500', borderRadius: 10, height: 20, width: 100, justifyContent: 'center', alignItems: 'center', paddingHorizontal: 10 }}><Text style={{ fontSize: 12, color: 'white' }}>{item.type == "promotion" ? t('latest_promotion') : t('latest_news')} </Text></View>
<View style={{ backgroundColor: '#FF9500', borderRadius: 10, height: 23,
alignSelf: 'flex-start', alignItems: 'center', justifyContent: 'center', flexWrap: 'nowrap',
paddingHorizontal: 10 }}>
<Text style={{ fontSize: 12, width: '100%', justifyContent: 'center', alignItems: 'center', color: 'white', flexWrap: 'nowrap' }}>{item.type == "promotion" ? t('latest_promotion') : t('latest_news')} </Text>
</View>
: null }
<Text style={styles.textNewsName} ellipsizeMode={'tail'} numberOfLines={2}>{item.title}</Text>
<View style={{ flexDirection: 'row', marginTop: 5 }}>
<Icon name="ic_calendar_alt" size={14} color="rgba(255, 255, 255, 0.65)"/>
<Text style={{ color: 'rgba(255, 255, 255, 0.65)', fontSize: 12, marginLeft: 5, marginTop: -1 }}>
{item.date}
{parseDateLocale(item.date)}
</Text>
</View>
</View>
@ -251,21 +493,11 @@ class NewsScreen extends Component {
</TouchableOpacity>
}
getDueAt (date) {
let d = moment(date).format('D')
let m = moment(date).format('MM')
let y = parseInt(moment(date).format('Y')) + 543
let new_date = moment().format('DD/MM/Y')
new_date = d + '/' + m + '/' + y
return new_date
}
_onCarouselScroll (e) {
const scrollX = e.nativeEvent.contentOffset.x
this.setState({
position: Math.ceil(scrollX / width)
})
// console.log(this.state.position)
}
@ -276,41 +508,32 @@ class NewsScreen extends Component {
}
loadMoreData = async () => {
const { loadMore } = this.state
if (loadMore) {
return
}
this.setState({ loadMore: true, isLoadmore: true })
if(parseInt(this.state.loadPage) < parseInt(this.state.last_page)){
this.setState({
loadMore: true,
isLoadmore: true,
loadPage: this.state.loadPage + 1
}, () => {
getNewsPage(this.state.loadPage)
.then(res => {
if (res.ok) {
let resData = res.data.data
let news_all = this.state.new_all
let news_arr = news_all.concat(resData)
let loadpage = this.state.loadPage + 1
this.setState({
new_all: news_arr,
refreshing: false,
loadMore: false,
isLoadmore: false,
last_page: res.data.last_page
})
}
})
})
}
/*loading - set loadMore = false when done*/
getNewsPage(loadpage)
.then(res => {
if (res.ok) {
let resData = res.data.data
let news_arr = this.state.new_all
resData.forEach(item => {
// console.log('data >>>>>><<<< ',item);
news_arr.push(item)
})
this.setState({
loadPage: loadpage,
new_all: news_arr,
refreshing: false,
loadMore: false,
isLoadmore: false
})
if (resData.length < 10) {
this.setState({
loadMore: true
})
return
}
}
})
}
_keyExtractorNewHead = (item, index) => 'new_head_' + index
@ -326,14 +549,19 @@ class NewsScreen extends Component {
}}>
<NavigationEvents
onDidFocus={() => {
this.setState({ isLoading: true })
let checkNav = this.props.navigation.getParam('isLogin')
this.setState({
isLoading: true
}, () => {
this.initData()
// this.checkNotifiedPopup()
})
/*let checkNav = this.props.navigation.getParam('isLogin')
if (checkNav) {
this.props.navigation.setParams({ isLogin: false })
this.initData()
} else {
this.setState({ isLoading: false })
}
}*/
}}
/>
<BackgroundImage>
@ -366,7 +594,11 @@ class NewsScreen extends Component {
onScroll={this._onCarouselScroll}
/>
<View style={{ position: 'absolute', bottom: 10, width: '100%', justifyContent: 'center', flexDirection: 'row' }}>
{(this.state.news_head).map((item, i) => <View key={'news_heade_' + i} style={[{ width: 10, height: 10, borderRadius: 5, backgroundColor: this.state.position == i ? '#269A21' : 'rgba(255,255,255,0.3)', marginHorizontal: 4 }]}></View>)}
{
this.state.news_head ?
(this.state.news_head).map((item, i) => <View key={'news_heade_' + i} style={[{ width: 10, height: 10, borderRadius: 5, backgroundColor: this.state.position == i ? '#269A21' : 'rgba(255,255,255,0.3)', marginHorizontal: 4 }]}></View>)
: <View></View>
}
</View>
</View>
{this.state.auth !== null &&
@ -397,10 +629,26 @@ class NewsScreen extends Component {
</Badge>
</View>
</TouchableOpacity>
{Platform.OS == 'ios' ? <Text style={{ color: 'white', marginTop: 10 }}>{t('or')}</Text> : null}
{Platform.OS == 'ios' ? <View>
<AppleButton
buttonStyle={AppleButton.Style.WHITE}
buttonType={AppleButton.Type.SIGN_IN}
style={{
width: 150,
height: 45,
marginTop: 10,
}}
onPress={ () => {signinApple(() => {
this.initData()
})
}}
/>
</View> : null}
<Text style={{ color: 'white', marginTop: 10 }}>{t('or')}</Text>
<TouchableOpacity onPress={() => {
loginWithFacebook(() => {
this.initData()
})
@ -408,7 +656,7 @@ class NewsScreen extends Component {
loginWithFacebook(() => {
this.initData()
})
}else{
}else
Alert.alert(
"",
"อิเมล์ "+this.state.email+" ยังไม่ได้ลงทะเบียนในระบบ กรุณาสมัครสมาชิก",
@ -434,8 +682,8 @@ class NewsScreen extends Component {
) : (
<View style={{ padding: 5 }}>
<View style={[styles.row, { alignItems: 'stretch' }]}>
<View style={styles.custom_card}>
<Card style={{ borderRadius: 5, backgroundColor: '#00420A', borderColor: 'rbga(0,0,0,0)' }}>
<View style={{width: '100%'}}>
<Card style={{ borderRadius: 5, backgroundColor: '#00420A', borderColor: 'rbga(0,0,0,0)', flex: 1 }}>
<BackgroundImage_RegisterForm>
<View style={{ flex: 1, flexDirection: 'column', alignItems: 'center', justifyContent: 'center', padding: 10, minHeight: 177 }}>
<View style={{ justifyContent: 'center', alignItems: 'center' }}>
@ -447,7 +695,7 @@ class NewsScreen extends Component {
<Text style={{ color: 'white', fontSize: 28 }}>{this.state.isBilling ? this.state.pending_payment : 'N/A'}</Text>
{/*<Text style={{ color: 'white', fontSize: 12 }}>{parseFloat(this.state.pending_payment) > 0 ?'โปรดชำระก่อนวันที่':'ยังไม่มียอดค้างชำระ'}</Text>*/}
<Text style={{ color: 'white', fontSize: 12, textAlign: 'center' }}>{parseFloat(this.state.pending_payment) > 0 ? t('to_view_outstanding_balance') : t('no_outstanding_balance_yet')}</Text>
{this.state.due_at !== '' && <Text style={{ color: 'white', fontSize: 12 }}>{parseFloat(this.state.pending_payment) > 0 && this.state.due_at !== '' ? this.getDueAt(this.state.due_at) : ''} </Text>}
{this.state.due_at !== '' && <Text style={{ color: 'white', fontSize: 12 }}>{parseFloat(this.state.pending_payment) > 0 && this.state.due_at !== '' ? this.state.due_at : ''} </Text>}
</View>
<TouchableOpacity disabled={!this.state.isBilling} onPress={() => {this.props.navigation.navigate('Bill')}}>
{/*<Badge style={{ backgroundColor: this.state.isBilling ? '#145EB3' : 'gray', borderRadius: 5, borderColor: 'rbga(0,0,0,0)', justifyContent:'center' }}><Text style={{ fontSize: 12, color: 'white' }}>ดูเพิ่มเติม</Text></Badge>*/}
@ -457,7 +705,7 @@ class NewsScreen extends Component {
</BackgroundImage_RegisterForm>
</Card>
</View>
<View style={[styles.custom_card, { paddingLeft: 5 }]}>
{/* <View style={[styles.custom_card]}>
<Card title='' style={{ borderRadius: 5, backgroundColor: '#003114', borderColor: 'rbga(0,0,0,0)', flex: 1 }}>
<BackgroundImage_RegisterForm>
<View style={{
@ -469,65 +717,60 @@ class NewsScreen extends Component {
minHeight: 177,
}}>
<Icon name='ic_star' color='white' size={24}/>
{/*<Text style={{ color: 'white', fontSize: 14, marginTop:5 }}>คะแนนสะสม</Text>*/}
<Text style={{ color: 'white', fontSize: 14, marginTop: 5 }}>{t('view_points')}</Text>
<Text style={{ color: 'white', fontSize: 28 }}>{this.state.user_point}</Text>
{/*<Text style={{ color: 'white', fontSize: 18 }}>พอยต์</Text>*/}
<Text style={{ color: 'white', fontSize: 14 }}>{t('point')}</Text>
<TouchableOpacity style={{ marginTop: 5 }} disabled={true} onPress={() => {}}>
{/*<Badge style={{ backgroundColor: 'gray', borderRadius: 5, borderColor: 'rbga(0,0,0,0)', justifyContent:'center' }}><Text style={{ fontSize: 12, color: 'white' }}>แลกคะแนน</Text></Badge>*/}
<Badge style={{ backgroundColor: 'gray', borderRadius: 5, borderColor: 'rbga(0,0,0,0)', justifyContent: 'center' }}><Text style={{ fontSize: 12, color: 'white' }}>{t('redeem')}</Text></Badge>
</TouchableOpacity>
</View>
</BackgroundImage_RegisterForm>
</Card>
</View>
</View> */}
</View>
<View style={[styles.row, { flexWrap: 'wrap', alignItems: 'stretch' }]}>
{this.state.isMeter ?
<View style={[styles.custom_card]}>
<TouchableOpacity disabled={false} onPress={() => {
this.props.navigation.navigate('Meter')
}} style={{ flex: 1 }}>
<Card title='' style={{ borderRadius: 5, backgroundColor: '#145EB3', borderColor: 'rbga(0,0,0,0)', flex: 1 }}>
<View style={{
flex: 1,
flexDirection: 'column',
alignItems: 'center',
padding: 10,
justifyContent: 'center'
}}>
<View style={{ alignItems: 'center' }}>
<Icon name='ic_meter' color='white' size={24}/>
<Text style={{ color: 'white', fontSize: 14, textAlign: 'center', marginTop: 5 }}> {t('smart_meter')} </Text>
</View>
<View style={[styles.custom_card]}>
<TouchableOpacity disabled={false} onPress={() => {
this.props.navigation.navigate('Meter')
}} style={{ flex: 1 }}>
<Card title='' style={{ borderRadius: 5, backgroundColor: '#145EB3', borderColor: 'rbga(0,0,0,0)', flex: 1 }}>
<View style={{
flex: 1,
flexDirection: 'column',
alignItems: 'center',
padding: 10,
justifyContent: 'center'
}}>
<View style={{ alignItems: 'center' }}>
<Icon name='ic_meter' color='white' size={24}/>
<Text style={{ color: 'white', fontSize: 14, textAlign: 'center', marginTop: 5 }}> {t('smart_meter')} </Text>
</View>
</Card>
</TouchableOpacity>
</View>
: null}
{this.state.isShipping ?
<View style={[styles.custom_card]}>
<TouchableOpacity disabled={false} onPress={() => {
this.props.navigation.navigate('Object')
}} style={{ flex: 1 }}>
<Card title='' style={{ borderRadius: 5, backgroundColor: '#145EB3', borderColor: 'rbga(0,0,0,0)', flex: 1 }}>
<View style={{
flex: 1,
flexDirection: 'column',
alignItems: 'center',
padding: 10,
justifyContent: 'center'
}}>
<View style={{ alignItems: 'center' }}>
<Icon name='ic_cart' color='white' size={24}/>
<Text style={{ color: 'white', fontSize: 14, textAlign: 'center', marginTop: 5 }}>{t('mail_and_parcel')}</Text>
</View>
</View>
</Card>
</TouchableOpacity>
</View>
<View style={[styles.custom_card]}>
<TouchableOpacity disabled={false} onPress={() => {
this.props.navigation.navigate('Object',{
user:this.props.user
})
}} style={{ flex: 1 }}>
<Card title='' style={{ borderRadius: 5, backgroundColor: '#145EB3', borderColor: 'rbga(0,0,0,0)', flex: 1 }}>
<View style={{
flex: 1,
flexDirection: 'column',
alignItems: 'center',
padding: 10,
justifyContent: 'center'
}}>
<View style={{ alignItems: 'center' }}>
<Icon name='ic_cart' color='white' size={24}/>
<Text style={{ color: 'white', fontSize: 14, textAlign: 'center', marginTop: 5 }}>{t('mail_and_parcel')}</Text>
</View>
</Card>
</TouchableOpacity>
</View>
: null}
</View>
</Card>
</TouchableOpacity>
</View>
<View style={[styles.custom_card]}>
<TouchableOpacity disabled={false}
onPress={() => { this.props.navigation.navigate('RepairService',{
@ -583,21 +826,59 @@ class NewsScreen extends Component {
data={this.state.new_all}
renderItem={this.renderNativeItem}
keyExtractor={this._keyExtractorNewAll}
// onEndReachedThreshold={0.01}
// onEndReached={this.loadMoreData.bind(this)}
ItemSeparatorComponent={() => {
return <View style={{ width: '100%', height: 8 }}></View>
}}
ListFooterComponent={() => {
if (!this.state.isLoadmore) return null
return (<View style={{ padding: 16, flexDirection: 'row', borderRadius: 10, justifyContent: 'center', alignItems: 'center' }}>
<ActivityIndicator size="small" color="black"/>
<Text style={{ fontSize: 12, marginLeft: 10, color: 'black' }}>Loading...</Text>
</View>)
return (<ActivityIndicator
size="large"
color={'white'}
/>)
}}
/>
</View>
</ScrollView>
</BackgroundImage>
<IndicatorLoading loadingVisible={this.state.isLoading}/>
<PopupNotiElectric
isVisible={this.state.visibleNotiElectric}
onCancel={() => this.setState({visibleNotiElectric: false})}
onPressLater={() => this.setPaymentLater()}
pending_payment={this.state.pending_payment}
due_at_payment={this.state.due_at_payment}
onPress={() => this.setState({
visibleNotiElectric: false
}, () => {
this.props.navigation.navigate('Bill')
this.setPaymentLater()
})}/>
<PopupOverDue
isVisible={this.state.visibleNotiOverDue}
onCancel={() => this.setState({visibleNotiOverDue: false})}
onPressLater={() => this.setPaymentLater()}
pending_payment={this.state.pending_payment}
onPress={() => this.setState({
visibleNotiOverDue: false
}, () => {
// this.props.navigation.navigate('Payment', {payment_id: this.state.payment_id})
this.props.navigation.navigate('Bill')
this.setPaymentLater()
})}/>
<PopupNotiFillInMeter
isVisible={this.state.visibleNotiMeter}
onCancel={() => this.setState({visibleNotiMeter: false})}
onPressLater={() => this.setFillInMeterLater()}
notified_meter_at={this.state.notified_meter_at}
onPress={() => this.setState({
visibleNotiMeter: false
}, () => {
this.props.navigation.navigate('Meter')
this.setFillInMeterLater()
})}
/>
</LinearGradient>
)
}
@ -649,6 +930,51 @@ const styles = StyleSheet.create({
custom_card: {
width: '50%', paddingHorizontal: 5,
// width: '100%'
},
popupNoti: {
backgroundColor: 'white',
justifyContent: 'center',
alignItems: 'center',
borderRadius: 5,
marginHorizontal: 50,
paddingVertical: 20,
paddingHorizontal: 30,
maxWidth: 300,
width: '100%'
},
popupNotiContainer: {
backgroundColor: 'rgba(0,0,0,0.6)',
justifyContent: 'center',
alignItems: 'center',
position: 'absolute',
width: '100%',
height: '100%',
flex: 1
},
costText: {
backgroundColor: '#EFEFF4',
alignItems: 'center',
paddingHorizontal: 20,
paddingVertical: 5,
borderRadius: 5,
width: '100%',
marginBottom: 10
},
badgeCancel: {
backgroundColor: 'white',
alignItems: 'center',
width: '100%'
},
badgeSubmit: {
backgroundColor: '#145EB3',
borderRadius: 5,
marginBottom: 10,
alignItems: 'center',
width: '100%',
height: 'auto'
},
TextFont: {
fontFamily: 'Prompt-Regular',
}
})
@ -656,5 +982,16 @@ const mapDisPatchToProps = state => {
return state.app
}
const setUser = dispatch => bindActionCreators({ appSetToken, appSetPushToken, appSetDevice, appSetUser, appCleanToken, appCleanUser, appSetNotification, appSetProjectID }, dispatch)
const setUser = dispatch => bindActionCreators({
appSetToken,
appSetPushToken,
appSetDevice,
appSetUser,
appCleanToken,
appCleanUser,
appSetNotification,
appSetProjectID,
setPaymentLater,
appCleanProjectID
}, dispatch)
export default connect(mapDisPatchToProps, setUser)(NewsScreen)

View File

@ -1,5 +1,5 @@
import React, { Component } from 'react'
import {View, ScrollView, StyleSheet, Linking, Button, TouchableOpacity, Alert} from 'react-native';
import {View, ScrollView, StyleSheet, Linking, Button, TouchableOpacity, Alert, Platform, Modal, ImageBackground} from 'react-native';
import Image from 'react-native-fast-image'
import { WebView } from 'react-native-webview';
import { Body, Badge, List, ListItem, Right, Title } from 'native-base'
@ -10,9 +10,12 @@ import { BackgroundImage } from '../../components/BackgroundImage'
import { getNewsDetail } from '../../api/UserApi';
import IndicatorLoading from '../../components/IndicatorLoading';
import { t } from '../../utils/i18n'
import parseDateLocale from '../../utils/parseDateLocale';
import ImageView from 'react-native-image-view';
import {NavigationActions} from "react-navigation";
import Config from 'src/utils/Config'
import Carousel from "../room/RoomDetail";
import {sliderWidth} from "../../styles/SliderEntry.style";
var uri = null;
const injectScript = `
(function () {
@ -41,11 +44,11 @@ export default class NewsDetailScreen extends Component {
};
componentWillUnmount() {
/*componentWillUnmount() {
if(this.props && this.props.navigation && this.props.navigation.state && this.props.navigation.state.params && this.props.navigation.state.params.getNotification){
this.props.navigation.state.params.getNotification()
}
}
}*/
getNewsData(){
this.setState({
@ -54,26 +57,34 @@ export default class NewsDetailScreen extends Component {
getNewsDetail(this.state.news_id)
.then(res => {
if(res.ok){
this.setState({
isLoading: false,
news_detail: res.data.data
})
}else{
this.setState({
isLoading: false,
news_detail: [
{
title: '',
content: '',
style: '',
is_new: true,
date:'',
url:'',
if(res.data.data){
this.setState({
isLoading: false,
news_detail: res.data.data
})
}else {
console.log('ถูกยกเลิกเผยแพร่ข่าว')
Alert.alert('','ถูกยกเลิกเผยแพร่ข่าว', [{
text: t('ok'),
onPress: () => {
console.log('press')
this.setState({
isLoading: false,
news_detail: {}
})
}
],
})
Alert.alert('','ถูกยกเลิกเผยแพร่ข่าว')
}])
}
}else{
Alert.alert('','ถูกยกเลิกเผยแพร่ข่าว', [{
text: t('ok'),
onPress: () => {
this.setState({
isLoading: false,
news_detail: {}
})
}
}])
// alert('ถูกยกเลิกเผยแพร่ข่าว')
// this.context.router.goBack()
@ -82,6 +93,20 @@ export default class NewsDetailScreen extends Component {
}
render() {
let source_webview = {};
if(Platform.OS === 'android'){
source_webview = {
baseUrl: '',
uri: `${Config.WEB_BASE_URL_PROD}/news_detail/${this.state.news_id}`
}
}else {
source_webview = {
baseUrl: '',
html: `${this.state.news_detail && this.state.news_detail.style ? this.state.news_detail.style : ''}<div id="content_detail"><meta charset="UTF-8"> ${this.state.news_detail && this.state.news_detail.content ? this.state.news_detail.content : ""} </div>`
}
}
return (
<LinearGradient colors={['#3AA40C', '#2C7C0B']} style={{
flex: 1,
@ -89,29 +114,36 @@ export default class NewsDetailScreen extends Component {
height: null
}}>
<BackgroundImage>
<ImageView
images={[{source: {uri: this.state.news_detail != null && this.state.news_detail.url }}]}
imageIndex={0}
isVisible={this.state.isImageViewVisible}
animationType={'fade'}
/>
{
Platform.OS === 'android' &&
<ImageView
images={[{source: {uri: this.state.news_detail != null && this.state.news_detail.url ? this.state.news_detail.url : '' }}]}
imageIndex={0}
isVisible={this.state.isImageViewVisible}
animationType={'fade'}
onClose={() => {this.setState({isImageViewVisible: false})}}
/>
}
<View>
<TouchableOpacity onPress={() => {this.setState({isImageViewVisible: true})}}>
<Image source={{ uri: this.state.news_detail != null && this.state.news_detail.url }} style={styles.imgBg} />
<Image source={{ uri: this.state.news_detail != null && this.state.news_detail.url ? this.state.news_detail.url : '' }} style={styles.imgBg} />
</TouchableOpacity>
</View>
<View style={{ backgroundColor: 'white', padding: 15 }}>
<View style={{ flexDirection: 'row' }}>
<Text style={{ color: '#00420A', fontSize: 16, }}>{this.state.news_detail.title}</Text>
<Text style={{ color: '#00420A', fontSize: 16, }}>{this.state.news_detail != null && this.state.news_detail.title}</Text>
</View>
<View style={{ flexDirection: 'row', marginTop: 5 }}>
<View style={{ width: '50%', flexDirection: "row", marginTop: 5 }}>
<Icon name="ic_event_note" size={16} color="#00420A" />
<Text style={{ marginLeft: 5, color: '#00420A', fontSize: 12, }}>{this.state.news_detail.date}</Text>
{
this.state.news_detail &&
<Text style={{ marginLeft: 5, color: '#00420A', fontSize: 12, }}>{parseDateLocale(this.state.news_detail.date)}</Text>
}
</View>
<View style={{ width: '50%', flexDirection: "row", flex: 1, justifyContent: 'flex-end' }}>
{this.state.news_detail.is_new == true ? <Badge style={{ backgroundColor: '#FF9500', borderRadius: 50, paddingLeft: 10, paddingTop: 5 }}>
<Text style={{ fontSize: 12, color: 'white' }}>{t('latest_news')} </Text>
{this.state.news_detail && this.state.news_detail.is_new == true ? <Badge style={{ backgroundColor: '#FF9500', borderRadius: 50, paddingLeft: 10, paddingTop: 5 }}>
<Text style={{ fontSize: 12, color: 'white' }}>{this.state.news_detail.type === 'promotion' ? t('latest_promotion') : t('latest_news')} </Text>
</Badge> : null}
</View>
</View>
@ -127,26 +159,55 @@ export default class NewsDetailScreen extends Component {
flex: 1,
}}
originWhitelist={['*']}
source={{ baseUrl: '', html: `${this.state.news_detail.style}<div id="content_detail"><meta charset="UTF-8">`+this.state.news_detail.content+'</div>' }}
// source={{baseUrl: '', html: `${this.state.news_detail && this.state.news_detail.style ? this.state.news_detail.style : ''}<div id="content_detail"><meta charset="UTF-8"> ${this.state.news_detail && this.state.news_detail.content ? this.state.news_detail.content : ""} </div>` }}
source={source_webview}
ref={(ref) => { this.webview = ref; }}
javaScriptEnabled={true}
domStorageEnabled={true}
// onShouldStartLoadWithRequest={(navState)=>{ //open external browser for android
// console.log('onShouldStartLoadWithRequest >>>>>> ',navState);
// Linking.openURL(navState.url)
// return false;
// }}
onMessage={(event) => {
if(event.nativeEvent.data){
let data = JSON.parse(event.nativeEvent.data);
if(data.video_id){
Linking.openURL(`https://youtube.com/embed/${data.video_id}`);
}
}
}}
onNavigationStateChange={(event) => {
/*onNavigationStateChange={(event) => {
console.log('onNavigationStateChange >>>>>> ',event);
if (event.url.startsWith("http")) {
this.webview.stopLoading();
this.webview.goBack();
Linking.openURL(event.url);
}
}}
}}*/
/>
</BackgroundImage>
{
Platform.OS === 'ios' &&
<Modal animationType="none"
transparent={true}
visible={this.state.isImageViewVisible}
onRequestClose={() => {
Alert.alert('Modal has been closed.');
}}>
<View style={{flex:1,backgroundColor: 'rgba(0,0,0,.9)', justifyContent: 'center', alignItems: 'center', width: '100%'}}>
<TouchableOpacity style={{height: 80,width: 80, position: 'absolute', zIndex: 1000, right: -25, top: '6%'}}
onPress={() => {this.setState({isImageViewVisible:false})}}
>
<Icon name='ic_add' size={36} color='white' style={{transform:[{rotate:'45deg'}]}}/>
</TouchableOpacity>
<View style={{width: '90%', justifyContent: 'center', height: '100%'}}>
<Image source={{ uri: this.state.news_detail != null && this.state.news_detail.url ? this.state.news_detail.url : '' }}
style={{flex: 1}}
resizeMode={'contain'}
/>
</View>
</View>
</Modal>
}
<IndicatorLoading loadingVisible={this.state.isLoading}/>
</LinearGradient>
)
@ -167,5 +228,11 @@ const styles = StyleSheet.create({
textAlign: 'center',
fontSize: 12
},
backgroundImage: {
flex: 1,
width: null,
height: null,
resizeMode: 'cover'
}
})

View File

@ -1,5 +1,5 @@
import React, {Component} from 'react'
import {FlatList, View, TouchableOpacity, RefreshControl, ScrollView, ActivityIndicator} from 'react-native'
import {FlatList, View, TouchableOpacity, RefreshControl, ScrollView, ActivityIndicator, SafeAreaView} from 'react-native'
import Image from 'react-native-fast-image'
import {BackgroundImage} from '../../components/BackgroundImage'
import LinearGradient from 'react-native-linear-gradient';
@ -8,8 +8,9 @@ import { get_notification, news, read_notification} from '../../api/UserApi'
import {bindActionCreators} from 'redux'
import {appSetNotification} from '../../redux/app/action'
import {connect} from 'react-redux';
import moment from "moment";
import { t } from '../../utils/i18n';
import parseDateLocale from '../../utils/parseDateLocale';
import { NavigationEvents } from "react-navigation";
const injectScript = `
(function () {
@ -33,9 +34,137 @@ class NotificationScreen extends Component {
}
_set_read(item) {
read_notification(item.id).then(res => {
console.log('read noti => ', res.data.message)
})
switch (item.source_type) {
case 'payment_success':
case 'update_app':
return false;
default:
read_notification(item.id).then(res => {
this.navigateNotification(item)
})
}
}
getContentId(item) {
let data = item.data;
let dataJson = JSON.parse(data);
if(dataJson.id){
return dataJson.id;
}else {
return null;
}
}
navigateNotification = (item) => {
switch (item.source_type) {
case 'news':
case 'general':
case 'promotion':
this.props.navigation.navigate('NewsDetail', {
news_id: item.source_id,
getNotification: () => {
this.setState({
page: 1
}, () => {
this.getNotification()
})
}
});
break;
case 'parcels':
if(item.parcel_status === 'PENDING'){
this.props.navigation.navigate('ObjectDetail', {
object_id: item.source_id,
getNotification: () => {
this.setState({
page: 1
}, () => {
this.getNotification()
})
}
})
}else {
this.props.navigation.navigate('Object', {
user: this.props.user,
getNotification: () => {
this.setState({
page: 1
}, () => {
this.getNotification()
})
}
})
}
break;
case 'message':
this.props.navigation.navigate('Question', {
getNotification: () => {
this.setState({
page: 1
}, () => {
this.getNotification()
})
}
});
break;
case 'meter':
this.props.navigation.navigate('Meter', {
getNotification: () => {
this.setState({
page: 1
}, () => {
this.getNotification()
})
}
});
break;
case 'invoice':
case 'invoice_overdue':
this.props.navigation.navigate('Payment', {
payment_id: this.getContentId(item),
getNotification: () => {
this.setState({
page: 1
}, () => {
this.getNotification()
})
}
});
break;
case 'repair':
case 'effect_repair':
case 'effect_responsible':
case 'edit_repair':
case 'appointment_repair':
case 'cancel_repair':
case 'success_repair':
case 'renew_appointment':
this.props.navigation.navigate('RepairHistoryDetail', {
repair_id: this.getContentId(item),
type: item.source_type,
getNotification: () => {
this.setState({
page: 1
}, () => {
this.getNotification()
})
}
})
break;
case 'request_contact':
this.props.navigation.navigate('Question', {
getNotification: () => {
this.setState({
page: 1
}, () => {
this.getNotification()
})
}
})
break;
default:
return false;
}
}
componentDidMount() {
@ -67,13 +196,13 @@ class NotificationScreen extends Component {
// console.log('user_noti_id => ', user_noti_id)
if(this.props.token != null){
get_notification(user_noti_id, 1).then(res => {
get_notification(user_noti_id, this.state.page).then(res => {
if (res.data) {
this.setState({
new_noti: res.data.data,
page: res.data.current_page,
refreshing: false,
last_page: res.data.last_page
last_page: res.data.last_page
});
}
})
@ -130,76 +259,79 @@ class NotificationScreen extends Component {
});
}
getTypeNoti(source_type) {
getTypeNoti(item) {
let type = 'ข่าวใหม่';
switch (source_type) {
switch (item.source_type) {
case 'news':
case 'general':
type = t('latest_news');
break;
case 'rooms':
type = t('new_room');
break;
case 'parcels':
type = t('new_parcel');
break;
case 'promotion':
type = t('latest_promotion');
break;
case 'message':
type = t('new_message');
break;
case 'invoice':
case 'invoice_overdue':
type = t('bill_payment');
break;
case 'meter':
type = t('meter_noti');
break;
case 'repair':
case 'effect_repair':
case 'effect_responsible':
case 'edit_repair':
case 'appointment_repair':
case 'request_contact':
case 'cancel_repair':
case 'success_repair':
case 'renew_appointment':
type = item.title;
break;
case 'update_app':
type = t('update_app');
break;
case 'payment_success':
type = t('payment_success');
break;
default:
type = t('latest_news');
type = '';
break;
}
return type;
}
getDateNoti(date) {
let d = moment(date).format('D')
let m = moment(date).format('MM')
let y = parseInt(moment(date).format('Y')) + 543
let new_month = 'ม.ค.';
let new_date = d + ' ' + new_month + ' ' + y;
switch (m) {
case '01':
new_month = 'ม.ค.';
break;
case '02':
new_month = 'ก.พ.';
break;
case '03':
new_month = 'มี.ค.';
break;
case '04':
new_month = 'เม.ย.';
break;
case '05':
new_month = 'พ.ค.';
break;
case '06':
new_month = 'มิ.ย.';
break;
case '07':
new_month = 'ก.ค.';
break;
case '08':
new_month = 'ส.ค.';
break;
case '09':
new_month = 'ก.ย.';
break;
case '10':
new_month = 'ต.ค.';
break;
case '11':
new_month = 'พ.ย.';
break;
case '12':
new_month = 'ธ.ค.';
break;
getStatusParcel (status) {
switch (status) {
case 'PENDING':
return t('waiting_for_pickup');
case 'WAIT_PICKUP':
return t('awaiting_payment');
case 'RECEIVE':
return t('paid');
case 'OTHER':
return t('other');
case 'ERROR':
default:
new_month = 'ม.ค.';
break;
return t('contact_front_desk');
}
}
new_date = d + ' ' + new_month + ' ' + y;
return new_date;
displayParcelContent (data) {
console.log('data >>> ', JSON.parse(data.data))
if(data.parcel_status){
return t('status') + ' : ' + this.getStatusParcel(data.parcel_status)
}
return '';
}
renderSeparator() {
@ -218,11 +350,57 @@ class NotificationScreen extends Component {
if (!this.state.refreshing) return null;
return (
<ActivityIndicator
style={{ color: '#000' }}
size="large"
color={'white'}
/>
);
}
getImageCover = (item) => {
if (item.image_path) {
return {uri: item.image_path};
} else {
switch (item.source_type) {
case 'invoice':
return require('../../../assets/images/invoice_icon.png');
case 'invoice_overdue':
return require('../../../assets/images/invoice_overdue_icon.png');
case 'meter':
return require('../../../assets/images/meter_icon.png');
case 'repair':
case 'effect_repair':
case 'effect_responsible':
case 'edit_repair':
case 'request_contact':
case 'cancel_repair':
case 'renew_appointment':
return require('../../../assets/images/repair_noti.png');
case 'appointment_repair':
return require('../../../assets/images/appointment_repair.png');
case 'success_repair':
return require('../../../assets/images/success_repair.png');
default:
return require('../../../assets/images/logo_5.png');
}
}
}
getContent = (item) => {
switch (item.source_type) {
// case 'parcels':
// return this.displayParcelContent(item);
case 'message':
if(item && item.source && item.source.media){
console.log('media >> ', item.source.media)
return <Image style={styles.image} source={item && item.source && item.source.media ? {uri: item.source.media} : require('../../../assets/images/default_small.png')}/>;
}else {
return item.content;
}
default:
return item.content;
}
}
_keyExtractorNewNoti = (item, index) => 'new_noti_'+index
render() {
@ -234,17 +412,30 @@ class NotificationScreen extends Component {
resizeMode: 'cover'
}}>
<BackgroundImage>
<ScrollView contentContainerStyle={styles.contentContainer}
{/*<ScrollView contentContainerStyle={styles.contentContainer}
refreshControl={
<RefreshControl
refreshing={this.state.refreshing}
onRefresh={this._onRefresh}
/>
}
>
<View style={styles.container}>
>*/}
<View style={styles.container}>
<NavigationEvents
onWillFocus={payload => {
this._onRefresh()
}}
/>
<SafeAreaView style={styles.container}>
<FlatList
data={this.state.new_noti}
refreshing={true}
refreshControl={
<RefreshControl
refreshing={this.state.refreshing}
onRefresh={this._onRefresh}
/>
}
keyExtractor={this._keyExtractorNewNoti}
ListEmptyComponent={() =>
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center', margin: 16,padding:16,borderRadius:5,backgroundColor:'white'}}>
@ -253,48 +444,50 @@ class NotificationScreen extends Component {
}
ItemSeparatorComponent={this.renderSeparator}
ListFooterComponent={this.renderFooter.bind(this)}
onEndReachedThreshold={0.01}
onEndReached={this.loadMoreNoti.bind(this)}
renderItem={({item, rowData, index}) =>
<TouchableOpacity
onPress={() => {
this._set_read(item),
this.props.navigation.navigate('NewsDetail', {
this._set_read(item)
/*this.props.navigation.navigate('NewsDetail', {
news_id: item.source_id,
getNotification: () => this.getNotification()
})
})*/
}}
key={index}
delayPressIn={50}
activeOpacity={0.8}
style={[item.is_read === false ? styles.isReadFalse : styles.isReadTrue]}
style={[ item && item.is_read === false ? styles.isReadFalse : styles.isReadTrue]}
>
<View style={styles.viewimages} key={index}>
<Image style={styles.image} //source={{uri: rowData.image}}
source={item.url ? {uri: item.url} : require('../../../assets/images/news_test.png')}
source={this.getImageCover(item)}
defaultSource={require('../../../assets/images/default_small.png')}
/>
<View style={styles.viewcontainer}>
<Text style={{fontSize: 14, color: '#145EB3', marginBottom: 3,}}>
{/*{this.getTypeNoti(item.source_type)}*/}
{
item.source &&
item.source.content_type &&
item.source.content_type == 'general' ? t('latest_news') : t('latest_promotion')
item && item.source_type && this.getTypeNoti(item)
}
</Text>
<Text numberOfLines={2} style={{fontSize: 14, color: 'black', marginBottom: 3,}}>
{item.title}
<Text
numberOfLines={item.source_type === 'payment_success' ? 0 : 3}
style={{fontSize: 14, color: 'black', marginBottom: 3,}}>
{this.getContent(item)}
</Text>
<Text style={{fontSize: 10, color: 'rgba(0, 0, 0, 0.5)',}}>
{this.getDateNoti(item.notified_at)}
{ item && item.notified_at && parseDateLocale(item.notified_at, 'D MMM Y, HH:mm')}
</Text>
</View>
</View>
</TouchableOpacity>
}
/>
</View>
</ScrollView>
</SafeAreaView>
</View>
{/*</ScrollView>*/}
</BackgroundImage>
</LinearGradient>
)

View File

@ -4,7 +4,7 @@ import Image from 'react-native-fast-image'
import { FlatList } from 'react-native-gesture-handler';
import Text from '../../components/Text';
import Icon from '../../components/Icon'
import {getObjectMessage} from '../../api/UserApi'
import {getObjectMessage, getRoomParcel} from '../../api/UserApi'
import moment from 'moment';
import IndicatorLoading from '../../components/IndicatorLoading';
import { NavigationEvents } from 'react-navigation'
@ -18,7 +18,9 @@ export default class MessageObject extends Component {
this.state = {
isRefreshing: false,
isLoading: true,
message_list:[]
message_list:[],
users:[],
roomIds:[],
};
this.statusText = this.statusText.bind(this)
@ -27,23 +29,55 @@ export default class MessageObject extends Component {
componentDidMount() {
// this.getObject()
const { navigation } = this.props
const users_state = navigation.getParam('user', 'NO ITEM')
this.state.users = users_state
this.state.roomIds = new Array()
if(users_state){
let rooms = users_state.room ? users_state.room : null
let rooms_list = rooms != null ? rooms.split(",") : []
var arrayLength = rooms_list.length;
let self = this;
for (var i = 0; i < arrayLength; i++) {
getRoomParcel(rooms_list[i])
.then(res => {
if(res.ok){
let result_data = new Array()
result_data = res.data.data
self.state.roomIds.push(result_data.id)
}
})
}
}
}
getObject(){
this.setState({
isLoading: true
})
getObjectMessage()
.then(res => {
if(res.ok){
this.setState({
message_list: res.data.data,
}, () => {
getObjectMessage()
.then(res => {
if(res.ok && res.data){
// let parcel_data = new Array()
// parcel_data=res.data.data
// var roomIds = this.state.roomIds
// var filteredArray = new Array()
// if(roomIds.length > 0){
// filteredArray = parcel_data.filter(function(itm){
// return roomIds.indexOf(itm.room_id) > -1;
// })
this.setState({
message_list: res.data.data,
})
}
})
}
this.setState({
isLoading: false
})
})
}
statusColor(status){
@ -69,6 +103,8 @@ export default class MessageObject extends Component {
return t('awaiting_payment')
case 'RECEIVE':
return t('paid')
case 'OTHER':
return t('other')
case 'ERROR':
default:
return t('contact_front_desk')
@ -89,11 +125,19 @@ export default class MessageObject extends Component {
<View style={{flex:1,justifyContent:'center'}}>
<View style={{flexDirection:'row',justifyContent:'space-between'}}>
<Text style={styles.textTitle} numberOfLines={1}>{item.parcel_name}</Text>
<Text>{item.code != null && t('confirmation_code')}</Text>
<Text>
{((item.code != null) && (item.status != 'PENDING' && item.status != 'OTHER' && item.status != 'ERROR') ) ? t('confirmation_code'): '' }
</Text>
</View>
<View style={{flexDirection:'row',justifyContent:'space-between'}}>
<Text style={styles.textTitle} numberOfLines={1}>{t('consignee')} : { item.customer ? item.customer.name : "" }</Text>
<Text style={{fontWeight: 'bold',fontSize: 18}}>{item.code != null && item.code}</Text>
<Text style={styles.textTitle} numberOfLines={1}>{t('consignee')} : { item.customer_name ? item.customer_name.length > 22 ? item.customer_name.substring(0, 22) + '...' : item.customer_name : "" }</Text>
<Text style={{fontWeight: 'bold',fontSize: 18}}>
{((item.code != null)&&(item.status != 'PENDING' && item.status != 'OTHER' && item.status != 'ERROR')) ? item.code: '' }
</Text>
</View>
<View style={{flexDirection:'row',justifyContent:'space-between'}}>
<View style={{justifyContent:'center',alignItems:'center',flexDirection:'row'}}>

View File

@ -24,6 +24,12 @@ export default class MessageObjectDetail extends Component {
this.getObjectDetail()
}
componentWillUnmount() {
if(this.props && this.props.navigation && this.props.navigation.state && this.props.navigation.state.params && this.props.navigation.state.params.getNotification){
this.props.navigation.state.params.getNotification()
}
}
getObjectDetail(){
getObjectMessageByID(this.state.object_id)
.then(res => {
@ -88,7 +94,7 @@ export default class MessageObjectDetail extends Component {
</View>
<View style={{marginVertical:16,height: 1,backgroundColor:'silver',width: '100%'}}/>
<Text style={styles.textTitle}></Text>
<Text style={styles.textBaclk}>{this.state.object_data.customer != null && this.state.object_data.customer.name}</Text>
<Text style={styles.textBaclk}>{this.state.object_data.customer_name != null && this.state.object_data.customer_name}</Text>
{/*<View style={{marginVertical:16,height: 1,backgroundColor:'silver',width: '100%'}}/>
<View style={{flexDirection:'row',justifyContent:'space-between'}}>
<View>

View File

@ -4,33 +4,48 @@ import Text from '../../components/Text';
import Signature from 'react-native-signature-canvas';
import {postSignatureImage} from '../../api/UserApi';
import { t } from '../../utils/i18n';
import SignaturePad from 'react-native-signature-pad';
export default class SignaturePadScreen extends Component {
constructor(props) {
super(props);
this.state = {
signature: null,
object_id: this.props.navigation.getParam('object_id','no-id')
object_id: this.props.navigation.getParam('object_id','no-id'),
keySign: 1
};
this.signPad = React.createRef();
}
handleSignature = signature => {
let param = {
id: this.state.object_id,
image: signature
if(signature === '' || !signature){
Alert.alert(null, t('please_sign'), [{text: 'ok'}])
}else {
let param = {
id: this.state.object_id,
image: signature
}
console.log('-----------> handle signature', signature);
this.setState({ signature },() => {
postSignatureImage(param)
.then(res => {
if(res.ok){
Alert.alert(null,t('save_success'),[{text: t('ok')}])
this.props.navigation.navigate('Object')
}else{
Alert.alert(null,t('save_fail_and_try'),[{text: t('ok')}])
}
})
});
}
console.log('-----------> handle signature')
this.setState({ signature },() => {
postSignatureImage(param)
.then(res => {
if(res.ok){
Alert.alert(null,'บันทึกสำเร็จ',[{text: t('ok')}])
this.props.navigation.navigate('Object')
}else{
Alert.alert(null,'บันทึกไม่สำเร็จ กรุณาลองอีกครั้ง',[{text: t('ok')}])
}
})
});
};
clearSignPad = () => {
this.setState({
keySign: this.state.keySign + 1
})
};
render() {
@ -39,6 +54,7 @@ export default class SignaturePadScreen extends Component {
background-color: #269A21;
color: #FFF;
}`;
return (
<View style={{flex:1}}>
{/*image show signature when save*/}
@ -51,18 +67,31 @@ export default class SignaturePadScreen extends Component {
/>
) : null}
</View>*/}
<Signature
ref={(c) => { this._signature = c }}
onOK={this.handleSignature}
descriptionText="ลายเซ็น"
clearText="ล้าง"
confirmText="บันทึกรูป"
webStyle={signatureStyle}
/>
{/*<TouchableOpacity style={{margin:16,height: 40,backgroundColor:'#269A21',justifyContent:'center',alignItems:'center',borderRadius:5}}*/}
{/*onPress={() => {this._signature.onOK()}}>*/}
{/*<Text style={{color:'white'}}>ยืนยัน</Text>*/}
{/*</TouchableOpacity>*/}
{/*<Signature*/}
{/*ref={(c) => { this._signature = c }}*/}
{/*onOK={this.handleSignature}*/}
{/*descriptionText="ลายเซ็น"*/}
{/*clearText="ล้าง"*/}
{/*confirmText="บันทึกรูป"*/}
{/*webStyle={signatureStyle}*/}
{/*/>*/}
<View style={{flex: 0.95, marginVertical: 10, marginHorizontal: 15, borderWidth: 1, borderColor: '#e8e8e8'}}>
<SignaturePad ref={this.signPad} key={this.state.keySign}/>
</View>
<View style={{flex: 0.05, flexDirection: 'row', alignItems: 'center', marginBottom: 15, marginHorizontal: 15, justifyContent: 'space-between'}}>
<TouchableOpacity style={{backgroundColor:'#269A21',borderRadius:5, marginRight: 10, justifyContent: 'center', alignItems: 'center', paddingVertical: 5, paddingHorizontal: 35}}
onPress={() => { this.clearSignPad() }}>
<Text style={{color:'white'}}>{t('clear_signature')}</Text>
</TouchableOpacity>
<Text style={{ opacity: 0.4 }}>{t('signature')}</Text>
<TouchableOpacity style={{backgroundColor:'#269A21',borderRadius:5, marginLeft: 10, justifyContent: 'center', alignItems: 'center', paddingVertical: 5, paddingHorizontal: 20}}
onPress={() => { this.handleSignature(this.signPad.current.state.base64DataUrl) }}>
<Text style={{color:'white'}}>{t('save_signature')}</Text>
</TouchableOpacity>
</View>
</View>
);
}

View File

@ -56,14 +56,21 @@ class EditProfileScreen extends Component {
componentDidMount () {
const { navigation } = this.props
const users_state = navigation.getParam('user', 'NO ITEM')
const image = navigation.getParam('image', 'NO ITEM')
console.log("defaultImage",image);
if(image != null ){
this.setState({
image_url :image
})
}
// console.log('check user state ----------- ',users_state)
if(users_state.gender == null || users_state.gender == 'null'){
console.log('NULL');
// this.state.user.show_birth_date = users_state.birth_date;
this.setState({
user: {
gender: 'male',
...users_state
...users_state,
}
})
}else{
@ -73,14 +80,14 @@ class EditProfileScreen extends Component {
})
}
this.getProjectList()
// this.getProjectList()
}
getProjectList() {
project()
.then(res => {
if (res.ok) {
return this.setState({
if (res.ok && res.data && res.data.data) {
this.setState({
project_list: res.data.data,
selected_project: res.data.data[0].id
})
@ -141,7 +148,7 @@ class EditProfileScreen extends Component {
profile_image_id: image_profile
}
})
}).catch(e => alert(e))
})
}
onTakeCamera () {
@ -165,7 +172,7 @@ class EditProfileScreen extends Component {
profile_image_id: image_profile
}
})
}).catch(e => alert(e))
})
}
render () {
@ -173,64 +180,71 @@ class EditProfileScreen extends Component {
const users = navigation.getParam('user', 'NO ITEM')
// console.log('users :', users);
return (
<View style={{ flex: 1, backgroundColor: '#00420A' }}>
<KeyboardAvoidingView style={{flex:1}} keyboardVerticalOffset={Platform.OS == 'ios' ? 75 : 0} behavior={Platform.OS == 'ios' ? "padding" : ""} enabled>
<KeyboardAvoidingView style={{flex:1}}
keyboardVerticalOffset={Platform.OS == 'ios' ? 75 : 0}
behavior={Platform.OS == 'ios' ? 'padding' : ''}
ref={(view) => {this.scrollView = view;}}
>
<View style={{ flex: 1, backgroundColor: '#00420A'}}>
<BackgroundImage_RegisterForm>
<ScrollView style={{ flexDirection: 'column' }}>
<LinearGradient colors={['#3AA40C', '#2C7C0B']} style={{
flex: 1,
width: null,
height: null,
resizeMode: 'cover'
}}>
<View style={{ flex: 1, paddingVertical: 20, alignItems: 'center' }}>
<View style={{ width: '30%' }}>
<TouchableOpacity
style={{
backgroundColor: '#FFF',
borderRadius: 50, padding: 5,
justifyContent: 'center',
alignItems: 'center',
position: 'absolute',
right: '-5%',
top: '0%',
zIndex: 1
}}
onPress={() => {
// this.onImagePick()
ActionSheet.showActionSheetWithOptions({
options: ACTIONSHEET_BUTTONS,
cancelButtonIndex: CANCEL_INDEX,
// destructiveButtonIndex: DESTRUCTIVE_INDEX,
// tintColor: 'blue'
},
(buttonIndex) => {
// console.log('button clicked :', buttonIndex)
if (buttonIndex == 0) {
this.onTakeCamera()
} else if (buttonIndex == 1) {
this.onImagePick()
}
})
}}>
<Icon name={'ic_outline_camera'} size={20} color={'#8BC34A'}/>
</TouchableOpacity>
<Image
style={{
width: 120,
height: 120,
borderRadius: 60,
borderColor: 'white',
borderWidth: 2
}}
source={this.state.image_url}
/>
</View>
<ScrollView style={{ flex: 1, height: '100%' }}>
<View style={{ flexDirection: 'column', flex: 1}}>
<View>
<LinearGradient colors={['#3AA40C', '#2C7C0B']} style={{
// flex: 1,
width: null,
height: null,
resizeMode: 'cover'
}}>
<View style={{ paddingVertical: 20, alignItems: 'center' }}>
<View>
<TouchableOpacity
style={{
backgroundColor: '#FFF',
borderRadius: 50, padding: 5,
justifyContent: 'center',
alignItems: 'center',
position: 'absolute',
right: '0%',
top: '0%',
zIndex: 1
}}
onPress={() => {
// this.onImagePick()
ActionSheet.showActionSheetWithOptions({
options: ACTIONSHEET_BUTTONS,
cancelButtonIndex: CANCEL_INDEX,
// destructiveButtonIndex: DESTRUCTIVE_INDEX,
// tintColor: 'blue'
},
(buttonIndex) => {
// console.log('button clicked :', buttonIndex)
if (buttonIndex == 0) {
this.onTakeCamera()
} else if (buttonIndex == 1) {
this.onImagePick()
}
})
}}>
<Icon name={'ic_outline_camera'} size={20} color={'#8BC34A'}/>
</TouchableOpacity>
<Image
style={{
width: 120,
height: 120,
borderRadius: 60,
borderColor: 'white',
borderWidth: 2
}}
source={this.state.image_url}
/>
</View>
</View>
</LinearGradient>
</View>
</LinearGradient>
<View style={{ flex: 1, height: '100%' }}>
<View style={{ flex: 1 }}>
<View style={[styles.form]}>
<View style={{ flexDirection: 'column' , padding: 15, paddingTop: 5, paddingBottom: 0,}}>
<View>
<Text style={styles.headerTitle}>{t('profile')}</Text>
<View style={styles.row}>
<CustomInput
@ -264,111 +278,9 @@ class EditProfileScreen extends Component {
})
}}/>
</View>
<View style={styles.row}>
<View style={styles.row_grow_first}>
<View
style={{
flexGrow: 1,
flexDirection: 'row',
height: 40,
maxHeight: 48,
minHeight: 40,
paddingHorizontal: 5,
backgroundColor: 'rgba(255,255,255,0.3)',
borderRadius: 30
}}
>
<View
style={{
justifyContent: 'center',
paddingLeft: 5,
paddingRight: 5
}}
>
<Text
style={{
color: 'white'
}}
>
{t('gender')}
</Text>
</View>
<View style={{ flex: 1,alignItems: Platform.OS == 'ios' ? 'flex-end' : 'stretch'}}>
<Picker
mode="dropdown"
style={{
height: 40,
color: 'white',
}}
textStyle={{color:'white',fontFamily: 'Prompt-Regular',fontSize:14,textAlign:'right'}}
itemStyle={{color:'white',fontFamily: 'Prompt-Regular',fontSize:14}}
itemTextStyle={{color:'black',fontFamily: 'Prompt-Regular',fontSize:14}}
labelName={t('gender')}
placeholder={t('male') +"/"+ t('female')}
selectedValue={this.state.user.gender}
onValueChange={e => {
// console.log('check gender +++++++++++++++ ',e);
this.setState({
user: {
...this.state.user,
gender: e
}
})
}}
>
<Picker.Item label={t('male')} value="male"/>
<Picker.Item label={t('female')} value="female"/>
</Picker>
</View>
</View>
</View>
</View>
<View style={styles.row}>
<View style={styles.row_grow}>
<CustomDatePicker titleText={t('birth_date')} dateText={moment(this.state.user.birth_date).format('YYYY-MM-DD')} handleDate={(data) => {
this.setState({
user: {
...this.state.user,
birth_date: moment(data).format('YYYY-MM-DD')
}
})}}/>
</View>
</View>
<View style={styles.row}>
<CustomInput
style={styles.register_input}
labelColor={'white'}
placeholderTextColor={'white'}
labelName={t('citizen_id')}
value={this.state.user.tax_id}
onChangeText={(text) => {
this.setState({
user: {
...this.state.user,
tax_id: text
}
})
}}/>
</View>
<View style={styles.row}>
<CustomInput
style={styles.register_input}
labelColor={'white'}
placeholderTextColor={'white'}
labelName={t('phone')}
value={this.state.user.mobile}
onChangeText={(text) => {
this.setState({
user: {
...this.state.user,
mobile: text
}
})
}}/>
</View>
<Text style={styles.headerTitle}>{t('accom_info')}</Text>
<View style={styles.row}>
<View
{/*<View style={styles.row}>
<View style={styles.row_grow_first}>
<View
style={{
flexGrow: 1,
flexDirection: 'row',
@ -392,114 +304,214 @@ class EditProfileScreen extends Component {
color: 'white'
}}
>
{t('project')}
{t('gender')}
</Text>
</View>
<View style={{ flex: 1 }}>
<Picker
<View style={{ flex: 1,alignItems: Platform.OS == 'ios' ? 'flex-end' : 'stretch'}}>
<Picker
mode="dropdown"
style={{
color: 'white',
height: 40,
color: 'white',
}}
textStyle={{color:'white',fontFamily:'Prompt-Regular',fontSize:14}}
labelName={t('project')}
placeholder={t('choose_project')}
selectedValue={this.state.project_item}
textStyle={{color:'white',fontFamily: 'Prompt-Regular',fontSize:14,textAlign:'right'}}
itemStyle={{color:'white',fontFamily: 'Prompt-Regular',fontSize:14}}
itemTextStyle={{color:'black',fontFamily: 'Prompt-Regular',fontSize:14}}
labelName={t('gender')}
placeholder={t('male') +"/"+ t('female')}
selectedValue={this.state.user.gender}
onValueChange={e => {
// console.log('@@@@@@ project selected --------> ',e);
// console.log('check gender +++++++++++++++ ',e);
this.setState({
project_name: e.name,
project_item:e,
selected_project: e.id,
user: {
...this.state.user,
project: e.code,
},
}, () => {
this.getBuildingList()
gender: e
}
})
}}
>
{this.state.project_list.map((item,index) => {
return <Picker.Item label={item.name} value={item} key={'project_'+index}/>
})}
<Picker.Item label={t('male')} value="male"/>
<Picker.Item label={t('female')} value="female"/>
</Picker>
</View>
</View>
</View>
</View>*/}
{/*<View style={styles.row}>
<View style={styles.row_grow}>
<CustomDatePicker titleText={t('birth_date')} dateText={moment(this.state.user.show_birth_date).add(543, 'years').format('DD-MM-YYYY')} handleDate={(data) => {
this.setState({
user: {
...this.state.user,
birth_date: moment(data).format('YYYY-MM-DD'),
show_birth_date: moment(data).format('YYYY-MM-DD')
}
})}}/>
</View>
</View>*/}
{/*<View style={styles.row}>
<CustomInput
style={styles.register_input}
labelColor={'white'}
placeholderTextColor={'white'}
labelName={t('citizen_id')}
value={this.state.user.tax_id}
onChangeText={(text) => {
this.setState({
user: {
...this.state.user,
tax_id: text
}
})
}}/>
</View>*/}
<View style={styles.row}>
<CustomInput
style={styles.register_input}
labelColor={'white'}
placeholderTextColor={'white'}
labelName={t('phone')}
value={this.state.user.mobile}
onChangeText={(text) => {
this.setState({
user: {
...this.state.user,
mobile: text
}
})
}}/>
</View>
{/*<Text style={styles.headerTitle}>{t('accom_info')}</Text>*/}
{/*<View style={styles.row}>
<View
style={{
flexGrow: 1,
flexDirection: 'row',
height: 40,
maxHeight: 48,
minHeight: 40,
paddingHorizontal: 5,
backgroundColor: 'rgba(255,255,255,0.3)',
borderRadius: 30
}}
>
<View
style={{
flexGrow: 1,
flexDirection: 'row',
height: 40,
maxHeight: 48,
minHeight: 40,
paddingHorizontal: 5,
backgroundColor: 'rgba(255,255,255,0.3)',
borderRadius: 30
}}>
<View
justifyContent: 'center',
paddingLeft: 5,
paddingRight: 5
}}
>
<Text
style={{
justifyContent: 'center',
paddingLeft: 5,
paddingRight: 5
}}>
<Text
style={{
color: 'white'
}}>
{t('building')}
</Text>
</View>
<View style={{ flex: 1 }}>
<Picker
// mode="dropdown"
style={{
color: 'white',
height: 40,
}}
textStyle={{
color: 'white',
fontFamily: 'Prompt-Regular'
}}
textStyle={{color:'white',fontFamily:'Prompt-Regular',fontSize:14}}
labelName={t('building')}
placeholder={t('choose_project')}
selectedValue={this.state.user.building != null && this.state.user.building}
onValueChange={e => {
this.setState({
user: {
...this.state.user,
building: e
}
})
}}>
{this.state.building_list.length > 0 && this.state.building_list.map((item,index) => {
return <Picker.Item label={item.room_build} value={item.room_build} key={'building_'+index}/>
})}
</Picker>
</View>
color: 'white'
}}
>
{t('project')}
</Text>
</View>
<View style={styles.row_grow}>
<CustomInput
style={styles.register_input}
labelColor={'white'}
placeholderTextColor={'white'}
labelName={t('room2')}
placeholder={t('room_no')}
placeholderTextColor={'#FFFFFF40'}
value={this.state.user.room}
onChangeText={(text) => {
<View style={{ flex: 1 }}>
<Picker
style={{
color: 'white',
height: 40,
}}
textStyle={{color:'white',fontFamily:'Prompt-Regular',fontSize:14}}
labelName={t('project')}
placeholder={t('choose_project')}
selectedValue={this.state.project_item}
onValueChange={e => {
// console.log('@@@@@@ project selected --------> ',e);
this.setState({
project_name: e.name,
project_item:e,
selected_project: e.id,
user: {
...this.state.user,
project: e.code,
},
}, () => {
this.getBuildingList()
})
}}
>
{this.state.project_list.map((item,index) => {
return <Picker.Item label={item.name} value={item} key={'project_'+index}/>
})}
</Picker>
</View>
</View>
</View>*/}
{/*<View style={styles.row}>
<View
style={{
flexGrow: 1,
flexDirection: 'row',
height: 40,
maxHeight: 48,
minHeight: 40,
paddingHorizontal: 5,
backgroundColor: 'rgba(255,255,255,0.3)',
borderRadius: 30
}}>
<View
style={{
justifyContent: 'center',
paddingLeft: 5,
paddingRight: 5
}}>
<Text
style={{
color: 'white'
}}>
{t('building')}
</Text>
</View>
<View style={{ flex: 1 }}>
<Picker
// mode="dropdown"
style={{
color: 'white',
height: 40,
}}
textStyle={{color:'white',fontFamily:'Prompt-Regular',fontSize:14}}
labelName={t('building')}
placeholder={t('choose_project')}
selectedValue={this.state.user.building != null && this.state.user.building}
onValueChange={e => {
this.setState({
user: {
...this.state.user,
room: text
building: e
}
})
}}/>
}}>
{this.state.building_list.map((item,index) => {
return <Picker.Item label={item.room_build} value={item.room_build} key={'building_'+index}/>
})}
</Picker>
</View>
</View>
<View style={styles.row_grow}>
<CustomInput
style={styles.register_input}
labelColor={'white'}
placeholderTextColor={'white'}
labelName={t('room2')}
placeholder={t('room_no')}
placeholderTextColor={'#FFFFFF40'}
value={this.state.user.room}
onChangeText={(text) => {
this.setState({
user: {
...this.state.user,
room: text
}
})
}}/>
</View>
</View>*/}
<Text style={styles.headerTitle}>{t('change_password')}</Text>
<View>
<View style={styles.row}>
@ -540,11 +552,14 @@ class EditProfileScreen extends Component {
}}/>
</View>
</View>
</View>
<View>
<View style={styles.buttons}>
<View style={styles.row_grow}>
<CustomButton style={styles.btn_next_register} title={t('complete')}
sizeText={14}
onPress={this.edit_profile}
sizeText={14}
onPress={this.edit_profile}
/>
</View>
</View>
@ -553,8 +568,8 @@ class EditProfileScreen extends Component {
</View>
</ScrollView>
</BackgroundImage_RegisterForm>
</KeyboardAvoidingView>
</View>
</KeyboardAvoidingView>
)
}
}
@ -609,10 +624,10 @@ const styles = {
backgroundColor: 'rgba(255,255,255,0.3)',
borderRadius: 30,
}
}
};
const mapDisPatchToProps = state => {
return state.app
}
};
const setUser = dispatch => bindActionCreators({ appSetDevice, appSetUser, appCleanUser }, dispatch)
export default connect(mapDisPatchToProps, setUser)(EditProfileScreen)

View File

@ -9,7 +9,7 @@ import Icon from 'src/components/Icon'
import { CustomButton } from '../../components/CustomButton'
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
import { getUserProfile } from '../../api/UserApi';
import { getUserProfile, requestDeleteAccount } from '../../api/UserApi';
import moment from 'moment'
import { NavigationEvents } from 'react-navigation'
import IndicatorLoading from '../../components/IndicatorLoading';
@ -23,6 +23,7 @@ class ProfileScreen extends Component {
isLoading: false,
user:{},
room:null,
profileImage: require('../../../assets/images/profile.png')
}
this.getUserData = this.getUserData.bind(this)
}
@ -42,10 +43,18 @@ class ProfileScreen extends Component {
.then(res => {
// console.log('user profile -------> ',res);
if(res.ok){
let image = require('../../../assets/images/profile.png')
if (res.data.user.image && res.data.user.image.url){
image = {
uri: res.data.user.image.url
}
}
this.props.user.show_birth_date = res.data.user.birth_date
this.setState({
isLoading: false,
user: res.data.user,
room: res.data.room
room: res.data.room,
profileImage : image,
})
}else{
this.setState({
@ -55,10 +64,69 @@ class ProfileScreen extends Component {
})
}
connectFBSuccess = () => {
this.state.user.fb_is_link = 't';
Alert.alert('Connect with Facebook Success', '', [
{
text: 'ok',
onPress: () => {
this.getUserData()
}
}
])
};
disConnectFBSuccess = () => {
this.state.user.fb_is_link = 'f';
this.state.user.fb_token = null;
Alert.alert('Disconnect with Facebook Success', '', [
{
text: 'ok',
onPress: () => {
this.getUserData()
}
}
])
};
refreshPage() {
window.location.reload(false);
}
confirmDeleteAccount = () => {
Alert.alert('ต้องการลบบัญชีใช่หรือไม่ ?', 'คำขอของท่านจะถูกส่งไปยังผู้ดุแลเพื่อตรวจสอบและทำการลบบัญชี อาจใช้เวลาประมาณ 30 วัน', [
{
text: t('cancel')
},
{
text: t('ok'),
onPress: () => {
this.deleteAccount()
}
}
])
}
deleteAccount = () => {
this.setState({
isLoading: true
}, () => {
requestDeleteAccount().then((res) => {
if(res.data?.success) {
Alert.alert('ทำรายการสำเร็จ')
this.setState({
isLoading: false
})
}else {
Alert.alert('ทำรายการสำเร็จไม่สำเร็จ', 'กรุณาติดต่อผู้ดูแลเพื่อขอลบบัญชี')
this.setState({
isLoading: false
})
}
})
})
}
render() {
return (
<LinearGradient colors={['#00420A', '#00420A']} style={{
@ -69,6 +137,7 @@ class ProfileScreen extends Component {
}}>
<NavigationEvents
onDidFocus={() => {
console.log('getUserData');
this.getUserData()
}}
/>
@ -80,7 +149,7 @@ class ProfileScreen extends Component {
}}>
<Image
style={{ width: 120, height: 120, borderRadius: 60, borderColor: 'white', borderWidth: 2 }}
source={require('../../../assets/images/profile.png')}
source={this.state.profileImage}
/>
</View>
<View style={{ flex: 1, padding: 15, }}>
@ -89,7 +158,7 @@ class ProfileScreen extends Component {
<Text style={{ color: '#8BC34A', marginBottom: 10 }}>{t('profile')}</Text>
<View style={{ flexDirection: 'row' }}>
<Text style={styles.text_field_style}>{t('category')}</Text>
<Text style={styles.data_field_style}>{t('individual2')}</Text>
<Text style={styles.data_field_style}>{this.state.user.is_customer ? t('customer') : t('guest')}</Text>
</View>
<View style={{ flexDirection: 'row' }}>
<Text style={styles.text_field_style}>{t('name')}</Text>
@ -109,11 +178,11 @@ class ProfileScreen extends Component {
</View>
<View style={{ flexDirection: 'row' }}>
<Text style={styles.text_field_style}>{t('gender')}</Text>
<Text style={styles.data_field_style}>{this.state.user.gender=="male"? t('male') : t('female')}</Text>
<Text style={styles.data_field_style}>{this.state.user.gender == "male" || this.state.user.gender == "ชาย" ? t('male') : t('female')}</Text>
</View>
<View style={{ flexDirection: 'row' }}>
<Text style={styles.text_field_style}>{t('birth_date')}</Text>
<Text style={styles.data_field_style}>{moment(this.state.user.birth_date).format('DD-MM-YYYY')}</Text>
<Text style={styles.data_field_style}>{moment(this.state.user.birth_date).add(543, 'years').format('DD-MM-YYYY')}</Text>
</View>
</View>
{
@ -141,41 +210,21 @@ class ProfileScreen extends Component {
{
!this.state.user.fb_is_link?
<View style={{ flexGrow: 0.5, justifyContent: 'flex-end', backgroundColor: 'rgba(0,0,0,0)' }}>
<View style={{ justifyContent: 'flex-end', backgroundColor: 'rgba(0,0,0,0)' }}>
<Button block style={{ backgroundColor: '#145EB3', marginHorizontal: 15 }}
onPress={() => {
setTimeout( () => {
loginWithFacebook()
setTimeout( () => {
this.state.user.fb_is_link = 't'
this.props.navigation.navigate('Profile',{user:this.state.user})
Alert.alert('Connect with Facebook Success')
},4000);
loginWithFacebook(this.connectFBSuccess)
},1000);
}} >
<Text style={{ color: '#ffffff', fontSize: 14 }}>{t('connect_facebook')}</Text>
</Button>
</View>
:
<View style={{ flexGrow: 0.5, justifyContent: 'flex-end', backgroundColor: 'rgba(0,0,0,0)' }}>
<View style={{ justifyContent: 'flex-end', backgroundColor: 'rgba(0,0,0,0)' }}>
<Button block style={{ backgroundColor: '#145EB3', marginHorizontal: 15 }}
onPress={() => {
disconnectWithFacebook();
setTimeout( () => {
this.state.user.fb_is_link = 'f'
//alert("Disconnected!")
this.props.navigation.replace('Profile',{user:this.state.user})
},3000);
disconnectWithFacebook(this.disConnectFBSuccess);
}}
>
<Text style={{ color: '#ffffff', fontSize: 14 }}>{t('disconnect_facebook')}</Text>
@ -183,14 +232,23 @@ class ProfileScreen extends Component {
</View>
}
<View style={{ flexGrow: 0.5, justifyContent: 'flex-end', backgroundColor: 'rgba(0,0,0,0)' }}>
<View style={{ justifyContent: 'flex-end', backgroundColor: 'rgba(0,0,0,0)' }}>
<Button block style={{ backgroundColor: '#145EB3', margin:15 }}
onPress={() => { this.props.navigation.navigate('EditProfile',{
user:this.props.user
user:this.props.user,
image:this.state.profileImage,
}) }}>
<Text style={{ color: '#ffffff', fontSize: 14 }}><Icon name={'ic_edit'} size={15}/> {t('edit_profile')} </Text>
</Button>
</View>
<View style={{ justifyContent: 'flex-end', backgroundColor: 'rgba(0,0,0,0)' }}>
<Button block
style={{backgroundColor: 'transparent', marginBottom: 15}}
onPress={() => { this.confirmDeleteAccount() }}>
<Text style={{ color: 'red', fontSize: 16 }}> {t('delete_account')} </Text>
</Button>
</View>
</BackgroundImage_RegisterForm>
<IndicatorLoading loadingVisible={this.state.isLoading}/>
</LinearGradient>

View File

@ -1,14 +1,15 @@
import React,{Component} from 'react'
import {
TouchableOpacity,
TextInput,
StyleSheet,
View,
ScrollView,
Alert,
Image,
ImageBackground,
FlatList
TouchableOpacity,
TextInput,
StyleSheet,
View,
ScrollView,
Alert,
Image,
ImageBackground,
FlatList,
Modal
} from 'react-native'
import Icon from "../../components/Icon";
import { CustomButton } from '../../components/CustomButton';
@ -21,9 +22,26 @@ import GetWidthHeightDevice from '../../components/GetWidthHeightDevice'
import { postRepair } from '../../api/UserApi';
import IndicatorLoading from '../../components/IndicatorLoading';
import DateTimePicker from "react-native-modal-datetime-picker";
//import { CustomPicker } from '../../components/CustomPicker'
import moment from 'moment';
import { t } from '../../utils/i18n'
import { Picker } from 'native-base'
function AlertWarning({isVisible, onPress, onCancel}) {
return <Modal visible={isVisible} transparent={true} animationType="none" key="alert-warning">
<View style={styles.AlertWarningContainer}>
<View style={styles.AlertWarning}>
<View style={{width: '100%'}}>
<Text style={{fontSize: 18, color: '#00420A', marginBottom: 10}}>ไมสามารถนดหมายเวลาดงกลาวได</Text>
<Text style={{fontSize: 13, color: 'rgba(0, 0, 0, 0.5)'}}>ไมสามารถนดหมายเวลาในชวงเวลาดงกลาวได กรณาเลอกวนและเวลานดหมายใหม</Text>
<TouchableOpacity onPress={onCancel} style={{width: '100%'}}>
<Text style={[{color: '#269A21', fontSize: 16, fontWeight: '800', textAlign: 'right'}]}>บทราบ</Text>
</TouchableOpacity>
</View>
</View>
</View>
</Modal>
}
export default class RepairConfirm extends Component {
constructor(props) {
super(props)
@ -46,13 +64,12 @@ export default class RepairConfirm extends Component {
],
success_data:{},
select_date: new Date(),
select_time: new Date(),
tomorrow: new Date(moment().add(1, 'days').format()),
select_time: '09:00:00',
isTimePickerVisible: false,
isDateTimePickerVisible: false,
room: '',
project: '',
isShowWarning: false
}
this.confirmRepairService = this.confirmRepairService.bind(this)
this.hideDateTimePicker = this.hideDateTimePicker.bind(this)
@ -64,22 +81,21 @@ export default class RepairConfirm extends Component {
componentDidMount = () => {
const { navigation } = this.props
const repair_state = navigation.getParam('repair', 'NO-DATA')
let sum_service_fee = 0;
if(repair_state && repair_state.repairs && repair_state.repairs.length > 0){
repair_state.repairs.map((value) => {
sum_service_fee += parseFloat(value.service_fee)
})
}
console.log('service >>> ', repair_state.repairs)
// this.state.repair = { repair: repair_state }
this.state.repair = repair_state
this.setState({
repair: repair_state,
room: repair_state.repairs[0].room,
project: repair_state.repairs[0].project,
room: repair_state.rooms && repair_state.rooms.length > 0 && repair_state.rooms[0].room_no ? repair_state.rooms[0].room_no : '',
project_name: repair_state.rooms && repair_state.rooms.length > 0 && repair_state.rooms[0].project_name ? repair_state.rooms[0].project_name : '',
project_id: repair_state.rooms && repair_state.rooms.length > 0 && repair_state.rooms[0].project_id ? repair_state.rooms[0].project_id : null,
sum_service_fee: sum_service_fee
})
console.log('repair_state:')
console.log(repair_state)
console.log('this.state.repair:')
console.log(this.state.repair)
console.log('room')
console.log(this.state.repair.repairs[0].room)
console.log('project')
console.log(this.state.repair.repairs[0].project)
};
confirmRepairService(){
@ -87,46 +103,44 @@ export default class RepairConfirm extends Component {
isLoading: true
})
console.log('this.state.repair.date:')
// console.log(this.state.repair.date)
console.log(moment(this.state.select_date).format('YYYY-MM-DD'))
console.log('this.state.repair.time:')
// console.log(this.state.repair.time)
console.log(moment(this.state.select_time).format('HH:mm'))
console.log('this.state.repair:')
console.log(this.state.repair)
let params = {
// date: this.state.repair.date,
date: moment(this.state.select_date).format('YYYY-MM-DD'),
// time: this.state.repair.time,
time: moment(this.state.select_time).format('HH:mm'),
repairs:[
{
services_id: this.state.repair.repairs[0].services_id,
},
],
room: this.state.repair.repairs[0].room,
project: this.state.repair.repairs[0].project,
let services = [];
if(this.state.repair && this.state.repair.repairs && this.state.repair.repairs.length > 0){
this.state.repair.repairs.map(value => {
services.push(value.id)
})
}
let params = {
date: moment(this.state.select_date).format('YYYY-MM-DD'),
time: this.state.select_time,
repairs: services,
room: this.state.room,
project: this.state.project_id,
}
console.log('check paran send ------->> ', params)
postRepair(params)
.then(res => {
console.log('response ----------------------- ',res.data);
if(res.ok){
this.setState({
success_data: res.data.data,
isLoading: false
},() => {
console.log('success_data:')
console.log(res.data.data)
this.props.navigation.navigate('RepairSuccess',{
repair: this.state.success_data,
room: this.state.repair.repairs[0].room,
project: this.state.repair.repairs[0].project,
if(!res.data.success){
this.setState({
isLoading: false,
isShowWarning: true
})
}else {
this.setState({
success_data: res.data.data,
isLoading: false
},() => {
this.props.navigation.navigate('RepairSuccess',{
repair: this.state.success_data
})
})
}
}else {
this.setState({
isLoading: false
})
}
})
@ -166,90 +180,136 @@ export default class RepairConfirm extends Component {
this.setState({ isTimePickerVisible: !this.state.isTimePickerVisible });
};
handleTimePicked = date => {
this.state.select_time = date
//alert(date)
this.hideTimePicker();
// this.setState({select_time: date})
this.state.select_time = date
handleTimePicked = time => {
this.setState({
select_time: time
})
};
render() {
return (
<ImageBackground source={require('../../../assets/images/tree2.png')} style={{width: '100%', height: '100%', backgroundColor:'#EEFFD7'}}>
<ImageBackground source={require('../../../assets/images/tree2.png')} style={{width: '100%', flex: 1, backgroundColor:'#EEFFD7'}}>
<View style={styles.containerHeadbar}>
<View>
<View style={{padding:16}}>
<LinearGradient colors={['#4BAF3B', '#0E5E29']} style={{resizeMode: 'cover', borderRadius:5}}>
<View style={{padding:16}}>
<Text style={{ fontSize: 18, color: 'white'}}>{t('room')} { this.state.room }</Text>
<Text style={{ fontSize: 14, color: 'white'}}>{ this.state.project }</Text>
</View>
</LinearGradient>
<Text style={{ fontSize: 14, color: '#00420A', paddingBottom: 10, paddingTop: 16 }}>{t('make_appoint')}</Text>
<View style={{width: '100%'}}>
<View style={{ flexDirection: 'row',}}>
<TouchableOpacity style={{flexDirection:'row', flex:0.6,backgroundColor: 'white',height:50, borderRadius:25, justifyContent:'center', alignItems:'center',marginRight:5}}
onPress={this.hideDateTimePicker}>
<Text style={{ fontSize: 14, color: Color.gray_half}}>{t('date')}</Text>
<Text style={{fontSize: 14, color: '#000000', marginHorizontal: 10,}}>{moment(this.state.select_date).format('DD-MM-YYYY')}</Text>
<Icon name="ic_calendar_alt" size={14} color="rgba(0,0,0,.5)" />
</TouchableOpacity>
<TouchableOpacity style={{flexDirection:'row', flex:0.4,backgroundColor: 'white',height:50, borderRadius:25, justifyContent:'center', alignItems:'center',marginLeft:5}}
onPress={this.hideTimePicker}>
<Text style={{ fontSize: 14, color: Color.gray_half}}>{t('time')}</Text>
<Text style={{ fontSize: 14, color: '#000000',marginLeft:10}}>{moment(this.state.select_time).format('HH:mm')}</Text>
</TouchableOpacity>
<View style={{paddingHorizontal: 16, paddingTop: 16}}>
<LinearGradient colors={['#4BAF3B', '#0E5E29']} style={{resizeMode: 'cover', borderRadius:5}}>
<View style={{padding:16}}>
<Text style={{ fontSize: 18, color: 'white'}}>{t('room')} { this.state.room }</Text>
<Text style={{ fontSize: 14, color: 'rgba(255, 255, 255, 0.65)' }}>{t('project') + this.state.project_name }</Text>
</View>
</LinearGradient>
</View>
<View style={{paddingHorizontal: 16, paddingBottom: 16}}>
<Text style={{ fontSize: 14, color: '#00420A', paddingBottom: 10, paddingTop: 16 }}>{t('make_appoint')}</Text>
<View style={{width: '100%'}}>
<View style={{ flexDirection: 'row',}}>
<TouchableOpacity style={{flexDirection:'row', flex:0.5,backgroundColor: 'white',height:50, borderRadius:25, justifyContent:'center', alignItems:'center',marginRight:5}}
onPress={this.hideDateTimePicker}>
<Text style={{ fontSize: 14, color: Color.gray_half}}>{t('date')}</Text>
<Text style={{fontSize: 14, color: '#000000', marginHorizontal: 10,}}>{moment(this.state.select_date).format('DD-MM-YYYY')}</Text>
<Icon name="ic_calendar_alt" size={14} color="rgba(0,0,0,.5)" />
</TouchableOpacity>
<View style={{ flexDirection:'row', paddingLeft: 15, flex:0.5,backgroundColor: 'white',height:50, borderRadius:25, justifyContent:'center', alignItems:'center',marginLeft:5}}>
<Text style={{ fontSize: 14, color: Color.gray_half}}>{t('time')}</Text>
<Picker
mode="dialog"
inlineLabel
iosHeader={t('time')}
style={{ backgroundColor: 'white', flexGrow: 0, width: 80, height: 40, fontFamily: 'Prompt-Regular', fontSize: 14 }}
placeholderStyle={{ fontFamily: 'Prompt-Regular', fontSize: 14, color: "#bfc6ea" }}
placeholderIconColor="#007aff"
textStyle={{ fontFamily: 'Prompt-Regular', fontSize: 14 }}
itemTextStyle={{ fontFamily: 'Prompt-Regular', fontSize: 14 }}
selectedValue={this.state.select_time}
enabled={true}
onValueChange={(itemValue, itemIndex) => {
console.log(itemValue)
this.handleTimePicked(itemValue)
}}
>
<Picker.Item label="09:00" value="09:00:00" />
<Picker.Item label="10:00" value="10:00:00" />
<Picker.Item label="11:00" value="11:00:00" />
<Picker.Item label="12:00" value="12:00:00" />
<Picker.Item label="13:00" value="13:00:00" />
<Picker.Item label="14:00" value="14:00:00" />
<Picker.Item label="15:00" value="15:00:00" />
<Picker.Item label="16:00" value="16:00:00" />
</Picker>
{/*<Picker
selectedValue={this.state.select_time}
// mode={'dropdown'}
style={{
height: 50, flex:1
}}
onValueChange={(itemValue, itemIndex) => this.handleTimePicked(itemValue)}
>
<Picker.Item label="09:00" value="09:00:00" />
<Picker.Item label="10:00" value="10:00:00" />
<Picker.Item label="11:00" value="11:00:00" />
<Picker.Item label="12:00" value="12:00:00" />
<Picker.Item label="13:00" value="13:00:00" />
<Picker.Item label="14:00" value="14:00:00" />
<Picker.Item label="15:00" value="15:00:00" />
<Picker.Item label="16:00" value="16:00:00" />
</Picker>*/}
</View>
</View>
</View>
</View>
<View style={{ flex: 1 }}>
<Text style={{ fontSize: 14, color: '#00420A', paddingBottom: 10, marginHorizontal:16}} >{t('information')}</Text>
<View style={{backgroundColor: 'white',}}>
<FlatList
data={this.state.repair.repairs}
renderItem={this.renderItem}
onScroll={this._onCarouselScroll}
pagingEnabled={true}
extraData={this.state}
keyExtractor={this._keyExtractor}
/>
<View style={{ backgroundColor: 'white', flex: 1}}>
<ScrollView>
<FlatList
data={this.state.repair.repairs}
renderItem={this.renderItem}
onScroll={this._onCarouselScroll}
pagingEnabled={true}
extraData={this.state}
keyExtractor={this._keyExtractor}
/>
</ScrollView>
<View style={{ flexDirection: 'row',paddingHorizontal:16,height: 40,justifyContent:'space-between',alignItems:'center'}}>
<Text style={{ fontSize: 14, color: '#269A21'}}>{t('estimate_charge')}</Text>
<Text style={{ textAlign: 'right', fontSize: 14, color: '#7CBB33'}}>{this.state.repair.service_fee} {t('baht')}</Text>
<Text style={{ fontSize: 14, color: '#269A21'}}>{t('estimate_charge')}</Text>
<Text style={{ textAlign: 'right', fontSize: 14, color: '#7CBB33'}}>{this.state.sum_service_fee} {t('baht')}</Text>
</View>
</View>
</View>
</View>
<View style={{flex:1,padding:16,justifyContent:'flex-end'}}>
<View style={{ padding: 16}}>
<CustomButton style={[styles.button_style]}
onPress={() => {
Alert.alert(
t('send_confirmation'),
t('send_confirm'),
[
{ text: t('cancel'), style: 'cancel' },
{ text: t('ok'), onPress: () => this.confirmRepairService() },
],
{ cancelable: false }
)
}}
title={'ยืนยัน'} />
onPress={() => {
Alert.alert(
t('send_confirmation'),
t('send_confirm'),
[
{ text: t('cancel'), style: 'cancel' },
{ text: t('ok'), onPress: () => this.confirmRepairService() },
],
{ cancelable: false }
)
}}
title={'ยืนยัน'} />
</View>
<DateTimePicker
date={this.state.select_date}
isVisible={this.state.isDateTimePickerVisible}
onConfirm={this.handleDatePicked}
onCancel={this.hideDateTimePicker}
minimumDate={this.state.tomorrow}
/>
<DateTimePicker
date={this.state.select_time}
isVisible={this.state.isTimePickerVisible}
onConfirm={this.handleTimePicked}
onCancel={this.hideTimePicker}
mode={'time'}
/>
<IndicatorLoading loadingVisible={this.state.isLoading}/>
</View>
<DateTimePicker
date={this.state.select_date}
isVisible={this.state.isDateTimePickerVisible}
onConfirm={this.handleDatePicked}
onCancel={this.hideDateTimePicker}
minimumDate={new Date()}
/>
<IndicatorLoading loadingVisible={this.state.isLoading}/>
<AlertWarning
isVisible={this.state.isShowWarning}
onCancel={() => this.setState({isShowWarning: false})}
onPress={() => this.setState({isShowWarning: false})}/>
</ImageBackground>
)
}
@ -258,13 +318,33 @@ export default class RepairConfirm extends Component {
const styles = {
containerHeadbar: {
flex: 1,
height: GetWidthHeightDevice.HeightContainer,
justifyContent:'space-between'
height: GetWidthHeightDevice.HeightContainer ? GetWidthHeightDevice.HeightContainer : null,
// justifyContent:'space-between',
},
button_style: {
backgroundColor: '#269A21',
height: 40,
height: 45,
borderRadius: 5,
justifyContent:'center',
},
AlertWarningContainer: {
backgroundColor: 'rgba(0,0,0,0.6)',
justifyContent: 'center',
alignItems: 'center',
position: 'absolute',
width: '100%',
height: '100%',
flex: 1
},
AlertWarning: {
backgroundColor: 'white',
justifyContent: 'center',
alignItems: 'center',
borderRadius: 5,
marginHorizontal: 25,
paddingVertical: 20,
paddingHorizontal: 20,
maxWidth: 300,
width: '100%'
}
}

View File

@ -22,6 +22,7 @@ import GetWidthHeightDevice from '../../components/GetWidthHeightDevice'
import {getRepairList} from '../../api/UserApi';
import IndicatorLoading from '../../components/IndicatorLoading';
import { t } from '../../utils/i18n'
import moment from "moment";
export default class RepairHistory extends Component {
@ -83,30 +84,31 @@ export default class RepairHistory extends Component {
convertStatus(statusName){
switch(statusName){
case 'Pending':
return t('pending')
return t('request_repair')
case 'InProgress':
return 'ซ่อมแซม'
return 'ยืนยันนัด'
case 'NewAppointment':
return 'นัดหมายใหม่'
case 'Cancel':
return t('cancel')
case 'Success':
return 'สำเร็จ'
return 'ซ่อมสำเร็จ'
default:
return t('pending')
return t('request_repair')
}
}
convertColorStatus(statusName){
switch(statusName){
case 'Pending':
return '#C4C4C4'
return '#FF9500'
case 'InProgress':
return '#FFCC00'
return '#007AFF'
// return '#FFCC00'
case 'NewAppointment':
return '#145EB3'
case 'Cancel':
return '#FF2D55'
return '#666666'
case 'Success':
return '#2C7C0B'
default:
@ -116,7 +118,10 @@ export default class RepairHistory extends Component {
renderItem = (item) => {
return <TouchableOpacity style={{ borderBottomColor: '#00000040', borderBottomWidth: 1, backgroundColor: 'white' }}
onPress={() => {this.props.navigation.navigate('RepairHistoryDetail',{repair_id:item.id})}}>
onPress={() => {this.props.navigation.navigate('RepairHistoryDetail',{
repair_id:item.id,
getRepairHistoryList: () => {this.getRepairHistoryList()}
})}}>
<View style={{height: 104,justifyContent:'center',paddingHorizontal:16}}>
<View style={{flexDirection:'row',justifyContent:'space-between'}}>
<Text style={{color: Color.green_title, fontSize: 16,}}>{t('room')} {item.room_no}</Text>
@ -127,14 +132,19 @@ export default class RepairHistory extends Component {
</View>
<View style={{flexDirection:'row',justifyContent:'space-between',marginVertical:5}}>
<Text style={{fontSize:14}}>{item.services_name}</Text>
<Text style={{fontSize:14}}>#{item.tag}</Text>
<Text style={{fontSize:14}}>#{item.id}</Text>
</View>
<View style={{flexDirection:'row',justifyContent:'space-between'}}>
<View style={{flexDirection:'row',alignItems:'center'}}>
<Icon name="ic_calendar_alt" size={14} color="#00000080" />
<Text style={{marginLeft: 10, fontSize:12}}>{`${item.date}, ${item.time}`}</Text>
<Text style={{marginLeft: 10, fontSize:12}}>
{ item.date ?
`${moment(item.date).format('DD-MM-YYYY')}, ${item.time.slice(0,-3)}`
: item.status === 'Cancel' ? '-' : 'รอการนัดหมายใหม่'
}
</Text>
</View>
<Text style={{color: '#145EB3'}}>{item.points} คะแนน</Text>
<Text style={{color: '#145EB3', fontSize: 12}}>{item.status === 'Success' && item.points ? item.points + ' คะแนน' : ''}</Text>
</View>
</View>
</TouchableOpacity>

View File

@ -1,14 +1,14 @@
import React,{Component} from 'react'
import {
TouchableOpacity,
TextInput,
StyleSheet,
View,
ScrollView,
Alert,
Image,
ImageBackground,
FlatList
TouchableOpacity,
TextInput,
StyleSheet,
View,
ScrollView,
Alert,
Image,
ImageBackground,
FlatList, Modal
} from 'react-native'
import Icon from "../../components/Icon";
import { CustomButton } from '../../components/CustomButton';
@ -18,18 +18,44 @@ import Text from '../../components/Text';
import LinearGradient from 'react-native-linear-gradient';
import Color from '../../color';
import GetWidthHeightDevice from '../../components/GetWidthHeightDevice'
import { getRepairById } from '../../api/UserApi';
import {cancelRepair, getRepairById} from '../../api/UserApi';
import IndicatorLoading from '../../components/IndicatorLoading';
import { t } from '../../utils/i18n'
import moment from 'moment';
function AlertWarning({isVisible, onPress, onCancel}) {
return <Modal visible={isVisible} transparent={true} animationType="none" key="alert-warning">
<View style={styles.AlertWarningContainer}>
<View style={styles.AlertWarning}>
<View style={{width: '100%'}}>
<Text style={{fontSize: 18, color: '#FF3B30', marginBottom: 10}}>นยนยกเลกการแจงซอม</Text>
<Text style={{fontSize: 14, color: 'rgba(0, 0, 0, 0.5)'}}>
ณตองการทจะยกเลกการแจงซอม หรอไม ? กด <Text style={{fontFamily: 'Prompt-Bold'}}>"ยืนยัน"</Text>
</Text>
<View style={{flexDirection: 'row', justifyContent: 'flex-end', width: '100%', marginTop: 10}}>
<TouchableOpacity onPress={onCancel} style={{marginRight: 20}}>
<Text style={[{color: 'rgba(0, 0, 0, 0.5)', fontSize: 16, fontWeight: '800'}]}>{t('cancel')}</Text>
</TouchableOpacity>
<TouchableOpacity onPress={onPress}>
<Text style={[{color: '#FF3B30', fontSize: 16, fontWeight: '800'}]}>นย</Text>
</TouchableOpacity>
</View>
</View>
</View>
</View>
</Modal>
}
export default class RepairHistoryDetail extends Component {
constructor(props) {
super(props)
this.state = {
isLoading: false,
repair_id: this.props.navigation.getParam('repair_id','NO_ITEM'),
type: this.props.navigation.getParam('type','NO_ITEM'), //params from Notification.js
repair:{},
visibleCancel: false,
rating_point: [0,0,0,0,0],
order_list:[
// {
// title: 'น้ำรั่ว',
@ -49,16 +75,53 @@ export default class RepairHistoryDetail extends Component {
this.convertColorStatus = this.convertColorStatus.bind(this)
}
componentWillUnmount = () => {
if(this.props && this.props.navigation && this.props.navigation.state && this.props.navigation.state.params && this.props.navigation.state.params.getRepairHistoryList){
this.props.navigation.state.params.getRepairHistoryList()
}
}
componentDidMount = () => {
this.props.navigation.setParams({cancelRepair: this.cancelRepair})
this.getRepairData()
};
cancelRepair = () => {
this.setState({
visibleCancel: true
})
}
confirmCancel = () => {
this.setState({
isLoading: true
}, () => {
cancelRepair(this.state.repair.id)
.then(res => {
if(res.ok){
if(res.data.success){
this.setState({
visibleCancel: false,
isLoading: false
}, () => {
this.getRepairData()
})
}else {
this.setState({
visibleCancel: false,
isLoading: false
})
}
}
})
})
}
getRepairData(){
this.setState({
isLoading: true
})
getRepairById(this.state.repair_id)
getRepairById(this.state.repair_id, this.state.type)
.then(res => {
console.log('repair data -------------> ',res.data.data)
this.setState({
@ -66,13 +129,29 @@ export default class RepairHistoryDetail extends Component {
order_list: res.data.data.services,
isLoading: false
})
let rating_star = [0, 0, 0, 0, 0];
for(let i=0; i<res.data.data.points; i++){
rating_star[i] = 1;
}
this.setState({
rating_point: rating_star
})
this.props.navigation.setParams({statusRepair: res.data.data.status})
})
.catch(() => {
this.setState({
isLoading: false
})
})
}
renderItem = (item) => {
return <View style={{ flexDirection: 'row', marginVertical:3, justifyContent:'space-between'}}>
<Text style={{ fontSize: 14, color: '#000000' }}>{item.name}</Text>
<Text style={{ textAlign: 'right', fontSize: 14, color: '#7CBB33' }}>{item.service_fee} {t('baht')}</Text>
<Text style={{ textAlign: 'right', fontSize: 14, color: this.state.type === 'effect_responsible' ? 'red' : '#7CBB33' }}>{this.state.repair.status === 'Cancel' ? 0: item.service_fee} {t('baht')}</Text>
</View>
}
@ -81,15 +160,15 @@ export default class RepairHistoryDetail extends Component {
convertStatus(statusName){
switch(statusName){
case 'Pending':
return t('pending')
return t('request_repair');
case 'InProgress':
return 'ซ่อมแซม'
return 'ยืนยันนัด';
case 'NewAppointment':
return 'นัดหมายใหม่'
return t('repair_re_appoint');
case 'Cancel':
return t('cancel')
return t('cancel');
case 'Success':
return 'สำเร็จ'
return t('repair_success');
default:
return t('pending')
}
@ -98,63 +177,184 @@ export default class RepairHistoryDetail extends Component {
convertColorStatus(statusName){
switch(statusName){
case 'Pending':
return '#C4C4C4'
return '#FF9500';
case 'InProgress':
return '#FFCC00'
// return '#FFCC00'
return '#007AFF';
case 'NewAppointment':
return '#145EB3'
return '#145EB3';
case 'Cancel':
return '#FF2D55'
return '#666666';
case 'Success':
return '#2C7C0B'
return '#2C7C0B';
default:
return '#C4C4C4'
return '#C4C4C4';
}
}
render() {
return (
<ImageBackground source={require('../../../assets/images/tree2.png')} style={{width: '100%', height: '100%', backgroundColor:'#EEFFD7'}}>
<View style={{padding:16}}>
<View>
<LinearGradient colors={['#4BAF3B', '#0E5E29']} style={{borderRadius:5, padding:16}}>
<View style={{flexDirection:'row',justifyContent:'space-between'}}>
<Text style={{ fontSize: 18, color: '#FFFFFF'}} >{t('room')} A1-1</Text>
<Text style={{ textAlign:'right', fontSize: 18, color: '#FFFFFF', }} >#{this.state.repair.tag}</Text>
</View>
<Text style={{ fontSize: 14, color: '#FFFFFF', }}>โครงการเจรญสนธาน (CNE)</Text>
</LinearGradient>
<View style={{backgroundColor: '#FFFFFF',borderRadius:5,padding:16}}>
<View style={{padding:16, flex: 1}}>
<LinearGradient colors={['#4BAF3B', '#0E5E29']} style={{borderRadius:5, padding:16}}>
<View style={{flexDirection:'row',justifyContent:'space-between'}}>
<Text style={{ fontSize: 18, color: '#FFFFFF'}} >{t('room')} {this.state.repair && this.state.repair.room_no ? this.state.repair.room_no : ''}</Text>
<Text style={{ textAlign:'right', fontSize: 18, color: '#FFFFFF', }} >#{this.state.repair && this.state.repair.id ? this.state.repair.id : ''}</Text>
</View>
<Text style={{ fontSize: 14, color: 'rgba(255, 255, 255, 0.65)', }}>{this.state.repair && this.state.repair.project_name ? this.state.repair.project_name : '' }</Text>
</LinearGradient>
<View style={{backgroundColor: '#FFFFFF',borderRadius:5,padding:16, flex: 1 }}>
<View>
<Text style={styles.textTitle}>{t('make_appoint')}</Text>
<View style={{ flexDirection: 'row',}}>
<Text style={{ fontSize: 14, color: '#C4C4C4', }}>{t('date')}</Text>
<Text style={{ fontSize: 14, color: '#000000', paddingHorizontal: 10,}}>{moment(this.state.repair.date).format('DD-MM-YYYY') }</Text>
<Text style={{ fontSize: 14, color: '#C4C4C4', }}>เวลา</Text>
<Text style={{ fontSize: 14, color: '#000000', paddingHorizontal: 10,}}>{moment(this.state.repair.time).format('HH:mm') }</Text>
{
this.state.repair && this.state.repair.status ?
this.state.repair.status === 'Pending'
&& (this.state.repair.date === null || this.state.repair.time === null || this.state.repair.date === '' || this.state.repair.time === '')
? <Text style={{ fontSize: 14, color: '#000000', paddingRight: 10,}}>กรณารอการนดหมายใหมจากเจาหนาท</Text>
: <View style={{flexDirection: 'row'}}>
<Text style={{ fontSize: 14, color: 'rgba(0, 0, 0, 0.5)' }}>{t('date')}</Text>
<Text style={{ fontSize: 14, color: '#000000', paddingHorizontal: 10,}}>{this.state.repair && this.state.repair.date ? moment(this.state.repair.date, 'YYYY-MM-DD').format('DD-MM-YYYY') : '' }</Text>
<Text style={{ fontSize: 14, color: 'rgba(0, 0, 0, 0.5)' }}>เวลา</Text>
<Text style={{ fontSize: 14, color: '#000000', paddingHorizontal: 10,}}>{this.state.repair && this.state.repair.time ? moment(this.state.repair.time, 'HH:mm:ss').format('HH:mm') + ' น.' : '' }</Text>
</View>
: <Text/>
}
</View>
<View style={{ flexDirection: 'row',alignItems:'center',marginVertical:3}}>
<Text style={{ fontSize: 14, color: '#C4C4C4',}}>{t('status')}</Text>
<Text style={{ fontSize: 14, color: 'rgba(0, 0, 0, 0.5)'}}>{t('status')}</Text>
<View style={{backgroundColor:this.convertColorStatus(this.state.repair.status),height: 10,width: 10,borderRadius:5, marginHorizontal:10}}/>
<Text style={{ fontSize: 14, color:this.convertColorStatus(this.state.repair.status)}}>{this.convertStatus(this.state.repair.status)}</Text>
<Text style={{ fontSize: 14, color:this.convertColorStatus(this.state.repair.status)}}>{this.state.repair && this.state.repair.status ? this.convertStatus(this.state.repair.status) : ''}</Text>
</View>
<View style={{borderWidth:1,marginVertical:16,borderColor:'silver'}}></View>
<Text style={styles.textTitle} >{t('information')}</Text>
<FlatList
data={this.state.order_list}
renderItem={({ item }) => this.renderItem(item)}
pagingEnabled={true}
extraData={this.state}
keyExtractor={this._keyExtractor}
/>
<View style={{borderWidth:1,marginVertical:16,borderColor:'silver'}}></View>
<View style={{ flexDirection:'row',justifyContent:'space-between'}}>
<Text style={{ fontSize: 14, color: Color.green_title }}>{t('estimate_charge')}</Text>
<Text style={{ textAlign: 'right', fontSize: 14, color: '#7CBB33'}}>850 {t('baht')}</Text>
</View>
<View style={{borderWidth:1,marginVertical:16,borderColor:'silver'}}></View>
<View style={{ flex: 1 }}>
<Text style={[styles.textTitle, this.state.type === 'effect_responsible' ? {color: '#FF3B30'} : {}]} >
{this.state.type === 'effect_responsible' ? 'รายการซ่อมที่ต้องรับผิดชอบ' : t('information')}
</Text>
<ScrollView>
<FlatList
data={this.state.order_list}
renderItem={({ item }) => this.renderItem(item)}
pagingEnabled={true}
extraData={this.state}
keyExtractor={this._keyExtractor}
/>
</ScrollView>
</View>
<View style={{borderWidth:1,marginVertical:16,borderColor:'silver'}}></View>
<View style={{ flexDirection:'row',justifyContent:'space-between'}}>
<Text style={[{ fontSize: 14}, this.state.type === 'effect_responsible' ? {color: '#FF3B30'} : {color: Color.green_title}]}>{t('estimate_charge')}</Text>
<Text style={[{ textAlign: 'right', fontSize: 14, color: '#7CBB33'}, this.state.type === 'effect_responsible' ? {color: '#FF3B30'} : {color: Color.green_title}]}>{this.state.repair.status === 'Cancel' ? 0 : this.state.repair && this.state.repair.total ? this.state.repair.total : 0} {t('baht')}</Text>
</View>
</View>
{
this.state.repair.status === 'Success' && this.state.repair.points &&
<View style={{marginTop: 16, backgroundColor: '#FFFFFF',borderRadius:5, paddingVertical: 16}}>
<View>
<Text style={{ fontSize: 14, color: Color.green_title, textAlign: 'center'}} >คะแนนการประเม</Text>
<View style={{flexDirection: 'row', marginTop: 15, justifyContent: 'center'}}>
{
this.state.rating_point.map((point, index) =>
point === 0 ?
<View style={{alignItems: 'center', marginRight: index !== this.state.rating_point.length - 1 ? 15 : 0}}>
<Text style={{ fontSize: 14, color: '#000000', marginBottom: 10}} >{index + 1}</Text>
<Image source={require('../../../assets/images/star_grey.png')} style={{width: 40, height: 40}}/>
</View>
: <View style={{alignItems: 'center', marginRight: index !== this.state.rating_point.length - 1 ? 15 : 0}}>
<Text style={{ fontSize: 14, color: '#000000', marginBottom: 10}} >{index + 1}</Text>
<Image source={require('../../../assets/images/star_yellow.png')} style={{width: 40, height: 40}}/>
</View>
)
}
</View>
</View>
</View>
}
<View style={{ width: '100%', alignItems: 'center', marginTop: 16}}>
{
!this.state.repair.points &&
<CustomButton style={[styles.button_style]}
onPress={() => {
this.props.navigation.navigate('Question')
}}
title={'ติดต่อเจ้าหน้าที่'}/>
}
{
!this.state.repair.points && this.state.repair.status === 'Success' &&
<CustomButton style={[styles.button_style, {backgroundColor: '#269A21', marginTop: 16}]}
onPress={() => {
this.props.navigation.navigate('RepairDetail', {
id: this.state.repair.id
})
}}
title={'ประเมินให้คะแนน'}/>
}
</View>
{/* <View>
{
this.state.repair.status === 'Success' && this.state.repair.points &&
<View style={{padding:16, backgroundColor: '#FFFFFF',borderRadius:5, marginHorizontal: 16}}>
<View>
<Text style={{ fontSize: 14, color: Color.green_title, textAlign: 'center'}} >คะแนนการประเม</Text>
<View style={{flexDirection: 'row', marginTop: 15, justifyContent: 'center'}}>
{
this.state.rating_point.map((point, index) =>
point === 0 ?
<View style={{alignItems: 'center', marginRight: index !== this.state.rating_point.length - 1 ? 15 : 0}}>
<Text style={{ fontSize: 14, color: '#000000', marginBottom: 10}} >{index + 1}</Text>
<Image source={require('../../../assets/images/star_grey.png')} style={{width: 40, height: 40}}/>
</View>
: <View style={{alignItems: 'center', marginRight: index !== this.state.rating_point.length - 1 ? 15 : 0}}>
<Text style={{ fontSize: 14, color: '#000000', marginBottom: 10}} >{index + 1}</Text>
<Image source={require('../../../assets/images/star_yellow.png')} style={{width: 40, height: 40}}/>
</View>
)
}
</View>
</View>
</View>
}
<View style={{position: 'absolute', bottom: 16, width: '100%', alignItems: 'center'}}>
{
!this.state.repair.points &&
<CustomButton style={[styles.button_style, {marginBottom: 10}]}
onPress={() => {
this.props.navigation.navigate('Question')
}}
title={'ติดต่อเจ้าหน้าที่'}/>
}
{
!this.state.repair.points && this.state.repair.status === 'Success' &&
<CustomButton style={[styles.button_style, {backgroundColor: '#269A21'}]}
onPress={() => {
this.props.navigation.navigate('RepairDetail', {
id: this.state.repair.id
})
}}
title={'ประเมินให้คะแนน'}/>
}
*/}
</View>
<IndicatorLoading loadingVisible={this.state.isLoading} />
<AlertWarning
isVisible={this.state.visibleCancel}
onPress={() => this.confirmCancel()}
onCancel={() => this.setState({visibleCancel: false})}
/>
</ImageBackground>
)
}
@ -165,5 +365,33 @@ const styles = {
fontSize: 14,
color: Color.green_title,
marginBottom: 10
},
button_style: {
backgroundColor: '#007AFF',
height: 40,
borderRadius: 5,
width: '100%',
justifyContent:'center',
},
AlertWarningContainer: {
backgroundColor: 'rgba(0,0,0,0.6)',
justifyContent: 'center',
alignItems: 'center',
position: 'absolute',
width: '100%',
height: '100%',
flex: 1
},
AlertWarning: {
backgroundColor: 'white',
justifyContent: 'center',
alignItems: 'center',
borderRadius: 5,
marginHorizontal: 25,
paddingVertical: 20,
paddingHorizontal: 20,
maxWidth: 300,
width: '100%'
}
}

View File

@ -1,5 +1,5 @@
import React, {Component} from 'react'
import {Button, View,} from 'native-base'
import {Accordion, Button, View,} from 'native-base'
import {Dimensions, FlatList, ScrollView, StyleSheet, TouchableOpacity, Alert, RefreshControl} from 'react-native'
import Image from 'react-native-fast-image'
import ImageBackground from 'react-native-fast-image'
@ -7,7 +7,7 @@ import LinearGradient from 'react-native-linear-gradient'
import Text from '../../components/Text';
import moment from "moment";
import Color from '../../../src/color';
import {getService, getServicesType, getUserProfile, payment} from '../../api/UserApi';
import {getRoomUser, getService, getServicesType, getUserProfile, payment} from '../../api/UserApi';
import IndicatorLoading from '../../components/IndicatorLoading';
import { t, locale } from '../../utils/i18n';
import Icon from '../../components/Icon';
@ -16,7 +16,7 @@ const SLIDER_1_FIRST_ITEM = 0;
const { height, width } = Dimensions.get('window')
const btnActiveColor = '#145EB3'
const btnUnActiveColor = '#FFFFFF'
const btnUnActiveColor = 'rgba(255, 255, 255, 0.45)'
export default class RepairService extends Component {
constructor(props) {
super(props)
@ -26,11 +26,12 @@ export default class RepairService extends Component {
refreshing: false,
activePage: 0,
repair_list:[],
isSelectReapair: true,
isSelectRepair: true,
isSelectOther: false,
indexItem: [],
selectServiceIndex: 0,
selectService:{},
selectServiceId: [],
selectService:[],
room_list:[],
service_data : [],
customer_project_name: '',
@ -47,7 +48,7 @@ export default class RepairService extends Component {
selected_project: '',
loadMore: false,
loadPage: 1,
isLoadmore: false,
isLoadmore: false
};
this._onCarouselScroll = this._onCarouselScroll.bind(this)
this.switchSelected = this.switchSelected.bind(this)
@ -57,237 +58,102 @@ export default class RepairService extends Component {
};
componentDidMount = () => {
const { navigation } = this.props
const users_state = navigation.getParam('user', 'NO ITEM')
const selected_room_state = navigation.getParam('selected_room', '')
const selected_project_state = navigation.getParam('selected_project', '')
this.state.selected_room = selected_room_state
this.state.selected_project = selected_project_state
console.log('init selected_room:'+ selected_room_state)
console.log('init selected_project:'+ selected_project_state)
// if((selected_room_state !== '')&&(selected_project_state !== '')){
//this.switchSelected('repair')
// }else{
this.getServicesListByType(2)
// }
// console.log('check user state ----------- ',users_state)
if(users_state.gender == null || users_state.gender == 'null'){
console.log('NULL');
this.setState({
user: {
gender: 'male',
...users_state
}
})
}else{
console.log('NOT NULL');
this.setState({
user: users_state
})
}
console.log('users_state:')
console.log(users_state)
if(users_state){
payment(users_state.id)
.then(res => {
if(res.ok){
let sum_payment = [];
let array_payment = [];
let sum_cost_room = res.data.sum_cost_room;
if(Object.keys(sum_cost_room).length > 0) {
Object.keys(sum_cost_room).map((sum_cost) => {
sum_payment.push({
total_cost : sum_cost_room[sum_cost].total_cost,
room: sum_cost_room[sum_cost].room,
project: sum_cost_room[sum_cost].project,
due_at: sum_cost_room[sum_cost].due_at,
}
)
})
}
let payment = res.data.payment_room_period
if(Object.keys(payment).length > 0){
Object.keys(payment).map((pay) => {
if(Object.keys(payment[pay]).length > 0){
Object.keys(payment[pay]).map((detail) => {
this.state.room_number_array.push(pay)
array_payment.push({
room_id: pay,
period: detail,
// total_cost: payment[pay][detail].total_cost,
// details: payment[pay][detail].details,
// status: payment[pay][detail].status,
// created_at: payment[pay][detail].created_at,
// payment_id: payment[pay][detail].id,
// enable_qr: payment[pay][detail].enable_qr
...payment[pay][detail]
})
})
}
})
}
let all_payment_data = array_payment;
let array_room_no = this.state.room_number_array;
this.setState({
room_number_array: array_room_no.filter((item, i, ar) => ar.indexOf(item) === i).reverse()
});
let first_room = this.state.room_number_array[0];
array_payment = array_payment.filter((obj)=>{
return Object.keys(obj).reduce((acc, curr)=>{
return obj.room_id === first_room
}, false);
});
let date_now = moment()
let findTimeout = array_payment.find((item) => {return moment(item.due_at) == date_now})
//check bill timeout
if(findTimeout !== undefined){
this.setState({
isCanPay: false
})
}
this.setState({
isLoading:false,
payment: array_payment,
sum_payment: sum_payment,
all_payment: all_payment_data
})
}
})
}
//this.state.selected_room=''
//this.state.selected_project=''
getRoomUser()
.then(res => {
if(res.ok){
this.setState({
room_list: res.data.data,
selected_room: res.data.data && res.data.data.length > 0 && res.data.data[0].rooms_id ? res.data.data[0].rooms_id : '',
selected_project: res.data.data && res.data.data.length > 0 && res.data.data[0].project_name ? res.data.data[0].project_name : '',
}, () => {
this.getServicesListByType(2)
})
}
})
};
switchSelected(typeName){
if(typeName == 'repair'){
this.setState({
isSelectReapair: true,
isSelectOther: false
})
this.getServicesListByType(2)
}else{
this.setState({
isSelectReapair: false,
isSelectOther: true
})
this.getServicesListByType(1)
if(typeName == 'repair' && this.state.isSelectOther){
Alert.alert(null, 'คุณต้องการเปลี่ยนไปเลือกใช้บริการแจ้งซ่อมหรือไม่ ?', [
{text: t('cancel'), style: 'cancel'},
{text: t('ok'),
onPress: () => {
this.setState({
isSelectRepair: true,
isSelectOther: false,
selectServiceId: [],
selectService: [],
}, () => {
this.getServicesListByType(2)
})}
}
])
}else if(typeName == 'other' && this.state.isSelectRepair){
Alert.alert(null, 'คุณต้องการเปลี่ยนไปเลือกบริการอื่นๆ หรือไม่ ?', [
{text: t('cancel'), style: 'cancel'},
{text: t('ok'),
onPress: () => {
this.setState({
isSelectRepair: false,
isSelectOther: true,
selectServiceId: [],
selectService: []
}, () => {
this.getServicesListByType(1)
})
}
}
])
}
}
getServicesListByType(id){
this.setState({
isLoading: true
})
getUserProfile()
.then(res => {
if(res.ok){
//alert(res.data.user.project_name)
this.setState({
// isLoading: false,
user: res.data.user,
room: res.data.room,
project_name: res.data.user.project_name,
})
console.log('res.data.user.project_name:')
console.log(res.data.user.project_name)
getServicesType(id)
.then(res => {
this.state.customer_project_name = this.state.project_name
//alert(this.state.project_name.slice(0,-4))
//alert(this.state.project_name.normalize())
//this.state.service_data = res.data.data
console.log('res.data.data:')
console.log(res.data.data)
this.state.service_data = res.data.data.filter(obj => {
return obj.project_code === this.state.selected_project
})
console.log('this.state.service_data:')
console.log(this.state.service_data)
/*this.state.service_data = this.state.service_data.filter(l => {
return l.project_code.match(
this.state.selected_project
)
})*/
this.setState({
repair_list: this.state.service_data,
isLoading: false,
selectService: this.state.service_data[0],
selected_project: this.state.service_data[0].project_name,
},() => {
this.state.repair_list.map(() => {
this.state.indexItem.push(false)
})
})
})
}else{
this.setState({
isLoading: false
})
let services = [];
getServicesType(id)
.then(res => {
if(res.ok){
if(this.state.selected_project !== ''){
services = res.data.data.filter(obj => {return obj.project_name == this.state.selected_project})
}
})
}
this.setState({
repair_list : services
})
})
}
sendRepairService(){
//alert(this.state.selected_room)
//alert(this.state.selected_project)
console.log('date:')
console.log('time:')
let params = {
date: moment().format('YYYY-MM-DD'),
time: moment().format('HH:MM:SS'),
repairs:[
{
name:this.state.selectService.name,
services_id: this.state.selectService.id,
service_fee: this.state.selectService.service_fee,
room: this.state.selected_room,
project: this.state.selected_project,
}
],
service_fee: this.state.selectService.service_fee
repairs: this.state.selectService,
rooms: this.state.room_list.filter(room => {return room.rooms_id === this.state.selected_room} )
// service_fee: this.state.selectService.service_fee
}
console.log('params >> ', params)
this.props.navigation.navigate('RepairConfirm',{repair: params})
}
setCheckIndex(index){
let indexBool = this.state.indexItem.slice(); //creates the clone of the state
indexBool[index] = !this.state.indexItem[index]
this.setState({
indexItem: indexBool
})
setCheckIndex(item){
let indexSelected = this.state.selectServiceId.indexOf(item.id);
if(indexSelected > -1){
this.state.selectServiceId.splice(indexSelected, 1);
this.state.selectService.splice(indexSelected, 1);
}else {
this.state.selectServiceId.push(item.id)
this.state.selectService.push(item)
}
this.forceUpdate();
}
_renderContent = (item,index) => {
return <TouchableOpacity style={{borderBottomWidth: 2,borderColor:'#F4F4F4',backgroundColor:'white'}}
onPress={() => {
// this.setCheckIndex(index)
this.setState({
selectServiceIndex: index,
selectService: item,
selected_project: item.project_name
})
this.setCheckIndex(item)
}}>
<View style={{height: 65,backgroundColor:'white',paddingLeft:16,flexDirection:'row',justifyContent:'space-between'}}>
<View style={{justifyContent:'center'}}>
@ -295,8 +161,7 @@ export default class RepairService extends Component {
<Text style={{color:Color.green_title,fontSize:12}}>าบรการขนต {item.service_fee} {t('baht')}</Text>
</View>
{
this.state.repair_list != null && this.state.repair_list.length > 0 &&
this.state.repair_list[this.state.selectServiceIndex].id == item.id &&
this.state.selectServiceId.indexOf(item.id) > -1 &&
<View style={{width: 64,justifyContent:'center',alignItems:'center'}}>
<Image source={require('../../../assets/images/check.png')} style={{width:32, height:32}}/>
</View>
@ -305,71 +170,22 @@ export default class RepairService extends Component {
</TouchableOpacity>
}
getDueDate (date) {
let d = moment(date).format('D')
let m = moment(date).format('MM')
let y = parseInt(moment(date).format('Y')) + 543
let new_month = 'ม.ค.';
let new_date = d + ' ' + new_month + ' ' + y;
switch (m) {
case '01':
new_month = 'ม.ค.';
break;
case '02':
new_month = 'ก.พ.';
break;
case '03':
new_month = 'มี.ค.';
break;
case '04':
new_month = 'เม.ย.';
break;
case '05':
new_month = 'พ.ค.';
break;
case '06':
new_month = 'มิ.ย.';
break;
case '07':
new_month = 'ก.ค.';
break;
case '08':
new_month = 'ส.ค.';
break;
case '09':
new_month = 'ก.ย.';
break;
case '10':
new_month = 'ต.ค.';
break;
case '11':
new_month = 'พ.ย.';
break;
case '12':
new_month = 'ธ.ค.';
break;
default:
new_month = 'ม.ค.';
break;
}
new_date = d + ' ' + new_month + ' ' + y;
return new_date;
}
renderNativeItemImages = (item) => {
return <View style={{width: width, alignItems: 'center', paddingTop: 10, paddingBottom: 40,height: 177,}}>
<View style={{width: '60%', height: '100%', backgroundColor: '#06ADB8', borderRadius: 5 }}>
<LinearGradient colors={['#4BAF3B', '#0E5E29']} style={{ flex:1, borderRadius: 5, height: 120,paddingBottom:10, justifyContent:'space-between'}}>
<View style={{ padding: 16,paddingBottom: 5,paddingTop:10 , borderRadius: 5}}>
<Text style={{ color: 'white', fontSize: 18 }}>{item.room && item.room.name}</Text>
<Text style={{ color: 'rgba(255, 255, 255, 0.65)', fontSize: 14 }}>{item.project && item.project.name}</Text>
</View>
<View style={{height:24,backgroundColor: '#FF2D55',justifyContent:'center',paddingLeft:16}}>
<Text style={{ fontSize: 12, color: 'white'}}>การแจงใชบรการ</Text>
</View>
</LinearGradient>
<View style={{width: '65%', height: '100%', backgroundColor: '#06ADB8', borderRadius: 5 }}>
<LinearGradient colors={['#4BAF3B', '#0e5e29']} style={{ flex:1, borderRadius: 5, height: 120,paddingBottom:10, justifyContent:'space-between'}}>
<View style={{ padding: 16,paddingBottom: 5,paddingTop:10 , borderRadius: 5}}>
<Text style={{ color: 'white', fontSize: 18 }}>{t('room')} {item.room_no}</Text>
<Text style={{ color: 'rgba(255, 255, 255, 0.65)', fontSize: 14 }}>{t('project') + item.project_name}</Text>
</View>
<View style={{height:24,backgroundColor: '#FF2D55',justifyContent:'center',alignItems:'center'}}>
<Text style={{ fontSize: 12, color: 'white'}}>การแจงใชบรการ {this.state.selectServiceId.length} รายการ</Text>
</View>
</LinearGradient>
</View>
</View>
</View>
}
_onCarouselScroll(e) {
const scrollX = e.nativeEvent.contentOffset.x
@ -382,167 +198,94 @@ export default class RepairService extends Component {
_keyExtractorContent = (item, index) => 'repair_content_'+index
getListViewItem = (item) => {
console.log('this.state.payment:')
console.log(this.state.payment)
console.log('this.state.sum_payment:')
console.log(this.state.sum_payment)
let selected_room_data = this.state.sum_payment.filter(obj => {
return obj.room === item
})
console.log('selected_room_data[0].project:')
console.log(selected_room_data[0].project)
//this.payment_room_period[''].project_code*/
this.state.selected_room=item
this.state.selected_project=selected_room_data[0].project
console.log("selected_room_data[0]:")
console.log(selected_room_data[0])
//Alert.alert(this.state.selected_project)
this.switchSelected('repair')
this.props.navigation.navigate('RepairService',
{user:this.state.user, selected_room:this.state.selected_room,selected_project:this.state.selected_project})
}
_onRefresh = () => {
this.setState({
refreshing: true, loadPage: 1, loadMore: false
}, () => {
//this.initData()
//alert('refresh')
})
}
render() {
let dataTest = ['']
console.log('room_number_array:')
console.log(this.state.room_number_array)
return (
<ImageBackground source={require('../../../assets/images/tree2.png')} style={{width: '100%', height: '100%', backgroundColor:'#EEFFD7'}}>
<ScrollView
contentContainerStyle={styles.contentContainer}
// refreshControl={
// <RefreshControl
// refreshing={this.state.refreshing}
// onRefresh={this._onRefresh}
// />
// }
>
<View style={{ alignItems: 'center' }}>
<ImageBackground source={require('../../../assets/images/tree2.png')} style={{width: '100%', flex: 1, backgroundColor:'#EEFFD7'}}>
<View>
<FlatList
data={this.state.room_list}
renderItem={({ item }) => this.renderNativeItemImages(item)}
horizontal={true}
onScroll={this._onCarouselScroll}
pagingEnabled={true}
extraData={this.state}
keyExtractor={this._keyExtractor}
showsHorizontalScrollIndicator={false}
/>
<View style={{ position: 'absolute', bottom: 10, width: '100%', justifyContent: 'center', flexDirection: 'row' }}>
{this.state.room_list.map((item, i) => <View key={'sum_payment_'+i} style={[{ width: 10, height: 10, borderRadius: 5, backgroundColor: this.state.activePage == i ? '#269A21' : 'rgba(124, 187, 51, 0.3)', marginHorizontal: 4 }]}></View>)}
</View>
data={this.state.room_list}
renderItem={({ item }) => this.renderNativeItemImages(item)}
horizontal={true}
onScroll={this._onCarouselScroll}
pagingEnabled={true}
extraData={this.state}
keyExtractor={this._keyExtractor}
// onScrollEndDrag={this.roomFilter(this.state.activePage)}
/>
<View style={{ position: 'absolute', bottom: 10, width: '100%', justifyContent: 'center', flexDirection: 'row' }}>
{ this.state.room_list?.length > 0 && this.state.room_list.map((item, i) => <View key={'sum_repair'+i} style={[{ width: 10, height: 10, borderRadius: 5, backgroundColor: this.state.activePage == i ? '#269A21' : 'rgba(124, 187, 51, 0.3)', marginHorizontal: 4 }]}></View>) }
</View>
{ this.state.selected_room !== ''?
<View style={{alignItems:'center'}}>
<Text style={{ fontSize: 14, marginTop: 5, color: '#00420A' }}>{t('place_choose_service')}</Text>
<View style={{ alignItems: 'center', marginTop: 12, flexDirection: 'row', marginBottom: 20 }}>
<Button style={[styles.button_style_repair,{backgroundColor:this.state.isSelectReapair ? btnActiveColor : btnUnActiveColor,borderTopRightRadius:0,borderBottomRightRadius:0}]}
onPress={() => {this.switchSelected('repair')}}>
<Text style={locale() == "my" ? { color: 'white', fontSize: 6, color: this.state.isSelectReapair ? '#FFFFFF' : '#000000' } : { color: 'white', fontSize: 14, color: this.state.isSelectReapair ? '#FFFFFF' : '#000000' }}>{t('request_repair')}</Text>
</Button>
<Button style={[styles.button_style_other,{backgroundColor:this.state.isSelectOther ? btnActiveColor : btnUnActiveColor,borderTopLeftRadius:0,borderBottomLeftRadius:0}]}
onPress={() => {this.switchSelected('other')}}>
<Text style={locale() == "my" ? { color: 'black', fontSize: 12, color: this.state.isSelectOther ? '#FFFFFF' : '#000000' }: { color: 'black', fontSize: 14, color: this.state.isSelectOther ? '#FFFFFF' : '#000000' }}>{t('other_service')}</Text>
</Button>
</View>
</View>
:
<View style={{alignItems:'center'}}>
<Text style={{ fontSize: 14, marginTop: 5, marginBottom: 10, color: '#00420A' }}>กรณาเลอกหองทองการแจ</Text>
</View>
}
<View style={{}}>
{ !this.state.room_number_array?
<Text>ไมรายการหองพ</Text>
:
this.state.selected_room == ''?
<FlatList
style={{backgroundColor:'white'}}
data={this.state.room_number_array}
renderItem={({ item }) => (
<View onPress={this.getListViewItem.bind(this, item)} style={{ margin: 0,padding:5,borderRadius:5,backgroundColor:'white', borderBottomColor:'black',borderBottomWidth: 0.5}}>
<Text style={{ margin: 5, left: 5, fontSize: 14,}}>
อง { item }
</Text>
</View>
)}
ListEmptyComponent={() => (
<View style={{height:64,margin:16,alignItems:'center',justifyContent:'center',backgroundColor:'white',borderRadius:5}}>
<Text style={{color:'black'}}>ไมรายการหองพ</Text>
</View>
)}
/>
:
<FlatList
style={{backgroundColor:'white'}}
data={this.state.repair_list}
renderItem={({ item, index }) => this._renderContent(item,index)}
extraData={this.state}
keyExtractor={this._keyExtractorContent}
ListEmptyComponent={() => (
<View style={{height:64,margin:16,alignItems:'center',justifyContent:'center',backgroundColor:'white',borderRadius:5}}>
<Text style={{color:'black'}}>ไมรายการของบรการอนๆ</Text>
</View>
)}
/>
}
</View>
</ScrollView>
<View style={{}}>
{this.state.selected_room !== '' ?
<TouchableOpacity style={{
backgroundColor: Color.blue,
height: 40,
margin: 16,
borderRadius: 5,
justifyContent: 'center',
alignItems: 'center',
}}
onPress={() => {
this.sendRepairService()
// this.props.navigation.navigate('RepairConfirm')
}}>
<Text style={{color: 'white'}}>{t('call_for_service')}</Text>
</TouchableOpacity>
:
<Text></Text>
}
</View>
{
this.state.selected_room !== '' ?
<View style={{ alignItems: 'center'}}>
<Text style={{ fontSize: 14, marginTop: 5, color: '#00420A' }}>{t('place_choose_service')}</Text>
<View style={{ alignItems: 'center', marginTop: 12, flexDirection: 'row', marginBottom: 20 }}>
<Button style={[styles.button_style_repair,{backgroundColor:this.state.isSelectRepair ? btnActiveColor : btnUnActiveColor,borderTopRightRadius:0,borderBottomRightRadius:0}]}
onPress={() => {this.switchSelected('repair')}}>
<Text style={locale() === "my" ? { fontSize: 6, color: this.state.isSelectRepair ? '#FFFFFF' : '#000000' } :
locale() === "en" ? { fontSize: 11, color: this.state.isSelectRepair ? '#FFFFFF' : '#000000' } :
{ fontSize: 14, color: this.state.isSelectRepair ? '#FFFFFF' : '#000000' }}>{t('request_repair')}</Text>
</Button>
<Button style={[styles.button_style_other,{backgroundColor:this.state.isSelectOther ? btnActiveColor : btnUnActiveColor,borderTopLeftRadius:0,borderBottomLeftRadius:0}]}
onPress={() => {this.switchSelected('other')}}>
<Text style={locale() === "my" ? { fontSize: 12, color: this.state.isSelectOther ? '#FFFFFF' : '#000000' } :
locale() === "en" ? { fontSize: 11, color: this.state.isSelectOther ? '#FFFFFF' : '#000000' } :
{ fontSize: 13, color: this.state.isSelectOther ? '#FFFFFF' : '#000000' }}>{t('other_service')}</Text>
</Button>
</View>
</View>
:
<View style={{alignItems:'center'}}>
<Text style={{ fontSize: 14, marginTop: 5, marginBottom: 10, color: '#00420A' }}>ไมพบขอมลหองพ</Text>
</View>
}
{
this.state.selected_room !== '' ?
<View style={{ flex: 1 }}>
<View style={{ flex: 0.8 }}>
<ScrollView
contentContainerStyle={styles.contentContainer}
>
<FlatList
style={{backgroundColor:'white'}}
data={this.state.repair_list}
renderItem={({ item, index }) => this._renderContent(item,index)}
extraData={this.state}
keyExtractor={this._keyExtractorContent}
ListEmptyComponent={() => (
<View style={{height:64,margin:16,alignItems:'center',justifyContent:'center',backgroundColor:'white',borderRadius:5}}>
<Text style={{color:'black'}}>{this.state.isSelectRepair ? 'ไม่มีรายการของแจ้งซ่อม' : 'ไม่มีรายการของบริการอื่นๆ'}</Text>
</View>
)}
/>
</ScrollView>
</View>
<View style={{ flex: 0.2, backgroundColor: 'white' }}>
<TouchableOpacity style={[{
height: 40,
margin: 16,
borderRadius: 5,
justifyContent: 'center',
alignItems: 'center',
}, this.state.selectServiceId.length === 0 ? {backgroundColor: Color.gray_half} : {backgroundColor: Color.blue}]}
onPress={() => {
this.sendRepairService()
}}
disabled={this.state.selectServiceId.length === 0}
>
<Text style={{color: 'white'}}>{t('call_for_service')}</Text>
</TouchableOpacity>
</View>
</View>
:
<View></View>
}
<IndicatorLoading loadingVisible={this.state.isLoading}/>
</ImageBackground>
@ -554,6 +297,7 @@ const styles = StyleSheet.create({
contentContainer: {
paddingVertical: 0,
flexGrow: 1,
width: '100%'
},
button_style_repair: {
height: 32,
@ -567,5 +311,5 @@ const styles = StyleSheet.create({
borderRadius: 5,
width: 127,
justifyContent: 'center',
},
}
})

View File

@ -1,14 +1,14 @@
import React, { Component } from 'react'
import {
TouchableOpacity,
TextInput,
StyleSheet,
View,
ScrollView,
Alert,
Image,
Slider,
ImageBackground
TouchableOpacity,
TextInput,
StyleSheet,
View,
ScrollView,
Alert,
Image,
Slider,
ImageBackground, FlatList, Modal
} from 'react-native'
import Icon from "../../components/Icon";
import { CustomButton } from '../../components/CustomButton';
@ -19,114 +19,245 @@ import LinearGradient from 'react-native-linear-gradient';
import GetWidthHeightDevice from '../../components/GetWidthHeightDevice'
import Color from '../../../src/color';
import { t } from 'src/utils/i18n'
import {getRepairById, postEvaluateRepair} from "../../api/UserApi";
import IndicatorLoading from '../../components/IndicatorLoading';
import { StackActions, NavigationActions } from 'react-navigation';
import moment from 'moment';
function ConfirmEvaluate({isVisible, onPress, onCancel, points}) {
return <Modal visible={isVisible} transparent={true} animationType="none" key="alert-warning">
<View style={styles.AlertWarningContainer}>
<View style={styles.AlertWarning}>
<View style={{width: '100%'}}>
<Text style={{fontSize: 18, color: '#00420A', marginBottom: 10}}>นยนการประเมนใหคะแนน</Text>
<Text style={{fontSize: 14, color: '#4F4F4F'}}>ณตองการจะใหคะแนน <Text style={{fontFamily: 'Prompt-Bold' }}>"{points} คะแนน"</Text> ? <Text style={{fontFamily: 'Prompt-Bold' }}>""</Text> </Text>
<View style={{flexDirection: 'row', justifyContent: 'flex-end', width: '100%', marginTop: 10}}>
<TouchableOpacity onPress={onCancel} style={{marginRight: 20}}>
<Text style={[{color: '#8A8A8F', fontSize: 16, fontWeight: '800'}]}>{t('cancel')}</Text>
</TouchableOpacity>
<TouchableOpacity onPress={onPress}>
<Text style={[{color: '#269A21', fontSize: 16, fontWeight: '800'}]}>นย</Text>
</TouchableOpacity>
</View>
</View>
</View>
</View>
</Modal>
}
export default class RepairServiceDetail extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
value: 2,
point_selected: 0
point_selected: 0,
rating_point: [0,0,0,0,0],
visibleConfirm: false
}
this.sendEvaluate = this.sendEvaluate.bind(this)
}
sendEvaluate(){
Alert.alert(null, 'ส่งผลประเมินสำเร็จ')
componentDidMount() {
const { navigation } = this.props
const id = navigation.getParam('id', 'NO-DATA')
this.getRepairData(id)
};
visibleConfirm = () => {
this.setState({
visibleConfirm: !this.state.visibleConfirm
})
}
changeSlide(value) {
getRepairData(id){
this.setState({
value: parseFloat(value),
point_selected: value+1
});
isLoading: true
}, () => {
getRepairById(id)
.then(res => {
console.log('repair data -------------> ',res.data.data)
this.setState({
repair: res.data.data,
order_list: res.data.data.services,
isLoading: false
})
this.props.navigation.setParams({statusRepair: res.data.data.status})
})
})
}
sendEvaluate(){
let params = {
id: this.state.repair.id,
point: this.state.point_selected
}
if(this.state.point_selected === 0){
Alert.alert('กรุณาเลือกระดับความพึงพอใจ', null, [{text: t('ok')}])
return
}
this.setState({
//isLoading: true,
visibleConfirm: false
}, () => {
postEvaluateRepair(params)
.then(res => {
if(res.data.success){
this.setState({
isLoading: false,
}, () => {
setTimeout(() => Alert.alert('ให้คะแนนสำเร็จ', null, [
{
text: t('ok'),
onPress: () => {
//this.getRepairData(this.state.repair.id)
this.props.navigation.dispatch(StackActions.reset({
index: 3,
actions: [
NavigationActions.navigate({
routeName: 'BottomTab',
action: NavigationActions.navigate({ routeName: 'ServiceScreen' })
}),
NavigationActions.navigate({ routeName: 'RepairService' }),
NavigationActions.navigate({ routeName: 'RepairHistory' }),
NavigationActions.navigate({ routeName: 'RepairHistoryDetail', params: { repair_id: this.state.repair.id } })
]
}))
}
}
]), 500)
})
}else {
this.setState({
isLoading: false
}, () => {
Alert.alert('ให้คะแนนไม่สำเร็จ กรุณาลองใหม่อีกครั้งภายหลัง', null, [{text: t('ok')}])
})
}
})
})
}
setRating = (index) => {
let rating_star = [0, 0, 0, 0, 0];
for(let i=0; i<=index; i++){
rating_star[i] = 1;
}
this.setState({
rating_point: rating_star,
point_selected: index + 1
})
}
renderItem = (item) => {
return <View style={{ flexDirection: 'row', marginVertical:3, justifyContent:'space-between'}}>
<Text style={{ fontSize: 14, color: '#000000' }}>{item.name}</Text>
<Text style={{ textAlign: 'right', fontSize: 14, color: '#7CBB33' }}>{item.service_fee} {t('baht')}</Text>
</View>
}
render() {
const {value} = this.state;
const {value, isLoading} = this.state;
return (
<ImageBackground source={require('../../../assets/images/tree2.png')} style={{width: '100%', height: '100%', backgroundColor:'#EEFFD7'}}>
<View style={[styles.containerHeadbar,]}>
<ImageBackground source={require('../../../assets/images/tree2.png')} style={{width: '100%', flex: 1, backgroundColor:'#EEFFD7'}}>
<View style={[styles.containerHeadbar]}>
<View>
<LinearGradient colors={['#4BAF3B', '#0E5E29']} style={{width: null,height: null,resizeMode: 'cover', borderRadius:5}}>
<View style={{padding:16,paddingVertical: 10}}>
<View style={{flexDirection:'row'}}>
<Text style={{ flex:1,fontSize: 18, color: '#FFFFFF'}}>{t('room')} A1-1</Text>
<Text style={{ fontSize: 18, color: '#FFFFFF'}}>#123456</Text>
<LinearGradient colors={['#4BAF3B', '#0E5E29']} style={{width: null,height: null,resizeMode: 'cover', borderRadius:5}}>
<View style={{padding:16,paddingVertical: 10}}>
<View style={{flexDirection:'row'}}>
<Text style={{ flex:1,fontSize: 18, color: '#FFFFFF'}}>{t('room')} {this.state.repair && this.state.repair.room_no}</Text>
<Text style={{ fontSize: 18, color: '#FFFFFF'}}>#{this.state.repair && this.state.repair.id}</Text>
</View>
<Text style={{ fontSize: 14, color: 'rgba(255, 255, 255, 0.65)'}}>{this.state.repair && this.state.repair.project_name ? t('project') + this.state.repair.project_name : ''}</Text>
</View>
<Text style={{ fontSize: 14, color: '#FFFFFF'}}>โครงการเจรญสนธาน (CNE)</Text>
</View>
</LinearGradient>
<View style={{backgroundColor: '#FFFFFF',padding:16}}>
<Text style={{ fontSize: 14, color: Color.green_title}}>{t('make_appoint')}</Text>
<View style={{ flexDirection: 'row',paddingVertical:5}}>
<Text style={{ fontSize: 14, color: Color.gray_half}}>{t('date')}</Text>
<Text style={{ fontSize: 14, color: '#000000'}}> 01-01-2019 </Text>
<Text style={{ fontSize: 14, color: '#00000080'}}> เวลา </Text>
<Text style={{ fontSize: 14, color: '#000000'}}> 12:00-13:00 </Text>
</View>
<View style={{ flexDirection: 'row',alignItems:'center'}}>
<Text style={{ fontSize: 14, color: '#00000080'}}>{t('status')}</Text>
<Image style={{marginHorizontal:10}} source={require('../../../assets/images/Ellipse2.png')} defaultSource={require('../../../assets/images/Ellipse2.png')} />
<Text style={{ fontSize: 14, color: Color.green_title}}>{t('complete')}</Text>
</View>
<View style={[styles.hairline]}></View>
</LinearGradient>
</View>
<View style={{backgroundColor: '#FFFFFF',padding:16, flex: 1}}>
<View>
<Text style={{ fontSize: 14, color: Color.green_title}}>{t('information')}</Text>
</View>
<View style={styles.info_order_view}>
<Text style={{ fontSize: 14, color: '#000000' }}>ำร</Text>
<Text style={{ textAlign: 'right', fontSize: 14, color: '#7CBB33'}}>าบรการขนต 200 {t('baht')}</Text>
</View>
<View style={styles.info_order_view}>
<Text style={{ fontSize: 14, color: '#000000' }}>เปลยนกอกน</Text>
<Text style={{ textAlign: 'right', fontSize: 14, color: '#7CBB33'}}>าบรการขนต 150 {t('baht')}</Text>
</View>
<View style={styles.info_order_view}>
<Text style={{ fontSize: 14, color: '#000000' }}>ไฟฟาชอต</Text>
<Text style={{ textAlign: 'right', fontSize: 14, color: '#7CBB33'}}>าบรการขนต 500 {t('baht')}</Text>
<Text style={{ fontSize: 14, color: Color.green_title}}>{t('make_appoint')}</Text>
<View style={{ flexDirection: 'row',paddingVertical:5}}>
<Text style={{ fontSize: 14, color: Color.gray_half}}>{t('date')}</Text>
<Text style={{ fontSize: 14, color: '#000000'}}> {this.state.repair && moment(this.state.repair.date, 'YYYY-MM-DD').format('DD-MM-YYYY')}</Text>
<Text style={{ fontSize: 14, color: '#00000080'}}> เวลา</Text>
<Text style={{ fontSize: 14, color: '#000000'}}> {this.state.repair && this.state.repair.time.slice(0, -3)}</Text>
</View>
<View style={{ flexDirection: 'row',alignItems:'center'}}>
<Text style={{ fontSize: 14, color: '#00000080'}}>{t('status')}</Text>
<Image style={{marginHorizontal:10}} source={require('../../../assets/images/Ellipse2.png')} defaultSource={require('../../../assets/images/Ellipse2.png')} />
<Text style={{ fontSize: 14, color: Color.green_title}}>อมสำเร</Text>
</View>
</View>
<View style={[styles.hairline]}></View>
<View style={{ flex: 1 }}>
<View>
<Text style={{ fontSize: 14, color: Color.green_title}}>{t('information')}</Text>
</View>
<ScrollView>
<FlatList
data={this.state.order_list}
renderItem={({ item }) => this.renderItem(item)}
pagingEnabled={true}
extraData={this.state}
keyExtractor={this._keyExtractor}
/>
</ScrollView>
</View>
<View style={[styles.hairline, {marginVertical: 5}]}></View>
<View style={styles.info_order_view}>
<Text style={{ fontSize: 14, color: Color.green_title }} >{t('estimate_charge')}</Text>
<Text style={{ textAlign: 'right', fontSize: 14, color: '#7CBB33'}} >าบรการขนต 850 {t('baht')}</Text>
<Text style={{ textAlign: 'right', fontSize: 14, color: '#7CBB33'}} >{this.state.repair && this.state.repair.total} {t('baht')}</Text>
</View>
</View>
<View style={{width: '100%', marginTop:10,padding:16, backgroundColor: '#FFFFFF',borderRadius:5, height:100}}>
{
!isLoading && <View style={{width: '100%', marginTop:10,padding:16, backgroundColor: '#FFFFFF',borderRadius:5}}>
<View>
<Text style={{ fontSize: 14, color: Color.green_title}} >{t('rating')}</Text>
<View style={{flexDirection:'row',justifyContent:'space-around',marginTop:10}}>
<Text style={{ fontSize: 12, color: '#000000'}} >1</Text>
<Text style={{ fontSize: 12, color: '#000000'}} >2</Text>
<Text style={{ fontSize: 12, color: '#000000'}} >3</Text>
<Text style={{ fontSize: 12, color: '#000000'}} >4</Text>
<Text style={{ fontSize: 12, color: '#000000'}} >5</Text>
<Text style={{ fontSize: 14, color: Color.green_title, textAlign: 'center'}} >{t('rating')}</Text>
<View style={{flexDirection: 'row', marginTop: 15, justifyContent: 'center'}}>
{
this.state.rating_point.map((point, index) =>
point === 0 ?
<View style={{alignItems: 'center', marginRight: index !== this.state.rating_point.length - 1 ? 15 : 0}}>
<Text style={{ fontSize: 14, color: '#000000', marginBottom: 10}} >{index + 1}</Text>
<TouchableOpacity onPress={() => this.state.repair.point === 0 || this.state.repair.points === null ? this.setRating(index) : {}} >
<Image source={require('../../../assets/images/star_grey.png')} style={{width: 40, height: 40}}/>
</TouchableOpacity>
</View>
: <View style={{alignItems: 'center', marginRight: index !== this.state.rating_point.length - 1 ? 15 : 0}}>
<Text style={{ fontSize: 14, color: '#000000', marginBottom: 10}} >{index + 1}</Text>
<TouchableOpacity onPress={() => this.state.repair.point === 0 || this.state.repair.points === null ? this.setRating(index) : {}} >
<Image source={require('../../../assets/images/star_yellow.png')} style={{width: 40, height: 40}}/>
</TouchableOpacity>
</View>
)
}
</View>
<Slider
style={{ width: '90%', alignSelf:'center',}}
step={1}
maximumTrackTintColor='#EAEAF4'
minimumTrackTintColor='#269A21'
maximumValue={4}
onValueChange={this.changeSlide.bind(this)}
value={value}
/>
</View>
</View>
}
{
!isLoading && this.state.repair && (this.state.repair.points === null || this.state.repair.points === 0) &&
<CustomButton style={[styles.button_style, {backgroundColor: this.state.point_selected === 0 ? '#C8C7CC' : '#145EB3' }, {marginTop: 16}]}
onPress={() => {this.visibleConfirm()}}
disabled={this.state.point_selected === 0}
title={'ส่งประเมิน'} />
}
</View>
<CustomButton style={[styles.button_style]}
onPress={() => {
Alert.alert(
'แจ้งเตือน !',
'ยืนยันการส่งข้อมูล ?',
[
{ text: 'Cancel', style: 'cancel' },
{ text: 'OK', onPress: () => this.sendEvaluate() },
],
{ cancelable: false }
)
}}
title={'ส่งประเมิน'} />
</View>
<ConfirmEvaluate
isVisible={this.state.visibleConfirm}
onPress={() => this.sendEvaluate()}
onCancel={() => this.setState({visibleConfirm: false})}
points={this.state.point_selected}
/>
<IndicatorLoading loadingVisible={this.state.isLoading}/>
</ImageBackground>
)
}
@ -138,14 +269,14 @@ const styles = {
containerHeadbar: {
flex: 1,
flexDirection: 'column',
height: GetWidthHeightDevice.HeightContainer,
//height: GetWidthHeightDevice.HeightContainer,
padding:16,
fontStyle: "normal",
justifyContent:'space-between'
},
hairline: {
marginVertical: 17,
backgroundColor: '#A2A2A2',
backgroundColor: '#EAEAF4',
height: 1,
width: '100%'
},
@ -162,5 +293,25 @@ const styles = {
paddingVertical:5,
flexDirection: 'row',
justifyContent:'space-between'
},
AlertWarningContainer: {
backgroundColor: 'rgba(0,0,0,0.6)',
justifyContent: 'center',
alignItems: 'center',
position: 'absolute',
width: '100%',
height: '100%',
flex: 1
},
AlertWarning: {
backgroundColor: 'white',
justifyContent: 'center',
alignItems: 'center',
borderRadius: 5,
marginHorizontal: 25,
paddingVertical: 20,
paddingHorizontal: 20,
maxWidth: 300,
width: '100%'
}
}

View File

@ -51,17 +51,10 @@ export default class RepairSuccess extends Component {
const { navigation } = this.props
const repair_state = navigation.getParam('repair', 'NO-DATA')
const room_state = navigation.getParam('room', 'NO-DATA')
const project_state = navigation.getParam('project', 'NO-DATA')
this.setState({
// repair: this.props.navigation.getParam('repair','NO-DATA')
repair: repair_state,
room: room_state,
project: project_state,
})
console.log('repair_state:')
console.log(repair_state)
@ -80,7 +73,7 @@ export default class RepairSuccess extends Component {
convertStatus(statusName){
switch(statusName){
case 'Pending':
return t('pending')
return t('request_repair')
case 'InProgress':
return 'ซ่อมแซม'
case 'NewAppointment':
@ -97,7 +90,7 @@ export default class RepairSuccess extends Component {
convertColorStatus(statusName){
switch(statusName){
case 'Pending':
return '#C4C4C4'
return '#FF9500'
case 'InProgress':
return '#FFCC00'
case 'NewAppointment':
@ -113,8 +106,71 @@ export default class RepairSuccess extends Component {
render() {
return (
<ImageBackground source={require('../../../assets/images/tree2.png')} style={{width: '100%', height: '100%', backgroundColor:'#EEFFD7'}}>
<View style={{padding:16}}>
<ImageBackground source={require('../../../assets/images/tree2.png')} style={{width: '100%', flex: 1, backgroundColor:'#EEFFD7'}}>
<View style={{alignItems:'center', paddingHorizontal: 16, marginTop: 16}}>
<View style={{flexDirection: 'row',justifyContent: 'center',}}>
<Image style={{height: 64, width: 64,}} source={require('../../../assets/images/GroupCheck.png')} defaultSource={require('../../../assets/images/GroupCheck.png')} />
</View>
<Text style={{ fontSize: 18, color: Color.green_title,marginVertical: 16,}}>{t('request_sent')}</Text>
</View>
<View style={{ paddingHorizontal: 16, flex: 1 }}>
<LinearGradient colors={['#4BAF3B', '#0E5E29']} style={{borderRadius:5, padding:16}}>
<View style={{flexDirection:'row',justifyContent:'space-between'}}>
<Text style={{ fontSize: 18, color: '#FFFFFF'}} >{t('room')} {this.state.repair.room_no}</Text>
<Text style={{ textAlign:'right', fontSize: 18, color: '#FFFFFF', }} >#{this.state.repair.id}</Text>
</View>
<Text style={{ fontSize: 14, color: '#FFFFFF', }}>{this.state.repair.project_name}</Text>
</LinearGradient>
<View style={{backgroundColor: '#FFFFFF',borderRadius:5,padding:16, flex: 1}}>
<View>
<Text style={styles.textTitle}>{t('make_appoint')}</Text>
<View style={{ flexDirection: 'row',}}>
<Text style={{ fontSize: 14, color: 'rgba(0, 0, 0, 0.5)', }}>{t('date')}</Text>
<Text style={{ fontSize: 14, color: '#000000', paddingHorizontal: 10,}}>{ moment(this.state.repair.date).format('DD-MM-YYYY') }</Text>
<Text style={{ fontSize: 14, color: 'rgba(0, 0, 0, 0.5)', }}>เวลา</Text>
<Text style={{ fontSize: 14, color: '#000000', paddingHorizontal: 10,}}>{this.state.repair.time == null ? '' : this.state.repair.time.slice(0,-3) + ' น.' }</Text>
</View>
<View style={{ flexDirection: 'row',alignItems:'center',marginVertical:3}}>
<Text style={{ fontSize: 14, color: 'rgba(0, 0, 0, 0.5)'}}>{t('status')}</Text>
<View style={{backgroundColor: this.convertColorStatus(this.state.repair.status),height: 10,width: 10,borderRadius:5, marginHorizontal:10}}/>
<Text style={{ fontSize: 14, color: this.convertColorStatus(this.state.repair.status)}}>{this.convertStatus(this.state.repair.status)}</Text>
</View>
</View>
<View style={{borderWidth:1,marginVertical:16,borderColor:'silver'}}></View>
<View style={{flex: 1}}>
<Text style={styles.textTitle} >{t('information')}</Text>
<ScrollView>
<FlatList
data={this.state.repair.services}
renderItem={this.renderItem}
pagingEnabled={true}
extraData={this.state}
keyExtractor={this._keyExtractor}
/>
</ScrollView>
</View>
<View style={{borderWidth:1,marginVertical:16,borderColor:'silver'}}></View>
<View style={{ flexDirection:'row',justifyContent:'space-between'}}>
<Text style={{ fontSize: 14, color: Color.green_title }}>{t('estimate_charge')}</Text>
<Text style={{ textAlign: 'right', fontSize: 14, color: '#7CBB33'}}>{this.state.repair.total} {t('baht')}</Text>
</View>
</View>
</View>
<View style={{margin: 16}}>
<CustomButton style={[styles.button_style]}
onPress={() => {this.props.navigation.popToTop()}}
title={t('back_home')} />
</View>
{/*<View style={{padding:16}}>
<View style={{alignItems:'center'}}>
<View style={{flexDirection: 'row',justifyContent: 'center',}}>
<Image style={{height: 64, width: 64,}} source={require('../../../assets/images/GroupCheck.png')} defaultSource={require('../../../assets/images/GroupCheck.png')} />
@ -124,29 +180,29 @@ export default class RepairSuccess extends Component {
<View>
<LinearGradient colors={['#4BAF3B', '#0E5E29']} style={{borderRadius:5, padding:16}}>
<View style={{flexDirection:'row',justifyContent:'space-between'}}>
<Text style={{ fontSize: 18, color: '#FFFFFF'}} >{t('room')} {this.state.room}</Text>
<Text style={{ textAlign:'right', fontSize: 18, color: '#FFFFFF', }} >#{this.state.repair.tag}</Text>
<Text style={{ fontSize: 18, color: '#FFFFFF'}} >{t('room')} {this.state.repair.room_no}</Text>
<Text style={{ textAlign:'right', fontSize: 18, color: '#FFFFFF', }} >#{this.state.repair.id}</Text>
</View>
<Text style={{ fontSize: 14, color: '#FFFFFF', }}>{this.state.repair.project_name}</Text>
</LinearGradient>
<View style={{backgroundColor: '#FFFFFF',borderRadius:5,padding:16}}>
<Text style={styles.textTitle}>{t('make_appoint')}</Text>
<View style={{ flexDirection: 'row',}}>
<Text style={{ fontSize: 14, color: '#C4C4C4', }}>{t('date')}</Text>
<Text style={{ fontSize: 14, color: 'rgba(0, 0, 0, 0.5)', }}>{t('date')}</Text>
<Text style={{ fontSize: 14, color: '#000000', paddingHorizontal: 10,}}>{ moment(this.state.repair.date).format('DD-MM-YYYY') }</Text>
<Text style={{ fontSize: 14, color: '#C4C4C4', }}>เวลา</Text>
<Text style={{ fontSize: 14, color: 'rgba(0, 0, 0, 0.5)', }}>เวลา</Text>
<Text style={{ fontSize: 14, color: '#000000', paddingHorizontal: 10,}}>{this.state.repair.time == null ? '' : this.state.repair.time.slice(0,-3) }</Text>
<Text style={{ fontSize: 14, color: '#000000', paddingHorizontal: 10,}}>{this.state.repair.time == null ? '' : this.state.repair.time.slice(0,-3) + ' น.' }</Text>
</View>
<View style={{ flexDirection: 'row',alignItems:'center',marginVertical:3}}>
<Text style={{ fontSize: 14, color: '#C4C4C4',}}>{t('status')}</Text>
<Text style={{ fontSize: 14, color: 'rgba(0, 0, 0, 0.5)'}}>{t('status')}</Text>
<View style={{backgroundColor: this.convertColorStatus(this.state.repair.status),height: 10,width: 10,borderRadius:5, marginHorizontal:10}}/>
<Text style={{ fontSize: 14, color: this.convertColorStatus(this.state.repair.status),}}>{this.convertStatus(this.state.repair.status)}</Text>
<Text style={{ fontSize: 14, color: this.convertColorStatus(this.state.repair.status)}}>{this.convertStatus(this.state.repair.status)}</Text>
</View>
<View style={{borderWidth:1,marginVertical:16,borderColor:'silver'}}></View>
<Text style={styles.textTitle} >{t('information')}</Text>
@ -169,7 +225,7 @@ export default class RepairSuccess extends Component {
onPress={() => {this.props.navigation.popToTop()}}
title={t('back_home')} />
</View>
</View>
</View>*/}
</ImageBackground>
)
}

View File

@ -51,8 +51,7 @@ export default class RewardDetailScreen extends Component {
}
onMessage({ nativeEvent }) {
const data = nativeEvent.data;
const data = nativeEvent.data
if (data !== undefined && data !== null) {
Linking.openURL(data);
}
@ -65,7 +64,6 @@ export default class RewardDetailScreen extends Component {
width: 60,
color: '#FFFFFF',
borderRadius: 5,
textAlign: 'center',
fontSize: 12
}
@ -75,10 +73,11 @@ export default class RewardDetailScreen extends Component {
const images = [
{
source: {
uri: this.state.product.image_path,
uri: this.state.product.image_url,
}
},
];
// console.log('uri',this.state.product.image_url);
return (
<LinearGradient colors={['#3AA40C', '#2C7C0B']} style={{
flex: 1,
@ -92,6 +91,7 @@ export default class RewardDetailScreen extends Component {
imageIndex={0}
isVisible={this.state.isImageViewVisible}
animationType={'fade'}
onClose={() => {this.setState({isImageViewVisible: false})}}
/>
<TouchableOpacity style={{backgroundColor:'white',borderBottomWidth:1,borderColor:'silver'}} onPress={() => {this.setState({isImageViewVisible: true})}}>
<Image source={{ uri: this.state.product.image_url }} defaultSource={require('../../../assets/images/logo_2.png')} style={{height: 200,}} resizeMode={'contain'}/>
@ -113,7 +113,7 @@ export default class RewardDetailScreen extends Component {
bounces={true}
// dataDetectorTypes={['link', 'phoneNumber']}
originWhitelist={['*']}
source={{ baseUrl: '', html: ` ${this.state.product.style} <div id="content_detail"><meta charset="UTF-8">`+this.state.product.description+'</div>' }}
source={{ baseUrl: '', html: ` ${this.state.product && this.state.product.style ? this.state.product.style : '' } <div id="content_detail"><meta charset="UTF-8"> ${this.state.product && this.state.product.description ? this.state.product.description : ''} </div>` }}
injectedJavaScript={injectScript}
onMessage={this.onMessage}
/>

View File

@ -1,9 +1,9 @@
import React, { Component } from 'react';
import { View, TouchableOpacity } from 'react-native';
import { View, TouchableOpacity, Appearance } from 'react-native';
import Text from '../../components/Text';
import DateTimePicker from "react-native-modal-datetime-picker";
import Icon from 'src/components/Icon'
import { Appearance } from 'react-native-appearance';
// import { Appearance } from 'react-native-appearance';
import { t } from '../../utils/i18n'
const colorScheme = Appearance.getColorScheme();

View File

@ -203,7 +203,7 @@ class RoomDetailScreen extends Component {
originWhitelist={['*']}
source={{
baseUrl: '',
html: `<div id="content_detail"><meta charset="UTF-8">` + this.state.room_detail.detail + '</div>'
html: `<div id="content_detail"><meta charset="UTF-8"> ${this.state.room_detail.detail} </div>`
}}
injectedJavaScript={injectScript}

View File

@ -1,5 +1,5 @@
import React, { Component } from 'react';
import { View, TouchableOpacity, KeyboardAvoidingView, FlatList, StyleSheet, TextInput, Alert , Image } from 'react-native';
import {View, TouchableOpacity, KeyboardAvoidingView, FlatList, StyleSheet, TextInput, Alert, Image, Platform, Keyboard} from 'react-native';
import Text from '../../components/Text';
import moment from "moment";
import Color from '../../../src/color';
@ -7,6 +7,7 @@ import {Button} from "native-base";
import {getConversation, postConversation} from '../../api/UserApi';
import IndicatorLoading from '../../components/IndicatorLoading';
import { t } from '../../utils/i18n';
import ImageView from 'react-native-image-view';
// import 'moment/locale/th';
//moment.locale('th');
@ -16,20 +17,42 @@ export default class QuestionScreen extends Component {
this.state = {
isLoading: false,
message_list:[],
text_input:''
text_input:'',
isSending: false,
keyboardAndroidOffset: 0,
isImageViewVisible: false,
media_url: null
};
this.sendQuestion = this.sendQuestion.bind(this)
this.getMessageList = this.getMessageList.bind(this)
}
componentWillUnmount = () => {
if(this.props && this.props.navigation && this.props.navigation.state && this.props.navigation.state.params && this.props.navigation.state.params.getNotification){
this.props.navigation.state.params.getNotification()
}
}
componentDidMount = () => {
this.props.navigation.setParams({onRefreshMessage: this.getMessageList})
this.getMessageList()
// Keyboard.addListener('keyboardDidShow', this._keyboardDidShow)
};
getMessageList(){
componentWillUnmount() {
if(this.props && this.props.navigation && this.props.navigation.state && this.props.navigation.state.params && this.props.navigation.state.params.getNotification){
this.props.navigation.state.params.getNotification()
}
}
/*_keyboardDidShow = (e) => {
this.setState({
isLoading: true
keyboardAndroidOffset: parseInt(e.endCoordinates.height)
})
};*/
getMessageList(loading = true){
this.setState({
isLoading: loading
})
getConversation()
.then(res => {
@ -43,54 +66,81 @@ export default class QuestionScreen extends Component {
}
this.setState({
isLoading: false
isLoading: false,
})
})
}
sendQuestion(){
this.setState({
isLoading: true
})
let param = {
message: this.state.text_input
}
postConversation(param)
.then(res => {
if(res.ok){
Alert.alert('รับคำถามเรียบร้อย', 'ทางเราได้รับคำถามของคุณแล้ว ขอบคุณค่ะ',[{text: t('ok'), onPress: () => this.getMessageList()}])
this.setState({
text_input: ''
})
}else{
Alert.alert('เกิดข้อผิดพลาด', 'กรุณาลองอีกครั้ง')
}
if(this.state.text_input !== ''){
this.setState({
isLoading: false
// isLoading: true
isSending: true
}, () => {
let param = {
message: this.state.text_input
}
postConversation(param)
.then(res => {
if(res.ok){
// Alert.alert('รับคำถามเรียบร้อย', 'ทางเราได้รับคำถามของคุณแล้ว ขอบคุณค่ะ',[{text: t('ok'), onPress: () => this.getMessageList()}])
this.setState({
text_input: ''
}, () => {
this.getMessageList(false)
let _this = this;
setTimeout(function () {
_this.setState({
isSending: false
})
}, 1000)
})
}else{
Alert.alert('เกิดข้อผิดพลาด', 'กรุณาลองอีกครั้ง')
this.setState({
isSending: false
})
}
console.log('check data ============== ',res);
})
})
console.log('check data ============== ',res);
})
}
}
_keyExtractor = (item, index) => 'nessage_item_'+index;
_renderItem = ({item}) => (
<View style={{padding:16,backgroundColor:item.sender_type == 'admin' ? '#EAEAF4' : '#E1EDD2'}}>
<View style={{flexDirection:'row',justifyContent:'space-between'}}>
<Text style={{fontSize: 14,}}>{item.sender_type == 'admin' ? t('project') : t('me')}</Text>
<Text style={{fontSize: 12,color:'#00000080'}}>{moment(item.created_at).format('DD MMMM YYYY, HH:mmน.')}</Text>
</View>
<Text style={{marginTop:10,fontSize: 14,}}>{item.content}</Text>
{item.media != null ? <Image style={styles.image} source={{uri: item.media.url}} /> : null}
<View style={{padding:16,backgroundColor: item.sender_type == 'admin' ? '#EAEAF4' : '#E1EDD2' }}>
<Text style={{fontSize: 12, color:'#00000080', textAlign: item.sender_type == 'admin' ? 'left' : 'right', marginBottom: 5}}>{moment(item.created_at).format('DD MMMM YYYY, HH:mmน.')}</Text>
<Text style={{fontSize: 14, color:'#00420A', fontWeight: '500' , textAlign: item.sender_type == 'admin' ? 'left' : 'right'}}>{item.sender_type == 'admin' ? t('project') : t('me')}</Text>
<Text style={{marginTop:10,fontSize: 14, textAlign: item.sender_type == 'admin' ? 'left' : 'right'}}>{item.content}</Text>
{
item.media != null ?
<TouchableOpacity onPress={() => {this.setState({isImageViewVisible: true, media_url: item.media.url})}}>
<Image style={styles.image} source={{uri: item.media.url}} />
</TouchableOpacity>
: null
}
</View>
);
render() {
return (
<KeyboardAvoidingView style={{flex:1,backgroundColor:'white'}} behavior={'padding'} ref={(view) => {
this.scrollView = view;
}}>
<KeyboardAvoidingView style={{flex: 1,backgroundColor:'white'}} behavior={Platform.OS == 'ios'? 'padding' : ''}
keyboardVerticalOffset={Platform.OS == 'ios'? 85 : 0}
ref={(view) => {this.scrollView = view;}}
>
<View style={{flex:1,padding:16}}>
<ImageView
images={[{source: {uri: this.state.media_url != null && this.state.media_url ? this.state.media_url : '' }}]}
imageIndex={0}
isVisible={this.state.isImageViewVisible}
animationType={'fade'}
onClose={() => {this.setState({isImageViewVisible: false, media_url: null})}}
/>
<FlatList
ref={c => this._flatlistRef = c}
data={this.state.message_list}
@ -109,7 +159,7 @@ export default class QuestionScreen extends Component {
}}
style={{}}/>
</View>
<View style={{borderTopWidth:1,borderColor:'#00000080'}}>
<View style={{borderTopWidth:1,borderColor:'#00000080', marginBottom: 15}}>
<TextInput
placeholder={t('message')}
style={[styles.textArea, {color: 'rgba(0,0,0,0.5)'}]}
@ -117,7 +167,8 @@ export default class QuestionScreen extends Component {
multiline={true}
numberOfLines={4}
onChangeText={(text) => this.setState({text_input: text})}/>
<Button block style={{backgroundColor: '#145EB3', marginHorizontal: 10, marginVertical: 15}}
<Button block style={{backgroundColor: this.state.isSending ? '#AAAAAA' : '#145EB3', marginHorizontal: 10, marginTop: 15}}
disabled={this.state.isSending}
onPress={() => {this.sendQuestion()}}>
<Text style={{color: '#ffffff', fontSize: 14}}>{t('submit_data')}</Text>
</Button>

View File

@ -14,7 +14,8 @@ import {connect} from 'react-redux'
import {clearToken} from "../../api/api";
import DeviceInfo from 'react-native-device-info';
import { t } from 'src/utils/i18n'
import {getUserProfile} from "../../api/UserApi";
import {getUserProfile, logout} from "../../api/UserApi";
import IndicatorLoading from '../../components/IndicatorLoading'
const buildVersion = DeviceInfo.getVersion()
const buildNumber = DeviceInfo.getBuildNumber()
@ -44,14 +45,18 @@ class ServiceScreen extends Component {
fb_is_link: false,
user: {
point: 0
}
},
profileImage : require('../../../assets/images/praw.png'),
isLoadingLogout: false
}
}
componentDidMount() {
this.onLoad()
if (this.props.token != null && this.props.user != null) {
this.onLoad()
this.getUserData()
}
this.initData()
this.getUserData()
}
onLoad = () => {
@ -76,27 +81,51 @@ class ServiceScreen extends Component {
}
_logout() {
clearToken()
this.props.appCleanUser()
this.props.appCleanToken()
this.props.appCleanProjectID()
this.setState({
auth: false
isLoadingLogout : true
}, () => {
logout()
.then(res => {
console.log('response >>> ', res.data);
if(res.data && res.data.status === 'success'){
clearToken();
setTimeout(() => {
this.props.appCleanUser();
this.props.appCleanToken();
this.props.appCleanProjectID();
this.setState({
auth: false
}, () => {
this.setState({ isLoadingLogout: false})
this.props.navigation.navigate('HomeScreen',{isLogin:true})
})
}, 500)
}else {
this.setState({ isLoadingLogout: false})
Alert.alert('Logout unsuccessfully');
}
})
})
this.props.navigation.navigate('HomeScreen',{isLogin:true})
}
getUserData(){
getUserProfile()
.then(res => {
if(res.ok){
let image = require('../../../assets/images/praw.png')
if (res.data.user && res.data.user.image){
image = {
uri: res.data.user.image.url
}
}
console.log('Service: getUserData:')
console.log(res.data.user)
console.log('Service: ---- >',res.data.user)
this.state.user = res.data.user
this.state.fb_is_link = res.data.user.fb_is_link
// this.setState({
// user: res.data.user,
// })
this.state.fb_is_link = (res.data.user.fb_is_link === null || !res.data.user.fb_is_link) ? false : res.data.fb_is_link
this.setState({
profileImage: image,
})
}
})
}
@ -119,7 +148,7 @@ class ServiceScreen extends Component {
{this.state.auth == true ?
<View style={[styles.profile, {borderBottomColor: '#00000040', borderBottomWidth: 1}]}>
<View style={styles.profile_image}>
<Image source={require('../../../assets/images/praw.png')} style={{height: 64, width: 64, flex: 1,}} resizeMode={'contain'}/>
<Image source={this.state.profileImage} style={{height: 64, width: 64, flex: 1,borderRadius: 50}} resizeMode={'contain'}/>
</View>
<View style={styles.profile_detail}>
<View style={{flexDirection:'row',alignItems:'center'}}>
@ -130,9 +159,9 @@ class ServiceScreen extends Component {
}
</View>
<Badge style={{backgroundColor: '#269A21', borderRadius: 50, marginLeft: 5, height: 24, marginTop: 5, justifyContent: 'center'}}>
{/* <Badge style={{backgroundColor: '#269A21', borderRadius: 50, marginLeft: 5, height: 24, marginTop: 5, justifyContent: 'center'}}>
<Text style={{fontSize: 14, color: 'white', marginHorizontal: 10}}><Icon name="ic_star" size={14} color="white"/> 0</Text>
</Badge>
</Badge> */}
</View>
<TouchableOpacity
style={{flex: 1, justifyContent: 'center', width: 45,}}
@ -151,7 +180,9 @@ class ServiceScreen extends Component {
}
{
this.props.token != null &&
<ButtonBar title={t('mail_and_parcel')} iconName='ic_newspaper' callback={() => this.props.navigation.navigate('Object')}/>
<ButtonBar title={t('mail_and_parcel')} iconName='ic_newspaper' callback={() => this.props.navigation.navigate('Object',{
user:this.props.user
})}/>
}
{
this.props.token != null &&
@ -187,6 +218,8 @@ class ServiceScreen extends Component {
<Text style={{textAlign:'right',color:'#00000026',fontSize:12}}>v{buildVersion} ({buildNumber})</Text>
</View>
</View>
<IndicatorLoading loadingVisible={this.state.isLoadingLogout}/>
</BackgroundImage>
</LinearGradient>
)

View File

@ -9,6 +9,7 @@ import { bindActionCreators } from 'redux'
import { appCleanToken, appCleanUser } from '../../redux/app/action'
import { connect } from 'react-redux'
import { getSubscription, postSubscription } from "../../api/UserApi";
import { t } from '../../utils/i18n';
class SettingsNotificationScreen extends Component {

View File

@ -12,7 +12,7 @@ import ImagePicker from 'react-native-image-crop-picker'
import {postSuggestion, postSuggestionLogin} from '../../api/UserApi';
import { connect } from "react-redux";
import { t } from 'src/utils/i18n'
import IndicatorLoading from '../../components/IndicatorLoading';
let ACTIONSHEET_BUTTONS = [
'ถ่ายรูป',
'รูปจากแกลอรี่',
@ -29,7 +29,9 @@ class SuggestionScreen extends Component {
suggestionText: null,
image_list: [],
isShowAddBtn: true,
image_selected: {}
image_selected: {},
isLoading: false,
suggestionTitle: null
};
this.onImagePick = this.onImagePick.bind(this)
this.onTakeCamera = this.onTakeCamera.bind(this)
@ -37,27 +39,50 @@ class SuggestionScreen extends Component {
}
sendDataSuggestion() {
let param = {
message: this.state.suggestionText,
image: this.state.image_selected
}
console.log("param",param);
if(this.props.user == null && param.message != null){
postSuggestion(param)
.then(res => {
console.log('check response suggestion -----------> ',res)
Alert.alert('รับข้อเสนอแนะเรียบร้อย', 'ทางเราได้รับคำแนะนำและเรื่องไว้พิจารณาแล้ว ขอบคุณสำหรับความร่วมมือคะ',[{text: t('ok'), onPress:() => {this.props.navigation.goBack()}}])
})
}else if(this.props.user != null && param.message != null){
postSuggestionLogin(param)
.then(res => {
console.log('check response suggestion -----------> ',res)
Alert.alert('รับข้อเสนอแนะเรียบร้อย', 'ทางเราได้รับคำแนะนำและเรื่องไว้พิจารณาแล้ว ขอบคุณสำหรับความร่วมมือคะ',[{text: t('ok'), onPress:() => {this.props.navigation.goBack()}}])
})
}else{
console.log('suggestion fails')
Alert.alert('ส่งข้อเสนอแนะไม่สำเร็จ', 'กรุณากรอกข้อเสนอแนะ ขอบคุณสำหรับความร่วมมือคะ',[{text: t('ok')}])
}
this.setState({
isLoading: true
}, () => {
let param = {
message: this.state.suggestionText,
image: this.state.image_selected,
title: this.state.suggestionTitle
}
console.log("param",param);
if(this.props.user == null && param.message != null && param.title != null && param.title.trim() !== ""){
postSuggestion(param)
.then(res => {
console.log('check response suggestion -----------> ',res)
Alert.alert('รับข้อเสนอแนะเรียบร้อย', 'ทางเราได้รับคำแนะนำและเรื่องไว้พิจารณาแล้ว ขอบคุณสำหรับความร่วมมือค่ะ',[{text: t('ok'), onPress:() => {
this.setState({
isLoading: false
}, () => {
this.props.navigation.goBack()
})
}}])
})
}else if(this.props.user != null && param.message != null && param.title != null && param.title.trim() !== ""){
postSuggestionLogin(param)
.then(res => {
console.log('check response suggestion -----------> ',res)
Alert.alert('รับข้อเสนอแนะเรียบร้อย', 'ทางเราได้รับคำแนะนำและเรื่องไว้พิจารณาแล้ว ขอบคุณสำหรับความร่วมมือค่ะ',[{text: t('ok'), onPress:() => {
this.setState({
isLoading: false
}, () => {
this.props.navigation.goBack()
})
}}])
})
}else{
console.log('suggestion fails')
this.setState({
isLoading: false
}, () => {
Alert.alert('ส่งข้อเสนอแนะไม่สำเร็จ', 'กรุณากรอกข้อมูลให้ครบถ้วน',[{text: t('ok')}])
})
}
})
}
onImagePick() {
@ -83,7 +108,9 @@ class SuggestionScreen extends Component {
isShowAddBtn: false
})
})
}).catch(e => alert(e))
}).catch(e => {
// alert(e)
})
}
onTakeCamera() {
@ -109,7 +136,9 @@ class SuggestionScreen extends Component {
isShowAddBtn: false
})
})
}).catch(e => alert(e))
}).catch(e => {
// alert(e)
})
}
render() {
@ -124,6 +153,14 @@ class SuggestionScreen extends Component {
<KeyboardAvoidingView style={{flex:1}} keyboardVerticalOffset={Platform.OS == 'ios' ? 75 : 0} behavior={Platform.OS == 'ios' ? "padding" : ""} enabled>
<ScrollView contentContainerStyle={{flex:1}}>
<View style={{backgroundColor: 'white'}}>
<View>
<Text style={{color: '#00420A', padding: 16, paddingBottom: 5}}>{t('title')}</Text>
<TextInput
placeholder={'เขียนหัวข้อ'}
style={styles.textInput}
onChangeText={(text) => this.setState({suggestionTitle: text})}
value={this.state.suggestionTitle}/>
</View>
<View>
<Text style={{color: '#00420A', padding: 16, paddingBottom: 5}}>{t('suggestion')}</Text>
<TextInput
@ -190,6 +227,7 @@ class SuggestionScreen extends Component {
</ScrollView>
</KeyboardAvoidingView>
</BackgroundImage>
<IndicatorLoading loadingVisible={this.state.isLoading}/>
</LinearGradient>
)
@ -213,6 +251,15 @@ const styles = StyleSheet.create({
display: 'flex',
flexDirection: 'row'
},
textInput: {
backgroundColor: 'white',
paddingVertical: 15,
borderRadius: 5,
borderWidth: 1,
borderColor: 'rgba(0, 0, 0, 0.25)',
paddingHorizontal: 10,
marginHorizontal: 10,
},
textArea: {
backgroundColor: 'white',
marginHorizontal: 10,

View File

@ -156,6 +156,8 @@
"coporate": "Corporate",
"new_room": "New Room",
"please_pay_before": "Please pay before",
"please_pay_within": "Please make payment within the date",
"begin_charge_on" : "Overdue charge date",
"to_view_outstanding_balance": "to see the outstanding balance",
"no_mail_parcel": "You don't have any mails or parcels",
"no_notification": "You don't have any notifications",
@ -175,6 +177,26 @@
"paid": "Paid",
"latest_promotion": "New Promotion",
"disconnect_facebook": "Disconnect Facebook",
"register_success": "Register Success"
"register_success": "Register Success",
"repair_history_detail": "History Detail",
"repair_inprogress": "In Progress",
"repair_re_appoint": "Re Appointment",
"repair_success": "Success",
"customer": "Customer",
"guest": "Guest",
"other": "Other",
"clear_signature": "clear",
"signature": "Signature",
"save_signature": "Save",
"save_success": "Save Success",
"save_fail_and_try": "Unsuccess, Try again",
"new_parcel": "New Parcel",
"customer_not_found": "Data not found.",
"new_message": "New Message",
"bill_payment": "Bill Payment",
"meter_noti": "Electric Meter",
"title": "Title",
"update_app": "Update Application",
"payment_success": "Payment Success",
"delete_account": "Delete Account"
}

View File

@ -175,5 +175,24 @@
"paid": "បង់ប្រាក់",
"latest_promotion": "លើកកម្ពស់ថ្មី",
"disconnect_facebook": "ផ្តាច់ហ្វេសប៊ុក",
"register_success": "ចុះឈ្មោះទទួលបានជោគជ័យ"
"register_success": "ចុះឈ្មោះទទួលបានជោគជ័យ",
"repair_history_detail": "History Detail",
"repair_inprogress": "In Progress",
"repair_re_appoint": "Re Appointment",
"repair_success": "Success",
"customer": "Customer",
"guest": "Guest",
"other": "Other",
"clear_signature": "clear",
"signature": "Signature",
"save_signature": "រក្សាទុក",
"save_success": "Save Success",
"save_fail_and_try": "Unsuccess, Try again",
"new_parcel": "New Parcel",
"customer_not_found": "Data not found.",
"new_message": "New Message",
"bill_payment": "Bill Payment",
"meter_noti": "Electric Meter",
"title": "Title",
"delete_account": "Delete Account"
}

View File

@ -175,5 +175,24 @@
"paid": "ပေးဆောင်သည်",
"latest_promotion": "နယူးမြှင့်တင်ရေး",
"disconnect_facebook": "အဆက်ဖြုတ် Facebook က",
"register_success": "မှတ်ပုံတင်မည်အောင်မြင်"
"register_success": "မှတ်ပုံတင်မည်အောင်မြင်",
"repair_history_detail": "History Detail",
"repair_inprogress": "In Progress",
"repair_re_appoint": "Re Appointment",
"repair_success": "Success",
"customer": "Customer",
"guest": "Guest",
"other": "Other",
"clear_signature": "clear",
"signature": "Signature",
"save_signature": "သိမ်းဆည်းပါ",
"save_success": "Save Success",
"save_fail_and_try": "Unsuccess, Try again",
"new_parcel": "New Parcel",
"customer_not_found": "Data not found.",
"new_message": "New Message",
"bill_payment": "Bill Payment",
"meter_noti": "Electric Meter",
"title": "Title",
"delete_account": "Delete Account"
}

View File

@ -124,7 +124,7 @@
"login": "เข้าสู่ระบบ",
"login_facebook": "เข้าสู่ระบบด้วย Facebook",
"term_condition": "ข้อตกลงและเงื่อนไข",
"not_agree": "ไมยอมรับ",
"not_agree": "ไมยอมรับ",
"agree": "ยอมรับ",
"register": "สมัครสมาชิก",
"next": "ถัดไป",
@ -156,6 +156,8 @@
"coporate": "ข้อมูลนิติบุคคล",
"new_room": "ห้องใหม่",
"please_pay_before": "โปรดชำระก่อนวันที่",
"please_pay_within": "โปรดชำระภายในวันที่",
"begin_charge_on" : "วันที่เริ่มปรับ",
"to_view_outstanding_balance": "เพื่อดูยอดค้างชำระ",
"no_mail_parcel": "ไม่มีจดหมายหรือพัสดุ",
"no_notification": "ไม่มีการแจ้งเตือน",
@ -170,10 +172,31 @@
"confirmation_code": "รหัสยืนยัน",
"consignee": "ผู้รับ",
"waiting_for_pickup": "รอรับของ",
"contact_front_desk": "ติดต่อเคา์เตอร์",
"contact_front_desk": "ติดต่อเคา์เตอร์",
"awaiting_payment": "รอจ่ายที่เคาน์เตอร์",
"paid": "จ่ายเรียบร้อย",
"latest_promotion": "โปรโมชั่นใหม่",
"disconnect_facebook": "ยกเลิกการเชื่อมต่อ Facebook",
"register_success": "สมัครสมาชิกสำเร็จ"
"register_success": "สมัครสมาชิกสำเร็จ",
"repair_history_detail" : "รายละเอียดประวัติ",
"repair_inprogress" : "ซ่อมแซม",
"repair_re_appoint": "นัดหมายใหม่",
"repair_success": "ซ่อมสำเร็จ",
"customer": "ลูกค้า",
"guest": "ผู้ใช้งานทั่วไป",
"other": "อื่น ๆ",
"clear_signature": "ล้าง",
"signature": "ลายเซ็น",
"save_signature": "บันทึกรูป",
"save_success": "บันทึกสำเร็จ",
"save_fail_and_try": "บันทึกไม่สำเร็จ กรุณาลองอีกครั้ง",
"new_parcel": "จดหมายและพัสดุใหม่",
"customer_not_found": "ไม่พบข้อมูลในระบบ",
"new_message": "ข้อความใหม่",
"bill_payment": "บิลชำระเงิน",
"meter_noti": "เลขมิเตอร์น้ำ-ไฟฟ้า",
"title": "หัวข้อ",
"update_app": "อัปเดตแอปพลิเคชัน",
"payment_success": "ชำระเงินสำเร็จ",
"delete_account": "ลบบัญชี"
}

View File

@ -0,0 +1,12 @@
import moment from 'moment';
const defaultformat = 'D MMMM Y'
export default function parseDateLocale(date, format = defaultformat) {
if(moment.locale() === 'th') {
const dateParse = moment(date).add(543,'year');
return dateParse.isValid() ? dateParse.format(format) : '';
}
const dateParse = moment(date);
return dateParse.isValid() ? dateParse.format(format) : '';
}

5149
yarn.lock

File diff suppressed because it is too large Load Diff