diff --git a/packages/store-sdk/src/index.ts b/packages/store-sdk/src/index.ts index f5dafc0e0d..531e82e925 100644 --- a/packages/store-sdk/src/index.ts +++ b/packages/store-sdk/src/index.ts @@ -15,3 +15,15 @@ export type { InitialState as UIInitialState, } from './ui/Provider' export { useGlobalUIState } from './ui/useGlobalUIState' + +// Session +export { + Provider as SessionProvider, + Context as SessionContext, +} from './session/Provider' +export type { + Actions as SessionActions, + Effects as SessionEffects, + InitialState as SessionInitialState, +} from './ui/Provider' +export { useSession } from './session/useSession' diff --git a/packages/store-sdk/src/session/Provider.tsx b/packages/store-sdk/src/session/Provider.tsx new file mode 100644 index 0000000000..23e7de9d1e --- /dev/null +++ b/packages/store-sdk/src/session/Provider.tsx @@ -0,0 +1,169 @@ +import React, { createContext, useMemo, useReducer } from 'react' +import type { FC, Dispatch } from 'react' + +interface Currency { + code: string // USD + symbol: string // $ +} + +interface User { + id: string // user id +} + +interface BaseState { + locale: string // en-US + currency: Currency + country: string // BRA + channel: string | null + region: string | null + priceTable: string | null + postalCode: string | null + user: User | null +} + +type State = Record & BaseState + +interface BaseContextValue extends BaseState { + setLocale: (locale: string) => void + setCurrency: (currency: Currency) => void + setCountry: (country: string) => void + setChannel: (channel: string | null) => void + setRegion: (region: string | null) => void + setPriceTable: (table: string | null) => void + setPostalCode: (postalCode: string | null) => void + setUser: (user: User) => void +} + +export type ContextValue = Record & BaseContextValue + +type Action = + | { + type: 'SET_LOCALE' + data: string + } + | { + type: 'SET_CURRENCY' + data: Currency + } + | { + type: 'SET_COUNTRY' + data: string + } + | { + type: 'SET_CHANNEL' + data: string | null + } + | { + type: 'SET_REGION' + data: string | null + } + | { + type: 'SET_PRICE_TABLE' + data: string | null + } + | { + type: 'SET_POSTAL_CODE' + data: string | null + } + | { + type: 'SET_USER' + data: User | null + } + | { + type: string + data?: any + } + +export const Context = createContext(undefined) +Context.displayName = 'StoreSessionContext' + +export type Actions = Record State> + +export type Effects = ( + dispatch: Dispatch +) => Omit + +const baseInitialState: State = { + currency: { + code: 'USD', + symbol: '$', + }, + country: 'USA', + locale: 'en', + postalCode: null, + priceTable: null, + channel: null, + region: null, + user: null, +} + +const reducer = (actions: Actions) => { + const allActions: Actions = { + SET_LOCALE: (state, locale) => ({ ...state, locale }), + SET_CURRENCY: (state, currency) => ({ ...state, currency }), + SET_COUNTRY: (state, country) => ({ ...state, country }), + SET_CHANNEL: (state, channel) => ({ ...state, channel }), + SET_REGION: (state, region) => ({ ...state, region }), + SET_PRICE_TABLE: (state, table) => ({ ...state, table }), + SET_POSTAL_CODE: (state, postalCode) => ({ ...state, postalCode }), + SET_USER: (state, user) => ({ ...state, user }), + ...actions, + } + + return (state: State, { type, data }: Action) => { + const maybeAction = allActions[type] + + if (typeof maybeAction === 'function') { + return maybeAction(state, data) + } + + throw new Error('Unknown Session state') + } +} + +export type InitialState = Record + +interface Props { + actions?: Actions + effects?: Effects + initialState?: InitialState +} + +const defaultEffects: Effects = () => ({}) + +export const Provider: FC = ({ + children, + actions = {}, + effects = defaultEffects, + initialState = {}, +}) => { + const [state, dispatch] = useReducer(reducer(actions), { + ...baseInitialState, + ...initialState, + }) + + const value = useMemo( + () => ({ + ...state, + ...effects(dispatch), + setLocale: (locale: string) => + dispatch({ type: 'SET_LOCALE', data: locale }), + setCurrency: (currency: Currency) => + dispatch({ type: 'SET_CURRENCY', data: currency }), + setCountry: (country: string) => + dispatch({ type: 'SET_COUNTRY', data: country }), + setChannel: (channel: string | null) => + dispatch({ type: 'SET_CHANNEL', data: channel }), + setRegion: (region: string | null) => + dispatch({ type: 'SET_REGION', data: region }), + setPriceTable: (table: string | null) => + dispatch({ type: 'SET_PRICE_TABLE', data: table }), + setPostalCode: (postalCode: string | null) => + dispatch({ type: 'SET_POSTAL_CODE', data: postalCode }), + setUser: (user: User) => dispatch({ type: 'SET_USER', data: user }), + }), + [effects, state] + ) + + return {children} +} diff --git a/packages/store-sdk/src/session/useSession.ts b/packages/store-sdk/src/session/useSession.ts new file mode 100644 index 0000000000..c1efbbfd34 --- /dev/null +++ b/packages/store-sdk/src/session/useSession.ts @@ -0,0 +1,4 @@ +import { Context } from './Provider' +import { useContext } from '../utils/useContext' + +export const useSession = () => useContext(Context) diff --git a/yarn.lock b/yarn.lock index 6fe2f5c5de..af65ff4d72 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6609,7 +6609,7 @@ resolved "https://registry.yarnpkg.com/@types/yoga-layout/-/yoga-layout-1.9.2.tgz#efaf9e991a7390dc081a0b679185979a83a9639a" integrity sha512-S9q47ByT2pPvD65IvrWp7qppVMpk9WGMbVq9wbWZOHg6tnXSD4vyhao6nOSBwwfDdV2p3Kx9evA9vI+XWTfDvw== -"@typescript-eslint/eslint-plugin@^2.10.0", "@typescript-eslint/eslint-plugin@^2.12.0", "@typescript-eslint/eslint-plugin@^4", "@typescript-eslint/eslint-plugin@^4.15.2", "@typescript-eslint/eslint-plugin@^4.18.0": +"@typescript-eslint/eslint-plugin@^2.10.0", "@typescript-eslint/eslint-plugin@^2.12.0", "@typescript-eslint/eslint-plugin@^4", "@typescript-eslint/eslint-plugin@^4.18.0", "@typescript-eslint/eslint-plugin@^4.28.1": version "4.29.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.29.0.tgz#b866c9cd193bfaba5e89bade0015629ebeb27996" integrity sha512-eiREtqWRZ8aVJcNru7cT/AMVnYd9a2UHsfZT8MR1dW3UUEg6jDv9EQ9Cq4CUPZesyQ58YUpoAADGv71jY8RwgA== @@ -6658,14 +6658,14 @@ eslint-scope "^5.0.0" eslint-utils "^2.0.0" -"@typescript-eslint/parser@^2.10.0", "@typescript-eslint/parser@^2.12.0", "@typescript-eslint/parser@^4", "@typescript-eslint/parser@^4.15.2", "@typescript-eslint/parser@^4.18.0": +"@typescript-eslint/parser@^2.10.0", "@typescript-eslint/parser@^2.12.0", "@typescript-eslint/parser@^4", "@typescript-eslint/parser@^4.18.0", "@typescript-eslint/parser@^4.28.1": version "4.29.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.29.0.tgz#e5367ca3c63636bb5d8e0748fcbab7a4f4a04289" integrity sha512-+92YRNHFdXgq+GhWQPT2bmjX09X7EH36JfgN2/4wmhtwV/HPxozpCNst8jrWcngLtEVd/4zAwA6BKojAlf+YqA== dependencies: - "@typescript-eslint/scope-manager" "4.28.5" - "@typescript-eslint/types" "4.28.5" - "@typescript-eslint/typescript-estree" "4.28.5" + "@typescript-eslint/scope-manager" "4.29.0" + "@typescript-eslint/types" "4.29.0" + "@typescript-eslint/typescript-estree" "4.29.0" debug "^4.3.1" "@typescript-eslint/scope-manager@4.19.0": @@ -6684,6 +6684,14 @@ "@typescript-eslint/types" "4.22.0" "@typescript-eslint/visitor-keys" "4.22.0" +"@typescript-eslint/scope-manager@4.28.5": + version "4.28.5" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.28.5.tgz#3a1b70c50c1535ac33322786ea99ebe403d3b923" + integrity sha512-PHLq6n9nTMrLYcVcIZ7v0VY1X7dK309NM8ya9oL/yG8syFINIMHxyr2GzGoBYUdv3NUfCOqtuqps0ZmcgnZTfQ== + dependencies: + "@typescript-eslint/types" "4.28.5" + "@typescript-eslint/visitor-keys" "4.28.5" + "@typescript-eslint/scope-manager@4.29.0": version "4.29.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.29.0.tgz#cf5474f87321bedf416ef65839b693bddd838599" @@ -6702,6 +6710,11 @@ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.22.0.tgz#0ca6fde5b68daf6dba133f30959cc0688c8dd0b6" integrity sha512-sW/BiXmmyMqDPO2kpOhSy2Py5w6KvRRsKZnV0c4+0nr4GIcedJwXAq+RHNK4lLVEZAJYFltnnk1tJSlbeS9lYA== +"@typescript-eslint/types@4.28.5": + version "4.28.5" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.28.5.tgz#d33edf8e429f0c0930a7c3d44e9b010354c422e9" + integrity sha512-MruOu4ZaDOLOhw4f/6iudyks/obuvvZUAHBDSW80Trnc5+ovmViLT2ZMDXhUV66ozcl6z0LJfKs1Usldgi/WCA== + "@typescript-eslint/types@4.29.0": version "4.29.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.29.0.tgz#c8f1a1e4441ea4aca9b3109241adbc145f7f8a4e" @@ -6733,6 +6746,19 @@ semver "^7.3.2" tsutils "^3.17.1" +"@typescript-eslint/typescript-estree@4.28.5": + version "4.28.5" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.28.5.tgz#4906d343de693cf3d8dcc301383ed638e0441cd1" + integrity sha512-FzJUKsBX8poCCdve7iV7ShirP8V+ys2t1fvamVeD1rWpiAnIm550a+BX/fmTHrjEpQJ7ZAn+Z7ZZwJjytk9rZw== + dependencies: + "@typescript-eslint/types" "4.28.5" + "@typescript-eslint/visitor-keys" "4.28.5" + debug "^4.3.1" + globby "^11.0.3" + is-glob "^4.0.1" + semver "^7.3.5" + tsutils "^3.21.0" + "@typescript-eslint/typescript-estree@4.29.0": version "4.29.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.29.0.tgz#af7ab547757b86c91bfdbc54ff86845410856256" @@ -6762,6 +6788,14 @@ "@typescript-eslint/types" "4.22.0" eslint-visitor-keys "^2.0.0" +"@typescript-eslint/visitor-keys@4.28.5": + version "4.28.5" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.28.5.tgz#ffee2c602762ed6893405ee7c1144d9cc0a29675" + integrity sha512-dva/7Rr+EkxNWdJWau26xU/0slnFlkh88v3TsyTgRS/IIYFi5iIfpCFM4ikw0vQTFUR9FYSSyqgK4w64gsgxhg== + dependencies: + "@typescript-eslint/types" "4.28.5" + eslint-visitor-keys "^2.0.0" + "@typescript-eslint/visitor-keys@4.29.0": version "4.29.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.29.0.tgz#1ff60f240def4d85ea68d4fd2e4e9759b7850c04" @@ -9134,7 +9168,7 @@ caniuse-lite@^1.0.30001219: resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001228.tgz#bfdc5942cd3326fa51ee0b42fbef4da9d492a7fa" integrity sha512-QQmLOGJ3DEgokHbMSA8cj2a+geXqmnpyOFT0lhQV6P3/YOJvGDEwoedcwxEQ30gJIwIIunHIicunJ2rzK5gB2A== -caniuse-lite@^1.0.30001243: +caniuse-lite@^1.0.30001243, caniuse-lite@^1.0.30001248: version "1.0.30001251" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001251.tgz#6853a606ec50893115db660f82c094d18f096d85" integrity sha512-HOe1r+9VkU4TFmnU70z+r7OLmtR+/chB1rdcJUeQlAinjEeb0cKL20tlAtOagNZhbrtLnCvV19B4FmF1rgzl6A== @@ -17520,15 +17554,6 @@ lodash.forown@^4.4.0: resolved "https://registry.yarnpkg.com/lodash.forown/-/lodash.forown-4.4.0.tgz#85115cf04f73ef966eced52511d3893cc46683af" integrity sha1-hRFc8E9z75ZuztUlEdOJPMRmg68= -lodash.forown@~2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/lodash.forown/-/lodash.forown-2.3.0.tgz#24fb4aaf800d45fc2dc60bfec3ce04c836a3ad7f" - integrity sha1-JPtKr4ANRfwtxgv+w84EyDajrX8= - dependencies: - lodash._basecreatecallback "~2.3.0" - lodash._objecttypes "~2.3.0" - lodash.keys "~2.3.0" - lodash.get@^4, lodash.get@^4.0, lodash.get@^4.4.2: version "4.4.2" resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" @@ -21282,15 +21307,6 @@ postcss@^8.2.9: nanoid "^3.1.23" source-map "^0.6.1" -postcss@^8.3.5: - version "8.3.6" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.3.6.tgz#2730dd76a97969f37f53b9a6096197be311cc4ea" - integrity sha512-wG1cc/JhRgdqB6WHEuyLTedf3KIRuD0hG6ldkFEZNCjRxiC+3i6kkWUUbiJQayP28iwG35cEmAbe98585BYV0A== - dependencies: - colorette "^1.2.2" - nanoid "^3.1.23" - source-map-js "^0.6.2" - prelude-ls@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"