@kasuvia/sdk 0.0.2 → 0.0.5
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/hooks/index.d.mts +430 -0
- package/dist/hooks/index.d.ts +430 -0
- package/dist/hooks/index.js +3073 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/hooks/index.mjs +2962 -0
- package/dist/hooks/index.mjs.map +1 -0
- package/dist/index-CxNLI4nw.d.ts +786 -0
- package/dist/index-CzVMyUs4.d.mts +492 -0
- package/dist/index-CzVMyUs4.d.ts +492 -0
- package/dist/index-Dowl5224.d.mts +786 -0
- package/dist/index.d.mts +48 -1739
- package/dist/index.d.ts +48 -1739
- package/dist/index.js +1544 -2359
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1527 -2258
- package/dist/index.mjs.map +1 -1
- package/dist/sdk-context-BuarJbeb.d.ts +75 -0
- package/dist/sdk-context-Db8kf1Tv.d.mts +75 -0
- package/dist/services/index.d.mts +2 -0
- package/dist/services/index.d.ts +2 -0
- package/dist/services/index.js +2369 -0
- package/dist/services/index.js.map +1 -0
- package/dist/services/index.mjs +2252 -0
- package/dist/services/index.mjs.map +1 -0
- package/package.json +11 -2
- package/src/config/index.ts +10 -91
- package/src/constants.ts +13 -0
- package/src/context/sdk-context.tsx +70 -0
- package/src/graphql/collections.graphql.ts +2 -10
- package/src/graphql/products.graphql.ts +215 -65
- package/src/graphql/wishlist.graphql.ts +7 -6
- package/src/hooks/index.ts +2 -0
- package/src/hooks/use-auth.ts +82 -158
- package/src/hooks/use-bespoke-availability.ts +25 -8
- package/src/hooks/use-cart.ts +222 -119
- package/src/hooks/use-cms.ts +179 -86
- package/src/hooks/use-collections.ts +52 -15
- package/src/hooks/use-consultation-stream.ts +4 -3
- package/src/hooks/use-consultations.ts +120 -51
- package/src/hooks/use-countries.ts +35 -13
- package/src/hooks/use-currencies.ts +26 -13
- package/src/hooks/use-google-translate.ts +22 -8
- package/src/hooks/use-languages.ts +40 -20
- package/src/hooks/use-mobile.ts +23 -0
- package/src/hooks/use-order-stream.ts +9 -5
- package/src/hooks/use-orders.ts +99 -44
- package/src/hooks/use-payment.ts +108 -40
- package/src/hooks/use-products.ts +251 -53
- package/src/hooks/use-service-booking.ts +152 -90
- package/src/hooks/use-states.ts +35 -15
- package/src/hooks/use-wishlist.ts +92 -91
- package/src/index.ts +26 -30
- package/src/services/auth.service.ts +209 -167
- package/src/services/bespoke.service.ts +12 -4
- package/src/services/cart.service.ts +172 -70
- package/src/services/cms.service.ts +70 -35
- package/src/services/collection.service.ts +22 -5
- package/src/services/config.service.ts +34 -14
- package/src/services/consultation.service.ts +72 -18
- package/src/services/logistics.service.ts +35 -11
- package/src/services/notifications.service.ts +27 -12
- package/src/services/order.service.ts +74 -15
- package/src/services/payment.service.ts +86 -31
- package/src/services/product.service.ts +279 -39
- package/src/services/service-booking.service.ts +98 -26
- package/src/services/wishlist.service.ts +69 -25
- package/src/types/auth/index.ts +6 -4
- package/src/types/business/index.ts +7 -2
- package/src/types/payments/index.ts +3 -3
- package/src/types/services/index.ts +2 -5
- package/src/types/store/index.ts +38 -3
- package/src/utils/error-handler.ts +10 -5
- package/src/utils/storage.ts +48 -26
- package/src/utils/validators.ts +85 -0
- package/src/client/authClient.ts +0 -135
- package/src/client/graphqlClient.ts +0 -53
- package/src/client/httpClient.ts +0 -298
package/src/hooks/use-cms.ts
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* CMS Hooks
|
|
3
3
|
*
|
|
4
4
|
* React Query hooks for CMS model and entry operations.
|
|
5
|
+
* config and accessToken are optional — if omitted, they are read from SdkContext.
|
|
5
6
|
*/
|
|
6
7
|
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
|
|
7
8
|
import {
|
|
@@ -11,14 +12,15 @@ import {
|
|
|
11
12
|
updateCmsEntry,
|
|
12
13
|
deleteCmsEntry,
|
|
13
14
|
} from '../services/cms.service'
|
|
14
|
-
import {
|
|
15
|
+
import type { SdkConfig } from '../config'
|
|
15
16
|
import type {
|
|
16
17
|
CmsEntry,
|
|
17
|
-
CmsEntryListResponse,
|
|
18
18
|
CreateCmsEntryParams,
|
|
19
19
|
UpdateCmsEntryParams,
|
|
20
20
|
ListCmsEntriesParams,
|
|
21
21
|
} from '../types/cms'
|
|
22
|
+
import { logger } from '../utils'
|
|
23
|
+
import { useSdkContext, resolveHookArgs } from '../context/sdk-context'
|
|
22
24
|
|
|
23
25
|
export interface UseCmsEntriesReturn {
|
|
24
26
|
entries: CmsEntry[]
|
|
@@ -32,25 +34,57 @@ export interface UseCmsEntriesReturn {
|
|
|
32
34
|
|
|
33
35
|
/**
|
|
34
36
|
* Hook to list CMS entries for a specific model.
|
|
37
|
+
* Signature can be:
|
|
38
|
+
* useCmsEntries(config, modelSlug, params)
|
|
39
|
+
* useCmsEntries(modelSlug, params)
|
|
35
40
|
*/
|
|
36
41
|
export function useCmsEntries(
|
|
37
|
-
|
|
38
|
-
|
|
42
|
+
configOrModelSlug: SdkConfig | string,
|
|
43
|
+
modelSlugOrParams?: string | ListCmsEntriesParams,
|
|
44
|
+
maybeParams?: ListCmsEntriesParams
|
|
39
45
|
): UseCmsEntriesReturn {
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
46
|
+
const ctx = useSdkContext()
|
|
47
|
+
let cfg: SdkConfig
|
|
48
|
+
let slug: string
|
|
49
|
+
let params: ListCmsEntriesParams | undefined
|
|
50
|
+
|
|
51
|
+
if (typeof configOrModelSlug === 'string') {
|
|
52
|
+
slug = configOrModelSlug
|
|
53
|
+
params = modelSlugOrParams as ListCmsEntriesParams | undefined
|
|
54
|
+
cfg = resolveHookArgs(undefined, undefined, ctx).config
|
|
55
|
+
} else {
|
|
56
|
+
cfg = configOrModelSlug
|
|
57
|
+
slug = modelSlugOrParams as string
|
|
58
|
+
params = maybeParams
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
try {
|
|
62
|
+
const query = useQuery({
|
|
63
|
+
queryKey: ['cms-entries', slug, params],
|
|
64
|
+
queryFn: () => listCmsEntries(cfg, slug, params),
|
|
65
|
+
enabled: !!slug,
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
return {
|
|
69
|
+
entries: query.data?.entries || [],
|
|
70
|
+
total: query.data?.total || 0,
|
|
71
|
+
page: query.data?.page || 1,
|
|
72
|
+
page_size: query.data?.page_size || 50,
|
|
73
|
+
isLoading: query.isLoading,
|
|
74
|
+
error: query.error as Error | null,
|
|
75
|
+
refetch: query.refetch,
|
|
76
|
+
}
|
|
77
|
+
} catch (error) {
|
|
78
|
+
logger.warn('[useCmsEntries] Called outside QueryClientProvider, returning empty list')
|
|
79
|
+
return {
|
|
80
|
+
entries: [],
|
|
81
|
+
total: 0,
|
|
82
|
+
page: 1,
|
|
83
|
+
page_size: 50,
|
|
84
|
+
isLoading: false,
|
|
85
|
+
error: null,
|
|
86
|
+
refetch: () => {},
|
|
87
|
+
}
|
|
54
88
|
}
|
|
55
89
|
}
|
|
56
90
|
|
|
@@ -63,22 +97,51 @@ export interface UseCmsEntryReturn {
|
|
|
63
97
|
|
|
64
98
|
/**
|
|
65
99
|
* Hook to get a single CMS entry by ID.
|
|
100
|
+
* Signature can be:
|
|
101
|
+
* useCmsEntry(config, modelSlug, entryId)
|
|
102
|
+
* useCmsEntry(modelSlug, entryId)
|
|
66
103
|
*/
|
|
67
104
|
export function useCmsEntry(
|
|
68
|
-
|
|
69
|
-
|
|
105
|
+
configOrModelSlug: SdkConfig | string,
|
|
106
|
+
modelSlugOrEntryId: string,
|
|
107
|
+
maybeEntryId?: string
|
|
70
108
|
): UseCmsEntryReturn {
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
109
|
+
const ctx = useSdkContext()
|
|
110
|
+
let cfg: SdkConfig
|
|
111
|
+
let slug: string
|
|
112
|
+
let entryId: string
|
|
113
|
+
|
|
114
|
+
if (maybeEntryId !== undefined) {
|
|
115
|
+
cfg = configOrModelSlug as SdkConfig
|
|
116
|
+
slug = modelSlugOrEntryId
|
|
117
|
+
entryId = maybeEntryId
|
|
118
|
+
} else {
|
|
119
|
+
cfg = resolveHookArgs(undefined, undefined, ctx).config
|
|
120
|
+
slug = configOrModelSlug as string
|
|
121
|
+
entryId = modelSlugOrEntryId
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
try {
|
|
125
|
+
const query = useQuery({
|
|
126
|
+
queryKey: ['cms-entry', slug, entryId],
|
|
127
|
+
queryFn: () => getCmsEntry(cfg, slug, entryId),
|
|
128
|
+
enabled: !!slug && !!entryId,
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
return {
|
|
132
|
+
entry: query.data,
|
|
133
|
+
isLoading: query.isLoading,
|
|
134
|
+
error: query.error as Error | null,
|
|
135
|
+
refetch: query.refetch,
|
|
136
|
+
}
|
|
137
|
+
} catch (error) {
|
|
138
|
+
logger.warn('[useCmsEntry] Called outside QueryClientProvider, returning undefined')
|
|
139
|
+
return {
|
|
140
|
+
entry: undefined,
|
|
141
|
+
isLoading: false,
|
|
142
|
+
error: null,
|
|
143
|
+
refetch: () => {},
|
|
144
|
+
}
|
|
82
145
|
}
|
|
83
146
|
}
|
|
84
147
|
|
|
@@ -88,23 +151,32 @@ export interface UseCreateCmsEntryReturn {
|
|
|
88
151
|
error: Error | null
|
|
89
152
|
}
|
|
90
153
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
154
|
+
export function useCreateCmsEntry(config?: SdkConfig, accessToken?: string | null, modelSlug?: string): UseCreateCmsEntryReturn {
|
|
155
|
+
const ctx = useSdkContext()
|
|
156
|
+
try {
|
|
157
|
+
const { config: cfg, accessToken: token } = resolveHookArgs(config, accessToken, ctx)
|
|
158
|
+
const queryClient = useQueryClient()
|
|
159
|
+
|
|
160
|
+
const mutation = useMutation({
|
|
161
|
+
mutationFn: (params: CreateCmsEntryParams) =>
|
|
162
|
+
token && modelSlug ? createCmsEntry(cfg, token, modelSlug, params) : Promise.reject('No access token or modelSlug'),
|
|
163
|
+
onSuccess: () => {
|
|
164
|
+
if (modelSlug) queryClient.invalidateQueries({ queryKey: ['cms-entries', modelSlug] })
|
|
165
|
+
},
|
|
166
|
+
})
|
|
167
|
+
|
|
168
|
+
return {
|
|
169
|
+
createEntry: mutation.mutate,
|
|
170
|
+
isLoading: mutation.isPending,
|
|
171
|
+
error: mutation.error as Error | null,
|
|
172
|
+
}
|
|
173
|
+
} catch (error) {
|
|
174
|
+
logger.warn('[useCreateCmsEntry] Called outside QueryClientProvider, returning no-op mutation')
|
|
175
|
+
return {
|
|
176
|
+
createEntry: () => {},
|
|
177
|
+
isLoading: false,
|
|
178
|
+
error: null,
|
|
179
|
+
}
|
|
108
180
|
}
|
|
109
181
|
}
|
|
110
182
|
|
|
@@ -114,26 +186,36 @@ export interface UseUpdateCmsEntryReturn {
|
|
|
114
186
|
error: Error | null
|
|
115
187
|
}
|
|
116
188
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
189
|
+
export function useUpdateCmsEntry(config?: SdkConfig, accessToken?: string | null, modelSlug?: string): UseUpdateCmsEntryReturn {
|
|
190
|
+
const ctx = useSdkContext()
|
|
191
|
+
try {
|
|
192
|
+
const { config: cfg, accessToken: token } = resolveHookArgs(config, accessToken, ctx)
|
|
193
|
+
const queryClient = useQueryClient()
|
|
194
|
+
|
|
195
|
+
const mutation = useMutation({
|
|
196
|
+
mutationFn: ({ entryId, params }: { entryId: string; params: UpdateCmsEntryParams }) =>
|
|
197
|
+
token && modelSlug ? updateCmsEntry(cfg, token, modelSlug, entryId, params) : Promise.reject('No access token or modelSlug'),
|
|
198
|
+
onSuccess: () => {
|
|
199
|
+
if (modelSlug) {
|
|
200
|
+
queryClient.invalidateQueries({ queryKey: ['cms-entries', modelSlug] })
|
|
201
|
+
queryClient.invalidateQueries({ queryKey: ['cms-entry', modelSlug] })
|
|
202
|
+
}
|
|
203
|
+
},
|
|
204
|
+
})
|
|
205
|
+
|
|
206
|
+
return {
|
|
207
|
+
updateEntry: (entryId: string, params: UpdateCmsEntryParams) =>
|
|
208
|
+
mutation.mutate({ entryId, params }),
|
|
209
|
+
isLoading: mutation.isPending,
|
|
210
|
+
error: mutation.error as Error | null,
|
|
211
|
+
}
|
|
212
|
+
} catch (error) {
|
|
213
|
+
logger.warn('[useUpdateCmsEntry] Called outside QueryClientProvider, returning no-op mutation')
|
|
214
|
+
return {
|
|
215
|
+
updateEntry: () => {},
|
|
216
|
+
isLoading: false,
|
|
217
|
+
error: null,
|
|
218
|
+
}
|
|
137
219
|
}
|
|
138
220
|
}
|
|
139
221
|
|
|
@@ -143,23 +225,34 @@ export interface UseDeleteCmsEntryReturn {
|
|
|
143
225
|
error: Error | null
|
|
144
226
|
}
|
|
145
227
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
228
|
+
export function useDeleteCmsEntry(config?: SdkConfig, accessToken?: string | null, modelSlug?: string): UseDeleteCmsEntryReturn {
|
|
229
|
+
const ctx = useSdkContext()
|
|
230
|
+
try {
|
|
231
|
+
const { config: cfg, accessToken: token } = resolveHookArgs(config, accessToken, ctx)
|
|
232
|
+
const queryClient = useQueryClient()
|
|
233
|
+
|
|
234
|
+
const mutation = useMutation({
|
|
235
|
+
mutationFn: (entryId: string) =>
|
|
236
|
+
token && modelSlug ? deleteCmsEntry(cfg, token, modelSlug, entryId) : Promise.reject('No access token or modelSlug'),
|
|
237
|
+
onSuccess: () => {
|
|
238
|
+
if (modelSlug) {
|
|
239
|
+
queryClient.invalidateQueries({ queryKey: ['cms-entries', modelSlug] })
|
|
240
|
+
queryClient.invalidateQueries({ queryKey: ['cms-entry', modelSlug] })
|
|
241
|
+
}
|
|
242
|
+
},
|
|
243
|
+
})
|
|
244
|
+
|
|
245
|
+
return {
|
|
246
|
+
deleteEntry: mutation.mutate,
|
|
247
|
+
isLoading: mutation.isPending,
|
|
248
|
+
error: mutation.error as Error | null,
|
|
249
|
+
}
|
|
250
|
+
} catch (error) {
|
|
251
|
+
logger.warn('[useDeleteCmsEntry] Called outside QueryClientProvider, returning no-op mutation')
|
|
252
|
+
return {
|
|
253
|
+
deleteEntry: () => {},
|
|
254
|
+
isLoading: false,
|
|
255
|
+
error: null,
|
|
256
|
+
}
|
|
164
257
|
}
|
|
165
258
|
}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Collections Hooks
|
|
3
3
|
*
|
|
4
|
-
* React Query hooks for fetching collections.
|
|
4
|
+
* React Query hooks for fetching collections via Next.js API routes.
|
|
5
|
+
* Client-side hooks fetch from API routes to avoid exposing backend URLs to browser.
|
|
5
6
|
*/
|
|
6
7
|
import { useQuery } from '@tanstack/react-query'
|
|
7
|
-
import { getStorefrontCollections, getStorefrontCollectionBySlug } from '../services/collection.service'
|
|
8
8
|
import type { ListParams } from '../types/store'
|
|
9
9
|
import { getCacheTier } from '../utils/cache'
|
|
10
|
+
import { logger } from '../utils'
|
|
10
11
|
|
|
11
12
|
export const collectionKeys = {
|
|
12
13
|
all: ['core', 'collections'] as const,
|
|
@@ -16,25 +17,61 @@ export const collectionKeys = {
|
|
|
16
17
|
|
|
17
18
|
/**
|
|
18
19
|
* Hook to fetch paginated collections for the storefront.
|
|
20
|
+
* Fetches from Next.js API route to avoid exposing backend URLs.
|
|
19
21
|
*/
|
|
20
22
|
export function useStorefrontCollections(params?: ListParams) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
try {
|
|
24
|
+
const queryParams = new URLSearchParams()
|
|
25
|
+
if (params?.page) queryParams.set('page', params.page.toString())
|
|
26
|
+
if (params?.pageSize) queryParams.set('pageSize', params.pageSize.toString())
|
|
27
|
+
|
|
28
|
+
return useQuery({
|
|
29
|
+
queryKey: collectionKeys.list(params),
|
|
30
|
+
queryFn: async () => {
|
|
31
|
+
const response = await fetch(`/api/collections?${queryParams.toString()}`)
|
|
32
|
+
if (!response.ok) throw new Error('Failed to fetch collections')
|
|
33
|
+
return response.json()
|
|
34
|
+
},
|
|
35
|
+
// medium — collections change infrequently
|
|
36
|
+
...getCacheTier('medium'),
|
|
37
|
+
})
|
|
38
|
+
} catch (error) {
|
|
39
|
+
logger.warn('[useStorefrontCollections] Called outside QueryClientProvider, returning empty list')
|
|
40
|
+
return {
|
|
41
|
+
data: undefined,
|
|
42
|
+
isLoading: false,
|
|
43
|
+
error: null,
|
|
44
|
+
isFetching: false,
|
|
45
|
+
refetch: () => Promise.resolve({ data: undefined }),
|
|
46
|
+
} as any
|
|
47
|
+
}
|
|
27
48
|
}
|
|
28
49
|
|
|
29
50
|
/**
|
|
30
51
|
* Hook to fetch a single collection by slug for the storefront.
|
|
52
|
+
* Fetches from Next.js API route to avoid exposing backend URLs.
|
|
31
53
|
*/
|
|
32
54
|
export function useStorefrontCollection(slug: string) {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
55
|
+
try {
|
|
56
|
+
return useQuery({
|
|
57
|
+
queryKey: collectionKeys.slug(slug),
|
|
58
|
+
queryFn: async () => {
|
|
59
|
+
const response = await fetch(`/api/collections/${slug}`)
|
|
60
|
+
if (!response.ok) throw new Error('Failed to fetch collection')
|
|
61
|
+
return response.json()
|
|
62
|
+
},
|
|
63
|
+
// medium — collection details change infrequently
|
|
64
|
+
...getCacheTier('medium'),
|
|
65
|
+
enabled: !!slug,
|
|
66
|
+
})
|
|
67
|
+
} catch (error) {
|
|
68
|
+
logger.warn('[useStorefrontCollection] Called outside QueryClientProvider, returning undefined')
|
|
69
|
+
return {
|
|
70
|
+
data: undefined,
|
|
71
|
+
isLoading: false,
|
|
72
|
+
error: null,
|
|
73
|
+
isFetching: false,
|
|
74
|
+
refetch: () => Promise.resolve({ data: undefined }),
|
|
75
|
+
} as any
|
|
76
|
+
}
|
|
40
77
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { useEffect, useRef, useState } from 'react';
|
|
4
4
|
import { fetchEventSource, EventSourceMessage } from '@microsoft/fetch-event-source';
|
|
5
|
-
import {
|
|
5
|
+
import type { SdkConfig } from '../config';
|
|
6
6
|
import { logger } from '../utils';
|
|
7
7
|
|
|
8
8
|
interface ConsultationMessageData {
|
|
@@ -39,6 +39,7 @@ interface ConsultationStatusData {
|
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
interface UseConsultationStreamOptions {
|
|
42
|
+
config: SdkConfig;
|
|
42
43
|
consultationId: string;
|
|
43
44
|
onMessage?: (data: ConsultationMessageData) => void;
|
|
44
45
|
onQuote?: (data: ConsultationQuoteData) => void;
|
|
@@ -47,6 +48,7 @@ interface UseConsultationStreamOptions {
|
|
|
47
48
|
}
|
|
48
49
|
|
|
49
50
|
export function useConsultationStream({
|
|
51
|
+
config,
|
|
50
52
|
consultationId,
|
|
51
53
|
onMessage,
|
|
52
54
|
onQuote,
|
|
@@ -65,8 +67,7 @@ export function useConsultationStream({
|
|
|
65
67
|
const abortController = new AbortController();
|
|
66
68
|
abortControllerRef.current = abortController;
|
|
67
69
|
|
|
68
|
-
const
|
|
69
|
-
const streamUrl = `${paymentUrl}/events/stream/consultation/${consultationId}`;
|
|
70
|
+
const streamUrl = `${config.backendUrls.payment}/events/stream/consultation/${consultationId}`;
|
|
70
71
|
|
|
71
72
|
fetchEventSource(streamUrl, {
|
|
72
73
|
method: 'GET',
|
|
@@ -1,76 +1,145 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Consultations Hooks
|
|
3
|
-
*
|
|
3
|
+
*
|
|
4
4
|
* React Query hooks for consultation operations.
|
|
5
|
+
* config and accessToken are optional — if omitted, they are read from SdkContext.
|
|
5
6
|
*/
|
|
6
7
|
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
|
|
7
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
getConsultations,
|
|
10
|
+
getConsultation,
|
|
11
|
+
createConsultation,
|
|
12
|
+
sendMessage,
|
|
13
|
+
acceptQuote,
|
|
14
|
+
rejectQuote,
|
|
15
|
+
} from '../services/consultation.service'
|
|
16
|
+
import type { SdkConfig } from '../config'
|
|
8
17
|
import type {
|
|
9
|
-
Consultation,
|
|
10
18
|
ConsultationCreatePayload,
|
|
11
19
|
ConsultationMessagePayload,
|
|
12
20
|
ConsultationQuoteAcceptPayload,
|
|
13
21
|
} from '../types/consultations'
|
|
22
|
+
import { logger } from '../utils'
|
|
23
|
+
import { useSdkContext, resolveHookArgs } from '../context/sdk-context'
|
|
14
24
|
|
|
15
|
-
export function useConsultations() {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
25
|
+
export function useConsultations(config?: SdkConfig, accessToken?: string | null) {
|
|
26
|
+
const ctx = useSdkContext()
|
|
27
|
+
try {
|
|
28
|
+
const { config: cfg, accessToken: token } = resolveHookArgs(config, accessToken, ctx)
|
|
29
|
+
return useQuery({
|
|
30
|
+
queryKey: ['consultations'],
|
|
31
|
+
queryFn: () => token ? getConsultations(cfg, token) : Promise.resolve([]),
|
|
32
|
+
enabled: !!token,
|
|
33
|
+
})
|
|
34
|
+
} catch (error) {
|
|
35
|
+
logger.warn('[useConsultations] Called outside QueryClientProvider, returning empty list')
|
|
36
|
+
return { data: undefined, isLoading: false, error: null, isFetching: false, refetch: () => Promise.resolve({ data: undefined }) } as any
|
|
37
|
+
}
|
|
20
38
|
}
|
|
21
39
|
|
|
22
|
-
export function useConsultation(
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
40
|
+
export function useConsultation(arg1?: SdkConfig | string, arg2?: string | null, arg3?: string) {
|
|
41
|
+
const ctx = useSdkContext()
|
|
42
|
+
const isArg1Config = typeof arg1 === 'object' && arg1 !== null
|
|
43
|
+
const explicitConfig = isArg1Config ? (arg1 as SdkConfig) : undefined
|
|
44
|
+
const explicitToken = isArg1Config ? (arg2 as string | null) : undefined
|
|
45
|
+
const id = isArg1Config ? arg3 : (typeof arg1 === 'string' ? arg1 : undefined)
|
|
29
46
|
|
|
30
|
-
|
|
31
|
-
|
|
47
|
+
try {
|
|
48
|
+
const { config: cfg, accessToken: token } = resolveHookArgs(explicitConfig, explicitToken, ctx)
|
|
49
|
+
return useQuery({
|
|
50
|
+
queryKey: ['consultation', id],
|
|
51
|
+
queryFn: () => token && id ? getConsultation(cfg, token, id) : Promise.resolve(undefined),
|
|
52
|
+
enabled: !!id && !!token,
|
|
53
|
+
})
|
|
54
|
+
} catch (error) {
|
|
55
|
+
logger.warn('[useConsultation] Called outside QueryClientProvider, returning undefined')
|
|
56
|
+
return { data: undefined, isLoading: false, error: null, isFetching: false, refetch: () => Promise.resolve({ data: undefined }) } as any
|
|
57
|
+
}
|
|
58
|
+
}
|
|
32
59
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
60
|
+
export function useCreateConsultation(config?: SdkConfig, accessToken?: string | null) {
|
|
61
|
+
const ctx = useSdkContext()
|
|
62
|
+
try {
|
|
63
|
+
const { config: cfg, accessToken: token } = resolveHookArgs(config, accessToken, ctx)
|
|
64
|
+
const queryClient = useQueryClient()
|
|
65
|
+
return useMutation({
|
|
66
|
+
mutationFn: (payload: ConsultationCreatePayload) =>
|
|
67
|
+
token ? createConsultation(cfg, token, payload) : Promise.reject('No access token'),
|
|
68
|
+
onSuccess: () => {
|
|
69
|
+
queryClient.invalidateQueries({ queryKey: ['consultations'] })
|
|
70
|
+
},
|
|
71
|
+
})
|
|
72
|
+
} catch (error) {
|
|
73
|
+
logger.warn('[useCreateConsultation] Called outside QueryClientProvider, returning no-op mutation')
|
|
74
|
+
return { mutate: () => {}, mutateAsync: () => Promise.resolve(undefined) } as any
|
|
75
|
+
}
|
|
40
76
|
}
|
|
41
77
|
|
|
42
|
-
export function useSendMessage(
|
|
43
|
-
const
|
|
78
|
+
export function useSendMessage(arg1?: SdkConfig | string, arg2?: string | null, arg3?: string) {
|
|
79
|
+
const ctx = useSdkContext()
|
|
80
|
+
const isArg1Config = typeof arg1 === 'object' && arg1 !== null
|
|
81
|
+
const explicitConfig = isArg1Config ? (arg1 as SdkConfig) : undefined
|
|
82
|
+
const explicitToken = isArg1Config ? (arg2 as string | null) : undefined
|
|
83
|
+
const consultationId = isArg1Config ? arg3 : (typeof arg1 === 'string' ? arg1 : undefined)
|
|
44
84
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
85
|
+
try {
|
|
86
|
+
const { config: cfg, accessToken: token } = resolveHookArgs(explicitConfig, explicitToken, ctx)
|
|
87
|
+
const queryClient = useQueryClient()
|
|
88
|
+
return useMutation({
|
|
89
|
+
mutationFn: (payload: ConsultationMessagePayload) =>
|
|
90
|
+
token && consultationId ? sendMessage(cfg, token, consultationId, payload) : Promise.reject('No access token'),
|
|
91
|
+
onSuccess: () => {
|
|
92
|
+
queryClient.invalidateQueries({ queryKey: ['consultation', consultationId] })
|
|
93
|
+
},
|
|
94
|
+
})
|
|
95
|
+
} catch (error) {
|
|
96
|
+
logger.warn('[useSendMessage] Called outside QueryClientProvider, returning no-op mutation')
|
|
97
|
+
return { mutate: () => {}, mutateAsync: () => Promise.resolve(undefined) } as any
|
|
98
|
+
}
|
|
52
99
|
}
|
|
53
100
|
|
|
54
|
-
export function useAcceptQuote(
|
|
55
|
-
const
|
|
101
|
+
export function useAcceptQuote(arg1?: SdkConfig | string, arg2?: string | null, arg3?: string) {
|
|
102
|
+
const ctx = useSdkContext()
|
|
103
|
+
const isArg1Config = typeof arg1 === 'object' && arg1 !== null
|
|
104
|
+
const explicitConfig = isArg1Config ? (arg1 as SdkConfig) : undefined
|
|
105
|
+
const explicitToken = isArg1Config ? (arg2 as string | null) : undefined
|
|
106
|
+
const consultationId = isArg1Config ? arg3 : (typeof arg1 === 'string' ? arg1 : undefined)
|
|
56
107
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
108
|
+
try {
|
|
109
|
+
const { config: cfg, accessToken: token } = resolveHookArgs(explicitConfig, explicitToken, ctx)
|
|
110
|
+
const queryClient = useQueryClient()
|
|
111
|
+
return useMutation({
|
|
112
|
+
mutationFn: (payload: ConsultationQuoteAcceptPayload) =>
|
|
113
|
+
token && consultationId ? acceptQuote(cfg, token, consultationId, payload) : Promise.reject('No access token'),
|
|
114
|
+
onSuccess: () => {
|
|
115
|
+
queryClient.invalidateQueries({ queryKey: ['consultation', consultationId] })
|
|
116
|
+
},
|
|
117
|
+
})
|
|
118
|
+
} catch (error) {
|
|
119
|
+
logger.warn('[useAcceptQuote] Called outside QueryClientProvider, returning no-op mutation')
|
|
120
|
+
return { mutate: () => {}, mutateAsync: () => Promise.resolve(undefined) } as any
|
|
121
|
+
}
|
|
64
122
|
}
|
|
65
123
|
|
|
66
|
-
export function useRejectQuote(
|
|
67
|
-
const
|
|
124
|
+
export function useRejectQuote(arg1?: SdkConfig | string, arg2?: string | null, arg3?: string) {
|
|
125
|
+
const ctx = useSdkContext()
|
|
126
|
+
const isArg1Config = typeof arg1 === 'object' && arg1 !== null
|
|
127
|
+
const explicitConfig = isArg1Config ? (arg1 as SdkConfig) : undefined
|
|
128
|
+
const explicitToken = isArg1Config ? (arg2 as string | null) : undefined
|
|
129
|
+
const consultationId = isArg1Config ? arg3 : (typeof arg1 === 'string' ? arg1 : undefined)
|
|
68
130
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
131
|
+
try {
|
|
132
|
+
const { config: cfg, accessToken: token } = resolveHookArgs(explicitConfig, explicitToken, ctx)
|
|
133
|
+
const queryClient = useQueryClient()
|
|
134
|
+
return useMutation({
|
|
135
|
+
mutationFn: (reason?: string) =>
|
|
136
|
+
token && consultationId ? rejectQuote(cfg, token, consultationId, reason) : Promise.reject('No access token'),
|
|
137
|
+
onSuccess: () => {
|
|
138
|
+
queryClient.invalidateQueries({ queryKey: ['consultation', consultationId] })
|
|
139
|
+
},
|
|
140
|
+
})
|
|
141
|
+
} catch (error) {
|
|
142
|
+
logger.warn('[useRejectQuote] Called outside QueryClientProvider, returning no-op mutation')
|
|
143
|
+
return { mutate: () => {}, mutateAsync: () => Promise.resolve(undefined) } as any
|
|
144
|
+
}
|
|
76
145
|
}
|