@salla.sa/twilight-components
Version:
Salla Web Component
276 lines (275 loc) • 10.9 kB
TypeScript
import { type EventEmitter } from "../../stencil-public-runtime";
import type { AddressCreatedEvent, Branch, BulletDeliveryConfirmedEvent, City, Country, District, HeaderContextUpdateEvent, IntentType, NewAddressFormData, Region, SavedAddress } from "./interfaces";
type ViewMode = "main" | "add-address";
/**
* @slot footer - The bottom section of the component for custom actions.
*/
export declare class SallaBulletDelivery {
private modal;
private confirmBtn;
private confirming;
private pendingCartSubmitResolver;
private pendingCartSubmitPromise;
private cartSubmitConfirmationPending;
private branchSearchDebounceTimer;
private countrySearchTimer;
private regionSearchTimer;
private citySearchTimer;
private districtSearchTimer;
private citySearchCounter;
private preselectedAddressId?;
private preselectedBranchId?;
private componentReady;
private pendingOpen;
private tabChanging;
private readonly intentStorageKey;
private readonly sessionShownKey;
private readonly incompleteIntentPromptKey;
private readonly cartItemAddedEvent;
private cartItemAddedHandler;
private cartSubmittingHandler;
private useCartEventApi;
private authLoggedInHandler;
private authLoggedOutHandler;
private loginClosedHandler;
private hasExplicitPreselectedIdsForOpen;
private bulletDeliveryOpenHandler;
private closeHandler;
private bulletDeliveryMobileSelectHandler;
/** True after saved addresses have been loaded (lazy: only when address tab is shown). */
private savedAddressesLoaded;
private isRTL;
activeTab: IntentType;
isLoggedIn: boolean;
viewMode: ViewMode;
countries: Country[];
regions: Region[];
cities: City[];
districts: District[];
loadingRegions: boolean;
selectedCountry: Country | null;
selectedRegion: Region | null;
selectedCity: City | null;
selectedDistrict: District | null;
districtName: string;
savedAddresses: SavedAddress[];
selectedSavedAddress: SavedAddress | null;
/** True when user selected the session address (guest address from before login, not yet saved) */
selectedSessionAddress: boolean;
branches: Branch[];
filteredBranches: Branch[];
selectedBranch: Branch | null;
branchSearchQuery: string;
loadingCountries: boolean;
loadingCities: boolean;
loadingDistricts: boolean;
loadingBranches: boolean;
loadingNearestBranch: boolean;
locationError: string;
savingAddress: boolean;
loadingSavedAddresses: boolean;
showCartWillBeClearedBanner: boolean;
countrySearchQuery: string;
regionSearchQuery: string;
citySearchQuery: string;
districtSearchQuery: string;
searchingCountries: boolean;
searchingRegions: boolean;
searchingCities: boolean;
searchingDistricts: boolean;
displayedCountries: Country[];
displayedRegions: Region[];
displayedCities: City[];
displayedDistricts: District[];
/** Shown when scopes/allocation returns 422 (address outside delivery coverage). Only on delivery tab. */
allocationOutOfCoverageMessage: string | null;
/**
* SA add-address view: 'confirmed' = selected address box + description + confirm, 'full' = all form fields (after Edit).
*/
private static readonly INITIAL_ADDRESS_FORM;
newAddressForm: NewAddressFormData;
/** Whether to show delivery + pickup tabs. From store.shipping.support_pickup */
private get supportsPickup();
/** The modal opening strategy: 'first_visit' | 'on_cart_click' | 'after_add_to_cart' */
private get openingType();
/** Whether the modal is required (cannot be closed/skipped). From store.settings.bullet_delivery.settings.is_required */
private get isRequired();
private get isMobileApp();
/**
* Emitted when the user confirms their selection
*/
bulletDeliveryConfirmed: EventEmitter<BulletDeliveryConfirmedEvent>;
/**
* Emitted when the modal is closed
*/
bulletDeliveryClosed: EventEmitter<void>;
/**
* Emitted when a new address is created
*/
addressCreated: EventEmitter<AddressCreatedEvent>;
/**
* Emitted to sync with the global header (Delivering to: [location])
*/
headerContextUpdate: EventEmitter<HeaderContextUpdateEvent>;
/**
* Opens the bullet delivery modal
*/
open(): Promise<void>;
/**
* Closes the bullet delivery modal
*/
close(): Promise<HTMLElement>;
private resetState;
private getIntentStorage;
private getShownStorage;
private getStoredIntent;
private isGuestUser;
private cleanStaleGuestAddressIdIfNeeded;
private applyPreselectedIdsFromIntent;
private hasIncompleteUserAddressIntent;
private hasCompleteIntentForLoggedInUser;
/**
* Authenticated users on the cart page must select/confirm an address before
* they can dismiss the modal.
*/
private shouldForceNonClosable;
private shouldPromptIncompleteIntentThisSession;
private markIncompleteIntentPrompted;
private setStoredIntent;
private clearBulletDeliveryStoredData;
/**
* Single prefill flow: load geography from stored intent and set selected location + form.
* Assumes this.countries is already loaded. No-op if no intent or no city in intent.
*/
private prefillAddressFromStoredIntent;
private updateNewAddressForm;
/** Whether allocation completed successfully this session (modal won't auto-open again). */
private hasBeenShownThisSession;
/** Mark allocation as completed this session (called only after allocateScope succeeds). */
private markShownThisSession;
private getIPLocationConfig;
private loadCountries;
private prefillFromIPLocation;
private loadCities;
private loadDistricts;
private findPrefillDistrict;
private loadBranches;
private filterBranches;
/**
* Prefill form fields from session storage
*/
private prefillFromSessionStorage;
private loadSavedAddresses;
private applyCountryChange;
private loadRegions;
private emitHeaderContextUpdate;
private handleBranchSearch;
private static readonly DROPDOWN_SEARCH_DEBOUNCE_MS;
private static readonly DROPDOWN_SEARCH_MIN_CHARS;
private handleCountrySearch;
private handleRegionSearch;
private handleCitySearch;
private handleDistrictSearch;
private clearSearchTimers;
private resetSearchState;
private handleCountryDropdownClosed;
private handleRegionDropdownClosed;
private handleCityDropdownClosed;
private handleDistrictDropdownClosed;
private loadBranchesWithLocation;
/** Locate nearest branch using device geolocation (branches tab only). */
private handleFindNearestBranch;
private handleBranchSelect;
private handleSavedAddressSelect;
private handleSessionAddressSelect;
/** Show delete confirmation UI for this address (do not call API yet). */
/**
* Switch to add-address form (unified form). Preselects country from session when present.
*/
private handleAddNewAddress;
private handleBackToAddressList;
/**
* Build address/location payload from guest-form state (same fields as add-address).
*/
private buildAddressLocationPayload;
/**
* Submit add-address form: create address via API then switch back to list.
*/
private handleSubmitAddAddress;
private handleTabChange;
private isConfirmDisabled;
private handleLogin;
private resolvePendingCartSubmit;
private buildIntentAddress;
private buildIntentAddressFromSaved;
private buildIntentBranch;
private buildAllocationConfirmedAddressData;
/**
* Build a minimal `BulletDeliveryAllocationConfirmedAddressData` from a mobile
* payload (no full SavedAddress object available). Only used for the
* `salla::bullet-delivery.allocation.confirmed` event so existing listeners
* keep working with the same shape they get on desktop.
*/
private buildAllocationConfirmedAddressFromIntent;
/** Synthesise a minimal `Branch` from a mobile branch intent. */
private buildBranchFromIntent;
/** Reconstruct the equivalent `ScopeAllocationPayload` from a mobile result. */
private buildAllocationRequestFromIntent;
/**
* Apply a selection performed inside the mobile app's native sheet.
*
* Mirrors the post-allocation side-effects of `handleConfirm()` so the
* webview ends up in the exact same state as if the user had confirmed via
* our component on desktop:
* 1. Sets `s-scope-allocation-*` headers for subsequent API calls.
* 2. Persists allocation in `Salla.storage.scope` (single source of truth).
* 3. Marks the modal as shown for this session and stores the intent so
* delivery-promise / scope-switch UIs reflect the selection.
* 4. Clears the API cache so cached data from the previous scope is gone.
* 5. Dispatches `salla::bullet-delivery.allocation.confirmed`,
* `bulletDeliveryConfirmed`, and the header-context update event so
* every listener (header pill, cart view, etc.) syncs.
* 6. Reloads the page so prices, availability, and cart reflect the
* newly-selected scope (matches desktop behaviour).
*/
private applyMobileBulletDeliverySelection;
private extractMobileSelectPayload;
private handleConfirm;
private getCartViewConfig;
/** Creates the cart view DOM for mounting into cart.items.start hook */
private createCartViewElement;
private renderTabs;
private renderAlert;
private renderAllocationOutOfCoverageAlert;
private handleCountrySelected;
private renderCountrySelect;
private handleRegionSelected;
/** Region select (SA only): shown when SA is selected; city and district disabled until region selected. */
private renderRegionSelect;
private handleCitySelected;
private handleDistrictSelected;
private renderCityDistrictSelects;
private renderSavedAddressesEmptyState;
/**
* Save session address (guest intent) to user profile. Returns the newly saved address or null.
*/
private saveSessionAddressToProfile;
private renderSavedAddresses;
private renderAddressRow;
private renderGuestDeliveryForm;
private renderDeliveryTab;
private renderBranchSearch;
private renderBranchList;
private renderPickupTab;
/** Add-address form: same fields as guest form (country, region, city, district) only. */
private renderAddAddressForm;
private renderFooter;
private renderMainView;
private handleAfterAddToCart;
private overrideScopeSwitchUI;
componentWillLoad(): Promise<void>;
render(): any;
componentDidLoad(): void;
disconnectedCallback(): void;
}
export {};