Browse Source

Merge branch 'add-firebase' of gitlab.com:jetup/truthordare into main

pull/1/head
Vitalik 2 years ago
parent
commit
97b6738126
  1. 7
      App.tsx
  2. 8
      ReactotronConfig.js
  3. 3
      android/app/build.gradle
  4. 47
      android/app/google-services.json
  5. 1
      android/build.gradle
  6. 36
      ios/GoogleService-Info.plist
  7. 9
      ios/Podfile
  8. 943
      ios/Podfile.lock
  9. 66
      ios/Truth.xcodeproj/project.pbxproj
  10. 2
      ios/Truth/AppDelegate.m
  11. 10
      iosDuplicate/Truth.xcworkspace/contents.xcworkspacedata
  12. 8
      iosDuplicate/Truth.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
  13. 10
      iosDuplicate1/Truth.xcworkspace/contents.xcworkspacedata
  14. 901
      package-lock.json
  15. 5
      package.json
  16. 16
      src/assets/icons/ENG.svg
  17. 14
      src/assets/icons/UAE.svg
  18. 11
      src/assets/icons/UKR.svg
  19. 4
      src/i18n/locales/en/custom-pack.translation.ts
  20. 6
      src/i18n/locales/en/index.ts
  21. 8
      src/i18n/locales/en/onBoardingButton.translation.ts
  22. 5
      src/i18n/locales/en/page-title.translation.ts
  23. 4
      src/i18n/locales/hi/custom-pack.translation.ts
  24. 7
      src/i18n/locales/hi/index.tsx
  25. 8
      src/i18n/locales/hi/onBoardingButton.translation.ts
  26. 5
      src/i18n/locales/hi/page-title.translation.ts
  27. 2
      src/i18n/locales/hi/steps.translation.ts
  28. 4
      src/i18n/locales/ua/custom-pack.translation.ts
  29. 9
      src/i18n/locales/ua/index.ts
  30. 8
      src/i18n/locales/ua/onBoardingButton.translation.ts
  31. 5
      src/i18n/locales/ua/page-title.translation.ts
  32. 6
      src/i18n/locales/ua/step.translation.ts
  33. 8
      src/i18n/types/buttons.types.ts
  34. 6
      src/i18n/types/index.ts
  35. 17
      src/module/game/screen/select-packages.screen.tsx
  36. 12
      src/module/package/atoms/create-custom-package.atom.tsx
  37. 18
      src/module/package/components/packages-item.component.tsx
  38. 1
      src/module/package/components/packages-list.tsx
  39. 5
      src/module/privacy-policy/config/privacy-texts.ts
  40. 42
      src/module/privacy-policy/screens/privacy-policy.tsx
  41. 40
      src/module/root/atoms/premium-button.component.tsx
  42. 4
      src/module/root/components/language-item.component.tsx
  43. 13
      src/module/root/navigations-groups/on-boardings-group.tsx
  44. 20
      src/module/root/screens/game.tsx
  45. 12
      src/module/root/screens/language-select.screen.tsx
  46. 40
      src/module/root/screens/loading-screen.tsx
  47. 14
      src/module/root/screens/on-boarding.screen.tsx
  48. 55
      src/module/root/screens/questions.tsx
  49. 5
      src/module/root/screens/settings.screen.tsx
  50. 65
      src/module/services/game-items/game-items-slice.ts
  51. 19
      src/module/setting/components/Settings-Item.component.tsx
  52. 27
      src/module/shared/components/buttons/red-button.tsx
  53. 9
      src/module/shared/components/header/header.component.tsx
  54. 10
      src/module/shared/components/modals/main-modal.tsx
  55. 0
      src/module/shared/components/name-title/name-title.tsx
  56. 32
      src/module/shared/components/question-block/question-block.tsx
  57. 36
      src/module/shared/components/text-containers/main-text-container.tsx
  58. 6
      src/module/shared/config/default-packages.tsx
  59. 2
      src/module/shared/enums/route-keys.ts
  60. 4
      src/module/shared/helpers/helper-height-view.ts
  61. 4
      src/module/shared/interfaces/custom-pack.ts
  62. 7
      src/module/shared/interfaces/game-item.ts
  63. 5
      src/module/shared/interfaces/page-titles.ts
  64. 2
      src/module/terms-of-use/config/terms-text.ts
  65. 6
      src/module/terms-of-use/config/use-of-terms.translations.ts
  66. 43
      src/module/terms-of-use/screens/use-of-terms.tsx
  67. 13
      src/store/store.ts

7
App.tsx

@ -3,7 +3,12 @@ import SplashScreen from 'react-native-splash-screen'; @@ -3,7 +3,12 @@ import SplashScreen from 'react-native-splash-screen';
import {Navigation} from './src/module/root';
import './src/i18n/index';
import {Provider} from 'react-redux';
import { store } from './src/store/store';
import {store} from './src/store/store';
if (__DEV__) {
import('./ReactotronConfig').then(() => console.log('Reactotron Configured'));
}
const App = () => {
useEffect(() => {
SplashScreen.hide();

8
ReactotronConfig.js

@ -0,0 +1,8 @@ @@ -0,0 +1,8 @@
import AsyncStorage from '@react-native-async-storage/async-storage'
import Reactotron from 'reactotron-react-native'
Reactotron
.setAsyncStorageHandler(AsyncStorage) // AsyncStorage would either come from `react-native` or `@react-native-community/async-storage` depending on where you get it from
.configure() // controls connection & communication settings
.useReactNative() // add all built-in react native plugins
.connect() // let's connect!

3
android/app/build.gradle

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
apply plugin: "com.android.application"
apply plugin: 'com.google.gms.google-services'
import com.android.build.OutputFile
@ -136,6 +137,7 @@ android { @@ -136,6 +137,7 @@ android {
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1
versionName "1.0"
multiDexEnabled true
}
splits {
abi {
@ -196,6 +198,7 @@ dependencies { @@ -196,6 +198,7 @@ dependencies {
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"
implementation project(':react-native-svg')
implementation project(':react-native-vector-icons')
implementation 'com.android.support:multidex:2.0.1'
debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") {
exclude group:'com.facebook.fbjni'

47
android/app/google-services.json

@ -0,0 +1,47 @@ @@ -0,0 +1,47 @@
{
"project_info": {
"project_number": "180425292880",
"firebase_url": "https://truthordare-6493e-default-rtdb.europe-west1.firebasedatabase.app",
"project_id": "truthordare-6493e",
"storage_bucket": "truthordare-6493e.appspot.com"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:180425292880:android:8690e5274abb413c7da555",
"android_client_info": {
"package_name": "com.truth"
}
},
"oauth_client": [
{
"client_id": "180425292880-1pfj1drhgqc9j19jit1ahfu7jouodjej.apps.googleusercontent.com",
"client_type": 3
}
],
"api_key": [
{
"current_key": "AIzaSyBXoidUFjbE84RZ8PqIP0IGAsTYU28PEO8"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": [
{
"client_id": "180425292880-1pfj1drhgqc9j19jit1ahfu7jouodjej.apps.googleusercontent.com",
"client_type": 3
},
{
"client_id": "180425292880-bfueoq3p0oq0b0lf2qviebio2q338eu8.apps.googleusercontent.com",
"client_type": 2,
"ios_info": {
"bundle_id": "org.reactjs.native.example.Truth"
}
}
]
}
}
}
],
"configuration_version": "1"
}

1
android/build.gradle

@ -14,6 +14,7 @@ buildscript { @@ -14,6 +14,7 @@ buildscript {
}
dependencies {
classpath("com.android.tools.build:gradle:4.2.2")
classpath 'com.google.gms:google-services:4.3.14'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}

36
ios/GoogleService-Info.plist

@ -0,0 +1,36 @@ @@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CLIENT_ID</key>
<string>180425292880-bfueoq3p0oq0b0lf2qviebio2q338eu8.apps.googleusercontent.com</string>
<key>REVERSED_CLIENT_ID</key>
<string>com.googleusercontent.apps.180425292880-bfueoq3p0oq0b0lf2qviebio2q338eu8</string>
<key>API_KEY</key>
<string>AIzaSyDsJWXu0NtusG6fric25R8zN-j-LSHd_tg</string>
<key>GCM_SENDER_ID</key>
<string>180425292880</string>
<key>PLIST_VERSION</key>
<string>1</string>
<key>BUNDLE_ID</key>
<string>org.reactjs.native.example.Truth</string>
<key>PROJECT_ID</key>
<string>truthordare-6493e</string>
<key>STORAGE_BUCKET</key>
<string>truthordare-6493e.appspot.com</string>
<key>IS_ADS_ENABLED</key>
<false></false>
<key>IS_ANALYTICS_ENABLED</key>
<false></false>
<key>IS_APPINVITE_ENABLED</key>
<true></true>
<key>IS_GCM_ENABLED</key>
<true></true>
<key>IS_SIGNIN_ENABLED</key>
<true></true>
<key>GOOGLE_APP_ID</key>
<string>1:180425292880:ios:7109aea721588b757da555</string>
<key>DATABASE_URL</key>
<string>https://truthordare-6493e-default-rtdb.europe-west1.firebasedatabase.app</string>
</dict>
</plist>

9
ios/Podfile

@ -2,6 +2,13 @@ require_relative '../node_modules/react-native/scripts/react_native_pods' @@ -2,6 +2,13 @@ require_relative '../node_modules/react-native/scripts/react_native_pods'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
platform :ios, '11.0'
pod 'Firebase', :modular_headers => true
pod 'FirebaseCoreInternal', :modular_headers => true
pod 'GoogleUtilities', :modular_headers => true
pod 'FirebaseCore', :modular_headers => true
use_frameworks!
$RNFirebaseAsStaticFramework = true
target 'Truth' do
config = use_native_modules!
@ -21,7 +28,7 @@ target 'Truth' do @@ -21,7 +28,7 @@ target 'Truth' do
#
# Note that if you have use_frameworks! enabled, Flipper will not work and
# you should disable the next line.
use_flipper!()
# use_flipper!()
post_install do |installer|
react_native_post_install(installer)

943
ios/Podfile.lock

File diff suppressed because it is too large Load Diff

66
ios/Truth.xcodeproj/project.pbxproj

File diff suppressed because one or more lines are too long

2
ios/Truth/AppDelegate.m

@ -4,6 +4,7 @@ @@ -4,6 +4,7 @@
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
#import "RNSplashScreen.h"
#import <Firebase.h>
#ifdef FB_SONARKIT_ENABLED
#import <FlipperKit/FlipperClient.h>
@ -28,6 +29,7 @@ static void InitializeFlipper(UIApplication *application) { @@ -28,6 +29,7 @@ static void InitializeFlipper(UIApplication *application) {
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[FIRApp configure];
#ifdef FB_SONARKIT_ENABLED
InitializeFlipper(application);
#endif

10
iosDuplicate/Truth.xcworkspace/contents.xcworkspacedata generated

@ -0,0 +1,10 @@ @@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:Truth.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>

8
iosDuplicate/Truth.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist

@ -0,0 +1,8 @@ @@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

10
iosDuplicate1/Truth.xcworkspace/contents.xcworkspacedata generated

@ -0,0 +1,10 @@ @@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:Truth.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>

901
package-lock.json generated

File diff suppressed because it is too large Load Diff

5
package.json

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
},
"dependencies": {
"@react-native-async-storage/async-storage": "^1.17.11",
"@react-native-firebase/app": "^17.0.0",
"@react-native-firebase/firestore": "^17.0.0",
"@react-navigation/native": "^6.0.11",
"@react-navigation/native-stack": "^6.7.0",
"@reduxjs/toolkit": "^1.9.2",
@ -31,7 +33,7 @@ @@ -31,7 +33,7 @@
"react-native-safe-area-context": "^4.3.1",
"react-native-screens": "^3.15.0",
"react-native-splash-screen": "^3.3.0",
"react-native-svg": "^12.4.4",
"react-native-svg": "^12.5.1",
"react-native-svg-transformer": "^1.0.0",
"react-native-vector-icons": "^9.2.0",
"react-redux": "^8.0.5"
@ -53,6 +55,7 @@ @@ -53,6 +55,7 @@
"jest": "^26.6.3",
"metro-react-native-babel-preset": "^0.66.2",
"react-test-renderer": "17.0.2",
"reactotron-react-native": "^5.0.3",
"typescript": "^4.4.4"
},
"resolutions": {

16
src/assets/icons/ENG.svg

@ -0,0 +1,16 @@ @@ -0,0 +1,16 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_836_1331)">
<rect width="24" height="24" rx="12" fill="#1A47B8"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M-1.22563 0H-4.79999V4L25.2063 24L28.8 24V20L-1.22563 0Z" fill="white"/>
<path d="M-3.60783 0L28.8 21.6567V24H27.6358L-4.79999 2.32089V0H-3.60783Z" fill="#F93939"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M25.6 0H28.8V4C28.8 4 8.0157 17.3249 -1.59999 24H-4.79999V20L25.6 0Z" fill="white"/>
<path d="M28.8 0H27.7148L-4.79999 21.6753V24H-3.60783L28.8 2.33842V0Z" fill="#F93939"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.41933 0H16.6086V7.40291H28.8V16.5922H16.6086V24H7.41933V16.5922H-4.79999V7.40291H7.41933V0Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M9.34738 0H14.6526V9.23077H28.8V14.7692H14.6526V24H9.34738V14.7692H-4.79999V9.23077H9.34738V0Z" fill="#F93939"/>
</g>
<defs>
<clipPath id="clip0_836_1331">
<rect width="24" height="24" rx="12" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

14
src/assets/icons/UAE.svg

@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_836_1381)">
<rect width="24" height="24" rx="12" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 16C14.208 16 16 14.208 16 12C16 9.792 14.208 8 12 8C9.79201 8 8.00001 9.792 8.00001 12C8.00001 14.208 9.79201 16 12 16ZM12 14.4C13.3248 14.4 14.4 13.3248 14.4 12C14.4 10.6752 13.3248 9.6 12 9.6C10.6752 9.6 9.60001 10.6752 9.60001 12C9.60001 13.3248 10.6752 14.4 12 14.4Z" fill="#1A47B8"/>
<path d="M12 12.8C12.4418 12.8 12.8 12.4418 12.8 12C12.8 11.5582 12.4418 11.2 12 11.2C11.5582 11.2 11.2 11.5582 11.2 12C11.2 12.4418 11.5582 12.8 12 12.8Z" fill="#1A47B8"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M-4.79999 16H28.8V24H-4.79999V16Z" fill="#249F58"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M-4.79999 0H28.8V8H-4.79999V0Z" fill="#FF6C2D"/>
</g>
<defs>
<clipPath id="clip0_836_1381">
<rect width="24" height="24" rx="12" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1021 B

11
src/assets/icons/UKR.svg

@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_835_1324)">
<path d="M24 0H0V12.8H24V0Z" fill="#3A99FF"/>
<path d="M24 12H0V24.8H24V12Z" fill="#FFDA2C"/>
</g>
<defs>
<clipPath id="clip0_835_1324">
<rect width="24" height="24" rx="12" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 349 B

4
src/i18n/locales/en/custom-pack.translation.ts

@ -0,0 +1,4 @@ @@ -0,0 +1,4 @@
export const customPack = {
title: 'Create custom pack',
description: 'Create your own custom pack with questions and task. It all depends on your imagination!',
}

6
src/i18n/locales/en/index.ts

@ -1,7 +1,13 @@ @@ -1,7 +1,13 @@
import {MainLocaleModule} from '../../types';
import {settingTranslation} from './settings.translation';
import {onBoardingTranslation} from './steps.translation';
import {buttonsTranslation} from './onBoardingButton.translation';
import {customPack} from './custom-pack.translation';
import {pageTitles} from './page-title.translation';
export const en: MainLocaleModule = {
settingTranslation,
stepTranslation: onBoardingTranslation,
buttonsTranslation,
customPack,
pageTitles,
};

8
src/i18n/locales/en/onBoardingButton.translation.ts

@ -0,0 +1,8 @@ @@ -0,0 +1,8 @@
export const buttonsTranslation = {
skip: 'Skip',
priceButton: 'Open now / $4.99',
later: 'Later',
truth: '-TRUTH-',
random: 'RANDOM CHANCE',
dare: '-DARE-',
}

5
src/i18n/locales/en/page-title.translation.ts

@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
export const pageTitles = {
setting: 'Setting',
privacy: 'Privacy Policy',
terms: 'Terms and conditions',
}

4
src/i18n/locales/hi/custom-pack.translation.ts

@ -0,0 +1,4 @@ @@ -0,0 +1,4 @@
export const customPack = {
title: 'एक कसटम पज बन',
description: 'परश और अभ अपनट बन। यह सब आपक कलपन पर निभर करत!',
}

7
src/i18n/locales/hi/index.tsx

@ -1,7 +1,14 @@ @@ -1,7 +1,14 @@
import {MainLocaleModule} from '../../types';
import {settingTranslation} from './settings.translation';
import {onBoardingTranslation} from './steps.translation';
import { buttonsTranslation } from './onBoardingButton.translation';
import {customPack} from './custom-pack.translation';
import {pageTitles} from './page-title.translation';
export const hi: MainLocaleModule = {
settingTranslation,
stepTranslation: onBoardingTranslation,
buttonsTranslation,
customPack,
pageTitles,
};

8
src/i18n/locales/hi/onBoardingButton.translation.ts

@ -0,0 +1,8 @@ @@ -0,0 +1,8 @@
export const buttonsTranslation = {
skip: 'जनक',
priceButton: 'जनक/ $4.99',
later: 'जनक',
truth: '-सच-',
random: 'यिक म',
dare: '-हिमत-',
}

5
src/i18n/locales/hi/page-title.translation.ts

@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
export const pageTitles = {
setting: 'सिग',
privacy: 'गपनयति',
terms: 'नियम और शर',
}

2
src/i18n/locales/hi/steps.translation.ts

@ -8,7 +8,7 @@ export const onBoardingTranslation: OnBoardingLocale.OnboardingSteps = { @@ -8,7 +8,7 @@ export const onBoardingTranslation: OnBoardingLocale.OnboardingSteps = {
step2: {
title: 'आरम कर और \n खल क आनद ल!',
description:
'इस गम म "मसरत" क 5 सतर ह, जिनमछ क \n जपनिए गम मिित कि गय। आपक बस इतन करनि \n खि और आप खलन कर सकत\n.एस. आप हम अपन \nरशन और कय बन सकत।',
'इस गम म "मसरत" क 5 सतर ह, जिनमछ क \n जपनिए गम मिित कि गय। आपक बस इतन करनि \n खि और आप खलन कर सकत। प.एस. आप हम अपनरशन और कय बन सकत।',
},
step3: {
title: 'पियम सकरण!',

4
src/i18n/locales/ua/custom-pack.translation.ts

@ -0,0 +1,4 @@ @@ -0,0 +1,4 @@
export const customPack = {
title: 'Створіть індивідуальний пакет',
description: 'Створіть свій власний пакет із запитаннями та завданнями. Все залежить від вашої фантазії!',
}

9
src/i18n/locales/ua/index.ts

@ -1,8 +1,15 @@ @@ -1,8 +1,15 @@
import {MainLocaleModule} from '../../types';
import {settingTranslation} from './settings.translation';
import {onBoardingTranslationUa} from './step.translation';
import { buttonsTranslation } from './onBoardingButton.translation';
import {customPack} from './custom-pack.translation';
import {pageTitles} from './page-title.translation';
export const ua: MainLocaleModule = {
stepTranslation: onBoardingTranslationUa,
settingTranslation: settingTranslation,
};
buttonsTranslation,
customPack,
pageTitles
};

8
src/i18n/locales/ua/onBoardingButton.translation.ts

@ -0,0 +1,8 @@ @@ -0,0 +1,8 @@
export const buttonsTranslation = {
skip: 'Далі',
priceButton: 'Придбати за / $4.99',
later: 'Пізніше',
truth: '-ПРАВДА-',
random: 'ВИПАДКОВО',
dare: '-ДІЯ-',
}

5
src/i18n/locales/ua/page-title.translation.ts

@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
export const pageTitles = {
setting: 'Налаштування',
privacy: 'Політика \n конфіденційності',
terms: 'Правила та умови',
}

6
src/i18n/locales/ua/step.translation.ts

@ -8,14 +8,14 @@ export const onBoardingTranslationUa = { @@ -8,14 +8,14 @@ export const onBoardingTranslationUa = {
},
step2: {
title: 'Розслабтеся та насолоджуйтеся \n грою',
title: 'Розслабтеся та насолоджуйтеся грою',
description:
'У цій грі є 5 рівнів "пікантності",\n деякі з яких розділені на ігри для пари \n або компанії. Все, що вам потрібно зробити, це \n додати гравців, і ви можете почати грати.\n P.S. Ви завжди можете створити власні \n питання та завдання',
'У цій грі є 5 рівнів "пікантності", деякі з яких розділені на ігри для пари або компанії. Все, що вам потрібно зробити, це додати гравців, і ви можете почати грати.\n P.S. Ви завжди можете створити власні питання та завдання',
},
step3: {
title: 'Преміум версія!',
description:
'Надає необмежений доступ до пакетів Hard і \nНасолоджуйтеся інтригуючими запитаннями та\nзахоплюючими діями',
'Надає необмежений доступ до пакетів Hard та режиму Extreme \nНасолоджуйтеся інтригуючими запитаннями та захоплюючими діями',
},
};

8
src/i18n/types/buttons.types.ts

@ -0,0 +1,8 @@ @@ -0,0 +1,8 @@
export interface Buttons {
skip: string,
priceButton: string,
later: string,
truth: string,
random: string,
dare: string,
}

6
src/i18n/types/index.ts

@ -1,6 +1,12 @@ @@ -1,6 +1,12 @@
import { CustomPack } from '../../module/shared/interfaces/custom-pack';
import { PageTitles } from '../../module/shared/interfaces/page-titles';
import { Buttons } from './buttons.types';
import {OnBoardingLocale} from './on-boarding.types';
import {SettingLocale} from './settings.types';
export interface MainLocaleModule {
stepTranslation: OnBoardingLocale.OnboardingSteps;
settingTranslation: SettingLocale.Core;
buttonsTranslation: Buttons;
customPack: CustomPack;
pageTitles: PageTitles;
}

17
src/module/game/screen/select-packages.screen.tsx

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
import React, {FC} from 'react';
import React, {FC, useEffect} from 'react';
import {
colors,
Header,
@ -7,27 +7,30 @@ import { @@ -7,27 +7,30 @@ import {
ScreenLayout,
} from '../../shared';
import {PackagesList} from '../../package';
import { ScrollView } from 'react-native-gesture-handler';
interface IProps extends IRouteParams {}
export const SelectPackages: FC<IProps> = ({navigation}) => {
return (
<ScreenLayout
backgroundColor={colors.primaryColor}
backgroundColor={colors.primaryColor}
backgroundStatusBar={colors.primaryColor}
headerComponent={
<Header
title="Packages"
leftIcon="settings"
rightIcon="setting"
onPressRight={() =>
leftIcon="settings"
rightIcon="setting"
onPressRight={() =>
navigation.navigate(RouteKey.Setting, {
previous_screen: RouteKey.Game,
title: RouteKey.Setting,
})
}
/>
/>
}>
<ScrollView contentContainerStyle={{paddingBottom: 30, paddingHorizontal: 5}}>
<PackagesList />
</ScrollView>
</ScreenLayout>
);
};

12
src/module/package/atoms/create-custom-package.atom.tsx

@ -1,19 +1,23 @@ @@ -1,19 +1,23 @@
import AsyncStorage from '@react-native-async-storage/async-storage';
import React from 'react';
import {useTranslation} from 'react-i18next';
import {StyleSheet, TouchableOpacity, View, Text} from 'react-native';
import {colors, Icon} from '../../shared';
export const CustomPackage = () => {
const {t, i18n} = useTranslation();
return (
<TouchableOpacity style={style.container}>
<View style={{flexDirection: 'row'}}>
<View style={style.iconContainer}>
<Icon name="lock" size={22} color="white"/>
<Icon name="lock" size={22} color="white" />
</View>
<View style={style.textContainer}>
<Text style={style.title}>Create custom pack</Text>
<Text style={style.title}>{t('customPack.title')}</Text>
<Text style={style.description}>
Create your own custom pack with questions and task. It all depends
on your imagination!
{t('customPack.description')}
</Text>
</View>
</View>

18
src/module/package/components/packages-item.component.tsx

@ -1,10 +1,14 @@ @@ -1,10 +1,14 @@
import {useNavigation} from '@react-navigation/native';
import React, {FC} from 'react';
import {StyleSheet, TouchableOpacity, View, Text} from 'react-native';
import { useAppDispatch } from '../../../store/hooks';
import { nextStep, resetSteps } from '../../services/current-step/current-step-slice';
import { shuffleDares } from '../../services/dares/dares-slice';
import { shuffleTruths } from '../../services/truths/truth-slice';
import {useAppDispatch} from '../../../store/hooks';
import {
nextStep,
resetSteps,
} from '../../services/current-step/current-step-slice';
import {shuffleDares} from '../../services/dares/dares-slice';
import {shuffleItems} from '../../services/game-items/game-items-slice';
import {shuffleTruths} from '../../services/truths/truth-slice';
import {Icon, RouteKey} from '../../shared';
interface IType {
@ -33,7 +37,7 @@ export const PackagesItem: FC<IPackage> = ({ @@ -33,7 +37,7 @@ export const PackagesItem: FC<IPackage> = ({
dispatch(resetSteps());
dispatch(shuffleTruths());
dispatch(shuffleDares());
}
};
return (
<View style={style.container}>
@ -44,9 +48,7 @@ export const PackagesItem: FC<IPackage> = ({ @@ -44,9 +48,7 @@ export const PackagesItem: FC<IPackage> = ({
<Text style={style.description}>{description}</Text>
</View>
</View>
<TouchableOpacity
style={style.play}
onPress={play}>
<TouchableOpacity style={style.play} onPress={play}>
<Icon name="play" size={20} color="white" />
</TouchableOpacity>
</View>

1
src/module/package/components/packages-list.tsx

@ -8,6 +8,7 @@ import {useTranslation} from 'react-i18next'; @@ -8,6 +8,7 @@ import {useTranslation} from 'react-i18next';
export const PackagesList = () => {
const {i18n} = useTranslation();
const lang = i18n.language;
console.log(lang);
return (
<View style={styles.container}>
{defaultPackages.map((item: any, index) => (

5
src/module/privacy-policy/config/privacy-texts.ts

@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
export const privacy = {
en: 'We collect, use and disclose Personal Information to provide you with the product or service you have requested and to offer you additional products and services we believe you might be interested in. The purposes for which we collect Personal Information will be identified before or at the time we collect the information. In certain circumstances, the purposes for which information is collected may be clear, and consent may be implied, such as where your name, address and payment information is provided as part of the order process',
ua: 'Ми збираємо, використовуємо та розкриваємо особисту інформацію, щоб надати вам продукт або послугу, які ви запитували, і запропонувати вам додаткові продукти та послуги, які, на нашу думку, можуть вас зацікавити. Цілі, для яких ми збираємо особисту інформацію, будуть визначені до або під час час, коли ми збираємо інформацію. За певних обставин цілі, для яких збирається інформація, можуть бути зрозумілими, а згода може матися на увазі, наприклад, коли ваше ім’я, адреса та платіжна інформація надаються як частина процесу замовлення',
hi: 'हम आपक अनित उतद यरदन करनिए वयकिगत जनक एकतर करत, उपयग करत और परकट करत और आपक अतिित उत और सशकश करनिए हमिस हि आपकि सकत। जिन उदिए हम वयकिगत जनक एकतर करत, उनक पहचन पहल पर कएग समय जब हम जनक एकतर करत। कछ परििि, जनक एकतर करन उदय सपषट ह सकत, और सहमतििित ह सकत, जि ऑरडर परकििप म आपकम, पत और भगतन जनक कहरदन क',
};

42
src/module/privacy-policy/screens/privacy-policy.tsx

@ -0,0 +1,42 @@ @@ -0,0 +1,42 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import {View} from 'react-native';
import {
colors,
Header,
IRouteParams,
RouteKey,
ScreenLayout,
} from '../../shared';
import { MainTextContainer } from '../../shared/components/text-containers/main-text-container';
import { privacy } from '../config/privacy-texts';
interface IProps extends IRouteParams {}
export const PrivacyPolicy: React.FC<IProps> = ({navigation}) => {
const goBack = () => {
navigation.navigate(RouteKey.Setting, {
previous_screen: RouteKey.Game,
});
};
const {t, i18n} = useTranslation();
const lang = i18n.language;
return (
<ScreenLayout
backgroundColor={colors.primaryColor}
backgroundStatusBar={colors.primaryColor}
paddingHorizontal={20}
headerComponent={
<Header
leftIcon="arrow"
title={t('pageTitles.privacy')}
onPressLeft={() => navigation.goBack()}
rightIcon="none"
/>
}>
<MainTextContainer text={privacy[lang as keyof typeof privacy]}/>
</ScreenLayout>
);
};

40
src/module/root/atoms/premium-button.component.tsx

@ -1,9 +1,10 @@ @@ -1,9 +1,10 @@
import AsyncStorage from '@react-native-async-storage/async-storage';
import { useNavigation } from '@react-navigation/native';
import { navigate } from '@react-navigation/routers/lib/typescript/src/CommonActions';
import {CommonActions, useNavigation} from '@react-navigation/native';
import {navigate} from '@react-navigation/routers/lib/typescript/src/CommonActions';
import React, {FC} from 'react';
import { useTranslation } from 'react-i18next';
import {StyleSheet, Text, TouchableOpacity, View} from 'react-native';
import { StorageKey, storageService } from '../../services/async-storage.service';
import {StorageKey, storageService} from '../../services/async-storage.service';
import {colors, IRouteParams, PrimaryBtn, RouteKey} from '../../shared';
interface IProps {
currentIndex: number;
@ -21,30 +22,29 @@ interface IProps { @@ -21,30 +22,29 @@ interface IProps {
) => void;
}
export const GroupBtn: FC<IProps> = ({currentIndex, data, onPressItem}) => {
const navigation = useNavigation();
const {i18n, t} = useTranslation();
const onBoardFinish = async () => {
await AsyncStorage.setItem(StorageKey.OnBoarding, 'true');
navigation.navigate(RouteKey.Game as any);
navigation.dispatch(CommonActions.reset({
index: 0,
routes: [{name: RouteKey.Game}]
}));
};
if (data.length - 1 === currentIndex) {
return (
<View style={styles.btncontainer}>
<PrimaryBtn
onPress={async () => {
await AsyncStorage.setItem(StorageKey.OnBoarding, 'true');
navigation.navigate(RouteKey.Game as any);
console.log('last buttons')
}}
children={<Text style={styles.text}>{`Open now / $4.99`}</Text>}
onPress={onBoardFinish}
children={<Text style={styles.text}>{t('buttonsTranslation.priceButton')}</Text>}
width={190}
/>
<TouchableOpacity
style={styles.laterBtn}
onPress={ async () =>{
await AsyncStorage.setItem(StorageKey.OnBoarding, 'true');
navigation.navigate(RouteKey.Game as any);
console.log('last buttons')
}
}>
<Text style={[styles.text, {fontWeight: '400'}]}>Later</Text>
<TouchableOpacity style={styles.laterBtn} onPress={onBoardFinish}>
<Text style={[styles.text, {fontWeight: '400'}]}>{t('buttonsTranslation.later')}</Text>
</TouchableOpacity>
</View>
);
@ -52,7 +52,7 @@ export const GroupBtn: FC<IProps> = ({currentIndex, data, onPressItem}) => { @@ -52,7 +52,7 @@ export const GroupBtn: FC<IProps> = ({currentIndex, data, onPressItem}) => {
return (
<PrimaryBtn
onPress={() => onPressItem(data)}
children={<Text style={styles.text}>Skip</Text>}
children={<Text style={styles.text}>{t('buttonsTranslation.skip')}</Text>}
width={155}
/>
);

4
src/module/root/components/language-item.component.tsx

@ -8,7 +8,9 @@ interface IProps { @@ -8,7 +8,9 @@ interface IProps {
export const LanguageItem: FC<IProps> = ({icon, name, onPress}) => {
return (
<TouchableOpacity onPress={onPress} style={styles.container}>
<View style={styles.circleContainer}>{icon}</View>
<View style={styles.circleContainer}>
{icon}
</View>
<Text style={styles.nameLanguage}>{name}</Text>
</TouchableOpacity>
);

13
src/module/root/navigations-groups/on-boardings-group.tsx

@ -5,17 +5,22 @@ import {LanguageSelect, Onboarding, Setting} from '../screens'; @@ -5,17 +5,22 @@ import {LanguageSelect, Onboarding, Setting} from '../screens';
import {SelectPackages} from '../../game/screen/select-packages.screen';
import {LoadingScreen} from '../screens/loading-screen';
import {Game} from '../screens/game';
import { Questions } from '../screens/questions';
import {Questions} from '../screens/questions';
import {PrivacyPolicy} from '../../privacy-policy/screens/privacy-policy';
import {UseOfTerms} from '../../terms-of-use/screens/use-of-terms';
import firestore from '@react-native-firebase/firestore';
const Stack = createNativeStackNavigator();
export const OnboardingGroup: FC = () => {
return (
<Stack.Navigator
screenOptions={{
headerShown: false,
animation: 'slide_from_left',
}}
initialRouteName={RouteKey.Loading}
>
initialRouteName={RouteKey.Loading}>
<Stack.Screen name={RouteKey.Questions} component={Questions} />
<Stack.Screen name={RouteKey.Package} component={Game} />
<Stack.Screen name={RouteKey.Onboarding} component={Onboarding} />
@ -23,6 +28,8 @@ export const OnboardingGroup: FC = () => { @@ -23,6 +28,8 @@ export const OnboardingGroup: FC = () => {
<Stack.Screen name={RouteKey.LanguageSelect} component={LanguageSelect} />
<Stack.Screen name={RouteKey.Game} component={SelectPackages} />
<Stack.Screen name={RouteKey.Setting} component={Setting} />
<Stack.Screen name={RouteKey.PrivacyPolicy} component={PrivacyPolicy} />
<Stack.Screen name={RouteKey.UseOfTerms} component={UseOfTerms} />
</Stack.Navigator>
);
};

20
src/module/root/screens/game.tsx

@ -7,11 +7,15 @@ import { @@ -7,11 +7,15 @@ import {
IRouteParams,
} from '../../shared';
import React from 'react';
import {NameTitle} from '../../shared/components/nameTitle/name-title';
import {NameTitle} from '../../shared/components/name-title/name-title';
import {RedButton} from '../../shared/components/buttons/red-button';
import {useTranslation} from 'react-i18next';
interface IProps extends IRouteParams {}
export const Game: React.FC<IProps> = ({navigation, route}) => {
const {title} = route.params;
const {t} = useTranslation();
const goBack = () => {
navigation.navigate(RouteKey.Game);
};
@ -19,8 +23,8 @@ export const Game: React.FC<IProps> = ({navigation, route}) => { @@ -19,8 +23,8 @@ export const Game: React.FC<IProps> = ({navigation, route}) => {
const randomGame = () => {
const isQuestions = Math.random() < 0.5;
navigation.navigate(RouteKey.Questions, {isQuestions})
}
navigation.navigate(RouteKey.Questions, {isQuestions, title});
};
return (
<ScreenLayout
@ -32,24 +36,26 @@ export const Game: React.FC<IProps> = ({navigation, route}) => { @@ -32,24 +36,26 @@ export const Game: React.FC<IProps> = ({navigation, route}) => {
leftIcon="arrow"
gamer={true}
onPressLeft={() => goBack()}
title="Crazy"
title={title}
/>
<NameTitle name="Player" />
<View style={styles.buttons}>
<RedButton
name="-TRUTH-"
name={t('buttonsTranslation.truth')}
isQuestions={true}
navigation={navigation}
route={route}
title={title}
/>
<TouchableOpacity onPress={randomGame}>
<Text style={styles.random}>RANDOM CHANCE</Text>
<Text style={styles.random}>{t('buttonsTranslation.random')}</Text>
</TouchableOpacity>
<RedButton
name="-DARE-"
name={t('buttonsTranslation.dare')}
isQuestions={false}
navigation={navigation}
route={route}
title={title}
/>
</View>
</>

12
src/module/root/screens/language-select.screen.tsx

@ -6,20 +6,24 @@ import {LangKeys} from '../../../i18n'; @@ -6,20 +6,24 @@ import {LangKeys} from '../../../i18n';
import { StorageKey, storageService } from '../../services/async-storage.service';
import {IRouteParams, RouteKey, colors, ScreenLayout} from '../../shared';
import {LanguageItem} from '../components';
import UALogo from '../../../assets/icons/UKR.svg';
import UAELogo from '../../../assets/icons/UAE.svg';
import ENGLogo from '../../../assets/icons/ENG.svg';
const languageArr = [
{
name: 'Українська',
icon: <Image source={require('../../../assets/icons/UKR.png')} />,
icon: <UALogo />,
key: LangKeys.UA,
},
{
name: 'English',
icon: <Image source={require('../../../assets/icons/ENG.png')} />,
icon: <ENGLogo />,
key: LangKeys.EN,
},
{
name: 'Hindi',
icon: <Image source={require('../../../assets/icons/UAE.png')} />,
icon: <UAELogo />,
key: LangKeys.HI,
},
];
@ -27,8 +31,6 @@ interface IProps extends IRouteParams {} @@ -27,8 +31,6 @@ interface IProps extends IRouteParams {}
export const LanguageSelect: FC<IProps> = ({navigation}) => {
const {t, i18n} = useTranslation();
console.log('before', i18n.language);
return (
<ScreenLayout
backgroundColor={colors.primaryColor}

40
src/module/root/screens/loading-screen.tsx

@ -8,10 +8,18 @@ import { @@ -8,10 +8,18 @@ import {
import React, {FC, useEffect, useState} from 'react';
import {ScreenLayout, colors, RouteKey} from '../../shared';
import AsyncStorage from '@react-native-async-storage/async-storage';
import {useNavigation} from '@react-navigation/native';
import {useNavigation, CommonActions} from '@react-navigation/native';
import {StorageKey, storageService} from '../../services/async-storage.service';
import {useTranslation} from 'react-i18next';
import {useAppDispatch} from '../../../store/hooks';
import {fetchPostsAsync} from '../../services/game-items/game-items-slice';
export const LoadingScreen = () => {
const {i18n} = useTranslation();
const navigate = useNavigation();
const dispatch = useAppDispatch();
const getLanguage = async () => {
const response = await AsyncStorage.getItem(StorageKey.Language);
return response;
@ -25,18 +33,38 @@ export const LoadingScreen = () => { @@ -25,18 +33,38 @@ export const LoadingScreen = () => {
const init = async () => {
let language = await getLanguage();
const isOnBoard = await getOnboardEnd();
dispatch(fetchPostsAsync());
console.log(language);
if (language) {
i18n.changeLanguage(language);
}
if (isOnBoard && language) {
navigate.navigate(RouteKey.Game as any);
navigate.dispatch(
CommonActions.reset({
index: 0,
routes: [{name: RouteKey.Game}],
}),
);
} else if (language && !isOnBoard) {
navigate.navigate(RouteKey.Onboarding as any);
navigate.dispatch(
CommonActions.reset({
index: 0,
routes: [{name: RouteKey.Onboarding}],
}),
);
} else if (!language) {
navigate.navigate(RouteKey.LanguageSelect as any);
navigate.dispatch(
CommonActions.reset({
index: 0,
routes: [{name: RouteKey.LanguageSelect}],
}),
);
}
};
const navigate = useNavigation();
useEffect(() => {
init();
}, []);

14
src/module/root/screens/on-boarding.screen.tsx

@ -33,13 +33,13 @@ export const Onboarding: FC<IProps> = ({navigation}) => { @@ -33,13 +33,13 @@ export const Onboarding: FC<IProps> = ({navigation}) => {
<Header
leftIcon="arrow"
onPressLeft={() => goBack()}
rightIcon="setting"
onPressRight={() =>
{console.log('Option');
navigation.navigate(RouteKey.Setting, {
previous_screen: RouteKey.Onboarding,
})}
}
rightIcon="none"
// onPressRight={() =>
// {console.log('Option');
// navigation.navigate(RouteKey.Setting, {
// previous_screen: RouteKey.Onboarding,
// })}
// }
/>
}>
<ContentOnBoarding

55
src/module/root/screens/questions.tsx

@ -14,14 +14,18 @@ import { @@ -14,14 +14,18 @@ import {
IRouteParams,
PrimaryBtn,
} from '../../shared';
import React, { useState } from 'react';
import {NameTitle} from '../../shared/components/nameTitle/name-title';
import {QuestionBlock} from '../../shared/components/questionBlock/question-block';
import { MainModal } from '../../shared/components/modals/main-modal';
import { useAppDispatch } from '../../../store/hooks';
import { nextStep, resetSteps } from '../../services/current-step/current-step-slice';
import { shuffleTruths } from '../../services/truths/truth-slice';
import { shuffleDares } from '../../services/dares/dares-slice';
import React, {useState} from 'react';
import {NameTitle} from '../../shared/components/name-title/name-title';
import {QuestionBlock} from '../../shared/components/question-block/question-block';
import {MainModal} from '../../shared/components/modals/main-modal';
import {useAppDispatch} from '../../../store/hooks';
import {
nextStep,
resetSteps,
} from '../../services/current-step/current-step-slice';
import {shuffleTruths} from '../../services/truths/truth-slice';
import {shuffleDares} from '../../services/dares/dares-slice';
import {shuffleItems} from '../../services/game-items/game-items-slice';
interface IProps extends IRouteParams {}
export const Questions: React.FC<IProps> = ({navigation, route}) => {
@ -29,22 +33,21 @@ export const Questions: React.FC<IProps> = ({navigation, route}) => { @@ -29,22 +33,21 @@ export const Questions: React.FC<IProps> = ({navigation, route}) => {
const dispatch = useAppDispatch();
console.log(route.params);
const {title} = route.params;
const goBack = () => {
navigation.navigate(RouteKey.Game);
};
const goGameScreen = () => {
navigation.navigate(RouteKey.Package);
navigation.navigate(RouteKey.Package, {title});
dispatch(nextStep());
}
};
const refreshList = () => {
dispatch(shuffleTruths());
dispatch(shuffleDares());
dispatch(shuffleItems());
dispatch(resetSteps());
}
};
return (
<ScreenLayout
@ -63,11 +66,15 @@ export const Questions: React.FC<IProps> = ({navigation, route}) => { @@ -63,11 +66,15 @@ export const Questions: React.FC<IProps> = ({navigation, route}) => {
leftIcon="arrow"
gamer={true}
onPressLeft={() => goBack()}
title="Crazy"
title={title}
/>
<NameTitle name="Player" />
<QuestionBlock isQuestions={route.params.isQuestions}/>
<MainModal isVisible={isVisible} rate={true}/>
<QuestionBlock isQuestions={route.params.isQuestions} />
<MainModal
isVisible={isVisible}
rate={true}
setIsVisible={setIsVisible}
/>
</View>
<View style={styles.buttons}>
@ -79,27 +86,31 @@ export const Questions: React.FC<IProps> = ({navigation, route}) => { @@ -79,27 +86,31 @@ export const Questions: React.FC<IProps> = ({navigation, route}) => {
style={{width: 20, height: 20}}
/>
}
width={101}
width={'30%'}
/>
<PrimaryBtn
onPress={() => {goGameScreen()}}
onPress={() => {
goGameScreen();
}}
children={
<Image
source={require('../../../assets/image/play.png')}
style={{width: 20, height: 20}}
/>
}
width={101}
width={'30%'}
/>
<PrimaryBtn
onPress={() => {setIsVisible(true)}}
onPress={() => {
setIsVisible(true);
}}
children={
<Image
source={require('../../../assets/image/addPlus.png')}
style={{width: 20, height: 20}}
/>
}
width={101}
width={'30%'}
/>
</View>
</View>

5
src/module/root/screens/settings.screen.tsx

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
import React, {FC} from 'react';
import { useTranslation } from 'react-i18next';
import {StyleSheet, View} from 'react-native';
import {SettingsItem} from '../../setting/components/Settings-Item.component';
import {SettingsData} from '../../setting/config/data-setting.config';
@ -9,6 +10,8 @@ interface IProps extends IRouteParams {} @@ -9,6 +10,8 @@ interface IProps extends IRouteParams {}
export const Setting: FC<IProps> = ({route, navigation}) => {
const {previous_screen, title} = route.params;
const {t} = useTranslation();
return (
<ScreenLayout
backgroundColor={colors.primaryColor}
@ -17,7 +20,7 @@ export const Setting: FC<IProps> = ({route, navigation}) => { @@ -17,7 +20,7 @@ export const Setting: FC<IProps> = ({route, navigation}) => {
<Header
leftIcon="arrow"
rightIcon="inst"
title={title}
title={t('pageTitles.setting')}
onPressLeft={() => navigation.navigate(previous_screen)}
/>
}>

65
src/module/services/game-items/game-items-slice.ts

@ -0,0 +1,65 @@ @@ -0,0 +1,65 @@
import {createAsyncThunk, createSlice} from '@reduxjs/toolkit';
import {GameItem} from '../../shared/interfaces/game-item';
import firestore from '@react-native-firebase/firestore';
import {RootState} from '../../../store/store';
import { shuffle } from '../shuffle/shuffle';
export interface PostsState {
posts: GameItem[];
shuffled: GameItem[];
loaded: boolean;
hasError: boolean;
}
const initialState: PostsState = {
posts: [],
shuffled: [],
loaded: false,
hasError: false,
};
export const fetchPostsAsync = createAsyncThunk(
'posts/fetchPosts',
async () => {
const data = [] as GameItem[];
let querySnapshot = await firestore().collection('GameItems').get();
querySnapshot.forEach(doc => {
const item = doc.data();
data.push(item as GameItem);
});
return data;
},
);
export const postsSlice = createSlice({
name: 'posts',
initialState,
reducers: {
shuffleItems: state => {
state.shuffled = shuffle(state.posts);
},
},
extraReducers(builder) {
builder
.addCase(fetchPostsAsync.fulfilled, (state, action) => {
state.posts = action.payload;
state.hasError = false;
state.loaded = true;
})
.addCase(fetchPostsAsync.pending, state => {
state.loaded = false;
})
.addCase(fetchPostsAsync.rejected, state => {
state.hasError = true;
});
},
});
export const {shuffleItems} = postsSlice.actions;
export const selectPosts = (state: RootState) => state.gameItems.posts;
export const selectHasError = (state: RootState) => state.gameItems.hasError;
export const selectLoaded = (state: RootState) => state.gameItems.loaded;
export const selectShuffled = (state: RootState) => state.gameItems.shuffled;
export default postsSlice.reducer;

19
src/module/setting/components/Settings-Item.component.tsx

@ -1,7 +1,9 @@ @@ -1,7 +1,9 @@
import {useNavigation} from '@react-navigation/native';
import React, {FC} from 'react';
import {useTranslation} from 'react-i18next';
import {StyleSheet, Text, View, TouchableOpacity} from 'react-native';
import {Icon} from '../../shared';
import {settingTranslation} from '../../../i18n/locales/en/settings.translation';
import {Icon, RouteKey} from '../../shared';
interface IProps {
title: string;
@ -11,8 +13,21 @@ interface IProps { @@ -11,8 +13,21 @@ interface IProps {
export const SettingsItem: FC<IProps> = ({title, iconName, component}) => {
const {t, i18n} = useTranslation();
const navigation = useNavigation();
const goTo = () => {
console.log(title);
switch (title) {
case 'settingTranslation.policy':
navigation.navigate(RouteKey.PrivacyPolicy as any);
break;
case 'settingTranslation.term':
navigation.navigate(RouteKey.UseOfTerms as any);
}
};
return (
<TouchableOpacity style={styles.container}>
<TouchableOpacity style={styles.container} onPress={goTo}>
<View style={styles.title}>
<Text style={styles.icon}>
<Icon name={iconName} size={22} color="#A798FF" />

27
src/module/shared/components/buttons/red-button.tsx

@ -1,19 +1,28 @@ @@ -1,19 +1,28 @@
import { useNavigation } from '@react-navigation/native';
import {useNavigation} from '@react-navigation/native';
import React from 'react';
import {StyleSheet, TouchableOpacity, Text} from 'react-native';
import { colors } from '../../colors';
import { RouteKey } from '../../enums';
import { IRouteParams } from '../../interfaces';
import {colors} from '../../colors';
import {RouteKey} from '../../enums';
import {IRouteParams} from '../../interfaces';
interface IProps extends IRouteParams {
name: string;
isQuestions: boolean;
title: string;
}
export const RedButton: React.FC<IProps> = ({name , isQuestions, navigation}) => {
export const RedButton: React.FC<IProps> = ({
name,
isQuestions,
navigation,
title,
}) => {
return (
<TouchableOpacity style={styles.container} onPress={() => navigation.navigate(RouteKey.Questions, {isQuestions})}>
<TouchableOpacity
style={styles.container}
onPress={() =>
navigation.navigate(RouteKey.Questions, {isQuestions, title})
}>
<Text style={styles.title}>{name}</Text>
</TouchableOpacity>
);
@ -32,6 +41,6 @@ const styles = StyleSheet.create({ @@ -32,6 +41,6 @@ const styles = StyleSheet.create({
title: {
fontSize: 36,
color: '#E36588',
fontWeight: '800'
}
fontWeight: '800',
},
});

9
src/module/shared/components/header/header.component.tsx

@ -34,11 +34,12 @@ export const Header: FC<IProps> = ({ @@ -34,11 +34,12 @@ export const Header: FC<IProps> = ({
<Text style={styles.title}>{title}</Text>
)}
{rightIcon && (
{rightIcon && rightIcon !== 'none' && (
<TouchableOpacity style={styles.button} onPress={onPressRight}>
<Icon name={rightIcon} size={22} color={colors.secondaryColor} />
</TouchableOpacity>
)}
{rightIcon === 'none' && <View style={{width: 30}}></View>}
{gamer && <View style={{width: 27}}></View>}
</View>
);
@ -57,12 +58,14 @@ const styles = StyleSheet.create({ @@ -57,12 +58,14 @@ const styles = StyleSheet.create({
fontSize: 24,
color: '#99EDCC',
fontWeight: 'bold',
textAlign: 'center',
},
gamerTitle: {
backgroundColor: '#2C205C',
borderRadius: 60,
width: 122,
height: 54,
minWidth: 122,
padding: 14,
minHeight: 54,
justifyContent: 'center',
alignItems: 'center',
},

10
src/module/shared/components/modals/main-modal.tsx

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
import {Modal, View, Text, StyleSheet} from 'react-native';
import React from 'react';
import {Modal, View, Text, StyleSheet, TouchableOpacity, TouchableWithoutFeedback} from 'react-native';
import React, { Dispatch, SetStateAction } from 'react';
import {colors} from '../../colors';
import {PrimaryBtn} from '../buttons';
@ -8,6 +8,7 @@ interface IProps { @@ -8,6 +8,7 @@ interface IProps {
limit?: boolean;
custom?: boolean;
rate?: boolean;
setIsVisible: Dispatch<SetStateAction<boolean>>,
}
export const MainModal: React.FC<IProps> = ({
@ -15,6 +16,7 @@ export const MainModal: React.FC<IProps> = ({ @@ -15,6 +16,7 @@ export const MainModal: React.FC<IProps> = ({
limit,
custom,
rate,
setIsVisible,
}) => {
return (
<Modal visible={isVisible} transparent={true} animationType={'fade'}>
@ -57,12 +59,12 @@ export const MainModal: React.FC<IProps> = ({ @@ -57,12 +59,12 @@ export const MainModal: React.FC<IProps> = ({
) : (
<View style={styles.buttonsVertical}>
<PrimaryBtn
onPress={async () => {}}
onPress={() => {setIsVisible(false)}}
children={<Text style={styles.buttonText}>Rate the app</Text>}
width={'100%'}
/>
<PrimaryBtn
onPress={async () => {}}
onPress={ () => {setIsVisible(false)}}
children={
<Text style={[styles.buttonText, {fontWeight: '400'}]}>
Let the developer be sad further :(

0
src/module/shared/components/nameTitle/name-title.tsx → src/module/shared/components/name-title/name-title.tsx

32
src/module/shared/components/questionBlock/question-block.tsx → src/module/shared/components/question-block/question-block.tsx

@ -13,6 +13,9 @@ import { @@ -13,6 +13,9 @@ import {
shuffleTruths,
} from '../../../services/truths/truth-slice';
import {getShuffledDares, shuffleDares} from '../../../services/dares/dares-slice';
import { selectPosts, selectShuffled, shuffleItems } from '../../../services/game-items/game-items-slice';
import { useTranslation } from 'react-i18next';
import { GameItem } from '../../interfaces/game-item';
interface IProps {
isQuestions: boolean;
@ -21,21 +24,30 @@ interface IProps { @@ -21,21 +24,30 @@ interface IProps {
export const QuestionBlock: React.FC<IProps> = ({isQuestions}) => {
const navigation = useNavigation();
const dispatch = useAppDispatch();
const {i18n} = useTranslation();
const lang = i18n.language;
const currentStep = useAppSelector(getStep);
const shuffledTruths = useAppSelector(getShuffledTruths);
const shuffledDares = useAppSelector(getShuffledDares);
console.log(currentStep);
const gameItems = useAppSelector(selectShuffled);
const dares = gameItems.filter((dare) => dare.isDare);
const questions = gameItems.filter((question) => !question.isDare);
console.log(dares);
useEffect(() => {
if (currentStep >= shuffledTruths.length) {
if (currentStep >= questions.length) {
dispatch(resetSteps());
dispatch(shuffleTruths());
dispatch(shuffleItems());
}
if (currentStep >= shuffledDares.length) {
if (currentStep >= dares.length) {
dispatch(resetSteps());
dispatch(shuffleDares());
dispatch(shuffleItems());
}
}, [currentStep]);
@ -45,12 +57,12 @@ export const QuestionBlock: React.FC<IProps> = ({isQuestions}) => { @@ -45,12 +57,12 @@ export const QuestionBlock: React.FC<IProps> = ({isQuestions}) => {
<Image source={require('../../../../assets/image/magic-star.png')} />
</View>
<Text style={styles.text}>
{currentStep < shuffledTruths.length &&
{currentStep < questions.length &&
isQuestions &&
shuffledTruths[currentStep].question}
{currentStep < shuffledDares.length &&
questions[currentStep][lang as keyof GameItem]}
{currentStep < dares.length &&
!isQuestions &&
shuffledDares[currentStep].dare}
dares[currentStep][lang as keyof GameItem]}
</Text>
</View>
);

36
src/module/shared/components/text-containers/main-text-container.tsx

@ -0,0 +1,36 @@ @@ -0,0 +1,36 @@
import {StyleSheet, Text, View} from 'react-native';
import React from 'react';
import { colors } from '../../colors';
import { ScrollView } from 'react-native-gesture-handler';
interface IProps {
text: string
}
export const MainTextContainer: React.FC<IProps> = ({text}) => {
return (
<View style={styles.container}>
<ScrollView contentContainerStyle={{paddingBottom: 0}}>
<Text style={styles.description}>
{text}
</Text>
</ScrollView>
</View>
);
};
const styles = StyleSheet.create({
container: {
backgroundColor: colors.darkPurple,
borderRadius: 20,
paddingVertical: 32,
paddingHorizontal: 20,
maxHeight: '80%'
},
description: {
lineHeight: 32,
fontSize: 22,
color: colors.purple,
textAlign: 'auto'
}
});

6
src/module/shared/config/default-packages.tsx

@ -3,7 +3,7 @@ import {Image} from 'react-native'; @@ -3,7 +3,7 @@ import {Image} from 'react-native';
export const defaultPackages = [
{
title: {en: 'Under 18', ua: 'до 18 років', hi: '18 स'},
title: {en: 'Under 18', ua: 'До 18 років', hi: '18 स'},
image: (
<Image
source={require('../../../assets/image/rabbit.png')}
@ -51,7 +51,7 @@ export const defaultPackages = [ @@ -51,7 +51,7 @@ export const defaultPackages = [
],
},
{
title: {en: 'Light', ua: 'легкий', hi: 'रशन'},
title: {en: 'Light', ua: 'Легкий', hi: 'रशन'},
image: (
<Image
source={require('../../../assets/image/feathers.png')}
@ -99,7 +99,7 @@ export const defaultPackages = [ @@ -99,7 +99,7 @@ export const defaultPackages = [
],
},
{
title: {en: 'Crazy', ua: 'божевільний', hi: 'पगल'},
title: {en: 'Crazy', ua: 'Божевільний', hi: 'पगल'},
image: (
<Image
source={require('../../../assets/image/hand.png')}

2
src/module/shared/enums/route-keys.ts

@ -6,4 +6,6 @@ export enum RouteKey { @@ -6,4 +6,6 @@ export enum RouteKey {
Loading = 'Loading',
Package = 'Package',
Questions = 'Questions',
PrivacyPolicy = 'PrivacyPolicy',
UseOfTerms = 'UseOfTerms',
}

4
src/module/shared/helpers/helper-height-view.ts

@ -3,8 +3,8 @@ import {Dimensions} from 'react-native'; @@ -3,8 +3,8 @@ import {Dimensions} from 'react-native';
const HEIGHT_SCREEN = Dimensions.get('screen').height;
export const heightPicture = () => {
if (HEIGHT_SCREEN < 812) {
if (HEIGHT_SCREEN < 1000) {
return 240;
}
return 310;
return 340;
};

4
src/module/shared/interfaces/custom-pack.ts

@ -0,0 +1,4 @@ @@ -0,0 +1,4 @@
export interface CustomPack {
title: string;
description: string;
}

7
src/module/shared/interfaces/game-item.ts

@ -0,0 +1,7 @@ @@ -0,0 +1,7 @@
export interface GameItem {
id: number;
isDare: boolean;
en: string;
ua: string;
hi: string;
}

5
src/module/shared/interfaces/page-titles.ts

@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
export interface PageTitles {
setting: string,
privacy: string,
terms: string,
}

2
src/module/terms-of-use/config/terms-text.ts

@ -0,0 +1,2 @@ @@ -0,0 +1,2 @@
export const TermsText =
'You agree to use our application for legitimate purposes and not for any illegal or unauthorized purpose, including without limitation, in violation of any intellectual property or privacy law. By agreeing to the Terms, you represent and warrant that you are at least the age of majority in your state or province of residence and are legally capable of entering into a binding contract.';

6
src/module/terms-of-use/config/use-of-terms.translations.ts

@ -0,0 +1,6 @@ @@ -0,0 +1,6 @@
export const terms = {
en: ' You agree to use our application for legitimate purposes and not for any illegal or unauthorized purpose, including without limitation, in violation of any intellectual property or privacy law. By agreeing to the Terms, you represent and warrant that you are at least the age of majority in your state or province of residence and are legally capable of entering into a binding contract',
ua: 'Ви погоджуєтеся використовувати нашу програму в законних цілях, а не в незаконних або несанкціонованих цілях, у тому числі, без обмежень, з порушенням будь-якого закону про інтелектуальну власність або конфіденційність. Погоджуючись із Умовами, ви заявляєте та гарантуєте, що досягли повноліття у вашому штаті чи провінції та маєте законну правоздатність укладати обов’язковий договір',
hi: 'आप हम आवदन कध उदिए उपयग करनिए सहमत ह, न किि अवध य अनधित उदय किए, जिसमिि, कििक सपदपनयतन क उलघन शिल ह। शर सहमत हकर, आप परतिििव करत और वि आप अपनय यिस कत म कम स कम वयसकत उमर क और बयक अनध मरवश करनप स सकषम ह',
};

43
src/module/terms-of-use/screens/use-of-terms.tsx

@ -0,0 +1,43 @@ @@ -0,0 +1,43 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import {View} from 'react-native';
import {
colors,
Header,
IRouteParams,
RouteKey,
ScreenLayout,
} from '../../shared';
import { MainTextContainer } from '../../shared/components/text-containers/main-text-container';
import { TermsText } from '../config/terms-text';
import { terms } from '../config/use-of-terms.translations';
interface IProps extends IRouteParams {}
export const UseOfTerms: React.FC<IProps> = ({navigation}) => {
// const goBack = () => {
// navigation.navigate(RouteKey.Setting, {
// previous_screen: RouteKey.Game,
// });
// };
const {t, i18n} = useTranslation();
const lang = i18n.language;
return (
<ScreenLayout
backgroundColor={colors.primaryColor}
backgroundStatusBar={colors.primaryColor}
paddingHorizontal={20}
headerComponent={
<Header
leftIcon="arrow"
title={t('pageTitles.terms')}
onPressLeft={() => navigation.goBack()}
rightIcon="none"
/>
}>
<MainTextContainer text={terms[lang as keyof typeof terms]}/>
</ScreenLayout>
);
};

13
src/store/store.ts

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
import { configureStore } from '@reduxjs/toolkit';
import {Action, configureStore, ThunkAction} from '@reduxjs/toolkit';
import currentStepSlice from '../module/services/current-step/current-step-slice';
import daresSlice from '../module/services/dares/dares-slice';
import postsSlice from '../module/services/game-items/game-items-slice';
import truthsSlice from '../module/services/truths/truth-slice';
export const store = configureStore({
@ -8,8 +9,16 @@ export const store = configureStore({ @@ -8,8 +9,16 @@ export const store = configureStore({
currentStep: currentStepSlice,
truth: truthsSlice,
dares: daresSlice,
gameItems: postsSlice,
},
});
export type AppDispatch = typeof store.dispatch;
export type RootState = ReturnType<typeof store.getState>;
export type RootState = ReturnType<typeof store.getState>;
export type AppThunk<ReturnType = void> = ThunkAction<
ReturnType,
RootState,
unknown,
Action<string>
>;

Loading…
Cancel
Save