Browse Source

IMPROVE | Improve shuffle questions and dares

pull/5/head
Vlad Narizhnyi 11 months ago
parent
commit
7763b95fb0
  1. 4
      src/config/fontello.json
  2. 1
      src/i18n/interfaces/common.interface.ts
  3. 3
      src/i18n/locales/en/common.translation.ts
  4. 12
      src/i18n/locales/en/custom-pack.translation.ts
  5. 2
      src/i18n/locales/en/steps.translation.ts
  6. 2
      src/i18n/locales/hi/onBoardingButton.translation.ts
  7. 5
      src/i18n/locales/ua/common.translation.ts
  8. 12
      src/i18n/locales/ua/custom-pack.translation.ts
  9. 2
      src/i18n/locales/ua/onBoardingButton.translation.ts
  10. 2
      src/i18n/locales/ua/purchases.translation.ts
  11. 35
      src/i18n/locales/ua/step.translation.ts
  12. 2
      src/module/common/components/buttons/button-primary.component.tsx
  13. 2
      src/module/common/hooks/index.ts
  14. 4
      src/module/common/hooks/use-dispatch.hook.ts
  15. 5
      src/module/common/hooks/use-selector.hook.ts
  16. 1
      src/module/common/index.ts
  17. 8
      src/module/common/questions-dares-list/questions-dares-list.ts
  18. 1
      src/module/common/services/index.ts
  19. 34
      src/module/common/services/storage.service.ts
  20. 4
      src/module/common/typing/enums/storage-key.enum.ts
  21. 36
      src/module/custom-package/screens/custom-package-editor.screen.tsx
  22. 12
      src/module/custom-package/screens/custom-package-play.screen.tsx
  23. 10
      src/module/game/components/player-name.component.tsx
  24. 49
      src/module/game/components/truth-or-dare-view.tsx
  25. 24
      src/module/game/helper/get-current-truth-dares.helper.ts
  26. 123
      src/module/game/helper/get-current-truth-dares.helper.tsx
  27. 49
      src/module/game/screens/game.screen.tsx
  28. 9
      src/module/game/screens/players.screen.tsx
  29. 88
      src/module/game/screens/truth-or-dare.screen.tsx
  30. 1
      src/module/packages/components/packages-item.component.tsx
  31. 2
      src/module/packages/screens/packages-list.screen.tsx
  32. 5
      src/module/root/atoms/on-boarding-button.component.tsx
  33. 4
      src/module/root/screens/language-select.screen.tsx
  34. 11
      src/module/root/screens/loading-screen.tsx
  35. 4
      src/module/settings/screens/settings.screen.tsx
  36. 10
      src/module/settings/services/purchases.service.ts
  37. 40
      src/store/slices/current-step.slice.ts
  38. 63
      src/store/slices/custom-package.slice.ts
  39. 20
      src/store/slices/game-items.slice.ts
  40. 7
      src/store/slices/players.slice.ts

4
src/config/fontello.json

@ -236,7 +236,7 @@ @@ -236,7 +236,7 @@
},
{
"uid": "c0f00bfaafecf771a588798f5995fee2",
"css": "settings",
"css": "players",
"code": 59411,
"src": "custom_icons",
"selected": true,
@ -244,7 +244,7 @@ @@ -244,7 +244,7 @@
"path": "M78.6 162.7C78.6 79.4 146.1 11.4 230 11.4 313.8 11.4 381.4 78.9 381.4 162.7 381.4 244.7 316.8 311.1 235.8 314.1 233.9 314.1 232.1 314.1 230.2 313.8 228.4 314.1 226.5 314.1 224.7 314.1 143.6 311.1 79.2 244.7 78.6 163L78.6 162.7ZM146.8 162.6C147.2 207.2 181.5 243 224.7 245.8 228.4 245.5 232.1 245.5 235.7 245.8 279 243 313.2 207.2 313.2 162.7 313.2 116.6 276.2 79.5 230 79.5 184 79.5 146.9 116.9 146.8 162.6ZM685.5 162.7C685.5 116.6 722.5 79.5 768.6 79.5 814.7 79.5 851.7 116.9 851.8 162.6 851.4 207.2 817.1 243 773.9 245.8 770.3 245.5 766.5 245.5 762.9 245.8 719.6 243 685.5 207.2 685.5 162.7ZM768.6 11.4C684.8 11.4 617.3 78.9 617.3 162.7 617.3 244.7 681.8 311.1 762.9 314.1 764.7 314.1 766.6 314.1 768.4 313.8 770.2 314.1 772.1 314.1 774 314.1 855 311.1 919.4 244.7 920 163H920V162.7C920 79.4 852.5 11.4 768.6 11.4ZM923.8 394.3C866.6 356.3 787.8 344.8 718.7 356.9 700.1 360.1 687.7 377.8 691 396.3 694.2 414.9 711.9 427.3 730.4 424 785.9 414.3 846.1 424.6 886.1 451.1 911 467.7 919 486.3 919 500.5 919 514.6 911 533.2 886.1 549.8L886 549.9C846.5 576.3 787.1 586.6 731.6 577.3 713 574.2 695.4 586.7 692.3 605.3 689.2 623.8 701.7 641.4 720.3 644.5 789.2 656.1 867 644.6 923.9 606.5 963.1 580.4 987.2 542.6 987.2 500.5 987.2 458.3 963.1 420.5 923.9 394.4L923.8 394.3ZM268.2 424C212.8 414.3 152.5 424.6 112.5 451.1 87.6 467.7 79.7 486.3 79.7 500.5 79.7 514.6 87.6 533.2 112.5 549.8L112.6 549.9C152.1 576.3 211.5 586.6 267.1 577.3 285.6 574.2 303.2 586.7 306.3 605.3 309.5 623.8 296.9 641.4 278.4 644.5 209.4 656.1 131.6 644.6 74.7 606.5 35.6 580.4 11.5 542.6 11.5 500.5 11.5 458.3 35.6 420.5 74.7 394.4L74.8 394.3C132.1 356.3 210.9 344.8 280 356.9 298.5 360.1 310.9 377.8 307.7 396.3 304.4 414.9 286.8 427.3 268.2 424ZM495.9 419.1C449.7 419.1 412.7 456.1 412.7 502.3 412.7 546.7 446.9 582.5 490.2 585.4 493.9 585 497.6 585 501.3 585.4 544.2 582.9 578.7 547 579.1 502.1 579 456.4 542 419.1 495.9 419.1ZM344.5 502.3C344.5 418.4 412.1 350.9 495.9 350.9 579.8 350.9 647.3 419 647.3 502.3V502.5H647.3C646.7 584.1 582.5 651.3 501 653.6 499.2 653.7 497.4 653.6 495.7 653.4 493.8 653.6 492 653.7 490.1 653.6 409.1 650.7 344.5 584.3 344.5 502.3ZM651.2 734.4C608.2 705.7 553.3 692.5 500.2 692.5 447 692.5 392 705.7 348.9 734.3L348.8 734.4C309.7 760.5 285.6 798.3 285.6 840.5 285.6 882.6 309.7 920.4 348.8 946.5 391.9 975.4 446.9 988.8 500 988.8 553.1 988.8 608.1 975.4 651.2 946.5 690.3 920.4 714.4 882.6 714.4 840.5 714.4 798.3 690.3 760.5 651.2 734.4ZM353.7 840.5C353.7 826.3 361.7 807.7 386.6 791.1 416.2 771.5 457.3 760.7 500.2 760.7 543.1 760.7 584 771.5 613.4 791.1 638.3 807.7 646.3 826.3 646.3 840.5 646.3 854.6 638.3 873.2 613.4 889.8L613.3 889.8C583.7 909.6 542.8 920.6 500 920.6 457.2 920.6 416.3 909.6 386.7 889.8L386.6 889.8C361.7 873.2 353.7 854.6 353.7 840.5Z",
"width": 1000
},
"search": ["settings"]
"search": ["players"]
},
{
"uid": "dd62c27b488715bc9c53b0d0eb62e70f",

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

@ -13,4 +13,5 @@ export interface Common { @@ -13,4 +13,5 @@ export interface Common {
limitTitle: string
limitDesc: string
buyAfterBtn: string
no: string
}

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

@ -17,6 +17,7 @@ export const common: Common = { @@ -17,6 +17,7 @@ export const common: Common = {
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.',
'You have reached the limit of questions for this set. You need the full version to continue, but you can use “Under18” and “Light” packages. They are always open for you.',
buyAfterBtn: 'Buy',
no: 'Back',
}

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

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
import { CustomPack } from "~i18n/interfaces/custom-pack.interface";
import { CustomPack } from '~i18n/interfaces/custom-pack.interface'
export const customPack: CustomPack = {
label: 'Custom package',
@ -11,17 +11,17 @@ export const customPack: CustomPack = { @@ -11,17 +11,17 @@ export const customPack: CustomPack = {
addDare: 'Add a dare',
viewTruths: 'View questions',
viewDares: 'View dares',
alertCreateTitle: 'Gratefully!',
alertCreateTitle: 'Gratefully! 🎉',
alertCreateDesc: 'You can play your custom package now!',
alertSaveTitle: 'You have unsaved changes',
alertSaveTitle: 'You have unsaved changes.',
alertSaveDesc: 'Save changes?',
alertSaveNo: 'No',
alertSaveYes: 'Save',
alertEmptyTitle: 'Oops!',
alertEmptyTitle: 'Oops! 👀',
alertEmptyTruthDesc:
'Your questions list is empty. You need have at least 1 question',
'Your questions list is empty. You need have at least 1 question.',
alertEmptyDaresDesc:
'Your dares list is empty. You need have at least 1 dare',
'Your dares list is empty. You need have at least 1 dare.',
editorBtn: 'Tasks and questions editor',
play: 'Play',
}

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

@ -13,6 +13,6 @@ export const onBoardingTranslation: OnBoardingLocale.OnboardingSteps = { @@ -13,6 +13,6 @@ export const onBoardingTranslation: OnBoardingLocale.OnboardingSteps = {
step3: {
title: 'Premium version!',
description:
'Provides unlimited access to Crazy and \n Extreme packages. Enjoy intriguing questions \n and exciting action.',
'Provides unlimited access to Crazy package. Enjoy intriguing questions \n and exciting action.',
},
}

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

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
export const buttonsTranslation = {
skip: 'जनक',
priceButton: 'जनक/ $4.99',
priceButton: 'जनक/ $1.99',
later: 'जनक',
truth: '-सच-',
random: 'यिक म',

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

@ -14,6 +14,7 @@ export const common: Common = { @@ -14,6 +14,7 @@ export const common: Common = {
helpAlertDesc: 'Ми розглянемо питання і якнайшвидше дамо відповідь.',
writeUsBtn: 'Відправити',
limitTitle: 'Ліміт вичерпано',
limitDesc: 'Ви досягли ліміту питань для пакету "Crazy". Щоб продовжити, потрібна повна версія. Але ти завжди можеш використовувати пакети «До 18» та «Легкий». Вони завжди відкриті для тебе.',
buyAfterBtn: 'До покупок'
limitDesc: 'Ліміт питань для пакету "Crazy" вичерпано. Щоб продовжити, потрібна повна версія. Але ти можеш використовувати пакети «До 18» та «Легкий». Вони завжди відкриті для тебе.',
buyAfterBtn: 'До покупок',
no: 'Назад'
}

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

@ -1,10 +1,10 @@ @@ -1,10 +1,10 @@
import { CustomPack } from '~i18n/interfaces/custom-pack.interface'
export const customPack: CustomPack = {
label: 'Власний пакет',
title: 'Створити власний пакет',
label: 'Мій пакет',
title: 'Створити свій пакет',
description:
'Створіть свій власний пакет з питань та дій. Все залежить від твоєї уяви!',
'Створи свій пакет з питань та дій. Все залежить від твоєї уяви!',
editor: 'Редактор',
placeholder: 'Писати тут...',
addTruth: 'Додати питання',
@ -13,15 +13,15 @@ export const customPack: CustomPack = { @@ -13,15 +13,15 @@ export const customPack: CustomPack = {
viewDares: 'Дії',
alertCreateTitle: 'Чудово! 🎉',
alertCreateDesc: 'Зіграй прямо зараз!',
alertSaveTitle: 'У тебе незбережені зміни',
alertSaveTitle: 'У тебе незбережені зміни.',
alertSaveDesc: 'Зберегти зміни?',
alertSaveNo: 'Ні',
alertSaveYes: 'Так',
alertEmptyTitle: 'Ой! 👀',
alertEmptyTruthDesc:
'Твій список питань порожній. Потрібно мати хоча б 1 питання',
'Твій список питань порожній. Потрібно мати хоча б 1 питання.',
alertEmptyDaresDesc:
'Твій список дій порожній. Потрібно мати хоча б 1 дії',
'Твій список дій порожній. Потрібно мати хоча б 1 дії.',
editorBtn: 'Редактор правд та дій',
play: 'Грати',
}

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

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

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

@ -5,7 +5,7 @@ export const purchases: PurchasesTranslate = { @@ -5,7 +5,7 @@ export const purchases: PurchasesTranslate = {
descSuccess: 'Тепер зіграйте з друзями! Насолоджуйтеся грою 😊',
alertError: 'Упс, щось не так 😢',
descError:
'Виникла помилка обробки вашої покупки. Будь ласка, спробуйте пізніше.',
'Виникла помилка при обробці покупки. Будь ласка, спробуйте пізніше.',
allPackage: 'Відкрити всі пакети',
crazy: 'Відкрити пакет "Божевільний"',
under18: 'Відкрити пакет "До 18"',

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

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

2
src/module/common/components/buttons/button-primary.component.tsx

@ -17,7 +17,7 @@ type ButtonStyleMod = 'filled' | 'outline' | 'danger' @@ -17,7 +17,7 @@ type ButtonStyleMod = 'filled' | 'outline' | 'danger'
interface IButtonPrimaryProps {
mod?: ButtonStyleMod
style?: ViewStyle
style?: ViewStyle | ViewStyle[]
onPress: () => void
isLoading?: boolean

2
src/module/common/hooks/index.ts

@ -1,5 +1,3 @@ @@ -1,5 +1,3 @@
export * from './use-nav.hook'
export * from './use-dispatch.hook'
export * from './use-events-listener.hook'
export * from './use-selector.hook'
export * from './use-form.hook'

4
src/module/common/hooks/use-dispatch.hook.ts

@ -1,4 +0,0 @@ @@ -1,4 +0,0 @@
import { useDispatch } from 'react-redux'
import { AppDispatch } from '../../../store/store'
export const useAppDispatch = () => useDispatch<AppDispatch>()

5
src/module/common/hooks/use-selector.hook.ts

@ -1,5 +0,0 @@ @@ -1,5 +0,0 @@
import { useSelector } from 'react-redux'
import { TypedUseSelectorHook } from 'react-redux'
import { RootState } from '../../../store/store'
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector

1
src/module/common/index.ts

@ -7,3 +7,4 @@ export * from './events' @@ -7,3 +7,4 @@ export * from './events'
export * from './tools'
export * from './widgets'
export * from './svg-icons'
export * from './services';

8
src/module/common/questions-dares-list/questions-dares-list.ts

@ -39,7 +39,7 @@ const under18 = [ @@ -39,7 +39,7 @@ const under18 = [
id: 7,
isDare: false,
en: 'If you could visit any place in the world, where would you go?',
ua: 'Якщо б ти міг(ла) відвідати будь-яке місце у світі, куди б ти поїхав(ла)?',
ua: 'Якщо б ти міг(могла) відвідати будь-яке місце у світі, куди б ти поїхав(ла)?',
},
{
id: 8,
@ -251,8 +251,8 @@ const light = [ @@ -251,8 +251,8 @@ const light = [
{
id: 1,
isDare: false,
en: 'Tell a lie that has benefited you.',
ua: 'Розкажи брехню, яка принесла тобі користь.',
en: 'Tell me about a deception that benefited you.',
ua: 'Розкажи про обман, який приніс тобі користь.',
},
{
id: 2,
@ -572,7 +572,7 @@ const crazy = [ @@ -572,7 +572,7 @@ const crazy = [
{
id: 12,
isDare: false,
en: 'Є людина, яку ти ннавидиш, але вона про це не знає?',
en: 'Є людина, яку ти ненавидиш, але вона про це не знає?',
ua: "Is there a person you hate, but they don't know it?",
},
{

1
src/module/common/services/index.ts

@ -0,0 +1 @@ @@ -0,0 +1 @@
export * from './storage.service';

34
src/module/common/services/storage.service.ts

@ -0,0 +1,34 @@ @@ -0,0 +1,34 @@
import AsyncStorage from '@react-native-async-storage/async-storage'
import { StorageKey } from '../typing'
export class StorageService {
constructor() {
this.init()
}
private init() {}
public async get(key: StorageKey) {
try {
const encode = await AsyncStorage.getItem(key)
if (encode) {
return JSON.parse(encode)
} else {
return null
}
} catch (error) {
console.error('error get from async storage', error)
}
}
public async set(key: StorageKey, data: any) {
try {
const encode = JSON.stringify(data)
await AsyncStorage.setItem(key, encode)
} catch (error) {
console.error('error set to async storage', error)
}
}
}
export const storageService = new StorageService()

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

@ -4,6 +4,8 @@ export enum StorageKey { @@ -4,6 +4,8 @@ export enum StorageKey {
Purchases = 'Purchases',
Products = 'Products',
CustomPackage = 'CustomPackage',
ShuffleCustomPackage = 'ShuffleCustomPackage',
Players = 'Players',
LimitForCrazy = 'limit'
LimitForCrazy = 'limit',
SavedSteps = 'SavedSteps',
}

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

@ -11,13 +11,13 @@ import { @@ -11,13 +11,13 @@ import {
appEvents,
colors,
CustomType,
useAppDispatch,
useNav,
UserRouteKey,
storageService,
} from '~module/common'
import { CustomBlock, EmptyItemsAtom } from '../atoms'
import _ from 'lodash'
import { useSelector } from 'react-redux'
import { useDispatch, useSelector } from 'react-redux'
import {
selectCustomPackage,
selectCustomPackageFromStore,
@ -26,11 +26,10 @@ import { @@ -26,11 +26,10 @@ import {
updateCustomPackage,
updateCustomPackageFromStore,
} from '~store/slices'
import AsyncStorage from '@react-native-async-storage/async-storage'
import { useTranslation } from 'react-i18next'
export const CustomPackageEditorScreen: FC = () => {
const dispatch = useAppDispatch()
const dispatch = useDispatch()
const { t } = useTranslation()
const nav = useNav()
@ -81,12 +80,7 @@ export const CustomPackageEditorScreen: FC = () => { @@ -81,12 +80,7 @@ export const CustomPackageEditorScreen: FC = () => {
const saveCustomPackage = async () => {
try {
const newCustomPackage = JSON.stringify(customPackage)
await AsyncStorage.setItem(
StorageKey.CustomPackage,
newCustomPackage,
)
await storageService.set(StorageKey.CustomPackage, customPackage)
dispatch(updateCustomPackageFromStore(customPackage))
} catch (error) {
@ -180,7 +174,15 @@ export const CustomPackageEditorScreen: FC = () => { @@ -180,7 +174,15 @@ export const CustomPackageEditorScreen: FC = () => {
<View style={[styles.row, { marginTop: 15 }]}>
<ButtonPrimary
styleTxt={styles.txt}
style={styles.btnTxt}
style={[
styles.btnTxt,
{
borderColor:
activeMod === CustomType.Questions
? colors.turquoise
: colors.darkPurple,
},
]}
txtColor={
activeMod === CustomType.Questions
? colors.turquoise
@ -190,7 +192,15 @@ export const CustomPackageEditorScreen: FC = () => { @@ -190,7 +192,15 @@ export const CustomPackageEditorScreen: FC = () => {
{t('customPack.viewTruths')}
</ButtonPrimary>
<ButtonPrimary
style={styles.btnTxt}
style={[
styles.btnTxt,
{
borderColor:
activeMod === CustomType.Dares
? colors.turquoise
: colors.darkPurple,
},
]}
styleTxt={styles.txt}
txtColor={
activeMod === CustomType.Dares
@ -246,7 +256,7 @@ const styles = StyleSheet.create({ @@ -246,7 +256,7 @@ const styles = StyleSheet.create({
btnTxt: {
backgroundColor: null,
flex: 1,
borderWidth: 2,
borderWidth: 1,
borderColor: colors.darkPurple,
},
txt: {

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

@ -20,10 +20,6 @@ export const CustomPackagePreviewScreen: FC = () => { @@ -20,10 +20,6 @@ export const CustomPackagePreviewScreen: FC = () => {
const customPackage = useSelector(selectCustomPackage)
const goToSettings = () => {
nav.navigate(UserRouteKey.Settings)
}
const goToCustomEditor = () => {
nav.navigate(UserRouteKey.CustomEditor)
}
@ -66,13 +62,7 @@ export const CustomPackagePreviewScreen: FC = () => { @@ -66,13 +62,7 @@ export const CustomPackagePreviewScreen: FC = () => {
return (
<ScreenLayout
headerComponent={
<Header
title={t('customPack.label')}
rightIcon="setting"
onPressRight={goToSettings}
/>
}>
headerComponent={<Header title={t('customPack.label')} />}>
<View style={styles.container}>
<ButtonPrimary
style={styles.editorBtn}

10
src/module/game/components/player-name.component.tsx

@ -1,12 +1,14 @@ @@ -1,12 +1,14 @@
import React, { FC } from 'react'
import { StyleSheet } from 'react-native'
import { useSelector } from 'react-redux'
import { Font, Txt } from '~module/common'
import { selectCurrentPlayer } from '~store/slices'
interface IProps {
playerName: string
}
interface IProps {}
export const PlayerName: FC<IProps> = () => {
const playerName = useSelector(selectCurrentPlayer)
export const PlayerName: FC<IProps> = ({ playerName }) => {
return <Txt style={styles.playerName}>{playerName}</Txt>
}

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

@ -1,48 +1,13 @@ @@ -1,48 +1,13 @@
import React, { useEffect } from 'react'
import { useTranslation } from 'react-i18next'
import {
Font,
Icon,
Language,
CustomType,
colors,
useAppDispatch,
useAppSelector,
} from '../../common'
import {
selectStep,
resetSteps,
shuffleCustom,
shuffleItems,
} from '../../../store/slices'
import React from 'react'
import { Font, Icon, colors } from '../../common'
import { Animated, StyleSheet } from 'react-native'
import { useAnimationTruthOrDare } from '../animations'
interface IProps {
items: any[]
isCustom?: CustomType | undefined
item: string
animStyle: any
}
export const TruthOrDareView: React.FC<IProps> = ({ items, isCustom }) => {
const dispatch = useAppDispatch()
const { i18n } = useTranslation()
const currentStep = useAppSelector(selectStep)
const { startAnimation, animStyle } = useAnimationTruthOrDare()
const content = isCustom
? items?.[currentStep]
: items?.[currentStep]?.[i18n.language as Language]
useEffect(() => {
if (currentStep == items.length) {
dispatch(shuffleItems())
dispatch(resetSteps())
isCustom && dispatch(shuffleCustom())
}
startAnimation()
}, [currentStep, items])
export const TruthOrDareView: React.FC<IProps> = ({ item, animStyle }) => {
return (
<Animated.View style={[styles.container, animStyle]}>
<Icon
@ -51,7 +16,7 @@ export const TruthOrDareView: React.FC<IProps> = ({ items, isCustom }) => { @@ -51,7 +16,7 @@ export const TruthOrDareView: React.FC<IProps> = ({ items, isCustom }) => {
color={colors.turquoise}
style={styles.starIcon}
/>
<Animated.Text style={[styles.text]}>{content}</Animated.Text>
<Animated.Text style={[styles.text]}>{item}</Animated.Text>
</Animated.View>
)
}
@ -68,7 +33,7 @@ const styles = StyleSheet.create({ @@ -68,7 +33,7 @@ const styles = StyleSheet.create({
shadowOpacity: 1,
shadowRadius: 4,
elevation: 5,
marginTop: '45%',
marginTop: 88,
},
starIcon: {
marginBottom: 14,

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

@ -1,24 +0,0 @@ @@ -1,24 +0,0 @@
import { selectShuffled, selectShuffledCustom } from '../../../store/slices'
import { CustomType, PackageType, useAppSelector } from '../../common'
interface UseTruthOrDareProps {
isTruth: boolean
customType: CustomType
}
export const getCurrentTruthOrDare = ({
isTruth,
customType,
}: UseTruthOrDareProps) => {
const shuffledGameItems = useAppSelector(selectShuffled)
const shuffledCustomPackage = useAppSelector(selectShuffledCustom)
const dares = shuffledGameItems.filter(dare => dare.isDare)
const questions = shuffledGameItems.filter(question => !question.isDare)
const packageTruthOrDare = isTruth ? questions : dares
const truthOrDareItems = customType
? shuffledCustomPackage[customType]
: packageTruthOrDare
return truthOrDareItems
}

123
src/module/game/helper/get-current-truth-dares.helper.tsx

@ -0,0 +1,123 @@ @@ -0,0 +1,123 @@
import { useEffect } from 'react'
import {
resetSteps,
resetStepsByTruthOrDare,
selectCustomPackage,
selectPackage,
selectShuffleCustomPackage,
selectStep,
shuffleCustomPackage,
shufflePackage,
} from '../../../store/slices'
import {
CustomType,
Language,
PackageType,
StorageKey,
storageService,
} from '../../common'
import { useTranslation } from 'react-i18next'
import { useAnimationTruthOrDare } from '../animations'
import { useDispatch, useSelector } from 'react-redux'
import { RootState } from '~store/store'
import firestore from '@react-native-firebase/firestore'
import _ from 'lodash'
interface UseTruthOrDareProps {
isTruth: boolean
customType: CustomType
packageType: PackageType
}
export const getCurrentTruthOrDare = ({
isTruth,
customType,
packageType,
}: UseTruthOrDareProps) => {
const dispatch = useDispatch()
const { i18n } = useTranslation()
const { stepTruth, stepDare } = useSelector(selectStep)
const customPackageShuffle = useSelector(selectShuffleCustomPackage)
const customPackage = useSelector(selectCustomPackage)
const gameItems = useSelector((state: RootState) =>
selectPackage(state, packageType),
)
const currentStep = isTruth ? stepTruth : stepDare
console.log('customPackageShuffle', customPackageShuffle)
console.log('customPackage', customPackage)
const { animStyle, startAnimation } = useAnimationTruthOrDare()
const getGameItemsByPackage = () => {
if (!packageType) return
const dares = gameItems.filter(dare => dare.isDare)
const questions = gameItems.filter(question => !question.isDare)
return isTruth ? questions : dares
}
const getGameItemsByCustomPackage = () => {
if (_.isEmpty(customPackageShuffle.questions))
return customPackage[customType]
return customPackageShuffle[customType]
}
const getCurrentItem = () => {
if (customType) {
return customTruthsOrDares?.[currentStep]
}
return packageTruthsOrDares?.[currentStep]?.[i18n.language as Language]
}
const customTruthsOrDares = getGameItemsByCustomPackage()
const packageTruthsOrDares = getGameItemsByPackage()
const currentItem = getCurrentItem()
const shuffleAndSavePackage = async () => {
const shufflePackages = _.shuffle(packageTruthsOrDares)
await firestore()
.collection('content')
.doc(packageType)
.update(shufflePackages)
dispatch(resetStepsByTruthOrDare(isTruth))
dispatch(shufflePackage(packageType))
}
const shuffleAndSaveCustomPackage = async () => {
if (_.isEmpty(customTruthsOrDares)) return
const shuffleCustom = _.shuffle(customTruthsOrDares)
console.log('newShuffle', shuffleCustom)
dispatch(shuffleCustomPackage({ customType, shuffleCustom }))
dispatch(resetStepsByTruthOrDare(isTruth))
const savedShuffleCustom = await storageService.get(
StorageKey.ShuffleCustomPackage,
)
const newShuffled = {
...savedShuffleCustom,
[customType]: shuffleCustom,
}
await storageService.set(StorageKey.ShuffleCustomPackage, newShuffled)
}
useEffect(() => {
if (packageType && currentStep === packageTruthsOrDares.length) {
shuffleAndSavePackage()
}
if (customType && currentStep === customTruthsOrDares.length) {
shuffleAndSaveCustomPackage()
}
startAnimation()
}, [currentStep])
return { currentItem, animStyle }
}

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

@ -9,20 +9,16 @@ import { @@ -9,20 +9,16 @@ import {
ScreenLayout,
CustomType,
useNav,
useAppDispatch,
PackageType,
StorageKey,
storageService,
} from '../../common'
import { useTranslation } from 'react-i18next'
import { useIsFocused, useRoute } from '@react-navigation/native'
import { useAnimationButton } from '../animations'
import {
shuffleItems,
shuffleCustom,
resetSteps,
selectCurrentPlayer,
} from '~store/slices'
import { resetSteps, setStep } from '~store/slices'
import { PlayerName } from '../components/player-name.component'
import { useSelector } from 'react-redux'
import { useDispatch } from 'react-redux'
import { packageNameConfig } from '../config'
interface IRouteParams {
@ -33,21 +29,26 @@ interface IRouteParams { @@ -33,21 +29,26 @@ interface IRouteParams {
export const GameScreen: FC = () => {
const { t, i18n } = useTranslation()
const nav = useNav()
const dispatch = useAppDispatch()
const { params } = useRoute()
const dispatch = useDispatch()
const { packageType, isCustom }: IRouteParams = params
const isFocused = useIsFocused()
const { animStyle, startAnimationsBorder } = useAnimationButton()
const currentPlayer = useSelector(selectCurrentPlayer)
useEffect(() => {
refreshList()
setStepsByPackage()
}, [])
const refreshList = () => {
!isCustom && dispatch(shuffleItems(packageType))
isCustom && dispatch(shuffleCustom())
dispatch(resetSteps())
const setStepsByPackage = async () => {
const lastSteps = await storageService.get(StorageKey.SavedSteps)
const typePackage = packageType ? packageType : 'custom'
const stepsByPackage = lastSteps?.[typePackage]
if (!stepsByPackage) return dispatch(resetSteps())
dispatch(setStep(stepsByPackage))
}
const randomGame = () => {
@ -60,7 +61,6 @@ export const GameScreen: FC = () => { @@ -60,7 +61,6 @@ export const GameScreen: FC = () => {
isTruth: isTruthRandom,
packageType,
customType: isCustom ? customRandom : null,
currentPlayer,
})
}
@ -69,7 +69,6 @@ export const GameScreen: FC = () => { @@ -69,7 +69,6 @@ export const GameScreen: FC = () => {
isTruth: true,
packageType,
customType: isCustom && CustomType.Questions,
currentPlayer,
})
}
@ -77,7 +76,6 @@ export const GameScreen: FC = () => { @@ -77,7 +76,6 @@ export const GameScreen: FC = () => {
nav.navigate(UserRouteKey.TruthOrDare, {
packageType,
customType: isCustom && CustomType.Dares,
currentPlayer,
})
}
@ -85,11 +83,16 @@ export const GameScreen: FC = () => { @@ -85,11 +83,16 @@ export const GameScreen: FC = () => {
<ScreenLayout
headerComponent={
<Header
title={packageNameConfig[packageType][i18n.language]}
title={
packageNameConfig?.[packageType]?.[i18n.language] ||
t('customPack.label')
}
rightIcon="players"
onPressRight={() => nav.navigate(UserRouteKey.Players)}
gamer
/>
}>
<PlayerName playerName={currentPlayer} />
<PlayerName />
<View style={styles.wrapButtons}>
<ButtonPrimary
width={200}
@ -127,11 +130,6 @@ export const GameScreen: FC = () => { @@ -127,11 +130,6 @@ export const GameScreen: FC = () => {
}
const styles = StyleSheet.create({
playerName: {
fontFamily: Font.Roboto700,
textAlign: 'center',
marginBottom: 122,
},
wrapButtons: {
alignItems: 'center',
justifyContent: 'center',
@ -156,5 +154,4 @@ const styles = StyleSheet.create({ @@ -156,5 +154,4 @@ const styles = StyleSheet.create({
fontSize: 36,
lineHeight: 46,
},
txt: {},
})

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

@ -11,18 +11,17 @@ import { @@ -11,18 +11,17 @@ import {
ButtonWithIcon,
appEvents,
StorageKey,
useAppDispatch,
storageService,
} from '../../common'
import { useTranslation } from 'react-i18next'
import { PlayerField } from '../components'
import AsyncStorage from '@react-native-async-storage/async-storage'
import { selectPlayers, setPlayers } from '~store/slices'
import { useSelector } from 'react-redux'
import { useDispatch, useSelector } from 'react-redux'
export const PlayersScreen: FC = () => {
const { t } = useTranslation()
const nav = useNav()
const dispatch = useAppDispatch()
const dispatch = useDispatch()
const players = useSelector(selectPlayers)
const onAddField = () => {
@ -58,7 +57,7 @@ export const PlayersScreen: FC = () => { @@ -58,7 +57,7 @@ export const PlayersScreen: FC = () => {
})
}
await AsyncStorage.setItem(StorageKey.Players, JSON.stringify(players))
await storageService.set(StorageKey.Players, players)
nav.navigate(UserRouteKey.Packages)
}

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

@ -7,65 +7,82 @@ import { @@ -7,65 +7,82 @@ import {
UserRouteKey,
ScreenLayout,
CustomType,
useAppDispatch,
useNav,
PackageType,
StorageKey,
appEvents,
storageService,
} from '../../common'
import {
nextStep,
onNextPlayer,
resetSteps,
shuffleCustom,
shuffleItems,
} from '../../../store/slices'
import { nextStep, onNextPlayer, selectStep } from '../../../store/slices'
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'
import { useDispatch, useSelector } from 'react-redux'
interface IRouteParams {
packageType?: PackageType
isTruth?: boolean
customType?: CustomType
currentPlayer?: string
isTruth?: boolean
}
export const TruthOrDareScreen: React.FC = () => {
const nav = useNav()
const { t, i18n } = useTranslation()
const dispatch = useAppDispatch()
const dispatch = useDispatch()
const { params } = useRoute()
const { packageType, isTruth, customType, currentPlayer }: IRouteParams =
params
const currentStep = useSelector(selectStep)
const { animRotate, animScale } = useAnimationIconsButton()
const { packageType, isTruth, customType }: IRouteParams = params
const truthOrDareItems = getCurrentTruthOrDare({
const { currentItem, animStyle } = getCurrentTruthOrDare({
isTruth,
customType,
packageType,
})
const { animRotate, animScale } = useAnimationIconsButton()
const onNext = () => {
const onNextTruthOrDare = async () => {
nav.navigate(UserRouteKey.Game, { packageType, isCustom: customType })
dispatch(onNextPlayer())
dispatch(nextStep(isTruth))
await saveLastStep()
}
const getLimitForCrazy = async () => {
const limit = await AsyncStorage.getItem(StorageKey.LimitForCrazy)
const saveLastStep = async () => {
const savedStepsAllPackages = await storageService.get(
StorageKey.SavedSteps,
)
const key = isTruth ? 'stepTruth' : 'stepDare'
const updateSteps = { ...currentStep, [key]: currentStep[key] + 1 }
if (!limit) return AsyncStorage.setItem(StorageKey.LimitForCrazy, '1')
const stepsByCurrentPackage = {
[packageType || 'custom']: updateSteps,
}
const saveStepsByPackage = {
...savedStepsAllPackages,
...stepsByCurrentPackage,
}
await storageService.set(StorageKey.SavedSteps, saveStepsByPackage)
}
const getLimitForCrazy = async () => {
const limit = await storageService.get(StorageKey.LimitForCrazy)
const currentLimit = Number(JSON.parse(limit))
if (!limit) return await storageService.set(StorageKey.LimitForCrazy, 1)
if (currentLimit >= 5) {
if (limit >= 5) {
return appEvents.emit('confirm', {
title: t('common.limitTitle'),
subtitle: t('common.limitDesc'),
confirmBtnText: t('common.buyAfterBtn'),
cancelBtnText: t('common.no'),
isRedButton: true,
buttons: [
{ onPress: () => nav.navigate(UserRouteKey.Packages) },
@ -76,18 +93,15 @@ export const TruthOrDareScreen: React.FC = () => { @@ -76,18 +93,15 @@ export const TruthOrDareScreen: React.FC = () => {
})
}
AsyncStorage.setItem(StorageKey.LimitForCrazy, `${currentLimit + 1}`)
await storageService.set(StorageKey.LimitForCrazy, limit + 1)
}
useEffect(() => {
dispatch(nextStep())
getLimitForCrazy()
if (packageType === PackageType.Crazy) getLimitForCrazy()
}, [])
const refreshList = () => {
!customType && dispatch(shuffleItems())
customType && dispatch(shuffleCustom())
dispatch(resetSteps())
const onNextSameItem = () => {
dispatch(nextStep(isTruth))
}
return (
@ -95,23 +109,23 @@ export const TruthOrDareScreen: React.FC = () => { @@ -95,23 +109,23 @@ export const TruthOrDareScreen: React.FC = () => {
headerComponent={
<Header
gamer
onPressLeft={() => onNext()}
title={packageNameConfig[packageType][i18n.language]}
onPressLeft={onNextTruthOrDare}
title={
packageNameConfig?.[packageType]?.[i18n.language] ||
t('customPack.label')
}
/>
}>
<View style={{ flex: 1 }}>
<PlayerName playerName={currentPlayer} />
<PlayerName />
<TruthOrDareView
items={truthOrDareItems}
isCustom={customType}
/>
<TruthOrDareView item={currentItem} animStyle={animStyle} />
<View style={styles.buttons}>
<ButtonWithIcon
styleBtn={{ width: 101 }}
iconName="union"
onPress={refreshList}
onPress={onNextSameItem}
animation={animRotate.func}
animStyle={animRotate.style}
/>
@ -119,7 +133,7 @@ export const TruthOrDareScreen: React.FC = () => { @@ -119,7 +133,7 @@ export const TruthOrDareScreen: React.FC = () => {
<ButtonWithIcon
styleBtn={{ width: 101 }}
iconName="play"
onPress={onNext}
onPress={onNextTruthOrDare}
animation={animScale.func}
animStyle={animScale.style}
/>

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

@ -72,7 +72,6 @@ const styles = StyleSheet.create({ @@ -72,7 +72,6 @@ const styles = StyleSheet.create({
marginBottom: 5,
},
description: {
marginBottom: 5,
color: colors.secondaryText,
fontSize: 16,
lineHeight: 24,

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

@ -15,7 +15,7 @@ export const PackagesListScreen: FC = () => { @@ -15,7 +15,7 @@ export const PackagesListScreen: FC = () => {
needScroll
headerComponent={
<Header
leftIcon="settings"
leftIcon="players"
rightIcon="setting"
onPressLeft={() => nav.navigate(UserRouteKey.Players)}
onPressRight={() => nav.navigate(UserRouteKey.Settings)}

5
src/module/root/atoms/on-boarding-button.component.tsx

@ -1,8 +1,7 @@ @@ -1,8 +1,7 @@
import AsyncStorage from '@react-native-async-storage/async-storage'
import React, { FC } from 'react'
import { useTranslation } from 'react-i18next'
import { StyleSheet, TouchableOpacity, View } from 'react-native'
import { ButtonPrimary, StorageKey, Txt, NavGroup } from '../../common'
import { ButtonPrimary, StorageKey, Txt, NavGroup, storageService } from '../../common'
import { useDispatch } from 'react-redux'
import { setNavGroup } from '~store/slices'
@ -16,7 +15,7 @@ export const OnBoardingBottom: FC<IProps> = ({ isLastBlock, onPressSkip }) => { @@ -16,7 +15,7 @@ export const OnBoardingBottom: FC<IProps> = ({ isLastBlock, onPressSkip }) => {
const dispatch = useDispatch()
const onBoardFinish = async () => {
await AsyncStorage.setItem(StorageKey.FinishOnBoarding, 'true')
await storageService.set(StorageKey.FinishOnBoarding, true)
dispatch(setNavGroup(NavGroup.User))
}

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

@ -1,4 +1,3 @@ @@ -1,4 +1,3 @@
import AsyncStorage from '@react-native-async-storage/async-storage'
import React, { FC } from 'react'
import { useTranslation } from 'react-i18next'
import { StyleSheet, View } from 'react-native'
@ -13,6 +12,7 @@ import { @@ -13,6 +12,7 @@ import {
UaSvg,
Font,
GuestRouteKey,
storageService,
} from '../../common'
import { LanguageItem } from '../components'
@ -35,7 +35,7 @@ export const LanguageSelectScreen: FC = () => { @@ -35,7 +35,7 @@ export const LanguageSelectScreen: FC = () => {
const onSelectLanguage = async (language: Language) => {
nav.navigate(GuestRouteKey.Onboarding)
i18n.changeLanguage(language)
await AsyncStorage.setItem(StorageKey.Language, language)
await storageService.set(StorageKey.Language, language)
}
return (

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

@ -3,13 +3,11 @@ import React, { FC, useEffect } from 'react' @@ -3,13 +3,11 @@ import React, { FC, useEffect } from 'react'
import {
ScreenLayout,
useNav,
useAppDispatch,
StorageKey,
NavGroup,
GuestRouteKey,
UserRouteKey,
storageService,
} from '../../common'
import AsyncStorage from '@react-native-async-storage/async-storage'
import { useTranslation } from 'react-i18next'
import { purchasesService } from '../../settings'
import {
@ -18,18 +16,19 @@ import { @@ -18,18 +16,19 @@ import {
setNavGroup,
getPlayersAsync,
} from '../../../store/slices'
import { useDispatch } from 'react-redux'
export const LoadingScreen: FC = () => {
const { i18n } = useTranslation()
const nav = useNav()
const dispatch = useAppDispatch()
const dispatch = useDispatch()
const getLanguage = async () => {
return await AsyncStorage.getItem(StorageKey.Language)
return await storageService.get(StorageKey.Language)
}
const getOnboardEnd = async () => {
return await AsyncStorage.getItem(StorageKey.FinishOnBoarding)
return await storageService.get(StorageKey.FinishOnBoarding)
}
const init = async () => {

4
src/module/settings/screens/settings.screen.tsx

@ -12,9 +12,9 @@ import { @@ -12,9 +12,9 @@ import {
StorageKey,
UaSvg,
useNav,
storageService,
} from '../../common'
import { SheetManager } from 'react-native-actions-sheet'
import AsyncStorage from '@react-native-async-storage/async-storage'
export const SettingsScreen: FC = () => {
const { t, i18n } = useTranslation()
@ -47,7 +47,7 @@ export const SettingsScreen: FC = () => { @@ -47,7 +47,7 @@ export const SettingsScreen: FC = () => {
const onChangeLanguage = async (language: Language) => {
SheetManager.hide('bottom-sheet')
await AsyncStorage.setItem(StorageKey.Language, language)
await storageService.set(StorageKey.Language, language)
return i18n.changeLanguage(language)
}

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

@ -6,9 +6,8 @@ import { @@ -6,9 +6,8 @@ import {
purchaseUpdatedListener,
finishTransaction,
} from 'react-native-iap'
import { ProductsEnum, StorageKey } from '../../common'
import { ProductsEnum, StorageKey, storageService } from '../../common'
import { purchasesConfig } from '../config'
import AsyncStorage from '@react-native-async-storage/async-storage'
const ID_PRODUCTS = [ProductsEnum.Crazy]
@ -70,16 +69,15 @@ export class PurchasesService { @@ -70,16 +69,15 @@ export class PurchasesService {
private async savePurchase(productId: ProductsEnum) {
const newProductsId = [...this.purchasedProducts, productId]
const newProducts = JSON.stringify(newProductsId)
this.purchasedProducts = newProductsId
await AsyncStorage.setItem(StorageKey.Purchases, newProducts)
await storageService.set(StorageKey.Purchases, newProductsId)
}
private async getPurchasedProducts() {
const response = await AsyncStorage.getItem(StorageKey.Purchases)
this.purchasedProducts = response ? JSON.parse(response) : []
const response = await storageService.get(StorageKey.Purchases)
this.purchasedProducts = response ? response : []
}
private purchaseListener() {

40
src/store/slices/current-step.slice.ts

@ -1,28 +1,54 @@ @@ -1,28 +1,54 @@
import { createSlice } from '@reduxjs/toolkit'
import { PayloadAction, createSlice } from '@reduxjs/toolkit'
import { RootState } from '../store'
interface IStep {
stepTruth: number
stepDare: number
}
interface CurrentStepState {
step: number
step: IStep
}
const initialState: CurrentStepState = {
step: 0,
step: {
stepDare: 0,
stepTruth: 0,
},
}
export const CurrentStepSlice = createSlice({
name: 'currentStep',
initialState,
reducers: {
nextStep: state => {
state.step = state.step + 1
nextStep: (state, action: PayloadAction<boolean>) => {
const isTruthStep = action.payload
isTruthStep
? (state.step.stepTruth = state.step.stepTruth + 1)
: (state.step.stepDare = state.step.stepDare + 1)
},
setStep: (state, action: PayloadAction<IStep>) => {
state.step = action.payload
},
resetStepsByTruthOrDare: (state, action: PayloadAction<boolean>) => {
const isResetForTruth = action.payload
isResetForTruth
? (state.step.stepTruth = 0)
: (state.step.stepDare = 0)
},
resetSteps: state => {
state.step = 0
state.step = {
stepDare: 0,
stepTruth: 0,
}
},
},
})
export const { nextStep, resetSteps } = CurrentStepSlice.actions
export const { nextStep, resetStepsByTruthOrDare, setStep, resetSteps } =
CurrentStepSlice.actions
export const selectStep = (state: RootState) => state.currentStep.step

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

@ -1,8 +1,7 @@ @@ -1,8 +1,7 @@
import { PayloadAction, createAsyncThunk, createSlice } from '@reduxjs/toolkit'
import { StorageKey, CustomType } from '../../module/common'
import { StorageKey, CustomType, storageService } from '../../module/common'
import { RootState } from '../store'
import _ from 'lodash'
import AsyncStorage from '@react-native-async-storage/async-storage'
interface ICustomPackage {
[CustomType.Questions]: string[]
@ -17,27 +16,30 @@ const defaultCustomPackage: ICustomPackage = { @@ -17,27 +16,30 @@ const defaultCustomPackage: ICustomPackage = {
export interface CustomPackageState {
customPackageFromStore: ICustomPackage
customPackage: ICustomPackage
shuffleCustomPackage: ICustomPackage
shuffled: ICustomPackage
loaded: boolean
hasError: boolean
shuffleCustom: ICustomPackage
}
const initialState: CustomPackageState = {
customPackage: defaultCustomPackage,
shuffleCustomPackage: defaultCustomPackage,
customPackageFromStore: defaultCustomPackage,
shuffled: defaultCustomPackage,
loaded: false,
hasError: false,
shuffleCustom: defaultCustomPackage,
}
export const getCustomPackage = createAsyncThunk(
'get-custom-package',
async () => {
const response = await AsyncStorage.getItem(StorageKey.CustomPackage)
const customPackageFromStore = await storageService.get(
StorageKey.CustomPackage,
)
return response ? JSON.parse(response) : defaultCustomPackage
const shuffleCustom = await storageService.get(
StorageKey.ShuffleCustomPackage,
)
const customPackage = customPackageFromStore || defaultCustomPackage
const customPackageShuffle = shuffleCustom || customPackage
return [customPackage, customPackageShuffle]
},
)
@ -45,14 +47,13 @@ export const customPackageSlice = createSlice({ @@ -45,14 +47,13 @@ export const customPackageSlice = createSlice({
name: 'customPackage',
initialState,
reducers: {
shuffleCustom: state => {
const shuffleTruths = _.shuffle(state.customPackage.questions)
const shuffleDares = _.shuffle(state.customPackage.dares)
shuffleCustomPackage: (state, action: PayloadAction<any>) => {
const shuffleItems = action.payload.shuffleCustom
const customType = action.payload.customType as CustomType
state.shuffleCustomPackage = {
dares: shuffleDares,
questions: shuffleTruths,
}
console.log('redux', shuffleItems, customType)
state.shuffleCustom[customType] = shuffleItems
},
setQuestions: (state, action: PayloadAction<string[]>) => {
const updateCustomPackage = {
@ -79,19 +80,11 @@ export const customPackageSlice = createSlice({ @@ -79,19 +80,11 @@ export const customPackageSlice = createSlice({
},
},
extraReducers(builder) {
builder
.addCase(getCustomPackage.fulfilled, (state, action) => {
state.customPackage = action.payload
state.customPackageFromStore = action.payload
state.hasError = false
state.loaded = true
})
.addCase(getCustomPackage.pending, state => {
state.loaded = false
})
.addCase(getCustomPackage.rejected, state => {
state.hasError = true
})
builder.addCase(getCustomPackage.fulfilled, (state, action) => {
state.customPackage = action.payload[0]
state.customPackageFromStore = action.payload[0]
state.shuffleCustom = action.payload[1]
})
},
})
@ -100,14 +93,14 @@ export const { @@ -100,14 +93,14 @@ export const {
setDares,
updateCustomPackageFromStore,
updateCustomPackage,
shuffleCustom,
shuffleCustomPackage,
} = customPackageSlice.actions
export const selectCustomPackage = (state: RootState) =>
state.customPackage.customPackage
export const selectShuffleCustomPackage = (state: RootState) =>
state.customPackage.shuffleCustom
export const selectCustomPackageFromStore = (state: RootState) =>
state.customPackage.customPackageFromStore
export const selectShuffledCustom = (state: RootState) =>
state.customPackage.shuffleCustomPackage
export default customPackageSlice.reducer

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

@ -8,7 +8,6 @@ export interface GameItemsState { @@ -8,7 +8,6 @@ export interface GameItemsState {
[PackageType.Under18]: GameItem[]
[PackageType.Light]: GameItem[]
[PackageType.Crazy]: GameItem[]
shuffled: GameItem[]
loaded: boolean
hasError: boolean
}
@ -17,7 +16,6 @@ const initialState: GameItemsState = { @@ -17,7 +16,6 @@ const initialState: GameItemsState = {
under18: [],
light: [],
crazy: [],
shuffled: [],
loaded: false,
hasError: false,
}
@ -25,6 +23,7 @@ const initialState: GameItemsState = { @@ -25,6 +23,7 @@ const initialState: GameItemsState = {
export const getGameItemsFromFirestore = createAsyncThunk(
'game-items/get-from-firestore',
async () => {
// await firestore().collection('content').doc('light').set(data)
const jsonResponse = await firestore().collection('content').get()
const data = jsonResponse.docs.map(it => it.data())
@ -42,16 +41,18 @@ export const gameItemsSlice = createSlice({ @@ -42,16 +41,18 @@ export const gameItemsSlice = createSlice({
name: 'gameItems',
initialState,
reducers: {
shuffleItems: (state, action: PayloadAction<PackageType>) => {
state.shuffled = _.shuffle(state[action.payload])
shufflePackage: (state, action: PayloadAction<PackageType>) => {
const packageType = action.payload
state[packageType] = _.shuffle(state[packageType])
},
},
extraReducers(builder) {
builder
.addCase(getGameItemsFromFirestore.fulfilled, (state, action) => {
state.under18 = action.payload[PackageType.Under18]
state.light = action.payload[PackageType.Light]
state.crazy = action.payload[PackageType.Crazy]
const allPackages = action.payload
state.under18 = allPackages[PackageType.Under18]
state.light = allPackages[PackageType.Light]
state.crazy = allPackages[PackageType.Crazy]
state.hasError = false
state.loaded = true
})
@ -64,8 +65,9 @@ export const gameItemsSlice = createSlice({ @@ -64,8 +65,9 @@ export const gameItemsSlice = createSlice({
},
})
export const { shuffleItems } = gameItemsSlice.actions
export const { shufflePackage } = gameItemsSlice.actions
export const selectShuffled = (state: RootState) => state.gameItems.shuffled
export const selectPackage = (state: RootState, packageType: PackageType) =>
state.gameItems[packageType]
export default gameItemsSlice.reducer

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

@ -1,8 +1,7 @@ @@ -1,8 +1,7 @@
import { PayloadAction, createAsyncThunk, createSlice } from '@reduxjs/toolkit'
import { StorageKey } from '../../module/common'
import { StorageKey, storageService } from '../../module/common'
import { RootState } from '../store'
import _ from 'lodash'
import AsyncStorage from '@react-native-async-storage/async-storage'
export interface PlayersState {
players: string[]
@ -21,9 +20,9 @@ const initialState: PlayersState = { @@ -21,9 +20,9 @@ const initialState: PlayersState = {
}
export const getPlayersAsync = createAsyncThunk('get-players', async () => {
const savedPlayers = await AsyncStorage.getItem(StorageKey.Players)
const savedPlayers = await storageService.get(StorageKey.Players)
return savedPlayers ? JSON.parse(savedPlayers) : ['']
return savedPlayers ? savedPlayers : ['']
})
export const playersSlice = createSlice({

Loading…
Cancel
Save