浏览代码

Initial commit

Dola 5 月之前
当前提交
6b3dd77278
共有 100 个文件被更改,包括 7174 次插入0 次删除
  1. 14 0
      .gitignore
  2. 3 0
      .idea/.gitignore
  3. 1 0
      .idea/.name
  4. 126 0
      .idea/codeStyles/Project.xml
  5. 5 0
      .idea/codeStyles/codeStyleConfig.xml
  6. 6 0
      .idea/compiler.xml
  7. 23 0
      .idea/deploymentTargetDropDown.xml
  8. 19 0
      .idea/gradle.xml
  9. 35 0
      .idea/jarRepositories.xml
  10. 6 0
      .idea/kotlinc.xml
  11. 10 0
      .idea/migrations.xml
  12. 81 0
      .idea/misc.xml
  13. 6 0
      .idea/vcs.xml
  14. 1 0
      app/.gitignore
  15. 143 0
      app/build.gradle
  16. 二进制
      app/dev/release/Kun-Khmer_devRelease_1.0.0-dev.apk
  17. 18 0
      app/dev/release/output-metadata.json
  18. 39 0
      app/google-services.json
  19. 二进制
      app/prod/debug/App_prodDebug_1.0_1.apk
  20. 18 0
      app/prod/debug/output-metadata.json
  21. 二进制
      app/prod/release/SBC-Mobile_prodRelease_1.0.0.apk
  22. 18 0
      app/prod/release/output-metadata.json
  23. 146 0
      app/proguard-rules.pro
  24. 24 0
      app/src/androidTest/java/com/sambath/kunkhmer/ExampleInstrumentedTest.kt
  25. 7 0
      app/src/dev/java/com/sambath/kunkhmer/config/Config.kt
  26. 60 0
      app/src/main/AndroidManifest.xml
  27. 二进制
      app/src/main/ic_launcher-playstore.png
  28. 47 0
      app/src/main/java/com/sambath/kunkhmer/adapter/AbstractAdapter.kt
  29. 23 0
      app/src/main/java/com/sambath/kunkhmer/adapter/AbstractViewHolder.kt
  30. 31 0
      app/src/main/java/com/sambath/kunkhmer/adapter/BaseListAdapter.kt
  31. 17 0
      app/src/main/java/com/sambath/kunkhmer/adapter/BaseListItem.kt
  32. 49 0
      app/src/main/java/com/sambath/kunkhmer/adapter/BaseListViewHolder.kt
  33. 56 0
      app/src/main/java/com/sambath/kunkhmer/adapter/EventAdapter.kt
  34. 3 0
      app/src/main/java/com/sambath/kunkhmer/adapter/EventCardItem.kt
  35. 101 0
      app/src/main/java/com/sambath/kunkhmer/adapter/FighterAdapter.kt
  36. 11 0
      app/src/main/java/com/sambath/kunkhmer/adapter/FighterCardItem.kt
  37. 77 0
      app/src/main/java/com/sambath/kunkhmer/adapter/HighlightNewsAdapter.kt
  38. 57 0
      app/src/main/java/com/sambath/kunkhmer/adapter/LivesAdapter.kt
  39. 3 0
      app/src/main/java/com/sambath/kunkhmer/adapter/LivesCardItem.kt
  40. 31 0
      app/src/main/java/com/sambath/kunkhmer/adapter/MainPagerAdapter.kt
  41. 54 0
      app/src/main/java/com/sambath/kunkhmer/adapter/ProductAdapter.kt
  42. 3 0
      app/src/main/java/com/sambath/kunkhmer/adapter/ProductCardItem.kt
  43. 73 0
      app/src/main/java/com/sambath/kunkhmer/adapter/TopNewsAdapter.kt
  44. 3 0
      app/src/main/java/com/sambath/kunkhmer/adapter/TopNewsCardItem.kt
  45. 66 0
      app/src/main/java/com/sambath/kunkhmer/adapter/TopNewsDetailAdapter.kt
  46. 40 0
      app/src/main/java/com/sambath/kunkhmer/adapter/TopNewsHeaderAdapter.kt
  47. 26 0
      app/src/main/java/com/sambath/kunkhmer/app/AdminActivity.kt
  48. 116 0
      app/src/main/java/com/sambath/kunkhmer/app/App.kt
  49. 41 0
      app/src/main/java/com/sambath/kunkhmer/app/ErrorInterceptor.kt
  50. 14 0
      app/src/main/java/com/sambath/kunkhmer/app/ExceptionExtension.kt
  51. 95 0
      app/src/main/java/com/sambath/kunkhmer/app/MainActivity.kt
  52. 23 0
      app/src/main/java/com/sambath/kunkhmer/app/ServiceInterceptor.kt
  53. 373 0
      app/src/main/java/com/sambath/kunkhmer/app/ShareActivity.kt
  54. 163 0
      app/src/main/java/com/sambath/kunkhmer/app/ShareViewModel.kt
  55. 19 0
      app/src/main/java/com/sambath/kunkhmer/app/ShareViewState.kt
  56. 45 0
      app/src/main/java/com/sambath/kunkhmer/base/AutoLogoutBaseActivity.kt
  57. 54 0
      app/src/main/java/com/sambath/kunkhmer/base/BaseActivity.kt
  58. 97 0
      app/src/main/java/com/sambath/kunkhmer/base/BaseFragment.kt
  59. 13 0
      app/src/main/java/com/sambath/kunkhmer/base/BaseViewModel.kt
  60. 104 0
      app/src/main/java/com/sambath/kunkhmer/extension/CurrentUserDataModel.kt
  61. 209 0
      app/src/main/java/com/sambath/kunkhmer/extension/ViewExtensions.kt
  62. 28 0
      app/src/main/java/com/sambath/kunkhmer/remote/CfModel.kt
  63. 119 0
      app/src/main/java/com/sambath/kunkhmer/remote/EventDataModel.kt
  64. 218 0
      app/src/main/java/com/sambath/kunkhmer/remote/FighterDataModel.kt
  65. 80 0
      app/src/main/java/com/sambath/kunkhmer/remote/HighlightDataModel.kt
  66. 32 0
      app/src/main/java/com/sambath/kunkhmer/remote/K.kt
  67. 90 0
      app/src/main/java/com/sambath/kunkhmer/remote/LivesDataModel.kt
  68. 630 0
      app/src/main/java/com/sambath/kunkhmer/remote/LoginDataModel.kt
  69. 415 0
      app/src/main/java/com/sambath/kunkhmer/remote/MainDataModel.kt
  70. 82 0
      app/src/main/java/com/sambath/kunkhmer/remote/NewsDataModel.kt
  71. 59 0
      app/src/main/java/com/sambath/kunkhmer/remote/NewsDetailDataModel.kt
  72. 93 0
      app/src/main/java/com/sambath/kunkhmer/remote/PlayDataModel.kt
  73. 84 0
      app/src/main/java/com/sambath/kunkhmer/remote/ProductDataModel.kt
  74. 153 0
      app/src/main/java/com/sambath/kunkhmer/remote/ReportDataModel.kt
  75. 126 0
      app/src/main/java/com/sambath/kunkhmer/remote/ResultDataModel.kt
  76. 15 0
      app/src/main/java/com/sambath/kunkhmer/remote/SocketMessageDataModel.kt
  77. 30 0
      app/src/main/java/com/sambath/kunkhmer/remote/UpdatePwdDataModel.kt
  78. 147 0
      app/src/main/java/com/sambath/kunkhmer/remote/service/ApiService.kt
  79. 19 0
      app/src/main/java/com/sambath/kunkhmer/remote/service/ConnectivityStates.java
  80. 29 0
      app/src/main/java/com/sambath/kunkhmer/remote/service/EventListener.java
  81. 133 0
      app/src/main/java/com/sambath/kunkhmer/remote/service/SocketService.java
  82. 91 0
      app/src/main/java/com/sambath/kunkhmer/screen/account/AccountFragment.kt
  83. 49 0
      app/src/main/java/com/sambath/kunkhmer/screen/account/AccountViewModel.kt
  84. 103 0
      app/src/main/java/com/sambath/kunkhmer/screen/event/EventAdminFragment.kt
  85. 60 0
      app/src/main/java/com/sambath/kunkhmer/screen/event/EventFragment.kt
  86. 77 0
      app/src/main/java/com/sambath/kunkhmer/screen/event/EventViewModel.kt
  87. 136 0
      app/src/main/java/com/sambath/kunkhmer/screen/fighter/CreateFighterFragment.kt
  88. 161 0
      app/src/main/java/com/sambath/kunkhmer/screen/fighter/FighterAdminFragment.kt
  89. 109 0
      app/src/main/java/com/sambath/kunkhmer/screen/fighter/FighterFragment.kt
  90. 163 0
      app/src/main/java/com/sambath/kunkhmer/screen/fighter/FighterViewModel.kt
  91. 40 0
      app/src/main/java/com/sambath/kunkhmer/screen/lives/LiveDetailFragment.kt
  92. 118 0
      app/src/main/java/com/sambath/kunkhmer/screen/lives/LivesAdminFragment.kt
  93. 111 0
      app/src/main/java/com/sambath/kunkhmer/screen/lives/LivesFragment.kt
  94. 76 0
      app/src/main/java/com/sambath/kunkhmer/screen/lives/LivesViewModel.kt
  95. 80 0
      app/src/main/java/com/sambath/kunkhmer/screen/login/LoginActivity.kt
  96. 50 0
      app/src/main/java/com/sambath/kunkhmer/screen/login/LoginViewModel.kt
  97. 9 0
      app/src/main/java/com/sambath/kunkhmer/screen/login/LoginViewState.kt
  98. 21 0
      app/src/main/java/com/sambath/kunkhmer/screen/main/MainAdapter.kt
  99. 22 0
      app/src/main/java/com/sambath/kunkhmer/screen/main/MainDataViewState.kt
  100. 170 0
      app/src/main/java/com/sambath/kunkhmer/screen/main/MainFragment.kt

+ 14 - 0
.gitignore

@@ -0,0 +1,14 @@
+*.iml
+.gradle
+/local.properties
+/.idea/caches
+/.idea/libraries
+/.idea/modules.xml
+/.idea/workspace.xml
+/.idea/navEditor.xml
+/.idea/assetWizardSettings.xml
+.DS_Store
+/build
+/captures
+.externalNativeBuild
+.cxx

+ 3 - 0
.idea/.gitignore

@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml

+ 1 - 0
.idea/.name

@@ -0,0 +1 @@
+SampleApp

+ 126 - 0
.idea/codeStyles/Project.xml

@@ -0,0 +1,126 @@
+<component name="ProjectCodeStyleConfiguration">
+  <code_scheme name="Project" version="173">
+    <option name="RIGHT_MARGIN" value="300" />
+    <JetCodeStyleSettings>
+      <option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
+    </JetCodeStyleSettings>
+    <codeStyleSettings language="JAVA">
+      <option name="WRAP_LONG_LINES" value="true" />
+    </codeStyleSettings>
+    <codeStyleSettings language="XML">
+      <indentOptions>
+        <option name="CONTINUATION_INDENT_SIZE" value="4" />
+      </indentOptions>
+      <arrangement>
+        <rules>
+          <section>
+            <rule>
+              <match>
+                <AND>
+                  <NAME>xmlns:android</NAME>
+                  <XML_ATTRIBUTE />
+                  <XML_NAMESPACE>^$</XML_NAMESPACE>
+                </AND>
+              </match>
+            </rule>
+          </section>
+          <section>
+            <rule>
+              <match>
+                <AND>
+                  <NAME>xmlns:.*</NAME>
+                  <XML_ATTRIBUTE />
+                  <XML_NAMESPACE>^$</XML_NAMESPACE>
+                </AND>
+              </match>
+              <order>BY_NAME</order>
+            </rule>
+          </section>
+          <section>
+            <rule>
+              <match>
+                <AND>
+                  <NAME>.*:id</NAME>
+                  <XML_ATTRIBUTE />
+                  <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
+                </AND>
+              </match>
+            </rule>
+          </section>
+          <section>
+            <rule>
+              <match>
+                <AND>
+                  <NAME>.*:name</NAME>
+                  <XML_ATTRIBUTE />
+                  <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
+                </AND>
+              </match>
+            </rule>
+          </section>
+          <section>
+            <rule>
+              <match>
+                <AND>
+                  <NAME>name</NAME>
+                  <XML_ATTRIBUTE />
+                  <XML_NAMESPACE>^$</XML_NAMESPACE>
+                </AND>
+              </match>
+            </rule>
+          </section>
+          <section>
+            <rule>
+              <match>
+                <AND>
+                  <NAME>style</NAME>
+                  <XML_ATTRIBUTE />
+                  <XML_NAMESPACE>^$</XML_NAMESPACE>
+                </AND>
+              </match>
+            </rule>
+          </section>
+          <section>
+            <rule>
+              <match>
+                <AND>
+                  <NAME>.*</NAME>
+                  <XML_ATTRIBUTE />
+                  <XML_NAMESPACE>^$</XML_NAMESPACE>
+                </AND>
+              </match>
+              <order>BY_NAME</order>
+            </rule>
+          </section>
+          <section>
+            <rule>
+              <match>
+                <AND>
+                  <NAME>.*</NAME>
+                  <XML_ATTRIBUTE />
+                  <XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
+                </AND>
+              </match>
+              <order>ANDROID_ATTRIBUTE_ORDER</order>
+            </rule>
+          </section>
+          <section>
+            <rule>
+              <match>
+                <AND>
+                  <NAME>.*</NAME>
+                  <XML_ATTRIBUTE />
+                  <XML_NAMESPACE>.*</XML_NAMESPACE>
+                </AND>
+              </match>
+              <order>BY_NAME</order>
+            </rule>
+          </section>
+        </rules>
+      </arrangement>
+    </codeStyleSettings>
+    <codeStyleSettings language="kotlin">
+      <option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
+    </codeStyleSettings>
+  </code_scheme>
+</component>

+ 5 - 0
.idea/codeStyles/codeStyleConfig.xml

@@ -0,0 +1,5 @@
+<component name="ProjectCodeStyleConfiguration">
+  <state>
+    <option name="USE_PER_PROJECT_SETTINGS" value="true" />
+  </state>
+</component>

+ 6 - 0
.idea/compiler.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="CompilerConfiguration">
+    <bytecodeTargetLevel target="15" />
+  </component>
+</project>

+ 23 - 0
.idea/deploymentTargetDropDown.xml

@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="deploymentTargetDropDown">
+    <value>
+      <entry key="app">
+        <State>
+          <targetSelectedWithDropDown>
+            <Target>
+              <type value="QUICK_BOOT_TARGET" />
+              <deviceKey>
+                <Key>
+                  <type value="VIRTUAL_DEVICE_PATH" />
+                  <value value="C:\Users\dolat\.android\avd\Pixel_3a_API_34_extension_level_7_x86_64.avd" />
+                </Key>
+              </deviceKey>
+            </Target>
+          </targetSelectedWithDropDown>
+          <timeTargetWasSelectedWithDropDown value="2024-04-20T06:58:23.132755200Z" />
+        </State>
+      </entry>
+    </value>
+  </component>
+</project>

+ 19 - 0
.idea/gradle.xml

@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="GradleMigrationSettings" migrationVersion="1" />
+  <component name="GradleSettings">
+    <option name="linkedExternalProjectsSettings">
+      <GradleProjectSettings>
+        <option name="externalProjectPath" value="$PROJECT_DIR$" />
+        <option name="gradleJvm" value="corretto-15" />
+        <option name="modules">
+          <set>
+            <option value="$PROJECT_DIR$" />
+            <option value="$PROJECT_DIR$/app" />
+          </set>
+        </option>
+        <option name="resolveExternalAnnotations" value="false" />
+      </GradleProjectSettings>
+    </option>
+  </component>
+</project>

+ 35 - 0
.idea/jarRepositories.xml

@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="RemoteRepositoriesConfiguration">
+    <remote-repository>
+      <option name="id" value="central" />
+      <option name="name" value="Maven Central repository" />
+      <option name="url" value="https://repo1.maven.org/maven2" />
+    </remote-repository>
+    <remote-repository>
+      <option name="id" value="jboss.community" />
+      <option name="name" value="JBoss Community repository" />
+      <option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
+    </remote-repository>
+    <remote-repository>
+      <option name="id" value="BintrayJCenter" />
+      <option name="name" value="BintrayJCenter" />
+      <option name="url" value="https://jcenter.bintray.com/" />
+    </remote-repository>
+    <remote-repository>
+      <option name="id" value="Google" />
+      <option name="name" value="Google" />
+      <option name="url" value="https://dl.google.com/dl/android/maven2/" />
+    </remote-repository>
+    <remote-repository>
+      <option name="id" value="maven" />
+      <option name="name" value="maven" />
+      <option name="url" value="https://jitpack.io" />
+    </remote-repository>
+    <remote-repository>
+      <option name="id" value="MavenRepo" />
+      <option name="name" value="MavenRepo" />
+      <option name="url" value="https://repo.maven.apache.org/maven2/" />
+    </remote-repository>
+  </component>
+</project>

+ 6 - 0
.idea/kotlinc.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="KotlinJpsPluginSettings">
+    <option name="version" value="1.6.21" />
+  </component>
+</project>

+ 10 - 0
.idea/migrations.xml

@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectMigrations">
+    <option name="MigrateToGradleLocalJavaHome">
+      <set>
+        <option value="$PROJECT_DIR$" />
+      </set>
+    </option>
+  </component>
+</project>

+ 81 - 0
.idea/misc.xml

@@ -0,0 +1,81 @@
+<project version="4">
+  <component name="DesignSurface">
+    <option name="filePathToZoomLevelMap">
+      <map>
+        <entry key="..\:/3-Work/Android/sbc-mobile/app/src/main/res/drawable/ic_baseline_add_circle_24.xml" value="0.333" />
+        <entry key="..\:/3-Work/Android/sbc-mobile/app/src/main/res/drawable/stroke_result.xml" value="0.3675" />
+        <entry key="..\:/3-Work/Android/sbc-mobile/app/src/main/res/layout/app_bar.xml" value="0.36666666666666664" />
+        <entry key="..\:/3-Work/Android/sbc-mobile/app/src/main/res/layout/fragment_cf_betting.xml" value="0.36666666666666664" />
+        <entry key="..\:/3-Work/Android/sbc-mobile/app/src/main/res/layout/fragment_cf_result.xml" value="0.36666666666666664" />
+        <entry key="..\:/3-Work/Android/sbc-mobile/app/src/main/res/layout/item_box.xml" value="0.36666666666666664" />
+        <entry key="..\:/AndroidStudioProjects/sbc-mobile/app/src/main/res/layout/app_bar.xml" value="0.20416666666666666" />
+        <entry key="..\:/AndroidStudioProjects/sbc-mobile/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml" value="0.2203125" />
+        <entry key="..\:/AndroidStudioProjects/sbc-mobile/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml" value="0.2203125" />
+        <entry key="..\:/PartTimeProject/CFLive/app/src/main/res/layout/activity_login.xml" value="0.28442028985507245" />
+        <entry key="..\:/PartTimeProject/CFLive/app/src/main/res/layout/activity_main.xml" value="0.28442028985507245" />
+        <entry key="..\:/PartTimeProject/CFLive/app/src/main/res/layout/activity_splash.xml" value="0.28442028985507245" />
+        <entry key="..\:/PartTimeProject/CFLive/app/src/main/res/layout/content_main.xml" value="0.28442028985507245" />
+        <entry key="..\:/PartTimeProject/CFLive/app/src/main/res/layout/fragment_cf_betting.xml" value="0.28306159420289856" />
+        <entry key="..\:/PartTimeProject/CFLive/app/src/main/res/layout/fragment_cf_result.xml" value="0.28306159420289856" />
+        <entry key="..\:/PartTimeProject/CFLive/app/src/main/res/layout/fragment_main.xml" value="0.28306159420289856" />
+        <entry key="..\:/PartTimeProject/SBClive/app/src/main/res/drawable/bg_orange.xml" value="0.196875" />
+        <entry key="..\:/PartTimeProject/SBClive/app/src/main/res/layout/activity_login.xml" value="0.225" />
+        <entry key="..\:/PartTimeProject/SBClive/app/src/main/res/layout/activity_main.xml" value="0.18072916666666666" />
+        <entry key="..\:/PartTimeProject/SBClive/app/src/main/res/layout/activity_splash.xml" value="0.18072916666666666" />
+        <entry key="..\:/PartTimeProject/SBClive/app/src/main/res/layout/app_bar.xml" value="0.22" />
+        <entry key="..\:/PartTimeProject/SBClive/app/src/main/res/layout/content_main.xml" value="0.18072916666666666" />
+        <entry key="..\:/PartTimeProject/SBClive/app/src/main/res/layout/fragment_cf_betting.xml" value="0.18072916666666666" />
+        <entry key="..\:/PartTimeProject/SBClive/app/src/main/res/layout/fragment_main.xml" value="0.18072916666666666" />
+        <entry key="..\:/PartTimeProject/SBClive/app/src/main/res/layout/item_box.xml" value="0.19322916666666667" />
+        <entry key="..\:/PartTimeProject/SBClive/app/src/main/res/menu/menu_channel.xml" value="0.175" />
+        <entry key="..\:/PartTimeProject/SBClive/app/src/main/res/menu/menu_main.xml" value="0.175" />
+        <entry key="..\:/PartTimeProject/Website/sbc-mobile/app/src/main/res/drawable/bg_circle_blue.xml" value="0.37407407407407406" />
+        <entry key="..\:/PartTimeProject/Website/sbc-mobile/app/src/main/res/drawable/bg_circle_green.xml" value="0.37407407407407406" />
+        <entry key="..\:/PartTimeProject/Website/sbc-mobile/app/src/main/res/drawable/bg_circle_red.xml" value="0.37407407407407406" />
+        <entry key="..\:/PartTimeProject/Website/sbc-mobile/app/src/main/res/drawable/bg_circle_yellow.xml" value="0.37407407407407406" />
+        <entry key="..\:/PartTimeProject/Website/sbc-mobile/app/src/main/res/drawable/bg_table_header.xml" value="0.31296296296296294" />
+        <entry key="..\:/PartTimeProject/Website/sbc-mobile/app/src/main/res/layout/activity_main.xml" value="0.33" />
+        <entry key="..\:/PartTimeProject/Website/sbc-mobile/app/src/main/res/layout/app_bar.xml" value="0.14322916666666666" />
+        <entry key="..\:/PartTimeProject/Website/sbc-mobile/app/src/main/res/layout/app_bar_dialog.xml" value="0.13541666666666666" />
+        <entry key="..\:/PartTimeProject/Website/sbc-mobile/app/src/main/res/layout/content_main.xml" value="0.23854166666666668" />
+        <entry key="..\:/PartTimeProject/Website/sbc-mobile/app/src/main/res/layout/current_bets_item.xml" value="0.36666666666666664" />
+        <entry key="..\:/PartTimeProject/Website/sbc-mobile/app/src/main/res/layout/fragment_cf_result.xml" value="0.36666666666666664" />
+        <entry key="..\:/PartTimeProject/Website/sbc-mobile/app/src/main/res/layout/fragment_current_bets.xml" value="0.2390625" />
+        <entry key="..\:/PartTimeProject/Website/sbc-mobile/app/src/main/res/layout/fragment_dialog_report.xml" value="0.2" />
+        <entry key="..\:/PartTimeProject/Website/sbc-mobile/app/src/main/res/layout/fragment_report.xml" value="0.5" />
+        <entry key="..\:/PartTimeProject/Website/sbc-mobile/app/src/main/res/layout/fragment_setting.xml" value="0.25677083333333334" />
+        <entry key="..\:/PartTimeProject/Website/sbc-mobile/app/src/main/res/layout/fragment_statement.xml" value="0.4650630011454754" />
+        <entry key="..\:/PartTimeProject/Website/sbc-mobile/app/src/main/res/layout/fragment_today_report.xml" value="0.2390625" />
+        <entry key="..\:/PartTimeProject/Website/sbc-mobile/app/src/main/res/layout/item_box.xml" value="0.25" />
+        <entry key="..\:/PartTimeProject/Website/sbc-mobile/app/src/main/res/layout/item_money_transaction.xml" value="0.21145833333333333" />
+        <entry key="..\:/PartTimeProject/Website/sbc-mobile/app/src/main/res/layout/item_report.xml" value="0.22" />
+        <entry key="..\:/PartTimeProject/Website/sbc-mobile/app/src/main/res/layout/item_table_report.xml" value="0.20520833333333333" />
+        <entry key="..\:/PartTimeProject/Website/sbc-mobile/app/src/main/res/layout/item_table_statement.xml" value="0.25" />
+        <entry key="..\:/PartTimeProject/Website/sbc-mobile/app/src/main/res/layout/tab_statement.xml" value="0.20520833333333333" />
+        <entry key="..\:/PartTimeProject/Website/sbc-mobile/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml" value="0.22135416666666666" />
+        <entry key="..\:/PartTimeProject/Website/sbc-mobile/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml" value="0.22135416666666666" />
+      </map>
+    </option>
+  </component>
+  <component name="ProjectRootManager" version="2" languageLevel="JDK_15" default="true" project-jdk-name="corretto-15" project-jdk-type="JavaSDK">
+    <output url="file://$PROJECT_DIR$/build/classes" />
+  </component>
+  <component name="ProjectType">
+    <option name="id" value="Android" />
+  </component>
+  <component name="masterDetails">
+    <states>
+      <state key="ScopeChooserConfigurable.UI">
+        <settings>
+          <splitter-proportions>
+            <option name="proportions">
+              <list>
+                <option value="0.2" />
+              </list>
+            </option>
+          </splitter-proportions>
+        </settings>
+      </state>
+    </states>
+  </component>
+</project>

+ 6 - 0
.idea/vcs.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="$PROJECT_DIR$" vcs="Git" />
+  </component>
+</project>

+ 1 - 0
app/.gitignore

@@ -0,0 +1 @@
+/build

+ 143 - 0
app/build.gradle

@@ -0,0 +1,143 @@
+apply plugin: 'com.android.application'
+apply plugin: 'kotlin-android'
+apply plugin: 'kotlin-android-extensions'
+apply plugin: 'kotlin-kapt'
+
+android {
+    compileSdkVersion 31
+    buildToolsVersion "29.0.3"
+    signingConfigs {
+        release {
+             storeFile rootProject.file("evaluation-testing.jks")
+            storePassword "123456"
+            keyAlias = "gdt"
+            keyPassword "123456"
+        }
+    }
+    defaultConfig {
+        applicationId "com.sambath.kunkhmer"
+        minSdkVersion 21
+        targetSdkVersion 31
+        versionCode 1
+        versionName "1.0.0"
+        signingConfig signingConfigs.release
+        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+    }
+
+    buildTypes {
+        debug {
+            minifyEnabled false
+            debuggable true
+            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+        }
+        release {
+            shrinkResources true
+            minifyEnabled true
+            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+        }
+    }
+
+// To inline the bytecode built with JVM target 1.8 into
+// bytecode that is being built with JVM target 1.6. (e.g. navArgs)
+
+    compileOptions {
+        sourceCompatibility JavaVersion.VERSION_1_8
+        targetCompatibility JavaVersion.VERSION_1_8
+    }
+    kotlinOptions {
+        jvmTarget = "1.8"
+    }
+    androidExtensions {
+        experimental = true
+    }
+    packagingOptions {
+        exclude 'META-INF/DEPENDENCIES'
+        exclude 'META-INF/LICENSE'
+        exclude 'META-INF/LICENSE.txt'
+        exclude 'META-INF/license.txt'
+        exclude 'META-INF/NOTICE'
+        exclude 'META-INF/NOTICE.txt'
+        exclude 'META-INF/notice.txt'
+        exclude 'META-INF/ASL2.0'
+    }
+    lintOptions {
+        checkReleaseBuilds false
+        abortOnError false
+    }
+    flavorDimensions 'env'
+    productFlavors {
+        dev {
+            dimension 'env'
+            //applicationIdSuffix = ".dev"
+            versionNameSuffix "-dev"
+        }
+        prod {
+            dimension 'env'
+        }
+    }
+    applicationVariants.all { variant ->
+        variant.outputs.all {
+            //def formattedDate = new Date().format('yyyy-MM-dd HH-mm')
+            def appName = "Kun-Khmer"
+            def appId = variant.applicationId
+            def versionName = variant.versionName
+            def versionCode = variant.versionCode
+            def flavorName = variant.flavorName // e. g. free
+            def buildType = variant.buildType // e. g. debug
+            def variantName = variant.name // e. g. freeDebug
+            def apkName = appName + '_' + variantName + '_' + versionName + '.apk'
+            outputFileName = apkName
+        }
+    }
+}
+
+dependencies {
+    implementation fileTree(dir: 'libs', include: ['*.jar'])
+    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+    implementation 'androidx.appcompat:appcompat:1.4.0'
+    implementation 'androidx.core:core-ktx:1.3.2'
+    implementation 'com.google.android.material:material:1.4.0'
+    implementation 'androidx.constraintlayout:constraintlayout:2.1.2'
+    implementation 'androidx.navigation:navigation-fragment-ktx:2.3.5'
+    implementation 'androidx.navigation:navigation-ui-ktx:2.3.5'
+
+    //Architecture components
+    def lifecycle_version = "2.2.0"
+    implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
+    implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
+    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
+    implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version"
+
+    //RxJava & RxAndroid
+    implementation "io.reactivex.rxjava2:rxjava:2.2.18"
+    implementation "io.reactivex.rxjava2:rxkotlin:2.4.0"
+    implementation "io.reactivex.rxjava2:rxandroid:2.1.1"
+
+    //Retrofit
+    def retrofit_version = "2.9.0"
+    implementation "com.squareup.retrofit2:retrofit:$retrofit_version"
+    implementation "com.squareup.retrofit2:adapter-rxjava2:$retrofit_version"
+    implementation "com.squareup.retrofit2:converter-moshi:$retrofit_version"
+    implementation 'com.squareup.okhttp3:logging-interceptor:4.9.0'
+    implementation 'com.squareup.okhttp3:okhttp:4.9.0'
+    implementation 'com.itkacher.okhttpprofiler:okhttpprofiler:1.0.7'
+
+    /*Json Serialize & Deserialize Library*/
+    implementation("com.squareup.moshi:moshi-kotlin:1.9.2")
+    kapt("com.squareup.moshi:moshi-kotlin-codegen:1.9.2")
+    //Socket io client
+    implementation('io.socket:socket.io-client:2.0.0') {
+        exclude group: 'org.json', module: 'json'
+    }
+
+    //  Logging helper
+    implementation 'com.jakewharton.timber:timber:4.7.1'
+    implementation 'com.google.code.gson:gson:2.8.6'
+
+    //Lib
+    implementation 'com.squareup.picasso:picasso:2.71828'
+
+    testImplementation 'junit:junit:4.13.2'
+    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
+    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
+}

二进制
app/dev/release/Kun-Khmer_devRelease_1.0.0-dev.apk


+ 18 - 0
app/dev/release/output-metadata.json

@@ -0,0 +1,18 @@
+{
+  "version": 2,
+  "artifactType": {
+    "type": "APK",
+    "kind": "Directory"
+  },
+  "applicationId": "com.sambath.kunkhmer",
+  "variantName": "processDevReleaseResources",
+  "elements": [
+    {
+      "type": "SINGLE",
+      "filters": [],
+      "versionCode": 1,
+      "versionName": "1.0.0-dev",
+      "outputFile": "Kun-Khmer_devRelease_1.0.0-dev.apk"
+    }
+  ]
+}

+ 39 - 0
app/google-services.json

@@ -0,0 +1,39 @@
+{
+  "project_info": {
+    "project_number": "352049919729",
+    "project_id": "sombath-e7d83",
+    "storage_bucket": "sombath-e7d83.appspot.com"
+  },
+  "client": [
+    {
+      "client_info": {
+        "mobilesdk_app_id": "1:352049919729:android:c9a1aaa2f22dbb29381b50",
+        "android_client_info": {
+          "package_name": "com.sambath.loto"
+        }
+      },
+      "oauth_client": [
+        {
+          "client_id": "352049919729-04apg997ana6cm330p2mjsv6kqmaoub7.apps.googleusercontent.com",
+          "client_type": 3
+        }
+      ],
+      "api_key": [
+        {
+          "current_key": "AIzaSyApUv8IWd7fYKs7t6w04OFnj70nIxtul2w"
+        }
+      ],
+      "services": {
+        "appinvite_service": {
+          "other_platform_oauth_client": [
+            {
+              "client_id": "352049919729-04apg997ana6cm330p2mjsv6kqmaoub7.apps.googleusercontent.com",
+              "client_type": 3
+            }
+          ]
+        }
+      }
+    }
+  ],
+  "configuration_version": "1"
+}

二进制
app/prod/debug/App_prodDebug_1.0_1.apk


+ 18 - 0
app/prod/debug/output-metadata.json

@@ -0,0 +1,18 @@
+{
+  "version": 2,
+  "artifactType": {
+    "type": "APK",
+    "kind": "Directory"
+  },
+  "applicationId": "com.sambath.loto",
+  "variantName": "processProdDebugResources",
+  "elements": [
+    {
+      "type": "SINGLE",
+      "filters": [],
+      "versionCode": 1,
+      "versionName": "1.0",
+      "outputFile": "App_prodDebug_1.0_1.apk"
+    }
+  ]
+}

二进制
app/prod/release/SBC-Mobile_prodRelease_1.0.0.apk


+ 18 - 0
app/prod/release/output-metadata.json

@@ -0,0 +1,18 @@
+{
+  "version": 2,
+  "artifactType": {
+    "type": "APK",
+    "kind": "Directory"
+  },
+  "applicationId": "com.sambath.sbc",
+  "variantName": "processProdReleaseResources",
+  "elements": [
+    {
+      "type": "SINGLE",
+      "filters": [],
+      "versionCode": 1,
+      "versionName": "1.0.0",
+      "outputFile": "SBC-Mobile_prodRelease_1.0.0.apk"
+    }
+  ]
+}

+ 146 - 0
app/proguard-rules.pro

@@ -0,0 +1,146 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
+-keep class * implements java.io.Serializable { *; }
+
+-keepattributes *Annotation*
+
+#### OkHttp, Retrofit and Moshi
+-dontwarn okhttp3.**
+-dontwarn retrofit2.Platform$Java8
+-dontwarn okio.**
+-dontwarn javax.annotation.**
+-dontwarn org.jetbrains.annotations.**
+
+#-keep class kotlin.reflect.jvm.internal.impl.builtins.BuiltInsLoaderImpl
+-keep class kotlin.Metadata { *; }
+-keepclassmembers class kotlin.Metadata {
+    public <methods>;
+}
+
+#-keepnames @kotlin.Metadata class gdt.com.e_payments.data.model.**
+#-keep class gdt.com.e_payments.data.model.** { *; }
+#-keepclassmembers class gdt.com.e_payments.data.model.** { *; }
+
+-keepclasseswithmembers class * {
+    @retrofit2.http.* <methods>;
+}
+
+-keepclasseswithmembers class * {
+    @com.squareup.moshi.* <methods>;
+}
+-keepclassmembers class * {
+    @com.squareup.moshi.FromJson <methods>;
+    @com.squareup.moshi.ToJson <methods>;
+}
+-keepclassmembers @com.squareup.moshi.JsonClass class * extends java.lang.Enum {
+    <fields>;
+    **[] values();
+}
+
+-keep @com.squareup.moshi.JsonQualifier interface *
+-keepnames @com.squareup.moshi.JsonClass class *
+
+# Retain generated target class's synthetic defaults constructor and keep DefaultConstructorMarker's
+# name. We will look this up reflectively to invoke the type's constructor.
+#
+# We can't _just_ keep the defaults constructor because Proguard/R8's spec doesn't allow wildcard
+# matching preceding parameters.
+-keepnames class kotlin.jvm.internal.DefaultConstructorMarker
+-keepclassmembers @com.squareup.moshi.JsonClass @kotlin.Metadata class * {
+    synthetic <init>(...);
+}
+
+# Retain generated JsonAdapters if annotated type is retained.
+-if @com.squareup.moshi.JsonClass class *
+-keep class <1>JsonAdapter {
+    <init>(...);
+    <fields>;
+}
+-if @com.squareup.moshi.JsonClass class **$*
+-keep class <1>_<2>JsonAdapter {
+    <init>(...);
+    <fields>;
+}
+-if @com.squareup.moshi.JsonClass class **$*$*
+-keep class <1>_<2>_<3>JsonAdapter {
+    <init>(...);
+    <fields>;
+}
+-if @com.squareup.moshi.JsonClass class **$*$*$*
+-keep class <1>_<2>_<3>_<4>JsonAdapter {
+    <init>(...);
+    <fields>;
+}
+-if @com.squareup.moshi.JsonClass class **$*$*$*$*
+-keep class <1>_<2>_<3>_<4>_<5>JsonAdapter {
+    <init>(...);
+    <fields>;
+}
+-if @com.squareup.moshi.JsonClass class **$*$*$*$*$*
+-keep class <1>_<2>_<3>_<4>_<5>_<6>JsonAdapter {
+    <init>(...);
+    <fields>;
+}
+
+# RxJava
+-dontwarn org.reactivestreams.FlowAdapters
+-dontwarn org.reactivestreams.**
+-dontwarn java.util.concurrent.Flow.**
+-dontwarn java.util.concurrent.**
+# Firebase Crashlytics
+#-keepattributes SourceFile,LineNumberTable        # Keep file names and line numbers.
+#-keep public class * extends java.lang.Exception  # Optional: Keep custom exceptions.
+#-keep class com.google.firebase.crashlytics. { *; }
+#-dontwarn com.google.firebase.crashlytics.
+#-keepnames @kotlin.Metadata class com.sambath.cflive.remote.**
+#-keep class com.sambath.cflive.remote.model.** { *; }
+#-keepclassmembers class com.sambath.cflive.remote.model.** { *; }
+
+##---------------Begin: proguard configuration for Gson  ----------
+# Gson uses generic type information stored in a class file when working with fields. Proguard
+# removes such information by default, so configure it to keep all of it.
+-keepattributes Signature
+
+# For using GSON @Expose annotation
+-keepattributes *Annotation*
+
+# Gson specific classes
+-dontwarn sun.misc.**
+#-keep class com.google.gson.stream.** { *; }
+
+# Application classes that will be serialized/deserialized over Gson
+#-keep class com.google.gson.examples.android.model.** { <fields>; }
+-keep class com.sambath.kunkhmer.remote.** { <fields>; }
+
+
+# Prevent proguard from stripping interface information from TypeAdapter, TypeAdapterFactory,
+# JsonSerializer, JsonDeserializer instances (so they can be used in @JsonAdapter)
+-keep class * implements com.google.gson.TypeAdapter
+-keep class * implements com.google.gson.TypeAdapterFactory
+-keep class * implements com.google.gson.JsonSerializer
+-keep class * implements com.google.gson.JsonDeserializer
+
+# Prevent R8 from leaving Data object members always null
+-keepclassmembers,allowobfuscation class * {
+  @com.google.gson.annotations.SerializedName <fields>;
+}
+##---------------End: proguard configuration for Gson  ----------

+ 24 - 0
app/src/androidTest/java/com/sambath/kunkhmer/ExampleInstrumentedTest.kt

@@ -0,0 +1,24 @@
+package com.sambath.kunkhmer
+
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.ext.junit.runners.AndroidJUnit4
+
+import org.junit.Test
+import org.junit.runner.RunWith
+
+import org.junit.Assert.*
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+@RunWith(AndroidJUnit4::class)
+class ExampleInstrumentedTest {
+    @Test
+    fun useAppContext() {
+        // Context of the app under test.
+        val appContext = InstrumentationRegistry.getInstrumentation().targetContext
+        assertEquals("com.sambath.loto", appContext.packageName)
+    }
+}

+ 7 - 0
app/src/dev/java/com/sambath/kunkhmer/config/Config.kt

@@ -0,0 +1,7 @@
+package com.sambath.kunkhmer.config
+
+object Config {
+    //development
+    const val BASE_URL = "http://146.190.102.206:30827"
+    const val SOCKET_1 = "http://146.190.102.206:30827/namespace-kun-khmer"
+}

+ 60 - 0
app/src/main/AndroidManifest.xml

@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    package="com.sambath.kunkhmer">
+
+    <uses-permission android:name="android.permission.INTERNET" />
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.BLUETOOTH" />
+    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" tools:ignore="ScopedStorage" />
+
+    <application
+        android:name=".app.App"
+        android:allowBackup="false"
+        android:hardwareAccelerated="true"
+        android:icon="@mipmap/ic_launcher"
+        android:label="@string/app_name"
+        android:supportsRtl="true"
+        android:theme="@style/AppTheme"
+        android:usesCleartextTraffic="true"
+        android:networkSecurityConfig="@xml/network_security_config"
+        tools:targetApi="m">
+        <activity
+            android:name=".app.AdminActivity"
+            android:exported="false" />
+        <activity
+            android:name=".app.MainActivity"
+            android:exported="false" />
+        <activity
+            android:name=".screen.register.RegisterActivity"
+            android:exported="false" />
+        <activity
+            android:name=".app.ShareActivity"
+            android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation"
+            android:label="@string/app_name"
+            android:screenOrientation="sensorPortrait"
+            android:windowSoftInputMode="adjustResize" />
+        <activity
+            android:name=".screen.login.LoginActivity"
+            android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation"
+            android:label="@string/app_name"
+            android:screenOrientation="sensorPortrait"
+            android:windowSoftInputMode="adjustResize" />
+        <activity
+            android:name=".screen.splash.SplashScreenActivity"
+            android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation"
+            android:exported="true"
+            android:screenOrientation="sensorPortrait"
+            android:windowSoftInputMode="adjustResize">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+
+</manifest>

二进制
app/src/main/ic_launcher-playstore.png


+ 47 - 0
app/src/main/java/com/sambath/kunkhmer/adapter/AbstractAdapter.kt

@@ -0,0 +1,47 @@
+package com.gdtlib.lib.adapter
+
+import android.view.LayoutInflater
+import androidx.recyclerview.widget.RecyclerView
+import com.gdtlib.lib.viewholder.AbstractViewHolder
+
+/**
+ * An abstract class of [RecyclerView.Adapter] to display a list of [T]
+ */
+abstract class AbstractAdapter<T : Any>(
+    protected val inflater: LayoutInflater
+) : RecyclerView.Adapter<AbstractViewHolder<T>>(),
+    AbstractViewHolder.OnClickListener {
+
+    interface OnItemClickListener<T : Any> {
+        fun onItemClick(item: T)
+
+    }
+
+    var listener: OnItemClickListener<T>? = null
+
+    var list: List<T> = ArrayList()
+        set(value) {
+            if (field.isNotEmpty()) (field as ArrayList).clear()
+            (field as ArrayList).addAll(value)
+            notifyDataSetChanged()
+        }
+
+    fun addList(list: List<T>) {
+        if (list.isEmpty()) return
+        (this.list as ArrayList).addAll(list)
+        notifyDataSetChanged()
+    }
+
+    override fun getItemCount(): Int {
+        return list.size
+    }
+
+    override fun onBindViewHolder(holder: AbstractViewHolder<T>, position: Int) {
+        val user = list[position]
+        holder.bindView(user)
+    }
+
+    override fun onClick(position: Int) {
+        listener?.onItemClick(list[position])
+    }
+}

+ 23 - 0
app/src/main/java/com/sambath/kunkhmer/adapter/AbstractViewHolder.kt

@@ -0,0 +1,23 @@
+package com.gdtlib.lib.viewholder
+
+import android.view.View
+import androidx.recyclerview.widget.RecyclerView
+
+abstract class AbstractViewHolder<T : Any>(
+    view: View,
+    private val listener: OnClickListener?
+) : RecyclerView.ViewHolder(view){
+
+    init {
+        itemView.setOnClickListener {
+            listener?.onClick(adapterPosition)
+        }
+    }
+
+    interface OnClickListener {
+        fun onClick(position: Int)
+    }
+
+    abstract fun bindView(item: T)
+
+}

+ 31 - 0
app/src/main/java/com/sambath/kunkhmer/adapter/BaseListAdapter.kt

@@ -0,0 +1,31 @@
+package com.gdtlib.lib.adapter
+import androidx.recyclerview.widget.ListAdapter
+import androidx.recyclerview.widget.RecyclerView
+import com.gdtlib.lib.viewholder.BaseListViewHolder
+
+abstract class BaseListAdapter :
+  ListAdapter<BaseListItem, RecyclerView.ViewHolder>(
+    BaseListItem.ITEM_CALLBACK
+  ) {
+
+  private var itemClickListener: ((Int) -> Unit)? = null
+  private var loadMoreListener: (() -> Unit)? = null
+
+  fun setItemClickListener(itemClickListener: ((Int) -> Unit)?) {
+    this.itemClickListener = itemClickListener
+  }
+
+  fun setLoadMoreListener(loadMoreListener: (() -> Unit)?) {
+    this.loadMoreListener = loadMoreListener
+  }
+
+  override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
+    if (holder is BaseListViewHolder) {
+      holder.bindView(getItem(position))
+      holder.setClickListener(itemClickListener)
+      if (position >= itemCount - 1 - 2) {
+        loadMoreListener?.invoke()
+      }
+    }
+  }
+}

+ 17 - 0
app/src/main/java/com/sambath/kunkhmer/adapter/BaseListItem.kt

@@ -0,0 +1,17 @@
+package com.gdtlib.lib.adapter
+
+import android.annotation.SuppressLint
+import androidx.recyclerview.widget.DiffUtil
+
+abstract class BaseListItem {
+    companion object {
+        val ITEM_CALLBACK = object : DiffUtil.ItemCallback<BaseListItem>() {
+            override fun areItemsTheSame(oldItem: BaseListItem, newItem: BaseListItem) =
+                oldItem.getUnique() == newItem.getUnique()
+            @SuppressLint("DiffUtilEquals")
+            override fun areContentsTheSame(oldItem: BaseListItem, newItem: BaseListItem) =
+                oldItem == newItem
+        }
+    }
+    abstract fun getUnique(): String
+}

+ 49 - 0
app/src/main/java/com/sambath/kunkhmer/adapter/BaseListViewHolder.kt

@@ -0,0 +1,49 @@
+package com.gdtlib.lib.viewholder
+
+import android.view.View
+import androidx.recyclerview.widget.RecyclerView
+import com.gdtlib.lib.adapter.BaseListItem
+
+abstract class BaseListViewHolder(
+    itemView: View
+) : RecyclerView.ViewHolder(itemView) {
+
+    abstract fun bindView(item: BaseListItem)
+
+    fun setClickListener(clickListener: ((Int) -> Unit)?) {
+        if (clickListener != null) {
+            itemView.setOnClickListener {
+                clickListener(adapterPosition)
+            }
+        } else {
+            itemView.setOnClickListener(null)
+        }
+    }
+    companion object{
+        fun  getCurrency(currency: Int): String{
+            val short = currency/1000
+            return "${short}K"
+        }
+        fun getBettingId(playNo:String, playDate: String) : String {
+            val playID = playNo.subSequence(0,playNo.length-5)
+            val playTime = playDate.subSequence(playDate.length -8, playDate.length-3)
+            return "$playID $playTime"
+        }
+
+        fun getTypeOfBetting(type: String): String{
+            return when(type){
+                "Small" -> "U"
+                "Large" -> "O"
+                else -> type
+            }
+        }
+
+        fun convertToTypeOfBetting(type: String): String{
+            return when(type){
+                "U" -> "Small"
+                "O" -> "Large"
+                else -> type
+            }
+        }
+    }
+}

+ 56 - 0
app/src/main/java/com/sambath/kunkhmer/adapter/EventAdapter.kt

@@ -0,0 +1,56 @@
+package com.sambath.kunkhmer.adapter
+
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import android.widget.TextView
+import androidx.recyclerview.widget.RecyclerView
+import com.sambath.kunkhmer.R
+import com.sambath.kunkhmer.remote.EventInfo
+import com.squareup.picasso.Picasso
+import java.text.SimpleDateFormat
+import java.util.Locale
+import java.util.TimeZone
+
+class EventAdapter(var cardList: MutableList<EventInfo>) : RecyclerView.Adapter<EventAdapter.ViewHolder>() {
+
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): EventAdapter.ViewHolder {
+        val itemView = LayoutInflater.from(parent.context).inflate(R.layout.layout_event_item_card, parent, false)
+        return EventAdapter.ViewHolder(itemView)
+    }
+
+    override fun onBindViewHolder(holder: EventAdapter.ViewHolder, position: Int) {
+        val currentItem = cardList[position]
+
+        Picasso.get().load(R.drawable.default_background).into(holder.imageView)
+        holder.subTitleTextView.text = currentItem.eventInfoId.desc
+        holder.titleTextView.text = currentItem.eventInfoId.title
+        holder.dateTitleTextView.text = parseAndFormatDate(currentItem.eventInfoId.createdAt)
+    }
+
+    override fun getItemCount() = cardList.size
+
+    class ViewHolder(ItemView: View) : RecyclerView.ViewHolder(ItemView) {
+        val imageView: ImageView = itemView.findViewById(R.id.imageView)
+        val subTitleTextView: TextView = itemView.findViewById(R.id.subTitleTextView)
+        val titleTextView: TextView = itemView.findViewById(R.id.titleTextView)
+        val dateTitleTextView: TextView = itemView.findViewById(R.id.dateTitleTextView)
+    }
+
+    private fun parseAndFormatDate(dateString: String): String {
+        // Create a SimpleDateFormat for parsing the date string
+        val parser = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.getDefault())
+        parser.timeZone = TimeZone.getTimeZone("UTC")
+
+        // Parse the date
+        val date = parser.parse(dateString)
+
+        // Create a SimpleDateFormat for formatting the date
+        val formatter = SimpleDateFormat("dd MMM yyyy HH:mm", Locale.getDefault())
+        formatter.timeZone = TimeZone.getDefault() // Use local timezone
+
+        // Format the date
+        return formatter.format(date)
+    }
+}

+ 3 - 0
app/src/main/java/com/sambath/kunkhmer/adapter/EventCardItem.kt

@@ -0,0 +1,3 @@
+package com.sambath.kunkhmer.adapter
+
+data class EventCardItem(val imageResource: String, val title: String, val subTitle: String, val dateTitle: String)

+ 101 - 0
app/src/main/java/com/sambath/kunkhmer/adapter/FighterAdapter.kt

@@ -0,0 +1,101 @@
+package com.sambath.kunkhmer.adapter
+
+import android.graphics.Bitmap
+import android.graphics.BitmapFactory
+import android.util.Log
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import android.widget.TextView
+import androidx.recyclerview.widget.RecyclerView
+import com.sambath.kunkhmer.R
+import com.sambath.kunkhmer.adapter.FighterAdapter.ViewHolder
+import com.sambath.kunkhmer.config.Config
+import com.sambath.kunkhmer.remote.Fighters
+import com.sambath.kunkhmer.remote.Matches
+import com.sambath.kunkhmer.remote.service.ApiService
+import com.squareup.picasso.Picasso
+import io.reactivex.android.schedulers.AndroidSchedulers
+import io.reactivex.disposables.CompositeDisposable
+import io.reactivex.schedulers.Schedulers
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import okhttp3.ResponseBody
+import java.lang.Exception
+import java.text.SimpleDateFormat
+import java.util.Locale
+import java.util.TimeZone
+
+
+class FighterAdapter(private val cardList: List<Matches>, private val apiService: ApiService) : RecyclerView.Adapter<ViewHolder>() {
+    private val disposables = CompositeDisposable()
+
+    class CardViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
+
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+        val itemView = LayoutInflater.from(parent.context).inflate(R.layout.layout_fighter_card, parent, false)
+        return ViewHolder(itemView)
+    }
+
+    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+        val currentItem = cardList[position]
+
+        holder.imageLeftTitle.text = currentItem.fighters[0]?.name
+        Picasso.get()
+            .load(Config.BASE_URL + "/v1/fighter/image/" + currentItem.fighters[0].filename)
+            .placeholder(R.drawable.ic_logo_header)
+            .into(holder.imageLeft);
+
+        //------------------------------Right
+        try {
+            Picasso.get()
+                .load(Config.BASE_URL + "/v1/fighter/image/" + currentItem.fighters[1].filename)
+                .placeholder(R.drawable.ic_logo_header)
+                .into(holder.imageRight)
+        } catch (e: Exception) {
+            // Handle the exception, maybe log it or show a user-friendly error message
+            Log.e("ImageLoadError", "Error loading image", e)
+            // Optionally set a fallback image in case of error
+            Picasso.get()
+                .load(R.drawable.ic_logo_header)
+                .into(holder.imageRight)
+        }
+
+
+        //---------------------------------------
+
+        holder.date.text = currentItem.date
+        holder.title.text = currentItem.title
+    }
+
+    override fun getItemCount() = cardList.size
+
+    // Holds the views for adding it to image and text
+    inner class ViewHolder(ItemView: View) : RecyclerView.ViewHolder(ItemView) {
+        val imageLeft: ImageView = itemView.findViewById(R.id.imageLeft)
+        val imageLeftTitle: TextView = itemView.findViewById(R.id.titleLeft)
+        val imageRight: ImageView = itemView.findViewById(R.id.imageRight)
+        val imageRightTitle: TextView = itemView.findViewById(R.id.titleRight)
+        val date: TextView = itemView.findViewById(R.id.tvDate)
+        val title: TextView = itemView.findViewById(R.id.titleMatch)
+        val favorite: ImageView = itemView.findViewById(R.id.bookmarkToggleButton)
+    }
+
+    private fun parseAndFormatDate(dateString: String): String {
+        // Create a SimpleDateFormat for parsing the date string
+        val parser = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.getDefault())
+        parser.timeZone = TimeZone.getTimeZone("UTC")
+
+        // Parse the date
+        val date = parser.parse(dateString)
+
+        // Create a SimpleDateFormat for formatting the date
+        val formatter = SimpleDateFormat("dd MMM yyyy HH:mm", Locale.getDefault())
+        formatter.timeZone = TimeZone.getDefault() // Use local timezone
+
+        // Format the date
+        return formatter.format(date)
+    }
+}

+ 11 - 0
app/src/main/java/com/sambath/kunkhmer/adapter/FighterCardItem.kt

@@ -0,0 +1,11 @@
+package com.sambath.kunkhmer.adapter
+
+data class FighterCardItem(
+    val imageLeft: Int,
+    val imageLeftTitle: String,
+    val imageRight: Int,
+    val imageRightTitle: String,
+    val date: String,
+    val title: String,
+    var favorite: Boolean
+)

+ 77 - 0
app/src/main/java/com/sambath/kunkhmer/adapter/HighlightNewsAdapter.kt

@@ -0,0 +1,77 @@
+package com.sambath.kunkhmer.adapter
+
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import android.widget.TextView
+import androidx.recyclerview.widget.RecyclerView
+import com.sambath.kunkhmer.R
+import com.sambath.kunkhmer.remote.Highlight
+import com.squareup.picasso.Picasso
+import java.text.SimpleDateFormat
+import java.util.Locale
+import java.util.TimeZone
+
+class HighlightNewsAdapter (var cardList: MutableList<Highlight>, private val listener: OnItemClickListener) : RecyclerView.Adapter<HighlightNewsAdapter.ViewHolder>() {
+
+    interface OnItemClickListener {
+        fun onItemClick(position: Int)
+    }
+
+    class CardViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
+
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+        val itemView = LayoutInflater.from(parent.context)
+            .inflate(R.layout.layout_highlight_item_card, parent, false)
+        return ViewHolder(itemView)
+    }
+
+    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+        val currentItem = cardList[position]
+        val videoId = currentItem.url.substringAfterLast("/")
+        val thumbnailUrl = "https://img.youtube.com/vi/$videoId/0.jpg"
+
+        Picasso.get()
+            .load(thumbnailUrl)
+            .placeholder(R.drawable.ic_logo_header)
+            .into(holder.imageView);
+
+        holder.dateTextView.text = parseAndFormatDate(currentItem.date)
+        holder.titleTextView.text = currentItem.title
+    }
+
+    override fun getItemCount() = cardList.size
+
+    // Holds the views for adding it to image and text
+    inner class ViewHolder(ItemView: View) : RecyclerView.ViewHolder(ItemView) {
+        val imageView: ImageView = itemView.findViewById(R.id.imageView)
+        val dateTextView: TextView = itemView.findViewById(R.id.dateTextView)
+        val titleTextView: TextView = itemView.findViewById(R.id.titleTextView)
+
+        init {
+            itemView.setOnClickListener {
+                val position = adapterPosition
+                if (position != RecyclerView.NO_POSITION) {
+                    listener.onItemClick(position)
+                }
+            }
+        }
+    }
+
+    private fun parseAndFormatDate(dateString: String): String {
+        // Create a SimpleDateFormat for parsing the date string
+        val parser = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.getDefault())
+        parser.timeZone = TimeZone.getTimeZone("UTC")
+
+        // Parse the date
+        val date = parser.parse(dateString)
+
+        // Create a SimpleDateFormat for formatting the date
+        val formatter = SimpleDateFormat("dd MMM yyyy HH:mm", Locale.getDefault())
+        formatter.timeZone = TimeZone.getDefault() // Use local timezone
+
+        // Format the date
+        return formatter.format(date)
+    }
+}

+ 57 - 0
app/src/main/java/com/sambath/kunkhmer/adapter/LivesAdapter.kt

@@ -0,0 +1,57 @@
+package com.sambath.kunkhmer.adapter
+
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import android.widget.TextView
+import androidx.recyclerview.widget.RecyclerView
+import com.sambath.kunkhmer.R
+import com.sambath.kunkhmer.config.Config
+import com.sambath.kunkhmer.remote.LivesInfo
+import com.squareup.picasso.Picasso
+
+class LivesAdapter(var cardList: List<LivesInfo>, private val listener: OnItemClickListener) : RecyclerView.Adapter<LivesAdapter.ViewHolder>() {
+
+    interface OnItemClickListener {
+        fun onItemClick(position: Int)
+    }
+
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LivesAdapter.ViewHolder {
+        val itemView = LayoutInflater.from(parent.context).inflate(R.layout.layout_lives_item_card, parent, false)
+        return ViewHolder(itemView)
+    }
+
+    override fun onBindViewHolder(holder: LivesAdapter.ViewHolder, position: Int) {
+        val currentItem = cardList[position]
+
+        if(currentItem.filename == null) {
+            Picasso.get().load(R.drawable.default_background).into(holder.imageView)
+        } else {
+            Picasso.get()
+                .load(Config.BASE_URL + "/v1/live/image/" + currentItem.filename)
+                .error(R.drawable.default_background) // Set the default image resource
+                .into(holder.imageView)
+        }
+
+        holder.subTitleTextView.text = currentItem.desc
+        holder.titleTextView.text = currentItem.name
+    }
+
+    override fun getItemCount() = cardList.size
+
+    inner class ViewHolder(ItemView: View) : RecyclerView.ViewHolder(ItemView) {
+        val imageView: ImageView = itemView.findViewById(R.id.imageView)
+        val subTitleTextView: TextView = itemView.findViewById(R.id.subTitleTextView)
+        val titleTextView: TextView = itemView.findViewById(R.id.titleTextView)
+
+        init {
+            itemView.setOnClickListener {
+                val position = adapterPosition
+                if (position != RecyclerView.NO_POSITION) {
+                    listener.onItemClick(position)
+                }
+            }
+        }
+    }
+}

+ 3 - 0
app/src/main/java/com/sambath/kunkhmer/adapter/LivesCardItem.kt

@@ -0,0 +1,3 @@
+package com.sambath.kunkhmer.adapter
+
+data class LivesCardItem(val imageResource: String, val title: String, val subTitle: String)

+ 31 - 0
app/src/main/java/com/sambath/kunkhmer/adapter/MainPagerAdapter.kt

@@ -0,0 +1,31 @@
+package com.sambath.kunkhmer.adapter
+
+import androidx.appcompat.app.AppCompatActivity
+import androidx.fragment.app.Fragment
+import androidx.viewpager2.adapter.FragmentStateAdapter
+import com.sambath.kunkhmer.screen.main.cflive.currentbets.CurrentBetsFragment
+import com.sambath.kunkhmer.screen.main.cflive.todayreport.TodayReportFragment
+
+private val TAB_TITLES = arrayOf(
+    "Current Bets",
+    "Today Report",
+)
+class MainPagerAdapter(
+    var activity: AppCompatActivity
+) : FragmentStateAdapter(activity) {
+    override fun getItemCount(): Int {
+        return 2
+    }
+
+    override fun createFragment(position: Int): Fragment {
+        return when (position) {
+            0 -> {
+                CurrentBetsFragment.newInstance(position + 1)
+            }
+            1 -> {
+                TodayReportFragment.newInstance(position + 1)
+            }
+            else -> CurrentBetsFragment.newInstance(position + 1)
+        }
+    }
+}

+ 54 - 0
app/src/main/java/com/sambath/kunkhmer/adapter/ProductAdapter.kt

@@ -0,0 +1,54 @@
+package com.sambath.kunkhmer.adapter
+
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import android.widget.TextView
+import androidx.recyclerview.widget.RecyclerView
+import com.sambath.kunkhmer.R
+import com.sambath.kunkhmer.config.Config
+import com.sambath.kunkhmer.remote.ProductInfo
+import com.squareup.picasso.Picasso
+
+class ProductAdapter(var cardList: MutableList<ProductInfo>, private val listener: ProductAdapter.OnItemClickListener) : RecyclerView.Adapter<ProductAdapter.ViewHolder>() {
+    interface OnItemClickListener {
+        fun onItemClick(position: Int)
+    }
+
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ProductAdapter.ViewHolder {
+        val itemView = LayoutInflater.from(parent.context).inflate(R.layout.layout_product_item_card, parent, false)
+        return ViewHolder(itemView)
+    }
+
+    override fun onBindViewHolder(holder: ProductAdapter.ViewHolder, position: Int) {
+        val currentItem = cardList[position]
+
+        if(currentItem.filename == null) {
+            Picasso.get().load(R.drawable.default_background).into(holder.imageView)
+        } else {
+            Picasso.get().load(Config.BASE_URL + "/v1/product/image/" + currentItem.filename).into(holder.imageView)
+        }
+        holder.subTitleTextView.text = currentItem.desc
+        holder.titleTextView.text = currentItem.name
+        holder.priceTextView.text = "$" + currentItem.price
+    }
+
+    override fun getItemCount() = cardList.size
+
+    inner class ViewHolder(ItemView: View) : RecyclerView.ViewHolder(ItemView) {
+        val imageView: ImageView = itemView.findViewById(R.id.product_image)
+        val subTitleTextView: TextView = itemView.findViewById(R.id.product_desc)
+        val titleTextView: TextView = itemView.findViewById(R.id.product_title)
+        val priceTextView: TextView = itemView.findViewById(R.id.product_price)
+
+        init {
+            itemView.setOnClickListener {
+                val position = adapterPosition
+                if (position != RecyclerView.NO_POSITION) {
+                    listener.onItemClick(position)
+                }
+            }
+        }
+    }
+}

+ 3 - 0
app/src/main/java/com/sambath/kunkhmer/adapter/ProductCardItem.kt

@@ -0,0 +1,3 @@
+package com.sambath.kunkhmer.adapter
+
+data class ProductCardItem(val id: String, val imageResource: String, val title: String, val subTitle: String, val price: Double)

+ 73 - 0
app/src/main/java/com/sambath/kunkhmer/adapter/TopNewsAdapter.kt

@@ -0,0 +1,73 @@
+package com.sambath.kunkhmer.adapter
+
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import android.widget.TextView
+import androidx.recyclerview.widget.RecyclerView
+import com.sambath.kunkhmer.R
+import com.sambath.kunkhmer.config.Config
+import com.sambath.kunkhmer.remote.News
+import com.sambath.kunkhmer.remote.NewsData
+import com.squareup.picasso.Picasso
+import java.text.SimpleDateFormat
+import java.util.Locale
+import java.util.TimeZone
+
+class TopNewsAdapter(var cardList: MutableList<News>, private val itemClickListener: OnItemClickListener) : RecyclerView.Adapter<TopNewsAdapter.ViewHolder>() {
+    interface OnItemClickListener {
+        fun onItemClick(newsItem: News)
+    }
+
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+        val itemView = LayoutInflater.from(parent.context).inflate(R.layout.layout_top_news_item_card, parent, false)
+        return ViewHolder(itemView)
+    }
+
+    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+        val currentItem = cardList[position]
+        if (!currentItem.filename.isNullOrEmpty()) {
+            Picasso.get()
+                .load(Config.BASE_URL + "/v1/new/image/" + currentItem.filename)
+                .into(holder.imageView);
+        } else {
+            Picasso.get()
+                .load(R.drawable.ic_logo_header)
+                .into(holder.imageView);
+        }
+        holder.dateTextView.text = parseAndFormatDate(currentItem.createdAt)
+        holder.titleTextView.text = currentItem.title
+        holder.subTextView.text = currentItem.desc
+
+        holder.itemView.setOnClickListener{
+            itemClickListener.onItemClick(cardList[position])
+        }
+    }
+
+    override fun getItemCount() = cardList.size
+
+    // Holds the views for adding it to image and text
+    class ViewHolder(ItemView: View) : RecyclerView.ViewHolder(ItemView) {
+        val imageView: ImageView = itemView.findViewById(R.id.imageView)
+        val dateTextView: TextView = itemView.findViewById(R.id.dateTextView)
+        val titleTextView: TextView = itemView.findViewById(R.id.titleTextView)
+        val subTextView: TextView = itemView.findViewById(R.id.descTextView)
+    }
+
+    private fun parseAndFormatDate(dateString: String): String {
+        // Create a SimpleDateFormat for parsing the date string
+        val parser = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.getDefault())
+        parser.timeZone = TimeZone.getTimeZone("UTC")
+
+        // Parse the date
+        val date = parser.parse(dateString)
+
+        // Create a SimpleDateFormat for formatting the date
+        val formatter = SimpleDateFormat("dd MMM yyyy HH:mm", Locale.getDefault())
+        formatter.timeZone = TimeZone.getDefault() // Use local timezone
+
+        // Format the date
+        return formatter.format(date)
+    }
+}

+ 3 - 0
app/src/main/java/com/sambath/kunkhmer/adapter/TopNewsCardItem.kt

@@ -0,0 +1,3 @@
+package com.sambath.kunkhmer.adapter
+
+data class TopNewsCardItem(val imageResource: String, val title: String, val subTitle: String, val date: String)

+ 66 - 0
app/src/main/java/com/sambath/kunkhmer/adapter/TopNewsDetailAdapter.kt

@@ -0,0 +1,66 @@
+package com.sambath.kunkhmer.adapter
+
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import android.widget.TextView
+import androidx.recyclerview.widget.RecyclerView
+import com.sambath.kunkhmer.R
+import com.sambath.kunkhmer.config.Config
+import com.sambath.kunkhmer.remote.News
+import com.sambath.kunkhmer.remote.NewsDetail
+import com.squareup.picasso.Picasso
+import java.text.SimpleDateFormat
+import java.util.Locale
+import java.util.TimeZone
+
+class TopNewsDetailAdapter(var newsDetail: NewsDetail) : RecyclerView.Adapter<TopNewsDetailAdapter.ViewHolder>() {
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+        val itemView = LayoutInflater.from(parent.context).inflate(R.layout.layout_news_detail, parent, false)
+        return ViewHolder(itemView)
+    }
+
+    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+        val currentItem = newsDetail
+        if (currentItem.filename != null) {
+            Picasso.get()
+                .load(Config.BASE_URL + "/v1/new/image/" + currentItem.filename.filename)
+                .into(holder.imageView);
+        } else {
+            Picasso.get()
+                .load(R.drawable.ic_logo_header)
+                .into(holder.imageView);
+        }
+        if (!currentItem.createdAt.isNullOrEmpty())
+            holder.dateTextView.text = parseAndFormatDate(currentItem.createdAt)
+        holder.titleTextView.text = currentItem.title
+        holder.subTextView.text = currentItem.desc
+    }
+
+    override fun getItemCount() = 1
+
+    // Holds the views for adding it to image and text
+    class ViewHolder(ItemView: View) : RecyclerView.ViewHolder(ItemView) {
+        val imageView: ImageView = itemView.findViewById(R.id.imageView)
+        val dateTextView: TextView = itemView.findViewById(R.id.news_date)
+        val titleTextView: TextView = itemView.findViewById(R.id.news_title)
+        val subTextView: TextView = itemView.findViewById(R.id.news_desc)
+    }
+
+    private fun parseAndFormatDate(dateString: String): String {
+        // Create a SimpleDateFormat for parsing the date string
+        val parser = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.getDefault())
+        parser.timeZone = TimeZone.getTimeZone("UTC")
+
+        // Parse the date
+        val date = parser.parse(dateString)
+
+        // Create a SimpleDateFormat for formatting the date
+        val formatter = SimpleDateFormat("dd MMM yyyy HH:mm", Locale.getDefault())
+        formatter.timeZone = TimeZone.getDefault() // Use local timezone
+
+        // Format the date
+        return formatter.format(date)
+    }
+}

+ 40 - 0
app/src/main/java/com/sambath/kunkhmer/adapter/TopNewsHeaderAdapter.kt

@@ -0,0 +1,40 @@
+package com.sambath.kunkhmer.adapter
+
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import android.widget.TextView
+import androidx.recyclerview.widget.RecyclerView
+import com.sambath.kunkhmer.R
+import com.squareup.picasso.Picasso
+
+class TopNewsHeaderAdapter(private val cardList: List<TopNewsCardItem>) :
+    RecyclerView.Adapter<TopNewsHeaderAdapter.ViewHolder>() {
+    class CardViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
+
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+        val itemView = LayoutInflater.from(parent.context)
+            .inflate(R.layout.layout_top_news_header_item_card, parent, false)
+        return ViewHolder(itemView)
+    }
+
+    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+        val currentItem = cardList[position]
+
+        Picasso.get().load(currentItem.imageResource).into(holder.imageView)
+        holder.dateTextView.text = currentItem.date
+        holder.titleTextView.text = currentItem.title
+        holder.subTextView.text = currentItem.subTitle
+    }
+
+    override fun getItemCount() = cardList.size
+
+    // Holds the views for adding it to image and text
+    class ViewHolder(ItemView: View) : RecyclerView.ViewHolder(ItemView) {
+        val imageView: ImageView = itemView.findViewById(R.id.imageView)
+        val dateTextView: TextView = itemView.findViewById(R.id.dateTextView)
+        val titleTextView: TextView = itemView.findViewById(R.id.titleTextView)
+        val subTextView: TextView = itemView.findViewById(R.id.subTitleTextView)
+    }
+}

+ 26 - 0
app/src/main/java/com/sambath/kunkhmer/app/AdminActivity.kt

@@ -0,0 +1,26 @@
+package com.sambath.kunkhmer.app
+
+import androidx.appcompat.app.AppCompatActivity
+import android.os.Bundle
+import androidx.navigation.findNavController
+import androidx.navigation.ui.setupWithNavController
+import com.google.android.material.bottomnavigation.BottomNavigationView
+import com.sambath.kunkhmer.R
+import kotlinx.android.synthetic.main.app_bar_boxing.iv_account
+
+class AdminActivity : AppCompatActivity() {
+    lateinit var navView: BottomNavigationView
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        setContentView(R.layout.activity_admin)
+
+        navView =  findViewById<BottomNavigationView>(R.id.nav_view)
+        val navController = findNavController(R.id.nav_host_fragment_activity_main)
+        navView.setupWithNavController(navController)
+
+        iv_account.setOnClickListener{
+            findNavController(R.id.nav_host_fragment_activity_main).navigate(R.id.navigation_account)
+        }
+    }
+}

+ 116 - 0
app/src/main/java/com/sambath/kunkhmer/app/App.kt

@@ -0,0 +1,116 @@
+package com.sambath.kunkhmer.app
+
+import android.app.Application
+import android.content.Context
+import android.util.Log
+import com.itkacher.okhttpprofiler.OkHttpProfilerInterceptor
+import com.sambath.kunkhmer.config.Config
+import com.sambath.kunkhmer.BuildConfig
+import com.sambath.kunkhmer.remote.service.ApiService
+import com.sambath.kunkhmer.remote.service.SocketService
+import com.sambath.kunkhmer.util.*
+import com.squareup.moshi.Moshi
+import com.squareup.picasso.Picasso
+import okhttp3.OkHttpClient
+import retrofit2.CallAdapter
+import retrofit2.Converter
+import retrofit2.Retrofit
+import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
+import retrofit2.converter.moshi.MoshiConverterFactory
+import timber.log.Timber
+import java.util.concurrent.TimeUnit
+
+class App : Application() {
+    companion object {
+        private lateinit var retrofit: Retrofit
+        private lateinit var apiService: ApiService
+        private lateinit var socketService: SocketService
+        private lateinit var picasso: Picasso
+        private lateinit var shareViewModel: ShareViewModel
+        private lateinit var prefHelper: PrefHelper
+        var guidelineLeft: Float = 0f
+        var guidelineRight: Float = 100f
+        fun injectApiService() = apiService
+        fun injectShareViewModel() = shareViewModel
+        fun injectPrefHelper() = prefHelper
+        // Called on main activity create
+        fun onStartSocket(token: String, channelType: Int) {
+            Log.d("Socket", "token :: "+ token)
+            shareViewModel.startListenSocket(token, channelType)
+        }
+        // Called on main activity destroy
+        fun onAppStop() {
+            //Log.d("Socket", "onAppStop")
+            shareViewModel.stopListeningToSocketServer()
+        }
+    }
+
+    override fun onCreate() {
+        super.onCreate()
+        ModelPreferencesManager.with(this)
+        picasso = Picasso.Builder(this).loggingEnabled(true).build()
+        // FirebaseApp.initializeApp(this)
+        Picasso.setSingletonInstance(picasso)
+        if (BuildConfig.DEBUG) {
+            Timber.uprootAll()
+            Timber.plant(Timber.DebugTree())
+        }
+        val widthPx = screenRectPx.width()
+        val heightPx = screenRectPx.height()
+        val percentage = widthPx * 100 / heightPx
+        // Log.d("DATA", ""+widthPx)
+        // Log.d("DATA", ""+heightPx)
+        //  Log.d("DATA", ""+percentage)
+        when (percentage) {
+            in 30..54 -> {
+                guidelineLeft = 0f
+                guidelineRight = 1f
+            }
+            else -> {
+                guidelineLeft = 0.05f
+                guidelineRight = 0.95f
+            }
+        }
+        prefHelper = PrefHelper(context = appContext(this))
+        val builder = OkHttpClient.Builder()
+        if (BuildConfig.DEBUG) {
+            builder
+                .addInterceptor(ServiceInterceptor(prefHelper))
+                .addInterceptor(OkHttpProfilerInterceptor())
+                .addInterceptor(ErrorInterceptor(appContext(this), prefHelper))
+                .connectTimeout(180, TimeUnit.SECONDS)
+                .readTimeout(5, TimeUnit.MINUTES)
+                .writeTimeout(180, TimeUnit.SECONDS)
+
+        } else {
+            builder
+                .addInterceptor(ServiceInterceptor(prefHelper))
+                .addInterceptor(ErrorInterceptor(appContext(this), prefHelper))
+                .connectTimeout(180, TimeUnit.SECONDS)
+                .readTimeout(5, TimeUnit.MINUTES)
+                .writeTimeout(180, TimeUnit.SECONDS)
+        }
+        val client = builder.build()
+        retrofit = Retrofit.Builder()
+            .baseUrl(Config.BASE_URL)
+            .client(client)
+            .addCallAdapterFactory(callFactory())
+            .addConverterFactory(converterFactory(moshi()))
+            .build()
+        apiService = retrofit.create(ApiService::class.java)
+        socketService = SocketService()
+        //loginViewModel = LoginViewModel(apiService, prefHelper)
+        //settingViewModel = SettingViewModel(apiService, prefHelper)
+        shareViewModel = ShareViewModel(apiService, prefHelper, socketService)
+    }
+
+    private fun  callFactory(): CallAdapter.Factory = RxJava2CallAdapterFactory.create()
+    private fun converterFactory(moshi: Moshi): Converter.Factory =
+        MoshiConverterFactory.create(moshi).withNullSerialization()
+
+    private fun moshi(): Moshi = Moshi.Builder().build()
+
+    //fun unSafeOkHttpClient(): OkHttpClient = UnsafeOkHttpClient.getClient()
+    private fun appContext(app: App): Context = app
+    fun unSafeOkHttpClient(): OkHttpClient = UnsafeOkHttpClient.getClient()
+}

+ 41 - 0
app/src/main/java/com/sambath/kunkhmer/app/ErrorInterceptor.kt

@@ -0,0 +1,41 @@
+package com.sambath.kunkhmer.app
+
+import android.content.Context
+import android.content.Intent
+import com.sambath.kunkhmer.screen.login.LoginActivity
+import com.sambath.kunkhmer.util.PrefHelper
+import okhttp3.Interceptor
+import okhttp3.Request
+import okhttp3.Response
+
+class ErrorInterceptor(private val context: Context, private val prefHelper: PrefHelper) : Interceptor {
+    override fun intercept(chain: Interceptor.Chain): Response {
+
+        val request: Request = chain.request()
+        val response = chain.proceed(request)
+        when (response.code) {
+//            400 -> {
+//                //Show Bad Request Error Message
+//            }
+            401 -> {
+                //Show UnauthorizedError Message
+                    prefHelper.logout()
+                    val i =  Intent(context, LoginActivity::class.java)
+                    i.flags=Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK
+                    context.startActivity(i)
+            }
+
+//            403 -> {
+//                //Show Forbidden Message
+//            }
+//
+//            404 -> {
+//                //Show NotFound Message
+//            }
+
+            // ... and so on
+
+        }
+        return response
+    }
+}

+ 14 - 0
app/src/main/java/com/sambath/kunkhmer/app/ExceptionExtension.kt

@@ -0,0 +1,14 @@
+package com.sambath.kunkhmer.app
+
+import java.net.ConnectException
+import java.net.SocketTimeoutException
+import java.util.concurrent.TimeoutException
+
+fun Throwable.getErrorCode(): String {
+    return when (this) {
+        is SocketTimeoutException -> "[120]"
+        is ConnectException -> "[120]"
+        is TimeoutException -> "[121]"
+        else -> "[122]"
+    }
+}

+ 95 - 0
app/src/main/java/com/sambath/kunkhmer/app/MainActivity.kt

@@ -0,0 +1,95 @@
+package com.sambath.kunkhmer.app
+
+import android.Manifest
+import android.content.pm.PackageManager
+import androidx.appcompat.app.AppCompatActivity
+import android.os.Bundle
+import androidx.core.app.ActivityCompat
+import androidx.core.content.ContextCompat
+import androidx.navigation.findNavController
+import androidx.navigation.ui.AppBarConfiguration
+import androidx.navigation.ui.setupWithNavController
+import com.google.android.material.bottomnavigation.BottomNavigationView
+import com.sambath.kunkhmer.R
+import com.sambath.kunkhmer.remote.User
+import com.sambath.kunkhmer.screen.fighter.FighterFragment
+import com.sambath.kunkhmer.util.Const
+import com.sambath.kunkhmer.util.ModelPreferencesManager
+import kotlinx.android.synthetic.main.app_bar_boxing.iv_account
+
+class MainActivity : AppCompatActivity(), FighterFragment.TabSelectionListener {
+
+    lateinit var navView: BottomNavigationView
+    private lateinit var user: User
+
+    // Define a constant at the top of your class or in a companion object
+    companion object {
+        private const val STORAGE_PERMISSION_REQUEST_CODE = 123
+    }
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        setContentView(R.layout.activity_main2)
+
+        navView =  findViewById<BottomNavigationView>(R.id.nav_view)
+        val navController = findNavController(R.id.nav_host_fragment_activity_main)
+        val appBarConfiguration = AppBarConfiguration(
+            setOf(
+                R.id.navigation_home,
+                R.id.navigation_dashboard,
+                R.id.navigation_live,
+                R.id.navigation_event,
+                R.id.navigation_shop
+            )
+        )
+
+        //setupActionBarWithNavController(navController, appBarConfiguration)
+        navView.setupWithNavController(navController)
+
+        iv_account.setOnClickListener{
+            findNavController(R.id.nav_host_fragment_activity_main).navigate(R.id.navigation_account)
+        }
+
+        user = ModelPreferencesManager.get<User>(Const.USER_KEY)!!
+
+        if (ContextCompat.checkSelfPermission(
+                this,
+                Manifest.permission.WRITE_EXTERNAL_STORAGE
+            ) == PackageManager.PERMISSION_GRANTED
+        ) {
+            // Permission already granted, proceed with your logic
+        } else {
+            // Permission not granted, request it
+            ActivityCompat.requestPermissions(
+                this,
+                arrayOf(
+                    Manifest.permission.WRITE_EXTERNAL_STORAGE,
+                    Manifest.permission.READ_EXTERNAL_STORAGE
+                ),
+                STORAGE_PERMISSION_REQUEST_CODE
+            )
+        }
+    }
+
+    override fun onTabSelected(tabIndex: Int) {
+        val fragment = supportFragmentManager.findFragmentById(R.id.navigation_home)
+        if (fragment is FighterFragment) {
+            fragment.selectTab(tabIndex)
+        }
+    }
+
+    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
+        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
+        when (requestCode) {
+            STORAGE_PERMISSION_REQUEST_CODE -> {
+                // Check if the permission was granted
+                if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+                    // Permission granted, proceed with your logic
+                } else {
+                    // Permission denied, inform the user or take appropriate action
+                }
+            }
+            // Handle other permissions if needed
+        }
+    }
+}

+ 23 - 0
app/src/main/java/com/sambath/kunkhmer/app/ServiceInterceptor.kt

@@ -0,0 +1,23 @@
+package com.sambath.kunkhmer.app
+
+import com.sambath.kunkhmer.util.PrefHelper
+import okhttp3.Interceptor
+import okhttp3.Response
+
+class ServiceInterceptor(private val prefHelper: PrefHelper) : Interceptor {
+    override fun intercept(chain: Interceptor.Chain): Response {
+        var request = chain.request()
+        if (request.header("No-Authentication") == null) {
+            //or use Token Function
+            if (prefHelper.getToken().isNotEmpty()) {
+                val finalToken = prefHelper.getToken()
+                val channelType = prefHelper.getChannelType()
+                request = request.newBuilder()
+                    .addHeader("Authorization", finalToken)
+                    .addHeader("channel-type", channelType.toString())
+                    .build()
+            }
+        }
+        return chain.proceed(request)
+    }
+}

+ 373 - 0
app/src/main/java/com/sambath/kunkhmer/app/ShareActivity.kt

@@ -0,0 +1,373 @@
+package com.sambath.kunkhmer.app
+
+import android.content.DialogInterface
+import android.content.Intent
+import android.graphics.Color
+import android.os.Bundle
+import android.os.CountDownTimer
+import android.util.Log
+import android.view.MenuInflater
+import android.view.View
+import android.widget.ImageView
+import android.widget.LinearLayout
+import android.widget.TextView
+import android.widget.Toast
+import androidx.appcompat.app.AlertDialog
+import androidx.appcompat.widget.PopupMenu
+import androidx.constraintlayout.widget.Group
+import androidx.core.view.isVisible
+import androidx.lifecycle.Observer
+import com.google.gson.Gson
+import com.sambath.kunkhmer.R
+import com.sambath.kunkhmer.base.AutoLogoutBaseActivity
+import com.sambath.kunkhmer.remote.ChannelData
+import com.sambath.kunkhmer.remote.K
+import com.sambath.kunkhmer.remote.User
+import com.sambath.kunkhmer.remote.service.ConnectivityStates
+import com.sambath.kunkhmer.screen.login.LoginActivity
+import com.sambath.kunkhmer.screen.main.MainFragment
+import com.sambath.kunkhmer.screen.main.MainViewModel
+import com.sambath.kunkhmer.screen.splash.SplashScreenActivity
+import com.sambath.kunkhmer.util.Const
+import com.sambath.kunkhmer.util.ModelPreferencesManager
+import com.sambath.kunkhmer.util.PrefHelper
+import com.squareup.moshi.JsonAdapter
+import com.squareup.moshi.Moshi
+import kotlinx.android.synthetic.main.app_bar.*
+import kotlinx.android.synthetic.main.content_main.*
+import org.json.JSONObject
+
+
+class ShareActivity : AutoLogoutBaseActivity() {
+    lateinit var settingImageView: ImageView
+    lateinit var reportImageView: ImageView
+    private val gson = Gson()
+
+    //    lateinit var soundImageView: ImageView
+    lateinit var userNameTextView: TextView
+    lateinit var balanceTextView: TextView
+    lateinit var refreshImageView: ImageView
+    private lateinit var moshi: Moshi
+
+    //    private lateinit var remoteConfig: FirebaseRemoteConfig
+    lateinit var groupToolbarIcons: Group
+    lateinit var sharePref: PrefHelper
+    lateinit var layCfStatus: LinearLayout
+    lateinit var userShare: User
+    private var isOpen: String = "null"
+    private val shareViewModel = App.injectShareViewModel()
+    private lateinit var mainViewModel: MainViewModel
+    override fun onCreate(savedInstanceState: Bundle?) {
+//        Log.d("Oncreate", "before")
+        moshi = Moshi.Builder().build()
+        mainViewModel = MainViewModel(App.injectApiService(), App.injectPrefHelper())
+        ModelPreferencesManager.get<User>(Const.USER_KEY)?.let {
+            userShare = it
+        }
+        super.onCreate(savedInstanceState)
+        setContentView(R.layout.activity_main)
+//        val balance = currencyFormat(userShare.accountBalances)
+//        when (userShare.currencyType) {
+//            1 -> {//dollar
+//                tv_amount.text = "$balance $"
+//            }
+//            2 -> {//riel
+//                tv_amount.text ="$balance ៛"
+//            }
+//            3 -> {//baht
+//                tv_amount.text = "$balance ฿"
+//            }
+//        }
+        tv_user_id.text = userShare.userName
+        sharePref = App.injectPrefHelper()
+        mtxt_switch_channel.text = "CH" + sharePref.getChannelType()
+        txtStatus.text = "Status " + sharePref.getChannelType()
+        mainViewModel.getChannel()
+        mainViewModel.getUser()
+        mainViewModel.getCfResuleData()
+        mainViewModel.stateChannel.observe(this, androidx.lifecycle.Observer {
+            Log.d("stateChannel", it.toString())
+            if (it?.isChSuccess == true) {
+                it.channelInfo?.let { it1 -> getChannelData(it1) }
+            }
+        })
+//        mainViewModel.stateUser.observe(this, androidx.lifecycle.Observer {
+//            Log.d("stateUser", it.toString())
+//            if (it?.isUserSuccess == true) {
+//                it.userInfo?.let { it1 -> getUserInfo(it1) }
+//            }
+//        })
+        mainViewModel.state.observe(this, androidx.lifecycle.Observer {
+            if (it.isSuccess) {
+                if (it.resultList.isNullOrEmpty() || isOpen == "true") {
+                    txtWinner.text = "None"
+                } else {
+                    txtWinner.text = it.resultList!![0].name
+                }
+            }
+        })
+//        mainViewModel.getMainData()
+        //Log.d("Oncreate", "after")
+        if (savedInstanceState == null) {
+            supportFragmentManager.beginTransaction()
+                .add(
+                    R.id.container,
+                    MainFragment().apply {
+                        arguments =
+                            Bundle().apply {
+                                //putInt(InventoryFragment.COM_INTO_ID_KEY,10)
+                            }
+                    })
+                .addToBackStack(null)
+                .commit()
+        }
+        reportImageView = findViewById<ImageView>(R.id.iv_report)
+        settingImageView = findViewById<ImageView>(R.id.iv_setting)
+        refreshImageView = findViewById<ImageView>(R.id.iv_auto_new)
+        layCfStatus = findViewById<LinearLayout>(R.id.layCfStatus)
+        groupToolbarIcons = findViewById<Group>(R.id.group_toolbar_icons)
+        userNameTextView = findViewById<TextView>(R.id.tv_user_id)
+        balanceTextView = findViewById<TextView>(R.id.tv_amount)
+        mtxt_switch_channel.setOnClickListener { v ->
+            val popup = PopupMenu(this, v)
+            val inflater: MenuInflater = popup.menuInflater
+            inflater.inflate(R.menu.menu_channel, popup.menu)
+            popup.setOnMenuItemClickListener {
+                when (it.itemId) {
+                    R.id.action_channel_1 -> {
+                        sharePref.setChannelType(1)
+                        this.recreate()
+                    }
+                    R.id.action_channel_2 -> {
+                        sharePref.setChannelType(2)
+                        this.recreate()
+                    }
+                    R.id.action_channel_3 -> {
+                        sharePref.setChannelType(3)
+                        this.recreate()
+                    }
+                    R.id.action_channel_4 -> {
+                        sharePref.setChannelType(4)
+                        this.recreate()
+                    }
+
+                }
+                true
+            }
+            popup.show()
+        }
+        shareViewModel.getUpdateChannelInfo.observe(this, Observer {
+            Log.d("Socket", "getUpdateChannelInfo" + it.toString())
+            if (!it.isNullOrEmpty()) {
+                val adapter: JsonAdapter<ChannelData> = moshi.adapter(
+                    ChannelData::class.java
+                )
+                val channelDataResponse = adapter.fromJson(it)
+                if (channelDataResponse != null) {
+                    getChannelData(channelDataResponse)
+                }
+            }
+        })
+        shareViewModel.getDefinedResultAndChannel.observe(this, Observer {
+            Log.d("Socket", "getDefinedResultAndChannel" + it.toString())
+            if (!it.isNullOrEmpty()) {
+                val obj = JSONObject(it)
+                val resultArr = obj.getJSONArray("objCoResult")
+                if (resultArr.length() > 0) {
+                    txtWinner.text = resultArr.getJSONObject(0).getString("name")
+                } else {
+                    txtWinner.text = "None"
+                }
+            }
+        })
+//        shareViewModel.getUpdateUserInfo.observe(this, Observer {
+//            Log.d("Socket", "getUpdateUserInfo" + it.toString())
+//            if (!it.isNullOrEmpty()) {
+//                val obj = JSONObject(it)
+//                val balance = currencyFormat(obj.getInt("balance"))
+//                if (userShare.currencyType == 1){//dollar
+//                    tv_amount.text = "$$balance"
+//                }else if(userShare.currencyType == 2){//riel
+//                    tv_amount.text ="៛$balance"
+//                }else{//baht
+//                    tv_amount.text = "฿$balance"
+//                }
+//            }
+//        })
+        shareViewModel.getResult.observe(this, Observer {
+            Log.d("Socket", "getResult")
+            if (!it.isNullOrEmpty()) {
+                txtWinner.text = it
+            } else {
+                txtWinner.text = "None"
+            }
+        })
+    }
+
+    private fun alertMsgLogout() {
+        val alertDialog: AlertDialog.Builder = AlertDialog.Builder(this)
+        alertDialog.setTitle("Logout Alert!")//for set Title
+        alertDialog.setMessage("សូមទំនាក់ទំនងទៅកាន់ភ្នាក់ងាររបស់អ្នក!")// for Message
+        val alert = alertDialog.create()
+//        alertDialog.setNegativeButton(getString(R.string.ok)) { dialog, id ->
+//            timer.cancel()
+//            dialog.dismiss()
+//            logout()
+//        }
+        alert.setCanceledOnTouchOutside(false)
+        alert.setOnShowListener {
+            val timer = object : CountDownTimer(1500, 100) {
+                override fun onTick(millisUntilFinished: Long) {
+
+                }
+
+                override fun onFinish() {
+                    alert.dismiss()
+                    logout()
+                }
+            }
+            timer.start()
+        }
+        alert.show()
+        val negativeButton = alert.getButton(DialogInterface.BUTTON_NEGATIVE)
+        negativeButton.setTextColor(Color.RED)
+    }
+
+    private fun logout() {
+        sharePref.logout()
+        val intent = Intent(this, LoginActivity::class.java)
+        startActivity(intent)
+        finishAffinity()
+    }
+
+    override fun onWindowFocusChanged(hasFocus: Boolean) {
+        super.onWindowFocusChanged(hasFocus)
+        //Log.d("Window", "hase focus")
+        if (hasFocus) hideSystemUI()
+    }
+
+//    private fun getUserInfo(it: User) {
+//        Log.d("stateUser", it.toString())
+//        tv_amount.text = it.accountBalances?.let { it1 ->
+//            val balance = currencyFormat(it1)
+//            if (userShare.currencyType == 1){//dollar
+//                 "$$balance"
+//            }else if(userShare.currencyType == 2){//riel
+//                "៛$balance"
+//            }else{//baht
+//                "฿$balance"
+//            }
+//
+//        }
+//        btnBettingStatus.isActivated = true
+//    }
+
+    private fun getChannelData(it: ChannelData) {
+        Log.d("statechannel", it.toString())
+//        if (!it.enable) {
+//            Log.d("Socket", "enable false")
+//            alertMsgLogout()
+//        }
+        shareViewModel.setChannelInfo(it)
+        txtFightNo.text = it.fightNo.toString()
+        isOpen = it.is_open.toString()
+        btnBettingStatus.isActivated = true
+        when (isOpen) {
+            "null" -> {
+                btnBettingStatus.text = K.Live
+                btnBettingStatus.isEnabled = false
+                btnBettingStatus.isActivated = false
+            }
+            "true" -> {
+                txtWinner.text = "None"
+                btnBettingStatus.text = K.Open
+                btnBettingStatus.isEnabled = true
+            }
+            "false" -> {
+                btnBettingStatus.text = K.Close
+                btnBettingStatus.isEnabled = false
+            }
+        }
+        shareViewModel.getConnectivityStates.observe(this, Observer {
+            getSocketConnectionStatus(it)
+        })
+    }
+
+    private fun hideSystemUI() {
+        window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
+                // Set the content to appear under the system bars so that the
+                // content doesn't resize when the system bars hide and show.
+                or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
+                or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+                or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+                // Hide the nav bar and status bar
+                or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
+                or View.SYSTEM_UI_FLAG_FULLSCREEN)
+    }
+
+    private fun getSocketConnectionStatus(status: Int) {
+        when (status) {
+            ConnectivityStates.STATE_DISCONNECTED -> {
+                Log.d("Socket", "onDisconnect...")
+                val mStartActivity = Intent(this, SplashScreenActivity::class.java)
+                startActivity(mStartActivity)
+                System.exit(0)
+            }
+            ConnectivityStates.STATE_NOT_CONNECTED -> {
+                Log.d("Socket", "onNotconnected...")
+                Toast.makeText(this, "មិនអាចភ្ជាប់ទៅកាន់ម៉ាស៊ីនមេ!", Toast.LENGTH_LONG).show()
+            }
+            ConnectivityStates.STATE_RECONNECTING -> {
+                Log.d("Socket", "onReconnecting...")
+            }
+            ConnectivityStates.STATE_TIMEOUT -> {
+                Log.d("Socket", "onTimout...")
+                val intent = Intent(this, SplashScreenActivity::class.java)
+                startActivity(intent)
+                finishAffinity()
+            }
+            ConnectivityStates.STATE_CONNECTED -> {
+                Log.d("Socket", "onConnected...")
+//                shareViewModel.remoteMainScreenAPI(userId = user.id)
+            }
+        }
+
+    }
+
+    override fun onBackPressed() {
+        when (supportFragmentManager.backStackEntryCount) {
+            1 -> {
+                finish()
+            }
+            else -> {
+                groupToolbarIcons.isVisible = true
+                layCfStatus.isVisible = true
+                super.onBackPressed()
+            }
+        }
+    }
+
+    override fun onDestroy() {
+        // App.onAppStop()
+        super.onDestroy()
+        Log.d("Lifecycle", "onDestroy")
+    }
+
+    private var confirmDialog: AlertDialog? = null
+
+    override fun onPause() {
+        super.onPause()
+        App.onAppStop()
+        //Log.d("Lifecycle","onPause")
+    }
+
+    override fun onResume() {
+        super.onResume()
+        App.onStartSocket(sharePref.getToken(), sharePref.getChannelType())//userID = userShare.id)
+    }
+
+    override fun onUserInteraction() {
+        super.onUserInteraction()
+    }
+
+}

+ 163 - 0
app/src/main/java/com/sambath/kunkhmer/app/ShareViewModel.kt

@@ -0,0 +1,163 @@
+package com.sambath.kunkhmer.app
+
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import com.google.gson.Gson
+import com.sambath.kunkhmer.base.BaseViewModel
+import com.sambath.kunkhmer.remote.*
+import com.sambath.kunkhmer.remote.service.EventListener
+import com.sambath.kunkhmer.remote.service.ApiService
+import com.sambath.kunkhmer.remote.service.ConnectivityStates
+import com.sambath.kunkhmer.remote.service.SocketService
+import com.sambath.kunkhmer.util.PrefHelper
+import org.json.JSONObject
+import java.net.URISyntaxException
+
+class ShareViewModel(
+    private val apiService: ApiService,
+    private val prefHelper: PrefHelper,
+    private val socketService: SocketService
+) : BaseViewModel(), EventListener {
+    private val gson = Gson()
+
+    //Socket Data LiveData
+    private val newCreatedBetting = MutableLiveData<JSONObject>()
+    val getBettingCreated: LiveData<JSONObject> get() = newCreatedBetting
+
+    //Socket Connection Live Data
+    private val connectivityStateLD = MutableLiveData<Int>()
+    val getConnectivityStates: LiveData<Int> get() = connectivityStateLD
+
+    // Remote
+    fun startListenSocket(token: String, channelType: Int) {
+        try {
+            socketService.registerListener(this)
+            socketService.startListening(token, channelType)
+        } catch (e: URISyntaxException) {
+            e.printStackTrace()
+        }
+    }
+
+    fun emitCfCreateBetting(createBettingObject: JSONObject) {
+        socketService.startEmitCfCreateBetting(createBettingObject)
+    }
+
+    fun stopListeningToSocketServer() {
+        socketService.unregisterListener(this)
+        socketService.stopListening()
+    }
+
+    // Server callbacks
+
+    // Server callbacks
+    override fun onConnect() {
+        connectivityStateLD.postValue(ConnectivityStates.STATE_CONNECTED)
+    }
+
+    override fun onReconnectionTimeout() {
+        connectivityStateLD.postValue(ConnectivityStates.STATE_TIMEOUT)
+    }
+
+    override fun onConnectionError() {
+        connectivityStateLD.postValue(ConnectivityStates.STATE_NOT_CONNECTED)
+    }
+
+    override fun onReconnect() {
+        connectivityStateLD.postValue(ConnectivityStates.STATE_RECONNECTING)
+    }
+
+    override fun onDisconnect() {
+        connectivityStateLD.postValue(ConnectivityStates.STATE_DISCONNECTED)
+    }
+
+    private val fakeBetting = MutableLiveData<String>()
+    val getFakeBetting: LiveData<String> = fakeBetting
+
+    private val viewResult = MutableLiveData<String>()
+    val getViewResult: LiveData<String> = viewResult
+
+    private val infoBalanceBetting = MutableLiveData<String>()
+    val getInfoBalanceBetting: LiveData<String> = infoBalanceBetting
+
+    private val updateChanelDeveloper = MutableLiveData<String>()
+    val onUpdateChanelDeveloper: LiveData<String> = updateChanelDeveloper
+
+    private val summaryBetting = MutableLiveData<String>()
+    val getSummaryBetting: LiveData<String> = summaryBetting
+
+    private val updateChannelInfo = MutableLiveData<String>()
+    val getUpdateChannelInfo: LiveData<String> = updateChannelInfo
+    override fun onUpdateChannelInfo(data: String?) {
+        updateChannelInfo.postValue(data)
+    }
+
+    private val definedResultAndChannel = MutableLiveData<String>()
+    val getDefinedResultAndChannel: LiveData<String> = definedResultAndChannel
+    override fun onDefinedResultAndChannel(data: String?) {
+        definedResultAndChannel.postValue(data)
+    }
+
+    private val updateUserInfo = MutableLiveData<String>()
+    val getUpdateUserInfo: LiveData<String> = updateUserInfo
+    override fun onUpdateUserInfo(data: String?) {
+        updateUserInfo.postValue(data)
+    }
+
+    private val updateBettingAmount = MutableLiveData<String>()
+    val onUpdateBettingAmount: LiveData<String> = updateBettingAmount
+    override fun onUpdateBettingAmount(data: String?) {
+        updateBettingAmount.postValue(data)
+    }
+
+    private val updatePayout = MutableLiveData<String>()
+    val getUpdatePayout: LiveData<String> = updatePayout
+    override fun onUpdatePayout(data: String?) {
+        updatePayout.postValue(data)
+    }
+
+    private val reverseRseult = MutableLiveData<String>()
+    val onReverseRseult: LiveData<String> = reverseRseult
+    override fun onReverseRseult(data: String?) {
+        reverseRseult.postValue(data)
+    }
+
+    private val resetAmount = MutableLiveData<String>()
+    val getResetAmount: LiveData<String> = resetAmount
+    override fun onResetAmount(data: String?) {
+        resetAmount.postValue(data)
+    }
+
+    private val currentBetting = MutableLiveData<Boolean>()
+    val getUpdateFlagMain: LiveData<Boolean> get() = currentBetting
+    fun setUpdateFlagMain(isUpdate: Boolean) {
+        currentBetting.postValue(isUpdate)
+    }
+
+//    private val channel = MutableLiveData<ChannelData>()
+//    val getChannel: LiveData<ChannelData> get() = channel
+//
+//    fun setChannel(channelObj: ChannelData) {
+//        channel.postValue(channelObj)
+//    }
+
+    private val channelInfo = MutableLiveData<ChannelData>()
+    val getChannelInfo: LiveData<ChannelData> get() = channelInfo
+
+    fun setChannelInfo(channelObj: ChannelData) {
+        channelInfo.postValue(channelObj)
+    }
+
+    private val result = MutableLiveData<String>()
+    val getResult: LiveData<String> get() = result
+
+    fun setResult(res: String) {
+        result.postValue(res)
+    }
+
+    private val updateData = MutableLiveData<JSONObject>()
+    val getUpdateData: LiveData<JSONObject> get() = updateData
+
+    fun setUpdateData(channelObj: JSONObject) {
+        updateData.postValue(channelObj)
+    }
+}

+ 19 - 0
app/src/main/java/com/sambath/kunkhmer/app/ShareViewState.kt

@@ -0,0 +1,19 @@
+package com.sambath.kunkhmer.app
+
+import com.sambath.kunkhmer.remote.CurrentBetting
+import com.sambath.kunkhmer.remote.ListItem
+import com.sambath.kunkhmer.remote.Result
+import com.sambath.kunkhmer.util.Event
+
+data class ShareViewState(
+    val initial: Boolean = true,
+    val isProgress: Boolean = false,
+    val error: String? = null,
+    val myBettingId: String?=null,
+    val myBettingList: MutableList<ListItem> ?= null,
+    val result: Result?= null,
+    val nextNo: String ?= null,
+    val accountBalance: String ?= null,
+    var currentBetting: CurrentBetting?= null,
+    val isAutoPrint: Event<Boolean>? = null
+)

+ 45 - 0
app/src/main/java/com/sambath/kunkhmer/base/AutoLogoutBaseActivity.kt

@@ -0,0 +1,45 @@
+package com.sambath.kunkhmer.base
+
+import android.content.Intent
+import android.os.Bundle
+import com.sambath.kunkhmer.app.App
+import com.sambath.kunkhmer.screen.login.LoginActivity
+import com.sambath.kunkhmer.util.Const
+import com.sambath.kunkhmer.util.Const.Companion.DEFAULT_LOGOUT_TIME
+import com.sambath.kunkhmer.util.LogOutTimerUtil
+
+abstract class AutoLogoutBaseActivity(private val logoutTime: Int = DEFAULT_LOGOUT_TIME) : BaseActivity() {
+    private val sharePref = App.injectPrefHelper()
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        LogOutTimerUtil.isUserTimedOutLiveData
+            .observe(this, { isUserTimedOut ->
+                if (isUserTimedOut)
+                    logout()
+            })
+    }
+
+    override fun onResume() {
+        super.onResume()
+        if (LogOutTimerUtil.isUserTimedOutLiveData.value == false) {
+            Const.LOGOUT_TIME = logoutTime
+            LogOutTimerUtil.resetLogoutTimer(null, null)
+        }
+    }
+
+//    override fun onUserInteraction() {
+//        super.onUserInteraction()
+//        LogOutTimerUtil.resetLogoutTimer(null, null)
+//    }
+
+    private fun logout() {
+        LogOutTimerUtil.isUserTimedOutLiveData.postValue(false)     // Reset timeout flag for background mode
+        sharePref.logout()
+
+        val intent = Intent(this, LoginActivity::class.java)
+        intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
+        startActivity(intent)
+        finish()
+    }
+}

+ 54 - 0
app/src/main/java/com/sambath/kunkhmer/base/BaseActivity.kt

@@ -0,0 +1,54 @@
+package com.sambath.kunkhmer.base
+
+import android.os.Bundle
+import android.view.MenuItem
+import androidx.appcompat.app.AppCompatActivity
+import com.sambath.kunkhmer.R
+import java.text.DecimalFormat
+
+abstract class BaseActivity : AppCompatActivity() {
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        if (savedInstanceState == null) overridePendingTransition(
+            R.anim.slide_in,
+            R.anim.slide_out
+        )
+    }
+    fun currencyFormat(amount: Int): String? {
+        val formatter = DecimalFormat("#,###")
+        return formatter.format(amount)
+    }
+
+    fun currencyFormat(amount: Long): String? {
+        val formatter = DecimalFormat("#,###")
+        return formatter.format(amount)
+    }
+
+    fun currencyFormat(amount: Double): String? {
+        val formatter = DecimalFormat("#,###")
+        return formatter.format(amount)
+    }
+    override fun finish() {
+        super.finish()
+        overridePendingTransition(
+            R.anim.slide_in_exit,
+            R.anim.slide_out_exit
+        )
+    }
+
+    override fun onOptionsItemSelected(item: MenuItem): Boolean {
+        if (item.itemId == android.R.id.home) {
+            onBackPressed()
+            return true
+        }
+        return super.onOptionsItemSelected(item)
+    }
+
+    override fun onBackPressed() {
+        super.onBackPressed()
+        overridePendingTransition(
+            R.anim.slide_in_exit,
+            R.anim.slide_out_exit
+        )
+    }
+}

+ 97 - 0
app/src/main/java/com/sambath/kunkhmer/base/BaseFragment.kt

@@ -0,0 +1,97 @@
+package com.sambath.kunkhmer.base
+
+import android.animation.ValueAnimator
+import android.annotation.SuppressLint
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.TextView
+import androidx.annotation.LayoutRes
+import androidx.fragment.app.Fragment
+import com.sambath.kunkhmer.remote.LottoSet
+import com.sambath.kunkhmer.remote.User
+import com.sambath.kunkhmer.util.Const
+import com.sambath.kunkhmer.util.ModelPreferencesManager
+import java.text.DecimalFormat
+import java.text.SimpleDateFormat
+import java.util.*
+
+abstract class BaseFragment(
+    @LayoutRes private val layoutRes: Int
+) : Fragment() {
+    private lateinit var user: User
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        user = ModelPreferencesManager.get<User>(Const.USER_KEY)!!
+    }
+
+//    fun currencyType(): String {
+//        when (user.currencyType) {
+//            1 -> {//dollar
+//                return "$"
+//            }
+//
+//            2 -> {//riel
+//                return "៛"
+//            }
+//
+//            3 -> {//baht
+//                return "฿"
+//            }
+//        }
+//        return ""
+//    }
+
+    override fun onCreateView(
+        inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
+    ): View? {
+        return inflater.inflate(layoutRes, container, false)
+    }
+
+    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+        super.onViewCreated(view, savedInstanceState)
+    }
+
+    fun currencyFormat(amount: Int): String {
+        val formatter = DecimalFormat("#,###")
+        return formatter.format(amount)
+    }
+
+    fun currencyFormatKh(amount: Double): String? {
+        val formatter = DecimalFormat("#,###")
+        return formatter.format(amount)
+    }
+
+    @SuppressLint("SimpleDateFormat")
+    open fun formatShowDate(showDate: Date): String {
+        val formatter = SimpleDateFormat(("dd/MM/yyyy HH:mm:ss"))
+        return formatter.format(showDate)
+    }
+
+    fun findLottoSet(lottoSet: List<LottoSet>, type_of_betting: String): LottoSet {
+
+        return lottoSet.find { type_of_betting == it.typeOfBetting }!!
+    }
+
+    fun animateTextView(initialValue: Int, finalValue: Int, textview: TextView): ValueAnimator {
+        val valueAnimator = ValueAnimator.ofInt(initialValue, finalValue)
+        valueAnimator.duration = 50
+        valueAnimator.addUpdateListener { animator ->
+            textview.text = animator.animatedValue.toString()
+        }
+        valueAnimator.start()
+
+        return valueAnimator
+
+
+    }
+
+    private fun getLastFourChars(str: String, n: Int): String {
+        var lastChars = str
+        if (lastChars.length > n) {
+            lastChars = lastChars.substring(lastChars.length - n, lastChars.length)
+        }
+        return lastChars
+    }
+}

+ 13 - 0
app/src/main/java/com/sambath/kunkhmer/base/BaseViewModel.kt

@@ -0,0 +1,13 @@
+package com.sambath.kunkhmer.base
+
+import androidx.lifecycle.ViewModel
+import io.reactivex.disposables.CompositeDisposable
+
+
+abstract class BaseViewModel : ViewModel() {
+    protected val disposables = CompositeDisposable()
+    override fun onCleared() {
+        disposables.clear()
+        super.onCleared()
+    }
+}

+ 104 - 0
app/src/main/java/com/sambath/kunkhmer/extension/CurrentUserDataModel.kt

@@ -0,0 +1,104 @@
+package com.sambath.kunkhmer.extension
+
+import com.sambath.kunkhmer.remote.NewsDetail
+import com.sambath.kunkhmer.remote.NewsDetailData
+import com.sambath.kunkhmer.remote.ResponseMessage
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+@JsonClass(generateAdapter = true)
+data class CurrentUserResponse(
+    @Json(name = "code")
+    val resultCode: Int,
+    @Json(name = "message")
+    val message: ResponseMessage,
+    @Json(name = "data")
+    val data: CurrentUserData?
+)
+
+@JsonClass(generateAdapter = true)
+data class CurrentUserData(
+    @Json(name = "object")
+    val obj: CurrentUser,
+)
+
+@JsonClass(generateAdapter = true)
+data class CurrentUser(
+    @Json(name = "_id")
+    val id: String,
+
+    @Json(name = "socket_id")
+    val socket_id: String?,
+
+    @Json(name = "user_name")
+    val user_name: String,
+
+    @Json(name = "fist_name")
+    val fist_name: String,
+
+    @Json(name = "last_name")
+    val last_name: String,
+
+    @Json(name = "gender")
+    val gender: String,
+
+    @Json(name = "password")
+    val password: String,
+
+    @Json(name = "register_by")
+    val register_by: String,
+
+    @Json(name = "email_or_phone")
+    val email_or_phone: String,
+
+    @Json(name = "role")
+    val role: String,
+
+    @Json(name = "firebase_token")
+    val firebase_token: String,
+
+    @Json(name = "device_id")
+    val device_id: String,
+
+    @Json(name = "createdAt")
+    val createdAt: String,
+
+    @Json(name = "updatedAt")
+    val updatedAt: String,
+
+    @Json(name = "__v")
+    val _v: Int,
+
+    @Json(name = "file_id")
+    val file_id: FileId,
+)
+
+@JsonClass(generateAdapter = true)
+data class FileId(
+    @Json(name = "fieldname")
+    val fieldname: String,
+    @Json(name = "originalname")
+    val originalname: String,
+    @Json(name = "encoding")
+    val encoding: String,
+    @Json(name = "mimetype")
+    val mimetype: String,
+    @Json(name = "id")
+    val id: String,
+    @Json(name = "filename")
+    val filename: String,
+    @Json(name = "metadata")
+    val metadata: String?,
+    @Json(name = "bucketName")
+    val bucketName: String,
+    @Json(name = "chunkSize")
+    val chunkSize: Int,
+    @Json(name = "size")
+    val size: Int,
+    @Json(name = "md5")
+    val md5: String,
+    @Json(name = "uploadDate")
+    val uploadDate: String,
+    @Json(name = "contentType")
+    val contentType: String,
+)

+ 209 - 0
app/src/main/java/com/sambath/kunkhmer/extension/ViewExtensions.kt

@@ -0,0 +1,209 @@
+package com.sambath.kunkhmer.extension
+
+import android.graphics.drawable.AnimationDrawable
+import android.os.Handler
+import android.view.View
+import android.view.animation.AlphaAnimation
+import android.view.animation.Animation
+import android.view.animation.LinearInterpolator
+import android.view.animation.OvershootInterpolator
+import com.sambath.kunkhmer.util.SafeClickListener
+import io.reactivex.Completable
+import java.util.*
+
+fun View.showIf(show: Boolean) {
+    if (show) {
+        show()
+    } else {
+        hide()
+    }
+}
+
+fun View.show() {
+    this.visibility = View.VISIBLE
+}
+
+fun View.hide() {
+    this.visibility = View.INVISIBLE
+}
+
+fun View.slideIn(offset: Float): Completable {
+    return Completable.create {
+        visibility = View.VISIBLE
+        alpha = 0f
+        scaleX = 0f
+        scaleY = 0f
+        translationY = offset
+        animate().alpha(1f)
+            .translationY(0f)
+            .scaleX(1f)
+            .scaleY(1f)
+            .setDuration(200)
+            .setInterpolator(OvershootInterpolator())
+            .withEndAction(it::onComplete)
+    }
+}
+
+fun View.slideOut(offset: Float): Completable {
+    return Completable.create {
+        animate().alpha(0f)
+            .scaleX(0f)
+            .scaleY(0f)
+            .translationY(offset)
+            .setDuration(200)
+            .withEndAction {
+                visibility = View.INVISIBLE
+                it.onComplete()
+            }
+    }
+}
+
+fun View.fadeOut(duration: Long = 30): Completable {
+    return Completable.create {
+        animate().setDuration(duration)
+            .alpha(0f)
+            .withEndAction {
+                visibility = View.GONE
+                it.onComplete()
+            }
+    }
+}
+
+fun View.fadeIn(): Completable {
+    return Completable.create {
+        //visibility = View.VISIBLE
+        alpha = 0f
+        animate().alpha(1f)
+            .setDuration(200)
+            .withEndAction(it::onComplete)
+    }
+}
+
+fun View.rotate(degree: Float): Completable {
+    return Completable.create {
+        rotation=degree
+        animate().rotation(0f)
+            .setDuration(200)
+            .withEndAction(it::onComplete)
+    }
+}
+
+fun View.blink(degree: Float): Completable {
+    return Completable.create {
+        rotation=degree
+        animate().rotation(0f)
+            .setDuration(200)
+            .withEndAction(it::onComplete)
+    }
+}
+fun View.blink(
+    times: Int = Animation.INFINITE,
+    duration: Long = 150L,
+    offset: Long = 20L,
+    minAlpha: Float = 0.0f,
+    maxAlpha: Float = 1.0f,
+    repeatMode: Int = Animation.REVERSE
+) {
+    startAnimation(AlphaAnimation(minAlpha, maxAlpha).also {
+        it.duration = duration
+        it.startOffset = offset
+        it.repeatMode = repeatMode
+        it.repeatCount = times
+    })
+
+
+}
+
+
+fun View.zoomIn(): Completable {
+    return Completable.create {
+        //alpha = 0f
+        //pivotX = 0.5f
+       // pivotY = 0.5f
+        scaleX = 4f
+        scaleY = 4f
+        //translationY = 0f
+        //translationX = 0f
+        animate().alpha(1f)
+            //.translationY(0f)
+            //.translationX(0f)
+            .scaleX(1f)
+            .scaleY(1f)
+            .setDuration(200)
+            .setInterpolator(LinearInterpolator())
+            .withEndAction(it::onComplete)
+    }
+}
+fun View.waitingLotto(): Completable {
+    return Completable.create {
+//        alpha = 0f
+//        scaleX = 0.5f
+//        scaleY = 0f
+//        translationY = 0f
+//        translationX = 20f
+//        animate().alpha(1f)
+//            .translationY(0f)
+//            .translationX(0f)
+//            .scaleX(1f)
+//            .scaleY(1f)
+//            .setDuration(200)
+//            .setInterpolator(OvershootInterpolator())
+//            .withEndAction(it::onComplete)
+        alpha = 0f
+        animate().alpha(1f)
+            .setDuration(50)
+            .withEndAction(it::onComplete)
+    }
+}
+fun View.btnClick(): Completable {
+    return Completable.create {
+        //visibility = View.VISIBLE
+        alpha = 0f
+        animate().alpha(1f)
+            .setDuration(30)
+            .withEndAction(it::onComplete)
+    }
+}
+fun View.resultBlink(): Completable {
+    return Completable.create {
+        //visibility = View.VISIBLE
+        alpha = 0f
+        animate().alpha(1f)
+            .setDuration(200)
+            .withEndAction(it::onComplete)
+    }
+}
+fun View.randomResult(): Completable {
+    return Completable.create {
+        //visibility = View.VISIBLE
+        alpha = 0f
+        animate().alpha(1f)
+//            .also {
+//                val rdns = (1..80).random()
+//                tvNumber.text= "$rdns"
+//            }
+            .setDuration(5)
+            .withEndAction(it::onComplete)
+    }
+}
+fun AnimationDrawable.onAnimationFinished(block: () -> Unit) {
+    var duration: Long = 0
+    for (i in 0..numberOfFrames) {
+        duration += getDuration(i)
+    }
+    Handler().postDelayed({
+        block()
+    }, duration*5)
+}
+fun IntRange.random() = Random().nextInt((endInclusive + 1) - start) + start
+
+fun View.setSafeOnClickListener(onSafeClick: (View) -> Unit) {
+    val safeClickListener = SafeClickListener {
+        onSafeClick(it)
+    }
+    setOnClickListener(safeClickListener)
+}
+
+fun <T> MutableList<T>.prepend(element: T) {
+    add(0, element)
+}

+ 28 - 0
app/src/main/java/com/sambath/kunkhmer/remote/CfModel.kt

@@ -0,0 +1,28 @@
+package com.sambath.kunkhmer.remote
+
+import com.google.gson.annotations.SerializedName
+
+data class TodayReport(
+    @SerializedName("_id")
+    var id: String? = null,
+    @SerializedName("t_meron")
+    var fightBet: String? = null,
+    @SerializedName("t_meron_total")
+    var type: String? = null,
+    @SerializedName("r_wala_total")
+    var result: String? = null,
+    @SerializedName("r_wala")
+    var time: String? = null,
+){}
+data class CurrentBet(
+    @SerializedName("_id")
+    var id: String? = null,
+    @SerializedName("t_meron")
+    var fight: String? = null,
+    @SerializedName("r_wala")
+    var time: String? = null,
+    @SerializedName("t_meron_total")
+    var type: String? = null,
+    @SerializedName("r_wala_total")
+    var amount: String? = null,
+){}

+ 119 - 0
app/src/main/java/com/sambath/kunkhmer/remote/EventDataModel.kt

@@ -0,0 +1,119 @@
+package com.sambath.kunkhmer.remote
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+@JsonClass(generateAdapter = true)
+data class EventResponse(
+    @Json(name = "code")
+    val resultCode: Int,
+    @Json(name = "message")
+    val message: ResponseMessage,
+    @Json(name = "data")
+    val data: EventData?
+)
+
+@JsonClass(generateAdapter = true)
+data class EventData(
+    @Json(name = "object")
+    val obj: MutableList<EventInfo>,
+)
+
+@JsonClass(generateAdapter = true)
+data class EventInfo(
+    @Json(name = "_id")
+    val eventInfoId: EventInfoId,
+    @Json(name = "fighters")
+    val fighters: MutableList<EventInfoFighters>,
+)
+
+@JsonClass(generateAdapter = true)
+data class EventInfoId(
+    @Json(name = "_id")
+    val id: String,
+    @Json(name = "title")
+    val title: String,
+    @Json(name = "desc")
+    val desc: String,
+    @Json(name = "status")
+    val status: Boolean,
+    @Json(name = "fighter_id")
+    val fighterId: String,
+    @Json(name = "createdAt")
+    val createdAt: String,
+)
+
+@JsonClass(generateAdapter = true)
+data class EventInfoFighters(
+    @Json(name = "_id")
+    val id: String,
+    @Json(name = "name")
+    val name: String,
+    @Json(name = "desc")
+    val desc: String,
+    @Json(name = "weight")
+    val weight: String,
+    @Json(name = "high")
+    val height: String,
+    @Json(name = "nationality")
+    val nationality: String,
+    @Json(name = "status")
+    val status: Boolean,
+    @Json(name = "filename")
+    val filename: String,
+)
+
+////////
+
+@JsonClass(generateAdapter = true)
+class CreateEventRequest(
+    @Json(name = "title")
+    val title: String,
+    @Json(name = "desc")
+    val desc: String,
+    @Json(name = "match_fighter_id")
+    val matchFighterId: String
+)
+
+@JsonClass(generateAdapter = true)
+data class CreateEventResponse(
+    @Json(name = "code")
+    val resultCode: Int,
+    @Json(name = "message")
+    val message: ResponseMessage,
+    @Json(name = "data")
+    val data: EventCreatedData?
+)
+
+@JsonClass(generateAdapter = true)
+data class EventCreatedData(
+    @Json(name = "event")
+    val obj: CreatedEvent,
+)
+
+@JsonClass(generateAdapter = true)
+data class CreatedEvent(
+    @Json(name = "status")
+    val status: Boolean,
+
+    @Json(name = "_id")
+    val id: String,
+
+    @Json(name = "title")
+    val title: String,
+
+    @Json(name = "desc")
+    val desc: String,
+
+    @Json(name = "match_fighter_id")
+    val matchFighterId: String,
+
+    @Json(name = "createdAt")
+    val createdAt: String,
+
+    @Json(name = "updatedAt")
+    val updatedAt: String,
+
+    @Json(name = "__v")
+    val _v: Int,
+)

+ 218 - 0
app/src/main/java/com/sambath/kunkhmer/remote/FighterDataModel.kt

@@ -0,0 +1,218 @@
+package com.sambath.kunkhmer.remote
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+@JsonClass(generateAdapter = true)
+data class FighterResponse(
+    @Json(name = "code")
+    val resultCode: Int,
+    @Json(name = "message")
+    val message: ResponseMessage,
+    @Json(name = "data")
+    val data: FightersData?
+)
+
+@JsonClass(generateAdapter = true)
+data class FightersData(
+    @Json(name = "object")
+    val obj: List<FightersInfo>,
+)
+
+@JsonClass(generateAdapter = true)
+data class FightersInfo(
+    @Json(name = "file_id")
+    val fighterFile: FighterFile?,
+
+    @Json(name = "_id")
+    val id: String,
+    @Json(name = "name")
+    val name: String,
+    @Json(name = "desc")
+    val desc: String,
+    @Json(name = "weight")
+    val weight: String,
+    @Json(name = "high")
+    val height: String,
+    @Json(name = "nationality")
+    val nationality: String,
+    @Json(name = "createdAt")
+    val createdAt: String,
+    @Json(name = "updatedAt")
+    val updatedAt: String,
+    @Json(name = "__v")
+    val _v: Int,
+)
+
+@JsonClass(generateAdapter = true)
+data class FighterFile(
+    @Json(name = "fieldname")
+    val fieldName: String,
+    @Json(name = "originalname")
+    val originalName: String,
+//    @Json(name = "encoding")
+//    val encoding: String,
+    @Json(name = "mimetype")
+    val mimetype: String,
+    @Json(name = "id")
+    val id: String,
+    @Json(name = "filename")
+    val filename: String,
+//    @Json(name = "metadata")
+//    val metadata: String = "",
+//    @Json(name = "bucketName")
+//    val bucketName: String,
+//    @Json(name = "chunkSize")
+//    val chunkSize: Int,
+//    @Json(name = "size")
+//    val size: Int,
+//    @Json(name = "md5")
+//    val md5: String,
+//    @Json(name = "uploadDate")
+//    val uploadDate: String,
+//    @Json(name = "contentType")
+//    val contentType: String,
+)
+
+
+// ----------------- Match Data Model
+@JsonClass(generateAdapter = true)
+data class MatchesResponse(
+    @Json(name = "code")
+    val resultCode: Int,
+    @Json(name = "message")
+    val message: ResponseMessage,
+    @Json(name = "data")
+    val data: MatchesData?
+)
+
+@JsonClass(generateAdapter = true)
+data class ResponseMessage(
+    @Json(name = "code")
+    val code: String,
+    @Json(name = "description")
+    val description: String = "NA",
+)
+
+@JsonClass(generateAdapter = true)
+data class MatchesData(
+    @Json(name = "object")
+    val obj: List<Matches>,
+)
+
+@JsonClass(generateAdapter = true)
+data class Matches(
+    @Json(name = "_id")
+    val matchInfo: String,
+    @Json(name = "title")
+    val title: String,
+    @Json(name = "desc")
+    val desc: String,
+    @Json(name = "date")
+    val date: String,
+//    @Json(name = "fighterA")
+//    val fighterA: String? = "N/A",
+//    @Json(name = "fighterB")
+//    val fighterB: String? = "N/A",
+    @Json(name = "fighters")
+    val fighters: List<Fighters>,
+)
+
+@JsonClass(generateAdapter = true)
+data class MatchInfo(
+    @Json(name = "_id")
+    val id: String,
+    @Json(name = "desc")
+    val desc: String,
+    @Json(name = "date")
+    val date: String,
+    @Json(name = "title")
+    val title: String,
+    @Json(name = "createdAt")
+    val createdAt: String,
+)
+
+@JsonClass(generateAdapter = true)
+data class Fighters(
+    @Json(name = "_id")
+    val id: String,
+    @Json(name = "name")
+    val name: String,
+    @Json(name = "desc")
+    val desc: String,
+    @Json(name = "weight")
+    val weight: String,
+    @Json(name = "high")
+    val high: String,
+    @Json(name = "nationality")
+    val nationality: String,
+    @Json(name = "filename")
+    val filename: String,
+)
+
+//------------- Create Match Data Model
+
+@JsonClass(generateAdapter = true)
+class CreateMatchRequest(
+    @Json(name = "date")
+    val date: String,
+    @Json(name = "title")
+    val title: String,
+    @Json(name = "desc")
+    val desc: String,
+    @Json(name = "fighter_id")
+    val fighterId: List<String>
+)
+
+@JsonClass(generateAdapter = true)
+data class CreateMatchResponse(
+    @Json(name = "code")
+    val resultCode: Int,
+    @Json(name = "message")
+    val message: ResponseMessage,
+    //@Json(name = "data")
+    //val data: MatchCreatedData?
+)
+
+@JsonClass(generateAdapter = true)
+data class MatchCreatedData(
+    @Json(name = "match")
+    val obj: CreatedMatch,
+)
+
+@JsonClass(generateAdapter = true)
+data class CreatedMatch(
+    @Json(name = "desc")
+    val desc: String,
+
+    @Json(name = "fighter_id")
+    val fighterId: List<String>,
+
+    @Json(name = "_id")
+    val id: String,
+
+    @Json(name = "date")
+    val date: String,
+
+    @Json(name = "title")
+    val title: String,
+
+    @Json(name = "createdAt")
+    val createdAt: String,
+
+    @Json(name = "updatedAt")
+    val updatedAt: String,
+
+    @Json(name = "__v")
+    val _v: Int,
+)
+
+///
+
+@JsonClass(generateAdapter = true)
+data class CreateFighterResponse(
+    @Json(name = "code")
+    val resultCode: Int,
+    @Json(name = "message")
+    val message: ResponseMessage,
+)

+ 80 - 0
app/src/main/java/com/sambath/kunkhmer/remote/HighlightDataModel.kt

@@ -0,0 +1,80 @@
+package com.sambath.kunkhmer.remote
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+@JsonClass(generateAdapter = true)
+data class HighlightResponse(
+    @Json(name = "code")
+    val resultCode: Int,
+    @Json(name = "message")
+    val message: ResponseMessage,
+    @Json(name = "data")
+    val data: HighlightData?
+)
+
+@JsonClass(generateAdapter = true)
+data class  HighlightData(
+    @Json(name = "object")
+    val obj: MutableList<Highlight>,
+)
+
+@JsonClass(generateAdapter = true)
+data class Highlight(
+    @Json(name = "_id")
+    val id: String,
+    @Json(name = "title")
+    val title: String,
+    @Json(name = "date")
+    val date: String,
+    @Json(name = "url")
+    val url: String,
+    @Json(name = "createdAt")
+    val createdAt: String,
+)
+
+/////////
+
+@JsonClass(generateAdapter = true)
+class CreateHighlightRequest(
+    @Json(name = "title")
+    val title: String,
+    @Json(name = "date")
+    val date: String,
+    @Json(name = "url")
+    val url: String
+)
+
+@JsonClass(generateAdapter = true)
+data class CreateHighlightResponse(
+    @Json(name = "code")
+    val resultCode: Int,
+    @Json(name = "message")
+    val message: ResponseMessage,
+    @Json(name = "data")
+    val data: HighlightCreatedData?
+)
+
+@JsonClass(generateAdapter = true)
+data class HighlightCreatedData(
+    @Json(name = "highLight")
+    val obj: CreatedHighlight,
+)
+
+@JsonClass(generateAdapter = true)
+data class CreatedHighlight(
+    @Json(name = "_id")
+    val id: String,
+    @Json(name = "title")
+    val title: String,
+    @Json(name = "date")
+    val date: String,
+    @Json(name = "url")
+    val url: String,
+    @Json(name = "createdAt")
+    val createdAt: String,
+    @Json(name = "updatedAt")
+    val updatedAt: String,
+    @Json(name = "__v")
+    val _v: Int,
+)

+ 32 - 0
app/src/main/java/com/sambath/kunkhmer/remote/K.kt

@@ -0,0 +1,32 @@
+package com.sambath.kunkhmer.remote
+
+class K {
+    companion object{
+        const val Column = "column"
+        const val Fix_Column = "fix_column"
+        const val Fight_No = "fight_no"
+        const val TypeOfPlay = "type_of_play"
+        const val CirBlue = "cir-blue"
+        const val CirRed = "cir-red"
+        const val CirGreen = "cir-green"
+        const val CirCancel = "cir-cancel"
+        const val Open="Open"
+        const val Close = "Close"
+        const val Live = "Live"
+        const val CastRed = "cast_red"
+        const val CastBlue = "cast_blue"
+        const val PayoutRed = "payout_red"
+        const val PayoutBlue = "payout_blue"
+        const val Red = "red"
+        const val Blue = "blue"
+        const val Meron = "MERON"
+        const val Wala = "WALA"
+        const val Tie = "TIE"
+        const val Cancel = "CANCEl"
+        const val ChannelId = "_id"
+        const val TemId = "tem_id"
+        const val AmountRed = "amount_red"
+        const val AmountBlue = "amount_blue"
+        const val date = "date"
+    }
+}

+ 90 - 0
app/src/main/java/com/sambath/kunkhmer/remote/LivesDataModel.kt

@@ -0,0 +1,90 @@
+package com.sambath.kunkhmer.remote
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+@JsonClass(generateAdapter = true)
+data class LivesResponse(
+    @Json(name = "code")
+    val resultCode: Int,
+    @Json(name = "message")
+    val message: ResponseMessage,
+    @Json(name = "data")
+    val data: LivesData?
+)
+
+@JsonClass(generateAdapter = true)
+data class LivesData(
+    @Json(name = "object")
+    val obj: MutableList<LivesInfo>,
+)
+
+@JsonClass(generateAdapter = true)
+data class LivesInfo(
+    @Json(name = "_id")
+    val id: String,
+    @Json(name = "desc")
+    val desc: String,
+    @Json(name = "status")
+    val status: Boolean,
+    @Json(name = "fighter_id")
+    val fighterId: String,
+    @Json(name = "createdAt")
+    val createdAt: String,
+    @Json(name = "name")
+    val name: String,
+    @Json(name = "filename")
+    val filename: String,
+    @Json(name = "url")
+    val url: String,
+)
+
+//@JsonClass(generateAdapter = true)
+//data class LivesInfoId(
+//    @Json(name = "_id")
+//    val id: String,
+//    @Json(name = "status")
+//    val status: Boolean,
+//    @Json(name = "fighter_id")
+//    val fighterId: String,
+//    @Json(name = "createdAt")
+//    val createdAt: String,
+//)
+
+//@JsonClass(generateAdapter = true)
+//data class LiveInfoFighters(
+//    @Json(name = "_id")
+//    val id: String,
+//    @Json(name = "desc")
+//    val desc: String,
+//    @Json(name = "name")
+//    val name: String,
+//    @Json(name = "weight")
+//    val weight: String,
+//    @Json(name = "high")
+//    val height: String,
+//    @Json(name = "nationality")
+//    val nationality: String,
+//    @Json(name = "filename")
+//    val filename: String,
+//)
+
+///////////////////////////////////////
+
+@JsonClass(generateAdapter = true)
+class CreateLivesRequest(
+    @Json(name = "match_fighter_id")
+    val matchFighterId: String,
+    @Json(name = "status")
+    val status: Boolean,
+    @Json(name = "url")
+    val url: String,
+)
+
+@JsonClass(generateAdapter = true)
+data class CreateLivesResponse(
+    @Json(name = "code")
+    val resultCode: Int,
+    @Json(name = "message")
+    val message: ResponseMessage,
+)

+ 630 - 0
app/src/main/java/com/sambath/kunkhmer/remote/LoginDataModel.kt

@@ -0,0 +1,630 @@
+package com.sambath.kunkhmer.remote
+
+import com.gdtlib.lib.adapter.BaseListItem
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+@JsonClass(generateAdapter = true)
+class LoginRequest(
+    @Json(name = "user_name")
+    val username: String,
+    @Json(name = "password")
+    val password: String,
+    @Json(name = "firebase_token")
+    val firebaseToken: String = "OiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiN"
+)
+
+@JsonClass(generateAdapter = true)
+data class LoginResponse(
+    @Json(name = "code")
+    val resultCode: Int,
+    @Json(name = "message")
+    val message: LoginMessage,
+    @Json(name = "data")
+    val data: LoginData?
+)
+
+@JsonClass(generateAdapter = true)
+data class ChangePwd(
+    @Json(name = "old_password")
+    val oldPassword: String,
+    @Json(name = "new_password")
+    val newPassword: String
+)
+
+@JsonClass(generateAdapter = true)
+data class ChangePwdResponse(
+    @Json(name = "code")
+    val resultCode: String,
+    @Json(name = "message")
+    val message: LoginMessage
+)
+
+@JsonClass(generateAdapter = true)
+data class BettingResponse(
+    @Json(name = "code")
+    val resultCode: String,
+    @Json(name = "message")
+    val message: LoginMessage,
+    @Json(name = "data")
+    val data: BettingData ?= null
+)
+
+@JsonClass(generateAdapter = true)
+data class BettingData(
+    @Json(name = "_id")
+    val _id: String,
+    @Json(name = "fight_no")
+    val fightNo: Int,
+    @Json(name = "group_no")
+    val groupNo: Int,
+    @Json(name = "betting")
+    val betting: String,
+    @Json(name = "bet_color")
+    val bet_color: String,
+    @Json(name = "amount")
+    val amount: String,
+    @Json(name = "time")
+    val time: String,
+    @Json(name = "balance")
+    val balance: String,
+    @Json(name = "payout_wala")
+    val payoutWala: String,
+    @Json(name = "payout_meron")
+    val payoutMeron: String
+)
+
+@JsonClass(generateAdapter = true)
+data class CurrentBetData(
+    @Json(name = "amount")
+    val amount: String,
+    @Json(name = "bet_color")
+    val bet_color: String,
+    @Json(name = "betting")
+    val betting: String,
+    @Json(name = "fight_no")
+    val fightNo: Int,
+    @Json(name = "group_no")
+    val groupNo: Int,
+    @Json(name = "time")
+    val time: String,
+    @Json(name = "_id")
+    val _id: String,
+) : BaseListItem() {
+    override fun getUnique(): String = _id
+}
+
+@JsonClass(generateAdapter = true)
+data class CurrentResponse(
+    @Json(name = "code")
+    val resultCode: String,
+    @Json(name = "message")
+    val message: LoginMessage,
+    @Json(name = "data")
+    val data: List<CurrentBetData>
+)
+
+@JsonClass(generateAdapter = true)
+data class TodayResponse(
+    @Json(name = "code")
+    val resultCode: String,
+    @Json(name = "message")
+    val message: LoginMessage,
+    @Json(name = "data")
+    val data: List<TodayData>? = null
+)
+
+@JsonClass(generateAdapter = true)
+data class TodayData(
+    @Json(name = "amount")
+    val amount: String,
+    @Json(name = "bet_color")
+    val bet_color: String,
+    @Json(name = "betting")
+    val betting: String,
+    @Json(name = "fight_no")
+    val fightNo: Int,
+    @Json(name = "group_no")
+    val groupNo: Int,
+    @Json(name = "is_win")
+    val isWin: Boolean,
+    @Json(name = "result_color")
+    val resultColor: String,
+    @Json(name = "result_name")
+    val resultName: String,
+    @Json(name = "time")
+    val time: String,
+    @Json(name = "_id")
+    val _id: String,
+) : BaseListItem() {
+    override fun getUnique(): String = _id
+}
+
+@JsonClass(generateAdapter = true)
+data class BtnData(
+    @Json(name = "amount")
+    val amount: Int,
+    @Json(name = "currency_type")
+    val currencyType: Int,
+    @Json(name = "label")
+    val label: String,
+    @Json(name = "order")
+    val order: Int,
+    @Json(name = "_id")
+    val _id: String
+)
+
+@JsonClass(generateAdapter = true)
+data class ButtonResponse(
+    @Json(name = "code")
+    val resultCode: String,
+    @Json(name = "message")
+    val message: LoginMessage,
+    @Json(name = "data")
+    val data: List<BtnData>
+)
+
+@JsonClass(generateAdapter = true)
+data class ChannelResponse(
+    @Json(name = "code")
+    val resultCode: String,
+    @Json(name = "message")
+    val message: LoginMessage,
+    @Json(name = "data")
+    val data: ChannelData?
+)
+
+@JsonClass(generateAdapter = true)
+data class UserResponse(
+    @Json(name = "code")
+    val resultCode: String,
+    @Json(name = "message")
+    val message: LoginMessage,
+    @Json(name = "data")
+    val data: User?
+)
+
+@JsonClass(generateAdapter = true)
+data class WeightResponse(
+    @Json(name = "code")
+    val resultCode: String,
+    @Json(name = "message")
+    val message: LoginMessage,
+    @Json(name = "data")
+    val data: WeightData?
+)
+
+@JsonClass(generateAdapter = true)
+data class WeightData(
+    @Json(name = "wala")
+    val wala: Wala?,
+    @Json(name = "meron")
+    val meron: Meron?,
+    @Json(name = "amount_min")
+    val amountMin: Int,
+    @Json(name = "amount_max")
+    val amountMax: Int
+)
+
+@JsonClass(generateAdapter = true)
+data class Wala(
+    @Json(name = "payout")
+    val payout: String,
+    @Json(name = "amount")
+    val amount: String
+)
+
+@JsonClass(generateAdapter = true)
+data class Meron(
+    @Json(name = "payout")
+    val payout: String,
+    @Json(name = "amount")
+    val amount: String
+)
+
+@JsonClass(generateAdapter = true)
+data class BettingTypeResponse(
+    @Json(name = "code")
+    val resultCode: String,
+    @Json(name = "message")
+    val message: LoginMessage,
+    @Json(name = "data")
+    val data: List<BettingTypeData>
+)
+
+@JsonClass(generateAdapter = true)
+data class BettingTypeData(
+    @Json(name = "_id")
+    val _id: String,
+    @Json(name = "name")
+    val name: String,
+    @Json(name = "desc")
+    val desc: String,
+    @Json(name = "color")
+    val color: String,
+    @Json(name = "is_betting")
+    val isBetting: Boolean
+)
+
+@JsonClass(generateAdapter = true)
+data class ResultsResponse(
+    @Json(name = "code")
+    val resultCode: String,
+    @Json(name = "message")
+    val message: LoginMessage,
+    @Json(name = "data")
+    val data: ResultsData
+)
+
+@JsonClass(generateAdapter = true)
+data class ResultsData(
+    @Json(name = "results")
+    val results: List<Results>,
+    @Json(name = "summary")
+    val resultSummary: ResultSummary?,
+)
+
+@JsonClass(generateAdapter = true)
+data class Results(
+    @Json(name = "_id")
+    val _id: String,
+    @Json(name = "fight_no")
+    val fightNo: Int,
+    @Json(name = "name")
+    val name: String,
+    @Json(name = "cid")
+    val cid: Int,
+    @Json(name = "rid")
+    val rid: Int,
+    @Json(name = "color")
+    val color: String,
+)
+
+@JsonClass(generateAdapter = true)
+data class ResultSummary(
+    @Json(name = "MERON")
+    val meron: Int,
+    @Json(name = "WALA")
+    val wala: Int,
+    @Json(name = "TIE")
+    val tie: Int,
+    @Json(name = "CANCEL")
+    val cancel: Int
+)
+
+
+@JsonClass(generateAdapter = true)
+data class LoginMessage(
+    @Json(name = "code")
+    val code: String,
+    @Json(name = "description")
+    val description: String = "NA",
+)
+
+@JsonClass(generateAdapter = true)
+data class LoginData(
+    @Json(name = "user")
+    val user: User?,
+    @Json(name = "token")
+    val token: String?,
+)
+
+@JsonClass(generateAdapter = true)
+data class ChannelData(
+    @Json(name = "is_stop_video")
+    val isStopVideo: Boolean,
+    @Json(name = "enable")
+    val enable: Boolean,
+    @Json(name = "is_open")
+    val is_open: Boolean? = null,
+    @Json(name = "live_urls")
+    val liveUrls: List<String>?,
+    @Json(name = "_id")
+    val id: String,
+    @Json(name = "info")
+    val info: String,
+    @Json(name = "video_info")
+    val videoInfo: String,
+    @Json(name = "date")
+    val date: String,
+    @Json(name = "fight_no")
+    val fightNo: Int,
+    @Json(name = "group_no")
+    val groupNo: Int,
+    @Json(name = "column")
+    val column: Int,
+    @Json(name = "fix_column")
+    val fixColumn: Int,
+    @Json(name = "is_maintain")
+    val isMaintain: Boolean,
+    @Json(name = "maintain_desc")
+    val maintainDesc: String,
+    @Json(name = "__v")
+    val v: String?,
+)
+
+@JsonClass(generateAdapter = true)
+data class Limit(
+    @Json(name = "amount_min")
+    val amountMin: Int,
+
+    @Json(name = "amount_max")
+    val amountMax: Int,
+)
+
+@JsonClass(generateAdapter = true)
+data class LottoSet(
+    @Json(name = "_id")
+    var id: String,
+
+    @Json(name = "type_of_betting")
+    val typeOfBetting: String,
+
+    @Json(name = "start_number")
+    val startNumber: Int,
+
+    @Json(name = "end_number")
+    val endNumber: Int,
+
+    @Json(name = "payment")
+    val payment: Double,
+
+    @Json(name = "category")
+    val category: String,
+
+    @Json(name = "type")
+    val type: String
+
+)
+
+@JsonClass(generateAdapter = true)
+data class User(
+    @Json(name = "_id")
+    val id: String,
+    @Json(name = "user_name")
+    val userName: String,
+
+
+//    @Json(name = "role")
+//    val roles: String,
+//    @Json(name = "enable")
+//    val readOnly: Boolean,
+//    @Json(name = "account_info")
+//    var accountInfo: String?,
+//    @Json(name = "account_name")
+//    var accountName: String?,
+//    @Json(name = "account_number")
+//    var accountNumber: String?,
+//    @Json(name = "balance")
+//    val accountBalances: Double,
+//    @Json(name = "currency_type")
+//    val currencyType: Int,
+)
+
+@JsonClass(generateAdapter = true)
+data class NewPassword(
+    @Json(name = "new_password")
+    var newPassword: String,
+)
+
+@JsonClass(generateAdapter = true)
+data class ReportOneResponse(
+    @Json(name = "code")
+    val resultCode: String,
+    @Json(name = "message")
+    val message: LoginMessage,
+    @Json(name = "data")
+    val data: ReportOneData
+)
+
+@JsonClass(generateAdapter = true)
+data class ReportDepositResponse(
+    @Json(name = "code")
+    val resultCode: String,
+    @Json(name = "message")
+    val message: LoginMessage,
+    @Json(name = "data")
+    val data: ReportDepositData
+)
+
+@JsonClass(generateAdapter = true)
+data class ReportWithdrawResponse(
+    @Json(name = "code")
+    val resultCode: String,
+    @Json(name = "message")
+    val message: LoginMessage,
+    @Json(name = "data")
+    val data: ReportWithdrawData
+)
+
+@JsonClass(generateAdapter = true)
+data class ReportDepositData(
+    @Json(name = "rows_per_page")
+    val rowsPerPage: Int,
+    @Json(name = "total_rows")
+    val totalRows: Int,
+    @Json(name = "page")
+    val page: Int,
+    @Json(name = "total_amount")
+    val totalAmount: String,
+    @Json(name = "total_pages")
+    val totalPages: Int,
+    @Json(name = "reports")
+    val reports: List<ReportDeposit>
+)
+
+@JsonClass(generateAdapter = true)
+data class ReportDeposit(
+    @Json(name = "_id")
+    val _id: String,
+    @Json(name = "date")
+    val date: String,
+    @Json(name = "amount")
+    val amount: String,
+    @Json(name = "old_balance")
+    val oldBalance: String,
+    @Json(name = "new_balance")
+    val newBalance: String
+): BaseListItem(){
+    override fun getUnique(): String = _id
+}
+
+@JsonClass(generateAdapter = true)
+data class ReportWithdrawData(
+    @Json(name = "rows_per_page")
+    val rowsPerPage: Int,
+    @Json(name = "total_rows")
+    val totalRows: Int,
+    @Json(name = "page")
+    val page: Int,
+    @Json(name = "total_amount")
+    val totalAmount: String,
+    @Json(name = "total_pages")
+    val totalPages: Int,
+    @Json(name = "reports")
+    val reports: List<ReportWithdraw>
+)
+
+@JsonClass(generateAdapter = true)
+data class ReportWithdraw(
+    @Json(name = "_id")
+    val _id: String,
+    @Json(name = "date")
+    val date: String,
+    @Json(name = "amount")
+    val amount: String,
+    @Json(name = "old_balance")
+    val oldBalance: String,
+    @Json(name = "new_balance")
+    val newBalance: String
+): BaseListItem(){
+    override fun getUnique(): String = _id
+}
+
+@JsonClass(generateAdapter = true)
+data class ReportBody(
+    @Json(name = "rows_per_page")
+    val rowsPerPage: Int,
+    @Json(name = "page")
+    val page: Int,
+    @Json(name = "start_date")
+    val startDate: String,
+    @Json(name = "end_date")
+    val endDate: String
+)
+
+@JsonClass(generateAdapter = true)
+data class ReportOneData(
+    @Json(name = "rows_per_page")
+    val rowsPerPage: Int,
+    @Json(name = "total_rows")
+    val totalRows: Int,
+    @Json(name = "page")
+    val page: Int,
+    @Json(name = "total_pages")
+    val totalPages: Int,
+    @Json(name = "is_win")
+    val isWin: Boolean,
+    @Json(name = "turn_over")
+    val turnOver: String,
+    @Json(name = "amount_win_lose")
+    val amountWinLose: String,
+    @Json(name = "reports")
+    val reports: List<ReportOne>
+)
+
+@JsonClass(generateAdapter = true)
+data class ReportOne(
+    @Json(name = "_id")
+    val _id: String,
+    @Json(name = "date")
+    val date: String,
+    @Json(name = "payout")
+    val payout: String,
+    @Json(name = "group")
+    val group: Int,
+    @Json(name = "fight_no")
+    val fightNo: Int,
+    @Json(name = "bet_name")
+    val betName: String,
+    @Json(name = "bet_color")
+    val betColor: String,
+    @Json(name = "is_win")
+    val is_win: Boolean? = null,
+    @Json(name = "result_name")
+    val resultName: String,
+    @Json(name = "result_color")
+    val resultColor: String,
+    @Json(name = "amount_win")
+    val amountWin: Int,
+    @Json(name = "amount")
+    val amount: Int,
+    @Json(name = "cast")
+    val cast: Int
+): BaseListItem(){
+    override fun getUnique(): String = _id
+}
+
+@JsonClass(generateAdapter = true)
+data class ReportTwoResponse(
+    @Json(name = "code")
+    val resultCode: String,
+    @Json(name = "message")
+    val message: LoginMessage,
+    @Json(name = "data")
+    val data: ReportTwoData
+)
+
+@JsonClass(generateAdapter = true)
+data class ReportTwoData(
+    @Json(name = "rows_per_page")
+    val rowsPerPage: Int,
+    @Json(name = "total_rows")
+    val totalRows: Int,
+    @Json(name = "page")
+    val page: Int,
+    @Json(name = "total_pages")
+    val totalPages: Int,
+    @Json(name = "results")
+    val results: List<ReportTwo>
+)
+
+@JsonClass(generateAdapter = true)
+data class ReportTwo(
+    @Json(name = "_id")
+    val _id: String,
+    @Json(name = "date")
+    val date: String,
+    @Json(name = "name")
+    val name: String?,
+    @Json(name = "color")
+    val color: String?,
+    @Json(name = "group_no")
+    val group: Int,
+    @Json(name = "fight_no")
+    val fightNo: Int
+): BaseListItem(){
+    override fun getUnique(): String = _id
+}
+
+@JsonClass(generateAdapter = true)
+data class ReportThreeResponse(
+    @Json(name = "code")
+    val resultCode: String,
+    @Json(name = "message")
+    val message: LoginMessage,
+    @Json(name = "data")
+    val data: List<ReportThree>
+)
+
+@JsonClass(generateAdapter = true)
+data class ReportThree(
+    @Json(name = "date")
+    val date: String,
+    @Json(name = "amount")
+    val amount: Int,
+    @Json(name = "type")
+    val type: String
+): BaseListItem(){
+    override fun getUnique(): String = date
+}

+ 415 - 0
app/src/main/java/com/sambath/kunkhmer/remote/MainDataModel.kt

@@ -0,0 +1,415 @@
+package com.sambath.kunkhmer.remote
+
+import com.gdtlib.lib.adapter.BaseListItem
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+@JsonClass(generateAdapter = true)
+data class MainResponse(
+    @Json(name = "code")
+    val resultCode: String,
+    @Json(name = "message")
+    val message: MainMessage,
+    @Json(name = "data")
+    val data: MainData?
+)
+
+@JsonClass(generateAdapter = true)
+data class CfMainResponse(
+    @Json(name = "code")
+    val resultCode: String,
+    @Json(name = "message")
+    val message: MainMessage,
+    @Json(name = "data")
+    val data: CfMainData?
+)
+
+@JsonClass(generateAdapter = true)
+data class MainMessage(
+    @Json(name = "code")
+    val code: String,
+
+    @Json(name = "descriptions")
+    val description: String
+
+)
+
+@JsonClass(generateAdapter = true)
+data class CfMainData(
+    @Json(name = "userInfo")
+    val userInfo: UserInfo,
+    @Json(name = "chanel")
+    val channel: Channel,
+    @Json(name = "lastResult")
+    val lastResult: LastResult?
+)
+
+@JsonClass(generateAdapter = true)
+data class LastResult(
+    @Json(name = "_id")
+    val id: String,
+    @Json(name = "user_id")
+    val user_id: String,
+    @Json(name = "chanel_id")
+    val channelId: String,
+    @Json(name = "fight_no")
+    val fightNo: String,
+    @Json(name = "type_betting")
+    val typeBetting: String,
+    @Json(name = "date")
+    val date: String,
+    @Json(name = "no")
+    val no: String,
+    @Json(name = "color")
+    val color: String,
+    @Json(name = "cid")
+    val cid: String,
+    @Json(name = "rid")
+    val rid: String,
+    @Json(name = "group")
+    val group: String
+)
+@JsonClass(generateAdapter = true)
+data class MainData(
+    @Json(name = "userInfo")
+    val userInfo: UserInfo,
+    @Json(name = "chanel")
+    val channel: Channel,
+
+//below will clear soon
+    @Json(name = "accountBalances")
+    val accountBalance: String,
+    @Json(name = "newResult")
+    val nextNo: String?,
+    @Json(name = "currentResult")
+    val result: Result?,
+    @Json(name = "currentBetting")
+    val myBetting: MyBetting?
+)
+
+@JsonClass(generateAdapter = true)
+data class UserInfo(
+    @Json(name = "account_info")
+    val accountInfo: String?,
+    @Json(name = "account_name")
+    val accountName: String?,
+    @Json(name = "account_number")
+    val accountNumber: Int?,
+    @Json(name = "balance")
+    val balance: Long,
+    @Json(name = "currency_type")
+    val currencyType: String,
+    @Json(name = "enable")
+    val enable: Boolean,
+    @Json(name = "role")
+    val role: String,
+    @Json(name = "user_name")
+    val userName: String
+)
+
+@JsonClass(generateAdapter = true)
+data class Channel(
+    @Json(name = "_id")
+    val id: String,
+    @Json(name = "tem_id")
+    val temId: String,
+    @Json(name = "name")
+    val name: String,
+    @Json(name = "status")
+    val status: String,
+    @Json(name = "info")
+    val info: String,
+    @Json(name = "date")
+    val date: String,
+    @Json(name = "type_of_play")
+    val typeOfPlay: String,
+    @Json(name = "fight_no")
+    val fightNo: Int,
+    @Json(name = "group")
+    val group: Int,
+    @Json(name = "amount_red")
+    val amountRed: Int,
+    @Json(name = "payout_red")
+    val payoutRed: Double,
+    @Json(name = "cast_red")
+    val castRed: Long,
+    @Json(name = "amount_equal")
+    val amountEqual: Int,
+    @Json(name = "payout_equal")
+    val payoutEqual: Int,
+    @Json(name = "cast_equal")
+    val castEqual: Int,
+    @Json(name = "amount_blue")
+    val amountBlue: Int,
+    @Json(name = "payout_blue")
+    val payoutBlue: Double,
+    @Json(name = "cast_blue")
+    val castBlue: Long,
+    @Json(name = "weigh_red_blue")
+    val weighRedBlue: Int,
+    @Json(name = "column")
+    val column: Int,
+    @Json(name = "fix_column")
+    val fixColumn: Int,
+    @Json(name = "target")
+    val target: Long,
+    @Json(name = "amount_min")
+    val amountMin: Int,
+    @Json(name = "amount_max")
+    val amountMax: Int,
+) {
+    override fun toString(): String {
+        return "{_id: ${this.id}, tem_id: ${this.temId}, name: ${this.name}, status: ${this.status}, info: ${this.info}, date: ${this.date}, type_of_play: ${this.typeOfPlay}, fight_no: ${this.fightNo}, " +
+                "group: ${this.group}, amount_red: ${this.amountRed}, payout_red: ${this.payoutRed}, cast_red: ${this.castRed}, amount_equal: ${this.amountEqual}, payout_equal: ${this.payoutEqual}, castEqual: ${this.castEqual}, amountBlue: ${this.amountBlue}, " +
+                "payout_blue: ${this.payoutBlue}, cast_blue: ${this.castBlue}, weigh_red_blue: ${this.weighRedBlue}, column: ${this.column}, fix_column: ${this.fixColumn}, target: ${this.target}, amount_min: ${this.amountMin}, amount_max: ${this.amountMax}}"
+    }
+}
+
+@JsonClass(generateAdapter = true)
+data class MyBetting(
+    @Json(name = "_id")
+    var id: String?,
+
+    @Json(name = "tem_id")
+    val data: List<ListItem>?
+)
+
+@JsonClass(generateAdapter = true)
+data class ListItem(
+    @Json(name = "_id")
+    var id: String,
+
+    @Json(name = "set_result_id")
+    var setId: String,
+
+    @Json(name = "type_of_betting")
+    val typeOfBetting: String,
+
+    @Json(name = "category")
+    val category: String,
+
+    @Json(name = "user_id")
+    val user_id: String,
+
+    @Json(name = "date")
+    val date: String,
+
+    @Json(name = "amount")
+    val amount: String,
+
+    @Json(name = "cast")
+    val cast: String,
+
+    @Json(name = "win_lose")
+    val win_lose: String?,
+
+    @Json(name = "amount_win")
+    val amount_win: String?
+) : BaseListItem() {
+    override fun getUnique(): String = id
+
+}
+
+@JsonClass(generateAdapter = true)
+data class Result(
+
+    @Json(name = "_id")
+    var id: String,
+
+    @Json(name = "no")
+    var no: String,
+
+    @Json(name = "total_ramdom")
+    var totalValue: String,
+
+    @Json(name = "set_result_id")
+    var smallBigSetId: String,
+
+    @Json(name = "type_of_betting")
+    val resultSmallOrBig: String,
+
+    @Json(name = "category")
+    var categorySmallOrBig: String,
+
+    @Json(name = "set_result_id_range")
+    var rangeSetId: String,
+
+    @Json(name = "type_of_betting_range")
+    val resultRange: String,
+
+    @Json(name = "category_range")
+    var categoryRange: String
+)
+
+@JsonClass(generateAdapter = true)
+data class TodayReportResponse(
+    @Json(name = "code")
+    val resultCode: String,
+    @Json(name = "message")
+    val message: MainMessage,
+    @Json(name = "data")
+    val data: TodayReportData?
+)
+
+@JsonClass(generateAdapter = true)
+data class TodayReportData(
+    @Json(name = "todayReport")
+    val todayReportList: List<CfTodayReport>?
+)
+
+@JsonClass(generateAdapter = true)
+data class CfTodayReport(
+    @Json(name = "_id")
+    val id: String,
+    @Json(name = "fight_no")
+    val fightNo: Int?,
+    @Json(name = "type_betting")
+    val typeBetting: String?,
+    @Json(name = "amount")
+    val amount: Long?,
+    @Json(name = "payout")
+    val payout: Double?,
+    @Json(name = "cast")
+    val cast: String?,
+    @Json(name = "result")
+    val result: String?,
+    @Json(name = "win_lose")
+    val winLose: String?,
+    @Json(name = "amount_win")
+    val amountWin: String?,
+    @Json(name = "date")
+    val date: String?,
+    @Json(name = "updatedAt")
+    val updateAt: String?,
+): BaseListItem(){
+    override fun getUnique(): String = id
+}
+
+@JsonClass(generateAdapter = true)
+data class CurrentBetsResponse(
+    @Json(name = "code")
+    val resultCode: String,
+    @Json(name = "message")
+    val message: MainMessage,
+    @Json(name = "data")
+    val data: CurrentBetsData?
+)
+
+@JsonClass(generateAdapter = true)
+data class CurrentBetsData(
+    @Json(name = "currenBetting")
+    val currentBetsList: List<CfCurrentBets>?
+)
+
+@JsonClass(generateAdapter = true)
+data class CfCurrentBets(
+    @Json(name = "_id")
+    val id: String,
+    @Json(name = "user_id")
+    val userId: String?,
+    @Json(name = "fight_no")
+    val fightNo: Int?,
+    @Json(name = "group")
+    val group: Int?,
+    @Json(name = "type_betting")
+    val typeBetting: String,
+    @Json(name = "amount")
+    val amount: Long,
+    @Json(name = "payout")
+    val payout: Double,
+    @Json(name = "cast")
+    val cast: Long?,
+    @Json(name = "win_lose")
+    val winLose: Boolean?,
+    @Json(name = "amount_win")
+    val amountWin: Long?,
+    @Json(name = "date")
+    val date: String,
+    @Json(name = "updatedAt")
+    val updateAt: String?,
+): BaseListItem(){
+    override fun getUnique(): String = id
+}
+
+@JsonClass(generateAdapter = true)
+data class StatementResponse(
+    @Json(name = "code")
+    val resultCode: String,
+    @Json(name = "message")
+    val message: MainMessage,
+    @Json(name = "data")
+    val data: StatementData?
+)
+
+@JsonClass(generateAdapter = true)
+data class StatementData(
+    @Json(name = "statement")
+    val statementList: List<CfStatement>?
+)
+
+@JsonClass(generateAdapter = true)
+data class CfStatement(
+    @Json(name = "_id")
+    val id: String,
+    @Json(name = "date")
+    val date: String?,
+    @Json(name = "note")
+    val note: String?,
+    @Json(name = "note_khmer")
+    val noteKhmer: String?,
+    @Json(name = "amount")
+    val amount: Int?,
+    @Json(name = "amount_win")
+    val amountWin: Int?,
+    @Json(name = "trun_over")
+    val trunOver: Int?,
+): BaseListItem(){
+    override fun getUnique(): String = id
+}
+
+@JsonClass(generateAdapter = true)
+data class CreateBetResponse(
+    @Json(name = "code")
+    val resultCode: String,
+    @Json(name = "message")
+    val message: MainMessage,
+    @Json(name = "data")
+    val data: CreateBetData?
+)
+
+@JsonClass(generateAdapter = true)
+data class CreateBetData(
+    @Json(name = "account_balances")
+    val accountBalances: Double?,
+    @Json(name = "chanel")
+    val channel: Channel?,
+    @Json(name = "print")
+    val print: Print?
+)
+
+@JsonClass(generateAdapter = true)
+class CreateBetting(
+    @Json(name = "amount")
+    val amount: Int,
+    @Json(name = "chicken_id")
+    val chickenId: String
+)
+
+@JsonClass(generateAdapter = true)
+data class Print(
+    @Json(name = "fight_no")
+    var fightNo: String,
+    @Json(name = "date")
+    var date: String,
+    @Json(name = "user_name")
+    var userName: String,
+    @Json(name = "type_betting")
+    var typeBetting: String,
+    @Json(name = "amount")
+    var amount: String,
+    @Json(name = "payout_rate")
+    var payoutRate: String,
+    @Json(name = "payout")
+    var payout: String,
+)
+

+ 82 - 0
app/src/main/java/com/sambath/kunkhmer/remote/NewsDataModel.kt

@@ -0,0 +1,82 @@
+package com.sambath.kunkhmer.remote
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+@JsonClass(generateAdapter = true)
+data class NewsResponse(
+    @Json(name = "code")
+    val resultCode: Int,
+    @Json(name = "message")
+    val message: ResponseMessage,
+    @Json(name = "data")
+    val data: NewsData?
+)
+
+@JsonClass(generateAdapter = true)
+data class NewsData(
+    @Json(name = "object")
+    val obj: MutableList<News>,
+)
+
+@JsonClass(generateAdapter = true)
+data class News(
+    @Json(name = "_id")
+    val id: String,
+    @Json(name = "viewer")
+    val viewer: Int,
+    @Json(name = "title")
+    val title: String,
+    @Json(name = "desc")
+    val desc: String,
+    @Json(name = "createdAt")
+    val createdAt: String,
+    @Json(name = "filename")
+    val filename: String?,
+)
+
+// ---- create request
+
+@JsonClass(generateAdapter = true)
+class CreateNewsRequest(
+    @Json(name = "title")
+    val title: String,
+    @Json(name = "desc")
+    val desc: String,
+    @Json(name = "upload")
+    val upload: String
+)
+
+@JsonClass(generateAdapter = true)
+data class CreateNewsResponse(
+    @Json(name = "code")
+    val resultCode: Int,
+    @Json(name = "message")
+    val message: ResponseMessage,
+    @Json(name = "data")
+    val data: NewsCreatedData?
+)
+
+@JsonClass(generateAdapter = true)
+data class NewsCreatedData(
+    @Json(name = "new")
+    val obj: CreatedNews,
+)
+
+@JsonClass(generateAdapter = true)
+data class CreatedNews(
+    @Json(name = "_id")
+    val id: String,
+    @Json(name = "viewer")
+    val viewer: Int,
+    @Json(name = "title")
+    val title: String,
+    @Json(name = "desc")
+    val desc: String,
+    @Json(name = "createdAt")
+    val createdAt: String,
+    @Json(name = "updatedAt")
+    val updatedAt: String,
+    @Json(name = "__v")
+    val _v: Int,
+)

+ 59 - 0
app/src/main/java/com/sambath/kunkhmer/remote/NewsDetailDataModel.kt

@@ -0,0 +1,59 @@
+package com.sambath.kunkhmer.remote
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+@JsonClass(generateAdapter = true)
+data class NewsDetailResponse(
+    @Json(name = "code")
+    val resultCode: Int,
+    @Json(name = "message")
+    val message: ResponseMessage,
+    @Json(name = "data")
+    val data: NewsDetailData?
+)
+
+@JsonClass(generateAdapter = true)
+data class NewsDetailData(
+    @Json(name = "object")
+    val obj: NewsDetail,
+)
+
+@JsonClass(generateAdapter = true)
+data class NewsDetail(
+    @Json(name = "viewer")
+    val viewer: Int = 0,
+
+    @Json(name = "_id")
+    val id: String = "",
+
+    @Json(name = "title")
+    val title: String = "",
+
+    @Json(name = "desc")
+    val desc: String = "",
+
+    @Json(name = "createdAt")
+    val createdAt: String = "",
+
+    @Json(name = "updatedAt")
+    val updatedAt: String = "",
+
+    @Json(name = "__v")
+    val _v: Int = 0,
+
+    @Json(name = "file_id")
+    val filename: NewsFile? = null
+)
+
+@JsonClass(generateAdapter = true)
+data class NewsFile(
+    @Json(name = "originalname")
+    val originalName: String,
+    @Json(name = "mimetype")
+    val mimetype: String,
+    @Json(name = "id")
+    val id: String,
+    @Json(name = "filename")
+    val filename: String,
+)

+ 93 - 0
app/src/main/java/com/sambath/kunkhmer/remote/PlayDataModel.kt

@@ -0,0 +1,93 @@
+package com.sambath.kunkhmer.remote
+
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+
+@JsonClass(generateAdapter = true)
+class PlayRequest(
+    @Json(name = "set_result_id")
+    val setID: String,
+
+    @Json(name = "user_id")
+    val userId: String,
+
+    @Json(name = "no")
+    val no: String,
+
+//    @Json(name = "date")
+//    val date: String,
+
+    @Json(name = "cast")
+    val cast: Double,
+
+    @Json(name = "amount")
+    val amount: Int
+)
+@JsonClass(generateAdapter = true)
+data class PlayResponse(
+
+    @Json(name = "code")
+    val resultCode: String,
+    @Json(name = "message")
+    val message: PlayMessage,
+    @Json(name = "data")
+    val data: PlayData?
+)
+@JsonClass(generateAdapter = true)
+data class PlayMessage(
+    @Json(name="code")
+    val code: String,
+
+    @Json(name="descriptions")
+    val description: String,
+)
+@JsonClass(generateAdapter = true)
+data class PlayData(
+
+    @Json(name = "objCurrentBetting")
+    val myBetting: CurrentBetting?,
+
+    @Json(name = "accountBalances")
+    val accountBalance: String?,
+)
+
+@JsonClass(generateAdapter = true)
+data class CurrentBetting(
+
+    @Json(name = "_id")
+    var id: String,
+
+    @Json(name = "no")
+    var no: String,
+
+    @Json(name = "set_result_id")
+    var setId: String,
+
+    @Json(name = "type_of_betting")
+    val typeOfBetting: String,
+
+    @Json(name = "category")
+    val category: String,
+
+    @Json(name = "user_id")
+    val userId: String,
+
+    @Json(name = "date")
+    val date: String,
+
+    @Json(name = "amount")
+    val amount: String,
+
+    @Json(name = "cast")
+    val cast: String,
+
+    @Json(name = "win_lose")
+    val win_lose: String?,
+
+    @Json(name = "amount_win")
+    val amount_win: String?
+
+)
+

+ 84 - 0
app/src/main/java/com/sambath/kunkhmer/remote/ProductDataModel.kt

@@ -0,0 +1,84 @@
+package com.sambath.kunkhmer.remote
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+@JsonClass(generateAdapter = true)
+data class ProductResponse(
+    @Json(name = "code")
+    val resultCode: Int,
+    @Json(name = "message")
+    val message: ResponseMessage,
+    @Json(name = "data")
+    val data: ProductData?
+)
+
+@JsonClass(generateAdapter = true)
+data class ProductData(
+    @Json(name = "object")
+    val obj: MutableList<ProductInfo>,
+)
+
+@JsonClass(generateAdapter = true)
+data class ProductInfo(
+    @Json(name = "_id")
+    val productId: String,
+    @Json(name = "price")
+    val price: Int,
+    @Json(name = "name")
+    val name: String,
+    @Json(name = "desc")
+    val desc: String,
+    @Json(name = "createdAt")
+    val createdAt: String,
+    @Json(name = "filename")
+    val filename: String? = null,
+)
+
+///////
+
+@JsonClass(generateAdapter = true)
+class CreateProductRequest(
+    @Json(name = "name")
+    val name: String,
+    @Json(name = "desc")
+    val desc: String,
+    @Json(name = "price")
+    val price: String,
+    @Json(name = "upload")
+    val upload: String
+)
+
+@JsonClass(generateAdapter = true)
+data class CreateProductResponse(
+    @Json(name = "code")
+    val resultCode: Int,
+    @Json(name = "message")
+    val message: ResponseMessage,
+    @Json(name = "data")
+    val data: ProductCreatedData?
+)
+
+@JsonClass(generateAdapter = true)
+data class ProductCreatedData(
+    @Json(name = "product")
+    val obj: CreatedProduct,
+)
+
+@JsonClass(generateAdapter = true)
+data class CreatedProduct(
+    @Json(name = "_id")
+    val id: String,
+    @Json(name = "price")
+    val price: Int,
+    @Json(name = "name")
+    val name: String,
+    @Json(name = "desc")
+    val desc: String,
+    @Json(name = "createdAt")
+    val createdAt: String,
+    @Json(name = "updatedAt")
+    val updatedAt: String,
+    @Json(name = "__v")
+    val _v: Int,
+)

+ 153 - 0
app/src/main/java/com/sambath/kunkhmer/remote/ReportDataModel.kt

@@ -0,0 +1,153 @@
+package com.sambath.kunkhmer.remote
+
+import com.gdtlib.lib.adapter.BaseListItem
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+@JsonClass(generateAdapter = true)
+data class ReportResponse(
+
+    @Json(name = "code")
+    val resultCode: String,
+    @Json(name = "message")
+    val message: ReportMessage,
+    @Json(name = "data")
+    val data: ReportData?
+)
+
+@JsonClass(generateAdapter = true)
+data class ReportMessage(
+    @Json(name = "code")
+    val code: String,
+
+    @Json(name = "descriptions")
+    val description: String)
+
+@JsonClass(generateAdapter = true)
+data class ReportData(
+
+    @Json(name = "objLotoBettingWin")
+    val winList: List<Win>?,
+
+    @Json(name = "objLotoBettingWinLose")
+    val winLostLst: List<WinLost>?,
+
+    @Json(name = "objGroupStatement")
+    val statementList: List<Statement>?
+
+)
+
+@JsonClass(generateAdapter = true)
+data class Win(
+    @Json(name = "_id")
+    var id: String,
+
+    @Json(name = "date")
+    val date: String,
+
+    @Json(name = "filter_date")
+    var filterDate: String,
+
+    @Json(name = "no")
+    val no: String,
+
+    @Json(name = "user_name")
+    val userName: String,
+
+    @Json(name = "bank_account")
+    val bankAccount: String,
+
+    @Json(name = "total_ramdom")
+    val totalRandom: String,
+
+    @Json(name = "type_of_betting")
+    val typeOfBetting: String,
+
+    @Json(name = "color")
+    val color: String,
+
+    @Json(name = "amount")
+    val amount: String,
+
+    @Json(name = "cast")
+    val cast: String,
+
+    @Json(name = "win_lose")
+    val win_lose: String?,
+
+    @Json(name = "amount_win")
+    val amount_win: String?
+): BaseListItem(){
+    override fun getUnique(): String = id
+
+}
+@JsonClass(generateAdapter = true)
+data class WinLost(
+    @Json(name = "_id")
+    var id: String,
+
+    @Json(name = "date")
+    val date: String,
+
+    @Json(name = "filter_date")
+    var filterDate: String,
+
+    @Json(name = "no")
+    val no: String,
+
+    @Json(name = "user_name")
+    val userName: String,
+
+    @Json(name = "bank_account")
+    val bankAccount: String,
+
+    @Json(name = "total_ramdom")
+    val totalRandom: String,
+
+    @Json(name = "type_of_betting")
+    val typeOfBetting: String,
+
+    @Json(name = "color")
+    val color: String,
+
+    @Json(name = "amount")
+    val amount: String,
+
+    @Json(name = "cast")
+    val cast: String,
+
+    @Json(name = "win_lose")
+    val win_lose: String?,
+
+    @Json(name = "amount_win")
+    val amount_win: String?
+): BaseListItem(){
+    override fun getUnique(): String = id
+
+}
+
+@JsonClass(generateAdapter = true)
+data class Statement(
+    @Json(name = "_id")
+    var id: String,
+
+    @Json(name = "date")
+    val date: String,
+
+    @Json(name = "note")
+    val note: String,
+
+    @Json(name = "note_khmer")
+    val khmerNote: String?,
+
+    @Json(name = "amount")
+    val amount: Double?,
+
+    @Json(name = "amount_win")
+    val amount_win: Double?
+
+    ): BaseListItem(){
+    override fun getUnique(): String = id
+
+}
+

+ 126 - 0
app/src/main/java/com/sambath/kunkhmer/remote/ResultDataModel.kt

@@ -0,0 +1,126 @@
+package com.sambath.kunkhmer.remote
+import com.google.gson.annotations.SerializedName
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+@JsonClass(generateAdapter = true)
+data class ResultResponse(
+    @Json(name = "code")
+    val resultCode: String,
+    @Json(name = "message")
+    val message: ResultMessage,
+    @Json(name = "data")
+    val data: ResultData?
+)
+
+@JsonClass(generateAdapter = true)
+data class CfResultResponse(
+    @Json(name = "code")
+    val resultCode: String,
+    @Json(name = "message")
+    val message: ResultMessage,
+    @Json(name = "data")
+    val data: CfResultData?
+)
+
+@JsonClass(generateAdapter = true)
+data class CfResultData(
+    @Json(name = "chanel")
+    val channel: Channel?,
+    @Json(name = "result")
+    val resultList: List<ResultCf>?
+)
+
+@JsonClass(generateAdapter = true)
+data class ResultCf(
+    @Json(name ="_id")
+    val id: String? = null,
+    @Json(name ="user_id")
+    val userId: String? = null,
+    @Json(name ="chanel_id")
+    val chanelId: String? = null,
+    @Json(name ="fight_no")
+    val fightNo: String? = null,
+    @Json(name ="type_betting")
+    val beetingType: String? = null,
+    @Json(name ="date")
+    val tWalaTotalAmount: String? = null,
+    @Json(name ="no")
+    val no: String? = null,
+    @Json(name ="color")
+    val color: String? = null,
+    @Json(name ="cid")
+    val colunmId: Int? = null,
+    @Json(name ="rid")
+    val rowId: Int? = null,
+    @Json(name ="group")
+    val group: String? = null,
+)
+
+@JsonClass(generateAdapter = true)
+data class ResultMessage(
+    @Json(name = "code")
+    val code: String,
+
+    @Json(name = "descriptions")
+    val description: String)
+
+@JsonClass(generateAdapter = true)
+data class ResultData(
+    @Json(name = "object")
+    val resultList: List<ResultLotto>?
+)
+
+@JsonClass(generateAdapter = true)
+data class ResultLotto(
+
+    @Json(name = "_id")
+    var id: String,
+
+    @Json(name = "no")
+    var no: String,
+
+    @Json(name = "set_result_id")
+    var smallBigSetId: String,
+
+    @Json(name = "type_of_betting")
+    val resultSmallOrBig: String,
+
+    @Json(name = "category")
+    var categorySmallOrBig: String,
+
+    @Json(name = "set_result_id_range")
+    var rangeSetId: String,
+
+    @Json(name = "type_of_betting_range")
+    val resultRange: String,
+
+    @Json(name = "category_range")
+    var categoryRange: String
+)
+
+data class CfResult(
+    @SerializedName("_id")
+    var id: String? = null,
+    @SerializedName("user_id")
+    var userId: String? = null,
+    @SerializedName("chanel_id")
+    var chanelId: String? = null,
+    @SerializedName("fight_no")
+    var fightNo: String? = null,
+    @SerializedName("type_betting")
+    var beetingType: String? = null,
+    @SerializedName("date")
+    var tWalaTotalAmount: String? = null,
+    @SerializedName("no")
+    var no: String? = null,
+    @SerializedName("color")
+    var color: String? = null,
+    @SerializedName("cid")
+    var colunmId: Int? = null,
+    @SerializedName("rid")
+    var rowId: Int? = null,
+    @SerializedName("group")
+    var group: String? = null,
+){}
+

+ 15 - 0
app/src/main/java/com/sambath/kunkhmer/remote/SocketMessageDataModel.kt

@@ -0,0 +1,15 @@
+package com.sambath.kunkhmer.remote
+
+import org.json.JSONArray
+
+
+data class SocketMessageDataModel(
+    val type: String,
+    val countDown: Int?= null,
+    val resultArray: JSONArray? = null,
+    val totalValue: Int?= null
+
+){
+    fun isCountDowning() = countDown != null && resultArray == null
+
+}

+ 30 - 0
app/src/main/java/com/sambath/kunkhmer/remote/UpdatePwdDataModel.kt

@@ -0,0 +1,30 @@
+package com.sambath.kunkhmer.remote
+
+import com.squareup.moshi.Json
+import com.squareup.moshi.JsonClass
+
+@JsonClass(generateAdapter = true)
+class UpdatePwdRequest(
+    @Json(name = "user_name")
+    val username: String,
+    @Json(name = "password")
+    val password: String
+)
+@JsonClass(generateAdapter = true)
+data class UpdatePwdResponse(
+
+    @Json(name = "code")
+    val resultCode: String,
+    @Json(name = "message")
+    val message: LoginMessage,
+
+)
+@JsonClass(generateAdapter = true)
+data class UpdatePwdMessage(
+    @Json(name="code")
+    val code: String,
+
+    @Json(name="descriptions")
+    val description: String,
+)
+

+ 147 - 0
app/src/main/java/com/sambath/kunkhmer/remote/service/ApiService.kt

@@ -0,0 +1,147 @@
+package com.sambath.kunkhmer.remote.service
+
+import com.sambath.kunkhmer.extension.CurrentUserResponse
+import com.sambath.kunkhmer.remote.*
+import io.reactivex.Single
+import okhttp3.MultipartBody
+import okhttp3.RequestBody
+import okhttp3.ResponseBody
+import retrofit2.http.*
+
+interface ApiService {
+
+    @POST("/v1/users/login")
+    @Headers("No-Authentication: true")
+    fun login(@Body loginRequest: LoginRequest): Single<LoginResponse>
+
+    @GET("/v1/match/getAll")
+    fun getMatches(): Single<MatchesResponse>
+
+    @GET("/v1/fighter/getAll")
+    fun getFighters(): Single<FighterResponse>
+
+    @GET("fighter/image/{imageId}.jpeg")
+    fun getFighterImage(@Path("imageId") imageId: String): Single<ResponseBody>
+
+    @GET("/v1/new/getAll")
+    fun getNews(): Single<NewsResponse>
+
+    @GET("/v1/highLight/getAll")
+    fun getHighlights(): Single<HighlightResponse>
+
+    @GET("/v1/live/getAll")
+    fun getLives(): Single<LivesResponse>
+
+    @GET("/v1/event/getAll")
+    fun getEvents(): Single<EventResponse>
+
+    @GET("/v1/product/getAll")
+    fun getProducts(): Single<ProductResponse>
+
+    @GET("/v1/new/get/{newsId}")
+    fun getNewsDetail(@Path("newsId") newsId: String): Single<NewsDetailResponse>
+
+    @POST("/v1/users/get")
+    fun getCurrentUser(): Single<CurrentUserResponse>
+
+    @Multipart
+    @POST("/v1/new/create")
+    fun createNews(@Part("title") title: RequestBody,
+                   @Part("desc") desc: RequestBody,
+                   @Part file: MultipartBody.Part
+    ): Single<CreateNewsResponse>
+
+    @Multipart
+    @POST("/v1/new/create")
+    fun createNews(@Part("title") title: RequestBody,
+                   @Part("desc") desc: RequestBody
+    ): Single<CreateNewsResponse>
+
+    @Multipart
+    @POST("/v1/product/create")
+    fun createProduct(@Part("name") name: RequestBody,
+                      @Part("desc") desc: RequestBody,
+                      @Part("price") price: RequestBody,
+                      @Part file: MultipartBody.Part): Single<CreateProductResponse>
+    @Multipart
+    @POST("/v1/product/create")
+    fun createProduct(@Part("name") name: RequestBody,
+                      @Part("desc") desc: RequestBody,
+                      @Part("price") price: RequestBody
+                      ): Single<CreateProductResponse>
+
+    @Multipart
+    @POST("/v1/fighter/create")
+    fun createFighter(@Part("name") name: RequestBody,
+                      @Part("desc") desc: RequestBody,
+                      @Part("weight") price: RequestBody,
+                      @Part("high") height: RequestBody,
+                      @Part("nationality") nationality: RequestBody,
+                      @Part file: MultipartBody.Part): Single<CreateFighterResponse>
+
+    @Multipart
+    @POST("/v1/fighter/create")
+    fun createFighter(@Part("name") name: RequestBody,
+                      @Part("desc") desc: RequestBody,
+                      @Part("weight") price: RequestBody,
+                      @Part("high") height: RequestBody,
+                      @Part("nationality") nationality: RequestBody): Single<CreateFighterResponse>
+
+    @POST("/v1/highLight/create")
+    fun createHighlight(@Body createHighlightRequest: CreateHighlightRequest): Single<CreateHighlightResponse>
+
+    @POST("/v1/match/create")
+    fun createMatch(@Body createMatchRequest: CreateMatchRequest): Single<CreateMatchResponse>
+
+    @POST("/v1/event/create")
+    fun createEvent(@Body createEventRequest: CreateEventRequest): Single<CreateEventResponse>
+
+    @POST("/v1/live/create")
+    fun createLives(@Body createLivesRequest: CreateLivesRequest): Single<CreateLivesResponse>
+    ///---------------------------------------------------------
+
+    @POST("/v1/api/user/changepassword")
+    fun changePassword(@Body changePwd: ChangePwd): Single<ChangePwdResponse>
+
+    @GET("/v1/api/user")
+    fun getUser(): Single<UserResponse>
+
+    @GET("/v1/api/channel")
+    fun getChannel(): Single<ChannelResponse>
+
+    @GET("/v1/api/weight")
+    fun getWeight(): Single<WeightResponse>
+
+    @GET("/v1/api/type")
+    fun getBettingType(): Single<BettingTypeResponse>
+
+    @GET("/v1/api/result")
+    fun getResult(): Single<ResultsResponse>
+
+    @POST("/v1/api/betting")
+    fun createBetting(@Body createBetting: CreateBetting): Single<BettingResponse>
+
+    @GET("/v1/api/betting/current")
+    fun getCurrentBetting(): Single<CurrentResponse>
+
+    @GET("/v1/api/betting/today")
+    fun getTodayReport(): Single<TodayResponse>
+
+    @GET("/v1/api/button")
+    fun getButton(): Single<ButtonResponse>
+
+    @POST("/v1/api/report/deposit")
+    fun getReportDeposit(@Body reportBetting: ReportBody): Single<ReportDepositResponse>
+
+    @POST("/v1/api/report/withdraw")
+    fun getReportWithdraw(@Body reportBetting: ReportBody): Single<ReportWithdrawResponse>
+
+    @POST("/v1/api/report/betting")
+    fun getReportOne(@Body reportBetting: ReportBody): Single<ReportOneResponse>
+
+    @POST("/v1/api/result/filter")
+    fun getReportTwo(@Body reportBetting: ReportBody): Single<ReportTwoResponse>
+
+    @GET("/v1/api/report")
+    fun getReportThree(): Single<ReportThreeResponse>
+}

+ 19 - 0
app/src/main/java/com/sambath/kunkhmer/remote/service/ConnectivityStates.java

@@ -0,0 +1,19 @@
+package com.sambath.kunkhmer.remote.service;
+
+public class ConnectivityStates {
+
+    private ConnectivityStates() {
+        // non-instantiable class
+    }
+
+    public static final int STATE_NOT_CONNECTED = 0 ;
+
+    public static final int STATE_RECONNECTING = 1 ;
+
+    public static final int STATE_CONNECTED = 2 ;
+
+    public static final int STATE_DISCONNECTED = 3 ;
+
+    public static final int STATE_TIMEOUT = 4 ;
+
+}

+ 29 - 0
app/src/main/java/com/sambath/kunkhmer/remote/service/EventListener.java

@@ -0,0 +1,29 @@
+package com.sambath.kunkhmer.remote.service;
+
+public interface EventListener {
+
+    void onConnect();
+
+    void onConnectionError() ;
+
+    void onReconnect();
+
+    void onReconnectionTimeout();
+
+    void onDisconnect();
+
+    void onUpdateChannelInfo(String data);
+
+    void onDefinedResultAndChannel(String data);
+
+    void onUpdateUserInfo(String data);
+
+    void onUpdateBettingAmount(String data);
+
+    void onUpdatePayout(String data);
+
+    void onReverseRseult(String data);
+
+    void onResetAmount(String data);
+
+}

+ 133 - 0
app/src/main/java/com/sambath/kunkhmer/remote/service/SocketService.java

@@ -0,0 +1,133 @@
+package com.sambath.kunkhmer.remote.service;
+
+import static java.util.Collections.singletonList;
+import static java.util.Collections.singletonMap;
+
+import android.util.Log;
+
+import com.sambath.kunkhmer.config.Config;
+import com.sambath.kunkhmer.util.BaseObservable;
+
+import org.json.JSONObject;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import io.socket.client.IO;
+import io.socket.client.Socket;
+import io.socket.emitter.Emitter;
+
+public class SocketService extends BaseObservable<EventListener> {
+    private static final String TAG = "Socket";
+    private static final String SOCKET_1 = Config.SOCKET_1;
+//    private static final String SOCKET_2 = Config.SOCKET_2;
+//    private static final String SOCKET_3 = Config.SOCKET_3;
+//    private static final String SOCKET_4 = Config.SOCKET_4;
+    private static final String EVENT_CONNECT = Socket.EVENT_CONNECT;
+    private static final String EVENT_CONNECT_ERROR = Socket.EVENT_CONNECT_ERROR;
+    private static final String EVENT_DISCONNECT = Socket.EVENT_DISCONNECT;
+    private static final String EVENT_UPDATE_CHANNEL_INFO = "client-update-channel-info";
+    private static final String EVENT_DEFINED_RESULT_AND_CHANNEL = "client-defind-result-and-new-channel";
+    private static final String EVENT_UPDATE_USER_INFO = "client-update-user-info";
+    private static final String EVENT_UPDATE_BETTING_AMOUNT = "client-update-betting-amount";
+    private static final String EVENT_UPDATE_PAYOUT = "client-update-payout";
+    private static final String EVENT_REVERSE_RESULT = "client-reserves-result";
+    private static final String EVENT_RESET_AMOUNT = "client-reset-amount";
+    private Socket mSocket;
+
+    public void startListening(String token, int channelType) throws URISyntaxException {
+        IO.Options options = IO.Options.builder()
+                .setExtraHeaders(singletonMap("authorization", singletonList(token)))
+                .build();
+        Log.d("Socket", "startListening mSocket"+ channelType);
+        mSocket = IO.socket(URI.create(SOCKET_1), options);
+        mSocket.on(EVENT_CONNECT, connectListener);
+        mSocket.on(EVENT_UPDATE_CHANNEL_INFO, updateChannelInfo);
+        mSocket.on(EVENT_DEFINED_RESULT_AND_CHANNEL, definedResultAndChannel);
+        mSocket.on(EVENT_UPDATE_USER_INFO, updateUserInfo);
+        mSocket.on(EVENT_UPDATE_BETTING_AMOUNT, updateBettingAmount);
+        mSocket.on(EVENT_UPDATE_PAYOUT, updatePayout);
+        mSocket.on(EVENT_REVERSE_RESULT, reverseResult);
+        mSocket.on(EVENT_RESET_AMOUNT, resetAmount);
+        mSocket.on(EVENT_DISCONNECT, disconnectListener);
+        mSocket.on(EVENT_CONNECT_ERROR, connectionErrorListener);
+        mSocket.connect();
+    }
+
+    private Emitter.Listener updateChannelInfo = args -> {
+        Log.d("Socket", "updateChannelInfo s...fghfhgfhgfhfghgf");
+        final String rawMessage = args[0].toString();
+        for (EventListener listener : getListeners())
+            listener.onUpdateChannelInfo(rawMessage);
+    };
+    private Emitter.Listener definedResultAndChannel = args -> {
+        Log.d("Socket", "definedResultAndChannel s...fghfhgfhgfhfghgf");
+        final String rawMessage = args[0].toString();
+        for (EventListener listener : getListeners())
+            listener.onDefinedResultAndChannel(rawMessage);
+    };
+    private Emitter.Listener updateUserInfo = args -> {
+        Log.d("Socket", "updateUserInfo s...fghfhgfhgfhfghgf");
+        final String rawMessage = args[0].toString();
+        for (EventListener listener : getListeners())
+            listener.onUpdateUserInfo(rawMessage);
+    };
+    private Emitter.Listener updateBettingAmount = args -> {
+        Log.d("Socket", "updateBettingAmount s...fghfhgfhgfhfghgf");
+        final String rawMessage = args[0].toString();
+        for (EventListener listener : getListeners())
+            listener.onUpdateBettingAmount(rawMessage);
+    };
+    private Emitter.Listener updatePayout = args -> {
+        Log.d("Socket", "updatePayout s...fghfhgfhgfhfghgf");
+        final String rawMessage = args[0].toString();
+        for (EventListener listener : getListeners())
+            listener.onUpdatePayout(rawMessage);
+    };
+    private Emitter.Listener reverseResult = args -> {
+        Log.d("Socket", "reverseResult s...fghfhgfhgfhfghgf");
+        final String rawMessage = args[0].toString();
+        for (EventListener listener : getListeners())
+            listener.onReverseRseult(rawMessage);
+    };
+    private Emitter.Listener resetAmount = args -> {
+        Log.d("Socket", "resetAmount s...fghfhgfhgfhfghgf");
+        final String rawMessage = args[0].toString();
+        for (EventListener listener : getListeners())
+            listener.onResetAmount(rawMessage);
+    };
+    private Emitter.Listener connectListener = args -> {
+        Log.d("Socket", "onConnect s...fghfhgfhgfhfghgf");
+        for (EventListener listener : getListeners())
+            listener.onConnect();
+    };
+
+    public void stopListening() {
+        if (mSocket != null)
+            mSocket.disconnect();
+    }
+
+    public void switchChannel(String token, int channelType) throws URISyntaxException {
+        if (mSocket != null)
+            mSocket.disconnect();
+        startListening(token, channelType);
+    }
+
+    public void startEmitCfCreateBetting(JSONObject joinObject) {
+        mSocket.emit("player-betting", joinObject);
+    }
+
+    private Emitter.Listener connectionErrorListener = args -> {
+//        Log.d(TAG,"onConnectionError s..."+args[0].toString());
+        for (EventListener listener : getListeners())
+            listener.onConnectionError();
+    };
+
+    private Emitter.Listener disconnectListener = args -> {
+//        Log.d(TAG,"onDisconnect s..."+args[0].toString());
+        mSocket.off();
+        for (EventListener listener : getListeners()) {
+            listener.onDisconnect();
+        }
+    };
+}

+ 91 - 0
app/src/main/java/com/sambath/kunkhmer/screen/account/AccountFragment.kt

@@ -0,0 +1,91 @@
+package com.sambath.kunkhmer.screen.account
+
+import android.content.Intent
+import android.os.Bundle
+import androidx.fragment.app.Fragment
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import com.sambath.kunkhmer.R
+import com.sambath.kunkhmer.app.App
+import com.sambath.kunkhmer.remote.User
+import com.sambath.kunkhmer.screen.login.LoginActivity
+import com.sambath.kunkhmer.util.Const
+import com.sambath.kunkhmer.util.ModelPreferencesManager
+import com.sambath.kunkhmer.util.PrefHelper
+import kotlinx.android.synthetic.main.fragment_account.view.country_tv
+import kotlinx.android.synthetic.main.fragment_account.view.email_tv
+import kotlinx.android.synthetic.main.fragment_account.view.logout_btn
+import kotlinx.android.synthetic.main.fragment_account.view.member_tv
+import kotlinx.android.synthetic.main.fragment_account.view.username_tv
+import java.text.SimpleDateFormat
+import java.util.Locale
+import java.util.TimeZone
+
+class AccountFragment : Fragment() {
+    private var _root: View? = null
+    private val binding get() = _root!!
+    private lateinit var user: User
+    private lateinit var accountViewModel: AccountViewModel
+    lateinit var sharePref: PrefHelper
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+    }
+
+    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+        // Inflate the layout for this fragment
+        _root = inflater.inflate(R.layout.fragment_account, container, false)
+        user = ModelPreferencesManager.get<User>(Const.USER_KEY)!!
+        sharePref = App.injectPrefHelper()
+
+        binding.username_tv.text = user.userName
+        accountViewModel = AccountViewModel(App.injectApiService(), App.injectPrefHelper())
+        accountViewModel.getCurrentUser()
+        accountViewModel.state.observe(viewLifecycleOwner, androidx.lifecycle.Observer {
+            render(it)
+        })
+
+        binding.logout_btn.setOnClickListener{
+            // Clear user-related data or preferences, such as the user token.
+            sharePref.logout()
+            // Redirect the user to the login screen or perform any other necessary actions.
+            // For example, you can start a new activity or fragment for the login screen:
+            val intent = Intent(context, LoginActivity::class.java)
+            intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
+            startActivity(intent)
+
+        }
+
+        return _root
+    }
+
+    private fun render(it: AccountViewModel.AccountViewState) {
+        if(it.isLoginSuccess){
+            if(it.currentUser != null) {
+                val data = it.currentUser
+
+                binding.member_tv.text = parseAndFormatDate(data.createdAt)
+                binding.email_tv.text = data.email_or_phone
+                binding.country_tv.text = "Cambodia"
+
+            }
+        }
+    }
+
+    private fun parseAndFormatDate(dateString: String): String {
+        // Create a SimpleDateFormat for parsing the date string
+        val parser = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.getDefault())
+        parser.timeZone = TimeZone.getTimeZone("UTC")
+
+        // Parse the date
+        val date = parser.parse(dateString)
+
+        // Create a SimpleDateFormat for formatting the date
+        val formatter = SimpleDateFormat("dd MMM yyyy HH:mm", Locale.getDefault())
+        formatter.timeZone = TimeZone.getDefault() // Use local timezone
+
+        // Format the date
+        return formatter.format(date)
+    }
+}

+ 49 - 0
app/src/main/java/com/sambath/kunkhmer/screen/account/AccountViewModel.kt

@@ -0,0 +1,49 @@
+package com.sambath.kunkhmer.screen.account
+
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import com.sambath.kunkhmer.app.getErrorCode
+import com.sambath.kunkhmer.base.BaseViewModel
+import com.sambath.kunkhmer.extension.CurrentUser
+import com.sambath.kunkhmer.remote.service.ApiService
+import com.sambath.kunkhmer.util.PrefHelper
+import io.reactivex.android.schedulers.AndroidSchedulers
+import io.reactivex.schedulers.Schedulers
+import java.util.concurrent.TimeUnit
+
+class AccountViewModel(val apiService: ApiService, val prefHelper: PrefHelper) : BaseViewModel() {
+    private val _state = MutableLiveData<AccountViewState>(AccountViewState())
+    val state: LiveData<AccountViewState> = _state
+    private fun prev() = _state.value!!
+
+    data class AccountViewState(
+        val initial: Boolean = false,
+        val isProgress: Boolean = false,
+        val isLoginSuccess: Boolean = false,
+        val error: String? = null,
+        val currentUser: CurrentUser? = null,
+    )
+
+    fun getCurrentUser() {
+        if (_state.value!!.isProgress) return
+        _state.value = prev().copy(isProgress = true)
+
+        disposables.add(
+            apiService.getCurrentUser()
+                .timeout(10, TimeUnit.SECONDS)
+                .subscribeOn(Schedulers.io())
+                .observeOn(AndroidSchedulers.mainThread())
+                .subscribe({
+                    if (it.resultCode == 1) {
+                        _state.value = prev().copy(isProgress = false, isLoginSuccess = true, currentUser = it.data!!.obj)
+                    } else {
+                        _state.value =
+                            prev().copy(isProgress = false, error = "[${it.message.description}]")
+                    }
+                }, {
+                    val message: String = "ប្រតិបត្តិការមិនជោគជ័យ " + it.getErrorCode()
+                    _state.value = prev().copy(isProgress = false, error = message)
+                })
+        )
+    }
+}

+ 103 - 0
app/src/main/java/com/sambath/kunkhmer/screen/event/EventAdminFragment.kt

@@ -0,0 +1,103 @@
+package com.sambath.kunkhmer.screen.event
+
+import android.os.Bundle
+import androidx.fragment.app.Fragment
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.AdapterView
+import android.widget.ArrayAdapter
+import android.widget.Toast
+import com.sambath.kunkhmer.R
+import com.sambath.kunkhmer.app.App
+import com.sambath.kunkhmer.remote.Matches
+import com.sambath.kunkhmer.screen.fighter.FighterViewModel
+import com.sambath.kunkhmer.screen.fighter.FighterViewState
+import kotlinx.android.synthetic.main.fragment_event_admin.view.et_desc
+import kotlinx.android.synthetic.main.fragment_event_admin.view.et_title
+import kotlinx.android.synthetic.main.fragment_event_admin.view.submitButton
+import kotlinx.android.synthetic.main.fragment_lives_admin.view.spinner_match
+
+class EventAdminFragment : Fragment() {
+    private var _root: View? = null
+    private val binding get() = _root!!
+    private lateinit var eventViewModel: EventViewModel
+    private lateinit var matchViewModel: FighterViewModel
+    private lateinit var selectedId: String
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+    }
+
+    override fun onCreateView(
+        inflater: LayoutInflater, container: ViewGroup?,
+        savedInstanceState: Bundle?
+    ): View? {
+        _root = inflater.inflate(R.layout.fragment_event_admin, container, false)
+
+        eventViewModel = EventViewModel(App.injectApiService(), App.injectPrefHelper())
+        eventViewModel.state.observe(viewLifecycleOwner, androidx.lifecycle.Observer {
+            render(it)
+        })
+
+        matchViewModel = FighterViewModel(App.injectApiService(), App.injectPrefHelper())
+        matchViewModel.state.observe(viewLifecycleOwner, androidx.lifecycle.Observer {
+            renderMatch(it)
+        })
+        matchViewModel.getMatches()
+
+        setDefaultData()
+        binding.submitButton.setOnClickListener{
+            eventViewModel.createEvent(
+                binding.et_title.text.toString(),
+                binding.et_desc.text.toString(),
+                selectedId
+            )
+        }
+
+        // Inflate the layout for this fragment
+        return binding
+    }
+
+    private fun renderMatch(state: FighterViewState) {
+        if (state.isLoginSuccess) {
+            val matchesResponse = state.matchesData
+            val matches: List<Matches> = matchesResponse!!.obj
+            // Ensure matches is not null before mapping
+            val dropdownItems = matches?.map { it.title  }
+
+            val adapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_item, dropdownItems)
+            adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
+            binding.spinner_match.adapter = adapter
+            binding.spinner_match.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
+                override fun onItemSelected(parentView: AdapterView<*>, selectedItemView: View, position: Int, id: Long) {
+                    //  Get the selected Matches object
+                    val selectedMatch = matches[position]
+
+                    // Access the corresponding ID (it.matchInfo.id)
+                    selectedId = selectedMatch.matchInfo
+                }
+
+                override fun onNothingSelected(parentView: AdapterView<*>) {
+                    // Do nothing here
+                }
+            }
+
+        }
+    }
+
+    private fun setDefaultData() {
+        binding.et_title.setText("Prum Samnang VS Thoeun Theara")
+        binding.et_desc.setText("Prum Samnang VS Thoeun Theara")
+    }
+
+    private fun render(state: EventViewModel.EventViewState) {
+        if (state.isLoginSuccess) {
+            Toast.makeText(context, "Create Success...", Toast.LENGTH_LONG).show()
+
+            binding.et_title.setText("")
+            binding.et_desc.setText("")
+        }
+        // Other state handling...
+    }
+}

+ 60 - 0
app/src/main/java/com/sambath/kunkhmer/screen/event/EventFragment.kt

@@ -0,0 +1,60 @@
+package com.sambath.kunkhmer.screen.event
+
+import android.os.Bundle
+import androidx.fragment.app.Fragment
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.recyclerview.widget.LinearLayoutManager
+import com.sambath.kunkhmer.R
+import com.sambath.kunkhmer.adapter.EventAdapter
+import com.sambath.kunkhmer.adapter.EventCardItem
+import com.sambath.kunkhmer.app.App
+import kotlinx.android.synthetic.main.fragment_event.view.recyclerViewEvent
+
+class EventFragment : Fragment() {
+    private var _root: View? = null
+    private val binding get() = _root!!
+    private lateinit var eventViewModel: EventViewModel
+    private lateinit var eventAdapter: EventAdapter
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+    }
+
+    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+        _root = inflater.inflate(R.layout.fragment_event, container, false)
+
+        eventViewModel = EventViewModel(App.injectApiService(), App.injectPrefHelper())
+        eventViewModel.getEvents()
+        eventViewModel.state.observe(viewLifecycleOwner, androidx.lifecycle.Observer {
+            render(it)
+        })
+
+        setEvent()
+
+        return binding
+    }
+
+    private fun render(state: EventViewModel.EventViewState) {
+        if (state.isProgress) {
+        }
+        if (state.isLoginSuccess) {
+            if(state.eventsData != null) {
+                eventAdapter.cardList = state.eventsData
+                eventAdapter.notifyDataSetChanged()
+            }
+        }
+        if (state.error != null) {
+        }
+    }
+
+    private fun setEvent() {
+        val recyclerView = binding.recyclerViewEvent
+        eventAdapter = EventAdapter(mutableListOf())
+
+        recyclerView.layoutManager =
+            LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
+        recyclerView.adapter = eventAdapter
+    }
+}

+ 77 - 0
app/src/main/java/com/sambath/kunkhmer/screen/event/EventViewModel.kt

@@ -0,0 +1,77 @@
+package com.sambath.kunkhmer.screen.event
+
+import android.graphics.Bitmap
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import com.sambath.kunkhmer.app.getErrorCode
+import com.sambath.kunkhmer.base.BaseViewModel
+import com.sambath.kunkhmer.remote.CreateEventRequest
+import com.sambath.kunkhmer.remote.EventData
+import com.sambath.kunkhmer.remote.EventInfo
+import com.sambath.kunkhmer.remote.MatchesData
+import com.sambath.kunkhmer.remote.service.ApiService
+import com.sambath.kunkhmer.util.PrefHelper
+import io.reactivex.android.schedulers.AndroidSchedulers
+import io.reactivex.schedulers.Schedulers
+import java.util.concurrent.TimeUnit
+
+class EventViewModel(val apiService: ApiService, val prefHelper: PrefHelper) : BaseViewModel() {
+    private val _state = MutableLiveData<EventViewState>(EventViewState())
+    val state: LiveData<EventViewState> = _state
+    private fun prev() = _state.value!!
+
+    data class EventViewState(
+        val initial: Boolean = false,
+        val isProgress: Boolean = false,
+        val isLoginSuccess: Boolean = false,
+        val error: String? = null,
+        val eventsData: MutableList<EventInfo>? = null,
+    )
+
+    fun getEvents(){
+        if (_state.value!!.isProgress) return
+        _state.value = prev().copy(isProgress = true)
+
+        disposables.add(
+            apiService.getEvents()
+                .timeout(10, TimeUnit.SECONDS)
+                .subscribeOn(Schedulers.io())
+                .observeOn(AndroidSchedulers.mainThread())
+                .subscribe({
+                    if (it.resultCode == 1) {
+                        _state.value = prev().copy(isProgress = false, isLoginSuccess = true, eventsData = it.data!!.obj)
+                    } else {
+                        _state.value =
+                            prev().copy(isProgress = false, error = "[${it.message.description}]")
+                    }
+                }, {
+                    val message: String = "ប្រតិបត្តិការមិនជោគជ័យ " + it.getErrorCode()
+                    _state.value = prev().copy(isProgress = false, error = message)
+                })
+        )
+    }
+
+    fun createEvent(title: String, desc: String, matchFighterId: String){
+        if (_state.value!!.isProgress) return
+        _state.value = prev().copy(isProgress = true)
+        val request = CreateEventRequest(title, desc, matchFighterId)
+
+        disposables.add(
+            apiService.createEvent(request)
+                .timeout(10, TimeUnit.SECONDS)
+                .subscribeOn(Schedulers.io())
+                .observeOn(AndroidSchedulers.mainThread())
+                .subscribe({
+                    if (it.resultCode == 1) {
+                        _state.value = prev().copy(isProgress = false, isLoginSuccess = true)
+                    } else {
+                        _state.value =
+                            prev().copy(isProgress = false, error = "[${it.message.description}]")
+                    }
+                }, {
+                    val message: String = "ប្រតិបត្តិការមិនជោគជ័យ " + it.getErrorCode()
+                    _state.value = prev().copy(isProgress = false, error = message)
+                })
+        )
+    }
+}

+ 136 - 0
app/src/main/java/com/sambath/kunkhmer/screen/fighter/CreateFighterFragment.kt

@@ -0,0 +1,136 @@
+package com.sambath.kunkhmer.screen.fighter
+
+import android.app.Activity
+import android.content.Intent
+import android.net.Uri
+import android.os.Bundle
+import android.provider.MediaStore
+import androidx.fragment.app.Fragment
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ProgressBar
+import android.widget.Toast
+import androidx.activity.result.ActivityResultLauncher
+import androidx.activity.result.contract.ActivityResultContracts
+import com.sambath.kunkhmer.R
+import com.sambath.kunkhmer.app.App
+import kotlinx.android.synthetic.main.fragment_create_fighter.view.et_desc
+import kotlinx.android.synthetic.main.fragment_create_fighter.view.et_height
+import kotlinx.android.synthetic.main.fragment_create_fighter.view.et_name
+import kotlinx.android.synthetic.main.fragment_create_fighter.view.et_nationality
+import kotlinx.android.synthetic.main.fragment_create_fighter.view.et_weight
+import kotlinx.android.synthetic.main.fragment_create_fighter.view.submitButton
+import kotlinx.android.synthetic.main.fragment_create_fighter.view.uploadButton
+import kotlinx.android.synthetic.main.fragment_create_fighter.view.uploadedImageView
+
+
+class CreateFighterFragment : Fragment() {
+    private var _root: View? = null
+    private val binding get() = _root!!
+    private var imageUri: Uri? = null
+    private lateinit var fighterViewModel: FighterViewModel
+    private lateinit var loadingProgressBar: ProgressBar
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+    }
+
+    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+        // Inflate the layout for this fragment
+        _root = inflater.inflate(R.layout.fragment_create_fighter, container, false)
+
+        loadingProgressBar = binding.findViewById(R.id.loadingProgressBar)
+        fighterViewModel = FighterViewModel(App.injectApiService(), App.injectPrefHelper())
+        fighterViewModel.state.observe(viewLifecycleOwner, androidx.lifecycle.Observer {
+            render(it)
+        })
+
+        binding.uploadButton.setOnClickListener {
+            openImagePicker()
+        }
+
+        binding.submitButton.setOnClickListener {
+            // Show loading view
+            loadingProgressBar.visibility = View.VISIBLE
+
+            val imagePath = imageUri?.let { it1 -> getImagePathFromUri(it1) }
+            if (imagePath != null) {
+                fighterViewModel.createFighter(
+                    binding.et_name.text.toString(),
+                    binding.et_desc.text.toString(),
+                    binding.et_weight.text.toString(),
+                    binding.et_height.text.toString(),
+                    binding.et_nationality.text.toString(),
+                    imagePath
+                )
+            } else {
+                fighterViewModel.createFighter(
+                    binding.et_name.text.toString(),
+                    binding.et_desc.text.toString(),
+                    binding.et_weight.text.toString(),
+                    binding.et_height.text.toString(),
+                    binding.et_nationality.text.toString(),
+                    ""
+                )
+            }
+        }
+
+        setDefault()
+        return binding
+    }
+
+    private fun render(state: FighterViewState) {
+        if (state.isLoginSuccess) {
+            Toast.makeText(context, "Create Success...", Toast.LENGTH_LONG).show()
+            // Hide loading view
+            loadingProgressBar.visibility = View.GONE
+
+            binding.et_name.setText("")
+            binding.et_desc.setText("")
+            binding.et_weight.setText("")
+            binding.et_height.setText("")
+            binding.et_nationality.setText("")
+            binding.uploadedImageView.setImageDrawable(null)
+        }
+    }
+
+    private val imagePicker: ActivityResultLauncher<Intent> =
+        registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
+            if (result.resultCode == Activity.RESULT_OK) {
+                val data: Intent? = result.data
+                if (data != null) {
+                    imageUri = data.data // The URI of the selected image
+                    if (imageUri != null) {
+                        // Load and display the selected image in the ImageView
+                        binding.uploadedImageView.setImageURI(imageUri)
+                    }
+                }
+            }
+        }
+
+    private fun openImagePicker() {
+        val intent = Intent(Intent.ACTION_GET_CONTENT)
+        intent.type = "image/*"
+        imagePicker.launch(intent)
+    }
+
+    private fun getImagePathFromUri(uri: Uri): String? {
+        val contentResolver = requireContext().contentResolver
+        val cursor = contentResolver.query(uri, null, null, null, null)
+        cursor?.use {
+            it.moveToFirst()
+            val index = it.getColumnIndex(MediaStore.Images.ImageColumns.DATA)
+            return it.getString(index)
+        }
+        return null
+    }
+
+    private fun setDefault() {
+        binding.et_name.setText("John Cena")
+        binding.et_desc.setText("John Cena")
+        binding.et_weight.setText("66")
+        binding.et_height.setText("1,75")
+        binding.et_nationality.setText("US")
+    }
+}

+ 161 - 0
app/src/main/java/com/sambath/kunkhmer/screen/fighter/FighterAdminFragment.kt

@@ -0,0 +1,161 @@
+package com.sambath.kunkhmer.screen.fighter
+
+import android.app.DatePickerDialog
+import android.os.Bundle
+import androidx.fragment.app.Fragment
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.AdapterView
+import android.widget.ArrayAdapter
+import android.widget.Toast
+import androidx.navigation.findNavController
+import com.sambath.kunkhmer.R
+import com.sambath.kunkhmer.app.App
+import kotlinx.android.synthetic.main.fragment_fighter_admin.loadingProgressBar
+import kotlinx.android.synthetic.main.fragment_fighter_admin.view.et_date
+import kotlinx.android.synthetic.main.fragment_fighter_admin.view.et_desc
+import kotlinx.android.synthetic.main.fragment_fighter_admin.view.et_title
+import kotlinx.android.synthetic.main.fragment_fighter_admin.view.fighter_button
+import kotlinx.android.synthetic.main.fragment_fighter_admin.view.spinner_fighter_1
+import kotlinx.android.synthetic.main.fragment_fighter_admin.view.spinner_fighter_2
+import kotlinx.android.synthetic.main.fragment_fighter_admin.view.submitButton
+import java.text.SimpleDateFormat
+import java.util.Calendar
+
+class FighterAdminFragment : Fragment() {
+    private var _root: View? = null
+    private val binding get() = _root!!
+    private lateinit var fighterViewModel: FighterViewModel
+    private lateinit var selectedFighter1Id: String
+    private lateinit var selectedFighter2Id: String
+
+    private val calendar = Calendar.getInstance()
+    private val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS+0000")
+
+    private final val fighter1 = "650d97d08cc32f66d67c0b60"
+    private final val fighter2 = "650d98498cc32f66d67c0b65"
+    private final val desc = "Keo Rumchong VS Thiago Teixeira"
+    private final val title = "Keo Rumchong VS Thiago Teixeira"
+    private final val date = "2023-10-30T12:55:04.395+0000"
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+    }
+
+    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+        _root = inflater.inflate(R.layout.fragment_fighter_admin, container, false)
+
+        fighterViewModel = FighterViewModel(App.injectApiService(), App.injectPrefHelper())
+        fighterViewModel.state.observe(viewLifecycleOwner, androidx.lifecycle.Observer {
+            render(it)
+        })
+        fighterViewModel.getFighters()
+
+
+        binding.et_date.setOnClickListener {
+            showDatePickerDialog()
+        }
+        setDefaultData()
+
+        binding.submitButton.setOnClickListener {
+            loadingProgressBar.visibility = View.VISIBLE
+
+            fighterViewModel.createMatch(
+                binding.et_date.text.toString(),
+                binding.et_title.text.toString(),
+                binding.et_desc.text.toString(),
+                listOf(selectedFighter1Id, selectedFighter2Id)
+            )
+        }
+
+        binding.fighter_button.setOnClickListener {
+            requireActivity().findNavController(R.id.nav_host_fragment_activity_main).navigate(R.id.navigation_create_fighter)
+        }
+
+        // Inflate the layout for this fragment
+        return binding
+    }
+
+    private fun setDefaultData() {
+        binding.et_title.setText("Keo Rumchong VS Thiago Teixeira")
+        binding.et_desc.setText("Keo Rumchong VS Thiago Teixeira")
+    }
+
+    private fun showDatePickerDialog() {
+        val year = calendar.get(Calendar.YEAR)
+        val month = calendar.get(Calendar.MONTH)
+        val day = calendar.get(Calendar.DAY_OF_MONTH)
+
+        val datePickerDialog = DatePickerDialog(
+            requireContext(),
+            DatePickerDialog.OnDateSetListener { view, year, monthOfYear, dayOfMonth ->
+                // Update the calendar with the selected date
+                calendar.set(year, monthOfYear, dayOfMonth)
+
+                // Format the selected date and update the EditText text
+                val formattedDate = dateFormat.format(calendar.time)
+                binding.et_date.setText(formattedDate)
+            },
+            year,
+            month,
+            day
+        )
+
+        datePickerDialog.show()
+    }
+
+    private fun render(state: FighterViewState) {
+        if (state.isCreatedMatch) {
+            Toast.makeText(context, "Create Success...", Toast.LENGTH_LONG).show()
+            loadingProgressBar.visibility = View.GONE
+
+            binding.et_date.setText("")
+            binding.et_title.setText("")
+            binding.et_desc.setText("")
+        }
+
+        if (state.isGetFighters) {
+            val matchesData = state.fightersData!!
+            // Ensure matches is not null before mapping
+            val dropdownItems1 = matchesData.map { it.name  }
+
+            val adapter1 = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_item, dropdownItems1)
+            adapter1.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
+            binding.spinner_fighter_1.adapter = adapter1
+            binding.spinner_fighter_1.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
+                override fun onItemSelected(parentView: AdapterView<*>, selectedItemView: View, position: Int, id: Long) {
+                    //  Get the selected Matches object
+                    val selectedMatch = matchesData[position]
+
+                    // Access the corresponding ID (it.matchInfo.id)
+                    selectedFighter1Id = selectedMatch.id
+                }
+
+                override fun onNothingSelected(parentView: AdapterView<*>) {
+                    // Do nothing here
+                }
+            }
+            //
+            val dropdownItems2 = matchesData.map { it.name  }
+
+            val adapter2 = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_item, dropdownItems2)
+            adapter2.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
+            binding.spinner_fighter_2.adapter = adapter2
+            binding.spinner_fighter_2.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
+                override fun onItemSelected(parentView: AdapterView<*>, selectedItemView: View, position: Int, id: Long) {
+                    //  Get the selected Matches object
+                    val selectedMatch = matchesData[position]
+
+                    // Access the corresponding ID (it.matchInfo.id)
+                    selectedFighter2Id = selectedMatch.id
+                }
+
+                override fun onNothingSelected(parentView: AdapterView<*>) {
+                    // Do nothing here
+                }
+            }
+        }
+        // Other state handling...
+    }
+}

+ 109 - 0
app/src/main/java/com/sambath/kunkhmer/screen/fighter/FighterFragment.kt

@@ -0,0 +1,109 @@
+package com.sambath.kunkhmer.screen.fighter
+
+import android.content.Intent
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import androidx.recyclerview.widget.LinearLayoutManager
+import com.google.android.material.tabs.TabLayout
+import com.sambath.kunkhmer.R
+import com.sambath.kunkhmer.adapter.FighterAdapter
+import com.sambath.kunkhmer.adapter.FighterCardItem
+import com.sambath.kunkhmer.app.App
+import com.sambath.kunkhmer.app.MainActivity
+import com.sambath.kunkhmer.remote.MatchesData
+import com.sambath.kunkhmer.screen.login.LoginViewModel
+import com.sambath.kunkhmer.screen.login.LoginViewState
+import kotlinx.android.synthetic.main.activity_login.tv_error
+import kotlinx.android.synthetic.main.fragment_fighter.view.recyclerViewFighter
+import kotlinx.android.synthetic.main.fragment_fighter.view.selectedTabTextView
+import kotlinx.android.synthetic.main.fragment_fighter.view.tabLayout
+import java.util.Observer
+
+class FighterFragment : Fragment() {
+    private var _root: View? = null
+    private val binding get() = _root!!
+
+    // Inside your Fragment:
+    var tabSelectionListener: TabSelectionListener? = null
+    private lateinit var fighterViewModel: FighterViewModel
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+    }
+
+    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+        _root = inflater.inflate(R.layout.fragment_fighter, container, false)
+
+        fighterViewModel = FighterViewModel(App.injectApiService(), App.injectPrefHelper())
+        fighterViewModel.getMatches()
+        fighterViewModel.state.observe(viewLifecycleOwner, androidx.lifecycle.Observer {
+            render(it)
+        })
+
+        return binding
+    }
+
+    private fun render(state: FighterViewState) {
+        if (state.isProgress) {
+        }
+        if (state.isLoginSuccess) {
+            if(state.matchesData != null) {
+                setTab(state.matchesData)
+            }
+        }
+        if (state.error != null) {
+        }
+    }
+
+    private fun setTab(data: MatchesData) {
+        val tabTitles = listOf("Fri 18 Aug", "Yesterday", "Today", "Tomorrow", "Tue 22 Aug")
+
+        // Populate TabLayout with dynamic tabs
+        for (title in tabTitles) {
+            val tab = binding.tabLayout.newTab().setText(title)
+            binding.tabLayout.addTab(tab)
+        }
+
+        // Set tab click listener
+        binding.tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
+            override fun onTabSelected(tab: TabLayout.Tab?) {
+                tab?.let {
+                    val selectedTitle = it.text.toString()
+                    binding.selectedTabTextView.text = "Selected Tab: $selectedTitle"
+                    setFighters(data)
+                }
+            }
+
+            override fun onTabUnselected(tab: TabLayout.Tab?) {
+                // No action needed
+            }
+
+            override fun onTabReselected(tab: TabLayout.Tab?) {
+                // No action needed
+            }
+        })
+
+        binding.tabLayout.getTabAt(2)?.select()
+    }
+
+    private fun setFighters(data: MatchesData) {
+        val recyclerView = binding.recyclerViewFighter
+        //val cardList = createCardList() // Create your card data list here
+        val cardAdapter = FighterAdapter(data.obj, App.injectApiService())
+
+        recyclerView.layoutManager =
+            LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
+        recyclerView.adapter = cardAdapter
+    }
+
+    interface TabSelectionListener {
+        fun onTabSelected(tabIndex: Int)
+    }
+
+    fun selectTab(tabIndex: Int) {
+        binding.tabLayout.getTabAt(tabIndex)?.select()
+    }
+}

+ 163 - 0
app/src/main/java/com/sambath/kunkhmer/screen/fighter/FighterViewModel.kt

@@ -0,0 +1,163 @@
+package com.sambath.kunkhmer.screen.fighter
+
+import android.graphics.Bitmap
+import android.graphics.BitmapFactory
+import android.util.Log
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import com.sambath.kunkhmer.app.getErrorCode
+import com.sambath.kunkhmer.base.BaseViewModel
+import com.sambath.kunkhmer.remote.CreateMatchRequest
+import com.sambath.kunkhmer.remote.CreateNewsRequest
+import com.sambath.kunkhmer.remote.FightersInfo
+import com.sambath.kunkhmer.remote.MatchesData
+import com.sambath.kunkhmer.remote.service.ApiService
+import com.sambath.kunkhmer.util.PrefHelper
+import io.reactivex.android.schedulers.AndroidSchedulers
+import io.reactivex.schedulers.Schedulers
+import okhttp3.MediaType.Companion.toMediaTypeOrNull
+import okhttp3.MultipartBody
+import okhttp3.RequestBody.Companion.asRequestBody
+import okhttp3.RequestBody.Companion.toRequestBody
+import okhttp3.ResponseBody
+import java.io.File
+import java.util.concurrent.TimeUnit
+
+class FighterViewModel(val apiService: ApiService, val prefHelper: PrefHelper) : BaseViewModel() {
+    private val _state = MutableLiveData<FighterViewState>(FighterViewState())
+    val state: LiveData<FighterViewState> = _state
+    private fun prev() = _state.value!!
+
+    fun getMatches() {
+        if (_state.value!!.isProgress) return
+        _state.value = prev().copy(isProgress = true)
+
+        disposables.add(
+            apiService.getMatches()
+                .timeout(10, TimeUnit.SECONDS)
+                .subscribeOn(Schedulers.io())
+                .observeOn(AndroidSchedulers.mainThread())
+                .subscribe({
+                    if (it.resultCode == 1) {
+                        _state.value = prev().copy(isProgress = false, isLoginSuccess = true, matchesData = it.data!!)
+                    } else {
+                        _state.value =
+                            prev().copy(isProgress = false, error = "[${it.message.description}]")
+                    }
+                }, {
+                    val message: String = "ប្រតិបត្តិការមិនជោគជ័យ " + it.getErrorCode()
+                    _state.value = prev().copy(isProgress = false, error = message)
+                })
+        )
+    }
+
+    fun createMatch(date: String, title: String, desc: String, fighterId: List<String>) {
+        if (_state.value!!.isProgress) return
+        _state.value = prev().copy(isProgress = true)
+        val request = CreateMatchRequest(date, title, desc, fighterId)
+
+        disposables.add(
+            apiService.createMatch(request)
+                .timeout(10, TimeUnit.SECONDS)
+                .subscribeOn(Schedulers.io())
+                .observeOn(AndroidSchedulers.mainThread())
+                .subscribe({
+                    if (it.resultCode == 1) {
+                        _state.value = prev().copy(isProgress = false, isCreatedMatch = true)
+                    } else {
+                        _state.value =
+                            prev().copy(isProgress = false, error = "[${it.message.description}]")
+                    }
+                }, {
+                    val message: String = "ប្រតិបត្តិការមិនជោគជ័យ " + it.getErrorCode()
+                    _state.value = prev().copy(isProgress = false, error = message)
+                })
+        )
+    }
+
+    fun getFighters() {
+        if (_state.value!!.isProgress) return
+        _state.value = prev().copy(isProgress = true)
+
+        disposables.add(
+            apiService.getFighters()
+                .timeout(10, TimeUnit.SECONDS)
+                .subscribeOn(Schedulers.io())
+                .observeOn(AndroidSchedulers.mainThread())
+                .subscribe({
+                    if (it.resultCode == 1) {
+                        _state.value = prev().copy(isProgress = false, isGetFighters = true, fightersData = it.data!!.obj)
+                    } else {
+                        _state.value =
+                            prev().copy(isProgress = false, error = "[${it.message.description}]")
+                    }
+                }, {
+                    val message: String = "ប្រតិបត្តិការមិនជោគជ័យ " + it.getErrorCode()
+                    _state.value = prev().copy(isProgress = false, error = message)
+                })
+        )
+    }
+
+    fun createFighter(name: String, desc: String, weight: String, height: String, nationality: String, upload: String) {
+        if (_state.value!!.isProgress) return
+
+        val namePart = name.toRequestBody("text/plain".toMediaTypeOrNull())
+        val descPart = desc.toRequestBody("text/plain".toMediaTypeOrNull())
+        val weightPart = weight.toRequestBody("text/plain".toMediaTypeOrNull())
+        val heightPart = height.toRequestBody("text/plain".toMediaTypeOrNull())
+        val nationalityPart = nationality.toRequestBody("text/plain".toMediaTypeOrNull())
+
+        if (!upload.isNullOrEmpty()) {
+            val file = File(upload)
+            val filePart = MultipartBody.Part.createFormData("upload", file.name, file.asRequestBody("image/jpg".toMediaTypeOrNull()))
+            _state.value = prev().copy(isProgress = true)
+
+            disposables.add(
+                apiService.createFighter(namePart, descPart, weightPart, heightPart, nationalityPart, filePart)
+                    .timeout(60, TimeUnit.SECONDS)
+                    .subscribeOn(Schedulers.io())
+                    .observeOn(AndroidSchedulers.mainThread())
+                    .subscribe({
+                        Log.d("login", it.toString())
+                        if (it.resultCode == 1) {
+                            _state.value = prev().copy(isProgress = false, isLoginSuccess = true)
+                        } else {
+                            _state.value = prev().copy(isProgress = false, error = "[${it.message.description}]")
+                        }
+                    }, {
+                        val message: String = "ប្រតិបត្តិការមិនជោគជ័យ " + it.getErrorCode()
+                        _state.value = prev().copy(isProgress = false, error = message)
+                    })
+            )
+        } else {
+            disposables.add(
+                apiService.createFighter(namePart, descPart, weightPart, heightPart, nationalityPart)
+                    .timeout(60, TimeUnit.SECONDS)
+                    .subscribeOn(Schedulers.io())
+                    .observeOn(AndroidSchedulers.mainThread())
+                    .subscribe({
+                        Log.d("login", it.toString())
+                        if (it.resultCode == 1) {
+                            _state.value = prev().copy(isProgress = false, isLoginSuccess = true)
+                        } else {
+                            _state.value = prev().copy(isProgress = false, error = "[${it.message.description}]")
+                        }
+                    }, {
+                        val message: String = "ប្រតិបត្តិការមិនជោគជ័យ " + it.getErrorCode()
+                        _state.value = prev().copy(isProgress = false, error = message)
+                    })
+            )
+        }
+    }
+}
+
+data class FighterViewState(
+    val initial: Boolean = false,
+    val isProgress: Boolean = false,
+    val isLoginSuccess: Boolean = false,
+    val isCreatedMatch: Boolean = false,
+    val isGetFighters: Boolean = false,
+    val error: String? = null,
+    val matchesData: MatchesData? = null,
+    val fightersData: List<FightersInfo>? = null
+)

+ 40 - 0
app/src/main/java/com/sambath/kunkhmer/screen/lives/LiveDetailFragment.kt

@@ -0,0 +1,40 @@
+package com.sambath.kunkhmer.screen.lives
+
+import android.os.Bundle
+import androidx.fragment.app.Fragment
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.webkit.WebView
+import android.webkit.WebViewClient
+import com.sambath.kunkhmer.R
+
+class LiveDetailFragment : Fragment() {
+    private var _root: View? = null
+    private val binding get() = _root!!
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+    }
+
+    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+        _root = inflater.inflate(R.layout.fragment_live_detail, container, false)
+
+        // Retrieve data from arguments
+        val imageUrl = arguments?.getString("image_url")
+        val title = arguments?.getString("title")
+        val description = arguments?.getString("description")
+        val link = arguments?.getString("url") ?: "https://youtu.be/SyheySKTg-U?si=RCK3NV6AgSKEV6cM"
+        //val link = "https://youtu.be/SyheySKTg-U?si=RCK3NV6AgSKEV6cM"
+
+        val webView = binding.findViewById<WebView>(R.id.webView)
+
+        // Load a YouTube video by specifying the video URL
+        val youtubeVideoUrl = link
+        webView.settings.javaScriptEnabled = true
+        webView.webViewClient = WebViewClient()
+        webView.loadUrl(youtubeVideoUrl)
+
+        return binding
+    }
+}

+ 118 - 0
app/src/main/java/com/sambath/kunkhmer/screen/lives/LivesAdminFragment.kt

@@ -0,0 +1,118 @@
+package com.sambath.kunkhmer.screen.lives
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.AdapterView
+import android.widget.ArrayAdapter
+import android.widget.RadioButton
+import android.widget.Toast
+import androidx.fragment.app.Fragment
+import com.google.gson.Gson
+import com.google.gson.reflect.TypeToken
+import com.sambath.kunkhmer.R
+import com.sambath.kunkhmer.app.App
+import com.sambath.kunkhmer.remote.CreateLivesRequest
+import com.sambath.kunkhmer.remote.Matches
+import com.sambath.kunkhmer.remote.MatchesResponse
+import com.sambath.kunkhmer.screen.fighter.FighterViewModel
+import com.sambath.kunkhmer.screen.fighter.FighterViewState
+import kotlinx.android.synthetic.main.fragment_lives_admin.view.et_url
+import kotlinx.android.synthetic.main.fragment_lives_admin.view.radio_group_status
+import kotlinx.android.synthetic.main.fragment_lives_admin.view.spinner_match
+import kotlinx.android.synthetic.main.fragment_lives_admin.view.submitButton
+
+
+class LivesAdminFragment : Fragment() {
+    private var _root: View? = null
+    private val binding get() = _root!!
+    private lateinit var livesViewModel: LivesViewModel
+    private lateinit var matchViewModel: FighterViewModel
+    private lateinit var selectedId: String
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+    }
+
+    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+        // Inflate the layout for this fragment
+        _root = inflater.inflate(R.layout.fragment_lives_admin, container, false)
+        livesViewModel = LivesViewModel(App.injectApiService(), App.injectPrefHelper())
+        matchViewModel = FighterViewModel(App.injectApiService(), App.injectPrefHelper())
+
+        livesViewModel.state.observe(viewLifecycleOwner, androidx.lifecycle.Observer {
+            render(it)
+        })
+
+        matchViewModel.state.observe(viewLifecycleOwner, androidx.lifecycle.Observer {
+            renderMatch(it)
+        })
+        matchViewModel.getMatches()
+
+        setDefault()
+
+        binding.submitButton.setOnClickListener {
+            val selectedStatusId = binding.radio_group_status.checkedRadioButtonId
+            var status = false
+            if (selectedStatusId != -1) {
+                val selectedRadioButton: RadioButton = binding.findViewById(selectedStatusId)
+                val selectedValue: String = selectedRadioButton.text.toString()
+                if (selectedValue == "True") {
+                    status = true
+                }
+            }
+
+            val createLivesRequest = CreateLivesRequest(
+                selectedId, status, binding.et_url.text.toString()
+            )
+
+            //Toast.makeText(requireContext(), "$selectedId-$status",Toast.LENGTH_LONG).show()
+            livesViewModel.createLives(createLivesRequest.matchFighterId, createLivesRequest.status, createLivesRequest.url)
+        }
+
+        return binding
+    }
+
+    private fun setDefault() {
+        //binding.et_match_fighter_id.setText("650ea3b6b66ab4183c1657c1")
+        binding.et_url.setText("https://youtu.be/xZtadif15WU")
+    }
+
+    private fun renderMatch(state: FighterViewState) {
+        if (state.isLoginSuccess) {
+            val matchesResponse = state.matchesData
+            val matches: List<Matches> = matchesResponse!!.obj
+            // Ensure matches is not null before mapping
+            val dropdownItems = matches?.map { it.title  }
+
+            val adapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_item, dropdownItems)
+            adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
+            binding.spinner_match.adapter = adapter
+            binding.spinner_match.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
+                override fun onItemSelected(parentView: AdapterView<*>, selectedItemView: View, position: Int, id: Long) {
+                    //  Get the selected Matches object
+                    val selectedMatch = matches[position]
+
+                    // Access the corresponding ID (it.matchInfo.id)
+                    selectedId = selectedMatch.matchInfo
+                }
+
+                override fun onNothingSelected(parentView: AdapterView<*>) {
+                    // Do nothing here
+                }
+            }
+
+        }
+    }
+
+    private fun render(state: LivesViewModel.LivesViewState) {
+        if (state.isLoginSuccess) {
+            Toast.makeText(context, "Create Success...", Toast.LENGTH_LONG).show()
+
+            //binding.et_match_fighter_id.setText("")
+            binding.et_url.setText("")
+        }
+        // Other state handling...
+    }
+}

+ 111 - 0
app/src/main/java/com/sambath/kunkhmer/screen/lives/LivesFragment.kt

@@ -0,0 +1,111 @@
+package com.sambath.kunkhmer.screen.lives
+
+import android.os.Bundle
+import androidx.fragment.app.Fragment
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Toast
+import androidx.appcompat.app.AppCompatActivity
+import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.RecyclerView
+import com.sambath.kunkhmer.R
+import com.sambath.kunkhmer.adapter.LivesAdapter
+import com.sambath.kunkhmer.adapter.LivesCardItem
+import com.sambath.kunkhmer.adapter.ProductAdapter
+import com.sambath.kunkhmer.app.App
+import com.sambath.kunkhmer.remote.LivesInfo
+import com.sambath.kunkhmer.screen.shop.ShopViewModel
+import kotlinx.android.synthetic.main.fragment_event.view.recyclerViewEvent
+import kotlinx.android.synthetic.main.fragment_lives.view.recyclerViewLives
+
+class LivesFragment : Fragment(), LivesAdapter.OnItemClickListener  {
+    private var _root: View? = null
+    private val binding get() = _root!!
+    private var cardList: List<LivesInfo>? = null
+    private lateinit var livesAdapter: LivesAdapter
+    private lateinit var livesViewModel: LivesViewModel
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+    }
+
+    override fun onCreateView(
+        inflater: LayoutInflater, container: ViewGroup?,
+        savedInstanceState: Bundle?
+    ): View? {
+        // Inflate the layout for this fragment
+        _root = inflater.inflate(R.layout.fragment_lives, container, false)
+
+        livesAdapter = LivesAdapter(mutableListOf(), this)
+        livesViewModel = LivesViewModel(App.injectApiService(), App.injectPrefHelper())
+        livesViewModel.getLives()
+        livesViewModel.state.observe(viewLifecycleOwner, androidx.lifecycle.Observer {
+            render(it)
+        })
+
+        val recyclerView = binding.recyclerViewLives
+        recyclerView.layoutManager =
+            LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
+        recyclerView.adapter = livesAdapter
+
+        return binding
+    }
+
+    private fun render(state: LivesViewModel.LivesViewState) {
+        if (state.isLoginSuccess) {
+            if(state.livesData != null) {
+                livesAdapter.cardList = state.livesData
+                cardList = livesAdapter.cardList
+                livesAdapter.notifyDataSetChanged()
+            }
+        }
+        // Other state handling...
+    }
+
+//    private fun setEvent() {
+//        val recyclerView = binding.recyclerViewLives
+//        cardList = createCardList() // Create your card data list here
+//        val cardAdapter = LivesAdapter(cardList!!, this)
+//
+//        recyclerView.layoutManager =
+//            LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
+//        recyclerView.adapter = cardAdapter
+//    }
+
+//    private fun createCardList(): List<LivesCardItem> {
+//        // Create and return your list of CardItems
+//        return listOf(
+//            LivesCardItem("https://i.ytimg.com/vi/Lh5O00zo_pc/hq720.jpg?sqp=-oaymwEcCOgCEMoBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLCEQ100buCWUuyBKWe_96UbevbIEA",
+//                "ផ្សាយបន្តផ្ទាល់កម្មវិធីប្រដាល់ Krud គុនខ្មែរ", "ឃឹម បូរ៉ា (ខ្មែរ) Vs ពេជ្រ សម្បត្តិ"),
+//            LivesCardItem("https://i.ytimg.com/vi/Lh5O00zo_pc/hq720.jpg?sqp=-oaymwEcCOgCEMoBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLCEQ100buCWUuyBKWe_96UbevbIEA",
+//                "ផ្សាយបន្តផ្ទាល់កម្មវិធីប្រដាល់ Krud គុនខ្មែរ", "ឃឹម បូរ៉ា (ខ្មែរ) Vs ពេជ្រ សម្បត្តិ"),
+//            LivesCardItem("https://i.ytimg.com/vi/Lh5O00zo_pc/hq720.jpg?sqp=-oaymwEcCOgCEMoBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLCEQ100buCWUuyBKWe_96UbevbIEA",
+//                "ផ្សាយបន្តផ្ទាល់កម្មវិធីប្រដាល់ Krud គុនខ្មែរ", "ឃឹម បូរ៉ា (ខ្មែរ) Vs ពេជ្រ សម្បត្តិ"),
+//            LivesCardItem("https://i.ytimg.com/vi/Lh5O00zo_pc/hq720.jpg?sqp=-oaymwEcCOgCEMoBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLCEQ100buCWUuyBKWe_96UbevbIEA",
+//                "ផ្សាយបន្តផ្ទាល់កម្មវិធីប្រដាល់ Krud គុនខ្មែរ", "ឃឹម បូរ៉ា (ខ្មែរ) Vs ពេជ្រ សម្បត្តិ"),
+//            LivesCardItem("https://i.ytimg.com/vi/Lh5O00zo_pc/hq720.jpg?sqp=-oaymwEcCOgCEMoBSFXyq4qpAw4IARUAAIhCGAFwAcABBg==&rs=AOn4CLCEQ100buCWUuyBKWe_96UbevbIEA",
+//                "ផ្សាយបន្តផ្ទាល់កម្មវិធីប្រដាល់ Krud គុនខ្មែរ", "ឃឹម បូរ៉ា (ខ្មែរ) Vs ពេជ្រ សម្បត្តិ"),
+//            // Add more card items as needed
+//        )
+//    }
+
+    override fun onItemClick(position: Int) {
+        val clickedItem = cardList!![position]
+        val liveDetailFragment = LiveDetailFragment()
+
+        // You can pass data to the LiveDetailFragment using arguments if needed
+        val bundle = Bundle()
+        bundle.putString("image_url", clickedItem.filename)
+        bundle.putString("title", clickedItem.name)
+        bundle.putString("description", clickedItem.desc)
+        bundle.putString("url", clickedItem.url)
+        liveDetailFragment.arguments = bundle
+
+        // Replace the current fragment with the LiveDetailFragment
+        parentFragmentManager.beginTransaction()
+            .replace(R.id.nav_host_fragment_activity_main, liveDetailFragment)
+            .addToBackStack(null) // Add to back stack to handle the back navigation
+            .commit()
+    }
+}

+ 76 - 0
app/src/main/java/com/sambath/kunkhmer/screen/lives/LivesViewModel.kt

@@ -0,0 +1,76 @@
+package com.sambath.kunkhmer.screen.lives
+
+import android.util.Log
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import com.sambath.kunkhmer.app.getErrorCode
+import com.sambath.kunkhmer.base.BaseViewModel
+import com.sambath.kunkhmer.remote.CreateLivesRequest
+import com.sambath.kunkhmer.remote.CreateProductRequest
+import com.sambath.kunkhmer.remote.LivesInfo
+import com.sambath.kunkhmer.remote.service.ApiService
+import com.sambath.kunkhmer.util.PrefHelper
+import io.reactivex.android.schedulers.AndroidSchedulers
+import io.reactivex.schedulers.Schedulers
+import java.util.concurrent.TimeUnit
+
+class LivesViewModel(val apiService: ApiService, val prefHelper: PrefHelper) : BaseViewModel() {
+    private val _state = MutableLiveData(LivesViewState())
+    val state: LiveData<LivesViewState> = _state
+    private fun prev() = _state.value!!
+
+    data class LivesViewState(
+        val initial: Boolean = false,
+        val isProgress: Boolean = false,
+        val isLoginSuccess: Boolean = false,
+        val error: String? = null,
+        val livesData: MutableList<LivesInfo>? = null,
+    )
+
+    fun getLives() {
+        if (_state.value!!.isProgress) return
+        _state.value = prev().copy(isProgress = true)
+
+        disposables.add(
+            apiService.getLives()
+                .timeout(10, TimeUnit.SECONDS)
+                .subscribeOn(Schedulers.io())
+                .observeOn(AndroidSchedulers.mainThread())
+                .subscribe({
+                    if (it.resultCode == 1) {
+                        _state.value = prev().copy(isProgress = false, isLoginSuccess = true, livesData = it.data!!.obj)
+                    } else {
+                        _state.value =
+                            prev().copy(isProgress = false, error = "[${it.message.description}]")
+                    }
+                }, {
+                    val message: String = "ប្រតិបត្តិការមិនជោគជ័យ " + it.getErrorCode()
+                    _state.value = prev().copy(isProgress = false, error = message)
+                })
+        )
+    }
+
+    fun createLives(match_fighter_id: String, status: Boolean, url: String) {
+        if (_state.value!!.isProgress) return
+        _state.value = prev().copy(isProgress = true)
+        val request = CreateLivesRequest(match_fighter_id, status, url)
+
+        disposables.add(
+            apiService.createLives(request)
+                .timeout(10, TimeUnit.SECONDS)
+                .subscribeOn(Schedulers.io())
+                .observeOn(AndroidSchedulers.mainThread())
+                .subscribe({
+                    Log.d("login", it.toString())
+                    if (it.resultCode == 1) {
+                        _state.value = prev().copy(isProgress = false, isLoginSuccess = true)
+                    } else {
+                        _state.value = prev().copy(isProgress = false, error = "[${it.message.description}]")
+                    }
+                }, {
+                    val message: String = "ប្រតិបត្តិការមិនជោគជ័យ " + it.getErrorCode() + it.message
+                    _state.value = prev().copy(isProgress = false, error = message)
+                })
+        )
+    }
+}

+ 80 - 0
app/src/main/java/com/sambath/kunkhmer/screen/login/LoginActivity.kt

@@ -0,0 +1,80 @@
+package com.sambath.kunkhmer.screen.login
+
+import android.content.Intent
+import android.os.Bundle
+import androidx.appcompat.app.AppCompatActivity
+import androidx.lifecycle.Observer
+import com.sambath.kunkhmer.R
+import com.sambath.kunkhmer.app.AdminActivity
+import com.sambath.kunkhmer.app.App
+import com.sambath.kunkhmer.app.MainActivity
+import com.sambath.kunkhmer.app.ShareActivity
+import com.sambath.kunkhmer.remote.User
+import com.sambath.kunkhmer.screen.register.RegisterActivity
+import com.sambath.kunkhmer.util.Const
+import com.sambath.kunkhmer.util.ModelPreferencesManager
+import kotlinx.android.synthetic.main.activity_login.*
+
+class LoginActivity : AppCompatActivity() {
+    //private val loginViewModel = App.injectLoginViewModel()
+    private lateinit var loginViewModel: LoginViewModel
+    private var user: User? = null
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        loginViewModel = LoginViewModel(App.injectApiService(), App.injectPrefHelper())
+        super.onCreate(savedInstanceState)
+        setContentView(R.layout.activity_login)
+        /*user = ModelPreferencesManager.get<User>(Const.USER_KEY)
+        if (user != null) et_username.setText(user?.userName)*/
+        loginViewModel.state.observe(this, Observer(this::render))
+        btn_login.setOnClickListener {
+            til_username.isErrorEnabled = false
+            til_username.error = null
+            til_password.isErrorEnabled = false
+            til_password.error = null
+            val username = et_username.text
+            val password = et_password.text
+            if (username.isNullOrEmpty()) {
+                til_username.error = getString(R.string.err_not_empty)
+                til_username.requestFocus()
+                return@setOnClickListener
+            }
+            if (password.isNullOrEmpty()) {
+                til_password.error = getString(R.string.err_not_empty)
+                til_password.requestFocus()
+                return@setOnClickListener
+            }
+            loginViewModel.login(username.toString(), password.toString())
+        }
+
+        btn_signup.setOnClickListener {
+            val intent = Intent(this, RegisterActivity::class.java)
+            startActivity(intent)
+            finishAffinity()
+        }
+    }
+
+    private fun render(state: LoginViewState) {
+        if (state.isProgress) {
+            tv_error.text = ""
+        }
+        if (state.isLoginSuccess) {
+            if (state.userName == "kk001") {
+                val intent = Intent(this, AdminActivity::class.java)
+                startActivity(intent)
+                finishAffinity()
+            } else {
+                val intent = Intent(this, MainActivity::class.java)
+                startActivity(intent)
+                finishAffinity()
+            }
+        }
+        if (state.error != null) {
+            tv_error.text = state.error
+        }
+    }
+
+    override fun onDestroy() {
+        super.onDestroy()
+    }
+}

+ 50 - 0
app/src/main/java/com/sambath/kunkhmer/screen/login/LoginViewModel.kt

@@ -0,0 +1,50 @@
+package com.sambath.kunkhmer.screen.login
+
+import android.util.Log
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import com.sambath.kunkhmer.app.getErrorCode
+import com.sambath.kunkhmer.base.BaseViewModel
+import com.sambath.kunkhmer.remote.service.ApiService
+import com.sambath.kunkhmer.remote.LoginRequest
+import com.sambath.kunkhmer.util.Const
+import com.sambath.kunkhmer.util.ModelPreferencesManager
+import com.sambath.kunkhmer.util.PrefHelper
+import io.reactivex.android.schedulers.AndroidSchedulers
+import io.reactivex.schedulers.Schedulers
+import java.util.concurrent.TimeUnit
+
+class LoginViewModel(val apiService: ApiService, val prefHelper: PrefHelper) : BaseViewModel() {
+    private val _state = MutableLiveData<LoginViewState>(LoginViewState())
+    val state: LiveData<LoginViewState> = _state
+
+    fun login(username: String, password: String) {
+        if (_state.value!!.isProgress) return
+        val request = LoginRequest(username, password)
+        _state.value = prev().copy(isProgress = true)
+
+        disposables.add(
+            apiService.login(request)
+                .timeout(10, TimeUnit.SECONDS)
+                .subscribeOn(Schedulers.io())
+                .observeOn(AndroidSchedulers.mainThread())
+                .subscribe({
+                    Log.d("login", it.toString())
+                    if (it.resultCode == 1) {
+                        _state.value = prev().copy(isProgress = false, isLoginSuccess = true, userName = it.data?.user?.userName)
+                        prefHelper.setUserToken(it.data?.token ?: "")
+                        prefHelper.setChannelType(1)
+                        ModelPreferencesManager.put(it.data?.user, Const.USER_KEY)
+                    } else {
+                        _state.value =
+                            prev().copy(isProgress = false, error = "[${it.message.description}]")
+                    }
+                }, {
+                    val message: String = "ប្រតិបត្តិការមិនជោគជ័យ " + it.getErrorCode()
+                    _state.value = prev().copy(isProgress = false, error = message)
+                })
+        )
+    }
+
+    private fun prev() = _state.value!!
+}

+ 9 - 0
app/src/main/java/com/sambath/kunkhmer/screen/login/LoginViewState.kt

@@ -0,0 +1,9 @@
+package com.sambath.kunkhmer.screen.login
+
+data class LoginViewState(
+    val initial: Boolean = false,
+    val isProgress: Boolean = false,
+    val isLoginSuccess: Boolean = false,
+    val error: String? = null,
+    val userName: String? = null
+)

+ 21 - 0
app/src/main/java/com/sambath/kunkhmer/screen/main/MainAdapter.kt

@@ -0,0 +1,21 @@
+package com.sambath.kunkhmer.screen.main
+
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.recyclerview.widget.RecyclerView
+import com.gdtlib.lib.adapter.BaseListAdapter
+import com.sambath.kunkhmer.R
+
+class MainAdapter(private val myBettingId: String): BaseListAdapter() {
+    var printButtonListener: ((String, String, String, String, String, String) -> Unit) ?= null
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder =
+        MainListViewHolder(
+            LayoutInflater.from(parent.context).inflate(
+                R.layout.item_table_holder,
+                parent,
+                false
+            ),myBettingId, printButtonListener
+        )
+
+
+}

+ 22 - 0
app/src/main/java/com/sambath/kunkhmer/screen/main/MainDataViewState.kt

@@ -0,0 +1,22 @@
+package com.sambath.kunkhmer.screen.main
+
+import com.sambath.kunkhmer.remote.*
+
+data class MainDataViewState(
+//    val isSuccess: Boolean = false,
+//    val channel: Channel? = null,
+//    val initial: Boolean = false,
+//    val isProgress: Boolean = false,
+//    val error: String? = null,
+//    val lastResult: LastResult? = null,
+
+    val isChPro: Boolean = false,
+    val errorCh: String? = null,
+    val channelInfo: ChannelData? = null,
+    val isChSuccess: Boolean = false,
+
+    val isUserPro: Boolean = false,
+    val errorUser: String? = null,
+    val userInfo: User? = null,
+    val isUserSuccess: Boolean = false,
+)

+ 170 - 0
app/src/main/java/com/sambath/kunkhmer/screen/main/MainFragment.kt

@@ -0,0 +1,170 @@
+package com.sambath.kunkhmer.screen.main
+
+import android.annotation.SuppressLint
+import android.media.MediaPlayer
+import android.os.Bundle
+import android.view.View
+import android.view.animation.AlphaAnimation
+import android.view.animation.Animation
+import androidx.core.view.isVisible
+import androidx.fragment.app.Fragment
+import androidx.viewpager2.widget.ViewPager2
+import com.google.android.material.tabs.TabLayout
+import com.google.android.material.tabs.TabLayoutMediator
+import com.sambath.kunkhmer.R
+import com.sambath.kunkhmer.adapter.MainPagerAdapter
+import com.sambath.kunkhmer.app.App
+import com.sambath.kunkhmer.app.ShareActivity
+import com.sambath.kunkhmer.base.BaseFragment
+import com.sambath.kunkhmer.extension.btnClick
+import com.sambath.kunkhmer.remote.User
+import com.sambath.kunkhmer.screen.main.cflive.Betting.CfBetFragment
+import com.sambath.kunkhmer.screen.main.cflive.result.CfResultFragment
+import com.sambath.kunkhmer.screen.report.StatementFragment
+import com.sambath.kunkhmer.screen.setting.SettingFragment
+import com.sambath.kunkhmer.view.SettingButtonView
+
+/**
+ * A simple [Fragment] subclass as the default destination in the navigation.
+ */
+class MainFragment : BaseFragment(R.layout.fragment_main) {
+//    private val TAB_TITLES = arrayOf(
+//        R.string.current_bets,
+//        R.string.today_report,
+//    )
+//    private lateinit var mainViewModel: MainViewModel
+//    private val shareViewModel = App.injectShareViewModel()
+//    private val sharePref = App.injectPrefHelper()
+//    private lateinit var user: User
+//    private lateinit var btnPlay: SettingButtonView
+//    private lateinit var btnResult: SettingButtonView
+//    private lateinit var betTouch: MediaPlayer
+//    lateinit var result: MediaPlayer
+//    private var anim: AlphaAnimation? = null
+//    override fun onCreate(savedInstanceState: Bundle?) {
+////        mainViewModel = MainViewModel(App.injectApiService(), App.injectPrefHelper())
+//        super.onCreate(savedInstanceState)
+//        //companyInfoId =arguments?.getInt(COM_INTO_ID_KEY) ?: 0
+//        (requireActivity() as ShareActivity).apply {
+//            user = userShare
+//        }
+//        anim = AlphaAnimation(0.0f, 1.0f)
+//        anim?.duration = 50 //You can manage the blinking time with this parameter
+//        anim?.startOffset = 50
+//        anim?.repeatMode = Animation.REVERSE
+//        anim?.repeatCount = Animation.INFINITE
+//    }
+//
+//    @SuppressLint("CheckResult")
+//    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+//        super.onViewCreated(view, savedInstanceState)
+////        mainViewModel.state.observe(viewLifecycleOwner, androidx.lifecycle.Observer {
+////            getMainData(it)
+////        })
+////        mainViewModel.getMainData()
+////        (requireActivity() as ShareActivity).apply {
+////            userNameTextView.text = user.userName
+////        }
+//        val mainPagerAdapter = MainPagerAdapter(requireActivity() as ShareActivity)
+//        val viewPager: ViewPager2 = view.findViewById(R.id.view_pager)
+//        viewPager.adapter = mainPagerAdapter
+//        val tabs: TabLayout = view.findViewById(R.id.tabLayout)
+//        TabLayoutMediator(
+//            tabs, viewPager
+//        ) { tab, position -> // Styling each tab here
+//            tab.text = getString(TAB_TITLES[position])
+//        }.attach()
+////        shareViewModel.getConnectivityStates.observe(viewLifecycleOwner, Observer {
+////            getSocketConectionStatus(it)
+////        })
+//        btnPlay = view.findViewById(R.id.btn_play)
+//        btnPlay.setOnClickListener {
+////            if (!sharePref.getIsMute()) betTouch.start()
+//            it.btnClick().subscribe {
+////                btnPlay.isEnabled = false
+//                (requireActivity() as? ShareActivity)?.apply {
+//                    supportFragmentManager.beginTransaction()
+//                        .setCustomAnimations(
+//                            R.anim.slide_in,
+//                            R.anim.slide_out,
+//                            R.anim.slide_in_exit,
+//                            R.anim.slide_out_exit
+//                        )
+//                        .add(R.id.container, CfBetFragment().apply {
+//                            arguments =
+//                                Bundle().apply {
+//                                    // putInt(Fragment7.COM_INFO_ID_KEY, companyInfoId)
+//                                }
+//                        })
+//                        .addToBackStack(null)
+//                        .commit()
+//                }
+//            }
+//        }
+//        btnResult = view.findViewById(R.id.btn_result)
+//        btnResult.setOnClickListener {
+////            if (!sharePref.getIsMute()) betTouch.start()
+//            it.btnClick().subscribe {
+////                btnResult.isEnabled = false
+//                (requireActivity() as? ShareActivity)?.apply {
+//                    supportFragmentManager.beginTransaction()
+//                        .setCustomAnimations(
+//                            R.anim.slide_in,
+//                            R.anim.slide_out,
+//                            R.anim.slide_in_exit,
+//                            R.anim.slide_out_exit
+//                        )
+//                        .add(R.id.container, CfResultFragment().apply {
+//                            arguments =
+//                                Bundle().apply {
+//                                    // putInt(Fragment7.COM_INFO_ID_KEY, companyInfoId)
+//                                }
+//                        })
+//                        .addToBackStack(null)
+//                        .commit()
+//                }
+//            }
+//        }
+//        (requireActivity() as? ShareActivity)?.apply {
+//            groupToolbarIcons.isVisible = true
+//            layCfStatus.isVisible = true
+//            settingImageView.setOnClickListener {
+////                if (!sharePref.getIsMute()) betTouch.start()
+//                it.btnClick().subscribe {
+//                    supportFragmentManager.beginTransaction()
+//                        .setCustomAnimations(
+//                            R.anim.slide_in,
+//                            R.anim.slide_out,
+//                            R.anim.slide_in_exit,
+//                            R.anim.slide_out_exit
+//                        )
+//                        .add(R.id.container, SettingFragment())
+//                        .addToBackStack(null)
+//                        .commit()
+//                }
+//            }
+//
+//            reportImageView.setOnClickListener {
+////                if (!sharePref.getIsMute()) betTouch.start()
+//                layCfStatus.isVisible = true
+//                it.btnClick().subscribe {
+//                    supportFragmentManager.beginTransaction()
+//                        .setCustomAnimations(
+//                            R.anim.slide_in,
+//                            R.anim.slide_out,
+//                            R.anim.slide_in_exit,
+//                            R.anim.slide_out_exit
+//                        )
+//                        .add(R.id.container, StatementFragment().apply {
+//                            arguments =
+//                                Bundle().apply {
+//                                    // putInt(Fragment7.COM_INFO_ID_KEY, companyInfoId)
+//                                }
+//                        })
+//                        .addToBackStack(null)
+//                        .commit()
+//                }
+//            }
+//        }
+//    }
+}

部分文件因为文件数量过多而无法显示