diff --git a/feature-libs/user/profile/assets/translations/en/address.json b/feature-libs/user/profile/assets/translations/en/address.json index bbfad2191ca..b1b1d5394b0 100644 --- a/feature-libs/user/profile/assets/translations/en/address.json +++ b/feature-libs/user/profile/assets/translations/en/address.json @@ -19,6 +19,8 @@ "placeholder": "City" }, "state": "State", + "province": "Province", + "district": "District", "zipCode": { "label": "Zip code", "placeholder": "Postal Code/Zip" @@ -36,6 +38,8 @@ "streetAddress": "Street Address", "aptSuite": "Apartment Number", "selectOne": "Select One...", + "selectProvinceFirst": "Please select a province first", + "selectCityFirst": "Please select a city first", "setAsDefault": "Set as default delivery address", "titleRequired": "Title is required.", "userAddressAddSuccess": "New address was added successfully!", diff --git a/feature-libs/user/profile/assets/translations/zh/address.json b/feature-libs/user/profile/assets/translations/zh/address.json index 241ec7cdf8d..97ba0a4674e 100644 --- a/feature-libs/user/profile/assets/translations/zh/address.json +++ b/feature-libs/user/profile/assets/translations/zh/address.json @@ -19,6 +19,8 @@ "placeholder": "城市" }, "state": "州/省", + "province": "省份", + "district": "区/县", "zipCode": { "label": "邮政编码", "placeholder": "邮政编码" @@ -36,6 +38,8 @@ "streetAddress": "街道地址", "aptSuite": "公寓号", "selectOne": "选择一个...", + "selectProvinceFirst": "请先选择省份", + "selectCityFirst": "请先选择城市", "setAsDefault": "设置默认送货地址", "titleRequired": "标题为必填项。", "userAddressAddSuccess": "新地址添加成功!", diff --git a/feature-libs/user/profile/assets/translations/zh_TW/address.json b/feature-libs/user/profile/assets/translations/zh_TW/address.json index e562c9bbe47..ea59a33f22b 100644 --- a/feature-libs/user/profile/assets/translations/zh_TW/address.json +++ b/feature-libs/user/profile/assets/translations/zh_TW/address.json @@ -19,6 +19,8 @@ "placeholder": "城市" }, "state": "州", + "province": "省份", + "district": "區/縣", "zipCode": { "label": "郵遞區號", "placeholder": "郵遞區號/ZIP" @@ -36,6 +38,8 @@ "streetAddress": "街道地址", "aptSuite": "公寓號碼", "selectOne": "選擇一個...", + "selectProvinceFirst": "請先選擇省份", + "selectCityFirst": "請先選擇城市", "setAsDefault": "設定為預設交貨地址", "titleRequired": "稱謂為必要。", "userAddressAddSuccess": "已成功新增地址!", diff --git a/feature-libs/user/profile/components/address-book/address-book.component.ts b/feature-libs/user/profile/components/address-book/address-book.component.ts index 0dcf3ddc93c..74ff43deacf 100644 --- a/feature-libs/user/profile/components/address-book/address-book.component.ts +++ b/feature-libs/user/profile/components/address-book/address-book.component.ts @@ -110,11 +110,12 @@ export class AddressBookComponent implements OnInit { textPhone, textMobile, ]) => { - let region = ''; - - if (address.region && address.region.isocode) { - region = address.region.isocode + ', '; - } + const region = this.buildRegion(address); + const countryName = + address.country?.name || address.country?.isocode || ''; + const townName = address.city?.name || address.town || ''; + const districtName = + address.cityDistrict?.name || address.district || ''; const actions: { name: string; event: string }[] = []; if (!address.defaultAddress) { @@ -125,16 +126,21 @@ export class AddressBookComponent implements OnInit { const numbers = getAddressNumbers(address, textPhone, textMobile); + const locationParts = [townName, region, countryName] + .filter(Boolean) + .join(', '); + return { role: 'application', textBold: address.firstName + ' ' + address.lastName, text: [ address.line1, address.line2, - address.town + ', ' + region + address.country?.isocode, + locationParts, + districtName, address.postalCode, numbers, - ], + ].filter(Boolean) as string[], actions: actions, header: address.defaultAddress ? `✓ ${defaultText}` : '', deleteMsg: textVerifyDeleteMsg, @@ -147,6 +153,10 @@ export class AddressBookComponent implements OnInit { ); } + private buildRegion(address: Address): string { + return address.region?.name || address.region?.isocode || ''; + } + setAddressAsDefault(address: Address): void { this.service.setAddressAsDefault(address.id ?? ''); this.globalMessageService.add( diff --git a/feature-libs/user/profile/components/address-book/address-form/address-form.component.html b/feature-libs/user/profile/components/address-book/address-form/address-form.component.html index 54fddcd11c1..3549dac0065 100644 --- a/feature-libs/user/profile/components/address-book/address-form/address-form.component.html +++ b/feature-libs/user/profile/components/address-book/address-form/address-form.component.html @@ -158,6 +158,45 @@
+ + +
+ +
+
+
- - -
- -
-
-
@@ -267,15 +329,23 @@
diff --git a/feature-libs/user/profile/components/address-book/address-form/address-form.component.spec.ts b/feature-libs/user/profile/components/address-book/address-form/address-form.component.spec.ts index b491623987f..cd73c7d7193 100644 --- a/feature-libs/user/profile/components/address-book/address-form/address-form.component.spec.ts +++ b/feature-libs/user/profile/components/address-book/address-form/address-form.component.spec.ts @@ -14,6 +14,7 @@ import { Country, GlobalMessageService, I18nTestingModule, + LanguageService, Region, Title, UserAddressService, @@ -70,6 +71,7 @@ const mockAddress: Address = { line2: 'line2', town: 'town', region: { isocode: 'JP-27' }, + district: '', postalCode: 'zip', country: { isocode: 'JP' }, phone: '123123123', @@ -102,7 +104,20 @@ class MockUserAddressService { verifyAddress(): Observable { return of({}); } + getCities(): Observable<{ isocode?: string; name?: string }[]> { + return of([]); + } + getDistricts(): Observable<{ isocode?: string; name?: string }[]> { + return of([]); + } } + +class MockLanguageService { + getActive() { + return of('en'); + } +} + const dialogClose$ = new BehaviorSubject(''); class MockLaunchDialogService implements Partial { @@ -152,6 +167,10 @@ describe('AddressFormComponent', () => { { provide: UserAddressService, useClass: MockUserAddressService }, { provide: GlobalMessageService, useValue: mockGlobalMessageService }, { provide: UserProfileFacade, useClass: MockUserProfileFacade }, + { + provide: LanguageService, + useClass: MockLanguageService, + }, ], }) .overrideComponent(AddressFormComponent, { @@ -361,6 +380,81 @@ describe('AddressFormComponent', () => { ); }); + it('should set isChineseAddress and add validators when CN is selected', () => { + spyOn(userAddressService, 'getRegions').and.returnValue(of([])); + component.countrySelected({ isocode: 'CN' }); + expect(component.isChineseAddress).toBe(true); + expect(component.addressForm.get('cellphone')?.validator).toBeTruthy(); + expect(component.addressForm.get('district')?.validator).toBeTruthy(); + }); + + it('should clear validators and reset state when switching away from CN', () => { + spyOn(userAddressService, 'getRegions').and.returnValue(of([])); + component.countrySelected({ isocode: 'CN' }); + component.countrySelected({ isocode: 'US' }); + expect(component.isChineseAddress).toBe(false); + expect(component.addressForm.get('cellphone')?.validator).toBeNull(); + expect(component.addressForm.get('district')?.validator).toBeNull(); + }); + + it('should reset town and district when region changes for CN address', () => { + component.isChineseAddress = true; + component.addressForm.get('town')?.setValue('old-town'); + component.addressForm.get('district')?.setValue('old-district'); + component.regionSelected({ isocode: 'CN-11' }); + expect(component.addressForm.get('town')?.value).toBeNull(); + expect(component.addressForm.get('district')?.value).toBeNull(); + }); + + it('should not reset town and district when region changes for non-CN address', () => { + component.isChineseAddress = false; + component.addressForm.get('town')?.setValue('old-town'); + component.regionSelected({ isocode: 'US-CA' }); + expect(component.addressForm.get('town')?.value).toEqual('old-town'); + }); + + it('should update selectedCity$ and reset district on citySelected', () => { + component.addressForm.get('district')?.setValue('old-district'); + component.citySelected({ isocode: 'CN-11-1', name: 'Beijing' }); + expect(component.addressForm.get('district')?.value).toBeNull(); + }); + + it('should not update selectedCity$ when city is undefined', () => { + component.addressForm.get('district')?.setValue('old-district'); + component.citySelected(undefined); + expect(component.addressForm.get('district')?.value).toEqual( + 'old-district' + ); + }); + + it('should initialize cities as empty array', () => { + spyOn(userAddressService, 'getDeliveryCountries').and.returnValue(of([])); + spyOn(userAddressService, 'getRegions').and.returnValue(of([])); + component.ngOnInit(); + expect(component.cities).toEqual([]); + }); + + it('should initialize districts as empty array', () => { + spyOn(userAddressService, 'getDeliveryCountries').and.returnValue(of([])); + spyOn(userAddressService, 'getRegions').and.returnValue(of([])); + component.ngOnInit(); + expect(component.districts).toEqual([]); + }); + + it('should have empty cities when no region is selected', () => { + spyOn(userAddressService, 'getDeliveryCountries').and.returnValue(of([])); + spyOn(userAddressService, 'getRegions').and.returnValue(of([])); + component.ngOnInit(); + expect(component.cities).toEqual([]); + }); + + it('should have empty districts when no city is selected', () => { + spyOn(userAddressService, 'getDeliveryCountries').and.returnValue(of([])); + spyOn(userAddressService, 'getRegions').and.returnValue(of([])); + component.ngOnInit(); + expect(component.districts).toEqual([]); + }); + it('should call verifyAddress', () => { spyOn(component, 'verifyAddress').and.callThrough(); const mockCountryIsocode = 'test country isocode'; diff --git a/feature-libs/user/profile/components/address-book/address-form/address-form.component.ts b/feature-libs/user/profile/components/address-book/address-form/address-form.component.ts index c5eadd3a32b..6ac6cad51f6 100644 --- a/feature-libs/user/profile/components/address-book/address-form/address-form.component.ts +++ b/feature-libs/user/profile/components/address-book/address-form/address-form.component.ts @@ -7,9 +7,11 @@ import { AsyncPipe, NgIf } from '@angular/common'; import { ChangeDetectionStrategy, + ChangeDetectorRef, Component, ElementRef, EventEmitter, + inject, Input, OnDestroy, OnInit, @@ -31,6 +33,7 @@ import { ErrorModel, GlobalMessageService, GlobalMessageType, + LanguageService, Region, Title, TranslatePipe, @@ -47,7 +50,13 @@ import { sortTitles, } from '@spartacus/storefront'; import { UserProfileFacade } from '@spartacus/user/profile/root'; -import { BehaviorSubject, Observable, Subscription, combineLatest } from 'rxjs'; +import { + BehaviorSubject, + Observable, + Subscription, + combineLatest, + of, +} from 'rxjs'; import { filter, map, switchMap, take, tap } from 'rxjs/operators'; @Component({ @@ -68,10 +77,19 @@ import { filter, map, switchMap, take, tap } from 'rxjs/operators'; ], }) export class AddressFormComponent implements OnInit, OnDestroy { + protected languageService = inject(LanguageService); + protected cdr = inject(ChangeDetectorRef); + protected userProfileFacade = inject(UserProfileFacade); + countries$: Observable; titles$: Observable; regions$: Observable; selectedCountry$: BehaviorSubject = new BehaviorSubject(''); + selectedRegion$: BehaviorSubject = new BehaviorSubject(''); + selectedCity$: BehaviorSubject = new BehaviorSubject(''); + isChineseAddress = false; + cities: { isocode?: string; name?: string }[] = []; + districts: { isocode?: string; name?: string }[] = []; addresses$: Observable; @Input() @@ -114,10 +132,11 @@ export class AddressFormComponent implements OnInit, OnDestroy { lastName: ['', Validators.required], line1: ['', Validators.required], line2: [''], - town: ['', Validators.required], + town: [null, Validators.required], region: this.fb.group({ isocode: [null, Validators.required], }), + district: [null], postalCode: ['', Validators.required], phone: '', cellphone: '', @@ -129,8 +148,7 @@ export class AddressFormComponent implements OnInit, OnDestroy { protected userAddressService: UserAddressService, protected globalMessageService: GlobalMessageService, protected translation: TranslationService, - protected launchDialogService: LaunchDialogService, - protected userProfileFacade: UserProfileFacade + protected launchDialogService: LaunchDialogService ) {} ngOnInit() { @@ -171,6 +189,57 @@ export class AddressFormComponent implements OnInit, OnDestroy { } this.addresses$ = this.userAddressService.getAddresses(); + + this.subscription.add( + combineLatest([this.selectedRegion$, this.languageService.getActive()]) + .pipe( + switchMap(([regionIsocode]) => { + if (!regionIsocode) { + return of([]); + } + return this.userAddressService.getCities(regionIsocode); + }) + ) + .subscribe((cities) => { + this.cities = cities; + if (this.addressData?.city?.isocode && !this.selectedCity$.value) { + this.selectedCity$.next(this.addressData.city.isocode); + this.addressForm + .get('town') + ?.setValue(this.addressData.city.isocode); + } + this.cdr.markForCheck(); + }) + ); + + this.subscription.add( + combineLatest([this.selectedCity$, this.languageService.getActive()]) + .pipe( + switchMap(([cityIsocode]) => { + if (!cityIsocode) { + return of([]); + } + return this.userAddressService.getDistricts(cityIsocode); + }) + ) + .subscribe((districts) => { + this.districts = districts; + if (this.addressData?.cityDistrict?.isocode) { + this.addressForm + .get('district') + ?.setValue(this.addressData.cityDistrict.isocode); + } + this.cdr.markForCheck(); + }) + ); + + this.subscription.add( + this.languageService.getActive().subscribe(() => { + if (this.isChineseAddress) { + this.cdr.markForCheck(); + } + }) + ); } getTitles(): Observable { @@ -214,12 +283,48 @@ export class AddressFormComponent implements OnInit, OnDestroy { countrySelected(country: Country | undefined): void { this.addressForm.get('country')?.get('isocode')?.setValue(country?.isocode); this.selectedCountry$.next(country?.isocode ?? ''); + this.isChineseAddress = country?.isocode === 'CN'; + + const cellphoneControl = this.addressForm.get('cellphone'); + const districtControl = this.addressForm.get('district'); + const townControl = this.addressForm.get('town'); + if (this.isChineseAddress) { + cellphoneControl?.setValidators([Validators.required]); + districtControl?.setValidators([Validators.required]); + townControl?.reset(); + districtControl?.reset(); + } else { + cellphoneControl?.clearValidators(); + districtControl?.clearValidators(); + districtControl?.reset(); + townControl?.enable(); + districtControl?.enable(); + this.selectedRegion$.next(''); + this.selectedCity$.next(''); + } + cellphoneControl?.updateValueAndValidity(); + districtControl?.updateValueAndValidity(); } regionSelected(region: Region): void { this.addressForm.get('region')?.get('isocode')?.setValue(region.isocode); + if (this.isChineseAddress) { + this.selectedRegion$.next(region.isocode ?? ''); + this.addressForm.get('town')?.reset(); + this.selectedCity$.next(''); + this.addressForm.get('district')?.reset(); + } } + citySelected(city: { isocode?: string; name?: string } | undefined): void { + if (city?.isocode) { + this.selectedCity$.next(city.isocode); + this.addressForm.get('district')?.reset(); + } + } + + protected updateChinesePlaceholders(): void {} + toggleDefaultAddress(): void { this.addressForm['controls'].defaultAddress.setValue( this.addressForm.value.defaultAddress @@ -251,13 +356,17 @@ export class AddressFormComponent implements OnInit, OnDestroy { } if (this.addressForm.dirty) { - this.subscription.add( - this.userAddressService - .verifyAddress(this.addressForm.value) - .subscribe((value) => { - this.handleAddressVerificationResults(value); - }) - ); + if (this.isChineseAddress) { + this.submitAddress.emit(this.addressForm.value); + } else { + this.subscription.add( + this.userAddressService + .verifyAddress(this.addressForm.value) + .subscribe((value) => { + this.handleAddressVerificationResults(value); + }) + ); + } } else { // address form value not changed // ignore duplicate address diff --git a/feature-libs/user/profile/root/model/user-profile.model.ts b/feature-libs/user/profile/root/model/user-profile.model.ts index 287115c406c..6e189be4caf 100644 --- a/feature-libs/user/profile/root/model/user-profile.model.ts +++ b/feature-libs/user/profile/root/model/user-profile.model.ts @@ -30,6 +30,16 @@ export interface Title { name?: string; } +export interface ChineseCity { + name?: string; + isocode?: string; +} + +export interface ChineseDistrict { + name?: string; + isocode?: string; +} + export interface UserSignUp { firstName?: string; lastName?: string; diff --git a/integration-libs/opf/checkout/components/opf-checkout-billing-address-form/opf-checkout-billing-address-form.component.spec.ts b/integration-libs/opf/checkout/components/opf-checkout-billing-address-form/opf-checkout-billing-address-form.component.spec.ts index dedeba545a2..f6edb7be1fa 100644 --- a/integration-libs/opf/checkout/components/opf-checkout-billing-address-form/opf-checkout-billing-address-form.component.spec.ts +++ b/integration-libs/opf/checkout/components/opf-checkout-billing-address-form/opf-checkout-billing-address-form.component.spec.ts @@ -13,6 +13,7 @@ import { BaseSiteService, Country, MockTranslatePipe, + SiteAdapter, TranslatePipe, UserAddressAdapter, } from '@spartacus/core'; @@ -73,6 +74,7 @@ describe('OpfCheckoutBillingAddressFormComponent', () => { }, { provide: Store, useValue: {} }, { provide: UserAddressAdapter, useValue: {} }, + { provide: SiteAdapter, useValue: {} }, { provide: CheckoutStepService, useValue: {} }, { provide: BaseSiteService, useValue: {} }, { provide: ActivatedRoute, useValue: { params: of({}) } }, diff --git a/projects/core/src/model/address.model.ts b/projects/core/src/model/address.model.ts index 693ab204bcc..c9bca07d6f9 100644 --- a/projects/core/src/model/address.model.ts +++ b/projects/core/src/model/address.model.ts @@ -38,8 +38,10 @@ export interface Address { line2?: string; postalCode?: string; town?: string; + city?: { isocode?: string; name?: string }; region?: Region; district?: string; + cityDistrict?: { isocode?: string; name?: string }; country?: Country; cellphone?: string; diff --git a/projects/core/src/occ/adapters/site-context/default-occ-site-context-config.ts b/projects/core/src/occ/adapters/site-context/default-occ-site-context-config.ts index b307b0021fd..003c835a3d8 100644 --- a/projects/core/src/occ/adapters/site-context/default-occ-site-context-config.ts +++ b/projects/core/src/occ/adapters/site-context/default-occ-site-context-config.ts @@ -15,6 +15,8 @@ export const defaultOccSiteContextConfig: OccConfig = { countries: 'countries', regions: 'countries/${isoCode}/regions?fields=regions(name,isocode,isocodeShort)', + chineseAddressCities: 'regions/${regionId}/cities', + chineseAddressDistricts: 'cities/${cityId}/districts', baseSites: 'basesites?fields=FULL', }, }, diff --git a/projects/core/src/occ/adapters/site-context/occ-site.adapter.ts b/projects/core/src/occ/adapters/site-context/occ-site.adapter.ts index 2cf18adcf66..556f85401c8 100644 --- a/projects/core/src/occ/adapters/site-context/occ-site.adapter.ts +++ b/projects/core/src/occ/adapters/site-context/occ-site.adapter.ts @@ -110,4 +110,30 @@ export class OccSiteAdapter implements SiteAdapter { this.converterService.pipeableMany(BASE_SITE_NORMALIZER) ); } + + loadCities( + regionIsocode: string + ): Observable<{ isocode?: string; name?: string }[]> { + const url = this.occEndpointsService.buildUrl('chineseAddressCities', { + urlParams: { regionId: regionIsocode }, + }); + return this.http + .get<{ cities: { isocode?: string; name?: string }[] }>(url, { + params: { fields: 'cities(name,isocode)' }, + }) + .pipe(map((res) => res.cities ?? [])); + } + + loadDistricts( + cityIsocode: string + ): Observable<{ isocode?: string; name?: string }[]> { + const url = this.occEndpointsService.buildUrl('chineseAddressDistricts', { + urlParams: { cityId: cityIsocode }, + }); + return this.http + .get<{ districts: { isocode?: string; name?: string }[] }>(url, { + params: { fields: 'districts(name,isocode)' }, + }) + .pipe(map((res) => res.districts ?? [])); + } } diff --git a/projects/core/src/occ/adapters/user/occ-user-address.adapter.ts b/projects/core/src/occ/adapters/user/occ-user-address.adapter.ts index bd067359882..908f401b83a 100644 --- a/projects/core/src/occ/adapters/user/occ-user-address.adapter.ts +++ b/projects/core/src/occ/adapters/user/occ-user-address.adapter.ts @@ -46,13 +46,18 @@ export class OccUserAddressAdapter implements UserAddressAdapter { ...CONTENT_TYPE_JSON_HEADER, }); - return this.http.get(url, { headers }).pipe( - catchError((error: any) => { - throw tryNormalizeHttpError(error, this.logger); - }), - map((addressList) => addressList.addresses ?? []), - this.converter.pipeableMany(ADDRESS_NORMALIZER) - ); + return this.http + .get(url, { + headers, + params: { fields: 'addresses(FULL)' }, + }) + .pipe( + catchError((error: any) => { + throw tryNormalizeHttpError(error, this.logger); + }), + map((addressList) => addressList.addresses ?? []), + this.converter.pipeableMany(ADDRESS_NORMALIZER) + ); } add(userId: string, address: Address): Observable<{}> { diff --git a/projects/core/src/occ/occ-models/occ-endpoints.model.ts b/projects/core/src/occ/occ-models/occ-endpoints.model.ts index 5f744a4fc5c..6ead02c43a2 100644 --- a/projects/core/src/occ/occ-models/occ-endpoints.model.ts +++ b/projects/core/src/occ/occ-models/occ-endpoints.model.ts @@ -97,6 +97,14 @@ export interface OccEndpoints { * @member {string} */ regions?: string | OccEndpoint; + /** + * Fetch cities for a Chinese address region + */ + chineseAddressCities?: string | OccEndpoint; + /** + * Fetch districts for a Chinese address city + */ + chineseAddressDistricts?: string | OccEndpoint; /** * Payment details root endpoint. * diff --git a/projects/core/src/site-context/connectors/site.adapter.ts b/projects/core/src/site-context/connectors/site.adapter.ts index 4dad32880e5..3878187f608 100644 --- a/projects/core/src/site-context/connectors/site.adapter.ts +++ b/projects/core/src/site-context/connectors/site.adapter.ts @@ -38,4 +38,18 @@ export abstract class SiteAdapter { * Abstract method used to get all base sites data. */ abstract loadBaseSites(): Observable; + + /** + * Abstract method used to get cities for a region. + */ + abstract loadCities( + regionIsocode: string + ): Observable<{ isocode?: string; name?: string }[]>; + + /** + * Abstract method used to get districts for a city. + */ + abstract loadDistricts( + cityIsocode: string + ): Observable<{ isocode?: string; name?: string }[]>; } diff --git a/projects/core/src/site-context/connectors/site.connector.spec.ts b/projects/core/src/site-context/connectors/site.connector.spec.ts index e8a5bbee336..8efb8c063a8 100644 --- a/projects/core/src/site-context/connectors/site.connector.spec.ts +++ b/projects/core/src/site-context/connectors/site.connector.spec.ts @@ -24,7 +24,7 @@ class MockSiteAdapter implements SiteAdapter { ); loadRegions = createSpy('SiteAdapter.loadRegions').and.callFake( - (countryCode) => of(`loadRegions-${countryCode}`) + (countryCode: string) => of(`loadRegions-${countryCode}`) ); loadBaseSite = createSpy('SiteAdapter.loadBaseSite').and.callFake(() => @@ -34,6 +34,12 @@ class MockSiteAdapter implements SiteAdapter { loadBaseSites = createSpy('SiteAdapter.loadBaseSites').and.callFake(() => of(mockBaseSites) ); + + loadCities = createSpy('SiteAdapter.loadCities').and.returnValue(of([])); + + loadDistricts = createSpy('SiteAdapter.loadDistricts').and.returnValue( + of([]) + ); } describe('SiteConnector', () => { diff --git a/projects/core/src/site-context/connectors/site.connector.ts b/projects/core/src/site-context/connectors/site.connector.ts index 27d1a66c447..055127c4582 100644 --- a/projects/core/src/site-context/connectors/site.connector.ts +++ b/projects/core/src/site-context/connectors/site.connector.ts @@ -32,6 +32,18 @@ export class SiteConnector { return this.adapter.loadRegions(countryIsoCode); } + getCities( + regionIsocode: string + ): Observable<{ isocode?: string; name?: string }[]> { + return this.adapter.loadCities(regionIsocode); + } + + getDistricts( + cityIsocode: string + ): Observable<{ isocode?: string; name?: string }[]> { + return this.adapter.loadDistricts(cityIsocode); + } + getBaseSite(siteUid?: string): Observable { return this.adapter.loadBaseSite(siteUid); } diff --git a/projects/core/src/user/facade/user-address.service.spec.ts b/projects/core/src/user/facade/user-address.service.spec.ts index 223e32e9c47..a28cdcd7aeb 100644 --- a/projects/core/src/user/facade/user-address.service.spec.ts +++ b/projects/core/src/user/facade/user-address.service.spec.ts @@ -12,6 +12,7 @@ import { import { OCC_USER_ID_CURRENT } from '../../occ/utils/occ-constants'; import { PROCESS_FEATURE } from '../../process/store/process-state'; import * as fromProcessReducers from '../../process/store/reducers'; +import { SiteAdapter } from '../../site-context/connectors/site.adapter'; import { UserAddressConnector } from '../connectors/address/user-address.connector'; import { UserActions } from '../store/actions/index'; import * as fromStoreReducers from '../store/reducers/index'; @@ -67,6 +68,7 @@ describe('UserAddressService', () => { UserAddressService, { provide: UserIdService, useClass: MockUserIdService }, { provide: UserAddressConnector, useClass: MockUserAddressConnector }, + { provide: SiteAdapter, useValue: {} }, ], }); diff --git a/projects/core/src/user/facade/user-address.service.ts b/projects/core/src/user/facade/user-address.service.ts index fbe5b31a294..d90b60f4eea 100644 --- a/projects/core/src/user/facade/user-address.service.ts +++ b/projects/core/src/user/facade/user-address.service.ts @@ -19,6 +19,7 @@ import { Command, CommandService, } from '../../util/command-query/command.service'; +import { SiteConnector } from '../../site-context/connectors/site.connector'; import { UserAddressConnector } from '../connectors/address/user-address.connector'; import { UserActions } from '../store/actions/index'; import { UsersSelectors } from '../store/selectors/index'; @@ -32,7 +33,8 @@ export class UserAddressService { protected store: Store, protected userIdService: UserIdService, protected userAddressConnector: UserAddressConnector, - protected command: CommandService + protected command: CommandService, + protected siteConnector: SiteConnector ) {} /** @@ -197,6 +199,19 @@ export class UserAddressService { }) ); } + + getCities( + regionIsocode: string + ): Observable<{ isocode?: string; name?: string }[]> { + return this.siteConnector.getCities(regionIsocode); + } + + getDistricts( + cityIsocode: string + ): Observable<{ isocode?: string; name?: string }[]> { + return this.siteConnector.getDistricts(cityIsocode); + } + /** * Verifies the address * @param address : the address to be verified