diff --git a/docs/composition/composables.md b/docs/composition/composables.md index 7261c0cc1..30534c52f 100644 --- a/docs/composition/composables.md +++ b/docs/composition/composables.md @@ -22,7 +22,7 @@ To make composables easily distinguishable from standard methods, we follow the ### What does it look like in practice? -Let's take a closer look at how it might look like using the [useUser](/api-reference/magento-theme.useuserinterface.html) composable as an example: +Let's take a closer look at how it might look like using the [useUser](https://github.com/vuestorefront/magento2/blob/main/packages/theme/modules/customer/composables/useUser/index.ts) composable as an example: diff --git a/docs/composition/list-of-composables.md b/docs/composition/list-of-composables.md index a170371ea..d1f5ee71f 100644 --- a/docs/composition/list-of-composables.md +++ b/docs/composition/list-of-composables.md @@ -4,208 +4,208 @@ Allows loading and manipulating addresses of the current user. These addresses can be used for both billing and shipping. -See the [UseAddressesInterface](/api-reference/magento-theme.useaddressesinterface.html) for more information. +See the [UseAddressesInterface](https://github.com/vuestorefront/magento2/blob/main/packages/theme/modules/customer/composables/useAddresses/useAddresses.ts#L9) for more information. ## `useApi` Allows executing arbitrary GraphQL queries and mutations. -See the [UseApiInterface](/api-reference/magento-theme.useapiinterface.html) for more information. +See the [UseApiInterface](https://github.com/vuestorefront/magento2/blob/main/packages/theme/composables/useApi/index.ts#L29) for more information. ## `useBilling` Allows loading and saving billing information of the current cart. -See the [UseBillingInterface](/api-reference/magento-theme.usebillinginterface.html) for more information. +See the [UseBillingInterface](https://github.com/vuestorefront/magento2/blob/main/packages/theme/modules/checkout/composables/useBilling/useBilling.ts#L54) for more information. ## `useCart` Allows loading and manipulating cart of the current user. -See the [UseCartInterface](/api-reference/magento-theme.usecartinterface.html) for more information. +See the [UseCartInterface](https://github.com/vuestorefront/magento2/blob/main/packages/theme/modules/checkout/composables/useCart/useCart.ts#L46) for more information. ## `useCategory` Allows loading categories from Magento API. It is commonly used in navigation menus, and provides the load function and refs for the categories, loading and error. -See the [UseCategoryInterface](/api-reference/magento-theme.usecategoryinterface.html) for more information. +See the [UseCategoryInterface](https://github.com/vuestorefront/magento2/blob/main/packages/theme/modules/catalog/category/composables/useCategory/useCategory.ts#L53) for more information. ## `useCategorySearch` Allows searching for categories. It is commonly used in subtrees navigation. -See the [UseCategorySearchInterface](/api-reference/magento-theme.usecategorysearchinterface.html) for more information. +See the [UseCategorySearchInterface](https://github.com/vuestorefront/magento2/blob/main/packages/theme/modules/catalog/category/composables/useCategorySearch/useCategorySearch.ts#L23) for more information. ## `useConfig` Allows interacting with the store configuration. -See the [UseConfigInterface](/api-reference/magento-theme.useconfiginterface.html) for more information. +See the [UseConfigInterface](https://github.com/vuestorefront/magento2/blob/main/packages/theme/composables/useConfig/useConfig.ts#L23) for more information. ## `useContent` Allows loading CMS Pages or Blocks from Magento API. -See the [UseContentInterface](/api-reference/magento-theme.usecontentinterface.html) for more information. +See the [UseContentInterface](https://github.com/vuestorefront/magento2/blob/main/packages/theme/composables/useConfig/useConfig.ts#L23) for more information. ## `useCountrySearch` Allows fetching a list of countries or a single country by ID -See the [UseCountrySearchInterface](/api-reference/magento-theme.usecountrysearchinterface.html) for more information. +See the [UseCountrySearchInterface](https://github.com/vuestorefront/magento2/blob/main/packages/theme/composables/useCountrySearch/useCountrySearch.ts#L30) for more information. ## `useCurrency` Allows loading and changing the currency. -See the [UseCurrencyInterface](/api-reference/magento-theme.usecurrencyinterface.html) for more information. +See the [UseCurrencyInterface](https://github.com/vuestorefront/magento2/blob/main/packages/theme/composables/useCountrySearch/useCountrySearch.ts#L30) for more information. ## `useExternalCheckout` (Work in progress) Allows redirecting to external checkout process. It depends on the [magento2-external-checkout repository](https://github.com/Vendic/magento2-external-checkout). -See the [UseExternalCheckoutInterface](/api-reference/magento-theme.useexternalcheckoutinterface.html) for more information. +See the [UseExternalCheckoutInterface](https://github.com/vuestorefront/magento2/blob/main/packages/theme/composables/useExternalCheckout/useExternalCheckout.ts#L12) for more information. ## `useFacet` Allows searching for products with pagination, totals and sorting options. -See the [UseFacetInterface](/api-reference/magento-theme.usefacetinterface.html) for more information. +See the [UseFacetInterface](https://github.com/vuestorefront/magento2/blob/main/packages/theme/modules/catalog/category/composables/useFacet/useFacet.ts#L58) for more information. ## `useForgotPassword` Allows to request a password reset email and to set a new password to a user. -Se the [UseForgotPasswordInterface](/api-reference/magento-theme.useforgotpasswordinterface.html) for more information. +Se the [UseForgotPasswordInterface](https://github.com/vuestorefront/magento2/blob/main/packages/theme/modules/customer/composables/useForgotPassword/useForgotPassword.ts#L33) for more information. ## `useGetShippingMethods` Allows fetching shipping methods available for a given cart. -See the [UseGetShippingMethodsInterface](/api-reference/magento-theme.usegetshippingmethodsinterface.html) for more information. +See the [UseGetShippingMethodsInterface](https://github.com/vuestorefront/magento2/blob/main/packages/theme/modules/checkout/composables/useGetShippingMethods/useGetShippingMethods.ts#L14) for more information. ## `useGuestUser` Allows to attach a guest cart to a user. -See the [UseGuestUserInterface](/api-reference/magento-theme.useguestuserinterface.html) for more information. +See the [UseGuestUserInterface](https://github.com/vuestorefront/magento2/blob/main/packages/theme/modules/customer/composables/useGuestUser/useGuestUser.ts#L20) for more information. ## `useImage` Allows extracting image paths from magento URL. -See the [UseImageInterface](/api-reference/magento-theme.useimageinterface.html) for more information. +See the [UseImageInterface](https://github.com/vuestorefront/magento2/blob/main/packages/theme/composables/useImage/useImage.ts#L29) for more information. ## `useMagentoConfiguration` Allows getting the Magento's major definitions, e.g., the selected currency, store, locale, and config object. -See the [UseMagentoConfigurationInterface](/api-reference/magento-theme.usemagentoconfigurationinterface.html) for more information. +See the [UseMagentoConfigurationInterface](https://github.com/vuestorefront/magento2/blob/main/packages/theme/composables/useMagentoConfiguration/UseMagentoConfiguration.ts#L7) for more information. ## `useMakeOrder` Allows making an order from a cart. -See the [UseMakeOrderInterface](/api-reference/magento-theme.usemakeorderinterface.html) for more information. +See the [UseMakeOrderInterface](https://github.com/vuestorefront/magento2/blob/main/packages/theme/modules/checkout/composables/useMakeOrder/useMakeOrder.ts#L17) for more information. ## `useNewsletter` Allows updating the subscription status of an email in the newsletter. -See the [UseNewsletterInterface](/api-reference/magento-theme.usenewsletterinterface.html) for more information. +See the [UseNewsletterInterface](https://github.com/vuestorefront/magento2/blob/main/packages/theme/composables/useNewsletter/useNewsletter.ts#L25) for more information. ## `usePaymentProvider` Allows loading the available payment methods for current cart, and selecting (saving) one of them. -See the [UsePaymentProviderInterface](/api-reference/magento-theme.usepaymentproviderinterface.html) for more information. +See the [UsePaymentProviderInterface](https://github.com/vuestorefront/magento2/blob/main/packages/theme/modules/checkout/composables/usePaymentProvider/usePaymentProvider.ts#L31) for more information. ## `useProduct` Allows loading product details or list with params for sorting, filtering and pagination. -See the [UseProductInterface](/api-reference/magento-theme.useproductinterface.html) for more information. +See the [UseProductInterface](https://github.com/vuestorefront/magento2/blob/main/packages/theme/modules/catalog/product/composables/useProduct/useProduct.ts#L25) for more information. ## `useRelatedProducts` Allows searching for related products with params for sort, filter and pagination. -See the [UseRelatedProductsInterface](/api-reference/magento-theme.userelatedproductsinterface.html) for more information. +See the [UseRelatedProductsInterface](https://github.com/vuestorefront/magento2/blob/main/packages/theme/modules/catalog/product/composables/useRelatedProducts/useRelatedProducts.ts#L23) for more information. ## `useReview` Allows loading and adding product reviews. -See the [UseReviewInterface](/api-reference/magento-theme.usereviewinterface.html) for more information. +See the [UseReviewInterface](https://github.com/vuestorefront/magento2/blob/main/packages/theme/modules/review/composables/useReview/useReview.ts#L50) for more information. ## `useShipping` Allows loading the shipping information for the current cart and saving (selecting) other shipping information for the same cart. -See the [UseShippingInterface](/api-reference/magento-theme.useshippinginterface.html) for more information. +See the [UseShippingInterface](https://github.com/vuestorefront/magento2/blob/main/packages/theme/modules/checkout/composables/useShipping/useShipping.ts#L28) for more information. ## `useShippingProvider` Allows loading the shipping provider for the current cart and saving (selecting) other shipping provider for the same cart. -See the [UseShippingProviderInterface](/api-reference/magento-theme.useshippingproviderinterface.html) for more information. +See the [UseShippingProviderInterface](https://github.com/vuestorefront/magento2/blob/main/packages/theme/modules/checkout/composables/useShippingProvider/useShippingProvider.ts#L35) for more information. ## `useStore` Allows loading and changing currently active store. -See the [UseStoreInterface](/api-reference/magento-theme.usestoreinterface.html) for more information. +See the [UseStoreInterface](https://github.com/vuestorefront/magento2/blob/main/packages/theme/composables/useStore/useStore.ts#L23) for more information. ## `useUiHelpers` Allows handling the parameters for filtering, searching, sorting and pagination in the URL search/query params. -See the [UseUiHelpersInterface](/api-reference/magento-theme.useuihelpersinterface.html) for more information. +See the [UseUiHelpersInterface](https://github.com/vuestorefront/magento2/blob/main/packages/theme/composables/useUiHelpers/useUiHelpers.ts#L8) for more information. ## `useUiNotification` Allows managing and showing notifications to the user. -See the [UseUiNotificationInterface](/api-reference/magento-theme.useuinotificationinterface.html) for more information. +See the [UseUiNotificationInterface](https://github.com/vuestorefront/magento2/blob/main/packages/theme/composables/useUiNotification/useUiNotification.ts#L22) for more information. ## `useUiState` Global store for managing UI state. -See the [UseUiStateInterface](/api-reference/magento-theme.useuistateinterface.html) for more information. +See the [UseUiStateInterface](https://github.com/vuestorefront/magento2/blob/main/packages/theme/composables/useUiState/useUiState.ts#L17) for more information. ## `useUpsellProducts` Allows loading upsell products. -See the [UseUpsellProductsInterface](/api-reference/magento-theme.useupsellproductsinterface.html) for more information. +See the [UseUpsellProductsInterface](https://github.com/vuestorefront/magento2/blob/main/packages/theme/modules/catalog/product/composables/useUpsellProducts/useUpsellProducts.ts#L23) for more information. ## `useUrlResolver` Allows searching the resolver for current route path (URL). -See the [UseUrlResolverInterface](/api-reference/magento-theme.useurlresolverinterface.html) for more information. +See the [UseUrlResolverInterface](https://github.com/vuestorefront/magento2/blob/main/packages/theme/composables/useUrlResolver/UseUrlResolver.ts#L22) for more information. ## `useUser` Allows loading and manipulating data of the current user. -See the [UseUserInterface](/api-reference/magento-theme.useuserinterface.html) for more information. +See the [UseUserInterface](https://github.com/vuestorefront/magento2/blob/main/packages/theme/modules/customer/composables/useUser/useUser.ts#L61) for more information. ## `useUserAddress` Allows loading and manipulating addresses of the current user. -See the [UseUserAddressInterface](/api-reference/magento-theme.useuseraddressinterface.html) for more information. +See the [UseUserAddressInterface](https://github.com/vuestorefront/magento2/blob/main/packages/theme/modules/customer/composables/useUserAddress/useUserAddress.ts#L61) for more information. ## `useUserOrder` Allows fetching customer orders. -See the [UseUserOrderInterface](/api-reference/magento-theme.useuserorderinterface.html) for more information. +See the [UseUserOrderInterface](https://github.com/vuestorefront/magento2/blob/main/packages/theme/modules/customer/composables/useUserOrder/useUserOrder.ts#L24) for more information. ## `useWishlist` Allows loading and manipulating wishlist of the current user. -See the [UseWishlistInterface](/api-reference/magento-theme.usewishlistinterface.html) for more information. +See the [UseWishlistInterface](https://github.com/vuestorefront/magento2/blob/main/packages/theme/modules/wishlist/composables/useWishlist/useWishlist.ts#L74) for more information. diff --git a/docs/composition/useAddresses.md b/docs/composition/useAddresses.md new file mode 100644 index 000000000..35e7e1acc --- /dev/null +++ b/docs/composition/useAddresses.md @@ -0,0 +1,214 @@ +# useAddresses composable + +`useAddresses` composable allows loading and manipulating addresses of the current user. These addresses can be used for both billing and shipping. + +This composable can be found in the `modules` folder. + +## API +`useAddresses` composable returns the following properties: + +- `load` - function that loads addresses of the current customer +- `save` - function that saves a new address in the profile of the current customer +- `update` - function that updates an existing address in the profile of the current customer +- `remove` - function that removes an existing address from the profile of the current customer +- `error` - ref that contains an errors from the composable methods +- `loading` - ref that contains information whether any of the composable methods is loading + +## Interfaces + +```ts +/** + * Almost every method is extending this type + */ +type ComposableFunctionArgs = T & { + customQuery?: CustomQuery; + customHeaders?: CustomHeaders; +}; + +interface CustomerAddress { + /** The city or town */ + city?: Maybe; + /** The customer's company */ + company?: Maybe; + /** The customer's country */ + country_code?: Maybe; + /** + The customer's country + @deprecated Use `country_code` instead. + */ + country_id?: Maybe; + /** @deprecated Custom attributes should not be put into container */ + custom_attributes?: Maybe>>; + /** + The customer ID + @deprecated customer_id is not needed as part of CustomerAddress, address ID (id) is unique identifier for the addresses. + */ + customer_id?: Maybe; + /** Indicates whether the address is the default billing address */ + default_billing?: Maybe; + /** Indicates whether the address is the default shipping address */ + default_shipping?: Maybe; + /** Address extension attributes */ + extension_attributes?: Maybe>>; + /** The fax number */ + fax?: Maybe; + /** The first name of the person associated with the shipping/billing address */ + firstname?: Maybe; + /** The ID assigned to the address object */ + id?: Maybe; + /** The family name of the person associated with the shipping/billing address */ + lastname?: Maybe; + /** The middle name of the person associated with the shipping/billing address */ + middlename?: Maybe; + /** The customer's ZIP or postal code */ + postcode?: Maybe; + /** An honorific, such as Dr., Mr., or Mrs. */ + prefix?: Maybe; + /** An object containing the region name, region code, and region ID */ + region?: Maybe; + /** The unique ID for a pre-defined region */ + region_id?: Maybe; + /** An array of strings that define the street number and name */ + street?: Maybe>>; + /** A value such as Sr., Jr., or III */ + suffix?: Maybe; + /** The telephone number */ + telephone?: Maybe; + /** The customer's Value-added tax (VAT) number (for corporate customers) */ + vat_id?: Maybe; +} + +interface UseAddressesParamsInput { + address: CustomerAddress; +} + +interface UseAddressesInterface { + error: Ref; + loading: Ref; + load(customQuery?: CustomQuery, customHeaders?: CustomHeaders): Promise; + save(params: ComposableFunctionArgs): Promise; + update(params: ComposableFunctionArgs): Promise; + remove(params: ComposableFunctionArgs): Promise; +} +``` +## Examples + +### Loading addresses + +Loading customer addresses on client side using the `onMounted` Composition API hook: + +```typescript +import { onMounted, ref } from '@nuxtjs/composition-api'; +import { useAddresses } from '~/composables'; + +export function { + setup() { + const { load } = useAddresses(); + const addresses = ref([]); + + onMounted(async () => { + addresses.value = await load(); + }); + } +} + ``` + +### Saving an address + +Save a new customer address using an event handler/function: + +```typescript +import { ref, useFetch } from '@nuxtjs/composition-api'; +import { useAddresses, UseAddressesParamsInput } from '~/composables'; + +export default { + setup(props) { + const { error, load } = useAddresses(); + const addresses = ref([]); + + useFetch(async () => { + addresses.value = await load(); + }); + + const onSaveAddress = async (input: UseAddressesParamsInput) => { + const newAddress = await save(input); + + if (error.value.save) { + // handle saving error + } + + addresses.value.push(newAddress); + }; + } +} +``` + +### Updating an address + +Update a customer address using an event handler/function: + +```typescript +import { ref, useFetch } from '@nuxtjs/composition-api'; +import { useAddresses, UseAddressesParamsInput } from '~/composables'; + +export default { + setup(props) { + const { error, load, update } = useAddresses(); + const addresses = ref([]); + + useFetch(async () => { + addresses.value = await load(); + }); + + const onUpdateAddress = async (input: UseAddressesParamsInput) => { + const updatedAddress = await update(input); + + if (error.value.update) { + // handle updating error + } + + addresses.value = addresses.value.map((address) => { + if (address.id === updatedAddress.id) { + return updatedAddress; + } + + return address; + }); + }; + } +} +``` + +### Removing an address + +Remove a customer address using event handler/function: + +```typescript +import { ref, useFetch } from '@nuxtjs/composition-api'; +import { useAddresses, UseAddressesParamsInput } from '~/composables'; + +export default { + setup(props) { + const { error, load, remove } = useAddresses(); + const addresses = ref([]); + + useFetch(async () => { + addresses.value = await load(); + }); + + const onRemoveAddress = async (input: UseAddressesParamsInput) => { + const wasRemoved = await remove(input); + + if (error.value.remove || !wasRemoved) { + // handle removing error + } + + addresses.value = addresses.value.filter((address) => { + return address.id !== input.address.id; + }); + }; + } +} +``` + + diff --git a/docs/composition/useApi.md b/docs/composition/useApi.md new file mode 100644 index 000000000..a6a846c9f --- /dev/null +++ b/docs/composition/useApi.md @@ -0,0 +1,75 @@ +# useApi composable + +`useApi` composable allows to execute received GraphQL query with optional variables and headers and returns the result. + +## API +`useApi` composable returns the following properties: + +- `query` - function that executes a GraphQL query and handle its error and result +- `mutate` - function that executes received GraphQL Mutation with optional variables and headers and returns the result. + +## Interfaces + +```ts +type FetchPolicy = 'cache-first' | 'network-only' | 'cache-only' | 'no-cache' | 'standby'; + +type Variables = { + [key: string]: any; +}; + +type Error = { + message: string; + locations?: { + line: number; + column: number; + }[]; + path?: string[]; + extensions?: any; +}; + +type Request = ( + request: string, + variables?: VARIABLES, + fetchPolicy?: FetchPolicy, +) => Promise<{ data: DATA, errors: Error[] }>; + +interface UseApiInterface { + query: Request; + mutate: Request; +} +``` + +## Example + +Execute a GraphQL query to get cart price: + +```ts +import { useApi } from '~/composables/useApi'; + +const GET_CART_PRICE_QUERY = ` + query GET_CART_PRICE_QUERY($cartId: String!) { + cart(cart_id: $cartId) { + prices { + subtotal_excluding_tax { + value + } + } + } + } +`; + +export default { + setup() { + const { query } = useApi(); + + async function getCartPrice(cartId: string) { + return await query( + GET_CART_PRICE_QUERY, + { cartId }, + { 'Accept': 'application/json' } + ); + } + } +}; +``` + diff --git a/docs/composition/useBilling.md b/docs/composition/useBilling.md new file mode 100644 index 000000000..f8aea312a --- /dev/null +++ b/docs/composition/useBilling.md @@ -0,0 +1,68 @@ +# useBilling composable + +`useBilling` composable allows loading and manipulating billing information of the current user. + +## API +`useBilling` composable returns the following properties: + +- `load` - function that loads the billing information. +- `save` - function that Saves the billing information. +- `error` - ref that contains an errors from the composable methods +- `loading` - ref that contains information whether any of the composable methods is loading + +## Interfaces + +```ts +/** + * Almost every method is extending this type + */ +type ComposableFunctionArgs = T & { + customQuery?: CustomQuery; + customHeaders?: CustomHeaders; +}; + +interface UseBillingError { + load: Error | null; + save: Error | null; +} + +type UseBillingLoadParams = ComposableFunctionArgs<{}>; + +type UseBillingSaveParams = ComposableFunctionArgs<{ + billingDetails: BillingDetails; +}>; + +interface UseBillingInterface { + load(params?: UseBillingLoadParams): Promise; + save(params: UseBillingSaveParams): Promise; + error: Readonly>; + loading: Readonly>; +} +``` + +## Example + +Load user's billing information and handle the form submit: + +```ts +import useBilling from '~/modules/checkout/composables/useBilling'; + +const { save, load } = useBilling(); + +onMounted(async () => { + const billingInformation = await load(); +}); + +const handleAddressSubmit = (reset: () => void) => async () => { + const billingDetailsData = { + billingDetails: { + customerAddressId: addressId, + sameAsShipping: false, + save_in_address_book: false, + }, + }; + + await save(billingDetailsData); +}; +``` + diff --git a/docs/composition/useCart.md b/docs/composition/useCart.md new file mode 100644 index 000000000..eb63c807b --- /dev/null +++ b/docs/composition/useCart.md @@ -0,0 +1,252 @@ +# useCart composable + +`useCart` composable allows loading and manipulating cart of the current user. + +The state of the wishlist is kept in [Pinia](https://pinia.vuejs.org/) Store and is accessible through `useCartStore()` composable. + +We use Pinia store to keep the same state for Wishlist across the whole application. There is always one instance of wishlist no matter how many times you instantiate `useCart` composable. + +## API +`useCart` composable returns the following properties: + +- `load` - function that loads the current cart. +- `loadTotalQty` - function that pdates the global application state with the current total quantity of the cart. +- `addItem` - function that takes in a product and its quantity and adds it to the cart. +- `removeItem` - function that removes an item from a cart +- `updateItemQty` - function that updates the quantity of an item in a cart +- `clear` - function that removes all items from the cart +- `applyCoupon` - function that applies a coupon to the cart +- `removeCoupon` - function that removes a coupon from the cart +- `isInCart` - function that checks whether a product is in the cart +- `setCart` - function that sets the contents of the cart +- `canAddToCart` - function that checks whether a product can be added to the cart +- `cart` - returns the items in the cart as a `computed` property +- `error` - ref that contains an errors from the composable methods +- `loading` - ref that contains information whether any of the composable methods is loading + +## Interfaces + +```ts +/** + * Almost every method is extending this type + */ +type ComposableFunctionArgs = T & { + customQuery?: CustomQuery; + customHeaders?: CustomHeaders; +}; + +type UseCartAddItemParams = ComposableFunctionArgs<{ + product: PRODUCT; + quantity: number; + productConfiguration?: { [key: string]: string }; +}>; + +type UseCartRemoveItemParams = ComposableFunctionArgs<{ + product: CART_ITEM +}>; + +type UseCartUpdateItemQtyParams = ComposableFunctionArgs<{ + product: CART_ITEM + quantity: number +}>; + +type UseCartClearParams = ComposableFunctionArgs<{ + realCart?: boolean +}>; + +type UseCartApplyCouponParams = ComposableFunctionArgs<{ + couponCode: string +}>; + + +interface UseCartInterface { + load(params?: ComposableFunctionArgs<{ realCart?: boolean }>): Promise; + loadTotalQty(): Promise; + addItem( + params: UseCartAddItemParams + ): Promise; + removeItem(params: UseCartRemoveItemParams< CART_ITEM>): Promise; + updateItemQty(params: UseCartUpdateItemQtyParams): Promise; + clear(params: UseCartClearParams): Promise; + applyCoupon(params: UseCartApplyCouponParams): Promise; + removeCoupon(params: ComposableFunctionArgs<{}>): Promise; + isInCart(PRODUCT): boolean; + setCart(newCart: CART): void; + canAddToCart(product: Product, qty: number); + cart: ComputedRef; + loading: Readonly>; + error: Readonly>; +} +``` + +## cartGetters + +`cartGetters` is a set of helper functions that can be used to get data from the cart. They receive either product or cart as a parameter and return the data from it. + +### product parameter + +- `getItemName` - returns the name of the item +- `getSlug` - returns the slug of the item +- `getItemImage` - returns the image of the item +- `getItemPrice` - returns object with the prices of the item: + - `regular` - returns the regular price of the item + - `special` - returns the special price of the item + - `credit` - returns the credit price of the item + - `discountPercentage` - returns the discount percentage of the item + - `total` - returns the total price of the item +- `productHasSpecialPrice` - returns whether the product has a special price +- `getItemQty` - returns the quantity of the item +- `getItemAttributes` - returns the attributes of the item +- `getItemSku` - returns the sku of the item +- `getConfiguredVariant` - returns the configured variant of the item +- `getStockStatus` - returns the stock status of the item + +### cart parameter + +- `getItems` - returns the items in the cart +- `getTotals` - returns object with the total cart prices: + - `total` - returns the total price of the cart + - `subtotal` - returns the subtotal price of the cart + - `special` - returns the special price of the cart +- `getShippingPrice` - returns the shipping price of the cart +- `getTotalItems` - returns the total quantity of items in the cart +- `getCoupons` - returns the coupons applied to the cart +- `getDiscounts` - returns the discounts applied to the cart +- `getDiscountAmount` - returns the discount amount applied to the cart +- `getAppliedCoupon` - returns the applied coupon +- `getSelectedShippingMethod` - returns the selected shipping method +- `getAvailablePaymentMethods` - returns the available payment methods + +## cartGetters usage + +```ts +import cartGetters from '~/modules/checkout/getters/cartGetters'; + +const productName = cartGetters.getItemName(product); +const productSlug = cartGetters.getSlug(product); +const productImage = cartGetters.getItemImage(product); + +const totalItemsInCart = cartGetters.getTotalItems(cart); +const cartItems = cartGetters.getItems(cart); +const cartCoupons = cartGetters.getCoupons(cart); +``` + +## Examples + +### Adding items to the cart + +Add item to the cart and disable the button if the product is out of stock: + +```ts + + +``` + +### Loading cart +Load user's total quantity of items in the cart: + +```ts +import { useCart } from '~/modules/checkout/composables/useCart'; + +const { loadTotalQty, cart } = useCart(); + +onMounted(async () => { + await loadTotalQty(); + + console.log(cart.value.total_quantity); +}); +``` + +### Removing items from the cart + +Load user's cart and handle removing items from the cart: + +```ts +import { useCart } from '~/modules/checkout/composables/useCart'; + +const { + cart, + removeItem, + updateItemQty, + load, +} = useCart(); + +onMounted(() => { + if (!cart.value.id) { + loadCart(); + } +}); + +const products = computed(() => cartGetters + .getItems(cart.value) + .filter(Boolean) + .map((item) => ({ + ...item, + product: { + ...item.product, + ...[(item as ConfigurableCartItem).configured_variant ?? {}], + original_sku: item.product.sku, + }, + }))); + +const actionRemoveItem = async (product: CartItemInterface) => { + await removeItem({ product }); + + console.log(product + ' removed from cart'); + + await updateItemQty({ product, quantity: 0 }); +}; +``` + +### Applying and removing coupons from the cart + +Check if user applied a coupon to the cart and apply or remove it: + +```ts +const {cart, applyCoupon, removeCoupon, error } = useCart(); + +const couponCodeUserInput = ref(''); + +const couponCodeAppliedToCart = computed(() => cartGetters.getAppliedCoupon(cart.value)?.code); +const isCouponCodeApplied = computed(() => couponCodeAppliedToCart.value !== undefined); + +const applyOrRemoveCoupon = async () => { + const operationPromise = isCouponCodeApplied.value + ? removeCoupon({}) + : applyCoupon({ couponCode: couponCodeUserInput.value }); + + await operationPromise; + + couponCodeUserInput.value = ''; +}; +``` + diff --git a/docs/composition/useCategory.md b/docs/composition/useCategory.md new file mode 100644 index 000000000..2a99ea74a --- /dev/null +++ b/docs/composition/useCategory.md @@ -0,0 +1,84 @@ +# useCategory composable + +`useCategory` composable allows loading categories from Magento API. It is commonly used in navigation menus, and provides the load function and refs for the categories, loading and error. + +## API +`useAddresses` composable returns the following properties: + +- `load` - function that loads the list of categories and updates `categories` +- `loadCategoryMeta` - function that loads the category metadata +- `categories` - the array of categories fetched in the `load` method, otherwise is `null`. +- `error` - ref that contains an errors from the composable methods +- `loading` - ref that contains information whether any of the composable methods is loading + +## Interfaces + +```ts +/** + * Almost every method is extending this type + */ +type ComposableFunctionArgs = T & { + customQuery?: CustomQuery; + customHeaders?: CustomHeaders; +}; + +interface UseCategoryErrors { + /** Error when loading categories fails, otherwise is `null`. */ + load: Error; + loadCategoryMeta: Error; +} + +type UseCategoryParamsInput = ComposableFunctionArgs< { + pageSize: number; +}>; + +type UseCategoryMetaParamsInput = ComposableFunctionArgs< { + category_uid: string; +}>; + +interface UseCategoryInterface { + categories: Ref; + error: Ref; + loading: Ref; + load(params: ComposableFunctionArgs): Promise; + loadCategoryMeta(params: ComposableFunctionArgs): Promise; +} +``` +## Example + +Load categories on client side using the `onMounted` Composition API hook: + +```ts + + + + ``` \ No newline at end of file diff --git a/docs/composition/useCategorySearch.md b/docs/composition/useCategorySearch.md new file mode 100644 index 000000000..c1d27f004 --- /dev/null +++ b/docs/composition/useCategorySearch.md @@ -0,0 +1,49 @@ +# useCategorySearch composable + +`useCategorySearch` composable allows searching for categories. It is commonly used in navigation menus, and provides the search function and refs for the categories, loading and error. + +## API +`useCategorySearch` composable returns the following properties: + +- `search` - function that searches for categories using the received filters and updates the categories with the results. +- `result` - the list of categories found by the last search. It's `null` if the search has not been executed yet or fails. +- `error` - ref that contains an errors from the composable methods +- `loading` - ref that contains information whether any of the composable methods is loading + +## Interfaces + +```ts +/** + * Almost every method is extending this type + */ +type ComposableFunctionArgs = T & { + customQuery?: CustomQuery; + customHeaders?: CustomHeaders; +}; + +type UseCategorySearchParams = ComposableFunctionArgs; + +interface UseCategorySearchInterface { + search(searchParams: UseCategorySearchParams): Promise; + error: DeepReadonly>; + result: DeepReadonly>; + loading: Readonly>; +} +``` +## Example + +Search for a category by its uid and get its name: + +```ts +import { useCategorySearch } from '~/modules/category/composables/useCategorySearch'; + +const { search } = useCategorySearch(); + +const myCategory = useAsync(async () => { + const data = await search({ filters: { category_uid: { "eq": "MjA=" } } }); + + return data?.[0] ?? {} +}); + +const myCategoryName = computed(() => myCategory.value.name); + ``` \ No newline at end of file diff --git a/docs/composition/useConfig.md b/docs/composition/useConfig.md new file mode 100644 index 000000000..f478e08c7 --- /dev/null +++ b/docs/composition/useConfig.md @@ -0,0 +1,72 @@ +# useConfig composable + +`useConfig` composable allows interacting with the store configuration. + +## API +`useConfig` composable returns the following properties: + +- `load` - function that loads store configuration +- `config` - ref that contains store configuration +- `error` - ref that contains an errors from the composable methods +- `loading` - ref that contains information whether any of the composable methods is loading + +## Interfaces + +```ts +/** + * Almost every method is extending this type + */ +type ComposableFunctionArgs = T & { + customQuery?: CustomQuery; + customHeaders?: CustomHeaders; +}; + +interface UseCategoryErrors { + /** Error when loading categories fails, otherwise is `null`. */ + load: Error; + loadCategoryMeta: Error; +} + +type UseCategoryParamsInput = ComposableFunctionArgs< { + pageSize: number; +}>; + +type UseCategoryMetaParamsInput = ComposableFunctionArgs< { + category_uid: string; +}>; + +interface UseCategoryInterface { + categories: Ref; + error: Ref; + loading: Ref; + load(params: ComposableFunctionArgs): Promise; + loadCategoryMeta(params: ComposableFunctionArgs): Promise; +} +``` +## Example + +Get store configuration and use it to retrieve logo information: + +```ts +import { useConfig } from '~/composables'; + +const { config } = useConfig(); + +const logoSrc = computed(() => { + const baseMediaUrl = config.value.base_media_url; + const logo = config.value.header_logo_src; + + return baseMediaUrl && logo ? `${baseMediaUrl}logo/${logo}` : ''; +}); + +const logoWidth = computed( + () => config.value.logo_width || '35', +); + +const logoHeight = computed( + () => config.value.logo_height || '34', +); + +const logoAlt = computed( + () => config.value.logo_alt || '', + ``` \ No newline at end of file diff --git a/docs/modules/catalog/filters.md b/docs/modules/catalog/filters.md index 995e470a2..a93374f51 100644 --- a/docs/modules/catalog/filters.md +++ b/docs/modules/catalog/filters.md @@ -75,7 +75,7 @@ To create a new renderer, open the `modules/catalog/category/components/filters/ Every renderer must: -- Emit `selectFilter` event whenever an option is selected (type: [AggregationOption](/api-reference/magento-theme.aggregationoption.html)). Otherwise parent component will not know about the change. +- Emit `selectFilter` event whenever an option is selected (type: `AggregationOption`). Otherwise parent component will not know about the change. ```html diff --git a/docs/modules/catalog/product-types.md b/docs/modules/catalog/product-types.md index d89631a7a..32e08141c 100644 --- a/docs/modules/catalog/product-types.md +++ b/docs/modules/catalog/product-types.md @@ -50,7 +50,7 @@ To add support for custom product types, create a new component inside the `modu It should accept two props: -- `product` (type: [Product](http://localhost:8080/api-reference/magento-theme.product.html)) - product object fetched from the API, +- `product` (type: `Product`) - product object fetched from the API, - `isFetching` (type: `boolean`) - a flag indicating whether the `product.vue` components currently fetches product data . ```typescript diff --git a/packages/theme/modules/checkout/composables/useCart/index.ts b/packages/theme/modules/checkout/composables/useCart/index.ts index 624baa8e2..0c5a4f7f1 100644 --- a/packages/theme/modules/checkout/composables/useCart/index.ts +++ b/packages/theme/modules/checkout/composables/useCart/index.ts @@ -15,6 +15,7 @@ import { useWishlist } from '~/modules/wishlist/composables/useWishlist'; import { Product } from '~/modules/catalog/product/types'; import { ComposableFunctionArgs } from '~/composables'; import { UseCartErrors, UseCartInterface } from './useCart'; +import { ProductStockStatus } from '~/modules/GraphQL/types'; /** * Allows loading and manipulating cart of the current user. @@ -272,7 +273,7 @@ PRODUCT return !!product?.configurable_product_options_selection?.variant ?.uid; } - const inStock = product?.stock_status || ''; + const inStock = product.stock_status === ProductStockStatus.InStock ? true : false; const stockLeft = product?.only_x_left_in_stock === null ? true : qty <= product?.only_x_left_in_stock;