Browse Source

FEATURE | Connect to firebase & add crazy package

pull/5/head
Vlad Narizhnyi 11 months ago
parent
commit
041542ef94
  1. 4
      android/app/google-services.json
  2. 6
      android/build.gradle
  3. 8
      index.js
  4. 18
      ios/GoogleService-Info.plist
  5. 3
      ios/Podfile
  6. 2
      ios/Podfile.lock
  7. 14
      ios/Truth.xcodeproj/project.pbxproj
  8. 8
      src/i18n/interfaces/common.interface.ts
  9. 11
      src/i18n/locales/en/common.translation.ts
  10. 8
      src/i18n/locales/ua/common.translation.ts
  11. 2
      src/i18n/locales/ua/custom-pack.translation.ts
  12. 2
      src/i18n/locales/ua/settings.translation.ts
  13. 2
      src/module/common/typing/enums/custom-type.enum.ts
  14. 8
      src/module/common/typing/enums/index.ts
  15. 5
      src/module/common/typing/enums/package-type.enum.ts
  16. 2
      src/module/common/typing/enums/products.enum.ts
  17. 1
      src/module/common/typing/enums/storage-key.enum.ts
  18. 257
      src/module/common/typing/interfaces/game-item.ts
  19. 1
      src/module/custom-package/animation/index.ts
  20. 53
      src/module/custom-package/animation/use-animation-block.hook.tsx
  21. 55
      src/module/custom-package/atoms/custom-block.atom.tsx
  22. 1
      src/module/custom-package/index.ts
  23. 32
      src/module/custom-package/screens/custom-package-editor.screen.tsx
  24. 10
      src/module/custom-package/screens/custom-package-play.screen.tsx
  25. 4
      src/module/game/components/truth-or-dare-view.tsx
  26. 1
      src/module/game/config/index.ts
  27. 11
      src/module/game/config/package-name.config.ts
  28. 4
      src/module/game/helper/get-current-truth-dares.helper.ts
  29. 1
      src/module/game/index.ts
  30. 49
      src/module/game/screens/game.screen.tsx
  31. 7
      src/module/game/screens/players.screen.tsx
  32. 54
      src/module/game/screens/truth-or-dare.screen.tsx
  33. 18
      src/module/packages/components/packages-item.component.tsx
  34. 106
      src/module/packages/config/packages-list.config.tsx
  35. 6
      src/module/packages/screens/packages-list.screen.tsx
  36. 1
      src/module/root/navigations-groups/user.group.tsx
  37. 12
      src/module/settings/atoms/purchases.atom.tsx
  38. 8
      src/module/settings/config/purchases.config.ts
  39. 1
      src/module/settings/screens/purchases.screen.tsx
  40. 8
      src/module/settings/screens/write-to-us.screen.tsx
  41. 2
      src/module/settings/services/purchases.service.ts
  42. 12
      src/store/slices/custom-package.slice.ts
  43. 45
      src/store/slices/game-items.slice.ts
  44. 1
      src/store/slices/players.slice.ts

4
android/app/google-services.json

@ -1,8 +1,8 @@ @@ -1,8 +1,8 @@
{
"project_info": {
"project_number": "180425292880",
"project_number": "552568521005",
"firebase_url": "https://truthordare-6493e-default-rtdb.europe-west1.firebasedatabase.app",
"project_id": "truthordare-6493e",
"project_id": "truth-or-dare-fcc54",
"storage_bucket": "truthordare-6493e.appspot.com"
},
"client": [

6
android/build.gradle

@ -20,9 +20,9 @@ buildscript { @@ -20,9 +20,9 @@ buildscript {
mavenCentral()
}
dependencies {
classpath("com.android.tools.build:gradle")
classpath("com.facebook.react:react-native-gradle-plugin")
classpath ("com.google.gms:google-services:4.3.14")
classpath "com.android.tools.build:gradle"
classpath "com.facebook.react:react-native-gradle-plugin"
classpath 'com.google.gms:google-services:4.4.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files

8
index.js

@ -2,8 +2,8 @@ @@ -2,8 +2,8 @@
* @format
*/
import {AppRegistry} from 'react-native';
import App from './App';
import {name as appName} from './app.json';
import { AppRegistry } from 'react-native'
import App from './App'
import { name as appName } from './app.json'
AppRegistry.registerComponent(appName, () => App);
AppRegistry.registerComponent(appName, () => App)

18
ios/GoogleService-Info.plist

@ -2,22 +2,18 @@ @@ -2,22 +2,18 @@
<!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>
<string>AIzaSyDmYx2wadrC7tLUI-eS_tgUVuH0GrB_4mE</string>
<key>GCM_SENDER_ID</key>
<string>180425292880</string>
<string>552568521005</string>
<key>PLIST_VERSION</key>
<string>1</string>
<key>BUNDLE_ID</key>
<string>org.reactjs.native.example.Truth</string>
<string>com.truth</string>
<key>PROJECT_ID</key>
<string>truthordare-6493e</string>
<string>truth-or-dare-fcc54</string>
<key>STORAGE_BUCKET</key>
<string>truthordare-6493e.appspot.com</string>
<string>truth-or-dare-fcc54.appspot.com</string>
<key>IS_ADS_ENABLED</key>
<false></false>
<key>IS_ANALYTICS_ENABLED</key>
@ -29,8 +25,6 @@ @@ -29,8 +25,6 @@
<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>
<string>1:552568521005:ios:66c16d5229fe90142353a4</string>
</dict>
</plist>

3
ios/Podfile

@ -18,7 +18,8 @@ flipper_config = ENV['NO_FLIPPER'] == "1" ? FlipperConfiguration.disabled : Flip @@ -18,7 +18,8 @@ flipper_config = ENV['NO_FLIPPER'] == "1" ? FlipperConfiguration.disabled : Flip
linkage = ENV['USE_FRAMEWORKS']
if linkage != nil
Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green
use_frameworks! :linkage => linkage.to_sym
use_frameworks! :linkage => :static
$RNFirebaseAsStaticFramework = true
end
target 'Truth' do

2
ios/Podfile.lock

@ -1588,6 +1588,6 @@ SPEC CHECKSUMS: @@ -1588,6 +1588,6 @@ SPEC CHECKSUMS:
Yoga: 4c3aa327e4a6a23eeacd71f61c81df1bcdf677d5
YogaKit: f782866e155069a2cca2517aafea43200b01fd5a
PODFILE CHECKSUM: ce2deb38e840b0f84d5baf01ec7da0d590e1e158
PODFILE CHECKSUM: 0c63220a19ca9fd3d2ce02dc5eecdb8c820bf5ab
COCOAPODS: 1.12.1

14
ios/Truth.xcodeproj/project.pbxproj

@ -11,10 +11,10 @@ @@ -11,10 +11,10 @@
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; };
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
3F5CDF352995282400BD4B7F /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3F5CDF342995282400BD4B7F /* GoogleService-Info.plist */; };
52BCE0F228C76D5A008C74BC /* Fonts in Resources */ = {isa = PBXBuildFile; fileRef = 52BCE0EE28C76941008C74BC /* Fonts */; };
52BCE0F328C77143008C74BC /* fontello.ttf in Resources */ = {isa = PBXBuildFile; fileRef = DA10DFDF3E05483BA976401B /* fontello.ttf */; };
63120D812B0DE8C900E76BCD /* StoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 63120D802B0DE8C900E76BCD /* StoreKit.framework */; };
6318D32F2B459A5D0034E561 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 6318D32E2B459A5D0034E561 /* GoogleService-Info.plist */; };
637B62A42B07BAFB008D8917 /* Roboto-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 637B62A32B07BAFB008D8917 /* Roboto-Bold.ttf */; };
637B62A62B07BB0B008D8917 /* Roboto-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 637B62A52B07BB0B008D8917 /* Roboto-Regular.ttf */; };
8D22E0E3287C39ED0031C6E5 /* Launch Screen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8D22E0E2287C39ED0031C6E5 /* Launch Screen.storyboard */; };
@ -46,9 +46,9 @@ @@ -46,9 +46,9 @@
28F2047B035775EA39D23C93 /* libPods-Truth-TruthTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Truth-TruthTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
36C7150ADAB54DA0B3D10FF5 /* Roboto-Bold.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Roboto-Bold.ttf"; path = "../src/assets/resources/fonts/Roboto-Bold.ttf"; sourceTree = "<group>"; };
3F5CDF302995158300BD4B7F /* ios */ = {isa = PBXFileReference; lastKnownFileType = folder; path = ios; sourceTree = "<group>"; };
3F5CDF342995282400BD4B7F /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; };
52BCE0EE28C76941008C74BC /* Fonts */ = {isa = PBXFileReference; lastKnownFileType = folder; path = Fonts; sourceTree = "<group>"; };
63120D802B0DE8C900E76BCD /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = System/Library/Frameworks/StoreKit.framework; sourceTree = SDKROOT; };
6318D32E2B459A5D0034E561 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "../../../Downloads/GoogleService-Info.plist"; sourceTree = "<group>"; };
637B62A12B07B836008D8917 /* Roboto-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "Roboto-Regular.ttf"; path = "../src/assets/resources/fonts/Roboto-Regular.ttf"; sourceTree = "<group>"; };
637B62A22B07B836008D8917 /* Roboto-Bold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "Roboto-Bold.ttf"; path = "../src/assets/resources/fonts/Roboto-Bold.ttf"; sourceTree = "<group>"; };
637B62A32B07BAFB008D8917 /* Roboto-Bold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "Roboto-Bold.ttf"; path = "../src/assets/resources/fonts/Roboto-Bold.ttf"; sourceTree = "<group>"; };
@ -146,9 +146,9 @@ @@ -146,9 +146,9 @@
83CBB9F61A601CBA00E9B192 = {
isa = PBXGroup;
children = (
6318D32E2B459A5D0034E561 /* GoogleService-Info.plist */,
637B62A52B07BB0B008D8917 /* Roboto-Regular.ttf */,
637B62A32B07BAFB008D8917 /* Roboto-Bold.ttf */,
3F5CDF342995282400BD4B7F /* GoogleService-Info.plist */,
3F5CDF302995158300BD4B7F /* ios */,
13B07FAE1A68108700A75B9A /* Truth */,
832341AE1AAA6A7D00B99B32 /* Libraries */,
@ -289,12 +289,12 @@ @@ -289,12 +289,12 @@
buildActionMask = 2147483647;
files = (
637B62A62B07BB0B008D8917 /* Roboto-Regular.ttf in Resources */,
6318D32F2B459A5D0034E561 /* GoogleService-Info.plist in Resources */,
637B62A42B07BAFB008D8917 /* Roboto-Bold.ttf in Resources */,
52BCE0F328C77143008C74BC /* fontello.ttf in Resources */,
52BCE0F228C76D5A008C74BC /* Fonts in Resources */,
8D22E0E3287C39ED0031C6E5 /* Launch Screen.storyboard in Resources */,
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
3F5CDF352995282400BD4B7F /* GoogleService-Info.plist in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -749,7 +749,8 @@ @@ -749,7 +749,8 @@
OTHER_CPLUSPLUSFLAGS = "$(inherited)";
OTHER_LDFLAGS = (
"$(inherited)",
" ",
"-Wl",
"-ld_classic",
);
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
SDKROOT = iphoneos;
@ -825,7 +826,8 @@ @@ -825,7 +826,8 @@
OTHER_CPLUSPLUSFLAGS = "$(inherited)";
OTHER_LDFLAGS = (
"$(inherited)",
" ",
"-Wl",
"-ld_classic",
);
REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
SDKROOT = iphoneos;

8
src/i18n/interfaces/common.interface.ts

@ -5,4 +5,12 @@ interface Validation { @@ -5,4 +5,12 @@ interface Validation {
export interface Common {
validate: Validation
shareMessage: string
notFillPlayerTitle: string
notFillPlayerMessage: string
helpAlertTitle: string
helpAlertDesc: string
writeUsBtn: string
limitTitle: string
limitDesc: string
buyAfterBtn: string
}

11
src/i18n/locales/en/common.translation.ts

@ -8,4 +8,15 @@ const Validation = { @@ -8,4 +8,15 @@ const Validation = {
export const common: Common = {
validate: Validation,
shareMessage: 'Share this app with your friends',
notFillPlayerTitle: 'Oops',
notFillPlayerMessage:
'It seems that you did not fill in all the players name. Please fill it!',
helpAlertTitle: 'Well!',
helpAlertDesc:
'We will consider your question and give you an answer as soon as possible.',
writeUsBtn: 'Send',
limitTitle: 'Limit exhausted',
limitDesc:
'You have reached the limit of questions for this set. You need the full version to continue, but you can always use “Under18” and “Light” packages. They are always open for you.',
buyAfterBtn: 'Buy',
}

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

@ -8,4 +8,12 @@ const Validation = { @@ -8,4 +8,12 @@ const Validation = {
export const common: Common = {
validate: Validation,
shareMessage: 'Поділіться цим додатком зі своїми друзями',
notFillPlayerTitle: 'Ой',
notFillPlayerMessage: 'Якесь поле не заповнене. Перевір будь ласка!',
helpAlertTitle: 'Добре!',
helpAlertDesc: 'Ми розглянемо питання і якнайшвидше дамо відповідь.',
writeUsBtn: 'Відправити',
limitTitle: 'Ліміт вичерпано',
limitDesc: 'Ви досягли ліміту питань для пакету "Crazy". Щоб продовжити, потрібна повна версія. Але ти завжди можеш використовувати пакети «До 18» та «Легкий». Вони завжди відкриті для тебе.',
buyAfterBtn: 'До покупок'
}

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

@ -6,7 +6,7 @@ export const customPack: CustomPack = { @@ -6,7 +6,7 @@ export const customPack: CustomPack = {
description:
'Створіть свій власний пакет з питань та дій. Все залежить від твоєї уяви!',
editor: 'Редактор',
placeholder: 'Пиши тут...',
placeholder: 'Писати тут...',
addTruth: 'Додати питання',
addDare: 'Додати дію',
viewTruths: 'Питання',

2
src/i18n/locales/ua/settings.translation.ts

@ -6,7 +6,7 @@ export const settingTranslation: SettingLocale.Core = { @@ -6,7 +6,7 @@ export const settingTranslation: SettingLocale.Core = {
notifications: 'Сповіщення',
write: 'Напишіть нам',
rate: 'Оцініть нас',
share: 'Поділитися програмою',
share: 'Поділитися додатком',
policy: 'Політика конфіденційності',
label: 'Чим ми можемо допомогти?',
}

2
src/module/common/typing/enums/type-custom.enum.ts → src/module/common/typing/enums/custom-type.enum.ts

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
export enum TypeCustom {
export enum CustomType {
Questions = 'questions',
Dares = 'dares',
}

8
src/module/common/typing/enums/index.ts

@ -3,8 +3,8 @@ export * from './fonts.enum' @@ -3,8 +3,8 @@ export * from './fonts.enum'
export * from './storage-key.enum'
export * from './language.enum'
export * from './products.enum'
export * from './type-custom.enum'
export * from './custom-type.enum'
export * from './guest-route-keys.enum'
export * from './nav-group.enum';
export * from './user-route-keys.enum';
export * from './nav-group.enum'
export * from './user-route-keys.enum'
export * from './package-type.enum'

5
src/module/common/typing/enums/package-type.enum.ts

@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
export enum PackageType {
Under18 = 'under18',
Light = 'light',
Crazy = 'crazy',
}

2
src/module/common/typing/enums/products.enum.ts

@ -1,5 +1,3 @@ @@ -1,5 +1,3 @@
export enum ProductsEnum {
All = 'ALL',
Under18 = 'un18',
Crazy = 'Crz',
}

1
src/module/common/typing/enums/storage-key.enum.ts

@ -5,4 +5,5 @@ export enum StorageKey { @@ -5,4 +5,5 @@ export enum StorageKey {
Products = 'Products',
CustomPackage = 'CustomPackage',
Players = 'Players',
LimitForCrazy = 'limit'
}

257
src/module/common/typing/interfaces/game-item.ts

@ -1,9 +1,252 @@ @@ -1,9 +1,252 @@
import { Language } from "../enums";
import { Language } from '../enums'
export interface GameItem {
id: number;
isDare: boolean;
en: Language;
ua: Language;
hi: Language;
}
id: number
isDare: boolean
en: Language
ua: Language
hi?: Language
}
const gameItems = [
{
id: 1,
isDare: false,
en: 'What is your favorite subject in school?',
ua: 'Який твій улюблений предмет у школі?',
},
{
id: 2,
isDare: true,
en: 'Do your best dance moves for 1 minute.',
ua: 'Покажи свої найкращі танцювальні рухи протягом 1 хвилини.',
},
{
id: 3,
isDare: false,
en: 'If you could have any superpower, what would it be?',
ua: 'Яку б суперсилу ти обрав(ла), якщо б міг(ла)?',
},
{
id: 4,
isDare: true,
en: 'Take a funny selfie and share it with the group.',
ua: 'Зроби веселий селфі та поділись ним з групою.',
},
{
id: 5,
isDare: false,
en: 'What is your dream job?',
ua: 'Яка твоя мрійна професія?',
},
{
id: 6,
isDare: true,
en: 'Tell a joke that makes everyone laugh.',
ua: 'Розкажи анекдот, який розсмішить всіх.',
},
{
id: 7,
isDare: false,
en: 'If you could visit any place in the world, where would you go?',
ua: 'Якщо б ти міг(ла) відвідати будь-яке місце у світі, куди б ти поїхав(ла)?',
},
{
id: 8,
isDare: true,
en: 'Create a short rap about your day and perform it.',
ua: 'Створи короткий репродукційний вірш про свій день та виконай його.',
},
{
id: 9,
isDare: false,
en: 'What is your favorite hobby?',
ua: 'Яке твоє улюблене хобі?',
},
{
id: 10,
isDare: true,
en: 'Speak in an accent for the next two rounds.',
ua: 'Говори з акцентом протягом наступних двох раундів.',
},
{
id: 11,
isDare: false,
en: 'If you could have dinner with any fictional character, who would it be?',
ua: 'Якщо б ти міг(ла) пообідати з будь-яким вигаданим персонажем, хто б це був?',
},
{
id: 12,
isDare: true,
en: 'Act out a scene from your favorite movie.',
ua: 'Виконай сцену з твого улюбленого фільму.',
},
{
id: 13,
isDare: false,
en: "What is the weirdest food you've ever tried?",
ua: 'Яка найдивніша їжа, яку ти коли-небудь пробував(ла)?',
},
{
id: 14,
isDare: true,
en: 'Sing the chorus of your favorite song loudly.',
ua: 'Голосно заспівай приспів улюбленої пісні.',
},
{
id: 15,
isDare: false,
en: 'If you could time travel, where and when would you go?',
ua: 'Якщо б ти міг(ла) подорожувати в часі, куди і коли б ти поїхав(ла)?',
},
{
id: 16,
isDare: true,
en: 'Do your best celebrity impression for 1 minute.',
ua: 'Імітуй свого улюбленого знаменитості протягом 1 хвилини.',
},
{
id: 17,
isDare: false,
en: "What is the most adventurous thing you've ever done?",
ua: 'Яка найбільш пригодницька річ, яку ти коли-небудь робив(ла)?',
},
{
id: 18,
isDare: true,
en: 'Create a funny jingle about yourself and sing it.',
ua: 'Створи веселий джингл про себе та співай його.',
},
{
id: 19,
isDare: false,
en: 'If you had a pet dragon, what would you name it?',
ua: 'Якщо б у тебе був домашній дракон, як ти б його назвав(ла)?',
},
{
id: 20,
isDare: true,
en: 'Do your best impression of a famous TV character.',
ua: 'Імітуй свого улюбленого телевізійного персонажу.',
},
{
id: 21,
isDare: false,
en: 'What is your most embarrassing moment from childhood?',
ua: "Який твій найбільш сором'язливий момент з дитинства?",
},
{
id: 22,
isDare: true,
en: 'Dance like nobody is watching for 2 minutes.',
ua: 'Танцюй так, наче тебе ніхто не бачить, протягом 2 хвилин.',
},
{
id: 23,
isDare: false,
en: 'If you could have any superpower, what would it be and why?',
ua: 'Яку б суперсилу ти обрав(ла) і чому?',
},
{
id: 24,
isDare: true,
en: 'Speak in an accent (real or imaginary) for the next 3 rounds.',
ua: 'Говори з акцентом (реальним чи уявним) протягом наступних 3 раундів.',
},
{
id: 25,
isDare: false,
en: 'What is your guilty pleasure TV show or movie?',
ua: 'Яке твоє улюблене гучне задоволення серіалу чи фільму?',
},
{
id: 26,
isDare: true,
en: 'Take a silly selfie and post it on your social media.',
ua: 'Зроби дурницю селфі і опублікуй його у своїй соціальній мережі.',
},
{
id: 27,
isDare: false,
en: 'If you could swap lives with someone for a day, who would it be?',
ua: 'Якщо б ти міг(ла) помінятися життям з кимось на один день, хто б це був?',
},
{
id: 28,
isDare: true,
en: 'Do an impression of a famous politician or celebrity.',
ua: 'Імітуй відомого політика чи знаменитість.',
},
{
id: 29,
isDare: false,
en: "What is the strangest dream you've ever had?",
ua: 'Яка найдивніша мрія, яку ти коли-небудь мав(ла)?',
},
{
id: 30,
isDare: true,
en: 'Recite a tongue twister without making a mistake.',
ua: 'Вимов труднощі без помилок.',
},
{
id: 31,
isDare: false,
en: 'If you could time travel, would you go to the past or the future?',
ua: 'Якщо б ти міг(ла) подорожувати в часі, куди б ти поїхав(ла): в минуле чи майбутнє?',
},
{
id: 32,
isDare: true,
en: 'Sing a verse from your favorite song at the top of your lungs.',
ua: 'Заспівай куплет своєї улюбленої пісні на весь голос.',
},
{
id: 33,
isDare: false,
en: "What is the most adventurous thing you've ever done?",
ua: 'Яка найвідважніша річ, яку ти коли-небудь робив(ла)?',
},
{
id: 34,
isDare: true,
en: 'Act out your favorite movie scene without saying the lines.',
ua: 'Виконай улюблену сцену з фільму, не говорячи текст.',
},
{
id: 35,
isDare: false,
en: 'If you had to eat one type of cuisine for the rest of your life, what would it be?',
ua: 'Яку кухню ти обрав(ла) для споживання на все життя?',
},
{
id: 36,
isDare: true,
en: 'Do an interpretive dance to express a random emotion.',
ua: 'Виконай інтерпретативний танець, щоб виразити випадкову емоцію.',
},
{
id: 37,
isDare: false,
en: 'What is the most useless talent you have?',
ua: 'Який найбільш безглуздий талант у тебе є?',
},
{
id: 38,
isDare: true,
en: "Tell a joke, and make sure it's a good one!",
ua: 'Розкажи жарт, і переконайся, що він дійсно смішний!',
},
{
id: 39,
isDare: false,
en: "What's your go-to karaoke song?",
ua: 'Яка твоя улюблена пісня для караоке?',
},
{
id: 40,
isDare: true,
en: 'Create a funny and fictional story about the person to your right.',
ua: 'Створи смішну і вигадану історію про особу праворуч від тебе.',
},
]

1
src/module/custom-package/animation/index.ts

@ -0,0 +1 @@ @@ -0,0 +1 @@
export * from './use-animation-block.hook';

53
src/module/custom-package/animation/use-animation-block.hook.tsx

@ -0,0 +1,53 @@ @@ -0,0 +1,53 @@
import { useEffect, useRef } from 'react'
import { Animated } from 'react-native'
export const useAnimationBlock = (onDelete: any) => {
const deleteBlockAnim = useRef(new Animated.Value(0)).current
const viewBlockAnim = useRef(new Animated.Value(0)).current
const onPressDelete = () => {
Animated.timing(deleteBlockAnim, {
toValue: 1,
duration: 200,
useNativeDriver: true,
}).start(() => deleteBlockAnim.setValue(0))
setTimeout(onDelete, 200)
}
useEffect(() => {
Animated.timing(viewBlockAnim, {
toValue: 1,
duration: 0,
useNativeDriver: true,
}).start()
}, [])
const animStyle = {
transform: [
{
translateX: deleteBlockAnim.interpolate({
inputRange: [0, 1],
outputRange: [0, 400],
}),
},
{
translateY: viewBlockAnim.interpolate({
inputRange: [0, 1],
outputRange: [-50, 0],
}),
},
],
opacity:
viewBlockAnim ||
deleteBlockAnim.interpolate({
inputRange: [0, 1],
outputRange: [1, 0],
}),
}
return {
onPressDelete,
animStyle,
}
}

55
src/module/custom-package/atoms/custom-block.atom.tsx

@ -1,64 +1,19 @@ @@ -1,64 +1,19 @@
import React, { FC, useEffect, useRef } from 'react'
import React, { FC } from 'react'
import { Animated, LayoutAnimation, StyleSheet } from 'react-native'
import { TouchableOpacity } from 'react-native-gesture-handler'
import { Icon, Txt, colors } from '~module/common'
import { useAnimationBlock } from '../animation'
interface IProps {
text: string
onDelete: () => void
delay?: number
}
export const CustomBlock: FC<IProps> = ({ text, onDelete, delay }) => {
const deleteAnim = useRef(new Animated.Value(0)).current
const renderAnim = useRef(new Animated.Value(0)).current
const onPressDelete = () => {
Animated.spring(deleteAnim, {
toValue: 1,
useNativeDriver: true,
}).start()
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut)
setTimeout(onDelete, 200)
}
useEffect(() => {
Animated.spring(renderAnim, {
toValue: 1,
useNativeDriver: true,
delay,
}).start()
}, [])
export const CustomBlock: FC<IProps> = ({ text, onDelete }) => {
const { onPressDelete, animStyle } = useAnimationBlock(onDelete)
return (
<Animated.View
style={[
styles.block,
{
transform: [
{
translateX: deleteAnim.interpolate({
inputRange: [0, 1],
outputRange: [0, 400],
}),
},
{
translateY: renderAnim.interpolate({
inputRange: [0, 1],
outputRange: [-100, 0],
}),
},
],
opacity:
renderAnim ||
deleteAnim.interpolate({
inputRange: [0, 1],
outputRange: [1, 0],
}),
},
]}>
<Animated.View style={[styles.block, animStyle]}>
<Txt style={styles.blockTxt}>{text}</Txt>
<TouchableOpacity
style={styles.iconContainer}

1
src/module/custom-package/index.ts

@ -1,2 +1,3 @@ @@ -1,2 +1,3 @@
export * from './screens'
export * from './atoms'
export * from './animation';

32
src/module/custom-package/screens/custom-package-editor.screen.tsx

@ -10,7 +10,7 @@ import { @@ -10,7 +10,7 @@ import {
StorageKey,
appEvents,
colors,
TypeCustom,
CustomType,
useAppDispatch,
useNav,
UserRouteKey,
@ -36,15 +36,16 @@ export const CustomPackageEditorScreen: FC = () => { @@ -36,15 +36,16 @@ export const CustomPackageEditorScreen: FC = () => {
const customPackage = useSelector(selectCustomPackage)
const customPackageFromStore = useSelector(selectCustomPackageFromStore)
const isHaveNewChanges = useMemo(
() => _.isEqual(customPackageFromStore, customPackage),
[customPackageFromStore, customPackage],
)
const [value, setValue] = useState('')
const [activeMod, setActiveMod] = useState(TypeCustom.Questions)
const [activeMod, setActiveMod] = useState(CustomType.Questions)
const onView = (mod: TypeCustom) => {
const onViewListByType = (mod: CustomType) => {
setActiveMod(mod)
}
@ -52,19 +53,19 @@ export const CustomPackageEditorScreen: FC = () => { @@ -52,19 +53,19 @@ export const CustomPackageEditorScreen: FC = () => {
setValue('')
}
const OnAddQuestion = () => {
const onAddQuestion = () => {
if (!value) return
dispatch(setQuestions([...customPackage.questions, value]))
setActiveMod(TypeCustom.Questions)
setActiveMod(CustomType.Questions)
clearValue()
}
const OnAddDare = () => {
const onAddDare = () => {
if (!value) return
dispatch(setDares([...customPackage.dares, value]))
setActiveMod(TypeCustom.Dares)
setActiveMod(CustomType.Dares)
clearValue()
}
@ -73,7 +74,7 @@ export const CustomPackageEditorScreen: FC = () => { @@ -73,7 +74,7 @@ export const CustomPackageEditorScreen: FC = () => {
(it, index) => index !== indexItem,
)
activeMod === TypeCustom.Questions
activeMod === CustomType.Questions
? dispatch(setQuestions(newCustomItems))
: dispatch(setDares(newCustomItems))
}
@ -168,10 +169,10 @@ export const CustomPackageEditorScreen: FC = () => { @@ -168,10 +169,10 @@ export const CustomPackageEditorScreen: FC = () => {
<ButtonPrimary
mb={0}
style={styles.btn}
onPress={OnAddQuestion}>
onPress={onAddQuestion}>
{t('customPack.addTruth')}
</ButtonPrimary>
<ButtonPrimary mb={0} style={styles.btn} onPress={OnAddDare}>
<ButtonPrimary mb={0} style={styles.btn} onPress={onAddDare}>
{t('customPack.addDare')}
</ButtonPrimary>
</View>
@ -181,22 +182,22 @@ export const CustomPackageEditorScreen: FC = () => { @@ -181,22 +182,22 @@ export const CustomPackageEditorScreen: FC = () => {
styleTxt={styles.txt}
style={styles.btnTxt}
txtColor={
activeMod === TypeCustom.Questions
activeMod === CustomType.Questions
? colors.turquoise
: colors.purple
}
onPress={() => onView(TypeCustom.Questions)}>
onPress={() => onViewListByType(CustomType.Questions)}>
{t('customPack.viewTruths')}
</ButtonPrimary>
<ButtonPrimary
style={styles.btnTxt}
styleTxt={styles.txt}
txtColor={
activeMod === TypeCustom.Dares
activeMod === CustomType.Dares
? colors.turquoise
: colors.purple
}
onPress={() => onView(TypeCustom.Dares)}>
onPress={() => onViewListByType(CustomType.Dares)}>
{t('customPack.viewDares')}
</ButtonPrimary>
</View>
@ -208,9 +209,8 @@ export const CustomPackageEditorScreen: FC = () => { @@ -208,9 +209,8 @@ export const CustomPackageEditorScreen: FC = () => {
<View style={styles.customBody}>
{customPackage[activeMod].map((it, index) => (
<CustomBlock
key={it}
key={it + index}
text={it}
delay={index * 100}
onDelete={() => onDeleteItem(index)}
/>
))}

10
src/module/custom-package/screens/custom-package-play.screen.tsx

@ -6,14 +6,12 @@ import { useSelector } from 'react-redux' @@ -6,14 +6,12 @@ import { useSelector } from 'react-redux'
import {
ButtonPrimary,
Header,
ProductsEnum,
UserRouteKey,
ScreenLayout,
appEvents,
colors,
useNav,
} from '~module/common'
import { purchasesService } from '~module/settings'
import { selectCustomPackage } from '~store/slices'
export const CustomPackagePreviewScreen: FC = () => {
@ -31,10 +29,6 @@ export const CustomPackagePreviewScreen: FC = () => { @@ -31,10 +29,6 @@ export const CustomPackagePreviewScreen: FC = () => {
}
const goToGame = () => {
const isPurchased = checkIsPurchasedCustomPack()
if (!isPurchased) return nav.navigate(UserRouteKey.Purchases)
const isFullCustomPack = checkIsFullCustomPack()
if (!isFullCustomPack) return
@ -45,10 +39,6 @@ export const CustomPackagePreviewScreen: FC = () => { @@ -45,10 +39,6 @@ export const CustomPackagePreviewScreen: FC = () => {
})
}
const checkIsPurchasedCustomPack = () => {
return purchasesService.purchasedProducts.includes(ProductsEnum.All)
}
const checkIsFullCustomPack = () => {
const isEmptyTruths = _.isEmpty(customPackage.questions)
const isEmptyDares = _.isEmpty(customPackage.dares)

4
src/module/game/components/truth-or-dare-view.tsx

@ -4,7 +4,7 @@ import { @@ -4,7 +4,7 @@ import {
Font,
Icon,
Language,
TypeCustom,
CustomType,
colors,
useAppDispatch,
useAppSelector,
@ -20,7 +20,7 @@ import { useAnimationTruthOrDare } from '../animations' @@ -20,7 +20,7 @@ import { useAnimationTruthOrDare } from '../animations'
interface IProps {
items: any[]
isCustom?: TypeCustom | undefined
isCustom?: CustomType | undefined
}
export const TruthOrDareView: React.FC<IProps> = ({ items, isCustom }) => {

1
src/module/game/config/index.ts

@ -0,0 +1 @@ @@ -0,0 +1 @@
export * from './package-name.config';

11
src/module/game/config/package-name.config.ts

@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
import { PackageType } from '~module/common'
export const packageNameConfig: any = {
[PackageType.Under18]: {
en: 'Under 18',
ua: 'До 18 років',
hi: '18 स',
},
[PackageType.Light]: { en: 'Light', ua: 'Легкий', hi: 'रशन' },
[PackageType.Crazy]: { en: 'Crazy', ua: 'Божевільний', hi: 'पगल' },
}

4
src/module/game/helper/get-current-truth-dares.helper.ts

@ -1,9 +1,9 @@ @@ -1,9 +1,9 @@
import { selectShuffled, selectShuffledCustom } from '../../../store/slices'
import { TypeCustom, useAppSelector } from '../../common'
import { CustomType, PackageType, useAppSelector } from '../../common'
interface UseTruthOrDareProps {
isTruth: boolean
customType: TypeCustom
customType: CustomType
}
export const getCurrentTruthOrDare = ({

1
src/module/game/index.ts

@ -2,3 +2,4 @@ export * from './screens' @@ -2,3 +2,4 @@ export * from './screens'
export * from './components'
export * from './animations';
export * from './helper';
export * from './config';

49
src/module/game/screens/game.screen.tsx

@ -7,9 +7,10 @@ import { @@ -7,9 +7,10 @@ import {
Header,
UserRouteKey,
ScreenLayout,
TypeCustom,
CustomType,
useNav,
useAppDispatch,
PackageType,
} from '../../common'
import { useTranslation } from 'react-i18next'
import { useIsFocused, useRoute } from '@react-navigation/native'
@ -22,23 +23,29 @@ import { @@ -22,23 +23,29 @@ import {
} from '~store/slices'
import { PlayerName } from '../components/player-name.component'
import { useSelector } from 'react-redux'
import { packageNameConfig } from '../config'
interface IRouteParams {
packageType?: PackageType
isCustom?: boolean
}
export const GameScreen: FC = () => {
const { t } = useTranslation()
const { t, i18n } = useTranslation()
const nav = useNav()
const dispatch = useAppDispatch()
const { params }: any = useRoute()
const { packageName, isCustom } = params
const { params } = useRoute()
const { packageType, isCustom }: IRouteParams = params
const isFocused = useIsFocused()
const { animStyle, startAnimationsBorder } = useAnimationButton()
const playerName = useSelector(selectCurrentPlayer)
const currentPlayer = useSelector(selectCurrentPlayer)
useEffect(() => {
refreshList()
}, [])
const refreshList = () => {
!isCustom && dispatch(shuffleItems())
!isCustom && dispatch(shuffleItems(packageType))
isCustom && dispatch(shuffleCustom())
dispatch(resetSteps())
}
@ -46,37 +53,43 @@ export const GameScreen: FC = () => { @@ -46,37 +53,43 @@ export const GameScreen: FC = () => {
const randomGame = () => {
const isTruthRandom = Math.random() < 0.5
const customRandom = isTruthRandom
? TypeCustom.Questions
: TypeCustom.Dares
? CustomType.Questions
: CustomType.Dares
nav.navigate(UserRouteKey.TruthOrDare, {
isTruth: isTruthRandom,
packageName,
packageType,
customType: isCustom ? customRandom : null,
playerName: playerName,
currentPlayer,
})
}
const onChooseTruth = () => {
nav.navigate(UserRouteKey.TruthOrDare, {
isTruth: true,
packageName,
customType: isCustom && TypeCustom.Questions,
playerName: playerName,
packageType,
customType: isCustom && CustomType.Questions,
currentPlayer,
})
}
const onChooseDare = () => {
nav.navigate(UserRouteKey.TruthOrDare, {
packageName,
customType: isCustom && TypeCustom.Dares,
playerName: playerName,
packageType,
customType: isCustom && CustomType.Dares,
currentPlayer,
})
}
return (
<ScreenLayout headerComponent={<Header title={packageName} gamer />}>
<PlayerName playerName={playerName} />
<ScreenLayout
headerComponent={
<Header
title={packageNameConfig[packageType][i18n.language]}
gamer
/>
}>
<PlayerName playerName={currentPlayer} />
<View style={styles.wrapButtons}>
<ButtonPrimary
width={200}

7
src/module/game/screens/players.screen.tsx

@ -53,14 +53,13 @@ export const PlayersScreen: FC = () => { @@ -53,14 +53,13 @@ export const PlayersScreen: FC = () => {
if (hasEmptyName) {
return appEvents.emit('alert', {
title: 'Oops',
subtitle:
'It seems that you did not fill in all the players name. Please fill it.',
title: t('common.notFillPlayerTitle'),
subtitle: t('common.notFillPlayerMessage'),
})
}
await AsyncStorage.setItem(StorageKey.Players, JSON.stringify(players))
nav.navigate(UserRouteKey.Packages)
}

54
src/module/game/screens/truth-or-dare.screen.tsx

@ -6,9 +6,12 @@ import { @@ -6,9 +6,12 @@ import {
Header,
UserRouteKey,
ScreenLayout,
TypeCustom,
CustomType,
useAppDispatch,
useNav,
PackageType,
StorageKey,
appEvents,
} from '../../common'
import {
nextStep,
@ -21,31 +24,64 @@ import { TruthOrDareView } from '../components' @@ -21,31 +24,64 @@ import { TruthOrDareView } from '../components'
import { useAnimationIconsButton } from '../animations'
import { getCurrentTruthOrDare } from '../helper'
import { PlayerName } from '../components/player-name.component'
import { packageNameConfig } from '../config'
import { useTranslation } from 'react-i18next'
import AsyncStorage from '@react-native-async-storage/async-storage'
interface IRouteParams {
packageName?: string
packageType?: PackageType
isTruth?: boolean
customType?: TypeCustom
playerName?: string
customType?: CustomType
currentPlayer?: string
}
export const TruthOrDareScreen: React.FC = () => {
const nav = useNav()
const { t, i18n } = useTranslation()
const dispatch = useAppDispatch()
const { params } = useRoute()
const { packageName, isTruth, customType, playerName }: IRouteParams =
const { packageType, isTruth, customType, currentPlayer }: IRouteParams =
params
const truthOrDareItems = getCurrentTruthOrDare({ isTruth, customType })
const truthOrDareItems = getCurrentTruthOrDare({
isTruth,
customType,
})
const { animRotate, animScale } = useAnimationIconsButton()
const onNext = () => {
nav.navigate(UserRouteKey.Game, { packageName })
nav.navigate(UserRouteKey.Game, { packageType, isCustom: customType })
dispatch(onNextPlayer())
}
const getLimitForCrazy = async () => {
const limit = await AsyncStorage.getItem(StorageKey.LimitForCrazy)
if (!limit) return AsyncStorage.setItem(StorageKey.LimitForCrazy, '1')
const currentLimit = Number(JSON.parse(limit))
if (currentLimit >= 5) {
return appEvents.emit('confirm', {
title: t('common.limitTitle'),
subtitle: t('common.limitDesc'),
confirmBtnText: t('common.buyAfterBtn'),
isRedButton: true,
buttons: [
{ onPress: () => nav.navigate(UserRouteKey.Packages) },
{
onPress: () => nav.navigate(UserRouteKey.Purchases),
},
],
})
}
AsyncStorage.setItem(StorageKey.LimitForCrazy, `${currentLimit + 1}`)
}
useEffect(() => {
dispatch(nextStep())
getLimitForCrazy()
}, [])
const refreshList = () => {
@ -60,11 +96,11 @@ export const TruthOrDareScreen: React.FC = () => { @@ -60,11 +96,11 @@ export const TruthOrDareScreen: React.FC = () => {
<Header
gamer
onPressLeft={() => onNext()}
title={packageName}
title={packageNameConfig[packageType][i18n.language]}
/>
}>
<View style={{ flex: 1 }}>
<PlayerName playerName={playerName} />
<PlayerName playerName={currentPlayer} />
<TruthOrDareView
items={truthOrDareItems}

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

@ -1,18 +1,21 @@ @@ -1,18 +1,21 @@
import React, { FC } from 'react'
import { Animated, StyleSheet, View } from 'react-native'
import { ButtonWithIcon, UserRouteKey, Txt, colors, useNav } from '../../common'
import {
ButtonWithIcon,
UserRouteKey,
Txt,
colors,
useNav,
PackageType,
} from '../../common'
import { useAnimationList } from '../animation'
interface IType {
[key: string]: string
}
interface IPackage {
packageName: string
description: string
image: JSX.Element
questions: IType[]
actions: IType[]
delay: number
packageType: PackageType
}
export const PackageItem: FC<IPackage> = ({
@ -20,13 +23,14 @@ export const PackageItem: FC<IPackage> = ({ @@ -20,13 +23,14 @@ export const PackageItem: FC<IPackage> = ({
description,
image,
delay,
packageType,
}) => {
const nav = useNav()
const { animationStyleItem } = useAnimationList(delay)
const onPlay = () => {
nav.navigate(UserRouteKey.Game, { packageName })
nav.navigate(UserRouteKey.Game, { packageType })
}
return (

106
src/module/packages/config/packages-list.config.tsx

@ -1,9 +1,11 @@ @@ -1,9 +1,11 @@
import React from 'react'
import { Image } from 'react-native'
import { PackageType } from '~module/common'
export const packageListConfig = [
{
title: { en: 'Under 18', ua: 'До 18 років', hi: '18 स' },
packageType: PackageType.Under18,
image: (
<Image
source={require('../../../assets/image/rabbit.png')}
@ -15,43 +17,10 @@ export const packageListConfig = [ @@ -15,43 +17,10 @@ export const packageListConfig = [
ua: 'Гострі питання і завдання для молоді і звичайно без алкоголю.',
hi: 'यिए तरशन और कय और निित रप सशरब नह।',
},
questions: [
{
en: 'Under truth',
ua: 'до 18 років правда',
hi: '18 स परषण',
},
{
en: 'Under truth2',
ua: 'до 18 років правда2',
hi: '18 स परषण2',
},
{
en: 'Under truth3',
ua: 'до 18 років правда3',
hi: '18 स परषण3',
},
],
actions: [
{
en: 'Light dare',
ua: 'до 18 років дія',
hi: '18 स परषण',
},
{
en: 'Light dare2',
ua: 'до 18 років дія2',
hi: '18 स परषण2',
},
{
en: 'Light dare3',
ua: 'до 18 років дія3',
hi: '18 स परषण3',
},
],
},
{
title: { en: 'Light', ua: 'Легкий', hi: 'रशन' },
packageType: PackageType.Light,
image: (
<Image
source={require('../../../assets/image/feathers.png')}
@ -63,43 +32,10 @@ export const packageListConfig = [ @@ -63,43 +32,10 @@ export const packageListConfig = [
ua: 'Киньте виклик своїм друзям або своїй другій половинці та подивіться, як далеко вони можуть зайти!',
hi: 'अपन अपन महतवपण दसर और दिितनर ज सकत!',
},
questions: [
{
en: 'Light truth',
ua: 'легка правда',
hi: 'रशन परषण',
},
{
en: 'Light truth2',
ua: 'легка правда2',
hi: 'रशन परषण',
},
{
en: 'Light truth3',
ua: 'легка правда3',
hi: 'रशन परषण3',
},
],
actions: [
{
en: 'Light dare',
ua: 'легка дія',
hi: 'रशन परषण',
},
{
en: 'Light dare2',
ua: 'легка дія2',
hi: 'रशन परषण2',
},
{
en: 'Light dare3',
ua: 'легка дія3',
hi: 'रशन परषण3',
},
],
},
{
title: { en: 'Crazy', ua: 'Божевільний', hi: 'पगल' },
packageType: PackageType.Crazy,
image: (
<Image
source={require('../../../assets/image/hand.png')}
@ -112,39 +48,5 @@ export const packageListConfig = [ @@ -112,39 +48,5 @@ export const packageListConfig = [
ua: 'Киньте виклик своїм друзям або своїй другій половинці та подивіться, як далеко вони можуть зайти!',
hi: 'अपन अपन महतवपण दसर और दिितनर ज सकत!',
},
questions: [
{
en: 'Crazy truth',
ua: 'божевільна правда',
hi: 'पगल परषण',
},
{
en: 'Crazy truth2',
ua: 'божевільна правда2',
hi: 'पगल परषण2',
},
{
en: 'Crazy truth3',
ua: 'божевільна правда3',
hi: 'पगल परषण3',
},
],
actions: [
{
en: 'Crazy dare',
ua: 'божевільна дія',
hi: 'पगल परषण',
},
{
en: 'Crazy dare2',
ua: 'божевільна дія2',
hi: 'पगल परषण2',
},
{
en: 'Crazy dare3',
ua: 'божевільна дія3',
hi: 'पगल परषण3',
},
],
},
]

6
src/module/packages/screens/packages-list.screen.tsx

@ -5,14 +5,11 @@ import { useTranslation } from 'react-i18next' @@ -5,14 +5,11 @@ import { useTranslation } from 'react-i18next'
import { packageListConfig } from '../config'
import { PackageItem } from '../components'
import { CustomPackage, PackagesPageSeparator } from '../atoms'
import { useIsFocused } from '@react-navigation/native'
export const PackagesListScreen: FC = () => {
const nav = useNav()
const { i18n } = useTranslation()
const isFocus = useIsFocused()
return (
<ScreenLayout
needScroll
@ -28,9 +25,8 @@ export const PackagesListScreen: FC = () => { @@ -28,9 +25,8 @@ export const PackagesListScreen: FC = () => {
{packageListConfig.map((item: any, index) => (
<PackageItem
packageName={item.title[i18n.language]}
packageType={item.packageType}
description={item.description[i18n.language]}
questions={item.questions}
actions={item.actions}
image={item.image}
key={index}
delay={Number(`${4 * index}00`)}

1
src/module/root/navigations-groups/user.group.tsx

@ -40,7 +40,6 @@ export const UserNavigationGroup: FC = () => { @@ -40,7 +40,6 @@ export const UserNavigationGroup: FC = () => {
<UserStack.Screen
name={UserRouteKey.Players}
component={PlayersScreen}
options={{ animation: 'fade_from_bottom' }}
/>
<UserStack.Screen name={UserRouteKey.Game} component={GameScreen} />

12
src/module/settings/atoms/purchases.atom.tsx

@ -7,7 +7,6 @@ interface IProps { @@ -7,7 +7,6 @@ interface IProps {
title: string
price: string
iconName: string
hasDiscount: boolean
isPurchased: boolean
onPress: () => void
}
@ -15,25 +14,15 @@ interface IProps { @@ -15,25 +14,15 @@ interface IProps {
export const PurchaseAtom: FC<IProps> = ({
title,
price,
hasDiscount,
iconName,
isPurchased,
onPress,
}) => {
const renderDiscountAtom = () => {
return (
<View style={styles.discount}>
<Txt style={styles.discountTxt}>-30%</Txt>
</View>
)
}
return (
<TouchableOpacity style={styles.container} onPress={onPress}>
<View style={styles.row}>
<Icon name={iconName} size={24} color={colors.purple} />
<Txt style={styles.txt}>{title}</Txt>
{hasDiscount && renderDiscountAtom()}
</View>
{isPurchased ? (
<ButtonWithIcon
@ -81,7 +70,6 @@ const styles = StyleSheet.create({ @@ -81,7 +70,6 @@ const styles = StyleSheet.create({
},
iconPlay: {
width: 60,
height: '100%',
},
txt: {
lineHeight: 24,

8
src/module/settings/config/purchases.config.ts

@ -1,16 +1,8 @@ @@ -1,16 +1,8 @@
import { ProductsEnum } from '../../common'
export const purchasesConfig: any = {
[ProductsEnum.Under18]: {
name: 'purchases.under18',
icon: 'ghost',
},
[ProductsEnum.Crazy]: {
name: 'purchases.crazy',
icon: 'crazy',
},
[ProductsEnum.All]: {
name: 'purchases.allPackage',
icon: 'all_packages',
},
}

1
src/module/settings/screens/purchases.screen.tsx

@ -72,7 +72,6 @@ export const PurchasesScreen: FC = () => { @@ -72,7 +72,6 @@ export const PurchasesScreen: FC = () => {
key={it.productId}
title={t(it.name)}
price={it.price}
hasDiscount={it.productId === ProductsEnum.All}
iconName={it.icon}
isPurchased={it.isPurchased}
onPress={() =>

8
src/module/settings/screens/write-to-us.screen.tsx

@ -24,8 +24,8 @@ export const WriteToUsScreen: FC = () => { @@ -24,8 +24,8 @@ export const WriteToUsScreen: FC = () => {
const onSendText = () => {
appEvents.emit('alert', {
title: 'Aga, thanks',
subtitle: 'We rozberemosya',
title: t('common.helpAlertTitle'),
subtitle: t('common.helpAlertDesc'),
onClose: () => nav.goBack(),
})
}
@ -46,7 +46,7 @@ export const WriteToUsScreen: FC = () => { @@ -46,7 +46,7 @@ export const WriteToUsScreen: FC = () => {
style={styles.button}
disabled={!form.values.message}
onPress={() => form.onSubmit(onSendText)}>
Send to us
{t('common.writeUsBtn')}
</ButtonPrimary>
</ScreenLayout>
)
@ -55,6 +55,6 @@ export const WriteToUsScreen: FC = () => { @@ -55,6 +55,6 @@ export const WriteToUsScreen: FC = () => {
const styles = StyleSheet.create({
button: {
marginTop: 20,
backgroundColor: colors.lightPurple,
backgroundColor: colors.purple,
},
})

2
src/module/settings/services/purchases.service.ts

@ -10,7 +10,7 @@ import { ProductsEnum, StorageKey } from '../../common' @@ -10,7 +10,7 @@ import { ProductsEnum, StorageKey } from '../../common'
import { purchasesConfig } from '../config'
import AsyncStorage from '@react-native-async-storage/async-storage'
const ID_PRODUCTS = [ProductsEnum.All, ProductsEnum.Crazy, ProductsEnum.Under18]
const ID_PRODUCTS = [ProductsEnum.Crazy]
interface ProductItem {
productId: ProductsEnum

12
src/store/slices/custom-package.slice.ts

@ -1,17 +1,17 @@ @@ -1,17 +1,17 @@
import { PayloadAction, createAsyncThunk, createSlice } from '@reduxjs/toolkit'
import { StorageKey, TypeCustom } from '../../module/common'
import { StorageKey, CustomType } from '../../module/common'
import { RootState } from '../store'
import _ from 'lodash'
import AsyncStorage from '@react-native-async-storage/async-storage'
interface ICustomPackage {
[TypeCustom.Questions]: string[]
[TypeCustom.Dares]: string[]
[CustomType.Questions]: string[]
[CustomType.Dares]: string[]
}
const defaultCustomPackage: ICustomPackage = {
[TypeCustom.Questions]: [],
[TypeCustom.Dares]: [],
[CustomType.Questions]: [],
[CustomType.Dares]: [],
}
export interface CustomPackageState {
@ -107,8 +107,6 @@ export const selectCustomPackage = (state: RootState) => @@ -107,8 +107,6 @@ export const selectCustomPackage = (state: RootState) =>
state.customPackage.customPackage
export const selectCustomPackageFromStore = (state: RootState) =>
state.customPackage.customPackageFromStore
export const selectCustomLoaded = (state: RootState) =>
state.customPackage.loaded
export const selectShuffledCustom = (state: RootState) =>
state.customPackage.shuffleCustomPackage

45
src/store/slices/game-items.slice.ts

@ -1,18 +1,23 @@ @@ -1,18 +1,23 @@
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit'
import { PayloadAction, createAsyncThunk, createSlice } from '@reduxjs/toolkit'
import firestore from '@react-native-firebase/firestore'
import { GameItem } from '../../module/common'
import { GameItem, PackageType } from '../../module/common'
import { RootState } from '../store'
import _ from 'lodash'
import { purchasesService } from '~module/settings'
export interface GameItemsState {
gameItems: GameItem[]
[PackageType.Under18]: GameItem[]
[PackageType.Light]: GameItem[]
[PackageType.Crazy]: GameItem[]
shuffled: GameItem[]
loaded: boolean
hasError: boolean
}
const initialState: GameItemsState = {
gameItems: [],
under18: [],
light: [],
crazy: [],
shuffled: [],
loaded: false,
hasError: false,
@ -198,28 +203,35 @@ const arr = [ @@ -198,28 +203,35 @@ const arr = [
export const getGameItemsFromFirestore = createAsyncThunk(
'game-items/get-from-firestore',
async () => {
const query = await firestore().collection('light').get()
const jsonResponse = await firestore().collection('content').get()
const data = jsonResponse.docs.map(it => it.data())
const response: any = query.docs.map(doc => doc.data())
const allPackages = data.reduce((acc, it) => {
const packageKey = _.keys(it)[0]
acc[packageKey] = it[packageKey]
return acc
}, {})
const truthsAndDares: GameItem[] = response[0]['data']
return truthsAndDares
return allPackages
},
)
export const postsSlice = createSlice({
export const gameItemsSlice = createSlice({
name: 'gameItems',
initialState,
reducers: {
shuffleItems: state => {
state.shuffled = _.shuffle(state.gameItems)
shuffleItems: (state, action: PayloadAction<PackageType>) => {
state.shuffled = _.shuffle(state[action.payload])
},
},
extraReducers(builder) {
builder
.addCase(getGameItemsFromFirestore.fulfilled, (state, action) => {
state.gameItems = action.payload
const setLimitForCrazy = purchasesService.purchasedProducts
state.under18 = action.payload[PackageType.Under18]
state.light = action.payload[PackageType.Light]
state.crazy = action.payload[PackageType.Crazy]
state.hasError = false
state.loaded = true
})
@ -232,11 +244,8 @@ export const postsSlice = createSlice({ @@ -232,11 +244,8 @@ export const postsSlice = createSlice({
},
})
export const { shuffleItems } = postsSlice.actions
export const { shuffleItems } = gameItemsSlice.actions
export const selectGameItems = (state: RootState) => state.gameItems.gameItems
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
export default gameItemsSlice.reducer

1
src/store/slices/players.slice.ts

@ -32,6 +32,7 @@ export const playersSlice = createSlice({ @@ -32,6 +32,7 @@ export const playersSlice = createSlice({
reducers: {
setPlayers: (state, action: PayloadAction<string[]>) => {
state.players = action.payload
state.currentPlayer = action.payload[0]
},
onNextPlayer: state => {
state.playerIndex = state.playerIndex + 1

Loading…
Cancel
Save