@rolatech/angular-services 20.3.0-beta.4 → 20.3.1-beta.2

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.
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, viewChild, ViewContainerRef, OutputEmitterRef, EventEmitter, HostListener, Component, Injectable, signal, computed, PLATFORM_ID, REQUEST, Directive, provideAppInitializer, makeEnvironmentProviders } from '@angular/core';
2
+ import { inject, viewChild, ViewContainerRef, OutputEmitterRef, EventEmitter, HostListener, Component, Injectable, signal, computed, PLATFORM_ID, REQUEST, LOCALE_ID, Directive, provideAppInitializer, makeEnvironmentProviders } from '@angular/core';
3
3
  import { MAT_DIALOG_DATA, MatDialogRef, MatDialogActions, MatDialogTitle, MatDialogContent, MatDialog } from '@angular/material/dialog';
4
4
  import * as i1 from '@angular/material/button';
5
5
  import { MatButtonModule } from '@angular/material/button';
@@ -7,7 +7,7 @@ import { switchMap, map, take, BehaviorSubject, Observable, Subject, firstValueF
7
7
  import _ from 'lodash';
8
8
  import { HttpClient, HttpParams, HttpHeaders, HTTP_INTERCEPTORS } from '@angular/common/http';
9
9
  import { APP_CONFIG, toApiRequestParams } from '@rolatech/angular-common';
10
- import { Location, isPlatformBrowser, isPlatformServer } from '@angular/common';
10
+ import { Location, isPlatformBrowser, DOCUMENT } from '@angular/common';
11
11
  import { Router, NavigationEnd, ActivatedRoute } from '@angular/router';
12
12
  import { BreakpointObserver, Breakpoints, MediaMatcher } from '@angular/cdk/layout';
13
13
  import { map as map$1, shareReplay, finalize } from 'rxjs/operators';
@@ -1630,6 +1630,9 @@ class PropertyService extends BaseService {
1630
1630
  findWishlist(options) {
1631
1631
  return this.http.get(`${this.actionUrl}/wishlist`, { params: options, withCredentials: true });
1632
1632
  }
1633
+ joinFeatureWaitlist(featureCode, data) {
1634
+ return this.http.post(`${this.actionUrl}/features/${featureCode}/waitlist`, data, { withCredentials: true });
1635
+ }
1633
1636
  addToWishlist(propertyId) {
1634
1637
  return this.http.post(`${this.actionUrl}/${propertyId}/wishlist`, {}, { withCredentials: true });
1635
1638
  }
@@ -1772,27 +1775,35 @@ class PropertyService extends BaseService {
1772
1775
  });
1773
1776
  }
1774
1777
  findViewings(options) {
1775
- return this.http.get(`${this.actionUrl}/viewings`, {
1778
+ return this.http
1779
+ .get(`${this.actionUrl}/viewings`, {
1776
1780
  params: options,
1777
1781
  withCredentials: true,
1778
- });
1782
+ })
1783
+ .pipe(map((response) => this.normalizeViewingResponse(response)));
1779
1784
  }
1780
1785
  findViewingsByUser(options) {
1781
- return this.http.get(`${this.actionUrl}/viewings/by/user`, {
1786
+ return this.http
1787
+ .get(`${this.actionUrl}/viewings/by/user`, {
1782
1788
  params: options,
1783
1789
  withCredentials: true,
1784
- });
1790
+ })
1791
+ .pipe(map((response) => this.normalizeViewingResponse(response)));
1785
1792
  }
1786
1793
  findViewingsByAgent(options) {
1787
- return this.http.get(`${this.actionUrl}/viewings/by/agent`, {
1794
+ return this.http
1795
+ .get(`${this.actionUrl}/viewings/by/agent`, {
1788
1796
  params: options,
1789
1797
  withCredentials: true,
1790
- });
1798
+ })
1799
+ .pipe(map((response) => this.normalizeViewingResponse(response)));
1791
1800
  }
1792
1801
  requestViewing(propertyId, data) {
1793
- return this.http.post(`${this.actionUrl}/${propertyId}/viewings`, data, {
1802
+ return this.http
1803
+ .post(`${this.actionUrl}/${propertyId}/viewings`, data, {
1794
1804
  withCredentials: true,
1795
- });
1805
+ })
1806
+ .pipe(map((response) => this.normalizeViewingResponse(response)));
1796
1807
  }
1797
1808
  confirmViewing(viewingId, slotId) {
1798
1809
  return this.http.post(`${this.actionUrl}/viewings/${viewingId}/confirm?slotId=${slotId}`, {}, {
@@ -1800,7 +1811,9 @@ class PropertyService extends BaseService {
1800
1811
  });
1801
1812
  }
1802
1813
  getViewing(viewingId) {
1803
- return this.http.get(`${this.actionUrl}/viewings/${viewingId}`, { withCredentials: true });
1814
+ return this.http
1815
+ .get(`${this.actionUrl}/viewings/${viewingId}`, { withCredentials: true })
1816
+ .pipe(map((response) => this.normalizeViewingResponse(response)));
1804
1817
  }
1805
1818
  cancelViewing(id) {
1806
1819
  return this.http.post(`${this.actionUrl}/viewings/${id}/cancel`, {}, {
@@ -1908,6 +1921,61 @@ class PropertyService extends BaseService {
1908
1921
  deleteEpc(id) {
1909
1922
  return this.http.delete(`${this.actionUrl}/${id}/epc`, { withCredentials: true });
1910
1923
  }
1924
+ normalizeViewingResponse(response) {
1925
+ if (!response || typeof response !== 'object' || !('data' in response)) {
1926
+ return response;
1927
+ }
1928
+ return {
1929
+ ...response,
1930
+ data: Array.isArray(response.data)
1931
+ ? response.data.map((item) => this.normalizeViewing(item))
1932
+ : this.normalizeViewing(response.data),
1933
+ };
1934
+ }
1935
+ normalizeViewing(viewing) {
1936
+ if (!viewing || typeof viewing !== 'object') {
1937
+ return viewing;
1938
+ }
1939
+ return {
1940
+ ...viewing,
1941
+ jobTitle: viewing.jobTitle ?? viewing.profession ?? null,
1942
+ monthlyBudget: viewing.monthlyBudget ?? viewing.budgetPerMonth ?? null,
1943
+ annualIncome: viewing.annualIncome ?? viewing.income ?? null,
1944
+ moveInDate: viewing.moveInDate ?? viewing.startDate ?? null,
1945
+ tenantCategory: viewing.tenantCategory ?? viewing.applicantType ?? null,
1946
+ viewerCategory: this.normalizeCode(viewing.viewerCategory),
1947
+ status: this.normalizeCode(viewing.status),
1948
+ item: viewing.item ? this.normalizeViewingItem(viewing.item, viewing.property?.media) : viewing.item,
1949
+ };
1950
+ }
1951
+ normalizeViewingItem(item, fallbackMedia) {
1952
+ if (!item || typeof item !== 'object') {
1953
+ return item;
1954
+ }
1955
+ const media = this.normalizeViewingMedia(item.media);
1956
+ const fallbackUrl = [item.mediaUrl, item.propertyMediaUrl, item.thumbnailUrl].find((value) => typeof value === 'string' && value.trim().length > 0);
1957
+ const inheritedMedia = this.normalizeViewingMedia(fallbackMedia);
1958
+ return {
1959
+ ...item,
1960
+ media: media.length > 0
1961
+ ? media
1962
+ : fallbackUrl
1963
+ ? [{ id: '', url: fallbackUrl, alt: item.title ?? '' }]
1964
+ : inheritedMedia,
1965
+ };
1966
+ }
1967
+ normalizeViewingMedia(media) {
1968
+ if (Array.isArray(media)) {
1969
+ return media;
1970
+ }
1971
+ if (media && typeof media === 'object') {
1972
+ return [media];
1973
+ }
1974
+ return [];
1975
+ }
1976
+ normalizeCode(value) {
1977
+ return typeof value === 'string' ? value.trim().toUpperCase() : value;
1978
+ }
1911
1979
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: PropertyService, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
1912
1980
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: PropertyService, providedIn: 'root' });
1913
1981
  }
@@ -3576,11 +3644,154 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImpor
3576
3644
  }]
3577
3645
  }] });
3578
3646
 
3579
- // i18n-locale.service.ts
3647
+ const YEAR_IN_SECONDS = 60 * 60 * 24 * 365;
3648
+ const LANGUAGE_OPTIONS = [
3649
+ {
3650
+ code: 'en',
3651
+ label: 'English',
3652
+ locale: 'en-GB',
3653
+ routePrefix: '/en-gb',
3654
+ pathPrefixes: ['/en-gb', '/en-us'],
3655
+ aliases: ['en', 'en-us', 'en-gb'],
3656
+ },
3657
+ {
3658
+ code: 'zh-Hans',
3659
+ label: '简体中文',
3660
+ locale: 'zh-CN',
3661
+ routePrefix: '/zh-cn',
3662
+ pathPrefixes: ['/zh-cn'],
3663
+ aliases: ['zh', 'zh-cn', 'zh-hans'],
3664
+ },
3665
+ ];
3666
+ class LanguageService {
3667
+ platformId = inject(PLATFORM_ID);
3668
+ request = inject(REQUEST, { optional: true });
3669
+ document = inject(DOCUMENT);
3670
+ localeId = inject(LOCALE_ID, { optional: true }) ?? 'en-US';
3671
+ storageKey = 'hl';
3672
+ cookieKey = 'hl';
3673
+ options = LANGUAGE_OPTIONS;
3674
+ lang = signal(this.detectInitial(), ...(ngDevMode ? [{ debugName: "lang" }] : []));
3675
+ currentOption = computed(() => this.findByCode(this.lang()) ?? LANGUAGE_OPTIONS[0], ...(ngDevMode ? [{ debugName: "currentOption" }] : []));
3676
+ acceptLanguage = computed(() => this.currentOption().locale, ...(ngDevMode ? [{ debugName: "acceptLanguage" }] : []));
3677
+ set(lang) {
3678
+ const option = this.findByCode(lang);
3679
+ if (!option)
3680
+ return;
3681
+ this.lang.set(option.code);
3682
+ if (!isPlatformBrowser(this.platformId))
3683
+ return;
3684
+ localStorage.setItem(this.storageKey, option.code);
3685
+ this.document.cookie = `${this.cookieKey}=${encodeURIComponent(option.code)}; Path=/; Max-Age=${YEAR_IN_SECONDS}; SameSite=Lax`;
3686
+ this.document.documentElement.lang = option.code === 'zh-Hans' ? 'zh' : 'en';
3687
+ }
3688
+ hrefFor(lang) {
3689
+ const option = this.findByCode(lang) ?? LANGUAGE_OPTIONS[0];
3690
+ const pathname = this.stripLocalePrefix(this.currentPathname());
3691
+ const search = this.currentSearch();
3692
+ const hash = this.currentHash();
3693
+ const targetPath = pathname === '/' ? option.routePrefix : `${option.routePrefix}${pathname}`;
3694
+ return `${targetPath}${search}${hash}`;
3695
+ }
3696
+ isActive(lang) {
3697
+ return this.currentOption().code === lang;
3698
+ }
3699
+ detectInitial() {
3700
+ return (this.detectFromPath(this.currentPathname()) ??
3701
+ this.detectFromValue(this.readCookie()) ??
3702
+ this.detectFromStorage() ??
3703
+ this.detectFromValue(this.localeId) ??
3704
+ this.detectFromNavigator() ??
3705
+ LANGUAGE_OPTIONS[0].code);
3706
+ }
3707
+ detectFromStorage() {
3708
+ if (!isPlatformBrowser(this.platformId) || typeof localStorage === 'undefined') {
3709
+ return null;
3710
+ }
3711
+ return this.detectFromValue(localStorage.getItem(this.storageKey));
3712
+ }
3713
+ detectFromNavigator() {
3714
+ if (!isPlatformBrowser(this.platformId) || typeof navigator === 'undefined') {
3715
+ return null;
3716
+ }
3717
+ return this.detectFromValue(navigator.language || navigator.languages?.[0] || null);
3718
+ }
3719
+ detectFromPath(pathname) {
3720
+ const normalizedPath = pathname.toLowerCase();
3721
+ const match = LANGUAGE_OPTIONS.find((option) => option.pathPrefixes.some((prefix) => normalizedPath === prefix || normalizedPath.startsWith(`${prefix}/`)));
3722
+ return match?.code ?? null;
3723
+ }
3724
+ detectFromValue(value) {
3725
+ const normalized = value?.toLowerCase().trim();
3726
+ if (!normalized)
3727
+ return null;
3728
+ const match = LANGUAGE_OPTIONS.find((option) => option.code.toLowerCase() === normalized || option.aliases.includes(normalized));
3729
+ return match?.code ?? null;
3730
+ }
3731
+ findByCode(code) {
3732
+ return LANGUAGE_OPTIONS.find((option) => option.code === code);
3733
+ }
3734
+ stripLocalePrefix(pathname) {
3735
+ const normalizedPath = pathname.startsWith('/') ? pathname : `/${pathname}`;
3736
+ const match = LANGUAGE_OPTIONS.find((option) => option.pathPrefixes.some((prefix) => normalizedPath === prefix || normalizedPath.startsWith(`${prefix}/`)));
3737
+ if (!match)
3738
+ return normalizedPath || '/';
3739
+ const matchedPrefix = match.pathPrefixes.find((prefix) => normalizedPath === prefix || normalizedPath.startsWith(`${prefix}/`));
3740
+ const suffix = normalizedPath.slice(matchedPrefix?.length ?? match.routePrefix.length);
3741
+ return suffix ? (suffix.startsWith('/') ? suffix : `/${suffix}`) : '/';
3742
+ }
3743
+ currentPathname() {
3744
+ if (isPlatformBrowser(this.platformId)) {
3745
+ return this.document.location?.pathname ?? '/';
3746
+ }
3747
+ return this.parseRequestUrl().pathname;
3748
+ }
3749
+ currentSearch() {
3750
+ if (isPlatformBrowser(this.platformId)) {
3751
+ return this.document.location?.search ?? '';
3752
+ }
3753
+ return this.parseRequestUrl().search;
3754
+ }
3755
+ currentHash() {
3756
+ if (!isPlatformBrowser(this.platformId))
3757
+ return '';
3758
+ return this.document.location?.hash ?? '';
3759
+ }
3760
+ parseRequestUrl() {
3761
+ const rawUrl = this.request?.originalUrl ?? this.request?.url ?? '/';
3762
+ return new URL(rawUrl, 'http://rolatech.local');
3763
+ }
3764
+ readCookie() {
3765
+ const cookieSource = isPlatformBrowser(this.platformId) ? this.document.cookie : this.readRequestCookieHeader();
3766
+ if (!cookieSource)
3767
+ return null;
3768
+ const cookies = cookieSource.split(';');
3769
+ for (const cookie of cookies) {
3770
+ const [name, ...valueParts] = cookie.trim().split('=');
3771
+ if (name === this.cookieKey) {
3772
+ return decodeURIComponent(valueParts.join('='));
3773
+ }
3774
+ }
3775
+ return null;
3776
+ }
3777
+ readRequestCookieHeader() {
3778
+ const cookieHeader = this.request?.headers?.['cookie'];
3779
+ if (Array.isArray(cookieHeader)) {
3780
+ return cookieHeader.join('; ');
3781
+ }
3782
+ return cookieHeader ?? '';
3783
+ }
3784
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: LanguageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
3785
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: LanguageService, providedIn: 'root' });
3786
+ }
3787
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: LanguageService, decorators: [{
3788
+ type: Injectable,
3789
+ args: [{ providedIn: 'root' }]
3790
+ }] });
3791
+
3580
3792
  class I18nLocaleService {
3581
- // integrate with Transloco/ngx-translate if you use it:
3582
- // set from your i18n library whenever language changes
3583
- lang = signal(navigator.language || 'en-GB', ...(ngDevMode ? [{ debugName: "lang" }] : []));
3793
+ language = inject(LanguageService);
3794
+ lang = computed(() => this.language.acceptLanguage(), ...(ngDevMode ? [{ debugName: "lang" }] : []));
3584
3795
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: I18nLocaleService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
3585
3796
  static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: I18nLocaleService, providedIn: 'root' });
3586
3797
  }
@@ -5255,42 +5466,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImpor
5255
5466
  }]
5256
5467
  }] });
5257
5468
 
5258
- // language.service.ts
5259
- class LanguageService {
5260
- platformId = inject(PLATFORM_ID);
5261
- req = inject(REQUEST);
5262
- storageKey = 'hl';
5263
- lang = signal(this.detectInitial(), ...(ngDevMode ? [{ debugName: "lang" }] : []));
5264
- acceptLanguage = computed(() => this.lang(), ...(ngDevMode ? [{ debugName: "acceptLanguage" }] : [])); // 'en' | 'zh-Hans'
5265
- detectInitial() {
5266
- // Default to English when header is null/blank/unknown
5267
- if (isPlatformServer(this.platformId)) {
5268
- const hdr = this.req?.headers?.['accept-language'] ?? '';
5269
- return hdr.toLowerCase().startsWith('zh') ? 'zh-Hans' : 'en';
5270
- }
5271
- // Browser
5272
- const saved = typeof localStorage !== 'undefined' ? localStorage.getItem(this.storageKey) : null;
5273
- if (saved === 'en' || saved === 'zh-Hans')
5274
- return saved;
5275
- const nav = (navigator.language || (navigator.languages?.[0] ?? '')).toLowerCase();
5276
- return nav.startsWith('zh') ? 'zh-Hans' : 'en';
5277
- }
5278
- set(lang) {
5279
- this.lang.set(lang);
5280
- if (isPlatformBrowser(this.platformId)) {
5281
- localStorage.setItem(this.storageKey, lang);
5282
- // Optional: keep <html lang="..."> in sync
5283
- document.documentElement.lang = lang.startsWith('zh') ? 'zh' : 'en';
5284
- }
5285
- }
5286
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: LanguageService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
5287
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: LanguageService, providedIn: 'root' });
5288
- }
5289
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.1", ngImport: i0, type: LanguageService, decorators: [{
5290
- type: Injectable,
5291
- args: [{ providedIn: 'root' }]
5292
- }] });
5293
-
5294
5469
  // Adjust to your app:
5295
5470
  const API_PREFIXES = ['/api', '/auth', '/properties']; // relative paths you own
5296
5471
  const API_HOSTS = new Set([
@@ -5533,5 +5708,5 @@ function onboardingVatModeLabel(mode) {
5533
5708
  * Generated bundle index. Do not edit.
5534
5709
  */
5535
5710
 
5536
- export { AmenityService, ApplicationService, AutomationService, BackButtonDirective, BaseService, BillingService, BookingService, BreadcrumbService, CartEventType, CartService, CategoryService, ConversationInitService, ConversationService, DialogComponent, DialogService, EnumApiClient, EnumCacheService, FacilityService, FeatureService, FloorplanService, FulfillmentService, HideFooterDirective, InventoryService, InvoiceLineService, InvoiceService, InvoiceStatsService, LayoutService, LoadingInterceptor, LoadingService, MediaService, MembershipService, NavigationService, NotificationService, NotificationStore, NotificationTemplateService, ONBOARDING_APPLICANT_TYPE_LABEL, ONBOARDING_DOCUMENT_TYPE_LABEL, ONBOARDING_ISSUE_TYPE_LABEL, ONBOARDING_STATUS_LABEL, ONBOARDING_VAT_MODE_LABEL, OfferingService, OnboardingAdminService, OnboardingApplicantService, OnboardingDocumentService, OrderPayoutService, OrderService, OrganizationInvitationService, OrganizationMemberService, PROPERTY_OFFER_STATUS_LABEL, PaymentService, PermissionService, PlatformAuthClientService, PlatformEndpointService, PlatformServiceRegistryService, PlatformUserService, PostService, ProductCategoryService, ProductService, PropertyHighlightsService, PropertyOfferCounterService, PropertyOfferService, PropertyOfferStatus, PropertySearchService, PropertyService, PropertyStatsService, PropertyViewingService, ResourceCategoryService, ResourceService, RoleService, SCHEDULE_CRON_META, SERVICE_DIRECTIVES, SidenavService, SnackBarService, SupportService, ThemeService, TimeZoneService, TitleService, acceptLanguageInterceptor, offerStatusLabel, onboardingApplicantTypeLabel, onboardingDocumentTypeLabel, onboardingIssueTypeLabel, onboardingStatusLabel, onboardingVatModeLabel, provideAngularServices };
5711
+ export { AmenityService, ApplicationService, AutomationService, BackButtonDirective, BaseService, BillingService, BookingService, BreadcrumbService, CartEventType, CartService, CategoryService, ConversationInitService, ConversationService, DialogComponent, DialogService, EnumApiClient, EnumCacheService, FacilityService, FeatureService, FloorplanService, FulfillmentService, HideFooterDirective, I18nLocaleService, InventoryService, InvoiceLineService, InvoiceService, InvoiceStatsService, LanguageService, LayoutService, LoadingInterceptor, LoadingService, MediaService, MembershipService, NavigationService, NotificationService, NotificationStore, NotificationTemplateService, ONBOARDING_APPLICANT_TYPE_LABEL, ONBOARDING_DOCUMENT_TYPE_LABEL, ONBOARDING_ISSUE_TYPE_LABEL, ONBOARDING_STATUS_LABEL, ONBOARDING_VAT_MODE_LABEL, OfferingService, OnboardingAdminService, OnboardingApplicantService, OnboardingDocumentService, OrderPayoutService, OrderService, OrganizationInvitationService, OrganizationMemberService, PROPERTY_OFFER_STATUS_LABEL, PaymentService, PermissionService, PlatformAuthClientService, PlatformEndpointService, PlatformServiceRegistryService, PlatformUserService, PostService, ProductCategoryService, ProductService, PropertyHighlightsService, PropertyOfferCounterService, PropertyOfferService, PropertyOfferStatus, PropertySearchService, PropertyService, PropertyStatsService, PropertyViewingService, ResourceCategoryService, ResourceService, RoleService, SCHEDULE_CRON_META, SERVICE_DIRECTIVES, SidenavService, SnackBarService, SupportService, ThemeService, TimeZoneService, TitleService, acceptLanguageInterceptor, offerStatusLabel, onboardingApplicantTypeLabel, onboardingDocumentTypeLabel, onboardingIssueTypeLabel, onboardingStatusLabel, onboardingVatModeLabel, provideAngularServices };
5537
5712
  //# sourceMappingURL=rolatech-angular-services.mjs.map