@htlkg/data 0.0.18 → 0.0.20
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/client/index.d.ts +257 -1
- package/dist/client/index.js +59 -1
- package/dist/client/index.js.map +1 -1
- package/dist/common-DSxswsZ3.d.ts +40 -0
- package/dist/hooks/index.d.ts +75 -9
- package/dist/hooks/index.js +135 -35
- package/dist/hooks/index.js.map +1 -1
- package/dist/index.d.ts +6 -3
- package/dist/index.js +355 -15
- package/dist/index.js.map +1 -1
- package/dist/mutations/index.d.ts +17 -12
- package/dist/mutations/index.js +204 -2
- package/dist/mutations/index.js.map +1 -1
- package/dist/{productInstances-3LDgCZSO.d.ts → productInstances-BpQv1oLS.d.ts} +3 -7
- package/dist/queries/index.d.ts +3 -0
- package/dist/queries/index.js +82 -0
- package/dist/queries/index.js.map +1 -1
- package/dist/reservations-C0FNm__0.d.ts +154 -0
- package/dist/reservations-CdDfkcZ_.d.ts +172 -0
- package/package.json +3 -3
- package/src/client/index.ts +18 -0
- package/src/client/reservations.ts +336 -0
- package/src/hooks/createDataHook.test.ts +534 -0
- package/src/hooks/createDataHook.ts +20 -13
- package/src/hooks/index.ts +1 -0
- package/src/hooks/useReservations.ts +145 -0
- package/src/mutations/accounts.ts +5 -2
- package/src/mutations/brands.ts +5 -4
- package/src/mutations/common.ts +41 -0
- package/src/mutations/index.ts +22 -0
- package/src/mutations/productInstances/productInstances.test.ts +3 -3
- package/src/mutations/productInstances/productInstances.ts +7 -9
- package/src/mutations/reservations.test.ts +459 -0
- package/src/mutations/reservations.ts +452 -0
- package/src/mutations/users.ts +5 -4
- package/src/queries/index.ts +11 -0
- package/src/queries/reservations.test.ts +374 -0
- package/src/queries/reservations.ts +247 -0
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useReservations Hook
|
|
3
|
+
*
|
|
4
|
+
* Vue composable for fetching and managing reservation data with reactive state.
|
|
5
|
+
* Provides loading states, error handling, pagination, and refetch capabilities.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { Ref, ComputedRef } from "vue";
|
|
9
|
+
import type { Reservation } from "../queries/reservations";
|
|
10
|
+
import { createDataHook, type BaseHookOptions } from "./createDataHook";
|
|
11
|
+
|
|
12
|
+
export interface UseReservationsOptions extends BaseHookOptions {
|
|
13
|
+
/** Filter by brand ID */
|
|
14
|
+
brandId?: string;
|
|
15
|
+
/** Filter by start date (check-in date >= startDate) */
|
|
16
|
+
startDate?: string;
|
|
17
|
+
/** Filter by end date (check-in date <= endDate) */
|
|
18
|
+
endDate?: string;
|
|
19
|
+
/** Filter by reservation status */
|
|
20
|
+
status?: Reservation["status"];
|
|
21
|
+
/** Filter by contact/visit ID */
|
|
22
|
+
contactId?: string;
|
|
23
|
+
/** Pagination token for fetching next page */
|
|
24
|
+
nextToken?: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface UseReservationsReturn {
|
|
28
|
+
/** Reactive array of reservations */
|
|
29
|
+
reservations: Ref<Reservation[]>;
|
|
30
|
+
/** Computed array of confirmed reservations */
|
|
31
|
+
confirmedReservations: ComputedRef<Reservation[]>;
|
|
32
|
+
/** Computed array of active reservations (confirmed or checked_in) */
|
|
33
|
+
activeReservations: ComputedRef<Reservation[]>;
|
|
34
|
+
/** Loading state */
|
|
35
|
+
loading: Ref<boolean>;
|
|
36
|
+
/** Error state */
|
|
37
|
+
error: Ref<Error | null>;
|
|
38
|
+
/** Refetch reservations */
|
|
39
|
+
refetch: () => Promise<void>;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Build filter from hook options
|
|
44
|
+
*/
|
|
45
|
+
function buildFilter(options: UseReservationsOptions): any {
|
|
46
|
+
const conditions: any[] = [];
|
|
47
|
+
|
|
48
|
+
if (options.brandId) {
|
|
49
|
+
conditions.push({ brandId: { eq: options.brandId } });
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (options.status) {
|
|
53
|
+
conditions.push({ status: { eq: options.status } });
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (options.contactId) {
|
|
57
|
+
conditions.push({ visitId: { eq: options.contactId } });
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (options.startDate) {
|
|
61
|
+
conditions.push({ checkIn: { ge: options.startDate } });
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (options.endDate) {
|
|
65
|
+
conditions.push({ checkIn: { le: options.endDate } });
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (options.filter) {
|
|
69
|
+
conditions.push(options.filter);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (conditions.length === 0) {
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (conditions.length === 1) {
|
|
77
|
+
return conditions[0];
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return { and: conditions };
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Internal hook created by factory
|
|
85
|
+
*/
|
|
86
|
+
const useReservationsInternal = createDataHook<
|
|
87
|
+
Reservation,
|
|
88
|
+
UseReservationsOptions,
|
|
89
|
+
{ confirmedReservations: Reservation[]; activeReservations: Reservation[] }
|
|
90
|
+
>({
|
|
91
|
+
model: "Reservation",
|
|
92
|
+
dataPropertyName: "reservations",
|
|
93
|
+
buildFilter,
|
|
94
|
+
computedProperties: {
|
|
95
|
+
confirmedReservations: (reservations) =>
|
|
96
|
+
reservations.filter((r) => r.status === "confirmed"),
|
|
97
|
+
activeReservations: (reservations) =>
|
|
98
|
+
reservations.filter((r) => r.status === "confirmed" || r.status === "checked_in"),
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Composable for fetching and managing reservations
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* ```typescript
|
|
107
|
+
* import { useReservations } from '@htlkg/data/hooks';
|
|
108
|
+
*
|
|
109
|
+
* const { reservations, loading, error, refetch } = useReservations({
|
|
110
|
+
* brandId: 'brand-123',
|
|
111
|
+
* startDate: '2026-01-01',
|
|
112
|
+
* endDate: '2026-01-31',
|
|
113
|
+
* status: 'confirmed'
|
|
114
|
+
* });
|
|
115
|
+
* ```
|
|
116
|
+
*
|
|
117
|
+
* @example With contact filter
|
|
118
|
+
* ```typescript
|
|
119
|
+
* const { reservations, loading } = useReservations({
|
|
120
|
+
* contactId: 'contact-123',
|
|
121
|
+
* limit: 50
|
|
122
|
+
* });
|
|
123
|
+
* ```
|
|
124
|
+
*
|
|
125
|
+
* @example With computed properties
|
|
126
|
+
* ```typescript
|
|
127
|
+
* const { reservations, activeReservations, confirmedReservations } = useReservations({
|
|
128
|
+
* brandId: 'brand-123'
|
|
129
|
+
* });
|
|
130
|
+
*
|
|
131
|
+
* // activeReservations includes confirmed + checked_in
|
|
132
|
+
* // confirmedReservations includes only confirmed
|
|
133
|
+
* ```
|
|
134
|
+
*/
|
|
135
|
+
export function useReservations(options: UseReservationsOptions = {}): UseReservationsReturn {
|
|
136
|
+
const result = useReservationsInternal(options);
|
|
137
|
+
return {
|
|
138
|
+
reservations: result.reservations as Ref<Reservation[]>,
|
|
139
|
+
confirmedReservations: result.confirmedReservations as ComputedRef<Reservation[]>,
|
|
140
|
+
activeReservations: result.activeReservations as ComputedRef<Reservation[]>,
|
|
141
|
+
loading: result.loading,
|
|
142
|
+
error: result.error,
|
|
143
|
+
refetch: result.refetch,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
@@ -9,26 +9,29 @@ import {
|
|
|
9
9
|
checkRestoreEligibility,
|
|
10
10
|
DEFAULT_SOFT_DELETE_RETENTION_DAYS,
|
|
11
11
|
} from "../queries/systemSettings";
|
|
12
|
+
import type { CreateAuditFields, UpdateWithSoftDeleteFields } from "./common";
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* Input type for creating an account
|
|
15
16
|
*/
|
|
16
|
-
export interface CreateAccountInput {
|
|
17
|
+
export interface CreateAccountInput extends CreateAuditFields {
|
|
17
18
|
name: string;
|
|
18
19
|
logo?: string;
|
|
19
20
|
subscription?: Record<string, any>;
|
|
20
21
|
settings?: Record<string, any>;
|
|
22
|
+
status?: "active" | "inactive" | "deleted";
|
|
21
23
|
}
|
|
22
24
|
|
|
23
25
|
/**
|
|
24
26
|
* Input type for updating an account
|
|
25
27
|
*/
|
|
26
|
-
export interface UpdateAccountInput {
|
|
28
|
+
export interface UpdateAccountInput extends UpdateWithSoftDeleteFields {
|
|
27
29
|
id: string;
|
|
28
30
|
name?: string;
|
|
29
31
|
logo?: string;
|
|
30
32
|
subscription?: Record<string, any>;
|
|
31
33
|
settings?: Record<string, any>;
|
|
34
|
+
status?: "active" | "inactive" | "deleted";
|
|
32
35
|
}
|
|
33
36
|
|
|
34
37
|
/**
|
package/src/mutations/brands.ts
CHANGED
|
@@ -9,28 +9,29 @@ import {
|
|
|
9
9
|
checkRestoreEligibility,
|
|
10
10
|
DEFAULT_SOFT_DELETE_RETENTION_DAYS,
|
|
11
11
|
} from "../queries/systemSettings";
|
|
12
|
+
import type { CreateAuditFields, UpdateWithSoftDeleteFields } from "./common";
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* Input type for creating a brand
|
|
15
16
|
*/
|
|
16
|
-
export interface CreateBrandInput {
|
|
17
|
+
export interface CreateBrandInput extends CreateAuditFields {
|
|
17
18
|
accountId: string;
|
|
18
19
|
name: string;
|
|
19
20
|
logo?: string;
|
|
20
21
|
timezone?: string;
|
|
21
|
-
status?: "active" | "inactive" | "maintenance" | "suspended";
|
|
22
|
+
status?: "active" | "inactive" | "maintenance" | "suspended" | "deleted";
|
|
22
23
|
settings?: Record<string, any>;
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
/**
|
|
26
27
|
* Input type for updating a brand
|
|
27
28
|
*/
|
|
28
|
-
export interface UpdateBrandInput {
|
|
29
|
+
export interface UpdateBrandInput extends UpdateWithSoftDeleteFields {
|
|
29
30
|
id: string;
|
|
30
31
|
name?: string;
|
|
31
32
|
logo?: string;
|
|
32
33
|
timezone?: string;
|
|
33
|
-
status?: "active" | "inactive" | "maintenance" | "suspended";
|
|
34
|
+
status?: "active" | "inactive" | "maintenance" | "suspended" | "deleted";
|
|
34
35
|
settings?: Record<string, any>;
|
|
35
36
|
}
|
|
36
37
|
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Common Mutation Input Base Types
|
|
3
|
+
*
|
|
4
|
+
* Provides reusable base interfaces for audit fields to avoid duplication
|
|
5
|
+
* across all mutation input types.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Audit fields for creation operations
|
|
10
|
+
* Includes timestamps and user tracking
|
|
11
|
+
*/
|
|
12
|
+
export interface CreateAuditFields {
|
|
13
|
+
createdAt?: string;
|
|
14
|
+
createdBy?: string;
|
|
15
|
+
updatedAt?: string;
|
|
16
|
+
updatedBy?: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Audit fields for update operations
|
|
21
|
+
* Includes timestamps and user tracking
|
|
22
|
+
*/
|
|
23
|
+
export interface UpdateAuditFields {
|
|
24
|
+
updatedAt?: string;
|
|
25
|
+
updatedBy?: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Soft delete fields for entities that support soft deletion
|
|
30
|
+
* Tracks when and by whom an entity was deleted
|
|
31
|
+
*/
|
|
32
|
+
export interface SoftDeleteFields {
|
|
33
|
+
deletedAt?: string | null;
|
|
34
|
+
deletedBy?: string | null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Complete audit trail for entities with soft delete support
|
|
39
|
+
* Combines update and soft delete fields
|
|
40
|
+
*/
|
|
41
|
+
export interface UpdateWithSoftDeleteFields extends UpdateAuditFields, SoftDeleteFields {}
|
package/src/mutations/index.ts
CHANGED
|
@@ -4,6 +4,14 @@
|
|
|
4
4
|
* Provides mutation functions for creating, updating, and deleting data via the GraphQL API.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
// Common base types
|
|
8
|
+
export type {
|
|
9
|
+
CreateAuditFields,
|
|
10
|
+
UpdateAuditFields,
|
|
11
|
+
SoftDeleteFields,
|
|
12
|
+
UpdateWithSoftDeleteFields,
|
|
13
|
+
} from "./common";
|
|
14
|
+
|
|
7
15
|
// Brand mutations
|
|
8
16
|
export {
|
|
9
17
|
createBrand,
|
|
@@ -53,3 +61,17 @@ export {
|
|
|
53
61
|
initializeSystemSettings,
|
|
54
62
|
type UpdateSystemSettingsInput,
|
|
55
63
|
} from "./systemSettings";
|
|
64
|
+
|
|
65
|
+
// Reservation mutations
|
|
66
|
+
export {
|
|
67
|
+
createReservation,
|
|
68
|
+
updateReservation,
|
|
69
|
+
deleteReservation,
|
|
70
|
+
softDeleteReservation,
|
|
71
|
+
restoreReservation,
|
|
72
|
+
updateReservationStatus,
|
|
73
|
+
ReservationValidationError,
|
|
74
|
+
type CreateReservationInput,
|
|
75
|
+
type UpdateReservationInput,
|
|
76
|
+
type ReservationStatus,
|
|
77
|
+
} from "./reservations";
|
|
@@ -132,7 +132,7 @@ describe('ProductInstance Mutations', () => {
|
|
|
132
132
|
accountId: 'account-789',
|
|
133
133
|
enabled: true,
|
|
134
134
|
version: '1.0.0',
|
|
135
|
-
|
|
135
|
+
updatedAt: mockTimestamp,
|
|
136
136
|
updatedBy: mockUserId,
|
|
137
137
|
})
|
|
138
138
|
);
|
|
@@ -183,7 +183,7 @@ describe('ProductInstance Mutations', () => {
|
|
|
183
183
|
await createProductInstance(mockClient, validInput);
|
|
184
184
|
|
|
185
185
|
const callArgs = mockCreate.mock.calls[0][0];
|
|
186
|
-
expect(callArgs.
|
|
186
|
+
expect(callArgs.updatedAt).toBe(mockTimestamp);
|
|
187
187
|
});
|
|
188
188
|
|
|
189
189
|
it('should use provided updatedBy if specified', async () => {
|
|
@@ -358,7 +358,7 @@ describe('ProductInstance Mutations', () => {
|
|
|
358
358
|
await updateProductInstance(mockClient, validInput);
|
|
359
359
|
|
|
360
360
|
const callArgs = mockUpdate.mock.calls[0][0];
|
|
361
|
-
expect(callArgs.
|
|
361
|
+
expect(callArgs.updatedAt).toBe(mockTimestamp);
|
|
362
362
|
expect(callArgs.updatedBy).toBe(mockUserId);
|
|
363
363
|
});
|
|
364
364
|
|
|
@@ -9,6 +9,7 @@ import type { ProductInstance } from "@htlkg/core/types";
|
|
|
9
9
|
import { getClientUser } from "@htlkg/core/auth";
|
|
10
10
|
import { getCurrentTimestamp } from "@htlkg/core/utils";
|
|
11
11
|
import { AppError } from "@htlkg/core/errors";
|
|
12
|
+
import type { CreateAuditFields, UpdateAuditFields } from "../common";
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* Get current user identifier for audit trails
|
|
@@ -29,7 +30,7 @@ async function getUserIdentifier(fallback = "system"): Promise<string> {
|
|
|
29
30
|
/**
|
|
30
31
|
* Input type for creating a product instance
|
|
31
32
|
*/
|
|
32
|
-
export interface CreateProductInstanceInput {
|
|
33
|
+
export interface CreateProductInstanceInput extends CreateAuditFields {
|
|
33
34
|
productId: string;
|
|
34
35
|
brandId: string;
|
|
35
36
|
accountId: string;
|
|
@@ -37,21 +38,16 @@ export interface CreateProductInstanceInput {
|
|
|
37
38
|
enabled: boolean;
|
|
38
39
|
config?: Record<string, any>;
|
|
39
40
|
version?: string;
|
|
40
|
-
createdBy?: string;
|
|
41
|
-
lastUpdated?: string;
|
|
42
|
-
updatedBy?: string;
|
|
43
41
|
}
|
|
44
42
|
|
|
45
43
|
/**
|
|
46
44
|
* Input type for updating a product instance
|
|
47
45
|
*/
|
|
48
|
-
export interface UpdateProductInstanceInput {
|
|
46
|
+
export interface UpdateProductInstanceInput extends UpdateAuditFields {
|
|
49
47
|
id: string;
|
|
50
48
|
enabled?: boolean;
|
|
51
49
|
config?: Record<string, any>;
|
|
52
50
|
version?: string;
|
|
53
|
-
lastUpdated?: string;
|
|
54
|
-
updatedBy?: string;
|
|
55
51
|
}
|
|
56
52
|
|
|
57
53
|
/**
|
|
@@ -81,6 +77,7 @@ export async function createProductInstance<TClient = any>(
|
|
|
81
77
|
const userIdentifier = input.createdBy || input.updatedBy || await getUserIdentifier();
|
|
82
78
|
|
|
83
79
|
// Build input - manually construct to avoid Vue Proxy issues
|
|
80
|
+
const timestamp = input.createdAt || getCurrentTimestamp();
|
|
84
81
|
const createInput: any = {
|
|
85
82
|
productId: input.productId,
|
|
86
83
|
productName: input.productName,
|
|
@@ -88,8 +85,9 @@ export async function createProductInstance<TClient = any>(
|
|
|
88
85
|
accountId: input.accountId,
|
|
89
86
|
enabled: input.enabled,
|
|
90
87
|
version: input.version,
|
|
88
|
+
createdAt: timestamp,
|
|
91
89
|
createdBy: userIdentifier,
|
|
92
|
-
|
|
90
|
+
updatedAt: input.updatedAt || timestamp,
|
|
93
91
|
updatedBy: userIdentifier,
|
|
94
92
|
};
|
|
95
93
|
|
|
@@ -154,7 +152,7 @@ export async function updateProductInstance<TClient = any>(
|
|
|
154
152
|
// Convert config from Vue Proxy to plain object
|
|
155
153
|
const updateInput: any = {
|
|
156
154
|
...input,
|
|
157
|
-
|
|
155
|
+
updatedAt: input.updatedAt || getCurrentTimestamp(),
|
|
158
156
|
updatedBy: input.updatedBy || await getUserIdentifier(),
|
|
159
157
|
};
|
|
160
158
|
|