@teincfood/core 0.7.8 → 0.8.0

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.
Files changed (198) hide show
  1. package/README.md +26 -21
  2. package/dist/adapters/auth.d.ts +10 -0
  3. package/dist/adapters/auth.js +43 -0
  4. package/dist/adapters/devices.d.ts +3 -1
  5. package/dist/adapters/devices.js +187 -3
  6. package/dist/adapters/filesystem.d.ts +4 -0
  7. package/dist/adapters/kv.d.ts +10 -0
  8. package/dist/adapters/kv.js +23 -7
  9. package/dist/adapters/local-node.d.ts +4 -6
  10. package/dist/adapters/local-node.js +9 -32
  11. package/dist/adapters/notify.d.ts +12 -0
  12. package/dist/adapters/notify.js +33 -0
  13. package/dist/adapters/query-keys.d.ts +4 -0
  14. package/dist/adapters/query-keys.js +4 -0
  15. package/dist/adapters/services.d.ts +99 -15
  16. package/dist/adapters/services.js +244 -4
  17. package/dist/auth/session.d.ts +66 -0
  18. package/dist/auth/session.js +172 -0
  19. package/dist/catalog/hooks.d.ts +10 -0
  20. package/dist/catalog/hooks.js +82 -11
  21. package/dist/db/migrations.js +274 -0
  22. package/dist/db/operations.d.ts +53 -2
  23. package/dist/db/operations.js +177 -8
  24. package/dist/domain/business/index.d.ts +5 -0
  25. package/dist/domain/business/index.js +5 -0
  26. package/dist/domain/orders/lifecycle.d.ts +6 -0
  27. package/dist/domain/orders/lifecycle.js +6 -0
  28. package/dist/domain/orders/service.d.ts +24 -0
  29. package/dist/domain/orders/service.js +242 -0
  30. package/dist/domain/payments/index.d.ts +6 -0
  31. package/dist/domain/payments/index.js +5 -0
  32. package/dist/domain/reference/index.d.ts +8 -0
  33. package/dist/domain/reference/index.js +8 -0
  34. package/dist/e2e/harness.d.ts +1 -0
  35. package/dist/e2e/harness.js +61 -0
  36. package/dist/hooks/analytics.hooks.d.ts +25 -0
  37. package/dist/hooks/analytics.hooks.js +214 -0
  38. package/dist/hooks/business-hours.hooks.d.ts +8 -0
  39. package/dist/hooks/business-hours.hooks.js +45 -0
  40. package/dist/hooks/dashboard.hooks.d.ts +30 -0
  41. package/dist/hooks/dashboard.hooks.js +132 -0
  42. package/dist/hooks/delivery.hooks.d.ts +225 -0
  43. package/dist/hooks/delivery.hooks.js +80 -0
  44. package/dist/hooks/fleet.hooks.d.ts +37 -0
  45. package/dist/hooks/fleet.hooks.js +229 -0
  46. package/dist/hooks/image.hooks.d.ts +20 -0
  47. package/dist/hooks/image.hooks.js +62 -0
  48. package/dist/hooks/kiosk.hooks.d.ts +22 -5
  49. package/dist/hooks/kiosk.hooks.js +74 -5
  50. package/dist/hooks/members.hooks.d.ts +48 -0
  51. package/dist/hooks/members.hooks.js +302 -0
  52. package/dist/hooks/offline-orders.hooks.d.ts +9 -0
  53. package/dist/hooks/offline-orders.hooks.js +51 -0
  54. package/dist/hooks/orders.hooks.d.ts +19 -39
  55. package/dist/hooks/orders.hooks.js +126 -321
  56. package/dist/hooks/places.hooks.d.ts +21 -0
  57. package/dist/hooks/places.hooks.js +112 -0
  58. package/dist/hooks/realtime-stubs.d.ts +28 -0
  59. package/dist/hooks/realtime-stubs.js +85 -0
  60. package/dist/hooks/rider.hooks.d.ts +470 -0
  61. package/dist/hooks/rider.hooks.js +373 -0
  62. package/dist/hooks/use-infinite-list.d.ts +243 -0
  63. package/dist/hooks/use-infinite-list.js +58 -0
  64. package/dist/hooks/wallet.hooks.d.ts +219 -0
  65. package/dist/hooks/wallet.hooks.js +56 -0
  66. package/dist/image-cache/service.d.ts +8 -0
  67. package/dist/image-cache/service.js +15 -3
  68. package/dist/index.d.ts +60 -5
  69. package/dist/index.js +78 -5
  70. package/dist/local-node/adapters.d.ts +87 -0
  71. package/dist/local-node/adapters.js +4 -0
  72. package/dist/local-node/index.d.ts +5 -0
  73. package/dist/local-node/index.js +5 -0
  74. package/dist/local-node/security.d.ts +25 -0
  75. package/dist/local-node/security.js +149 -0
  76. package/dist/local-node/service.d.ts +83 -0
  77. package/dist/local-node/service.js +706 -0
  78. package/dist/local-node/store.d.ts +50 -0
  79. package/dist/local-node/store.js +284 -0
  80. package/dist/local-node/types.d.ts +92 -0
  81. package/dist/local-node/types.js +4 -0
  82. package/dist/printer/receipt.d.ts +4 -0
  83. package/dist/printer/receipt.js +75 -0
  84. package/dist/printer/service.js +1 -1
  85. package/dist/providers/query-client.d.ts +13 -0
  86. package/dist/providers/query-client.js +58 -0
  87. package/dist/realtime/events.service.d.ts +18 -0
  88. package/dist/realtime/events.service.js +76 -0
  89. package/dist/realtime/order-events.service.d.ts +6 -0
  90. package/dist/realtime/order-events.service.js +17 -0
  91. package/dist/realtime/phoenix-socket.d.ts +55 -0
  92. package/dist/realtime/phoenix-socket.js +269 -0
  93. package/dist/realtime/useEventsConnection.d.ts +1 -0
  94. package/dist/realtime/useEventsConnection.js +50 -0
  95. package/dist/reference/api.d.ts +2 -0
  96. package/dist/reference/api.js +2 -0
  97. package/dist/reference/capabilities.d.ts +12 -7
  98. package/dist/reference/capabilities.js +28 -13
  99. package/dist/reference/hooks.d.ts +34 -0
  100. package/dist/reference/hooks.js +124 -0
  101. package/dist/reference/menu-apply.d.ts +29 -0
  102. package/dist/reference/menu-apply.js +289 -0
  103. package/dist/reference/menu-record.d.ts +69 -0
  104. package/dist/reference/menu-record.js +163 -0
  105. package/dist/reference/operations.d.ts +3 -0
  106. package/dist/reference/operations.js +35 -1
  107. package/dist/reference/service.js +36 -9
  108. package/dist/reference/types.d.ts +1 -1
  109. package/dist/repositories/order.repository.d.ts +8 -0
  110. package/dist/repositories/order.repository.js +24 -2
  111. package/dist/repositories/pos.repository.d.ts +4 -0
  112. package/dist/repositories/pos.repository.js +4 -0
  113. package/dist/sync/backoff.d.ts +21 -0
  114. package/dist/sync/backoff.js +42 -0
  115. package/dist/sync/command-builder.js +10 -2
  116. package/dist/sync/command-queue.service.d.ts +12 -0
  117. package/dist/sync/command-queue.service.js +115 -18
  118. package/dist/sync/device-lease.service.d.ts +3 -3
  119. package/dist/sync/device-lease.service.js +80 -20
  120. package/dist/sync/engine.d.ts +3 -1
  121. package/dist/sync/engine.js +44 -4
  122. package/dist/sync/full-sync.d.ts +6 -0
  123. package/dist/sync/full-sync.js +72 -0
  124. package/dist/sync/health-probe.d.ts +24 -0
  125. package/dist/sync/health-probe.js +138 -0
  126. package/dist/sync/offline-capable.js +25 -0
  127. package/dist/sync/online-gates.d.ts +17 -0
  128. package/dist/sync/online-gates.js +55 -0
  129. package/dist/sync/order-number.d.ts +4 -4
  130. package/dist/sync/order-number.js +33 -13
  131. package/dist/sync/order-snapshots.service.d.ts +1 -0
  132. package/dist/sync/order-snapshots.service.js +47 -2
  133. package/dist/sync/pending-orders.service.d.ts +18 -0
  134. package/dist/sync/pending-orders.service.js +148 -3
  135. package/dist/sync/reconciliation/index.d.ts +5 -0
  136. package/dist/sync/reconciliation/index.js +5 -0
  137. package/dist/sync/snapshots/entity.d.ts +6 -0
  138. package/dist/sync/snapshots/entity.js +6 -0
  139. package/dist/sync/sync-jobs.service.d.ts +18 -0
  140. package/dist/sync/sync-jobs.service.js +539 -0
  141. package/dist/sync/transition-endpoints.d.ts +11 -0
  142. package/dist/sync/transition-endpoints.js +30 -0
  143. package/dist/sync/transport-local-node.js +3 -2
  144. package/dist/sync/transport-rest.d.ts +7 -0
  145. package/dist/sync/transport-rest.js +90 -25
  146. package/dist/sync/use-sync-reconciliation.js +58 -16
  147. package/dist/test-helpers/memory-driver.js +182 -4
  148. package/dist/test-helpers/seed-hours.d.ts +1 -0
  149. package/dist/test-helpers/seed-hours.js +23 -0
  150. package/dist/types/api/business.api.d.ts +42 -0
  151. package/dist/types/api/menu.api.d.ts +15 -0
  152. package/dist/types/api/seller.api.d.ts +20 -0
  153. package/dist/types/places.d.ts +19 -0
  154. package/dist/types/places.js +2 -0
  155. package/dist/types/rider.d.ts +67 -0
  156. package/dist/types/rider.js +2 -0
  157. package/dist/utils/attempt-stats.d.ts +23 -0
  158. package/dist/utils/attempt-stats.js +61 -0
  159. package/dist/utils/business-hours.d.ts +37 -0
  160. package/dist/utils/business-hours.js +96 -0
  161. package/dist/utils/debug-log.d.ts +23 -0
  162. package/dist/utils/debug-log.js +153 -0
  163. package/dist/utils/order-filter.d.ts +1 -1
  164. package/dist/utils/order-filter.js +1 -1
  165. package/dist/utils/order-transitions.d.ts +30 -0
  166. package/dist/utils/order-transitions.js +185 -0
  167. package/dist/utils/sync-logger.js +5 -4
  168. package/dist/validation/offline.d.ts +46 -0
  169. package/dist/validation/offline.js +79 -0
  170. package/package.json +6 -1
  171. package/dist/pricing/engine.test.d.ts +0 -1
  172. package/dist/pricing/engine.test.js +0 -142
  173. package/dist/reference/lww.test.d.ts +0 -1
  174. package/dist/reference/lww.test.js +0 -23
  175. package/dist/reference/operations.test.d.ts +0 -1
  176. package/dist/reference/operations.test.js +0 -66
  177. package/dist/standalone.integration.test.d.ts +0 -1
  178. package/dist/standalone.integration.test.js +0 -235
  179. package/dist/sync/device-lease.test.d.ts +0 -1
  180. package/dist/sync/device-lease.test.js +0 -38
  181. package/dist/sync/offline-integration.test.d.ts +0 -1
  182. package/dist/sync/offline-integration.test.js +0 -52
  183. package/dist/sync/order-number.test.d.ts +0 -1
  184. package/dist/sync/order-number.test.js +0 -51
  185. package/dist/sync/perms.test.d.ts +0 -1
  186. package/dist/sync/perms.test.js +0 -15
  187. package/dist/utils/currency.test.d.ts +0 -1
  188. package/dist/utils/currency.test.js +0 -17
  189. package/dist/utils/hlc.test.d.ts +0 -1
  190. package/dist/utils/hlc.test.js +0 -29
  191. package/dist/utils/phone.test.d.ts +0 -1
  192. package/dist/utils/phone.test.js +0 -19
  193. package/dist/utils/responsive.d.ts +0 -13
  194. package/dist/utils/responsive.js +0 -18
  195. package/dist/utils/uuid.test.d.ts +0 -1
  196. package/dist/utils/uuid.test.js +0 -13
  197. package/dist/utils/validation.test.d.ts +0 -1
  198. package/dist/utils/validation.test.js +0 -23
@@ -0,0 +1,302 @@
1
+ /**
2
+ * Members / invitations / roles / tax hooks — single source for both apps.
3
+ * Reads serve the SQLite reference cache instantly; network refreshes
4
+ * silently when online. Invites and management mutations require online.
5
+ */
6
+ import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
7
+ import { useSyncExternalStore } from "react";
8
+ import { getActiveBusiness, subscribeBusiness } from "../adapters/business";
9
+ import { businessService, rolesService, fleetService } from "../adapters/services";
10
+ import { assertOnlineFor } from "../sync/online-gates";
11
+ import { validateInviteInput } from "../validation/offline";
12
+ import { notifySuccess, notifyError } from "../adapters/notify";
13
+ import { extractApiErrorMessage } from "../utils/error";
14
+ import { emitReferenceChanged } from "../reference/events";
15
+ import { useReferenceData } from "../reference/hooks";
16
+ import { useIsEffectivelyOnline } from "./use-infinite-list";
17
+ function useBusinessId() {
18
+ const id = useSyncExternalStore(subscribeBusiness, () => getActiveBusiness()?.id ?? null, () => null);
19
+ return id ?? undefined;
20
+ }
21
+ const OFFLINE_FIRST = { retry: false, networkMode: "offlineFirst" };
22
+ // ─── Keys ───
23
+ export const MEMBER_KEYS = {
24
+ all: ["business-members"],
25
+ list: (businessId) => [...MEMBER_KEYS.all, businessId],
26
+ invitations: (businessId) => [...MEMBER_KEYS.all, businessId, "invitations"],
27
+ };
28
+ export const INVITATION_KEYS = {
29
+ all: ["invitations"],
30
+ list: () => [...INVITATION_KEYS.all, "list"],
31
+ };
32
+ export const ROLES_KEYS = {
33
+ all: ["business-roles"],
34
+ forBusiness: (businessId) => [...ROLES_KEYS.all, businessId],
35
+ };
36
+ export const TAX_KEYS = {
37
+ all: ["tax-rules"],
38
+ list: (businessId) => [...TAX_KEYS.all, "list", businessId],
39
+ };
40
+ // ─── Members ───
41
+ export function useBusinessMembersQuery() {
42
+ const businessId = useBusinessId();
43
+ const cached = useReferenceData("members");
44
+ const online = useIsEffectivelyOnline();
45
+ const q = useQuery({
46
+ queryKey: MEMBER_KEYS.list(businessId ?? ""),
47
+ queryFn: () => businessService.fetchBusinessMembers(businessId),
48
+ enabled: Boolean(businessId) && online,
49
+ staleTime: 30 * 1000,
50
+ ...OFFLINE_FIRST,
51
+ placeholderData: cached.data?.payload,
52
+ });
53
+ // Offline: SQLite cache directly so screens stay populated when down.
54
+ return { ...q, data: q.data ?? cached.data?.payload };
55
+ }
56
+ export function useInviteMemberMutation() {
57
+ const queryClient = useQueryClient();
58
+ const businessId = useBusinessId();
59
+ return useMutation({
60
+ mutationFn: (data) => {
61
+ assertOnlineFor("member:invite");
62
+ validateInviteInput({ email: data.email });
63
+ return businessService.inviteBusinessMember(businessId, data);
64
+ },
65
+ onSuccess: () => {
66
+ notifySuccess("Invitation sent!");
67
+ queryClient.invalidateQueries({ queryKey: MEMBER_KEYS.list(businessId ?? "") });
68
+ if (businessId)
69
+ emitReferenceChanged(businessId, ["members"]);
70
+ },
71
+ onError: (error) => {
72
+ notifyError(extractApiErrorMessage(error));
73
+ },
74
+ });
75
+ }
76
+ export function useRemoveMemberMutation() {
77
+ const queryClient = useQueryClient();
78
+ const businessId = useBusinessId();
79
+ return useMutation({
80
+ mutationFn: (userId) => {
81
+ assertOnlineFor("member:manage");
82
+ return businessService.removeBusinessMember(businessId, userId);
83
+ },
84
+ onSuccess: () => {
85
+ notifySuccess("Member removed");
86
+ queryClient.invalidateQueries({ queryKey: MEMBER_KEYS.list(businessId ?? "") });
87
+ if (businessId)
88
+ emitReferenceChanged(businessId, ["members"]);
89
+ },
90
+ onError: (error) => {
91
+ notifyError(extractApiErrorMessage(error));
92
+ },
93
+ });
94
+ }
95
+ export function useBusinessMemberInvitationsQuery() {
96
+ const businessId = useBusinessId();
97
+ // No invitations SQLite mirror — never fire while unreachable.
98
+ const online = useIsEffectivelyOnline();
99
+ return useQuery({
100
+ queryKey: MEMBER_KEYS.invitations(businessId ?? ""),
101
+ queryFn: () => businessService.fetchBusinessMemberInvitations(businessId),
102
+ enabled: Boolean(businessId) && online,
103
+ ...OFFLINE_FIRST,
104
+ });
105
+ }
106
+ export function useRevokeMemberInvitationMutation() {
107
+ const queryClient = useQueryClient();
108
+ const businessId = useBusinessId();
109
+ return useMutation({
110
+ mutationFn: (invitationId) => {
111
+ assertOnlineFor("member:manage");
112
+ return businessService.revokeBusinessMemberInvitation(businessId, invitationId);
113
+ },
114
+ onSuccess: () => {
115
+ notifySuccess("Invitation revoked");
116
+ queryClient.invalidateQueries({ queryKey: MEMBER_KEYS.invitations(businessId ?? "") });
117
+ if (businessId)
118
+ emitReferenceChanged(businessId, ["members"]);
119
+ },
120
+ onError: (error) => {
121
+ notifyError(extractApiErrorMessage(error));
122
+ },
123
+ });
124
+ }
125
+ export function useDeleteMemberInvitationMutation() {
126
+ const queryClient = useQueryClient();
127
+ const businessId = useBusinessId();
128
+ return useMutation({
129
+ mutationFn: (invitationId) => {
130
+ assertOnlineFor("member:manage");
131
+ return businessService.deleteBusinessMemberInvitation(businessId, invitationId);
132
+ },
133
+ onSuccess: () => {
134
+ notifySuccess("Invitation deleted");
135
+ queryClient.invalidateQueries({ queryKey: MEMBER_KEYS.invitations(businessId ?? "") });
136
+ if (businessId)
137
+ emitReferenceChanged(businessId, ["members"]);
138
+ },
139
+ onError: (error) => {
140
+ notifyError(extractApiErrorMessage(error));
141
+ },
142
+ });
143
+ }
144
+ // ─── User invitations ───
145
+ export function useUserInvitationsQuery() {
146
+ // No invitations SQLite mirror — never fire while unreachable.
147
+ const online = useIsEffectivelyOnline();
148
+ return useQuery({
149
+ queryKey: INVITATION_KEYS.list(),
150
+ queryFn: () => businessService.fetchUserInvitations(),
151
+ enabled: online,
152
+ staleTime: 15000,
153
+ ...OFFLINE_FIRST,
154
+ });
155
+ }
156
+ export function useLeaveBusinessMutation() {
157
+ const queryClient = useQueryClient();
158
+ return useMutation({
159
+ mutationFn: (invitationId) => {
160
+ assertOnlineFor("member:manage");
161
+ return businessService.leaveBusiness(invitationId);
162
+ },
163
+ onSuccess: () => {
164
+ notifySuccess("Left the business");
165
+ queryClient.invalidateQueries({ queryKey: INVITATION_KEYS.list() });
166
+ },
167
+ onError: (error) => {
168
+ notifyError(extractApiErrorMessage(error));
169
+ },
170
+ });
171
+ }
172
+ export function useAcceptFleetInvitationMutation() {
173
+ const queryClient = useQueryClient();
174
+ return useMutation({
175
+ mutationFn: (data) => {
176
+ assertOnlineFor("member:manage");
177
+ return fleetService.acceptFleetInvitation(data);
178
+ },
179
+ onSuccess: () => {
180
+ notifySuccess("You have joined the business!");
181
+ queryClient.invalidateQueries({ queryKey: INVITATION_KEYS.list() });
182
+ },
183
+ onError: (error) => {
184
+ notifyError(extractApiErrorMessage(error));
185
+ },
186
+ });
187
+ }
188
+ export function useAcceptBusinessInvitationMutation() {
189
+ const queryClient = useQueryClient();
190
+ return useMutation({
191
+ mutationFn: (data) => {
192
+ assertOnlineFor("member:manage");
193
+ return businessService.acceptBusinessInvitation(data);
194
+ },
195
+ onSuccess: () => {
196
+ notifySuccess("Invitation accepted!");
197
+ queryClient.invalidateQueries({ queryKey: INVITATION_KEYS.list() });
198
+ },
199
+ onError: (error) => {
200
+ notifyError(extractApiErrorMessage(error));
201
+ },
202
+ });
203
+ }
204
+ // ─── Roles ───
205
+ export function useBusinessRolesQuery(enabled = true) {
206
+ const businessId = useBusinessId();
207
+ const cached = useReferenceData("roles");
208
+ const online = useIsEffectivelyOnline();
209
+ const q = useQuery({
210
+ queryKey: ROLES_KEYS.forBusiness(businessId),
211
+ queryFn: () => rolesService.fetchBusinessRoles(),
212
+ staleTime: Infinity,
213
+ enabled: enabled && !!businessId && online,
214
+ ...OFFLINE_FIRST,
215
+ placeholderData: cached.data?.payload,
216
+ });
217
+ return { ...q, data: q.data ?? cached.data?.payload };
218
+ }
219
+ // ─── Tax rules ───
220
+ export function useBusinessTaxRulesQuery(enabled = true) {
221
+ const businessId = useBusinessId();
222
+ const cached = useReferenceData("tax-rules");
223
+ const online = useIsEffectivelyOnline();
224
+ const q = useQuery({
225
+ queryKey: TAX_KEYS.list(businessId),
226
+ queryFn: () => businessService.fetchBusinessTaxRules(businessId),
227
+ enabled: enabled && Boolean(businessId) && online,
228
+ staleTime: 30 * 1000,
229
+ ...OFFLINE_FIRST,
230
+ placeholderData: cached.data?.payload,
231
+ });
232
+ return { ...q, data: q.data ?? cached.data?.payload };
233
+ }
234
+ export function useCreateTaxRuleMutation() {
235
+ const queryClient = useQueryClient();
236
+ const businessId = useBusinessId();
237
+ return useMutation({
238
+ mutationFn: (data) => {
239
+ assertOnlineFor("settings:manage");
240
+ return businessService.createBusinessTaxRule(businessId, data);
241
+ },
242
+ onSuccess: () => {
243
+ queryClient.invalidateQueries({ queryKey: TAX_KEYS.list(businessId) });
244
+ notifySuccess("Tax rule created");
245
+ if (businessId)
246
+ emitReferenceChanged(businessId, ["tax-rules"]);
247
+ },
248
+ onError: (err) => {
249
+ try {
250
+ console.debug("[TaxHook] Create failed", err);
251
+ }
252
+ catch { }
253
+ notifyError(extractApiErrorMessage(err));
254
+ },
255
+ });
256
+ }
257
+ export function useUpdateTaxRuleMutation() {
258
+ const queryClient = useQueryClient();
259
+ const businessId = useBusinessId();
260
+ return useMutation({
261
+ mutationFn: ({ id, data }) => {
262
+ assertOnlineFor("settings:manage");
263
+ return businessService.updateTaxRule(id, data);
264
+ },
265
+ onSuccess: () => {
266
+ queryClient.invalidateQueries({ queryKey: TAX_KEYS.list(businessId) });
267
+ notifySuccess("Tax rule updated");
268
+ if (businessId)
269
+ emitReferenceChanged(businessId, ["tax-rules"]);
270
+ },
271
+ onError: (err) => {
272
+ try {
273
+ console.debug("[TaxHook] Update failed", err);
274
+ }
275
+ catch { }
276
+ notifyError(extractApiErrorMessage(err));
277
+ },
278
+ });
279
+ }
280
+ export function useDeleteTaxRuleMutation() {
281
+ const queryClient = useQueryClient();
282
+ const businessId = useBusinessId();
283
+ return useMutation({
284
+ mutationFn: (id) => {
285
+ assertOnlineFor("settings:manage");
286
+ return businessService.deleteTaxRule(id);
287
+ },
288
+ onSuccess: () => {
289
+ queryClient.invalidateQueries({ queryKey: TAX_KEYS.list(businessId) });
290
+ notifySuccess("Tax rule removed");
291
+ if (businessId)
292
+ emitReferenceChanged(businessId, ["tax-rules"]);
293
+ },
294
+ onError: (err) => {
295
+ try {
296
+ console.debug("[TaxHook] Delete failed", err);
297
+ }
298
+ catch { }
299
+ notifyError(extractApiErrorMessage(err));
300
+ },
301
+ });
302
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Offline order hydration — single source for both apps.
3
+ *
4
+ * On startup / business change, seeds the TanStack Query cache from the
5
+ * durable SQLite order read-model so seller, POS, kitchen and display
6
+ * screens render current + recent orders immediately, even before any
7
+ * network fetch completes (and fully offline after a restart).
8
+ */
9
+ export declare function useOfflineOrderHydration(): void;
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Offline order hydration — single source for both apps.
3
+ *
4
+ * On startup / business change, seeds the TanStack Query cache from the
5
+ * durable SQLite order read-model so seller, POS, kitchen and display
6
+ * screens render current + recent orders immediately, even before any
7
+ * network fetch completes (and fully offline after a restart).
8
+ */
9
+ import { useEffect } from "react";
10
+ import { useQueryClient } from "@tanstack/react-query";
11
+ import { useSyncExternalStore } from "react";
12
+ import { getActiveBusiness, subscribeBusiness } from "../adapters/business";
13
+ import { orderSnapshotsService } from "../sync/order-snapshots.service";
14
+ import { SELLER_KEYS, POS_KEYS } from "./orders.hooks";
15
+ export function useOfflineOrderHydration() {
16
+ const queryClient = useQueryClient();
17
+ const businessId = useSyncExternalStore(subscribeBusiness, () => getActiveBusiness()?.id ?? null, () => null);
18
+ useEffect(() => {
19
+ if (!businessId)
20
+ return;
21
+ const bid = businessId;
22
+ let cancelled = false;
23
+ async function hydrate() {
24
+ const orders = await orderSnapshotsService.getSellerList(bid, bid);
25
+ if (cancelled || !orders || orders.length === 0)
26
+ return;
27
+ const pages = {
28
+ pages: [
29
+ {
30
+ data: orders,
31
+ pagination: {
32
+ page: 1,
33
+ total_pages: 1,
34
+ page_size: orders.length,
35
+ total_entries: orders.length,
36
+ },
37
+ },
38
+ ],
39
+ pageParams: [1],
40
+ };
41
+ // Seed the same key shape the seller and POS screens use with no filters.
42
+ queryClient.setQueryData([...SELLER_KEYS.orders(bid)], pages);
43
+ queryClient.setQueryData([...POS_KEYS.orders(bid), undefined], pages);
44
+ }
45
+ hydrate().catch(() => { });
46
+ orderSnapshotsService.pruneOld().catch(() => { });
47
+ return () => {
48
+ cancelled = true;
49
+ };
50
+ }, [businessId, queryClient]);
51
+ }
@@ -1,54 +1,27 @@
1
- /**
2
- * Order lifecycle hooks — offline-first, device-owned outbox.
3
- *
4
- * Device owns its partition: when offline it serves the durable
5
- * entity_snapshots + pending overlay immediately; the SyncEngine replays
6
- * queued commands when back online. No hook ever blocks on a cloud timeout
7
- * when offline.
8
- *
9
- * Host apps just re-export from "@teincfood/core" — no app-local duplication.
10
- */
11
- import type { POSOrderCreateRequest, POSOrderPreviewResponse } from "../types/pos.types";
12
- import type { POSCartItem, POSOrderType } from "../types/pos.types";
1
+ import type { POSOrderCreateRequest, POSOrderPreviewResponse, POSCartItem, POSOrderType } from "../types/pos.types";
13
2
  import type { SellerOrder } from "../types/api/seller.api";
14
3
  export declare const POS_KEYS: {
15
- readonly all: readonly ["pos"];
16
- readonly orders: (businessId?: string) => readonly ["pos", "orders", string | undefined];
17
- readonly preview: (businessId?: string) => readonly ["pos", "preview", string | undefined];
4
+ all: readonly ["pos"];
5
+ orders: (bid?: string) => readonly ["pos", "orders", string | undefined];
6
+ preview: (bid?: string) => readonly ["pos", "preview", string | undefined];
18
7
  };
19
8
  export declare const SELLER_KEYS: {
20
- readonly all: readonly ["seller"];
21
- readonly orders: (businessId?: string, filters?: Record<string, unknown>) => readonly unknown[];
22
- readonly deliveries: (businessId?: string, filters?: Record<string, unknown>) => readonly unknown[];
23
- readonly order: (id: string, businessId?: string) => readonly ["seller", "order", string, string | undefined];
24
- };
25
- export declare function usePOSOrdersQuery(filters?: {
26
- status?: string;
27
- order_type?: string;
28
- is_pos?: string;
29
- date_from?: string;
30
- date_to?: string;
31
- q?: string;
32
- search?: string;
33
- }, enabled?: boolean): import("@tanstack/react-query").UseInfiniteQueryResult<SellerOrder[], Error> & {
34
- data: SellerOrder[] | undefined;
9
+ all: readonly ["seller"];
10
+ orders: (bid?: string, f?: Record<string, unknown>) => readonly unknown[];
11
+ deliveries: (bid?: string, f?: Record<string, unknown>) => readonly unknown[];
12
+ order: (id: string, bid?: string) => readonly ["seller", "order", string, string | undefined];
35
13
  };
14
+ export declare function usePOSOrdersQuery(filters?: Record<string, string>, enabled?: boolean): import("@tanstack/react-query").UseInfiniteQueryResult<SellerOrder[], Error>;
36
15
  export declare function useSellerOrdersQuery(enabled?: boolean, filters?: {
37
16
  status?: string;
38
17
  q?: string;
39
18
  search?: string;
40
- date_from?: string;
41
- date_to?: string;
42
- }): import("@tanstack/react-query").UseInfiniteQueryResult<SellerOrder[], Error> & {
43
- data: SellerOrder[] | undefined;
44
- };
45
- export declare function usePendingOrders(businessId?: string): SellerOrder[];
46
- export declare function useCreatePOSOrderMutation(): import("@tanstack/react-query").UseMutationResult<unknown, Error, POSOrderCreateRequest, unknown>;
47
- export declare function usePOSOrderPreviewQuery(items: POSCartItem[], orderType: POSOrderType, customerName: string): import("@tanstack/react-query").UseQueryResult<POSOrderPreviewResponse, Error>;
19
+ }): import("@tanstack/react-query").UseInfiniteQueryResult<SellerOrder[], Error>;
48
20
  export declare function useSellerOrderQuery(orderId: string, enabled?: boolean): import("@tanstack/react-query").UseQueryResult<{
49
21
  data: SellerOrder;
50
22
  }, Error>;
51
- export declare function isQueuedTransition(result: unknown): boolean;
23
+ export declare function useCreatePOSOrderMutation(): import("@tanstack/react-query").UseMutationResult<SellerOrder, Error, POSOrderCreateRequest, unknown>;
24
+ export declare function usePOSOrderPreviewQuery(items: POSCartItem[], orderType: POSOrderType, customerName: string): import("@tanstack/react-query").UseQueryResult<POSOrderPreviewResponse, Error>;
52
25
  export declare const useAcceptOrderMutation: () => import("@tanstack/react-query").UseMutationResult<unknown, Error, string, unknown>;
53
26
  export declare const useRejectOrderMutation: () => import("@tanstack/react-query").UseMutationResult<unknown, Error, string, unknown>;
54
27
  export declare const useStartPreparingOrderMutation: () => import("@tanstack/react-query").UseMutationResult<unknown, Error, string, unknown>;
@@ -63,7 +36,14 @@ export declare function useAssignRiderMutation(): import("@tanstack/react-query"
63
36
  orderId: string;
64
37
  riderId: string;
65
38
  }, unknown>;
39
+ export declare function useConfirmCashPaymentMutation(): import("@tanstack/react-query").UseMutationResult<SellerOrder, Error, string, unknown>;
66
40
  export declare function useUpdateOrderStatusMutation(): {
67
41
  mutate: (orderId: string, status: string) => Promise<unknown>;
68
42
  isPending: boolean;
69
43
  };
44
+ export declare function isQueuedTransition(result: unknown): boolean;
45
+ /**
46
+ * Reactive view of locally queued (unconfirmed) order creations.
47
+ * Hydrates persisted optimistic events once (survives restart offline).
48
+ */
49
+ export declare function usePendingOrders(): SellerOrder[];