import gql from 'graphql-tag' import { useQuery, useResult } from '@vue/apollo-composable' import { Ref, computed, isRef } from '@vue/composition-api' export const productFragment = gql` fragment product on Product { id name label description mainImage includedOptions currencies recurring enabled prices { name label description bannerMessage enabled highlighted tokens { name count unlimited } basePrice yearlyPrice defaultPromoCode } } ` export const productOptionFragment = gql` fragment productOption on ProductOption { name label description basePrice } ` export interface Product { name: string label: string description?: string mainImage?: string includedOptions?: string[] recurring: boolean enabled: boolean hidden: boolean currencies: string[] prices: ProductPrice[] options: ProductOption[] info?: any } export interface ProductPrice { name: string label?: string description?: string bannerMessage?: string enabled: boolean highlighted?: boolean tokens?: ProductPriceToken[] basePrice: any yearlyPrice?: any promoCodes?: PromoCode[] defaultPromoCode?: string } export interface PromoCode { name: string value: string field: 'totalPrice' | 'basePrice' modifier: string maxUser?: number info?: any } export interface ProductPriceToken { name: string count?: number unlimited?: boolean } export interface ProductOption { name: string label: string description?: string basePrice: any tokens?: string[] info?: any } export interface UseProductsOptions { query?: 'products' | 'recurringProducts' | 'oneTimeProducts' productFragment?: string productOptionFragment?: string } export function useProducts (options: UseProductsOptions = {}) { const query = useQuery(gql` query products { ${options.query || 'products'} { ...product ${options.productFragment || ''} options { ...productOption ${options.productOptionFragment || ''} } } } ${productFragment} ${productOptionFragment} `) const products = useResult(query.result, []) as Ref return { ...query, products, } } export interface UseProductOptions { productFragment?: string productOptionFragment?: string } export function useProduct (name: Ref, options: UseProductOptions = {}) { const query = useQuery(gql` query product ($name: String!) { product (name: $name) { ...product ${options.productFragment || ''} options { ...productOption ${options.productOptionFragment || ''} } } } ${productFragment} ${productOptionFragment} `, () => ({ name: name.value, })) const product = useResult(query.result) as Ref const hasYearlyPrice = computed(() => product.value?.prices?.some(p => p.yearlyPrice != null)) return { ...query, product, hasYearlyPrice, } } export interface ProductPriceInput { priceName: string currency: string options: string[] promoCode?: string } export interface PricePreview { price: number exTaxPrice: number rawPrice: number tax?: PricePreviewTax } export interface PricePreviewTax { type: string rate: number amount: number } export function useProductPrice (productName: string | Ref, input: Ref) { const finalProductName = computed(() => isRef(productName) ? productName.value : productName) const query = useQuery(gql` query productPrice ($name: String!, $input: ProductPriceInput!) { product (name: $name) { id price (input: $input) { ...productPricePreview } yearlyPrice: price (input: $input, yearly: true) { ...productPricePreview } } } fragment productPricePreview on ProductPricePreview { price exTaxPrice rawPrice tax { type rate amount } promoCodeDescription } `, () => ({ name: finalProductName.value, input: input.value, }), () => ({ enabled: !!input.value.priceName && !!input.value.currency, fetchPolicy: 'cache-and-network', })) const pricePreview = useResult(query.result, null, data => data.product.price) as Ref const yearlyPricePreview = useResult(query.result, null, data => data.product.yearlyPrice) as Ref return { ...query, pricePreview, yearlyPricePreview, } }