@explorins/pers-sdk-react-native 2.3.2 → 2.3.4

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/index.d.ts CHANGED
@@ -137,6 +137,7 @@ export { PersSDKProvider, usePersSDK, type PersConfig, type PersSDKContext } fro
137
137
  *
138
138
  * **Business & Campaign Management:**
139
139
  * - `useBusiness` - Business profile and operations
140
+ * - `useBookings` - Booking management with status validation
140
141
  * - `useCampaigns` - Marketing campaigns and promotions
141
142
  * - `useRedemptions` - Reward redemption and fulfillment
142
143
  *
@@ -207,7 +208,7 @@ export { PersSDKProvider, usePersSDK, type PersConfig, type PersSDKContext } fro
207
208
  * }
208
209
  * ```
209
210
  */
210
- export { useAuth, useTokens, useTokenBalances, useTransactions, useTransactionSigner, SigningStatus, useBusiness, useCampaigns, useRedemptions, useWeb3, usePurchases, useTenants, useUsers, useUserStatus, useFiles, useAnalytics, useDonations, useEvents, useTriggerSources, useResolvedUrl, useMetadata, useIPFSUrl, // alias for useResolvedUrl
211
+ export { useAuth, useTokens, useTokenBalances, useTransactions, useTransactionSigner, SigningStatus, useBusiness, useBookings, useCampaigns, useRedemptions, useWeb3, usePurchases, useTenants, useUsers, useUserStatus, useFiles, useAnalytics, useDonations, useEvents, useTriggerSources, useResolvedUrl, useMetadata, useIPFSUrl, // alias for useResolvedUrl
211
212
  useTransactionMetadata } from './hooks';
212
213
  export type { TransactionSignerHook, OnStatusUpdateFn, StatusUpdateData, SigningStatusType, TransactionSigningResult, SubmissionResult, AuthenticatedUser } from './hooks';
213
214
  export type { EventsHook, PersEvent, EventHandler, EventFilter, Unsubscribe } from './hooks';
@@ -218,6 +219,7 @@ export type { BusinessFilterOptions, BusinessHook } from './hooks';
218
219
  export type { TransactionQueryOptions, TransactionHook } from './hooks';
219
220
  export type { TriggerSourceQueryOptions, TriggerSourceHook } from './hooks';
220
221
  export type { AnalyticsHook } from './hooks';
222
+ export type { BookingHook, BookingQueryOptions, BookingValidationOptions } from './hooks';
221
223
  /**
222
224
  * React Native-optimized HTTP client with automatic request/response handling
223
225
  *
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -3445,10 +3445,6 @@ const getOperatorText = (op) => operatorText[op];
3445
3445
  * Does not check cross-field comparisons (use validateFieldComparisons for that).
3446
3446
  */
3447
3447
  const validateFieldValue = (value, rules, fieldType) => {
3448
- // No rules = valid
3449
- if (!rules) {
3450
- return null;
3451
- }
3452
3448
  const stringValue = value !== null && value !== undefined ? String(value) : '';
3453
3449
  const isEmpty = value === null || value === undefined || value === '';
3454
3450
  // Skip validation if empty - required-ness is determined by requiredUserFields
@@ -3456,16 +3452,17 @@ const validateFieldValue = (value, rules, fieldType) => {
3456
3452
  if (isEmpty) {
3457
3453
  return null;
3458
3454
  }
3459
- // Type-specific validation
3455
+ // Type-specific validation (happens regardless of rules)
3456
+ // Rules object only controls additional constraints (min/max, length, etc.)
3460
3457
  switch (fieldType) {
3461
3458
  case 'text':
3462
- if (rules.minLength && stringValue.length < rules.minLength) {
3459
+ if (rules?.minLength && stringValue.length < rules.minLength) {
3463
3460
  return { field: '', message: `Minimum ${rules.minLength} characters required`, code: 'minLength' };
3464
3461
  }
3465
- if (rules.maxLength && stringValue.length > rules.maxLength) {
3462
+ if (rules?.maxLength && stringValue.length > rules.maxLength) {
3466
3463
  return { field: '', message: `Maximum ${rules.maxLength} characters allowed`, code: 'maxLength' };
3467
3464
  }
3468
- if (rules.pattern && !new RegExp(rules.pattern).test(stringValue)) {
3465
+ if (rules?.pattern && !new RegExp(rules.pattern).test(stringValue)) {
3469
3466
  return { field: '', message: rules.patternMessage || 'Invalid format', code: 'pattern' };
3470
3467
  }
3471
3468
  break;
@@ -3473,7 +3470,7 @@ const validateFieldValue = (value, rules, fieldType) => {
3473
3470
  if (stringValue.length > EMAIL_MAX_LENGTH || !EMAIL_REGEX.test(stringValue)) {
3474
3471
  return { field: '', message: 'Invalid email format', code: 'email' };
3475
3472
  }
3476
- if (rules.maxLength && stringValue.length > rules.maxLength) {
3473
+ if (rules?.maxLength && stringValue.length > rules.maxLength) {
3477
3474
  return { field: '', message: `Maximum ${rules.maxLength} characters allowed`, code: 'maxLength' };
3478
3475
  }
3479
3476
  break;
@@ -3481,19 +3478,20 @@ const validateFieldValue = (value, rules, fieldType) => {
3481
3478
  if (!URL_REGEX.test(stringValue)) {
3482
3479
  return { field: '', message: 'Invalid URL format', code: 'url' };
3483
3480
  }
3484
- if (rules.maxLength && stringValue.length > rules.maxLength) {
3481
+ if (rules?.maxLength && stringValue.length > rules.maxLength) {
3485
3482
  return { field: '', message: `Maximum ${rules.maxLength} characters allowed`, code: 'maxLength' };
3486
3483
  }
3487
3484
  break;
3488
3485
  case 'number':
3489
3486
  const numValue = typeof value === 'number' ? value : parseFloat(stringValue);
3490
- if (isNaN(numValue)) {
3487
+ // Check if string contains non-numeric garbage
3488
+ if (isNaN(numValue) || (typeof value === 'string' && !/^-?\d*\.?\d+$/.test(stringValue.trim()))) {
3491
3489
  return { field: '', message: 'Must be a valid number', code: 'type' };
3492
3490
  }
3493
- if (rules.min !== undefined && numValue < rules.min) {
3491
+ if (rules?.min !== undefined && numValue < rules.min) {
3494
3492
  return { field: '', message: `Minimum value is ${rules.min}`, code: 'min' };
3495
3493
  }
3496
- if (rules.max !== undefined && numValue > rules.max) {
3494
+ if (rules?.max !== undefined && numValue > rules.max) {
3497
3495
  return { field: '', message: `Maximum value is ${rules.max}`, code: 'max' };
3498
3496
  }
3499
3497
  break;
@@ -3508,7 +3506,7 @@ const validateFieldValue = (value, rules, fieldType) => {
3508
3506
  return { field: '', message: 'Must be a valid date', code: 'type' };
3509
3507
  }
3510
3508
  const now = new Date();
3511
- if (rules.minDate) {
3509
+ if (rules?.minDate) {
3512
3510
  const minDate = rules.minDate === 'now' ? now : new Date(rules.minDate);
3513
3511
  if (dateValue < minDate) {
3514
3512
  return {
@@ -3518,7 +3516,7 @@ const validateFieldValue = (value, rules, fieldType) => {
3518
3516
  };
3519
3517
  }
3520
3518
  }
3521
- if (rules.maxDate) {
3519
+ if (rules?.maxDate) {
3522
3520
  const maxDate = rules.maxDate === 'now' ? now : new Date(rules.maxDate);
3523
3521
  if (dateValue > maxDate) {
3524
3522
  return {
@@ -3535,10 +3533,10 @@ const validateFieldValue = (value, rules, fieldType) => {
3535
3533
  if (!phoneRegex.test(stringValue)) {
3536
3534
  return { field: '', message: 'Invalid phone number format', code: 'phone' };
3537
3535
  }
3538
- if (rules.minLength && stringValue.replace(/\D/g, '').length < rules.minLength) {
3536
+ if (rules?.minLength && stringValue.replace(/\D/g, '').length < rules.minLength) {
3539
3537
  return { field: '', message: `Phone number too short`, code: 'minLength' };
3540
3538
  }
3541
- if (rules.maxLength && stringValue.length > rules.maxLength) {
3539
+ if (rules?.maxLength && stringValue.length > rules.maxLength) {
3542
3540
  return { field: '', message: `Maximum ${rules.maxLength} characters allowed`, code: 'maxLength' };
3543
3541
  }
3544
3542
  break;
@@ -3552,10 +3550,10 @@ const validateFieldValue = (value, rules, fieldType) => {
3552
3550
  if (!Array.isArray(value)) {
3553
3551
  return { field: '', message: 'Must be an array', code: 'type' };
3554
3552
  }
3555
- if (rules.minItems !== undefined && value.length < rules.minItems) {
3553
+ if (rules?.minItems !== undefined && value.length < rules.minItems) {
3556
3554
  return { field: '', message: `Select at least ${rules.minItems} options`, code: 'minItems' };
3557
3555
  }
3558
- if (rules.maxItems !== undefined && value.length > rules.maxItems) {
3556
+ if (rules?.maxItems !== undefined && value.length > rules.maxItems) {
3559
3557
  return { field: '', message: `Select at most ${rules.maxItems} options`, code: 'maxItems' };
3560
3558
  }
3561
3559
  // Validate each item is a string
@@ -4249,6 +4247,48 @@ function isBookingStatusValid(status, requirement) {
4249
4247
  return false;
4250
4248
  }
4251
4249
  }
4250
+ /**
4251
+ * Compute booking status based on check-in and check-out dates.
4252
+ *
4253
+ * Logic:
4254
+ * - 'past': Check-out date is before today (booking ended yesterday or earlier)
4255
+ * - 'active': Check-in date is today or earlier, AND check-out is today or later (guest is staying)
4256
+ * - 'future': Check-in date is after today (upcoming booking)
4257
+ *
4258
+ * Note: Checkout day itself counts as 'active' since guest is there until end of day.
4259
+ *
4260
+ * @param checkInDate - Booking start date
4261
+ * @param checkOutDate - Booking end date
4262
+ * @param referenceDate - Date to compare against (defaults to current date)
4263
+ * @returns Computed booking status
4264
+ *
4265
+ * @example
4266
+ * // Today is June 5
4267
+ * computeBookingStatus('2026-06-01', '2026-06-04') // 'past' (checked out yesterday)
4268
+ * computeBookingStatus('2026-06-01', '2026-06-05') // 'active' (checking out today)
4269
+ * computeBookingStatus('2026-06-03', '2026-06-08') // 'active' (currently staying)
4270
+ * computeBookingStatus('2026-06-10', '2026-06-15') // 'future' (upcoming)
4271
+ */
4272
+ function computeBookingStatus(checkInDate, checkOutDate, referenceDate = new Date()) {
4273
+ // Normalize all dates to start of day (00:00:00)
4274
+ const now = new Date(referenceDate);
4275
+ const checkIn = new Date(checkInDate);
4276
+ const checkOut = new Date(checkOutDate);
4277
+ now.setHours(0, 0, 0, 0);
4278
+ checkIn.setHours(0, 0, 0, 0);
4279
+ checkOut.setHours(0, 0, 0, 0);
4280
+ // Checkout day itself counts as still active (guest there until end of day)
4281
+ if (checkOut < now) {
4282
+ return 'past';
4283
+ }
4284
+ else if (checkIn <= now) {
4285
+ // Note: checkOut >= now is implicit here (already ruled out checkOut < now above)
4286
+ return 'active';
4287
+ }
4288
+ else {
4289
+ return 'future';
4290
+ }
4291
+ }
4252
4292
 
4253
4293
  /**
4254
4294
  * Unified data source tracking for analytics across all entities.
@@ -12075,7 +12115,7 @@ class DefaultAuthProvider {
12075
12115
  /** SDK package name */
12076
12116
  const SDK_NAME = "@explorins/pers-sdk";
12077
12117
  /** SDK version - injected from package.json at build time */
12078
- const SDK_VERSION = "2.3.3";
12118
+ const SDK_VERSION = "2.3.9";
12079
12119
  /** Full SDK identifier for headers */
12080
12120
  const SDK_USER_AGENT = `${SDK_NAME}/${SDK_VERSION}`;
12081
12121
 
@@ -50322,6 +50362,158 @@ const useTriggerSources = () => {
50322
50362
  };
50323
50363
  };
50324
50364
 
50365
+ /**
50366
+ * React hook for booking management operations
50367
+ *
50368
+ * Provides methods to create, read, update, and delete bookings,
50369
+ * as well as checking if a user has a valid booking for redemption eligibility.
50370
+ *
50371
+ * @example
50372
+ * ```typescript
50373
+ * import { useBookings } from '@explorins/pers-sdk-react-native';
50374
+ *
50375
+ * function BookingScreen() {
50376
+ * const { getBookings, createBooking, hasValidBooking } = useBookings();
50377
+ *
50378
+ * // List all bookings for a user
50379
+ * const userBookings = await getBookings({ userId: 'user-123' });
50380
+ *
50381
+ * // Create a booking
50382
+ * const newBooking = await createBooking({
50383
+ * userId: 'user-123',
50384
+ * locationName: 'Resort Hotel',
50385
+ * checkInDate: '2026-06-01',
50386
+ * checkOutDate: '2026-06-05'
50387
+ * });
50388
+ *
50389
+ * // Check if user has valid booking for redemption
50390
+ * const isEligible = await hasValidBooking('user-123', { status: 'active' });
50391
+ * }
50392
+ * ```
50393
+ */
50394
+ const useBookings = () => {
50395
+ const { sdk, isInitialized, isAuthenticated } = usePersSDK();
50396
+ /**
50397
+ * Get all bookings with optional filters
50398
+ *
50399
+ * @param options - Query options including userId, businessId, status filters
50400
+ * @returns Array of booking DTOs
50401
+ */
50402
+ const getBookings = react.useCallback(async (options) => {
50403
+ if (!isInitialized || !sdk) {
50404
+ throw new Error('SDK not initialized. Call initialize() first.');
50405
+ }
50406
+ try {
50407
+ return await sdk.bookings.getAll(options);
50408
+ }
50409
+ catch (error) {
50410
+ console.error('Failed to fetch bookings:', error);
50411
+ throw error;
50412
+ }
50413
+ }, [sdk, isInitialized]);
50414
+ /**
50415
+ * Get a single booking by ID
50416
+ *
50417
+ * @param id - Booking UUID
50418
+ * @returns Booking DTO
50419
+ */
50420
+ const getBookingById = react.useCallback(async (id) => {
50421
+ if (!isInitialized || !sdk) {
50422
+ throw new Error('SDK not initialized. Call initialize() first.');
50423
+ }
50424
+ try {
50425
+ return await sdk.bookings.getById(id);
50426
+ }
50427
+ catch (error) {
50428
+ console.error('Failed to fetch booking:', error);
50429
+ throw error;
50430
+ }
50431
+ }, [sdk, isInitialized]);
50432
+ /**
50433
+ * Create a new booking
50434
+ *
50435
+ * @param data - Booking data including userId, locationName, dates
50436
+ * @returns Created booking DTO
50437
+ */
50438
+ const createBooking = react.useCallback(async (data) => {
50439
+ if (!isInitialized || !sdk) {
50440
+ throw new Error('SDK not initialized. Call initialize() first.');
50441
+ }
50442
+ try {
50443
+ return await sdk.bookings.create(data);
50444
+ }
50445
+ catch (error) {
50446
+ console.error('Failed to create booking:', error);
50447
+ throw error;
50448
+ }
50449
+ }, [sdk, isInitialized]);
50450
+ /**
50451
+ * Update an existing booking
50452
+ *
50453
+ * @param id - Booking UUID
50454
+ * @param data - Partial booking data to update
50455
+ * @returns Updated booking DTO
50456
+ */
50457
+ const updateBooking = react.useCallback(async (id, data) => {
50458
+ if (!isInitialized || !sdk) {
50459
+ throw new Error('SDK not initialized. Call initialize() first.');
50460
+ }
50461
+ try {
50462
+ return await sdk.bookings.update(id, data);
50463
+ }
50464
+ catch (error) {
50465
+ console.error('Failed to update booking:', error);
50466
+ throw error;
50467
+ }
50468
+ }, [sdk, isInitialized]);
50469
+ /**
50470
+ * Delete a booking
50471
+ *
50472
+ * @param id - Booking UUID
50473
+ */
50474
+ const deleteBooking = react.useCallback(async (id) => {
50475
+ if (!isInitialized || !sdk) {
50476
+ throw new Error('SDK not initialized. Call initialize() first.');
50477
+ }
50478
+ try {
50479
+ await sdk.bookings.delete(id);
50480
+ }
50481
+ catch (error) {
50482
+ console.error('Failed to delete booking:', error);
50483
+ throw error;
50484
+ }
50485
+ }, [sdk, isInitialized]);
50486
+ /**
50487
+ * Check if a user has a valid booking
50488
+ *
50489
+ * @param userId - User ID to check
50490
+ * @param options - Validation options including status filter
50491
+ * @returns true if user has valid booking matching criteria
50492
+ */
50493
+ const hasValidBooking = react.useCallback(async (userId, options) => {
50494
+ if (!isInitialized || !sdk) {
50495
+ throw new Error('SDK not initialized. Call initialize() first.');
50496
+ }
50497
+ try {
50498
+ return await sdk.bookings.hasValidBooking(userId, options);
50499
+ }
50500
+ catch (error) {
50501
+ console.error('Failed to check booking validity:', error);
50502
+ throw error;
50503
+ }
50504
+ }, [sdk, isInitialized]);
50505
+ return {
50506
+ getBookings,
50507
+ getBookingById,
50508
+ createBooking,
50509
+ updateBooking,
50510
+ deleteBooking,
50511
+ hasValidBooking,
50512
+ isInitialized,
50513
+ isAuthenticated,
50514
+ };
50515
+ };
50516
+
50325
50517
  exports.ACTIVE_USER_DEFINITION = ACTIVE_USER_DEFINITION;
50326
50518
  exports.ANALYTICS_GROUP_BY_TYPES = ANALYTICS_GROUP_BY_TYPES;
50327
50519
  exports.ANALYTICS_METRIC_TYPES = ANALYTICS_METRIC_TYPES;
@@ -50485,6 +50677,7 @@ exports.buildWalletEventsWsUrl = buildWalletEventsWsUrl;
50485
50677
  exports.builtInUserFieldMetadata = builtInUserFieldMetadata;
50486
50678
  exports.builtInUserFields = builtInUserFields;
50487
50679
  exports.compareValues = compareValues;
50680
+ exports.computeBookingStatus = computeBookingStatus;
50488
50681
  exports.createPersEventsClient = createPersEventsClient;
50489
50682
  exports.createPersSDK = createPersSDK;
50490
50683
  exports.createReactNativeAuthProvider = createReactNativeAuthProvider;
@@ -50558,6 +50751,7 @@ exports.testnetShortPrefix = testnetShortPrefix;
50558
50751
  exports.uniqueUserIdentifierKeys = uniqueUserIdentifierKeys;
50559
50752
  exports.useAnalytics = useAnalytics;
50560
50753
  exports.useAuth = useAuth;
50754
+ exports.useBookings = useBookings;
50561
50755
  exports.useBusiness = useBusiness;
50562
50756
  exports.useCampaigns = useCampaigns;
50563
50757
  exports.useDonations = useDonations;