@superbright/indexeddb-orm 1.0.29 → 1.0.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/structured-store.cjs +1 -1
- package/dist/adapters/structured-store.cjs.map +1 -1
- package/dist/adapters/structured-store.d.ts +1 -0
- package/dist/adapters/structured-store.mjs +8 -7
- package/dist/adapters/structured-store.mjs.map +1 -1
- package/dist/adapters/zustand-store.cjs +1 -1
- package/dist/adapters/zustand-store.cjs.map +1 -1
- package/dist/adapters/zustand-store.d.ts +1 -0
- package/dist/adapters/zustand-store.mjs +3 -0
- package/dist/adapters/zustand-store.mjs.map +1 -1
- package/dist/stores/store.cjs +1 -1
- package/dist/stores/store.cjs.map +1 -1
- package/dist/stores/store.d.ts +7 -0
- package/dist/stores/store.mjs +54 -34
- package/dist/stores/store.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const d=require("./zustand-store.cjs");function u(t,i){return{property:{unit:{favorites:{toggle:t.toggleFavorite.bind(t),setAll:t.setFavoriteUnitIds.bind(t)},viewed:{mark:t.markUnitAsViewed.bind(t)}},questionnaire:{setResults:t.setQuestionnaireResults.bind(t)},tour:{setContactedOn:t.setTourContactedOn.bind(t),getContactedOn:t.getTourContactedOn.bind(t),setContactData:t.setTourContactData.bind(t)}},filters:{set:t.setFilters.bind(t),setTemp:t.setTempFilters.bind(t),setToDefault:t.setFiltersToDefault.bind(t),commitTemp:async(e,n)=>{const c=(i?i():t).tempFilters[e]??n;await t.handleTempFilterChange(e,c),await t.submitFilterUpdate()},commitDateAvailability:async()=>{await t.submitFilterUpdate()},submit:t.submitFilterUpdate.bind(t)}}}function r(t){return(i,e)=>{const n=d.createZustandUnifiedStore(t)(i,e),a=u(n,e);return{...n,...a}}}exports.createStructuredStore=r;exports.createStructuredStoreActions=u;
|
|
2
2
|
//# sourceMappingURL=structured-store.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"structured-store.cjs","sources":["../../src/adapters/structured-store.ts"],"sourcesContent":["/**\n * Structured store wrapper (preferred DX)\n *\n * This layer wraps the flat Zustand adapter with domain‑grouped actions\n * for a more discoverable API in apps. It does not add new behavior —\n * it simply organizes calls like:\n * - `property.unit.favorites.toggle` → `toggleFavorite`\n * - `property.unit.viewed.mark` → `markUnitAsViewed`\n * - `filters.set/submit/...` → filter methods\n */\nimport {\n type ZustandUnifiedStoreState,\n createZustandUnifiedStore,\n type Filters,\n type UnitData,\n type TourContactData,\n type QueryParams\n} from \"./zustand-store\";\n\nexport interface StructuredStoreActions {\n property: {\n unit: {\n favorites: {\n toggle: (unitId: string) => Promise<void>;\n };\n viewed: {\n mark: (unitId: string, slug: string) => Promise<void>;\n };\n };\n questionnaire: {\n setResults: (results: unknown) => Promise<void>;\n };\n tour: {\n setContactedOn: () => Promise<void>;\n getContactedOn: () => Promise<string | null>;\n setContactData: (data: TourContactData) => Promise<void>;\n };\n };\n\n filters: {\n set: (filters: Partial<Filters>) => Promise<void>;\n setTemp: (filters: Partial<Filters>) => Promise<void>;\n setToDefault: () => Promise<void>;\n commitTemp: <K extends keyof Filters>(key: K, defaultValue: Filters[K]) => Promise<void>;\n commitDateAvailability: () => Promise<void>;\n submit: () => Promise<void>;\n };\n}\n\nexport function createStructuredStoreActions(store: ZustandUnifiedStoreState, get?: () => ZustandUnifiedStoreState): StructuredStoreActions {\n return {\n property: {\n unit: {\n favorites: {\n toggle: store.toggleFavorite.bind(store),\n },\n viewed: {\n mark: store.markUnitAsViewed.bind(store),\n },\n },\n questionnaire: {\n setResults: store.setQuestionnaireResults.bind(store),\n },\n tour: {\n setContactedOn: store.setTourContactedOn.bind(store),\n getContactedOn: store.getTourContactedOn.bind(store),\n setContactData: store.setTourContactData.bind(store),\n },\n },\n filters: {\n set: store.setFilters.bind(store),\n setTemp: store.setTempFilters.bind(store),\n setToDefault: store.setFiltersToDefault.bind(store),\n commitTemp: async (key, defaultValue) => {\n const state = get ? get() : (store as unknown as ZustandUnifiedStoreState);\n const value = (state.tempFilters as Filters)[key] ?? defaultValue;\n await store.handleTempFilterChange(key, value as any);\n await store.submitFilterUpdate();\n },\n commitDateAvailability: async () => {\n await store.submitFilterUpdate();\n },\n submit: store.submitFilterUpdate.bind(store),\n },\n };\n}\n\nexport type StructuredStore = ZustandUnifiedStoreState & StructuredStoreActions;\n\nexport function createStructuredStore(options?: {\n onFilterUpdate?: (apiParams: QueryParams) => void;\n}) {\n return (set: any, get: any): StructuredStore => {\n const baseStore = createZustandUnifiedStore(options)(set, get);\n const actions = createStructuredStoreActions(baseStore, get);\n\n return {\n ...baseStore,\n ...actions,\n };\n };\n}\n"],"names":["createStructuredStoreActions","store","get","key","defaultValue","value","createStructuredStore","options","set","baseStore","createZustandUnifiedStore","actions"],"mappings":"
|
|
1
|
+
{"version":3,"file":"structured-store.cjs","sources":["../../src/adapters/structured-store.ts"],"sourcesContent":["/**\n * Structured store wrapper (preferred DX)\n *\n * This layer wraps the flat Zustand adapter with domain‑grouped actions\n * for a more discoverable API in apps. It does not add new behavior —\n * it simply organizes calls like:\n * - `property.unit.favorites.toggle` → `toggleFavorite`\n * - `property.unit.viewed.mark` → `markUnitAsViewed`\n * - `filters.set/submit/...` → filter methods\n */\nimport {\n type ZustandUnifiedStoreState,\n createZustandUnifiedStore,\n type Filters,\n type UnitData,\n type TourContactData,\n type QueryParams\n} from \"./zustand-store\";\n\nexport interface StructuredStoreActions {\n property: {\n unit: {\n favorites: {\n toggle: (unitId: string) => Promise<void>;\n setAll: (unitIds: string[]) => Promise<void>;\n };\n viewed: {\n mark: (unitId: string, slug: string) => Promise<void>;\n };\n };\n questionnaire: {\n setResults: (results: unknown) => Promise<void>;\n };\n tour: {\n setContactedOn: () => Promise<void>;\n getContactedOn: () => Promise<string | null>;\n setContactData: (data: TourContactData) => Promise<void>;\n };\n };\n\n filters: {\n set: (filters: Partial<Filters>) => Promise<void>;\n setTemp: (filters: Partial<Filters>) => Promise<void>;\n setToDefault: () => Promise<void>;\n commitTemp: <K extends keyof Filters>(key: K, defaultValue: Filters[K]) => Promise<void>;\n commitDateAvailability: () => Promise<void>;\n submit: () => Promise<void>;\n };\n}\n\nexport function createStructuredStoreActions(store: ZustandUnifiedStoreState, get?: () => ZustandUnifiedStoreState): StructuredStoreActions {\n return {\n property: {\n unit: {\n favorites: {\n toggle: store.toggleFavorite.bind(store),\n setAll: store.setFavoriteUnitIds.bind(store),\n },\n viewed: {\n mark: store.markUnitAsViewed.bind(store),\n },\n },\n questionnaire: {\n setResults: store.setQuestionnaireResults.bind(store),\n },\n tour: {\n setContactedOn: store.setTourContactedOn.bind(store),\n getContactedOn: store.getTourContactedOn.bind(store),\n setContactData: store.setTourContactData.bind(store),\n },\n },\n filters: {\n set: store.setFilters.bind(store),\n setTemp: store.setTempFilters.bind(store),\n setToDefault: store.setFiltersToDefault.bind(store),\n commitTemp: async (key, defaultValue) => {\n const state = get ? get() : (store as unknown as ZustandUnifiedStoreState);\n const value = (state.tempFilters as Filters)[key] ?? defaultValue;\n await store.handleTempFilterChange(key, value as any);\n await store.submitFilterUpdate();\n },\n commitDateAvailability: async () => {\n await store.submitFilterUpdate();\n },\n submit: store.submitFilterUpdate.bind(store),\n },\n };\n}\n\nexport type StructuredStore = ZustandUnifiedStoreState & StructuredStoreActions;\n\nexport function createStructuredStore(options?: {\n onFilterUpdate?: (apiParams: QueryParams) => void;\n}) {\n return (set: any, get: any): StructuredStore => {\n const baseStore = createZustandUnifiedStore(options)(set, get);\n const actions = createStructuredStoreActions(baseStore, get);\n\n return {\n ...baseStore,\n ...actions,\n };\n };\n}\n"],"names":["createStructuredStoreActions","store","get","key","defaultValue","value","createStructuredStore","options","set","baseStore","createZustandUnifiedStore","actions"],"mappings":"uHAkDO,SAASA,EAA6BC,EAAiCC,EAA8D,CAC1I,MAAO,CACL,SAAU,CACR,KAAM,CACJ,UAAW,CACT,OAAQD,EAAM,eAAe,KAAKA,CAAK,EACvC,OAAQA,EAAM,mBAAmB,KAAKA,CAAK,CAAA,EAE7C,OAAQ,CACN,KAAMA,EAAM,iBAAiB,KAAKA,CAAK,CAAA,CACzC,EAEF,cAAe,CACb,WAAYA,EAAM,wBAAwB,KAAKA,CAAK,CAAA,EAEtD,KAAM,CACJ,eAAgBA,EAAM,mBAAmB,KAAKA,CAAK,EACnD,eAAgBA,EAAM,mBAAmB,KAAKA,CAAK,EACnD,eAAgBA,EAAM,mBAAmB,KAAKA,CAAK,CAAA,CACrD,EAEF,QAAS,CACP,IAAKA,EAAM,WAAW,KAAKA,CAAK,EAChC,QAASA,EAAM,eAAe,KAAKA,CAAK,EACxC,aAAcA,EAAM,oBAAoB,KAAKA,CAAK,EAClD,WAAY,MAAOE,EAAKC,IAAiB,CAEvC,MAAMC,GADQH,EAAMA,EAAA,EAASD,GACR,YAAwBE,CAAG,GAAKC,EACrD,MAAMH,EAAM,uBAAuBE,EAAKE,CAAY,EACpD,MAAMJ,EAAM,mBAAA,CACd,EACA,uBAAwB,SAAY,CAClC,MAAMA,EAAM,mBAAA,CACd,EACA,OAAQA,EAAM,mBAAmB,KAAKA,CAAK,CAAA,CAC7C,CAEJ,CAIO,SAASK,EAAsBC,EAEnC,CACD,MAAO,CAACC,EAAUN,IAA8B,CAC9C,MAAMO,EAAYC,EAAAA,0BAA0BH,CAAO,EAAEC,EAAKN,CAAG,EACvDS,EAAUX,EAA6BS,EAAWP,CAAG,EAE3D,MAAO,CACL,GAAGO,EACH,GAAGE,CAAA,CAEP,CACF"}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { createZustandUnifiedStore as
|
|
1
|
+
import { createZustandUnifiedStore as u } from "./zustand-store.mjs";
|
|
2
2
|
function c(t, i) {
|
|
3
3
|
return {
|
|
4
4
|
property: {
|
|
5
5
|
unit: {
|
|
6
6
|
favorites: {
|
|
7
|
-
toggle: t.toggleFavorite.bind(t)
|
|
7
|
+
toggle: t.toggleFavorite.bind(t),
|
|
8
|
+
setAll: t.setFavoriteUnitIds.bind(t)
|
|
8
9
|
},
|
|
9
10
|
viewed: {
|
|
10
11
|
mark: t.markUnitAsViewed.bind(t)
|
|
@@ -24,8 +25,8 @@ function c(t, i) {
|
|
|
24
25
|
setTemp: t.setTempFilters.bind(t),
|
|
25
26
|
setToDefault: t.setFiltersToDefault.bind(t),
|
|
26
27
|
commitTemp: async (e, n) => {
|
|
27
|
-
const
|
|
28
|
-
await t.handleTempFilterChange(e,
|
|
28
|
+
const d = (i ? i() : t).tempFilters[e] ?? n;
|
|
29
|
+
await t.handleTempFilterChange(e, d), await t.submitFilterUpdate();
|
|
29
30
|
},
|
|
30
31
|
commitDateAvailability: async () => {
|
|
31
32
|
await t.submitFilterUpdate();
|
|
@@ -34,9 +35,9 @@ function c(t, i) {
|
|
|
34
35
|
}
|
|
35
36
|
};
|
|
36
37
|
}
|
|
37
|
-
function
|
|
38
|
+
function s(t) {
|
|
38
39
|
return (i, e) => {
|
|
39
|
-
const n =
|
|
40
|
+
const n = u(t)(i, e), a = c(n, e);
|
|
40
41
|
return {
|
|
41
42
|
...n,
|
|
42
43
|
...a
|
|
@@ -44,7 +45,7 @@ function r(t) {
|
|
|
44
45
|
};
|
|
45
46
|
}
|
|
46
47
|
export {
|
|
47
|
-
|
|
48
|
+
s as createStructuredStore,
|
|
48
49
|
c as createStructuredStoreActions
|
|
49
50
|
};
|
|
50
51
|
//# sourceMappingURL=structured-store.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"structured-store.mjs","sources":["../../src/adapters/structured-store.ts"],"sourcesContent":["/**\n * Structured store wrapper (preferred DX)\n *\n * This layer wraps the flat Zustand adapter with domain‑grouped actions\n * for a more discoverable API in apps. It does not add new behavior —\n * it simply organizes calls like:\n * - `property.unit.favorites.toggle` → `toggleFavorite`\n * - `property.unit.viewed.mark` → `markUnitAsViewed`\n * - `filters.set/submit/...` → filter methods\n */\nimport {\n type ZustandUnifiedStoreState,\n createZustandUnifiedStore,\n type Filters,\n type UnitData,\n type TourContactData,\n type QueryParams\n} from \"./zustand-store\";\n\nexport interface StructuredStoreActions {\n property: {\n unit: {\n favorites: {\n toggle: (unitId: string) => Promise<void>;\n };\n viewed: {\n mark: (unitId: string, slug: string) => Promise<void>;\n };\n };\n questionnaire: {\n setResults: (results: unknown) => Promise<void>;\n };\n tour: {\n setContactedOn: () => Promise<void>;\n getContactedOn: () => Promise<string | null>;\n setContactData: (data: TourContactData) => Promise<void>;\n };\n };\n\n filters: {\n set: (filters: Partial<Filters>) => Promise<void>;\n setTemp: (filters: Partial<Filters>) => Promise<void>;\n setToDefault: () => Promise<void>;\n commitTemp: <K extends keyof Filters>(key: K, defaultValue: Filters[K]) => Promise<void>;\n commitDateAvailability: () => Promise<void>;\n submit: () => Promise<void>;\n };\n}\n\nexport function createStructuredStoreActions(store: ZustandUnifiedStoreState, get?: () => ZustandUnifiedStoreState): StructuredStoreActions {\n return {\n property: {\n unit: {\n favorites: {\n toggle: store.toggleFavorite.bind(store),\n },\n viewed: {\n mark: store.markUnitAsViewed.bind(store),\n },\n },\n questionnaire: {\n setResults: store.setQuestionnaireResults.bind(store),\n },\n tour: {\n setContactedOn: store.setTourContactedOn.bind(store),\n getContactedOn: store.getTourContactedOn.bind(store),\n setContactData: store.setTourContactData.bind(store),\n },\n },\n filters: {\n set: store.setFilters.bind(store),\n setTemp: store.setTempFilters.bind(store),\n setToDefault: store.setFiltersToDefault.bind(store),\n commitTemp: async (key, defaultValue) => {\n const state = get ? get() : (store as unknown as ZustandUnifiedStoreState);\n const value = (state.tempFilters as Filters)[key] ?? defaultValue;\n await store.handleTempFilterChange(key, value as any);\n await store.submitFilterUpdate();\n },\n commitDateAvailability: async () => {\n await store.submitFilterUpdate();\n },\n submit: store.submitFilterUpdate.bind(store),\n },\n };\n}\n\nexport type StructuredStore = ZustandUnifiedStoreState & StructuredStoreActions;\n\nexport function createStructuredStore(options?: {\n onFilterUpdate?: (apiParams: QueryParams) => void;\n}) {\n return (set: any, get: any): StructuredStore => {\n const baseStore = createZustandUnifiedStore(options)(set, get);\n const actions = createStructuredStoreActions(baseStore, get);\n\n return {\n ...baseStore,\n ...actions,\n };\n };\n}\n"],"names":["createStructuredStoreActions","store","get","key","defaultValue","value","createStructuredStore","options","set","baseStore","createZustandUnifiedStore","actions"],"mappings":";
|
|
1
|
+
{"version":3,"file":"structured-store.mjs","sources":["../../src/adapters/structured-store.ts"],"sourcesContent":["/**\n * Structured store wrapper (preferred DX)\n *\n * This layer wraps the flat Zustand adapter with domain‑grouped actions\n * for a more discoverable API in apps. It does not add new behavior —\n * it simply organizes calls like:\n * - `property.unit.favorites.toggle` → `toggleFavorite`\n * - `property.unit.viewed.mark` → `markUnitAsViewed`\n * - `filters.set/submit/...` → filter methods\n */\nimport {\n type ZustandUnifiedStoreState,\n createZustandUnifiedStore,\n type Filters,\n type UnitData,\n type TourContactData,\n type QueryParams\n} from \"./zustand-store\";\n\nexport interface StructuredStoreActions {\n property: {\n unit: {\n favorites: {\n toggle: (unitId: string) => Promise<void>;\n setAll: (unitIds: string[]) => Promise<void>;\n };\n viewed: {\n mark: (unitId: string, slug: string) => Promise<void>;\n };\n };\n questionnaire: {\n setResults: (results: unknown) => Promise<void>;\n };\n tour: {\n setContactedOn: () => Promise<void>;\n getContactedOn: () => Promise<string | null>;\n setContactData: (data: TourContactData) => Promise<void>;\n };\n };\n\n filters: {\n set: (filters: Partial<Filters>) => Promise<void>;\n setTemp: (filters: Partial<Filters>) => Promise<void>;\n setToDefault: () => Promise<void>;\n commitTemp: <K extends keyof Filters>(key: K, defaultValue: Filters[K]) => Promise<void>;\n commitDateAvailability: () => Promise<void>;\n submit: () => Promise<void>;\n };\n}\n\nexport function createStructuredStoreActions(store: ZustandUnifiedStoreState, get?: () => ZustandUnifiedStoreState): StructuredStoreActions {\n return {\n property: {\n unit: {\n favorites: {\n toggle: store.toggleFavorite.bind(store),\n setAll: store.setFavoriteUnitIds.bind(store),\n },\n viewed: {\n mark: store.markUnitAsViewed.bind(store),\n },\n },\n questionnaire: {\n setResults: store.setQuestionnaireResults.bind(store),\n },\n tour: {\n setContactedOn: store.setTourContactedOn.bind(store),\n getContactedOn: store.getTourContactedOn.bind(store),\n setContactData: store.setTourContactData.bind(store),\n },\n },\n filters: {\n set: store.setFilters.bind(store),\n setTemp: store.setTempFilters.bind(store),\n setToDefault: store.setFiltersToDefault.bind(store),\n commitTemp: async (key, defaultValue) => {\n const state = get ? get() : (store as unknown as ZustandUnifiedStoreState);\n const value = (state.tempFilters as Filters)[key] ?? defaultValue;\n await store.handleTempFilterChange(key, value as any);\n await store.submitFilterUpdate();\n },\n commitDateAvailability: async () => {\n await store.submitFilterUpdate();\n },\n submit: store.submitFilterUpdate.bind(store),\n },\n };\n}\n\nexport type StructuredStore = ZustandUnifiedStoreState & StructuredStoreActions;\n\nexport function createStructuredStore(options?: {\n onFilterUpdate?: (apiParams: QueryParams) => void;\n}) {\n return (set: any, get: any): StructuredStore => {\n const baseStore = createZustandUnifiedStore(options)(set, get);\n const actions = createStructuredStoreActions(baseStore, get);\n\n return {\n ...baseStore,\n ...actions,\n };\n };\n}\n"],"names":["createStructuredStoreActions","store","get","key","defaultValue","value","createStructuredStore","options","set","baseStore","createZustandUnifiedStore","actions"],"mappings":";AAkDO,SAASA,EAA6BC,GAAiCC,GAA8D;AAC1I,SAAO;AAAA,IACL,UAAU;AAAA,MACR,MAAM;AAAA,QACJ,WAAW;AAAA,UACT,QAAQD,EAAM,eAAe,KAAKA,CAAK;AAAA,UACvC,QAAQA,EAAM,mBAAmB,KAAKA,CAAK;AAAA,QAAA;AAAA,QAE7C,QAAQ;AAAA,UACN,MAAMA,EAAM,iBAAiB,KAAKA,CAAK;AAAA,QAAA;AAAA,MACzC;AAAA,MAEF,eAAe;AAAA,QACb,YAAYA,EAAM,wBAAwB,KAAKA,CAAK;AAAA,MAAA;AAAA,MAEtD,MAAM;AAAA,QACJ,gBAAgBA,EAAM,mBAAmB,KAAKA,CAAK;AAAA,QACnD,gBAAgBA,EAAM,mBAAmB,KAAKA,CAAK;AAAA,QACnD,gBAAgBA,EAAM,mBAAmB,KAAKA,CAAK;AAAA,MAAA;AAAA,IACrD;AAAA,IAEF,SAAS;AAAA,MACP,KAAKA,EAAM,WAAW,KAAKA,CAAK;AAAA,MAChC,SAASA,EAAM,eAAe,KAAKA,CAAK;AAAA,MACxC,cAAcA,EAAM,oBAAoB,KAAKA,CAAK;AAAA,MAClD,YAAY,OAAOE,GAAKC,MAAiB;AAEvC,cAAMC,KADQH,IAAMA,EAAA,IAASD,GACR,YAAwBE,CAAG,KAAKC;AACrD,cAAMH,EAAM,uBAAuBE,GAAKE,CAAY,GACpD,MAAMJ,EAAM,mBAAA;AAAA,MACd;AAAA,MACA,wBAAwB,YAAY;AAClC,cAAMA,EAAM,mBAAA;AAAA,MACd;AAAA,MACA,QAAQA,EAAM,mBAAmB,KAAKA,CAAK;AAAA,IAAA;AAAA,EAC7C;AAEJ;AAIO,SAASK,EAAsBC,GAEnC;AACD,SAAO,CAACC,GAAUN,MAA8B;AAC9C,UAAMO,IAAYC,EAA0BH,CAAO,EAAEC,GAAKN,CAAG,GACvDS,IAAUX,EAA6BS,GAAWP,CAAG;AAE3D,WAAO;AAAA,MACL,GAAGO;AAAA,MACH,GAAGE;AAAA,IAAA;AAAA,EAEP;AACF;"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("../stores/store.cjs");function
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("../stores/store.cjs");function c(n){return(a,o)=>{const s=async()=>{const t=await e.store.getFullState();a({properties:t.properties,currentPropertyId:t.currentPropertyId,currentPropertySlug:t.currentPropertySlug,hasPreviouslySearched:t.hasPreviouslySearched,unitResults:t.unitResults,filters:t.filters,tempFilters:t.tempFilters,apiFilters:t.apiFilters,resultsMode:t.resultsMode,resolvedQuestionnaireValues:t.resolvedQuestionnaireValues,sortBy:t.sortBy})},u=async()=>{if(n!=null&&n.onFilterUpdate){const t=(await e.store.getFullState()).apiFilters;n.onFilterUpdate(t)}};return{properties:{},currentPropertyId:null,currentPropertySlug:null,hasPreviouslySearched:[],unitResults:[],filters:{date_availability:void 0,qty_bedrooms:void 0,base_price:void 0,highlights:void 0},tempFilters:{date_availability:void 0,qty_bedrooms:void 0,base_price:void 0,highlights:void 0},apiFilters:{limit:10,page:1,sortBy:"relevance"},resultsMode:"all",resolvedQuestionnaireValues:{},sortBy:"relevance",filtersLoaded:!1,async initializeProperty(t,r){await e.store.initializeProperty(t,r),await s()},async setCurrentProperty(t,r){await e.store.setCurrentProperty(t,r),a({currentPropertyId:t,...r&&{currentPropertySlug:r}})},async setCurrentPropertySlug(t){await e.store.setCurrentPropertySlug(t),a({currentPropertySlug:t})},async setHasPreviouslySearched(t){await e.store.setHasPreviouslySearched(t),await s()},async setFavoriteUnitIds(t){await e.store.setFavoriteUnitIds(t),await s()},async toggleFavorite(t){await e.store.toggleFavorite(t),await s()},async markUnitAsViewed(t,r){await e.store.markUnitAsViewed(t,r),await s()},async setTourContactedOn(){await e.store.setTourContactedOn(),await s()},getTourContactedOn:e.store.getTourContactedOn.bind(e.store),async setQuestionnaireResults(t){await e.store.setQuestionnaireResults(t),await s()},async setTourContactData(t){await e.store.setTourContactData(t),await s()},async setUnitResults(t){await e.store.setUnitResults(t),await s()},async clearUnitResults(){await e.store.clearUnitResults(),await s()},async setFilters(t){await e.store.setFilters(t);const r=o();a({filters:{...r.filters,...t}})},async setTempFilters(t){await e.store.setTempFilters(t);const r=o();a({tempFilters:{...r.tempFilters,...t}})},async setFiltersToDefault(){await e.store.setFiltersToDefault(),a({filters:{date_availability:void 0,qty_bedrooms:void 0,base_price:void 0,highlights:void 0}})},async setApiFilters(t){await e.store.setApiFilters(t);const r=o();a({apiFilters:{...r.apiFilters,...t}})},async handleTempFilterChange(t,r){await e.store.handleTempFilterChange(t,r);const i=o();a({tempFilters:{...i.tempFilters,[t]:r}})},async submitFilterUpdate(){await e.store.submitFilterUpdate(),await s(),await u()},async setResultsMode(t){await e.store.setResultsMode(t),a({resultsMode:t})},async setSortBy(t){await e.store.setSortBy(t),a({sortBy:t})},async setResolvedQuestionnaireValues(t,r){await e.store.setResolvedQuestionnaireValues(t,r);const i=o();a({resolvedQuestionnaireValues:{...i.resolvedQuestionnaireValues,[t]:r}})},getUnitState(t){var l;const r=o(),i=r.currentPropertyId?r.properties[r.currentPropertyId]:null;return{isFavorite:(i==null?void 0:i.favoritedUnits.includes(t))??!1,viewedDate:((l=i==null?void 0:i.viewedUnits.find(d=>d.unitId===t))==null?void 0:l.viewedDate)??""}},getResultsUrl:e.store.getResultsUrl.bind(e.store),getCurrentProperty:e.store.getCurrentProperty.bind(e.store),getPropertyData:e.store.getPropertyData.bind(e.store),async _hydrate(){await s()},async _initialize(){await e.store.initialize(),await s(),a({filtersLoaded:!0})}}}}function y(){return n=>a=>n(o=>o.getUnitState(a))}exports.createUseUnitState=y;exports.createZustandUnifiedStore=c;
|
|
2
2
|
//# sourceMappingURL=zustand-store.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"zustand-store.cjs","sources":["../../src/adapters/zustand-store.ts"],"sourcesContent":["/**\n * Zustand adapter (flat API)\n *\n * This file exposes a flat, unified Zustand store that mirrors the underlying\n * ORM store and keeps React state in sync. It is the low-level bridge.\n *\n * For a friendlier, domain-grouped API, use `createStructuredStore` from\n * `./structured-store`, which wraps this adapter and exposes nested actions\n * like `property.unit.favorites.toggle`, `filters.set`, etc.\n */\nimport { store } from \"../stores/store\";\nimport type { UnifiedStoreData, UserPropertyState, Filters, QueryParams, ResultsMode, SortBy, TourContactData, Unit } from \"../schema\";\n\n// Unified Zustand store interface\nexport interface ZustandUnifiedStoreState {\n // Property data\n properties: Record<string, UserPropertyState>;\n currentPropertyId: string | null;\n currentPropertySlug: string | null;\n hasPreviouslySearched: string[];\n\n // App data\n unitResults: Unit[];\n filters: Filters;\n tempFilters: Filters;\n apiFilters: QueryParams;\n resultsMode: ResultsMode;\n resolvedQuestionnaireValues: Record<string, string[]>;\n sortBy: SortBy;\n filtersLoaded: boolean;\n\n // === PROPERTY OPERATIONS ===\n initializeProperty: (propertyId: string, slug: string) => Promise<void>;\n setCurrentProperty: (propertyId: string, slug?: string) => Promise<void>;\n setCurrentPropertySlug: (slug: string) => Promise<void>;\n setHasPreviouslySearched: (slug: string) => Promise<void>;\n toggleFavorite: (unitId: string) => Promise<void>;\n markUnitAsViewed: (unitId: string, slug: string) => Promise<void>;\n setTourContactedOn: () => Promise<void>;\n getTourContactedOn: () => Promise<string | null>;\n setQuestionnaireResults: (results: unknown) => Promise<void>;\n setTourContactData: (data: TourContactData) => Promise<void>;\n setUnitResults: (units: unknown) => Promise<void>;\n clearUnitResults: () => Promise<void>;\n\n\n // === FILTER OPERATIONS ===\n setFilters: (filters: Partial<Filters>) => Promise<void>;\n setTempFilters: (filters: Partial<Filters>) => Promise<void>;\n setFiltersToDefault: () => Promise<void>;\n setApiFilters: (filters: Partial<QueryParams>) => Promise<void>;\n handleTempFilterChange: <K extends keyof Filters>(key: K, value: Filters[K]) => Promise<void>;\n submitFilterUpdate: () => Promise<void>;\n\n // === RESULTS AND SORTING ===\n setResultsMode: (mode: ResultsMode) => Promise<void>;\n setSortBy: (sortBy: SortBy) => Promise<void>;\n\n // === QUESTIONNAIRE ===\n setResolvedQuestionnaireValues: (name: string, values: string[]) => Promise<void>;\n\n // === UTILITY METHODS ===\n getUnitState: (unitId: string) => {\n isFavorite: boolean;\n viewedDate: string;\n };\n getResultsUrl: () => Promise<string | null>;\n getCurrentProperty: () => Promise<UserPropertyState | null>;\n getPropertyData: (propertyId?: string) => Promise<UserPropertyState | null>;\n\n // === INTERNAL ===\n _hydrate: () => Promise<void>;\n _initialize: () => Promise<void>;\n}\n\n/**\n * @deprecated For new apps, use `createStructuredStore` from `./structured-store`.\n * This flat adapter remains for migration/advanced cases.\n */\nexport function createZustandUnifiedStore(options?: {\n onFilterUpdate?: (apiParams: QueryParams) => void;\n}) {\n return (set: any, get: any): ZustandUnifiedStoreState => {\n // Helper to update local state after ORM operations\n const syncState = async () => {\n const ormState = await store.getFullState();\n set({\n properties: ormState.properties,\n currentPropertyId: ormState.currentPropertyId,\n currentPropertySlug: ormState.currentPropertySlug,\n hasPreviouslySearched: ormState.hasPreviouslySearched,\n unitResults: ormState.unitResults,\n filters: ormState.filters,\n tempFilters: ormState.tempFilters,\n apiFilters: ormState.apiFilters,\n resultsMode: ormState.resultsMode,\n resolvedQuestionnaireValues: ormState.resolvedQuestionnaireValues,\n sortBy: ormState.sortBy,\n });\n };\n\n // Helper to notify of filter updates\n const notifyFilterUpdate = async () => {\n if (options?.onFilterUpdate) {\n const apiFilters = (await store.getFullState()).apiFilters;\n options.onFilterUpdate(apiFilters);\n }\n };\n\n return {\n // Initial state\n properties: {},\n currentPropertyId: null,\n currentPropertySlug: null,\n hasPreviouslySearched: [],\n unitResults: [],\n filters: {\n date_availability: undefined,\n qty_bedrooms: undefined,\n base_price: undefined,\n highlights: undefined,\n },\n tempFilters: {\n date_availability: undefined,\n qty_bedrooms: undefined,\n base_price: undefined,\n highlights: undefined,\n },\n apiFilters: {\n limit: 10,\n page: 1,\n sortBy: \"relevance\",\n },\n resultsMode: \"all\",\n resolvedQuestionnaireValues: {},\n sortBy: \"relevance\",\n filtersLoaded: false,\n\n // === PROPERTY OPERATIONS ===\n async initializeProperty(propertyId, slug) {\n await store.initializeProperty(propertyId, slug);\n await syncState();\n },\n\n async setCurrentProperty(propertyId, slug) {\n await store.setCurrentProperty(propertyId, slug);\n set({\n currentPropertyId: propertyId,\n ...(slug && { currentPropertySlug: slug })\n });\n },\n\n async setCurrentPropertySlug(slug) {\n await store.setCurrentPropertySlug(slug);\n set({ currentPropertySlug: slug });\n },\n\n async setHasPreviouslySearched(slug) {\n await store.setHasPreviouslySearched(slug);\n await syncState();\n },\n\n async toggleFavorite(unitId) {\n await store.toggleFavorite(unitId);\n await syncState();\n },\n\n async markUnitAsViewed(unitId, slug) {\n await store.markUnitAsViewed(unitId, slug);\n await syncState();\n },\n\n async setTourContactedOn() {\n await store.setTourContactedOn();\n await syncState();\n },\n\n getTourContactedOn: store.getTourContactedOn.bind(store),\n\n async setQuestionnaireResults(results) {\n await store.setQuestionnaireResults(results);\n await syncState();\n },\n\n async setTourContactData(data) {\n await store.setTourContactData(data);\n await syncState();\n },\n\n async setUnitResults(units) {\n await store.setUnitResults(units);\n await syncState();\n },\n\n async clearUnitResults() {\n await store.clearUnitResults();\n await syncState();\n },\n\n\n // === FILTER OPERATIONS ===\n async setFilters(filters) {\n await store.setFilters(filters);\n const state = get();\n set({ filters: { ...state.filters, ...filters } });\n },\n\n async setTempFilters(filters) {\n await store.setTempFilters(filters);\n const state = get();\n set({ tempFilters: { ...state.tempFilters, ...filters } });\n },\n\n async setFiltersToDefault() {\n await store.setFiltersToDefault();\n const defaultFilters = {\n date_availability: undefined,\n qty_bedrooms: undefined,\n base_price: undefined,\n highlights: undefined,\n };\n set({ filters: defaultFilters });\n },\n\n async setApiFilters(filters) {\n await store.setApiFilters(filters);\n const state = get();\n set({ apiFilters: { ...state.apiFilters, ...filters } });\n },\n\n async handleTempFilterChange(key, value) {\n await store.handleTempFilterChange(key, value);\n const state = get();\n set({ tempFilters: { ...state.tempFilters, [key]: value } });\n },\n\n async submitFilterUpdate() {\n await store.submitFilterUpdate();\n await syncState();\n await notifyFilterUpdate();\n },\n\n // === RESULTS AND SORTING ===\n async setResultsMode(mode) {\n await store.setResultsMode(mode);\n set({ resultsMode: mode });\n },\n\n async setSortBy(sortBy) {\n await store.setSortBy(sortBy);\n set({ sortBy });\n },\n\n // === QUESTIONNAIRE ===\n async setResolvedQuestionnaireValues(name, values) {\n await store.setResolvedQuestionnaireValues(name, values);\n const state = get();\n set({\n resolvedQuestionnaireValues: {\n ...state.resolvedQuestionnaireValues,\n [name]: values,\n }\n });\n },\n\n // === UTILITY METHODS ===\n getUnitState(unitId: string) {\n const state = get();\n const property = state.currentPropertyId ? state.properties[state.currentPropertyId] : null;\n\n return {\n isFavorite: property?.favoritedUnits.includes(unitId) ?? false,\n viewedDate:\n property?.viewedUnits.find((u: any) => u.unitId === unitId)?.viewedDate ?? \"\",\n };\n },\n\n getResultsUrl: store.getResultsUrl.bind(store),\n getCurrentProperty: store.getCurrentProperty.bind(store),\n getPropertyData: store.getPropertyData.bind(store),\n\n // === INTERNAL ===\n async _hydrate() {\n await syncState();\n },\n\n async _initialize() {\n await store.initialize();\n await syncState();\n set({ filtersLoaded: true });\n },\n };\n };\n}\n\n// Helper hook factory for unit state\nexport function createUseUnitState() {\n return (useStore: any) => (unitId: string) =>\n useStore((state: ZustandUnifiedStoreState) => state.getUnitState(unitId));\n}\n\n// Export types for consuming apps\nexport type { UnitData, UserPropertyState, Filters, QueryParams, ResultsMode, SortBy, TourContactData, Unit } from \"../schema\";\n\n// Intentionally no alias exports in vNext; use `createStructuredStore` or `createZustandUnifiedStore` explicitly.\n"],"names":["createZustandUnifiedStore","options","set","get","syncState","ormState","store","notifyFilterUpdate","apiFilters","propertyId","slug","unitId","results","data","units","filters","state","key","value","mode","sortBy","name","values","property","_a","u","createUseUnitState","useStore"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"zustand-store.cjs","sources":["../../src/adapters/zustand-store.ts"],"sourcesContent":["/**\n * Zustand adapter (flat API)\n *\n * This file exposes a flat, unified Zustand store that mirrors the underlying\n * ORM store and keeps React state in sync. It is the low-level bridge.\n *\n * For a friendlier, domain-grouped API, use `createStructuredStore` from\n * `./structured-store`, which wraps this adapter and exposes nested actions\n * like `property.unit.favorites.toggle`, `filters.set`, etc.\n */\nimport { store } from \"../stores/store\";\nimport type { UnifiedStoreData, UserPropertyState, Filters, QueryParams, ResultsMode, SortBy, TourContactData, Unit } from \"../schema\";\n\n// Unified Zustand store interface\nexport interface ZustandUnifiedStoreState {\n // Property data\n properties: Record<string, UserPropertyState>;\n currentPropertyId: string | null;\n currentPropertySlug: string | null;\n hasPreviouslySearched: string[];\n\n // App data\n unitResults: Unit[];\n filters: Filters;\n tempFilters: Filters;\n apiFilters: QueryParams;\n resultsMode: ResultsMode;\n resolvedQuestionnaireValues: Record<string, string[]>;\n sortBy: SortBy;\n filtersLoaded: boolean;\n\n // === PROPERTY OPERATIONS ===\n initializeProperty: (propertyId: string, slug: string) => Promise<void>;\n setCurrentProperty: (propertyId: string, slug?: string) => Promise<void>;\n setCurrentPropertySlug: (slug: string) => Promise<void>;\n setHasPreviouslySearched: (slug: string) => Promise<void>;\n setFavoriteUnitIds: (unitIds: string[]) => Promise<void>;\n toggleFavorite: (unitId: string) => Promise<void>;\n markUnitAsViewed: (unitId: string, slug: string) => Promise<void>;\n setTourContactedOn: () => Promise<void>;\n getTourContactedOn: () => Promise<string | null>;\n setQuestionnaireResults: (results: unknown) => Promise<void>;\n setTourContactData: (data: TourContactData) => Promise<void>;\n setUnitResults: (units: unknown) => Promise<void>;\n clearUnitResults: () => Promise<void>;\n\n\n // === FILTER OPERATIONS ===\n setFilters: (filters: Partial<Filters>) => Promise<void>;\n setTempFilters: (filters: Partial<Filters>) => Promise<void>;\n setFiltersToDefault: () => Promise<void>;\n setApiFilters: (filters: Partial<QueryParams>) => Promise<void>;\n handleTempFilterChange: <K extends keyof Filters>(key: K, value: Filters[K]) => Promise<void>;\n submitFilterUpdate: () => Promise<void>;\n\n // === RESULTS AND SORTING ===\n setResultsMode: (mode: ResultsMode) => Promise<void>;\n setSortBy: (sortBy: SortBy) => Promise<void>;\n\n // === QUESTIONNAIRE ===\n setResolvedQuestionnaireValues: (name: string, values: string[]) => Promise<void>;\n\n // === UTILITY METHODS ===\n getUnitState: (unitId: string) => {\n isFavorite: boolean;\n viewedDate: string;\n };\n getResultsUrl: () => Promise<string | null>;\n getCurrentProperty: () => Promise<UserPropertyState | null>;\n getPropertyData: (propertyId?: string) => Promise<UserPropertyState | null>;\n\n // === INTERNAL ===\n _hydrate: () => Promise<void>;\n _initialize: () => Promise<void>;\n}\n\n/**\n * @deprecated For new apps, use `createStructuredStore` from `./structured-store`.\n * This flat adapter remains for migration/advanced cases.\n */\nexport function createZustandUnifiedStore(options?: {\n onFilterUpdate?: (apiParams: QueryParams) => void;\n}) {\n return (set: any, get: any): ZustandUnifiedStoreState => {\n // Helper to update local state after ORM operations\n const syncState = async () => {\n const ormState = await store.getFullState();\n set({\n properties: ormState.properties,\n currentPropertyId: ormState.currentPropertyId,\n currentPropertySlug: ormState.currentPropertySlug,\n hasPreviouslySearched: ormState.hasPreviouslySearched,\n unitResults: ormState.unitResults,\n filters: ormState.filters,\n tempFilters: ormState.tempFilters,\n apiFilters: ormState.apiFilters,\n resultsMode: ormState.resultsMode,\n resolvedQuestionnaireValues: ormState.resolvedQuestionnaireValues,\n sortBy: ormState.sortBy,\n });\n };\n\n // Helper to notify of filter updates\n const notifyFilterUpdate = async () => {\n if (options?.onFilterUpdate) {\n const apiFilters = (await store.getFullState()).apiFilters;\n options.onFilterUpdate(apiFilters);\n }\n };\n\n return {\n // Initial state\n properties: {},\n currentPropertyId: null,\n currentPropertySlug: null,\n hasPreviouslySearched: [],\n unitResults: [],\n filters: {\n date_availability: undefined,\n qty_bedrooms: undefined,\n base_price: undefined,\n highlights: undefined,\n },\n tempFilters: {\n date_availability: undefined,\n qty_bedrooms: undefined,\n base_price: undefined,\n highlights: undefined,\n },\n apiFilters: {\n limit: 10,\n page: 1,\n sortBy: \"relevance\",\n },\n resultsMode: \"all\",\n resolvedQuestionnaireValues: {},\n sortBy: \"relevance\",\n filtersLoaded: false,\n\n // === PROPERTY OPERATIONS ===\n async initializeProperty(propertyId, slug) {\n await store.initializeProperty(propertyId, slug);\n await syncState();\n },\n\n async setCurrentProperty(propertyId, slug) {\n await store.setCurrentProperty(propertyId, slug);\n set({\n currentPropertyId: propertyId,\n ...(slug && { currentPropertySlug: slug })\n });\n },\n\n async setCurrentPropertySlug(slug) {\n await store.setCurrentPropertySlug(slug);\n set({ currentPropertySlug: slug });\n },\n\n async setHasPreviouslySearched(slug) {\n await store.setHasPreviouslySearched(slug);\n await syncState();\n },\n\n async setFavoriteUnitIds(unitIds) {\n await store.setFavoriteUnitIds(unitIds);\n await syncState();\n },\n\n async toggleFavorite(unitId) {\n await store.toggleFavorite(unitId);\n await syncState();\n },\n\n async markUnitAsViewed(unitId, slug) {\n await store.markUnitAsViewed(unitId, slug);\n await syncState();\n },\n\n async setTourContactedOn() {\n await store.setTourContactedOn();\n await syncState();\n },\n\n getTourContactedOn: store.getTourContactedOn.bind(store),\n\n async setQuestionnaireResults(results) {\n await store.setQuestionnaireResults(results);\n await syncState();\n },\n\n async setTourContactData(data) {\n await store.setTourContactData(data);\n await syncState();\n },\n\n async setUnitResults(units) {\n await store.setUnitResults(units);\n await syncState();\n },\n\n async clearUnitResults() {\n await store.clearUnitResults();\n await syncState();\n },\n\n\n // === FILTER OPERATIONS ===\n async setFilters(filters) {\n await store.setFilters(filters);\n const state = get();\n set({ filters: { ...state.filters, ...filters } });\n },\n\n async setTempFilters(filters) {\n await store.setTempFilters(filters);\n const state = get();\n set({ tempFilters: { ...state.tempFilters, ...filters } });\n },\n\n async setFiltersToDefault() {\n await store.setFiltersToDefault();\n const defaultFilters = {\n date_availability: undefined,\n qty_bedrooms: undefined,\n base_price: undefined,\n highlights: undefined,\n };\n set({ filters: defaultFilters });\n },\n\n async setApiFilters(filters) {\n await store.setApiFilters(filters);\n const state = get();\n set({ apiFilters: { ...state.apiFilters, ...filters } });\n },\n\n async handleTempFilterChange(key, value) {\n await store.handleTempFilterChange(key, value);\n const state = get();\n set({ tempFilters: { ...state.tempFilters, [key]: value } });\n },\n\n async submitFilterUpdate() {\n await store.submitFilterUpdate();\n await syncState();\n await notifyFilterUpdate();\n },\n\n // === RESULTS AND SORTING ===\n async setResultsMode(mode) {\n await store.setResultsMode(mode);\n set({ resultsMode: mode });\n },\n\n async setSortBy(sortBy) {\n await store.setSortBy(sortBy);\n set({ sortBy });\n },\n\n // === QUESTIONNAIRE ===\n async setResolvedQuestionnaireValues(name, values) {\n await store.setResolvedQuestionnaireValues(name, values);\n const state = get();\n set({\n resolvedQuestionnaireValues: {\n ...state.resolvedQuestionnaireValues,\n [name]: values,\n }\n });\n },\n\n // === UTILITY METHODS ===\n getUnitState(unitId: string) {\n const state = get();\n const property = state.currentPropertyId ? state.properties[state.currentPropertyId] : null;\n\n return {\n isFavorite: property?.favoritedUnits.includes(unitId) ?? false,\n viewedDate:\n property?.viewedUnits.find((u: any) => u.unitId === unitId)?.viewedDate ?? \"\",\n };\n },\n\n getResultsUrl: store.getResultsUrl.bind(store),\n getCurrentProperty: store.getCurrentProperty.bind(store),\n getPropertyData: store.getPropertyData.bind(store),\n\n // === INTERNAL ===\n async _hydrate() {\n await syncState();\n },\n\n async _initialize() {\n await store.initialize();\n await syncState();\n set({ filtersLoaded: true });\n },\n };\n };\n}\n\n// Helper hook factory for unit state\nexport function createUseUnitState() {\n return (useStore: any) => (unitId: string) =>\n useStore((state: ZustandUnifiedStoreState) => state.getUnitState(unitId));\n}\n\n// Export types for consuming apps\nexport type { UnitData, UserPropertyState, Filters, QueryParams, ResultsMode, SortBy, TourContactData, Unit } from \"../schema\";\n\n// Intentionally no alias exports in vNext; use `createStructuredStore` or `createZustandUnifiedStore` explicitly.\n"],"names":["createZustandUnifiedStore","options","set","get","syncState","ormState","store","notifyFilterUpdate","apiFilters","propertyId","slug","unitIds","unitId","results","data","units","filters","state","key","value","mode","sortBy","name","values","property","_a","u","createUseUnitState","useStore"],"mappings":"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"}
|
|
@@ -16,6 +16,7 @@ export interface ZustandUnifiedStoreState {
|
|
|
16
16
|
setCurrentProperty: (propertyId: string, slug?: string) => Promise<void>;
|
|
17
17
|
setCurrentPropertySlug: (slug: string) => Promise<void>;
|
|
18
18
|
setHasPreviouslySearched: (slug: string) => Promise<void>;
|
|
19
|
+
setFavoriteUnitIds: (unitIds: string[]) => Promise<void>;
|
|
19
20
|
toggleFavorite: (unitId: string) => Promise<void>;
|
|
20
21
|
markUnitAsViewed: (unitId: string, slug: string) => Promise<void>;
|
|
21
22
|
setTourContactedOn: () => Promise<void>;
|
|
@@ -66,6 +66,9 @@ function y(l) {
|
|
|
66
66
|
async setHasPreviouslySearched(t) {
|
|
67
67
|
await e.setHasPreviouslySearched(t), await r();
|
|
68
68
|
},
|
|
69
|
+
async setFavoriteUnitIds(t) {
|
|
70
|
+
await e.setFavoriteUnitIds(t), await r();
|
|
71
|
+
},
|
|
69
72
|
async toggleFavorite(t) {
|
|
70
73
|
await e.toggleFavorite(t), await r();
|
|
71
74
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"zustand-store.mjs","sources":["../../src/adapters/zustand-store.ts"],"sourcesContent":["/**\n * Zustand adapter (flat API)\n *\n * This file exposes a flat, unified Zustand store that mirrors the underlying\n * ORM store and keeps React state in sync. It is the low-level bridge.\n *\n * For a friendlier, domain-grouped API, use `createStructuredStore` from\n * `./structured-store`, which wraps this adapter and exposes nested actions\n * like `property.unit.favorites.toggle`, `filters.set`, etc.\n */\nimport { store } from \"../stores/store\";\nimport type { UnifiedStoreData, UserPropertyState, Filters, QueryParams, ResultsMode, SortBy, TourContactData, Unit } from \"../schema\";\n\n// Unified Zustand store interface\nexport interface ZustandUnifiedStoreState {\n // Property data\n properties: Record<string, UserPropertyState>;\n currentPropertyId: string | null;\n currentPropertySlug: string | null;\n hasPreviouslySearched: string[];\n\n // App data\n unitResults: Unit[];\n filters: Filters;\n tempFilters: Filters;\n apiFilters: QueryParams;\n resultsMode: ResultsMode;\n resolvedQuestionnaireValues: Record<string, string[]>;\n sortBy: SortBy;\n filtersLoaded: boolean;\n\n // === PROPERTY OPERATIONS ===\n initializeProperty: (propertyId: string, slug: string) => Promise<void>;\n setCurrentProperty: (propertyId: string, slug?: string) => Promise<void>;\n setCurrentPropertySlug: (slug: string) => Promise<void>;\n setHasPreviouslySearched: (slug: string) => Promise<void>;\n toggleFavorite: (unitId: string) => Promise<void>;\n markUnitAsViewed: (unitId: string, slug: string) => Promise<void>;\n setTourContactedOn: () => Promise<void>;\n getTourContactedOn: () => Promise<string | null>;\n setQuestionnaireResults: (results: unknown) => Promise<void>;\n setTourContactData: (data: TourContactData) => Promise<void>;\n setUnitResults: (units: unknown) => Promise<void>;\n clearUnitResults: () => Promise<void>;\n\n\n // === FILTER OPERATIONS ===\n setFilters: (filters: Partial<Filters>) => Promise<void>;\n setTempFilters: (filters: Partial<Filters>) => Promise<void>;\n setFiltersToDefault: () => Promise<void>;\n setApiFilters: (filters: Partial<QueryParams>) => Promise<void>;\n handleTempFilterChange: <K extends keyof Filters>(key: K, value: Filters[K]) => Promise<void>;\n submitFilterUpdate: () => Promise<void>;\n\n // === RESULTS AND SORTING ===\n setResultsMode: (mode: ResultsMode) => Promise<void>;\n setSortBy: (sortBy: SortBy) => Promise<void>;\n\n // === QUESTIONNAIRE ===\n setResolvedQuestionnaireValues: (name: string, values: string[]) => Promise<void>;\n\n // === UTILITY METHODS ===\n getUnitState: (unitId: string) => {\n isFavorite: boolean;\n viewedDate: string;\n };\n getResultsUrl: () => Promise<string | null>;\n getCurrentProperty: () => Promise<UserPropertyState | null>;\n getPropertyData: (propertyId?: string) => Promise<UserPropertyState | null>;\n\n // === INTERNAL ===\n _hydrate: () => Promise<void>;\n _initialize: () => Promise<void>;\n}\n\n/**\n * @deprecated For new apps, use `createStructuredStore` from `./structured-store`.\n * This flat adapter remains for migration/advanced cases.\n */\nexport function createZustandUnifiedStore(options?: {\n onFilterUpdate?: (apiParams: QueryParams) => void;\n}) {\n return (set: any, get: any): ZustandUnifiedStoreState => {\n // Helper to update local state after ORM operations\n const syncState = async () => {\n const ormState = await store.getFullState();\n set({\n properties: ormState.properties,\n currentPropertyId: ormState.currentPropertyId,\n currentPropertySlug: ormState.currentPropertySlug,\n hasPreviouslySearched: ormState.hasPreviouslySearched,\n unitResults: ormState.unitResults,\n filters: ormState.filters,\n tempFilters: ormState.tempFilters,\n apiFilters: ormState.apiFilters,\n resultsMode: ormState.resultsMode,\n resolvedQuestionnaireValues: ormState.resolvedQuestionnaireValues,\n sortBy: ormState.sortBy,\n });\n };\n\n // Helper to notify of filter updates\n const notifyFilterUpdate = async () => {\n if (options?.onFilterUpdate) {\n const apiFilters = (await store.getFullState()).apiFilters;\n options.onFilterUpdate(apiFilters);\n }\n };\n\n return {\n // Initial state\n properties: {},\n currentPropertyId: null,\n currentPropertySlug: null,\n hasPreviouslySearched: [],\n unitResults: [],\n filters: {\n date_availability: undefined,\n qty_bedrooms: undefined,\n base_price: undefined,\n highlights: undefined,\n },\n tempFilters: {\n date_availability: undefined,\n qty_bedrooms: undefined,\n base_price: undefined,\n highlights: undefined,\n },\n apiFilters: {\n limit: 10,\n page: 1,\n sortBy: \"relevance\",\n },\n resultsMode: \"all\",\n resolvedQuestionnaireValues: {},\n sortBy: \"relevance\",\n filtersLoaded: false,\n\n // === PROPERTY OPERATIONS ===\n async initializeProperty(propertyId, slug) {\n await store.initializeProperty(propertyId, slug);\n await syncState();\n },\n\n async setCurrentProperty(propertyId, slug) {\n await store.setCurrentProperty(propertyId, slug);\n set({\n currentPropertyId: propertyId,\n ...(slug && { currentPropertySlug: slug })\n });\n },\n\n async setCurrentPropertySlug(slug) {\n await store.setCurrentPropertySlug(slug);\n set({ currentPropertySlug: slug });\n },\n\n async setHasPreviouslySearched(slug) {\n await store.setHasPreviouslySearched(slug);\n await syncState();\n },\n\n async toggleFavorite(unitId) {\n await store.toggleFavorite(unitId);\n await syncState();\n },\n\n async markUnitAsViewed(unitId, slug) {\n await store.markUnitAsViewed(unitId, slug);\n await syncState();\n },\n\n async setTourContactedOn() {\n await store.setTourContactedOn();\n await syncState();\n },\n\n getTourContactedOn: store.getTourContactedOn.bind(store),\n\n async setQuestionnaireResults(results) {\n await store.setQuestionnaireResults(results);\n await syncState();\n },\n\n async setTourContactData(data) {\n await store.setTourContactData(data);\n await syncState();\n },\n\n async setUnitResults(units) {\n await store.setUnitResults(units);\n await syncState();\n },\n\n async clearUnitResults() {\n await store.clearUnitResults();\n await syncState();\n },\n\n\n // === FILTER OPERATIONS ===\n async setFilters(filters) {\n await store.setFilters(filters);\n const state = get();\n set({ filters: { ...state.filters, ...filters } });\n },\n\n async setTempFilters(filters) {\n await store.setTempFilters(filters);\n const state = get();\n set({ tempFilters: { ...state.tempFilters, ...filters } });\n },\n\n async setFiltersToDefault() {\n await store.setFiltersToDefault();\n const defaultFilters = {\n date_availability: undefined,\n qty_bedrooms: undefined,\n base_price: undefined,\n highlights: undefined,\n };\n set({ filters: defaultFilters });\n },\n\n async setApiFilters(filters) {\n await store.setApiFilters(filters);\n const state = get();\n set({ apiFilters: { ...state.apiFilters, ...filters } });\n },\n\n async handleTempFilterChange(key, value) {\n await store.handleTempFilterChange(key, value);\n const state = get();\n set({ tempFilters: { ...state.tempFilters, [key]: value } });\n },\n\n async submitFilterUpdate() {\n await store.submitFilterUpdate();\n await syncState();\n await notifyFilterUpdate();\n },\n\n // === RESULTS AND SORTING ===\n async setResultsMode(mode) {\n await store.setResultsMode(mode);\n set({ resultsMode: mode });\n },\n\n async setSortBy(sortBy) {\n await store.setSortBy(sortBy);\n set({ sortBy });\n },\n\n // === QUESTIONNAIRE ===\n async setResolvedQuestionnaireValues(name, values) {\n await store.setResolvedQuestionnaireValues(name, values);\n const state = get();\n set({\n resolvedQuestionnaireValues: {\n ...state.resolvedQuestionnaireValues,\n [name]: values,\n }\n });\n },\n\n // === UTILITY METHODS ===\n getUnitState(unitId: string) {\n const state = get();\n const property = state.currentPropertyId ? state.properties[state.currentPropertyId] : null;\n\n return {\n isFavorite: property?.favoritedUnits.includes(unitId) ?? false,\n viewedDate:\n property?.viewedUnits.find((u: any) => u.unitId === unitId)?.viewedDate ?? \"\",\n };\n },\n\n getResultsUrl: store.getResultsUrl.bind(store),\n getCurrentProperty: store.getCurrentProperty.bind(store),\n getPropertyData: store.getPropertyData.bind(store),\n\n // === INTERNAL ===\n async _hydrate() {\n await syncState();\n },\n\n async _initialize() {\n await store.initialize();\n await syncState();\n set({ filtersLoaded: true });\n },\n };\n };\n}\n\n// Helper hook factory for unit state\nexport function createUseUnitState() {\n return (useStore: any) => (unitId: string) =>\n useStore((state: ZustandUnifiedStoreState) => state.getUnitState(unitId));\n}\n\n// Export types for consuming apps\nexport type { UnitData, UserPropertyState, Filters, QueryParams, ResultsMode, SortBy, TourContactData, Unit } from \"../schema\";\n\n// Intentionally no alias exports in vNext; use `createStructuredStore` or `createZustandUnifiedStore` explicitly.\n"],"names":["createZustandUnifiedStore","options","set","get","syncState","ormState","store","notifyFilterUpdate","apiFilters","propertyId","slug","unitId","results","data","units","filters","state","key","value","mode","sortBy","name","values","property","_a","u","createUseUnitState","useStore"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"zustand-store.mjs","sources":["../../src/adapters/zustand-store.ts"],"sourcesContent":["/**\n * Zustand adapter (flat API)\n *\n * This file exposes a flat, unified Zustand store that mirrors the underlying\n * ORM store and keeps React state in sync. It is the low-level bridge.\n *\n * For a friendlier, domain-grouped API, use `createStructuredStore` from\n * `./structured-store`, which wraps this adapter and exposes nested actions\n * like `property.unit.favorites.toggle`, `filters.set`, etc.\n */\nimport { store } from \"../stores/store\";\nimport type { UnifiedStoreData, UserPropertyState, Filters, QueryParams, ResultsMode, SortBy, TourContactData, Unit } from \"../schema\";\n\n// Unified Zustand store interface\nexport interface ZustandUnifiedStoreState {\n // Property data\n properties: Record<string, UserPropertyState>;\n currentPropertyId: string | null;\n currentPropertySlug: string | null;\n hasPreviouslySearched: string[];\n\n // App data\n unitResults: Unit[];\n filters: Filters;\n tempFilters: Filters;\n apiFilters: QueryParams;\n resultsMode: ResultsMode;\n resolvedQuestionnaireValues: Record<string, string[]>;\n sortBy: SortBy;\n filtersLoaded: boolean;\n\n // === PROPERTY OPERATIONS ===\n initializeProperty: (propertyId: string, slug: string) => Promise<void>;\n setCurrentProperty: (propertyId: string, slug?: string) => Promise<void>;\n setCurrentPropertySlug: (slug: string) => Promise<void>;\n setHasPreviouslySearched: (slug: string) => Promise<void>;\n setFavoriteUnitIds: (unitIds: string[]) => Promise<void>;\n toggleFavorite: (unitId: string) => Promise<void>;\n markUnitAsViewed: (unitId: string, slug: string) => Promise<void>;\n setTourContactedOn: () => Promise<void>;\n getTourContactedOn: () => Promise<string | null>;\n setQuestionnaireResults: (results: unknown) => Promise<void>;\n setTourContactData: (data: TourContactData) => Promise<void>;\n setUnitResults: (units: unknown) => Promise<void>;\n clearUnitResults: () => Promise<void>;\n\n\n // === FILTER OPERATIONS ===\n setFilters: (filters: Partial<Filters>) => Promise<void>;\n setTempFilters: (filters: Partial<Filters>) => Promise<void>;\n setFiltersToDefault: () => Promise<void>;\n setApiFilters: (filters: Partial<QueryParams>) => Promise<void>;\n handleTempFilterChange: <K extends keyof Filters>(key: K, value: Filters[K]) => Promise<void>;\n submitFilterUpdate: () => Promise<void>;\n\n // === RESULTS AND SORTING ===\n setResultsMode: (mode: ResultsMode) => Promise<void>;\n setSortBy: (sortBy: SortBy) => Promise<void>;\n\n // === QUESTIONNAIRE ===\n setResolvedQuestionnaireValues: (name: string, values: string[]) => Promise<void>;\n\n // === UTILITY METHODS ===\n getUnitState: (unitId: string) => {\n isFavorite: boolean;\n viewedDate: string;\n };\n getResultsUrl: () => Promise<string | null>;\n getCurrentProperty: () => Promise<UserPropertyState | null>;\n getPropertyData: (propertyId?: string) => Promise<UserPropertyState | null>;\n\n // === INTERNAL ===\n _hydrate: () => Promise<void>;\n _initialize: () => Promise<void>;\n}\n\n/**\n * @deprecated For new apps, use `createStructuredStore` from `./structured-store`.\n * This flat adapter remains for migration/advanced cases.\n */\nexport function createZustandUnifiedStore(options?: {\n onFilterUpdate?: (apiParams: QueryParams) => void;\n}) {\n return (set: any, get: any): ZustandUnifiedStoreState => {\n // Helper to update local state after ORM operations\n const syncState = async () => {\n const ormState = await store.getFullState();\n set({\n properties: ormState.properties,\n currentPropertyId: ormState.currentPropertyId,\n currentPropertySlug: ormState.currentPropertySlug,\n hasPreviouslySearched: ormState.hasPreviouslySearched,\n unitResults: ormState.unitResults,\n filters: ormState.filters,\n tempFilters: ormState.tempFilters,\n apiFilters: ormState.apiFilters,\n resultsMode: ormState.resultsMode,\n resolvedQuestionnaireValues: ormState.resolvedQuestionnaireValues,\n sortBy: ormState.sortBy,\n });\n };\n\n // Helper to notify of filter updates\n const notifyFilterUpdate = async () => {\n if (options?.onFilterUpdate) {\n const apiFilters = (await store.getFullState()).apiFilters;\n options.onFilterUpdate(apiFilters);\n }\n };\n\n return {\n // Initial state\n properties: {},\n currentPropertyId: null,\n currentPropertySlug: null,\n hasPreviouslySearched: [],\n unitResults: [],\n filters: {\n date_availability: undefined,\n qty_bedrooms: undefined,\n base_price: undefined,\n highlights: undefined,\n },\n tempFilters: {\n date_availability: undefined,\n qty_bedrooms: undefined,\n base_price: undefined,\n highlights: undefined,\n },\n apiFilters: {\n limit: 10,\n page: 1,\n sortBy: \"relevance\",\n },\n resultsMode: \"all\",\n resolvedQuestionnaireValues: {},\n sortBy: \"relevance\",\n filtersLoaded: false,\n\n // === PROPERTY OPERATIONS ===\n async initializeProperty(propertyId, slug) {\n await store.initializeProperty(propertyId, slug);\n await syncState();\n },\n\n async setCurrentProperty(propertyId, slug) {\n await store.setCurrentProperty(propertyId, slug);\n set({\n currentPropertyId: propertyId,\n ...(slug && { currentPropertySlug: slug })\n });\n },\n\n async setCurrentPropertySlug(slug) {\n await store.setCurrentPropertySlug(slug);\n set({ currentPropertySlug: slug });\n },\n\n async setHasPreviouslySearched(slug) {\n await store.setHasPreviouslySearched(slug);\n await syncState();\n },\n\n async setFavoriteUnitIds(unitIds) {\n await store.setFavoriteUnitIds(unitIds);\n await syncState();\n },\n\n async toggleFavorite(unitId) {\n await store.toggleFavorite(unitId);\n await syncState();\n },\n\n async markUnitAsViewed(unitId, slug) {\n await store.markUnitAsViewed(unitId, slug);\n await syncState();\n },\n\n async setTourContactedOn() {\n await store.setTourContactedOn();\n await syncState();\n },\n\n getTourContactedOn: store.getTourContactedOn.bind(store),\n\n async setQuestionnaireResults(results) {\n await store.setQuestionnaireResults(results);\n await syncState();\n },\n\n async setTourContactData(data) {\n await store.setTourContactData(data);\n await syncState();\n },\n\n async setUnitResults(units) {\n await store.setUnitResults(units);\n await syncState();\n },\n\n async clearUnitResults() {\n await store.clearUnitResults();\n await syncState();\n },\n\n\n // === FILTER OPERATIONS ===\n async setFilters(filters) {\n await store.setFilters(filters);\n const state = get();\n set({ filters: { ...state.filters, ...filters } });\n },\n\n async setTempFilters(filters) {\n await store.setTempFilters(filters);\n const state = get();\n set({ tempFilters: { ...state.tempFilters, ...filters } });\n },\n\n async setFiltersToDefault() {\n await store.setFiltersToDefault();\n const defaultFilters = {\n date_availability: undefined,\n qty_bedrooms: undefined,\n base_price: undefined,\n highlights: undefined,\n };\n set({ filters: defaultFilters });\n },\n\n async setApiFilters(filters) {\n await store.setApiFilters(filters);\n const state = get();\n set({ apiFilters: { ...state.apiFilters, ...filters } });\n },\n\n async handleTempFilterChange(key, value) {\n await store.handleTempFilterChange(key, value);\n const state = get();\n set({ tempFilters: { ...state.tempFilters, [key]: value } });\n },\n\n async submitFilterUpdate() {\n await store.submitFilterUpdate();\n await syncState();\n await notifyFilterUpdate();\n },\n\n // === RESULTS AND SORTING ===\n async setResultsMode(mode) {\n await store.setResultsMode(mode);\n set({ resultsMode: mode });\n },\n\n async setSortBy(sortBy) {\n await store.setSortBy(sortBy);\n set({ sortBy });\n },\n\n // === QUESTIONNAIRE ===\n async setResolvedQuestionnaireValues(name, values) {\n await store.setResolvedQuestionnaireValues(name, values);\n const state = get();\n set({\n resolvedQuestionnaireValues: {\n ...state.resolvedQuestionnaireValues,\n [name]: values,\n }\n });\n },\n\n // === UTILITY METHODS ===\n getUnitState(unitId: string) {\n const state = get();\n const property = state.currentPropertyId ? state.properties[state.currentPropertyId] : null;\n\n return {\n isFavorite: property?.favoritedUnits.includes(unitId) ?? false,\n viewedDate:\n property?.viewedUnits.find((u: any) => u.unitId === unitId)?.viewedDate ?? \"\",\n };\n },\n\n getResultsUrl: store.getResultsUrl.bind(store),\n getCurrentProperty: store.getCurrentProperty.bind(store),\n getPropertyData: store.getPropertyData.bind(store),\n\n // === INTERNAL ===\n async _hydrate() {\n await syncState();\n },\n\n async _initialize() {\n await store.initialize();\n await syncState();\n set({ filtersLoaded: true });\n },\n };\n };\n}\n\n// Helper hook factory for unit state\nexport function createUseUnitState() {\n return (useStore: any) => (unitId: string) =>\n useStore((state: ZustandUnifiedStoreState) => state.getUnitState(unitId));\n}\n\n// Export types for consuming apps\nexport type { UnitData, UserPropertyState, Filters, QueryParams, ResultsMode, SortBy, TourContactData, Unit } from \"../schema\";\n\n// Intentionally no alias exports in vNext; use `createStructuredStore` or `createZustandUnifiedStore` explicitly.\n"],"names":["createZustandUnifiedStore","options","set","get","syncState","ormState","store","notifyFilterUpdate","apiFilters","propertyId","slug","unitIds","unitId","results","data","units","filters","state","key","value","mode","sortBy","name","values","property","_a","u","createUseUnitState","useStore"],"mappings":"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"}
|
package/dist/stores/store.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const y=require("../storage.cjs"),c=require("../schema.cjs"),S=require("../validation.cjs"),P=require("../features/filters/transformers.cjs"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const y=require("../storage.cjs"),c=require("../schema.cjs"),S=require("../validation.cjs"),P=require("../features/filters/transformers.cjs"),h={date_availability:void 0,qty_bedrooms:void 0,base_price:void 0,highlights:void 0},f={properties:{},currentPropertyId:null,currentPropertySlug:null,hasPreviouslySearched:[],unitResults:[],filters:h,tempFilters:h,apiFilters:{limit:10,page:1,sortBy:"relevance"},resultsMode:"all",resolvedQuestionnaireValues:{},sortBy:"relevance"};class w{async getState(){const t=await y.kvGet("app");if(!t)return f;const e={...f,...t,properties:t.properties??{},unitResults:t.unitResults??[],currentPropertyId:t.currentPropertyId==null?null:String(t.currentPropertyId),currentPropertySlug:t.currentPropertySlug??null,hasPreviouslySearched:Array.isArray(t.hasPreviouslySearched)?t.hasPreviouslySearched.map(String):[]},r=c.UnifiedStoreDataSchema.safeParse(e);if(r.success)return r.data;const i=Object.entries(e.properties??{}).reduce((p,[u,l])=>{const d=c.UserPropertyStateSchema.safeParse(l);return d.success&&(p[u]=d.data),p},{}),s=(Array.isArray(e.unitResults)?e.unitResults:e.unitResults&&typeof e.unitResults=="object"?Object.values(e.unitResults):[]).reduce((p,u)=>{const l=c.UnitSchema.safeParse(u);return l.success&&p.push(l.data),p},[]),a={...e,properties:i,unitResults:s},o=c.UnifiedStoreDataSchema.safeParse(a);return o.success?o.data:f}async setState(t){const e=await this.getState(),r=t(e),i=c.UnifiedStoreDataSchema.parse(r);await y.kvSet("app",i)}async waitForCurrentProperty(t=1e3){const e=Date.now()+t;for(;Date.now()<e;){const n=await this.getState(),s=n.currentPropertyId;if(s&&n.properties[s])return s;await new Promise(a=>setTimeout(a,16))}const r=await this.getState(),i=r.currentPropertyId;if(i&&r.properties[i])return i;throw new Error("UnifiedStore: current property was not initialized in time")}async initializeProperty(t,e){const r=String(t);await this.setState(i=>i.properties&&i.properties[r]?{...i,currentPropertyId:r,currentPropertySlug:e}:{...i,currentPropertyId:r,currentPropertySlug:e,properties:{...i.properties,[r]:{id:r,slug:e,favoritedUnits:[],tourContactedOn:null,viewedUnits:[],questionnaireResults:null,tourContactData:null}}})}async setUnitResults(t,e){const r=e??c.UnitSchema,i=[];(Array.isArray(t)?t:t&&typeof t=="object"?Object.values(t):[]).forEach((s,a)=>{const o=S.validate(r,s,`unitResults[${a}]`);o&&i.push(o)}),await this.setState(s=>({...s,unitResults:i}))}async clearUnitResults(){await this.setState(t=>({...t,unitResults:[]}))}async setPropertyData(t,e,r){const i=String(t),n=r??c.PropertySchema;await this.setState(s=>{const a=s.properties[i];if(!a)return s;const o=S.validate(n,e,`properties.${i}.data`);return o?{...s,properties:{...s.properties,[i]:{...a,data:o}}}:s})}async mergePropertyData(t,e,r){const i=String(t),n=r??c.PropertySchema;await this.setState(s=>{const a=s.properties[i];if(!a)return s;const o=a.data;if(!o){const d=S.validate(n,e,`properties.${i}.data`);return d?{...s,properties:{...s.properties,[i]:{...a,data:d}}}:s}const p=n.partial(),u=S.validate(p,e,`properties.${i}.data.partial`);if(!u)return s;const l=S.validate(n,{...o,...u},`properties.${i}.data`);return l?{...s,properties:{...s.properties,[i]:{...a,data:l}}}:s})}async upsertPropertyFromApi(t,e){const i=(e??c.PropertySchema).parse(t),n=i.id??i.propertyId;if(n==null)throw new Error("upsertPropertyFromApi: property id is required");const s=String(n),a=i.slug??void 0;await this.setState(o=>{const p=o.properties[s],u=p?{...p,...a?{slug:a}:{},data:i}:{id:s,slug:a??"",favoritedUnits:[],tourContactedOn:null,viewedUnits:[],questionnaireResults:null,tourContactData:null,data:i};return{...o,properties:{...o.properties,[s]:u}}})}async setCurrentProperty(t,e){const r=String(t);await this.setState(i=>({...i,currentPropertyId:r,currentPropertySlug:e||i.currentPropertySlug}))}async setCurrentPropertySlug(t){await this.setState(e=>({...e,currentPropertySlug:t}))}async setHasPreviouslySearched(t){await this.setState(e=>({...e,hasPreviouslySearched:Array.from(new Set([...e.hasPreviouslySearched,t]))}))}async setFavoriteUnitIds(t){await this.setState(e=>{const r=e.currentPropertyId;if(!r)return e;const i=e.properties[r];return i?{...e,properties:{...e.properties,[r]:{...i,favoritedUnits:t}}}:e})}async toggleFavorite(t){await this.setState(e=>{const r=e.currentPropertyId;if(!r)return e;const i=e.properties[r];if(!i)return e;const s=i.favoritedUnits.includes(t)?i.favoritedUnits.filter(a=>a!==t):[...i.favoritedUnits,t];return{...e,properties:{...e.properties,[r]:{...i,favoritedUnits:s}}}})}async markUnitAsViewed(t,e){const r=`https://${e}`;window.open(r,"_blank","noopener,noreferrer");const i=new Date,n=`${String(i.getMonth()+1).padStart(2,"0")}/${String(i.getDate()).padStart(2,"0")}`;await this.setState(s=>{const a=s.currentPropertyId;if(!a)return s;const o=s.properties[a];if(!o)return s;const p=[...o.viewedUnits.filter(u=>u.unitId!==t),{unitId:t,viewedDate:n}];return{...s,properties:{...s.properties,[a]:{...o,viewedUnits:p}}}})}async setTourContactedOn(){await this.setState(t=>{const e=t.currentPropertyId;if(!e)return t;const r=t.properties[e];return r?{...t,properties:{...t.properties,[e]:{...r,tourContactedOn:new Date().toISOString()}}}:t})}async getTourContactedOn(){var r;const t=await this.getState(),e=t.currentPropertyId;return e?((r=t.properties[e])==null?void 0:r.tourContactedOn)??null:null}async setQuestionnaireResults(t){await this.setState(e=>{const r=e.currentPropertyId;if(!r)return e;const i=e.properties[r];return i?{...e,properties:{...e.properties,[r]:{...i,questionnaireResults:t}}}:e})}async setTourContactData(t){const e=await this.waitForCurrentProperty();await this.setState(r=>{const i=r.properties[e];return i?{...r,properties:{...r.properties,[e]:{...i,tourContactData:t}}}:r})}async setFilters(t){await this.setState(e=>({...e,filters:{...e.filters,...t}}))}async setTempFilters(t){await this.setState(e=>({...e,tempFilters:{...e.tempFilters,...t}}))}async setFiltersToDefault(){await this.setState(t=>({...t,filters:h}))}async setApiFilters(t){await this.setState(e=>({...e,apiFilters:{...e.apiFilters,...t}}))}async handleTempFilterChange(t,e){await this.setState(r=>({...r,tempFilters:{...r.tempFilters,[t]:e}}))}async submitFilterUpdate(){await this.setState(t=>{const e=P.transformFiltersToUnitsSearchParams({...t.filters,limit:t.apiFilters.limit,page:t.apiFilters.page,sortBy:t.sortBy},{defaultLimit:t.apiFilters.limit,defaultPage:t.apiFilters.page,defaultSort:t.sortBy});return{...t,apiFilters:e}})}async setResultsMode(t){await this.setState(e=>({...e,resultsMode:t}))}async setSortBy(t){await this.setState(e=>({...e,sortBy:t}))}async setResolvedQuestionnaireValues(t,e){await this.setState(r=>({...r,resolvedQuestionnaireValues:{...r.resolvedQuestionnaireValues,[t]:e}}))}async getVisitorUUID(){const t=await y.kvGet("user");return(t==null?void 0:t.visitor_uuid)??null}async setVisitorUUID(t){const e=await y.kvGet("user"),r=e!==null&&typeof e=="object"&&!Array.isArray(e)?e:{};await y.kvSet("user",{...r,visitor_uuid:t})}async getUnitState(t){var i;const e=await this.getState(),r=e.currentPropertyId?e.properties[e.currentPropertyId]:null;return{isFavorite:(r==null?void 0:r.favoritedUnits.includes(t))??!1,viewedDate:((i=r==null?void 0:r.viewedUnits.find(n=>n.unitId===t))==null?void 0:i.viewedDate)??""}}async getResultsUrl(){const t=await this.getState();return t.currentPropertySlug?`/${t.currentPropertySlug}/results`:null}async getCurrentProperty(){const t=await this.getState();return t.currentPropertyId?t.properties[t.currentPropertyId]??null:null}async getPropertyData(t){const e=await this.getState(),r=t==null?e.currentPropertyId:String(t);return r?e.properties[r]??null:null}async getFullState(){return this.getState()}async initialize(){await this.setState(t=>({...f,...t}))}}const v=new w;exports.Store=w;exports.UnifiedStore=w;exports.store=v;
|
|
2
2
|
//# sourceMappingURL=store.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.cjs","sources":["../../src/stores/store.ts"],"sourcesContent":["import { kvGet, kvSet } from \"../storage\";\nimport type { ZodObject, ZodType, ZodTypeAny } from \"zod\";\nimport {\n UnifiedStoreDataSchema,\n UserPropertyStateSchema,\n type UnifiedStoreData,\n type UserPropertyState,\n type Property,\n type Filters,\n type QueryParams,\n type ResultsMode,\n type SortBy,\n type TourContactData,\n type Unit,\n PropertySchema,\n TourContactDataSchema,\n UnitSchema,\n} from \"../schema\";\nimport { validate } from \"../validation\";\nimport { transformFiltersToUnitsSearchParams } from \"../features/filters/transformers\";\n\n// Default values\nconst defaultFilters: Filters = {\n date_availability: undefined,\n qty_bedrooms: undefined,\n base_price: undefined,\n highlights: undefined,\n};\n\nconst defaultUnifiedStoreData: UnifiedStoreData = {\n // Property data\n properties: {},\n currentPropertyId: null,\n currentPropertySlug: null,\n hasPreviouslySearched: [],\n\n // App data\n unitResults: [],\n filters: defaultFilters,\n tempFilters: defaultFilters,\n apiFilters: {\n limit: 10,\n page: 1,\n sortBy: \"relevance\",\n },\n resultsMode: \"all\",\n resolvedQuestionnaireValues: {},\n sortBy: \"relevance\",\n};\n\nconst toArray = (input: unknown): unknown[] => {\n if (input == null) return [];\n return Array.isArray(input) ? input : [input];\n};\n\nconst extractFilterValues = (value: unknown): unknown[] => {\n return toArray(value).flatMap(item => {\n if (item == null) return [];\n if (Array.isArray(item)) return item;\n if (typeof item === \"object\" && \"value\" in (item as any)) {\n const v = (item as any).value;\n return Array.isArray(v) ? v : v != null ? [v] : [];\n }\n return [item];\n });\n};\n\nconst toStringArray = (value: unknown): string[] =>\n extractFilterValues(value)\n .flatMap(v => (Array.isArray(v) ? v : [v]))\n .map(v => String(v))\n .map(v => v.trim())\n .filter(v => v.length > 0);\n\nconst toNumberArray = (value: unknown): number[] =>\n extractFilterValues(value)\n .map(v => {\n if (typeof v === \"number\" && Number.isFinite(v)) return v;\n const num = Number(v);\n return Number.isFinite(num) ? num : null;\n })\n .filter((v): v is number => v !== null);\n\nconst toNumberValue = (value: unknown): number | null => {\n if (value == null) return null;\n if (typeof value === \"number\") return Number.isFinite(value) ? value : null;\n if (typeof value === \"object\" && \"value\" in (value as any)) {\n return toNumberValue((value as any).value);\n }\n const num = Number(value);\n return Number.isFinite(num) ? num : null;\n};\n\n// Unified store class\nexport class UnifiedStore {\n /**\n * Resolves the persisted unified store snapshot, coercing legacy shapes into the latest schema\n * and sanitizing invalid entries where possible.\n */\n private async getState(): Promise<UnifiedStoreData> {\n const state = await kvGet<UnifiedStoreData>(\"app\");\n if (!state) {\n return defaultUnifiedStoreData;\n }\n\n const merged = {\n ...defaultUnifiedStoreData,\n ...state,\n properties: state.properties ?? {},\n unitResults: state.unitResults ?? [],\n currentPropertyId:\n state.currentPropertyId == null ? null : String(state.currentPropertyId),\n currentPropertySlug: state.currentPropertySlug ?? null,\n hasPreviouslySearched: Array.isArray(state.hasPreviouslySearched)\n ? state.hasPreviouslySearched.map(String)\n : [],\n };\n\n const parsed = UnifiedStoreDataSchema.safeParse(merged);\n if (parsed.success) return parsed.data;\n\n // Sanitize by dropping invalid property entries and unit results\n const sanitizedProperties = Object.entries(merged.properties ?? {}).reduce<\n Record<string, UserPropertyState>\n >((acc, [key, value]) => {\n const entry = UserPropertyStateSchema.safeParse(value);\n if (entry.success) acc[key] = entry.data;\n return acc;\n }, {});\n\n const rawUnitResults = Array.isArray(merged.unitResults)\n ? merged.unitResults\n : merged.unitResults && typeof merged.unitResults === \"object\"\n ? Object.values(merged.unitResults as Record<string, unknown>)\n : [];\n\n const sanitizedUnitResults = rawUnitResults.reduce<Unit[]>((acc, value) => {\n const entry = UnitSchema.safeParse(value);\n if (entry.success) acc.push(entry.data);\n return acc;\n }, []);\n\n const fallback = {\n ...merged,\n properties: sanitizedProperties,\n unitResults: sanitizedUnitResults,\n };\n\n const fallbackParsed = UnifiedStoreDataSchema.safeParse(fallback);\n return fallbackParsed.success ? fallbackParsed.data : defaultUnifiedStoreData;\n }\n\n /**\n * Applies an updater function to the current store state, validates the result, and persists it.\n *\n * @param updater - Pure function that maps the current state to the next state.\n */\n private async setState(updater: (state: UnifiedStoreData) => UnifiedStoreData): Promise<void> {\n const currentState = await this.getState();\n const newState = updater(currentState);\n const validatedState = UnifiedStoreDataSchema.parse(newState);\n await kvSet(\"app\", validatedState);\n }\n\n /**\n * Polls the persisted state until a current property pointer is available or the timeout elapses.\n *\n * @param timeoutMs - Maximum time in milliseconds to wait before failing.\n * @returns The active property ID once it becomes available.\n * @throws Error if the property pointer is not set before the timeout expires.\n */\n private async waitForCurrentProperty(timeoutMs = 1000): Promise<string> {\n const deadline = Date.now() + timeoutMs;\n\n while (Date.now() < deadline) {\n const state = await this.getState();\n const propertyId = state.currentPropertyId;\n if (propertyId && state.properties[propertyId]) return propertyId;\n\n await new Promise(resolve => setTimeout(resolve, 16));\n }\n\n const finalState = await this.getState();\n const propertyId = finalState.currentPropertyId;\n if (propertyId && finalState.properties[propertyId]) return propertyId;\n\n throw new Error(\"UnifiedStore: current property was not initialized in time\");\n }\n\n // === PROPERTY OPERATIONS ===\n\n /**\n * Ensures a property entry exists and registers it as the current property.\n *\n * @param propertyId - Identifier used to track the property.\n * @param slug - Canonical slug associated with the property.\n */\n async initializeProperty(propertyId: string | number, slug: string): Promise<void> {\n const id = String(propertyId);\n await this.setState(state => {\n if (state.properties && state.properties[id]) {\n return {\n ...state,\n currentPropertyId: id,\n currentPropertySlug: slug\n };\n }\n\n return {\n ...state,\n currentPropertyId: id,\n currentPropertySlug: slug,\n properties: {\n ...state.properties,\n [id]: {\n id,\n slug,\n favoritedUnits: [],\n tourContactedOn: null,\n viewedUnits: [],\n questionnaireResults: null,\n tourContactData: null,\n },\n },\n };\n });\n }\n\n // === UNIT RESULTS CACHE ===\n /**\n * Persists a collection of units after validating each entry against the provided schema.\n *\n * @param units - Raw units collection returned by an API call.\n * @param schema - Optional override schema when the default `UnitSchema` is not sufficient.\n */\n async setUnitResults(\n units: unknown,\n schema?: ZodTypeAny,\n ): Promise<void> {\n const baseSchema = (schema ?? UnitSchema) as ZodType<Unit>;\n const validatedUnits: Unit[] = [];\n const collection = Array.isArray(units)\n ? units\n : units && typeof units === \"object\"\n ? Object.values(units as Record<string, unknown>)\n : [];\n\n collection.forEach((unit, index) => {\n const parsed = validate(baseSchema, unit, `unitResults[${index}]`);\n if (parsed) validatedUnits.push(parsed);\n });\n await this.setState(state => ({\n ...state,\n unitResults: validatedUnits,\n }));\n }\n\n /**\n * Clears the cached unit results array.\n */\n async clearUnitResults(): Promise<void> {\n await this.setState(state => ({\n ...state,\n unitResults: [],\n }));\n }\n\n // === PROPERTY DATA BAG (full property payloads & custom data) ===\n /**\n * Replaces the persisted property payload with validated data.\n *\n * @param propertyId - ID of the property to mutate.\n * @param data - New property payload.\n * @param schema - Optional schema override used for validation.\n */\n async setPropertyData(\n propertyId: string | number,\n data: unknown,\n schema?: ZodObject<any, any, any, any, any>,\n ): Promise<void> {\n const id = String(propertyId);\n const baseSchema = (schema ?? PropertySchema) as ZodObject<any, any, any, any, any>;\n await this.setState(state => {\n const property = state.properties[id];\n if (!property) return state;\n const validated = validate(baseSchema, data, `properties.${id}.data`) as Property | null;\n if (!validated) return state;\n return {\n ...state,\n properties: {\n ...state.properties,\n [id]: {\n ...property,\n data: validated,\n },\n },\n };\n });\n }\n\n /**\n * Merges partial property data into the persisted payload with validation safeguards.\n *\n * @param propertyId - ID of the property to update.\n * @param partial - Partial payload to merge.\n * @param schema - Optional schema override for validation.\n */\n async mergePropertyData(\n propertyId: string | number,\n partial: unknown,\n schema?: ZodObject<any, any, any, any, any>,\n ): Promise<void> {\n const id = String(propertyId);\n const baseSchema = (schema ?? PropertySchema) as ZodObject<any, any, any, any, any>;\n await this.setState(state => {\n const property = state.properties[id];\n if (!property) return state;\n const current = property.data;\n if (!current) {\n const full = validate(baseSchema, partial, `properties.${id}.data`) as Property | null;\n if (!full) return state;\n return {\n ...state,\n properties: {\n ...state.properties,\n [id]: {\n ...property,\n data: full,\n },\n },\n };\n }\n\n const partialSchema = baseSchema.partial();\n const validatedPartial = validate(\n partialSchema,\n partial,\n `properties.${id}.data.partial`,\n ) as Partial<Property> | null;\n if (!validatedPartial) return state;\n const merged = validate(\n baseSchema,\n { ...current, ...validatedPartial },\n `properties.${id}.data`,\n ) as Property | null;\n if (!merged) return state;\n return {\n ...state,\n properties: {\n ...state.properties,\n [id]: {\n ...property,\n data: merged,\n },\n },\n };\n });\n }\n\n // Accepts a full API property object, validates, and stores it into the\n // per-property `data` bag. Ensures the property entry exists/updated.\n /**\n * Inserts or updates a property entry from an API payload, enforcing schema validation.\n *\n * @param apiProperty - Raw property object returned by an API.\n * @param schema - Optional schema override.\n */\n async upsertPropertyFromApi(\n apiProperty: unknown,\n schema?: ZodTypeAny,\n ): Promise<void> {\n const s = schema ?? PropertySchema;\n const parsed: any = s.parse(apiProperty);\n const id = parsed.id ?? parsed.propertyId;\n if (id === undefined || id === null) {\n throw new Error(\"upsertPropertyFromApi: property id is required\");\n }\n const propertyId = String(id);\n const slug: string | undefined = parsed.slug ?? undefined;\n\n await this.setState(state => {\n const existing = state.properties[propertyId];\n const next: UserPropertyState = existing\n ? {\n ...existing,\n ...(slug ? { slug } : {}),\n data: parsed,\n }\n : {\n id: propertyId,\n slug: slug ?? \"\",\n favoritedUnits: [],\n tourContactedOn: null,\n viewedUnits: [],\n questionnaireResults: null,\n tourContactData: null,\n data: parsed,\n };\n\n return {\n ...state,\n properties: {\n ...state.properties,\n [propertyId]: next,\n },\n };\n });\n }\n\n /**\n * Marks the provided property as current and optionally updates the slug.\n *\n * @param propertyId - Property identifier to focus.\n * @param slug - Optional slug override.\n */\n async setCurrentProperty(propertyId: string | number, slug?: string): Promise<void> {\n const id = String(propertyId);\n await this.setState(state => ({\n ...state,\n currentPropertyId: id,\n currentPropertySlug: slug || state.currentPropertySlug,\n }));\n }\n\n /**\n * Updates the slug for the current property selection.\n *\n * @param slug - New slug to persist.\n */\n async setCurrentPropertySlug(slug: string): Promise<void> {\n await this.setState(state => ({\n ...state,\n currentPropertySlug: slug\n }));\n }\n\n /**\n * Adds a slug to the `hasPreviouslySearched` list without duplicating existing entries.\n *\n * @param slug - Slug to record.\n */\n async setHasPreviouslySearched(slug: string): Promise<void> {\n await this.setState(state => ({\n ...state,\n hasPreviouslySearched: Array.from(\n new Set([...state.hasPreviouslySearched, slug])\n ),\n }));\n }\n\n /**\n * Toggles a unit's favorite state for the currently active property.\n *\n * @param unitId - Unit identifier to toggle.\n */\n async toggleFavorite(unitId: string): Promise<void> {\n await this.setState(state => {\n const propertyId = state.currentPropertyId;\n if (!propertyId) return state;\n\n const property = state.properties[propertyId];\n if (!property) return state;\n\n const isFavorited = property.favoritedUnits.includes(unitId);\n const updatedFavoritedUnits = isFavorited\n ? property.favoritedUnits.filter((id) => id !== unitId)\n : [...property.favoritedUnits, unitId];\n\n return {\n ...state,\n properties: {\n ...state.properties,\n [propertyId]: {\n ...property,\n favoritedUnits: updatedFavoritedUnits,\n },\n },\n };\n });\n }\n\n /**\n * Records the most recent view date for a unit and opens the unit URL in the browser when available.\n *\n * @param unitId - Identifier of the viewed unit.\n * @param slug - Property slug used to construct the URL.\n */\n async markUnitAsViewed(unitId: string, slug: string): Promise<void> {\n\n const url = `https://${slug}`;\n window.open(url, \"_blank\", \"noopener,noreferrer\");\n\n const today = new Date();\n const formattedDate = `${String(today.getMonth() + 1).padStart(\n 2,\n \"0\"\n )}/${String(today.getDate()).padStart(2, \"0\")}`;\n\n await this.setState(state => {\n const propertyId = state.currentPropertyId;\n if (!propertyId) return state;\n\n const property = state.properties[propertyId];\n if (!property) return state;\n\n const updatedViewedUnits = [\n ...property.viewedUnits.filter((u) => u.unitId !== unitId),\n { unitId, viewedDate: formattedDate },\n ];\n\n return {\n ...state,\n properties: {\n ...state.properties,\n [propertyId]: {\n ...property,\n viewedUnits: updatedViewedUnits,\n },\n },\n };\n });\n\n\n }\n\n /**\n * Stamps the current property with the moment the tour outreach occurred.\n */\n async setTourContactedOn(): Promise<void> {\n await this.setState(state => {\n const propertyId = state.currentPropertyId;\n if (!propertyId) return state;\n\n const property = state.properties[propertyId];\n if (!property) return state;\n\n return {\n ...state,\n properties: {\n ...state.properties,\n [propertyId]: {\n ...property,\n tourContactedOn: new Date().toISOString(),\n },\n },\n };\n });\n }\n\n /**\n * Reads the stored tour contact timestamp for the current property.\n *\n * @returns ISO string or null when no timestamp exists.\n */\n async getTourContactedOn(): Promise<string | null> {\n const state = await this.getState();\n const propertyId = state.currentPropertyId;\n if (!propertyId) return null;\n\n return state.properties[propertyId]?.tourContactedOn ?? null;\n }\n\n /**\n * Persists questionnaire results captured for the current property.\n *\n * @param results - Arbitrary questionnaire data.\n */\n async setQuestionnaireResults(results: unknown): Promise<void> {\n await this.setState(state => {\n const propertyId = state.currentPropertyId;\n if (!propertyId) return state;\n\n const property = state.properties[propertyId];\n if (!property) return state;\n\n return {\n ...state,\n properties: {\n ...state.properties,\n [propertyId]: {\n ...property,\n questionnaireResults: results,\n },\n },\n };\n });\n }\n\n /**\n * Persists structured tour contact preferences for the active property. The method waits until\n * a current property is available, allowing callers to invoke it before initialization completes.\n *\n * @param data - Contact preferences captured from the UI.\n */\n async setTourContactData(data: TourContactData): Promise<void> {\n const propertyId = await this.waitForCurrentProperty();\n\n await this.setState(state => {\n const property = state.properties[propertyId];\n if (!property) return state;\n\n return {\n ...state,\n properties: {\n ...state.properties,\n [propertyId]: {\n ...property,\n tourContactData: data,\n },\n },\n };\n });\n }\n\n\n\n\n\n\n\n // === FILTER OPERATIONS ===\n\n /**\n * Merges the provided filter values into the committed filter state.\n *\n * @param filters - Partial filter payload to apply.\n */\n async setFilters(filters: Partial<Filters>): Promise<void> {\n await this.setState(state => ({\n ...state,\n filters: { ...state.filters, ...filters }\n }));\n }\n\n /**\n * Updates the transient filters used for in-progress UI interactions.\n *\n * @param filters - Partial staging filter payload.\n */\n async setTempFilters(filters: Partial<Filters>): Promise<void> {\n await this.setState(state => ({\n ...state,\n tempFilters: { ...state.tempFilters, ...filters }\n }));\n }\n\n /**\n * Resets the committed filters to their default values.\n */\n async setFiltersToDefault(): Promise<void> {\n await this.setState(state => ({ ...state, filters: defaultFilters }));\n }\n\n /**\n * Merges partial values into the API filters payload used for network requests.\n *\n * @param filters - Partial query parameters to persist.\n */\n async setApiFilters(filters: Partial<QueryParams>): Promise<void> {\n await this.setState(state => ({\n ...state,\n apiFilters: { ...state.apiFilters, ...filters }\n }));\n }\n\n /**\n * Updates a single temporary filter field without touching the rest of the staged filters.\n *\n * @param key - Filter key to mutate.\n * @param value - New value to assign.\n */\n async handleTempFilterChange<K extends keyof Filters>(\n key: K,\n value: Filters[K]\n ): Promise<void> {\n await this.setState(state => ({\n ...state,\n tempFilters: { ...state.tempFilters, [key]: value }\n }));\n }\n\n /**\n * Normalizes the committed filters into API-ready structures and persists the result.\n */\n async submitFilterUpdate(): Promise<void> {\n await this.setState(state => {\n const apiParams: QueryParams = transformFiltersToUnitsSearchParams(\n {\n ...state.filters,\n limit: state.apiFilters.limit,\n page: state.apiFilters.page,\n sortBy: state.sortBy,\n },\n {\n defaultLimit: state.apiFilters.limit,\n defaultPage: state.apiFilters.page,\n defaultSort: state.sortBy,\n },\n );\n\n return {\n ...state,\n apiFilters: apiParams,\n };\n });\n }\n\n // === RESULTS AND SORTING ===\n\n /**\n * Persists the selected results mode (e.g. \"all\" or \"favorites\").\n *\n * @param mode - Mode identifier to store.\n */\n async setResultsMode(mode: ResultsMode): Promise<void> {\n await this.setState(state => ({ ...state, resultsMode: mode }));\n }\n\n /**\n * Persists the currently selected sort option.\n *\n * @param sortBy - Sort identifier.\n */\n async setSortBy(sortBy: SortBy): Promise<void> {\n await this.setState(state => ({ ...state, sortBy }));\n }\n\n // === QUESTIONNAIRE ===\n\n /**\n * Stores resolved questionnaire answers keyed by questionnaire name.\n *\n * @param name - Questionnaire identifier.\n * @param values - Selected option values.\n */\n async setResolvedQuestionnaireValues(name: string, values: string[]): Promise<void> {\n await this.setState(state => ({\n ...state,\n resolvedQuestionnaireValues: {\n ...state.resolvedQuestionnaireValues,\n [name]: values\n }\n }));\n }\n\n // === VISITOR UUID ===\n\n /**\n * Reads the persisted visitor UUID from the KV store.\n *\n * @returns The visitor UUID string or null when not yet set.\n */\n async getVisitorUUID(): Promise<string | null> {\n const user = await kvGet<{ visitor_uuid?: string }>(\"user\");\n return user?.visitor_uuid ?? null;\n }\n\n /**\n * Persists a visitor UUID to the KV store.\n *\n * @param vid - Visitor UUID string returned by the session API.\n */\n async setVisitorUUID(vid: string): Promise<void> {\n const current = await kvGet<Record<string, unknown>>(\"user\");\n const safe = current !== null && typeof current === \"object\" && !Array.isArray(current) ? current : {};\n await kvSet(\"user\", { ...safe, visitor_uuid: vid });\n }\n\n // === UTILITY METHODS ===\n\n /**\n * Returns convenience state for a unit within the current property.\n *\n * @param unitId - Identifier of the unit to inspect.\n * @returns Favorite flag and last viewed date.\n */\n async getUnitState(unitId: string): Promise<{\n isFavorite: boolean;\n viewedDate: string;\n }> {\n const state = await this.getState();\n const property = state.currentPropertyId ? state.properties[state.currentPropertyId] : null;\n\n return {\n isFavorite: property?.favoritedUnits.includes(unitId) ?? false,\n viewedDate:\n property?.viewedUnits.find((u) => u.unitId === unitId)?.viewedDate ?? \"\",\n };\n }\n\n /**\n * Builds a canonical results URL based on the current property slug.\n *\n * @returns Relative results URL or null when no property is selected.\n */\n async getResultsUrl(): Promise<string | null> {\n const state = await this.getState();\n return state.currentPropertySlug ? `/${state.currentPropertySlug}/results` : null;\n }\n\n /**\n * Retrieves the currently selected property entry.\n *\n * @returns Property state or null when unset.\n */\n async getCurrentProperty(): Promise<UserPropertyState | null> {\n const state = await this.getState();\n return state.currentPropertyId ? state.properties[state.currentPropertyId] ?? null : null;\n }\n\n /**\n * Retrieves property data for a specific property or defaults to the current property.\n *\n * @param propertyId - Optional property identifier to fetch.\n * @returns Property state or null when unavailable.\n */\n async getPropertyData(propertyId?: string | number): Promise<UserPropertyState | null> {\n const state = await this.getState();\n const id = propertyId == null ? state.currentPropertyId : String(propertyId);\n return id ? state.properties[id] ?? null : null;\n }\n\n /**\n * Reads and returns the full validated unified store state.\n */\n async getFullState(): Promise<UnifiedStoreData> {\n return this.getState();\n }\n\n /**\n * Hydrates the store with the default scaffold when no data has been persisted yet.\n */\n async initialize(): Promise<void> {\n // Ensure default shape is present; no-op if already initialized\n await this.setState(state => ({ ...defaultUnifiedStoreData, ...state }));\n }\n\n}\n\n// Export singleton instance\nexport const store = new UnifiedStore();\n// Alias to prefer neutral naming going forward\nexport { UnifiedStore as Store };\n// Re-export types for convenience (tests import from this module)\nexport type { UserPropertyState, Filters } from \"../schema\";\n"],"names":["defaultFilters","defaultUnifiedStoreData","UnifiedStore","state","kvGet","merged","parsed","UnifiedStoreDataSchema","sanitizedProperties","acc","key","value","entry","UserPropertyStateSchema","sanitizedUnitResults","UnitSchema","fallback","fallbackParsed","updater","currentState","newState","validatedState","kvSet","timeoutMs","deadline","propertyId","resolve","finalState","slug","id","units","schema","baseSchema","validatedUnits","unit","index","validate","data","PropertySchema","property","validated","partial","current","full","partialSchema","validatedPartial","apiProperty","existing","next","unitId","updatedFavoritedUnits","url","today","formattedDate","updatedViewedUnits","_a","results","filters","apiParams","transformFiltersToUnitsSearchParams","mode","sortBy","name","values","user","vid","safe","u","store"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"store.cjs","sources":["../../src/stores/store.ts"],"sourcesContent":["import { kvGet, kvSet } from \"../storage\";\nimport type { ZodObject, ZodType, ZodTypeAny } from \"zod\";\nimport {\n UnifiedStoreDataSchema,\n UserPropertyStateSchema,\n type UnifiedStoreData,\n type UserPropertyState,\n type Property,\n type Filters,\n type QueryParams,\n type ResultsMode,\n type SortBy,\n type TourContactData,\n type Unit,\n PropertySchema,\n TourContactDataSchema,\n UnitSchema,\n} from \"../schema\";\nimport { validate } from \"../validation\";\nimport { transformFiltersToUnitsSearchParams } from \"../features/filters/transformers\";\n\n// Default values\nconst defaultFilters: Filters = {\n date_availability: undefined,\n qty_bedrooms: undefined,\n base_price: undefined,\n highlights: undefined,\n};\n\nconst defaultUnifiedStoreData: UnifiedStoreData = {\n // Property data\n properties: {},\n currentPropertyId: null,\n currentPropertySlug: null,\n hasPreviouslySearched: [],\n\n // App data\n unitResults: [],\n filters: defaultFilters,\n tempFilters: defaultFilters,\n apiFilters: {\n limit: 10,\n page: 1,\n sortBy: \"relevance\",\n },\n resultsMode: \"all\",\n resolvedQuestionnaireValues: {},\n sortBy: \"relevance\",\n};\n\nconst toArray = (input: unknown): unknown[] => {\n if (input == null) return [];\n return Array.isArray(input) ? input : [input];\n};\n\nconst extractFilterValues = (value: unknown): unknown[] => {\n return toArray(value).flatMap(item => {\n if (item == null) return [];\n if (Array.isArray(item)) return item;\n if (typeof item === \"object\" && \"value\" in (item as any)) {\n const v = (item as any).value;\n return Array.isArray(v) ? v : v != null ? [v] : [];\n }\n return [item];\n });\n};\n\nconst toStringArray = (value: unknown): string[] =>\n extractFilterValues(value)\n .flatMap(v => (Array.isArray(v) ? v : [v]))\n .map(v => String(v))\n .map(v => v.trim())\n .filter(v => v.length > 0);\n\nconst toNumberArray = (value: unknown): number[] =>\n extractFilterValues(value)\n .map(v => {\n if (typeof v === \"number\" && Number.isFinite(v)) return v;\n const num = Number(v);\n return Number.isFinite(num) ? num : null;\n })\n .filter((v): v is number => v !== null);\n\nconst toNumberValue = (value: unknown): number | null => {\n if (value == null) return null;\n if (typeof value === \"number\") return Number.isFinite(value) ? value : null;\n if (typeof value === \"object\" && \"value\" in (value as any)) {\n return toNumberValue((value as any).value);\n }\n const num = Number(value);\n return Number.isFinite(num) ? num : null;\n};\n\n// Unified store class\nexport class UnifiedStore {\n /**\n * Resolves the persisted unified store snapshot, coercing legacy shapes into the latest schema\n * and sanitizing invalid entries where possible.\n */\n private async getState(): Promise<UnifiedStoreData> {\n const state = await kvGet<UnifiedStoreData>(\"app\");\n if (!state) {\n return defaultUnifiedStoreData;\n }\n\n const merged = {\n ...defaultUnifiedStoreData,\n ...state,\n properties: state.properties ?? {},\n unitResults: state.unitResults ?? [],\n currentPropertyId:\n state.currentPropertyId == null ? null : String(state.currentPropertyId),\n currentPropertySlug: state.currentPropertySlug ?? null,\n hasPreviouslySearched: Array.isArray(state.hasPreviouslySearched)\n ? state.hasPreviouslySearched.map(String)\n : [],\n };\n\n const parsed = UnifiedStoreDataSchema.safeParse(merged);\n if (parsed.success) return parsed.data;\n\n // Sanitize by dropping invalid property entries and unit results\n const sanitizedProperties = Object.entries(merged.properties ?? {}).reduce<\n Record<string, UserPropertyState>\n >((acc, [key, value]) => {\n const entry = UserPropertyStateSchema.safeParse(value);\n if (entry.success) acc[key] = entry.data;\n return acc;\n }, {});\n\n const rawUnitResults = Array.isArray(merged.unitResults)\n ? merged.unitResults\n : merged.unitResults && typeof merged.unitResults === \"object\"\n ? Object.values(merged.unitResults as Record<string, unknown>)\n : [];\n\n const sanitizedUnitResults = rawUnitResults.reduce<Unit[]>((acc, value) => {\n const entry = UnitSchema.safeParse(value);\n if (entry.success) acc.push(entry.data);\n return acc;\n }, []);\n\n const fallback = {\n ...merged,\n properties: sanitizedProperties,\n unitResults: sanitizedUnitResults,\n };\n\n const fallbackParsed = UnifiedStoreDataSchema.safeParse(fallback);\n return fallbackParsed.success ? fallbackParsed.data : defaultUnifiedStoreData;\n }\n\n /**\n * Applies an updater function to the current store state, validates the result, and persists it.\n *\n * @param updater - Pure function that maps the current state to the next state.\n */\n private async setState(updater: (state: UnifiedStoreData) => UnifiedStoreData): Promise<void> {\n const currentState = await this.getState();\n const newState = updater(currentState);\n const validatedState = UnifiedStoreDataSchema.parse(newState);\n await kvSet(\"app\", validatedState);\n }\n\n /**\n * Polls the persisted state until a current property pointer is available or the timeout elapses.\n *\n * @param timeoutMs - Maximum time in milliseconds to wait before failing.\n * @returns The active property ID once it becomes available.\n * @throws Error if the property pointer is not set before the timeout expires.\n */\n private async waitForCurrentProperty(timeoutMs = 1000): Promise<string> {\n const deadline = Date.now() + timeoutMs;\n\n while (Date.now() < deadline) {\n const state = await this.getState();\n const propertyId = state.currentPropertyId;\n if (propertyId && state.properties[propertyId]) return propertyId;\n\n await new Promise(resolve => setTimeout(resolve, 16));\n }\n\n const finalState = await this.getState();\n const propertyId = finalState.currentPropertyId;\n if (propertyId && finalState.properties[propertyId]) return propertyId;\n\n throw new Error(\"UnifiedStore: current property was not initialized in time\");\n }\n\n // === PROPERTY OPERATIONS ===\n\n /**\n * Ensures a property entry exists and registers it as the current property.\n *\n * @param propertyId - Identifier used to track the property.\n * @param slug - Canonical slug associated with the property.\n */\n async initializeProperty(propertyId: string | number, slug: string): Promise<void> {\n const id = String(propertyId);\n await this.setState(state => {\n if (state.properties && state.properties[id]) {\n return {\n ...state,\n currentPropertyId: id,\n currentPropertySlug: slug\n };\n }\n\n return {\n ...state,\n currentPropertyId: id,\n currentPropertySlug: slug,\n properties: {\n ...state.properties,\n [id]: {\n id,\n slug,\n favoritedUnits: [],\n tourContactedOn: null,\n viewedUnits: [],\n questionnaireResults: null,\n tourContactData: null,\n },\n },\n };\n });\n }\n\n // === UNIT RESULTS CACHE ===\n /**\n * Persists a collection of units after validating each entry against the provided schema.\n *\n * @param units - Raw units collection returned by an API call.\n * @param schema - Optional override schema when the default `UnitSchema` is not sufficient.\n */\n async setUnitResults(\n units: unknown,\n schema?: ZodTypeAny,\n ): Promise<void> {\n const baseSchema = (schema ?? UnitSchema) as ZodType<Unit>;\n const validatedUnits: Unit[] = [];\n const collection = Array.isArray(units)\n ? units\n : units && typeof units === \"object\"\n ? Object.values(units as Record<string, unknown>)\n : [];\n\n collection.forEach((unit, index) => {\n const parsed = validate(baseSchema, unit, `unitResults[${index}]`);\n if (parsed) validatedUnits.push(parsed);\n });\n await this.setState(state => ({\n ...state,\n unitResults: validatedUnits,\n }));\n }\n\n /**\n * Clears the cached unit results array.\n */\n async clearUnitResults(): Promise<void> {\n await this.setState(state => ({\n ...state,\n unitResults: [],\n }));\n }\n\n // === PROPERTY DATA BAG (full property payloads & custom data) ===\n /**\n * Replaces the persisted property payload with validated data.\n *\n * @param propertyId - ID of the property to mutate.\n * @param data - New property payload.\n * @param schema - Optional schema override used for validation.\n */\n async setPropertyData(\n propertyId: string | number,\n data: unknown,\n schema?: ZodObject<any, any, any, any, any>,\n ): Promise<void> {\n const id = String(propertyId);\n const baseSchema = (schema ?? PropertySchema) as ZodObject<any, any, any, any, any>;\n await this.setState(state => {\n const property = state.properties[id];\n if (!property) return state;\n const validated = validate(baseSchema, data, `properties.${id}.data`) as Property | null;\n if (!validated) return state;\n return {\n ...state,\n properties: {\n ...state.properties,\n [id]: {\n ...property,\n data: validated,\n },\n },\n };\n });\n }\n\n /**\n * Merges partial property data into the persisted payload with validation safeguards.\n *\n * @param propertyId - ID of the property to update.\n * @param partial - Partial payload to merge.\n * @param schema - Optional schema override for validation.\n */\n async mergePropertyData(\n propertyId: string | number,\n partial: unknown,\n schema?: ZodObject<any, any, any, any, any>,\n ): Promise<void> {\n const id = String(propertyId);\n const baseSchema = (schema ?? PropertySchema) as ZodObject<any, any, any, any, any>;\n await this.setState(state => {\n const property = state.properties[id];\n if (!property) return state;\n const current = property.data;\n if (!current) {\n const full = validate(baseSchema, partial, `properties.${id}.data`) as Property | null;\n if (!full) return state;\n return {\n ...state,\n properties: {\n ...state.properties,\n [id]: {\n ...property,\n data: full,\n },\n },\n };\n }\n\n const partialSchema = baseSchema.partial();\n const validatedPartial = validate(\n partialSchema,\n partial,\n `properties.${id}.data.partial`,\n ) as Partial<Property> | null;\n if (!validatedPartial) return state;\n const merged = validate(\n baseSchema,\n { ...current, ...validatedPartial },\n `properties.${id}.data`,\n ) as Property | null;\n if (!merged) return state;\n return {\n ...state,\n properties: {\n ...state.properties,\n [id]: {\n ...property,\n data: merged,\n },\n },\n };\n });\n }\n\n // Accepts a full API property object, validates, and stores it into the\n // per-property `data` bag. Ensures the property entry exists/updated.\n /**\n * Inserts or updates a property entry from an API payload, enforcing schema validation.\n *\n * @param apiProperty - Raw property object returned by an API.\n * @param schema - Optional schema override.\n */\n async upsertPropertyFromApi(\n apiProperty: unknown,\n schema?: ZodTypeAny,\n ): Promise<void> {\n const s = schema ?? PropertySchema;\n const parsed: any = s.parse(apiProperty);\n const id = parsed.id ?? parsed.propertyId;\n if (id === undefined || id === null) {\n throw new Error(\"upsertPropertyFromApi: property id is required\");\n }\n const propertyId = String(id);\n const slug: string | undefined = parsed.slug ?? undefined;\n\n await this.setState(state => {\n const existing = state.properties[propertyId];\n const next: UserPropertyState = existing\n ? {\n ...existing,\n ...(slug ? { slug } : {}),\n data: parsed,\n }\n : {\n id: propertyId,\n slug: slug ?? \"\",\n favoritedUnits: [],\n tourContactedOn: null,\n viewedUnits: [],\n questionnaireResults: null,\n tourContactData: null,\n data: parsed,\n };\n\n return {\n ...state,\n properties: {\n ...state.properties,\n [propertyId]: next,\n },\n };\n });\n }\n\n /**\n * Marks the provided property as current and optionally updates the slug.\n *\n * @param propertyId - Property identifier to focus.\n * @param slug - Optional slug override.\n */\n async setCurrentProperty(propertyId: string | number, slug?: string): Promise<void> {\n const id = String(propertyId);\n await this.setState(state => ({\n ...state,\n currentPropertyId: id,\n currentPropertySlug: slug || state.currentPropertySlug,\n }));\n }\n\n /**\n * Updates the slug for the current property selection.\n *\n * @param slug - New slug to persist.\n */\n async setCurrentPropertySlug(slug: string): Promise<void> {\n await this.setState(state => ({\n ...state,\n currentPropertySlug: slug\n }));\n }\n\n /**\n * Adds a slug to the `hasPreviouslySearched` list without duplicating existing entries.\n *\n * @param slug - Slug to record.\n */\n async setHasPreviouslySearched(slug: string): Promise<void> {\n await this.setState(state => ({\n ...state,\n hasPreviouslySearched: Array.from(\n new Set([...state.hasPreviouslySearched, slug])\n ),\n }));\n }\n\n /**\n * Replaces the favoritedUnits list for the current property with the provided array.\n * Intended for seeding IndexedDB from an API response (e.g. bootstrap endpoint).\n *\n * @param unitIds - Canonical list of favorited unit IDs from the API.\n */\n async setFavoriteUnitIds(unitIds: string[]): Promise<void> {\n await this.setState(state => {\n const propertyId = state.currentPropertyId;\n if (!propertyId) return state;\n\n const property = state.properties[propertyId];\n if (!property) return state;\n\n return {\n ...state,\n properties: {\n ...state.properties,\n [propertyId]: { ...property, favoritedUnits: unitIds },\n },\n };\n });\n }\n\n /**\n * Toggles a unit's favorite state for the currently active property.\n *\n * @param unitId - Unit identifier to toggle.\n */\n async toggleFavorite(unitId: string): Promise<void> {\n await this.setState(state => {\n const propertyId = state.currentPropertyId;\n if (!propertyId) return state;\n\n const property = state.properties[propertyId];\n if (!property) return state;\n\n const isFavorited = property.favoritedUnits.includes(unitId);\n const updatedFavoritedUnits = isFavorited\n ? property.favoritedUnits.filter((id) => id !== unitId)\n : [...property.favoritedUnits, unitId];\n\n return {\n ...state,\n properties: {\n ...state.properties,\n [propertyId]: {\n ...property,\n favoritedUnits: updatedFavoritedUnits,\n },\n },\n };\n });\n }\n\n /**\n * Records the most recent view date for a unit and opens the unit URL in the browser when available.\n *\n * @param unitId - Identifier of the viewed unit.\n * @param slug - Property slug used to construct the URL.\n */\n async markUnitAsViewed(unitId: string, slug: string): Promise<void> {\n\n const url = `https://${slug}`;\n window.open(url, \"_blank\", \"noopener,noreferrer\");\n\n const today = new Date();\n const formattedDate = `${String(today.getMonth() + 1).padStart(\n 2,\n \"0\"\n )}/${String(today.getDate()).padStart(2, \"0\")}`;\n\n await this.setState(state => {\n const propertyId = state.currentPropertyId;\n if (!propertyId) return state;\n\n const property = state.properties[propertyId];\n if (!property) return state;\n\n const updatedViewedUnits = [\n ...property.viewedUnits.filter((u) => u.unitId !== unitId),\n { unitId, viewedDate: formattedDate },\n ];\n\n return {\n ...state,\n properties: {\n ...state.properties,\n [propertyId]: {\n ...property,\n viewedUnits: updatedViewedUnits,\n },\n },\n };\n });\n\n\n }\n\n /**\n * Stamps the current property with the moment the tour outreach occurred.\n */\n async setTourContactedOn(): Promise<void> {\n await this.setState(state => {\n const propertyId = state.currentPropertyId;\n if (!propertyId) return state;\n\n const property = state.properties[propertyId];\n if (!property) return state;\n\n return {\n ...state,\n properties: {\n ...state.properties,\n [propertyId]: {\n ...property,\n tourContactedOn: new Date().toISOString(),\n },\n },\n };\n });\n }\n\n /**\n * Reads the stored tour contact timestamp for the current property.\n *\n * @returns ISO string or null when no timestamp exists.\n */\n async getTourContactedOn(): Promise<string | null> {\n const state = await this.getState();\n const propertyId = state.currentPropertyId;\n if (!propertyId) return null;\n\n return state.properties[propertyId]?.tourContactedOn ?? null;\n }\n\n /**\n * Persists questionnaire results captured for the current property.\n *\n * @param results - Arbitrary questionnaire data.\n */\n async setQuestionnaireResults(results: unknown): Promise<void> {\n await this.setState(state => {\n const propertyId = state.currentPropertyId;\n if (!propertyId) return state;\n\n const property = state.properties[propertyId];\n if (!property) return state;\n\n return {\n ...state,\n properties: {\n ...state.properties,\n [propertyId]: {\n ...property,\n questionnaireResults: results,\n },\n },\n };\n });\n }\n\n /**\n * Persists structured tour contact preferences for the active property. The method waits until\n * a current property is available, allowing callers to invoke it before initialization completes.\n *\n * @param data - Contact preferences captured from the UI.\n */\n async setTourContactData(data: TourContactData): Promise<void> {\n const propertyId = await this.waitForCurrentProperty();\n\n await this.setState(state => {\n const property = state.properties[propertyId];\n if (!property) return state;\n\n return {\n ...state,\n properties: {\n ...state.properties,\n [propertyId]: {\n ...property,\n tourContactData: data,\n },\n },\n };\n });\n }\n\n\n\n\n\n\n\n // === FILTER OPERATIONS ===\n\n /**\n * Merges the provided filter values into the committed filter state.\n *\n * @param filters - Partial filter payload to apply.\n */\n async setFilters(filters: Partial<Filters>): Promise<void> {\n await this.setState(state => ({\n ...state,\n filters: { ...state.filters, ...filters }\n }));\n }\n\n /**\n * Updates the transient filters used for in-progress UI interactions.\n *\n * @param filters - Partial staging filter payload.\n */\n async setTempFilters(filters: Partial<Filters>): Promise<void> {\n await this.setState(state => ({\n ...state,\n tempFilters: { ...state.tempFilters, ...filters }\n }));\n }\n\n /**\n * Resets the committed filters to their default values.\n */\n async setFiltersToDefault(): Promise<void> {\n await this.setState(state => ({ ...state, filters: defaultFilters }));\n }\n\n /**\n * Merges partial values into the API filters payload used for network requests.\n *\n * @param filters - Partial query parameters to persist.\n */\n async setApiFilters(filters: Partial<QueryParams>): Promise<void> {\n await this.setState(state => ({\n ...state,\n apiFilters: { ...state.apiFilters, ...filters }\n }));\n }\n\n /**\n * Updates a single temporary filter field without touching the rest of the staged filters.\n *\n * @param key - Filter key to mutate.\n * @param value - New value to assign.\n */\n async handleTempFilterChange<K extends keyof Filters>(\n key: K,\n value: Filters[K]\n ): Promise<void> {\n await this.setState(state => ({\n ...state,\n tempFilters: { ...state.tempFilters, [key]: value }\n }));\n }\n\n /**\n * Normalizes the committed filters into API-ready structures and persists the result.\n */\n async submitFilterUpdate(): Promise<void> {\n await this.setState(state => {\n const apiParams: QueryParams = transformFiltersToUnitsSearchParams(\n {\n ...state.filters,\n limit: state.apiFilters.limit,\n page: state.apiFilters.page,\n sortBy: state.sortBy,\n },\n {\n defaultLimit: state.apiFilters.limit,\n defaultPage: state.apiFilters.page,\n defaultSort: state.sortBy,\n },\n );\n\n return {\n ...state,\n apiFilters: apiParams,\n };\n });\n }\n\n // === RESULTS AND SORTING ===\n\n /**\n * Persists the selected results mode (e.g. \"all\" or \"favorites\").\n *\n * @param mode - Mode identifier to store.\n */\n async setResultsMode(mode: ResultsMode): Promise<void> {\n await this.setState(state => ({ ...state, resultsMode: mode }));\n }\n\n /**\n * Persists the currently selected sort option.\n *\n * @param sortBy - Sort identifier.\n */\n async setSortBy(sortBy: SortBy): Promise<void> {\n await this.setState(state => ({ ...state, sortBy }));\n }\n\n // === QUESTIONNAIRE ===\n\n /**\n * Stores resolved questionnaire answers keyed by questionnaire name.\n *\n * @param name - Questionnaire identifier.\n * @param values - Selected option values.\n */\n async setResolvedQuestionnaireValues(name: string, values: string[]): Promise<void> {\n await this.setState(state => ({\n ...state,\n resolvedQuestionnaireValues: {\n ...state.resolvedQuestionnaireValues,\n [name]: values\n }\n }));\n }\n\n // === VISITOR UUID ===\n\n /**\n * Reads the persisted visitor UUID from the KV store.\n *\n * @returns The visitor UUID string or null when not yet set.\n */\n async getVisitorUUID(): Promise<string | null> {\n const user = await kvGet<{ visitor_uuid?: string }>(\"user\");\n return user?.visitor_uuid ?? null;\n }\n\n /**\n * Persists a visitor UUID to the KV store.\n *\n * @param vid - Visitor UUID string returned by the session API.\n */\n async setVisitorUUID(vid: string): Promise<void> {\n const current = await kvGet<Record<string, unknown>>(\"user\");\n const safe = current !== null && typeof current === \"object\" && !Array.isArray(current) ? current : {};\n await kvSet(\"user\", { ...safe, visitor_uuid: vid });\n }\n\n // === UTILITY METHODS ===\n\n /**\n * Returns convenience state for a unit within the current property.\n *\n * @param unitId - Identifier of the unit to inspect.\n * @returns Favorite flag and last viewed date.\n */\n async getUnitState(unitId: string): Promise<{\n isFavorite: boolean;\n viewedDate: string;\n }> {\n const state = await this.getState();\n const property = state.currentPropertyId ? state.properties[state.currentPropertyId] : null;\n\n return {\n isFavorite: property?.favoritedUnits.includes(unitId) ?? false,\n viewedDate:\n property?.viewedUnits.find((u) => u.unitId === unitId)?.viewedDate ?? \"\",\n };\n }\n\n /**\n * Builds a canonical results URL based on the current property slug.\n *\n * @returns Relative results URL or null when no property is selected.\n */\n async getResultsUrl(): Promise<string | null> {\n const state = await this.getState();\n return state.currentPropertySlug ? `/${state.currentPropertySlug}/results` : null;\n }\n\n /**\n * Retrieves the currently selected property entry.\n *\n * @returns Property state or null when unset.\n */\n async getCurrentProperty(): Promise<UserPropertyState | null> {\n const state = await this.getState();\n return state.currentPropertyId ? state.properties[state.currentPropertyId] ?? null : null;\n }\n\n /**\n * Retrieves property data for a specific property or defaults to the current property.\n *\n * @param propertyId - Optional property identifier to fetch.\n * @returns Property state or null when unavailable.\n */\n async getPropertyData(propertyId?: string | number): Promise<UserPropertyState | null> {\n const state = await this.getState();\n const id = propertyId == null ? state.currentPropertyId : String(propertyId);\n return id ? state.properties[id] ?? null : null;\n }\n\n /**\n * Reads and returns the full validated unified store state.\n */\n async getFullState(): Promise<UnifiedStoreData> {\n return this.getState();\n }\n\n /**\n * Hydrates the store with the default scaffold when no data has been persisted yet.\n */\n async initialize(): Promise<void> {\n // Ensure default shape is present; no-op if already initialized\n await this.setState(state => ({ ...defaultUnifiedStoreData, ...state }));\n }\n\n}\n\n// Export singleton instance\nexport const store = new UnifiedStore();\n// Alias to prefer neutral naming going forward\nexport { UnifiedStore as Store };\n// Re-export types for convenience (tests import from this module)\nexport type { UserPropertyState, Filters } from \"../schema\";\n"],"names":["defaultFilters","defaultUnifiedStoreData","UnifiedStore","state","kvGet","merged","parsed","UnifiedStoreDataSchema","sanitizedProperties","acc","key","value","entry","UserPropertyStateSchema","sanitizedUnitResults","UnitSchema","fallback","fallbackParsed","updater","currentState","newState","validatedState","kvSet","timeoutMs","deadline","propertyId","resolve","finalState","slug","id","units","schema","baseSchema","validatedUnits","unit","index","validate","data","PropertySchema","property","validated","partial","current","full","partialSchema","validatedPartial","apiProperty","existing","next","unitIds","unitId","updatedFavoritedUnits","url","today","formattedDate","updatedViewedUnits","_a","results","filters","apiParams","transformFiltersToUnitsSearchParams","mode","sortBy","name","values","user","vid","safe","u","store"],"mappings":"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"}
|
package/dist/stores/store.d.ts
CHANGED
|
@@ -80,6 +80,13 @@ export declare class UnifiedStore {
|
|
|
80
80
|
* @param slug - Slug to record.
|
|
81
81
|
*/
|
|
82
82
|
setHasPreviouslySearched(slug: string): Promise<void>;
|
|
83
|
+
/**
|
|
84
|
+
* Replaces the favoritedUnits list for the current property with the provided array.
|
|
85
|
+
* Intended for seeding IndexedDB from an API response (e.g. bootstrap endpoint).
|
|
86
|
+
*
|
|
87
|
+
* @param unitIds - Canonical list of favorited unit IDs from the API.
|
|
88
|
+
*/
|
|
89
|
+
setFavoriteUnitIds(unitIds: string[]): Promise<void>;
|
|
83
90
|
/**
|
|
84
91
|
* Toggles a unit's favorite state for the currently active property.
|
|
85
92
|
*
|
package/dist/stores/store.mjs
CHANGED
|
@@ -51,11 +51,11 @@ class U {
|
|
|
51
51
|
}, {}), i = (Array.isArray(e.unitResults) ? e.unitResults : e.unitResults && typeof e.unitResults == "object" ? Object.values(e.unitResults) : []).reduce((p, u) => {
|
|
52
52
|
const c = g.safeParse(u);
|
|
53
53
|
return c.success && p.push(c.data), p;
|
|
54
|
-
}, []),
|
|
54
|
+
}, []), n = {
|
|
55
55
|
...e,
|
|
56
56
|
properties: s,
|
|
57
57
|
unitResults: i
|
|
58
|
-
}, o = f.safeParse(
|
|
58
|
+
}, o = f.safeParse(n);
|
|
59
59
|
return o.success ? o.data : y;
|
|
60
60
|
}
|
|
61
61
|
/**
|
|
@@ -77,9 +77,9 @@ class U {
|
|
|
77
77
|
async waitForCurrentProperty(t = 1e3) {
|
|
78
78
|
const e = Date.now() + t;
|
|
79
79
|
for (; Date.now() < e; ) {
|
|
80
|
-
const
|
|
81
|
-
if (i &&
|
|
82
|
-
await new Promise((
|
|
80
|
+
const a = await this.getState(), i = a.currentPropertyId;
|
|
81
|
+
if (i && a.properties[i]) return i;
|
|
82
|
+
await new Promise((n) => setTimeout(n, 16));
|
|
83
83
|
}
|
|
84
84
|
const r = await this.getState(), s = r.currentPropertyId;
|
|
85
85
|
if (s && r.properties[s]) return s;
|
|
@@ -125,8 +125,8 @@ class U {
|
|
|
125
125
|
*/
|
|
126
126
|
async setUnitResults(t, e) {
|
|
127
127
|
const r = e ?? g, s = [];
|
|
128
|
-
(Array.isArray(t) ? t : t && typeof t == "object" ? Object.values(t) : []).forEach((i,
|
|
129
|
-
const o = d(r, i, `unitResults[${
|
|
128
|
+
(Array.isArray(t) ? t : t && typeof t == "object" ? Object.values(t) : []).forEach((i, n) => {
|
|
129
|
+
const o = d(r, i, `unitResults[${n}]`);
|
|
130
130
|
o && s.push(o);
|
|
131
131
|
}), await this.setState((i) => ({
|
|
132
132
|
...i,
|
|
@@ -151,17 +151,17 @@ class U {
|
|
|
151
151
|
* @param schema - Optional schema override used for validation.
|
|
152
152
|
*/
|
|
153
153
|
async setPropertyData(t, e, r) {
|
|
154
|
-
const s = String(t),
|
|
154
|
+
const s = String(t), a = r ?? h;
|
|
155
155
|
await this.setState((i) => {
|
|
156
|
-
const
|
|
157
|
-
if (!
|
|
158
|
-
const o = d(
|
|
156
|
+
const n = i.properties[s];
|
|
157
|
+
if (!n) return i;
|
|
158
|
+
const o = d(a, e, `properties.${s}.data`);
|
|
159
159
|
return o ? {
|
|
160
160
|
...i,
|
|
161
161
|
properties: {
|
|
162
162
|
...i.properties,
|
|
163
163
|
[s]: {
|
|
164
|
-
...
|
|
164
|
+
...n,
|
|
165
165
|
data: o
|
|
166
166
|
}
|
|
167
167
|
}
|
|
@@ -176,32 +176,32 @@ class U {
|
|
|
176
176
|
* @param schema - Optional schema override for validation.
|
|
177
177
|
*/
|
|
178
178
|
async mergePropertyData(t, e, r) {
|
|
179
|
-
const s = String(t),
|
|
179
|
+
const s = String(t), a = r ?? h;
|
|
180
180
|
await this.setState((i) => {
|
|
181
|
-
const
|
|
182
|
-
if (!
|
|
183
|
-
const o =
|
|
181
|
+
const n = i.properties[s];
|
|
182
|
+
if (!n) return i;
|
|
183
|
+
const o = n.data;
|
|
184
184
|
if (!o) {
|
|
185
|
-
const l = d(
|
|
185
|
+
const l = d(a, e, `properties.${s}.data`);
|
|
186
186
|
return l ? {
|
|
187
187
|
...i,
|
|
188
188
|
properties: {
|
|
189
189
|
...i.properties,
|
|
190
190
|
[s]: {
|
|
191
|
-
...
|
|
191
|
+
...n,
|
|
192
192
|
data: l
|
|
193
193
|
}
|
|
194
194
|
}
|
|
195
195
|
} : i;
|
|
196
196
|
}
|
|
197
|
-
const p =
|
|
197
|
+
const p = a.partial(), u = d(
|
|
198
198
|
p,
|
|
199
199
|
e,
|
|
200
200
|
`properties.${s}.data.partial`
|
|
201
201
|
);
|
|
202
202
|
if (!u) return i;
|
|
203
203
|
const c = d(
|
|
204
|
-
|
|
204
|
+
a,
|
|
205
205
|
{ ...o, ...u },
|
|
206
206
|
`properties.${s}.data`
|
|
207
207
|
);
|
|
@@ -210,7 +210,7 @@ class U {
|
|
|
210
210
|
properties: {
|
|
211
211
|
...i.properties,
|
|
212
212
|
[s]: {
|
|
213
|
-
...
|
|
213
|
+
...n,
|
|
214
214
|
data: c
|
|
215
215
|
}
|
|
216
216
|
}
|
|
@@ -226,18 +226,18 @@ class U {
|
|
|
226
226
|
* @param schema - Optional schema override.
|
|
227
227
|
*/
|
|
228
228
|
async upsertPropertyFromApi(t, e) {
|
|
229
|
-
const s = (e ?? h).parse(t),
|
|
230
|
-
if (
|
|
229
|
+
const s = (e ?? h).parse(t), a = s.id ?? s.propertyId;
|
|
230
|
+
if (a == null)
|
|
231
231
|
throw new Error("upsertPropertyFromApi: property id is required");
|
|
232
|
-
const i = String(
|
|
232
|
+
const i = String(a), n = s.slug ?? void 0;
|
|
233
233
|
await this.setState((o) => {
|
|
234
234
|
const p = o.properties[i], u = p ? {
|
|
235
235
|
...p,
|
|
236
|
-
...
|
|
236
|
+
...n ? { slug: n } : {},
|
|
237
237
|
data: s
|
|
238
238
|
} : {
|
|
239
239
|
id: i,
|
|
240
|
-
slug:
|
|
240
|
+
slug: n ?? "",
|
|
241
241
|
favoritedUnits: [],
|
|
242
242
|
tourContactedOn: null,
|
|
243
243
|
viewedUnits: [],
|
|
@@ -292,6 +292,26 @@ class U {
|
|
|
292
292
|
)
|
|
293
293
|
}));
|
|
294
294
|
}
|
|
295
|
+
/**
|
|
296
|
+
* Replaces the favoritedUnits list for the current property with the provided array.
|
|
297
|
+
* Intended for seeding IndexedDB from an API response (e.g. bootstrap endpoint).
|
|
298
|
+
*
|
|
299
|
+
* @param unitIds - Canonical list of favorited unit IDs from the API.
|
|
300
|
+
*/
|
|
301
|
+
async setFavoriteUnitIds(t) {
|
|
302
|
+
await this.setState((e) => {
|
|
303
|
+
const r = e.currentPropertyId;
|
|
304
|
+
if (!r) return e;
|
|
305
|
+
const s = e.properties[r];
|
|
306
|
+
return s ? {
|
|
307
|
+
...e,
|
|
308
|
+
properties: {
|
|
309
|
+
...e.properties,
|
|
310
|
+
[r]: { ...s, favoritedUnits: t }
|
|
311
|
+
}
|
|
312
|
+
} : e;
|
|
313
|
+
});
|
|
314
|
+
}
|
|
295
315
|
/**
|
|
296
316
|
* Toggles a unit's favorite state for the currently active property.
|
|
297
317
|
*
|
|
@@ -303,7 +323,7 @@ class U {
|
|
|
303
323
|
if (!r) return e;
|
|
304
324
|
const s = e.properties[r];
|
|
305
325
|
if (!s) return e;
|
|
306
|
-
const i = s.favoritedUnits.includes(t) ? s.favoritedUnits.filter((
|
|
326
|
+
const i = s.favoritedUnits.includes(t) ? s.favoritedUnits.filter((n) => n !== t) : [...s.favoritedUnits, t];
|
|
307
327
|
return {
|
|
308
328
|
...e,
|
|
309
329
|
properties: {
|
|
@@ -325,24 +345,24 @@ class U {
|
|
|
325
345
|
async markUnitAsViewed(t, e) {
|
|
326
346
|
const r = `https://${e}`;
|
|
327
347
|
window.open(r, "_blank", "noopener,noreferrer");
|
|
328
|
-
const s = /* @__PURE__ */ new Date(),
|
|
348
|
+
const s = /* @__PURE__ */ new Date(), a = `${String(s.getMonth() + 1).padStart(
|
|
329
349
|
2,
|
|
330
350
|
"0"
|
|
331
351
|
)}/${String(s.getDate()).padStart(2, "0")}`;
|
|
332
352
|
await this.setState((i) => {
|
|
333
|
-
const
|
|
334
|
-
if (!
|
|
335
|
-
const o = i.properties[
|
|
353
|
+
const n = i.currentPropertyId;
|
|
354
|
+
if (!n) return i;
|
|
355
|
+
const o = i.properties[n];
|
|
336
356
|
if (!o) return i;
|
|
337
357
|
const p = [
|
|
338
358
|
...o.viewedUnits.filter((u) => u.unitId !== t),
|
|
339
|
-
{ unitId: t, viewedDate:
|
|
359
|
+
{ unitId: t, viewedDate: a }
|
|
340
360
|
];
|
|
341
361
|
return {
|
|
342
362
|
...i,
|
|
343
363
|
properties: {
|
|
344
364
|
...i.properties,
|
|
345
|
-
[
|
|
365
|
+
[n]: {
|
|
346
366
|
...o,
|
|
347
367
|
viewedUnits: p
|
|
348
368
|
}
|
|
@@ -564,7 +584,7 @@ class U {
|
|
|
564
584
|
const e = await this.getState(), r = e.currentPropertyId ? e.properties[e.currentPropertyId] : null;
|
|
565
585
|
return {
|
|
566
586
|
isFavorite: (r == null ? void 0 : r.favoritedUnits.includes(t)) ?? !1,
|
|
567
|
-
viewedDate: ((s = r == null ? void 0 : r.viewedUnits.find((
|
|
587
|
+
viewedDate: ((s = r == null ? void 0 : r.viewedUnits.find((a) => a.unitId === t)) == null ? void 0 : s.viewedDate) ?? ""
|
|
568
588
|
};
|
|
569
589
|
}
|
|
570
590
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.mjs","sources":["../../src/stores/store.ts"],"sourcesContent":["import { kvGet, kvSet } from \"../storage\";\nimport type { ZodObject, ZodType, ZodTypeAny } from \"zod\";\nimport {\n UnifiedStoreDataSchema,\n UserPropertyStateSchema,\n type UnifiedStoreData,\n type UserPropertyState,\n type Property,\n type Filters,\n type QueryParams,\n type ResultsMode,\n type SortBy,\n type TourContactData,\n type Unit,\n PropertySchema,\n TourContactDataSchema,\n UnitSchema,\n} from \"../schema\";\nimport { validate } from \"../validation\";\nimport { transformFiltersToUnitsSearchParams } from \"../features/filters/transformers\";\n\n// Default values\nconst defaultFilters: Filters = {\n date_availability: undefined,\n qty_bedrooms: undefined,\n base_price: undefined,\n highlights: undefined,\n};\n\nconst defaultUnifiedStoreData: UnifiedStoreData = {\n // Property data\n properties: {},\n currentPropertyId: null,\n currentPropertySlug: null,\n hasPreviouslySearched: [],\n\n // App data\n unitResults: [],\n filters: defaultFilters,\n tempFilters: defaultFilters,\n apiFilters: {\n limit: 10,\n page: 1,\n sortBy: \"relevance\",\n },\n resultsMode: \"all\",\n resolvedQuestionnaireValues: {},\n sortBy: \"relevance\",\n};\n\nconst toArray = (input: unknown): unknown[] => {\n if (input == null) return [];\n return Array.isArray(input) ? input : [input];\n};\n\nconst extractFilterValues = (value: unknown): unknown[] => {\n return toArray(value).flatMap(item => {\n if (item == null) return [];\n if (Array.isArray(item)) return item;\n if (typeof item === \"object\" && \"value\" in (item as any)) {\n const v = (item as any).value;\n return Array.isArray(v) ? v : v != null ? [v] : [];\n }\n return [item];\n });\n};\n\nconst toStringArray = (value: unknown): string[] =>\n extractFilterValues(value)\n .flatMap(v => (Array.isArray(v) ? v : [v]))\n .map(v => String(v))\n .map(v => v.trim())\n .filter(v => v.length > 0);\n\nconst toNumberArray = (value: unknown): number[] =>\n extractFilterValues(value)\n .map(v => {\n if (typeof v === \"number\" && Number.isFinite(v)) return v;\n const num = Number(v);\n return Number.isFinite(num) ? num : null;\n })\n .filter((v): v is number => v !== null);\n\nconst toNumberValue = (value: unknown): number | null => {\n if (value == null) return null;\n if (typeof value === \"number\") return Number.isFinite(value) ? value : null;\n if (typeof value === \"object\" && \"value\" in (value as any)) {\n return toNumberValue((value as any).value);\n }\n const num = Number(value);\n return Number.isFinite(num) ? num : null;\n};\n\n// Unified store class\nexport class UnifiedStore {\n /**\n * Resolves the persisted unified store snapshot, coercing legacy shapes into the latest schema\n * and sanitizing invalid entries where possible.\n */\n private async getState(): Promise<UnifiedStoreData> {\n const state = await kvGet<UnifiedStoreData>(\"app\");\n if (!state) {\n return defaultUnifiedStoreData;\n }\n\n const merged = {\n ...defaultUnifiedStoreData,\n ...state,\n properties: state.properties ?? {},\n unitResults: state.unitResults ?? [],\n currentPropertyId:\n state.currentPropertyId == null ? null : String(state.currentPropertyId),\n currentPropertySlug: state.currentPropertySlug ?? null,\n hasPreviouslySearched: Array.isArray(state.hasPreviouslySearched)\n ? state.hasPreviouslySearched.map(String)\n : [],\n };\n\n const parsed = UnifiedStoreDataSchema.safeParse(merged);\n if (parsed.success) return parsed.data;\n\n // Sanitize by dropping invalid property entries and unit results\n const sanitizedProperties = Object.entries(merged.properties ?? {}).reduce<\n Record<string, UserPropertyState>\n >((acc, [key, value]) => {\n const entry = UserPropertyStateSchema.safeParse(value);\n if (entry.success) acc[key] = entry.data;\n return acc;\n }, {});\n\n const rawUnitResults = Array.isArray(merged.unitResults)\n ? merged.unitResults\n : merged.unitResults && typeof merged.unitResults === \"object\"\n ? Object.values(merged.unitResults as Record<string, unknown>)\n : [];\n\n const sanitizedUnitResults = rawUnitResults.reduce<Unit[]>((acc, value) => {\n const entry = UnitSchema.safeParse(value);\n if (entry.success) acc.push(entry.data);\n return acc;\n }, []);\n\n const fallback = {\n ...merged,\n properties: sanitizedProperties,\n unitResults: sanitizedUnitResults,\n };\n\n const fallbackParsed = UnifiedStoreDataSchema.safeParse(fallback);\n return fallbackParsed.success ? fallbackParsed.data : defaultUnifiedStoreData;\n }\n\n /**\n * Applies an updater function to the current store state, validates the result, and persists it.\n *\n * @param updater - Pure function that maps the current state to the next state.\n */\n private async setState(updater: (state: UnifiedStoreData) => UnifiedStoreData): Promise<void> {\n const currentState = await this.getState();\n const newState = updater(currentState);\n const validatedState = UnifiedStoreDataSchema.parse(newState);\n await kvSet(\"app\", validatedState);\n }\n\n /**\n * Polls the persisted state until a current property pointer is available or the timeout elapses.\n *\n * @param timeoutMs - Maximum time in milliseconds to wait before failing.\n * @returns The active property ID once it becomes available.\n * @throws Error if the property pointer is not set before the timeout expires.\n */\n private async waitForCurrentProperty(timeoutMs = 1000): Promise<string> {\n const deadline = Date.now() + timeoutMs;\n\n while (Date.now() < deadline) {\n const state = await this.getState();\n const propertyId = state.currentPropertyId;\n if (propertyId && state.properties[propertyId]) return propertyId;\n\n await new Promise(resolve => setTimeout(resolve, 16));\n }\n\n const finalState = await this.getState();\n const propertyId = finalState.currentPropertyId;\n if (propertyId && finalState.properties[propertyId]) return propertyId;\n\n throw new Error(\"UnifiedStore: current property was not initialized in time\");\n }\n\n // === PROPERTY OPERATIONS ===\n\n /**\n * Ensures a property entry exists and registers it as the current property.\n *\n * @param propertyId - Identifier used to track the property.\n * @param slug - Canonical slug associated with the property.\n */\n async initializeProperty(propertyId: string | number, slug: string): Promise<void> {\n const id = String(propertyId);\n await this.setState(state => {\n if (state.properties && state.properties[id]) {\n return {\n ...state,\n currentPropertyId: id,\n currentPropertySlug: slug\n };\n }\n\n return {\n ...state,\n currentPropertyId: id,\n currentPropertySlug: slug,\n properties: {\n ...state.properties,\n [id]: {\n id,\n slug,\n favoritedUnits: [],\n tourContactedOn: null,\n viewedUnits: [],\n questionnaireResults: null,\n tourContactData: null,\n },\n },\n };\n });\n }\n\n // === UNIT RESULTS CACHE ===\n /**\n * Persists a collection of units after validating each entry against the provided schema.\n *\n * @param units - Raw units collection returned by an API call.\n * @param schema - Optional override schema when the default `UnitSchema` is not sufficient.\n */\n async setUnitResults(\n units: unknown,\n schema?: ZodTypeAny,\n ): Promise<void> {\n const baseSchema = (schema ?? UnitSchema) as ZodType<Unit>;\n const validatedUnits: Unit[] = [];\n const collection = Array.isArray(units)\n ? units\n : units && typeof units === \"object\"\n ? Object.values(units as Record<string, unknown>)\n : [];\n\n collection.forEach((unit, index) => {\n const parsed = validate(baseSchema, unit, `unitResults[${index}]`);\n if (parsed) validatedUnits.push(parsed);\n });\n await this.setState(state => ({\n ...state,\n unitResults: validatedUnits,\n }));\n }\n\n /**\n * Clears the cached unit results array.\n */\n async clearUnitResults(): Promise<void> {\n await this.setState(state => ({\n ...state,\n unitResults: [],\n }));\n }\n\n // === PROPERTY DATA BAG (full property payloads & custom data) ===\n /**\n * Replaces the persisted property payload with validated data.\n *\n * @param propertyId - ID of the property to mutate.\n * @param data - New property payload.\n * @param schema - Optional schema override used for validation.\n */\n async setPropertyData(\n propertyId: string | number,\n data: unknown,\n schema?: ZodObject<any, any, any, any, any>,\n ): Promise<void> {\n const id = String(propertyId);\n const baseSchema = (schema ?? PropertySchema) as ZodObject<any, any, any, any, any>;\n await this.setState(state => {\n const property = state.properties[id];\n if (!property) return state;\n const validated = validate(baseSchema, data, `properties.${id}.data`) as Property | null;\n if (!validated) return state;\n return {\n ...state,\n properties: {\n ...state.properties,\n [id]: {\n ...property,\n data: validated,\n },\n },\n };\n });\n }\n\n /**\n * Merges partial property data into the persisted payload with validation safeguards.\n *\n * @param propertyId - ID of the property to update.\n * @param partial - Partial payload to merge.\n * @param schema - Optional schema override for validation.\n */\n async mergePropertyData(\n propertyId: string | number,\n partial: unknown,\n schema?: ZodObject<any, any, any, any, any>,\n ): Promise<void> {\n const id = String(propertyId);\n const baseSchema = (schema ?? PropertySchema) as ZodObject<any, any, any, any, any>;\n await this.setState(state => {\n const property = state.properties[id];\n if (!property) return state;\n const current = property.data;\n if (!current) {\n const full = validate(baseSchema, partial, `properties.${id}.data`) as Property | null;\n if (!full) return state;\n return {\n ...state,\n properties: {\n ...state.properties,\n [id]: {\n ...property,\n data: full,\n },\n },\n };\n }\n\n const partialSchema = baseSchema.partial();\n const validatedPartial = validate(\n partialSchema,\n partial,\n `properties.${id}.data.partial`,\n ) as Partial<Property> | null;\n if (!validatedPartial) return state;\n const merged = validate(\n baseSchema,\n { ...current, ...validatedPartial },\n `properties.${id}.data`,\n ) as Property | null;\n if (!merged) return state;\n return {\n ...state,\n properties: {\n ...state.properties,\n [id]: {\n ...property,\n data: merged,\n },\n },\n };\n });\n }\n\n // Accepts a full API property object, validates, and stores it into the\n // per-property `data` bag. Ensures the property entry exists/updated.\n /**\n * Inserts or updates a property entry from an API payload, enforcing schema validation.\n *\n * @param apiProperty - Raw property object returned by an API.\n * @param schema - Optional schema override.\n */\n async upsertPropertyFromApi(\n apiProperty: unknown,\n schema?: ZodTypeAny,\n ): Promise<void> {\n const s = schema ?? PropertySchema;\n const parsed: any = s.parse(apiProperty);\n const id = parsed.id ?? parsed.propertyId;\n if (id === undefined || id === null) {\n throw new Error(\"upsertPropertyFromApi: property id is required\");\n }\n const propertyId = String(id);\n const slug: string | undefined = parsed.slug ?? undefined;\n\n await this.setState(state => {\n const existing = state.properties[propertyId];\n const next: UserPropertyState = existing\n ? {\n ...existing,\n ...(slug ? { slug } : {}),\n data: parsed,\n }\n : {\n id: propertyId,\n slug: slug ?? \"\",\n favoritedUnits: [],\n tourContactedOn: null,\n viewedUnits: [],\n questionnaireResults: null,\n tourContactData: null,\n data: parsed,\n };\n\n return {\n ...state,\n properties: {\n ...state.properties,\n [propertyId]: next,\n },\n };\n });\n }\n\n /**\n * Marks the provided property as current and optionally updates the slug.\n *\n * @param propertyId - Property identifier to focus.\n * @param slug - Optional slug override.\n */\n async setCurrentProperty(propertyId: string | number, slug?: string): Promise<void> {\n const id = String(propertyId);\n await this.setState(state => ({\n ...state,\n currentPropertyId: id,\n currentPropertySlug: slug || state.currentPropertySlug,\n }));\n }\n\n /**\n * Updates the slug for the current property selection.\n *\n * @param slug - New slug to persist.\n */\n async setCurrentPropertySlug(slug: string): Promise<void> {\n await this.setState(state => ({\n ...state,\n currentPropertySlug: slug\n }));\n }\n\n /**\n * Adds a slug to the `hasPreviouslySearched` list without duplicating existing entries.\n *\n * @param slug - Slug to record.\n */\n async setHasPreviouslySearched(slug: string): Promise<void> {\n await this.setState(state => ({\n ...state,\n hasPreviouslySearched: Array.from(\n new Set([...state.hasPreviouslySearched, slug])\n ),\n }));\n }\n\n /**\n * Toggles a unit's favorite state for the currently active property.\n *\n * @param unitId - Unit identifier to toggle.\n */\n async toggleFavorite(unitId: string): Promise<void> {\n await this.setState(state => {\n const propertyId = state.currentPropertyId;\n if (!propertyId) return state;\n\n const property = state.properties[propertyId];\n if (!property) return state;\n\n const isFavorited = property.favoritedUnits.includes(unitId);\n const updatedFavoritedUnits = isFavorited\n ? property.favoritedUnits.filter((id) => id !== unitId)\n : [...property.favoritedUnits, unitId];\n\n return {\n ...state,\n properties: {\n ...state.properties,\n [propertyId]: {\n ...property,\n favoritedUnits: updatedFavoritedUnits,\n },\n },\n };\n });\n }\n\n /**\n * Records the most recent view date for a unit and opens the unit URL in the browser when available.\n *\n * @param unitId - Identifier of the viewed unit.\n * @param slug - Property slug used to construct the URL.\n */\n async markUnitAsViewed(unitId: string, slug: string): Promise<void> {\n\n const url = `https://${slug}`;\n window.open(url, \"_blank\", \"noopener,noreferrer\");\n\n const today = new Date();\n const formattedDate = `${String(today.getMonth() + 1).padStart(\n 2,\n \"0\"\n )}/${String(today.getDate()).padStart(2, \"0\")}`;\n\n await this.setState(state => {\n const propertyId = state.currentPropertyId;\n if (!propertyId) return state;\n\n const property = state.properties[propertyId];\n if (!property) return state;\n\n const updatedViewedUnits = [\n ...property.viewedUnits.filter((u) => u.unitId !== unitId),\n { unitId, viewedDate: formattedDate },\n ];\n\n return {\n ...state,\n properties: {\n ...state.properties,\n [propertyId]: {\n ...property,\n viewedUnits: updatedViewedUnits,\n },\n },\n };\n });\n\n\n }\n\n /**\n * Stamps the current property with the moment the tour outreach occurred.\n */\n async setTourContactedOn(): Promise<void> {\n await this.setState(state => {\n const propertyId = state.currentPropertyId;\n if (!propertyId) return state;\n\n const property = state.properties[propertyId];\n if (!property) return state;\n\n return {\n ...state,\n properties: {\n ...state.properties,\n [propertyId]: {\n ...property,\n tourContactedOn: new Date().toISOString(),\n },\n },\n };\n });\n }\n\n /**\n * Reads the stored tour contact timestamp for the current property.\n *\n * @returns ISO string or null when no timestamp exists.\n */\n async getTourContactedOn(): Promise<string | null> {\n const state = await this.getState();\n const propertyId = state.currentPropertyId;\n if (!propertyId) return null;\n\n return state.properties[propertyId]?.tourContactedOn ?? null;\n }\n\n /**\n * Persists questionnaire results captured for the current property.\n *\n * @param results - Arbitrary questionnaire data.\n */\n async setQuestionnaireResults(results: unknown): Promise<void> {\n await this.setState(state => {\n const propertyId = state.currentPropertyId;\n if (!propertyId) return state;\n\n const property = state.properties[propertyId];\n if (!property) return state;\n\n return {\n ...state,\n properties: {\n ...state.properties,\n [propertyId]: {\n ...property,\n questionnaireResults: results,\n },\n },\n };\n });\n }\n\n /**\n * Persists structured tour contact preferences for the active property. The method waits until\n * a current property is available, allowing callers to invoke it before initialization completes.\n *\n * @param data - Contact preferences captured from the UI.\n */\n async setTourContactData(data: TourContactData): Promise<void> {\n const propertyId = await this.waitForCurrentProperty();\n\n await this.setState(state => {\n const property = state.properties[propertyId];\n if (!property) return state;\n\n return {\n ...state,\n properties: {\n ...state.properties,\n [propertyId]: {\n ...property,\n tourContactData: data,\n },\n },\n };\n });\n }\n\n\n\n\n\n\n\n // === FILTER OPERATIONS ===\n\n /**\n * Merges the provided filter values into the committed filter state.\n *\n * @param filters - Partial filter payload to apply.\n */\n async setFilters(filters: Partial<Filters>): Promise<void> {\n await this.setState(state => ({\n ...state,\n filters: { ...state.filters, ...filters }\n }));\n }\n\n /**\n * Updates the transient filters used for in-progress UI interactions.\n *\n * @param filters - Partial staging filter payload.\n */\n async setTempFilters(filters: Partial<Filters>): Promise<void> {\n await this.setState(state => ({\n ...state,\n tempFilters: { ...state.tempFilters, ...filters }\n }));\n }\n\n /**\n * Resets the committed filters to their default values.\n */\n async setFiltersToDefault(): Promise<void> {\n await this.setState(state => ({ ...state, filters: defaultFilters }));\n }\n\n /**\n * Merges partial values into the API filters payload used for network requests.\n *\n * @param filters - Partial query parameters to persist.\n */\n async setApiFilters(filters: Partial<QueryParams>): Promise<void> {\n await this.setState(state => ({\n ...state,\n apiFilters: { ...state.apiFilters, ...filters }\n }));\n }\n\n /**\n * Updates a single temporary filter field without touching the rest of the staged filters.\n *\n * @param key - Filter key to mutate.\n * @param value - New value to assign.\n */\n async handleTempFilterChange<K extends keyof Filters>(\n key: K,\n value: Filters[K]\n ): Promise<void> {\n await this.setState(state => ({\n ...state,\n tempFilters: { ...state.tempFilters, [key]: value }\n }));\n }\n\n /**\n * Normalizes the committed filters into API-ready structures and persists the result.\n */\n async submitFilterUpdate(): Promise<void> {\n await this.setState(state => {\n const apiParams: QueryParams = transformFiltersToUnitsSearchParams(\n {\n ...state.filters,\n limit: state.apiFilters.limit,\n page: state.apiFilters.page,\n sortBy: state.sortBy,\n },\n {\n defaultLimit: state.apiFilters.limit,\n defaultPage: state.apiFilters.page,\n defaultSort: state.sortBy,\n },\n );\n\n return {\n ...state,\n apiFilters: apiParams,\n };\n });\n }\n\n // === RESULTS AND SORTING ===\n\n /**\n * Persists the selected results mode (e.g. \"all\" or \"favorites\").\n *\n * @param mode - Mode identifier to store.\n */\n async setResultsMode(mode: ResultsMode): Promise<void> {\n await this.setState(state => ({ ...state, resultsMode: mode }));\n }\n\n /**\n * Persists the currently selected sort option.\n *\n * @param sortBy - Sort identifier.\n */\n async setSortBy(sortBy: SortBy): Promise<void> {\n await this.setState(state => ({ ...state, sortBy }));\n }\n\n // === QUESTIONNAIRE ===\n\n /**\n * Stores resolved questionnaire answers keyed by questionnaire name.\n *\n * @param name - Questionnaire identifier.\n * @param values - Selected option values.\n */\n async setResolvedQuestionnaireValues(name: string, values: string[]): Promise<void> {\n await this.setState(state => ({\n ...state,\n resolvedQuestionnaireValues: {\n ...state.resolvedQuestionnaireValues,\n [name]: values\n }\n }));\n }\n\n // === VISITOR UUID ===\n\n /**\n * Reads the persisted visitor UUID from the KV store.\n *\n * @returns The visitor UUID string or null when not yet set.\n */\n async getVisitorUUID(): Promise<string | null> {\n const user = await kvGet<{ visitor_uuid?: string }>(\"user\");\n return user?.visitor_uuid ?? null;\n }\n\n /**\n * Persists a visitor UUID to the KV store.\n *\n * @param vid - Visitor UUID string returned by the session API.\n */\n async setVisitorUUID(vid: string): Promise<void> {\n const current = await kvGet<Record<string, unknown>>(\"user\");\n const safe = current !== null && typeof current === \"object\" && !Array.isArray(current) ? current : {};\n await kvSet(\"user\", { ...safe, visitor_uuid: vid });\n }\n\n // === UTILITY METHODS ===\n\n /**\n * Returns convenience state for a unit within the current property.\n *\n * @param unitId - Identifier of the unit to inspect.\n * @returns Favorite flag and last viewed date.\n */\n async getUnitState(unitId: string): Promise<{\n isFavorite: boolean;\n viewedDate: string;\n }> {\n const state = await this.getState();\n const property = state.currentPropertyId ? state.properties[state.currentPropertyId] : null;\n\n return {\n isFavorite: property?.favoritedUnits.includes(unitId) ?? false,\n viewedDate:\n property?.viewedUnits.find((u) => u.unitId === unitId)?.viewedDate ?? \"\",\n };\n }\n\n /**\n * Builds a canonical results URL based on the current property slug.\n *\n * @returns Relative results URL or null when no property is selected.\n */\n async getResultsUrl(): Promise<string | null> {\n const state = await this.getState();\n return state.currentPropertySlug ? `/${state.currentPropertySlug}/results` : null;\n }\n\n /**\n * Retrieves the currently selected property entry.\n *\n * @returns Property state or null when unset.\n */\n async getCurrentProperty(): Promise<UserPropertyState | null> {\n const state = await this.getState();\n return state.currentPropertyId ? state.properties[state.currentPropertyId] ?? null : null;\n }\n\n /**\n * Retrieves property data for a specific property or defaults to the current property.\n *\n * @param propertyId - Optional property identifier to fetch.\n * @returns Property state or null when unavailable.\n */\n async getPropertyData(propertyId?: string | number): Promise<UserPropertyState | null> {\n const state = await this.getState();\n const id = propertyId == null ? state.currentPropertyId : String(propertyId);\n return id ? state.properties[id] ?? null : null;\n }\n\n /**\n * Reads and returns the full validated unified store state.\n */\n async getFullState(): Promise<UnifiedStoreData> {\n return this.getState();\n }\n\n /**\n * Hydrates the store with the default scaffold when no data has been persisted yet.\n */\n async initialize(): Promise<void> {\n // Ensure default shape is present; no-op if already initialized\n await this.setState(state => ({ ...defaultUnifiedStoreData, ...state }));\n }\n\n}\n\n// Export singleton instance\nexport const store = new UnifiedStore();\n// Alias to prefer neutral naming going forward\nexport { UnifiedStore as Store };\n// Re-export types for convenience (tests import from this module)\nexport type { UserPropertyState, Filters } from \"../schema\";\n"],"names":["defaultFilters","defaultUnifiedStoreData","UnifiedStore","state","kvGet","merged","parsed","UnifiedStoreDataSchema","sanitizedProperties","acc","key","value","entry","UserPropertyStateSchema","sanitizedUnitResults","UnitSchema","fallback","fallbackParsed","updater","currentState","newState","validatedState","kvSet","timeoutMs","deadline","propertyId","resolve","finalState","slug","id","units","schema","baseSchema","validatedUnits","unit","index","validate","data","PropertySchema","property","validated","partial","current","full","partialSchema","validatedPartial","apiProperty","existing","next","unitId","updatedFavoritedUnits","url","today","formattedDate","updatedViewedUnits","_a","results","filters","apiParams","transformFiltersToUnitsSearchParams","mode","sortBy","name","values","user","vid","safe","u","store"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"store.mjs","sources":["../../src/stores/store.ts"],"sourcesContent":["import { kvGet, kvSet } from \"../storage\";\nimport type { ZodObject, ZodType, ZodTypeAny } from \"zod\";\nimport {\n UnifiedStoreDataSchema,\n UserPropertyStateSchema,\n type UnifiedStoreData,\n type UserPropertyState,\n type Property,\n type Filters,\n type QueryParams,\n type ResultsMode,\n type SortBy,\n type TourContactData,\n type Unit,\n PropertySchema,\n TourContactDataSchema,\n UnitSchema,\n} from \"../schema\";\nimport { validate } from \"../validation\";\nimport { transformFiltersToUnitsSearchParams } from \"../features/filters/transformers\";\n\n// Default values\nconst defaultFilters: Filters = {\n date_availability: undefined,\n qty_bedrooms: undefined,\n base_price: undefined,\n highlights: undefined,\n};\n\nconst defaultUnifiedStoreData: UnifiedStoreData = {\n // Property data\n properties: {},\n currentPropertyId: null,\n currentPropertySlug: null,\n hasPreviouslySearched: [],\n\n // App data\n unitResults: [],\n filters: defaultFilters,\n tempFilters: defaultFilters,\n apiFilters: {\n limit: 10,\n page: 1,\n sortBy: \"relevance\",\n },\n resultsMode: \"all\",\n resolvedQuestionnaireValues: {},\n sortBy: \"relevance\",\n};\n\nconst toArray = (input: unknown): unknown[] => {\n if (input == null) return [];\n return Array.isArray(input) ? input : [input];\n};\n\nconst extractFilterValues = (value: unknown): unknown[] => {\n return toArray(value).flatMap(item => {\n if (item == null) return [];\n if (Array.isArray(item)) return item;\n if (typeof item === \"object\" && \"value\" in (item as any)) {\n const v = (item as any).value;\n return Array.isArray(v) ? v : v != null ? [v] : [];\n }\n return [item];\n });\n};\n\nconst toStringArray = (value: unknown): string[] =>\n extractFilterValues(value)\n .flatMap(v => (Array.isArray(v) ? v : [v]))\n .map(v => String(v))\n .map(v => v.trim())\n .filter(v => v.length > 0);\n\nconst toNumberArray = (value: unknown): number[] =>\n extractFilterValues(value)\n .map(v => {\n if (typeof v === \"number\" && Number.isFinite(v)) return v;\n const num = Number(v);\n return Number.isFinite(num) ? num : null;\n })\n .filter((v): v is number => v !== null);\n\nconst toNumberValue = (value: unknown): number | null => {\n if (value == null) return null;\n if (typeof value === \"number\") return Number.isFinite(value) ? value : null;\n if (typeof value === \"object\" && \"value\" in (value as any)) {\n return toNumberValue((value as any).value);\n }\n const num = Number(value);\n return Number.isFinite(num) ? num : null;\n};\n\n// Unified store class\nexport class UnifiedStore {\n /**\n * Resolves the persisted unified store snapshot, coercing legacy shapes into the latest schema\n * and sanitizing invalid entries where possible.\n */\n private async getState(): Promise<UnifiedStoreData> {\n const state = await kvGet<UnifiedStoreData>(\"app\");\n if (!state) {\n return defaultUnifiedStoreData;\n }\n\n const merged = {\n ...defaultUnifiedStoreData,\n ...state,\n properties: state.properties ?? {},\n unitResults: state.unitResults ?? [],\n currentPropertyId:\n state.currentPropertyId == null ? null : String(state.currentPropertyId),\n currentPropertySlug: state.currentPropertySlug ?? null,\n hasPreviouslySearched: Array.isArray(state.hasPreviouslySearched)\n ? state.hasPreviouslySearched.map(String)\n : [],\n };\n\n const parsed = UnifiedStoreDataSchema.safeParse(merged);\n if (parsed.success) return parsed.data;\n\n // Sanitize by dropping invalid property entries and unit results\n const sanitizedProperties = Object.entries(merged.properties ?? {}).reduce<\n Record<string, UserPropertyState>\n >((acc, [key, value]) => {\n const entry = UserPropertyStateSchema.safeParse(value);\n if (entry.success) acc[key] = entry.data;\n return acc;\n }, {});\n\n const rawUnitResults = Array.isArray(merged.unitResults)\n ? merged.unitResults\n : merged.unitResults && typeof merged.unitResults === \"object\"\n ? Object.values(merged.unitResults as Record<string, unknown>)\n : [];\n\n const sanitizedUnitResults = rawUnitResults.reduce<Unit[]>((acc, value) => {\n const entry = UnitSchema.safeParse(value);\n if (entry.success) acc.push(entry.data);\n return acc;\n }, []);\n\n const fallback = {\n ...merged,\n properties: sanitizedProperties,\n unitResults: sanitizedUnitResults,\n };\n\n const fallbackParsed = UnifiedStoreDataSchema.safeParse(fallback);\n return fallbackParsed.success ? fallbackParsed.data : defaultUnifiedStoreData;\n }\n\n /**\n * Applies an updater function to the current store state, validates the result, and persists it.\n *\n * @param updater - Pure function that maps the current state to the next state.\n */\n private async setState(updater: (state: UnifiedStoreData) => UnifiedStoreData): Promise<void> {\n const currentState = await this.getState();\n const newState = updater(currentState);\n const validatedState = UnifiedStoreDataSchema.parse(newState);\n await kvSet(\"app\", validatedState);\n }\n\n /**\n * Polls the persisted state until a current property pointer is available or the timeout elapses.\n *\n * @param timeoutMs - Maximum time in milliseconds to wait before failing.\n * @returns The active property ID once it becomes available.\n * @throws Error if the property pointer is not set before the timeout expires.\n */\n private async waitForCurrentProperty(timeoutMs = 1000): Promise<string> {\n const deadline = Date.now() + timeoutMs;\n\n while (Date.now() < deadline) {\n const state = await this.getState();\n const propertyId = state.currentPropertyId;\n if (propertyId && state.properties[propertyId]) return propertyId;\n\n await new Promise(resolve => setTimeout(resolve, 16));\n }\n\n const finalState = await this.getState();\n const propertyId = finalState.currentPropertyId;\n if (propertyId && finalState.properties[propertyId]) return propertyId;\n\n throw new Error(\"UnifiedStore: current property was not initialized in time\");\n }\n\n // === PROPERTY OPERATIONS ===\n\n /**\n * Ensures a property entry exists and registers it as the current property.\n *\n * @param propertyId - Identifier used to track the property.\n * @param slug - Canonical slug associated with the property.\n */\n async initializeProperty(propertyId: string | number, slug: string): Promise<void> {\n const id = String(propertyId);\n await this.setState(state => {\n if (state.properties && state.properties[id]) {\n return {\n ...state,\n currentPropertyId: id,\n currentPropertySlug: slug\n };\n }\n\n return {\n ...state,\n currentPropertyId: id,\n currentPropertySlug: slug,\n properties: {\n ...state.properties,\n [id]: {\n id,\n slug,\n favoritedUnits: [],\n tourContactedOn: null,\n viewedUnits: [],\n questionnaireResults: null,\n tourContactData: null,\n },\n },\n };\n });\n }\n\n // === UNIT RESULTS CACHE ===\n /**\n * Persists a collection of units after validating each entry against the provided schema.\n *\n * @param units - Raw units collection returned by an API call.\n * @param schema - Optional override schema when the default `UnitSchema` is not sufficient.\n */\n async setUnitResults(\n units: unknown,\n schema?: ZodTypeAny,\n ): Promise<void> {\n const baseSchema = (schema ?? UnitSchema) as ZodType<Unit>;\n const validatedUnits: Unit[] = [];\n const collection = Array.isArray(units)\n ? units\n : units && typeof units === \"object\"\n ? Object.values(units as Record<string, unknown>)\n : [];\n\n collection.forEach((unit, index) => {\n const parsed = validate(baseSchema, unit, `unitResults[${index}]`);\n if (parsed) validatedUnits.push(parsed);\n });\n await this.setState(state => ({\n ...state,\n unitResults: validatedUnits,\n }));\n }\n\n /**\n * Clears the cached unit results array.\n */\n async clearUnitResults(): Promise<void> {\n await this.setState(state => ({\n ...state,\n unitResults: [],\n }));\n }\n\n // === PROPERTY DATA BAG (full property payloads & custom data) ===\n /**\n * Replaces the persisted property payload with validated data.\n *\n * @param propertyId - ID of the property to mutate.\n * @param data - New property payload.\n * @param schema - Optional schema override used for validation.\n */\n async setPropertyData(\n propertyId: string | number,\n data: unknown,\n schema?: ZodObject<any, any, any, any, any>,\n ): Promise<void> {\n const id = String(propertyId);\n const baseSchema = (schema ?? PropertySchema) as ZodObject<any, any, any, any, any>;\n await this.setState(state => {\n const property = state.properties[id];\n if (!property) return state;\n const validated = validate(baseSchema, data, `properties.${id}.data`) as Property | null;\n if (!validated) return state;\n return {\n ...state,\n properties: {\n ...state.properties,\n [id]: {\n ...property,\n data: validated,\n },\n },\n };\n });\n }\n\n /**\n * Merges partial property data into the persisted payload with validation safeguards.\n *\n * @param propertyId - ID of the property to update.\n * @param partial - Partial payload to merge.\n * @param schema - Optional schema override for validation.\n */\n async mergePropertyData(\n propertyId: string | number,\n partial: unknown,\n schema?: ZodObject<any, any, any, any, any>,\n ): Promise<void> {\n const id = String(propertyId);\n const baseSchema = (schema ?? PropertySchema) as ZodObject<any, any, any, any, any>;\n await this.setState(state => {\n const property = state.properties[id];\n if (!property) return state;\n const current = property.data;\n if (!current) {\n const full = validate(baseSchema, partial, `properties.${id}.data`) as Property | null;\n if (!full) return state;\n return {\n ...state,\n properties: {\n ...state.properties,\n [id]: {\n ...property,\n data: full,\n },\n },\n };\n }\n\n const partialSchema = baseSchema.partial();\n const validatedPartial = validate(\n partialSchema,\n partial,\n `properties.${id}.data.partial`,\n ) as Partial<Property> | null;\n if (!validatedPartial) return state;\n const merged = validate(\n baseSchema,\n { ...current, ...validatedPartial },\n `properties.${id}.data`,\n ) as Property | null;\n if (!merged) return state;\n return {\n ...state,\n properties: {\n ...state.properties,\n [id]: {\n ...property,\n data: merged,\n },\n },\n };\n });\n }\n\n // Accepts a full API property object, validates, and stores it into the\n // per-property `data` bag. Ensures the property entry exists/updated.\n /**\n * Inserts or updates a property entry from an API payload, enforcing schema validation.\n *\n * @param apiProperty - Raw property object returned by an API.\n * @param schema - Optional schema override.\n */\n async upsertPropertyFromApi(\n apiProperty: unknown,\n schema?: ZodTypeAny,\n ): Promise<void> {\n const s = schema ?? PropertySchema;\n const parsed: any = s.parse(apiProperty);\n const id = parsed.id ?? parsed.propertyId;\n if (id === undefined || id === null) {\n throw new Error(\"upsertPropertyFromApi: property id is required\");\n }\n const propertyId = String(id);\n const slug: string | undefined = parsed.slug ?? undefined;\n\n await this.setState(state => {\n const existing = state.properties[propertyId];\n const next: UserPropertyState = existing\n ? {\n ...existing,\n ...(slug ? { slug } : {}),\n data: parsed,\n }\n : {\n id: propertyId,\n slug: slug ?? \"\",\n favoritedUnits: [],\n tourContactedOn: null,\n viewedUnits: [],\n questionnaireResults: null,\n tourContactData: null,\n data: parsed,\n };\n\n return {\n ...state,\n properties: {\n ...state.properties,\n [propertyId]: next,\n },\n };\n });\n }\n\n /**\n * Marks the provided property as current and optionally updates the slug.\n *\n * @param propertyId - Property identifier to focus.\n * @param slug - Optional slug override.\n */\n async setCurrentProperty(propertyId: string | number, slug?: string): Promise<void> {\n const id = String(propertyId);\n await this.setState(state => ({\n ...state,\n currentPropertyId: id,\n currentPropertySlug: slug || state.currentPropertySlug,\n }));\n }\n\n /**\n * Updates the slug for the current property selection.\n *\n * @param slug - New slug to persist.\n */\n async setCurrentPropertySlug(slug: string): Promise<void> {\n await this.setState(state => ({\n ...state,\n currentPropertySlug: slug\n }));\n }\n\n /**\n * Adds a slug to the `hasPreviouslySearched` list without duplicating existing entries.\n *\n * @param slug - Slug to record.\n */\n async setHasPreviouslySearched(slug: string): Promise<void> {\n await this.setState(state => ({\n ...state,\n hasPreviouslySearched: Array.from(\n new Set([...state.hasPreviouslySearched, slug])\n ),\n }));\n }\n\n /**\n * Replaces the favoritedUnits list for the current property with the provided array.\n * Intended for seeding IndexedDB from an API response (e.g. bootstrap endpoint).\n *\n * @param unitIds - Canonical list of favorited unit IDs from the API.\n */\n async setFavoriteUnitIds(unitIds: string[]): Promise<void> {\n await this.setState(state => {\n const propertyId = state.currentPropertyId;\n if (!propertyId) return state;\n\n const property = state.properties[propertyId];\n if (!property) return state;\n\n return {\n ...state,\n properties: {\n ...state.properties,\n [propertyId]: { ...property, favoritedUnits: unitIds },\n },\n };\n });\n }\n\n /**\n * Toggles a unit's favorite state for the currently active property.\n *\n * @param unitId - Unit identifier to toggle.\n */\n async toggleFavorite(unitId: string): Promise<void> {\n await this.setState(state => {\n const propertyId = state.currentPropertyId;\n if (!propertyId) return state;\n\n const property = state.properties[propertyId];\n if (!property) return state;\n\n const isFavorited = property.favoritedUnits.includes(unitId);\n const updatedFavoritedUnits = isFavorited\n ? property.favoritedUnits.filter((id) => id !== unitId)\n : [...property.favoritedUnits, unitId];\n\n return {\n ...state,\n properties: {\n ...state.properties,\n [propertyId]: {\n ...property,\n favoritedUnits: updatedFavoritedUnits,\n },\n },\n };\n });\n }\n\n /**\n * Records the most recent view date for a unit and opens the unit URL in the browser when available.\n *\n * @param unitId - Identifier of the viewed unit.\n * @param slug - Property slug used to construct the URL.\n */\n async markUnitAsViewed(unitId: string, slug: string): Promise<void> {\n\n const url = `https://${slug}`;\n window.open(url, \"_blank\", \"noopener,noreferrer\");\n\n const today = new Date();\n const formattedDate = `${String(today.getMonth() + 1).padStart(\n 2,\n \"0\"\n )}/${String(today.getDate()).padStart(2, \"0\")}`;\n\n await this.setState(state => {\n const propertyId = state.currentPropertyId;\n if (!propertyId) return state;\n\n const property = state.properties[propertyId];\n if (!property) return state;\n\n const updatedViewedUnits = [\n ...property.viewedUnits.filter((u) => u.unitId !== unitId),\n { unitId, viewedDate: formattedDate },\n ];\n\n return {\n ...state,\n properties: {\n ...state.properties,\n [propertyId]: {\n ...property,\n viewedUnits: updatedViewedUnits,\n },\n },\n };\n });\n\n\n }\n\n /**\n * Stamps the current property with the moment the tour outreach occurred.\n */\n async setTourContactedOn(): Promise<void> {\n await this.setState(state => {\n const propertyId = state.currentPropertyId;\n if (!propertyId) return state;\n\n const property = state.properties[propertyId];\n if (!property) return state;\n\n return {\n ...state,\n properties: {\n ...state.properties,\n [propertyId]: {\n ...property,\n tourContactedOn: new Date().toISOString(),\n },\n },\n };\n });\n }\n\n /**\n * Reads the stored tour contact timestamp for the current property.\n *\n * @returns ISO string or null when no timestamp exists.\n */\n async getTourContactedOn(): Promise<string | null> {\n const state = await this.getState();\n const propertyId = state.currentPropertyId;\n if (!propertyId) return null;\n\n return state.properties[propertyId]?.tourContactedOn ?? null;\n }\n\n /**\n * Persists questionnaire results captured for the current property.\n *\n * @param results - Arbitrary questionnaire data.\n */\n async setQuestionnaireResults(results: unknown): Promise<void> {\n await this.setState(state => {\n const propertyId = state.currentPropertyId;\n if (!propertyId) return state;\n\n const property = state.properties[propertyId];\n if (!property) return state;\n\n return {\n ...state,\n properties: {\n ...state.properties,\n [propertyId]: {\n ...property,\n questionnaireResults: results,\n },\n },\n };\n });\n }\n\n /**\n * Persists structured tour contact preferences for the active property. The method waits until\n * a current property is available, allowing callers to invoke it before initialization completes.\n *\n * @param data - Contact preferences captured from the UI.\n */\n async setTourContactData(data: TourContactData): Promise<void> {\n const propertyId = await this.waitForCurrentProperty();\n\n await this.setState(state => {\n const property = state.properties[propertyId];\n if (!property) return state;\n\n return {\n ...state,\n properties: {\n ...state.properties,\n [propertyId]: {\n ...property,\n tourContactData: data,\n },\n },\n };\n });\n }\n\n\n\n\n\n\n\n // === FILTER OPERATIONS ===\n\n /**\n * Merges the provided filter values into the committed filter state.\n *\n * @param filters - Partial filter payload to apply.\n */\n async setFilters(filters: Partial<Filters>): Promise<void> {\n await this.setState(state => ({\n ...state,\n filters: { ...state.filters, ...filters }\n }));\n }\n\n /**\n * Updates the transient filters used for in-progress UI interactions.\n *\n * @param filters - Partial staging filter payload.\n */\n async setTempFilters(filters: Partial<Filters>): Promise<void> {\n await this.setState(state => ({\n ...state,\n tempFilters: { ...state.tempFilters, ...filters }\n }));\n }\n\n /**\n * Resets the committed filters to their default values.\n */\n async setFiltersToDefault(): Promise<void> {\n await this.setState(state => ({ ...state, filters: defaultFilters }));\n }\n\n /**\n * Merges partial values into the API filters payload used for network requests.\n *\n * @param filters - Partial query parameters to persist.\n */\n async setApiFilters(filters: Partial<QueryParams>): Promise<void> {\n await this.setState(state => ({\n ...state,\n apiFilters: { ...state.apiFilters, ...filters }\n }));\n }\n\n /**\n * Updates a single temporary filter field without touching the rest of the staged filters.\n *\n * @param key - Filter key to mutate.\n * @param value - New value to assign.\n */\n async handleTempFilterChange<K extends keyof Filters>(\n key: K,\n value: Filters[K]\n ): Promise<void> {\n await this.setState(state => ({\n ...state,\n tempFilters: { ...state.tempFilters, [key]: value }\n }));\n }\n\n /**\n * Normalizes the committed filters into API-ready structures and persists the result.\n */\n async submitFilterUpdate(): Promise<void> {\n await this.setState(state => {\n const apiParams: QueryParams = transformFiltersToUnitsSearchParams(\n {\n ...state.filters,\n limit: state.apiFilters.limit,\n page: state.apiFilters.page,\n sortBy: state.sortBy,\n },\n {\n defaultLimit: state.apiFilters.limit,\n defaultPage: state.apiFilters.page,\n defaultSort: state.sortBy,\n },\n );\n\n return {\n ...state,\n apiFilters: apiParams,\n };\n });\n }\n\n // === RESULTS AND SORTING ===\n\n /**\n * Persists the selected results mode (e.g. \"all\" or \"favorites\").\n *\n * @param mode - Mode identifier to store.\n */\n async setResultsMode(mode: ResultsMode): Promise<void> {\n await this.setState(state => ({ ...state, resultsMode: mode }));\n }\n\n /**\n * Persists the currently selected sort option.\n *\n * @param sortBy - Sort identifier.\n */\n async setSortBy(sortBy: SortBy): Promise<void> {\n await this.setState(state => ({ ...state, sortBy }));\n }\n\n // === QUESTIONNAIRE ===\n\n /**\n * Stores resolved questionnaire answers keyed by questionnaire name.\n *\n * @param name - Questionnaire identifier.\n * @param values - Selected option values.\n */\n async setResolvedQuestionnaireValues(name: string, values: string[]): Promise<void> {\n await this.setState(state => ({\n ...state,\n resolvedQuestionnaireValues: {\n ...state.resolvedQuestionnaireValues,\n [name]: values\n }\n }));\n }\n\n // === VISITOR UUID ===\n\n /**\n * Reads the persisted visitor UUID from the KV store.\n *\n * @returns The visitor UUID string or null when not yet set.\n */\n async getVisitorUUID(): Promise<string | null> {\n const user = await kvGet<{ visitor_uuid?: string }>(\"user\");\n return user?.visitor_uuid ?? null;\n }\n\n /**\n * Persists a visitor UUID to the KV store.\n *\n * @param vid - Visitor UUID string returned by the session API.\n */\n async setVisitorUUID(vid: string): Promise<void> {\n const current = await kvGet<Record<string, unknown>>(\"user\");\n const safe = current !== null && typeof current === \"object\" && !Array.isArray(current) ? current : {};\n await kvSet(\"user\", { ...safe, visitor_uuid: vid });\n }\n\n // === UTILITY METHODS ===\n\n /**\n * Returns convenience state for a unit within the current property.\n *\n * @param unitId - Identifier of the unit to inspect.\n * @returns Favorite flag and last viewed date.\n */\n async getUnitState(unitId: string): Promise<{\n isFavorite: boolean;\n viewedDate: string;\n }> {\n const state = await this.getState();\n const property = state.currentPropertyId ? state.properties[state.currentPropertyId] : null;\n\n return {\n isFavorite: property?.favoritedUnits.includes(unitId) ?? false,\n viewedDate:\n property?.viewedUnits.find((u) => u.unitId === unitId)?.viewedDate ?? \"\",\n };\n }\n\n /**\n * Builds a canonical results URL based on the current property slug.\n *\n * @returns Relative results URL or null when no property is selected.\n */\n async getResultsUrl(): Promise<string | null> {\n const state = await this.getState();\n return state.currentPropertySlug ? `/${state.currentPropertySlug}/results` : null;\n }\n\n /**\n * Retrieves the currently selected property entry.\n *\n * @returns Property state or null when unset.\n */\n async getCurrentProperty(): Promise<UserPropertyState | null> {\n const state = await this.getState();\n return state.currentPropertyId ? state.properties[state.currentPropertyId] ?? null : null;\n }\n\n /**\n * Retrieves property data for a specific property or defaults to the current property.\n *\n * @param propertyId - Optional property identifier to fetch.\n * @returns Property state or null when unavailable.\n */\n async getPropertyData(propertyId?: string | number): Promise<UserPropertyState | null> {\n const state = await this.getState();\n const id = propertyId == null ? state.currentPropertyId : String(propertyId);\n return id ? state.properties[id] ?? null : null;\n }\n\n /**\n * Reads and returns the full validated unified store state.\n */\n async getFullState(): Promise<UnifiedStoreData> {\n return this.getState();\n }\n\n /**\n * Hydrates the store with the default scaffold when no data has been persisted yet.\n */\n async initialize(): Promise<void> {\n // Ensure default shape is present; no-op if already initialized\n await this.setState(state => ({ ...defaultUnifiedStoreData, ...state }));\n }\n\n}\n\n// Export singleton instance\nexport const store = new UnifiedStore();\n// Alias to prefer neutral naming going forward\nexport { UnifiedStore as Store };\n// Re-export types for convenience (tests import from this module)\nexport type { UserPropertyState, Filters } from \"../schema\";\n"],"names":["defaultFilters","defaultUnifiedStoreData","UnifiedStore","state","kvGet","merged","parsed","UnifiedStoreDataSchema","sanitizedProperties","acc","key","value","entry","UserPropertyStateSchema","sanitizedUnitResults","UnitSchema","fallback","fallbackParsed","updater","currentState","newState","validatedState","kvSet","timeoutMs","deadline","propertyId","resolve","finalState","slug","id","units","schema","baseSchema","validatedUnits","unit","index","validate","data","PropertySchema","property","validated","partial","current","full","partialSchema","validatedPartial","apiProperty","existing","next","unitIds","unitId","updatedFavoritedUnits","url","today","formattedDate","updatedViewedUnits","_a","results","filters","apiParams","transformFiltersToUnitsSearchParams","mode","sortBy","name","values","user","vid","safe","u","store"],"mappings":"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"}
|