diff --git a/packages/manager/apps/pci-gateway/src/api/data/gateway-plans.ts b/packages/manager/apps/pci-gateway/src/api/data/gateway-plans.ts index 5a7eb793806a..e19116f9ee06 100644 --- a/packages/manager/apps/pci-gateway/src/api/data/gateway-plans.ts +++ b/packages/manager/apps/pci-gateway/src/api/data/gateway-plans.ts @@ -1,17 +1,21 @@ import { v6 } from '@ovh-ux/manager-core-api'; import { RegionType } from '@/types/region'; +export type TPlanRegion = { + name: string; + continentCode: string; + datacenter: string; + enabled: boolean; + type: RegionType; +}; + +export type TPlan = { + code: string; + regions: TPlanRegion[]; +}; + export type TAvailableGatewayPlansResponse = { - plans: { - code: string; - regions: { - name: string; - continentCode: string; - datacenter: string; - enabled: boolean; - type: RegionType; - }[]; - }[]; + plans: TPlan[]; }; export const getAvailableGatewayPlans = async ( diff --git a/packages/manager/apps/pci-gateway/src/api/hooks/data.ts b/packages/manager/apps/pci-gateway/src/api/hooks/data.ts index a5763a663966..661e53f225ad 100644 --- a/packages/manager/apps/pci-gateway/src/api/hooks/data.ts +++ b/packages/manager/apps/pci-gateway/src/api/hooks/data.ts @@ -1,10 +1,10 @@ -import { useEffect, useState } from 'react'; +import { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { getMacroRegion } from '@ovh-ux/manager-react-components'; -import { TCatalog } from '@ovh-ux/manager-pci-common'; +import { TAddon } from '@ovh-ux/manager-pci-common'; import { useCloudCatalog } from '@/api/hooks/cloud-catalog'; import { useAvailableGatewayPlans } from '@/api/hooks/gateway-plans'; -import { TAvailableGatewayPlansResponse } from '@/api/data/gateway-plans'; +import { TPlan, TPlanRegion } from '@/api/data/gateway-plans'; import { RegionType } from '@/types/region'; const getLitteralProductSize = (productName: string): string => { @@ -34,124 +34,117 @@ export type TSizeItem = { availableRegions: TAvailableRegion[]; }; +export type TAvailablePlansGrouped = { + [key: string]: { code: string; regions: TPlanRegion[] }; +}; + +const getPrice = (addon: TAddon): number | undefined => + addon?.pricings.find((price) => price.capacities.includes('consumption')) + ?.price; + export const useData = (projectId: string) => { - const { i18n, t: tSelector } = useTranslation('catalog-selector'); - const { t: tRegion } = useTranslation('regions'); + const { t } = useTranslation(['catalog-selector', 'regions']); const { data: cloudCatalog } = useCloudCatalog(); const { data: availableGatewayPlans } = useAvailableGatewayPlans(projectId); - const [sizes, setSizes] = useState([]); - - useEffect(() => { - if (availableGatewayPlans && cloudCatalog) { - const gatewayPlansWithRegions = availableGatewayPlans.plans.filter( - (plan) => plan.regions.length, - ); - - const newSizes = gatewayPlansWithRegions - .reduce( - (accumulator, currentValue) => { - const addon = cloudCatalog.addons.find( - ($addon) => $addon.planCode === currentValue.code, - ); - const plansProductName = addon.product; - - const isHourly = addon.planCode.includes('hour'); - - const foundProduct = accumulator.find( - (product) => product.name === plansProductName, - ); - - if (foundProduct) { - if (isHourly) { - foundProduct.hourly = { addon, plan: currentValue }; - } else { - foundProduct.monthly = { addon, plan: currentValue }; - } - } else { - const newProduct = isHourly - ? { - name: plansProductName, - hourly: { addon, plan: currentValue }, - } - : { - name: plansProductName, - monthly: { addon, plan: currentValue }, - }; - accumulator.push(newProduct); - } - return accumulator; - }, - [] as { - name: string; - hourly?: { - plan: TAvailableGatewayPlansResponse['plans'][0]; - addon: TCatalog['addons'][0]; - }; - monthly?: { - plan: TAvailableGatewayPlansResponse['plans'][0]; - addon: TCatalog['addons'][0]; - }; - }[], + const getBandWidthLabel = (bandwidth: number) => + bandwidth > 1000 + ? t(`pci_projects_project_gateways_model_selector_bandwidth`, { + bandwidth: bandwidth / 1000, + }) + + t( + 'pci_projects_project_gateways_model_selector_bandwidth_unit_size_gbps', ) - .map((product) => { - const size: TSizeItem = { - payload: getLitteralProductSize(product.name), - label: `${tSelector( - `pci_projects_project_gateways_model_selector_size`, - )} ${getLitteralProductSize(product.name).toUpperCase()}`, - bandwidth: product.hourly.addon.blobs.technical.bandwidth.level, - bandwidthLabel: ((bandwidthLevel: number) => - bandwidthLevel > 1000 - ? tSelector( - `pci_projects_project_gateways_model_selector_bandwidth`, - { bandwidth: bandwidthLevel / 1000 }, - ) + - tSelector( - 'pci_projects_project_gateways_model_selector_bandwidth_unit_size_gbps', - ) - : tSelector( - `pci_projects_project_gateways_model_selector_bandwidth`, - { bandwidth: bandwidthLevel }, - ) + - tSelector( - 'pci_projects_project_gateways_model_selector_bandwidth_unit_size_mbps', - ))(product.hourly.addon.blobs.technical.bandwidth.level), - hourlyPrice: product.hourly.addon.pricings.find((price) => - price.capacities.includes('consumption'), - )?.price, - monthlyPrice: product.monthly.addon.pricings.find((price) => - price.capacities.includes('consumption'), - )?.price, - availableRegions: product.monthly.plan?.regions.map((region) => ({ - name: region.name, - datacenter: region.datacenter, - continentCode: region.continentCode, - enabled: region.enabled, - active: region.enabled, - macroName: tRegion( - `manager_components_region_${getMacroRegion(region.name)}`, - ), - microName: tRegion( - `manager_components_region_${getMacroRegion( - region.name, - )}_micro`, - { micro: region.name }, - ), - continent: tRegion( - `manager_components_region_continent_${getMacroRegion( - region.name, - )}`, - ), - type: region.type, - })), - }; - return size; - }); - - setSizes(newSizes?.sort((a, b) => a.monthlyPrice - b.monthlyPrice)); + : t(`pci_projects_project_gateways_model_selector_bandwidth`, { + bandwidth, + }) + + t( + 'pci_projects_project_gateways_model_selector_bandwidth_unit_size_mbps', + ); + + const mergedRegionPlan = useMemo( + () => + availableGatewayPlans?.plans.reduce( + (result: TAvailablePlansGrouped, currentValue: TPlan) => { + const code = currentValue.code.replace(/\.3AZ$/, ''); + const newResult = { ...result }; + + if (newResult[code]) { + newResult[code] = { + code, + regions: [...newResult[code].regions, ...currentValue.regions], + }; + } else { + newResult[code] = currentValue; + } + + return newResult; + }, + {}, + ), + [availableGatewayPlans], + ); + + const gatewayRefPlans = useMemo( + () => + mergedRegionPlan + ? Object.values(mergedRegionPlan).filter((plan) => + plan.code.includes('hour'), + ) + : [], + [mergedRegionPlan], + ); + + const sizes: TSizeItem[] = useMemo(() => { + if (cloudCatalog) { + return gatewayRefPlans.map((plan) => { + const addonHourly = cloudCatalog.addons.find( + ($addon) => $addon.planCode === plan.code, + ); + + const addonMonthly = cloudCatalog.addons.find( + ($addon) => $addon.planCode === plan.code.replace('hour', 'month'), + ); + + const hourlyPrice = getPrice(addonHourly); + const monthlyPrice = getPrice(addonMonthly); + + return { + payload: getLitteralProductSize(addonHourly.product), + label: `${t( + `pci_projects_project_gateways_model_selector_size`, + )} ${getLitteralProductSize(addonHourly.product).toUpperCase()}`, + bandwidth: addonHourly.blobs.technical.bandwidth.level, + bandwidthLabel: getBandWidthLabel( + addonHourly.blobs.technical.bandwidth.level, + ), + hourlyPrice, + monthlyPrice, + availableRegions: plan.regions.map((region) => ({ + ...region, + macroName: t( + `regions:manager_components_region_${getMacroRegion( + region.name, + )}`, + ), + microName: t( + `regions:manager_components_region_${getMacroRegion( + region.name, + )}_micro`, + { micro: region.name }, + ), + continent: t( + `regions:manager_components_region_continent_${getMacroRegion( + region.name, + )}`, + ), + })) as TAvailableRegion[], + }; + }); } - }, [availableGatewayPlans, cloudCatalog, i18n]); - return sizes; + return []; + }, [gatewayRefPlans, cloudCatalog]); + + return sizes.sort((a, b) => a.monthlyPrice - b.monthlyPrice); };