From b8d17ec8ab616498a8563d29615ba7a9f39effcc Mon Sep 17 00:00:00 2001 From: tsiorifamonjena Date: Fri, 17 Jan 2025 10:56:34 +0100 Subject: [PATCH] feat(pci.public-ip): select default gatway by region and lowest price ref: TAPC-2602 Signed-off-by: tsiorifamonjena --- .../translations/order/Messages_fr_FR.json | 2 +- .../api/hooks/useDefaultAvailableGateway.ts | 47 ++++++++++++++++ .../pci-public-ip/src/api/hooks/useRegions.ts | 19 +++++++ .../src/api/hooks/useSelectedGateway.ts | 54 ------------------- .../pages/order/steps/FloatingIpSummary.tsx | 30 ++--------- 5 files changed, 72 insertions(+), 80 deletions(-) create mode 100644 packages/manager/apps/pci-public-ip/src/api/hooks/useDefaultAvailableGateway.ts delete mode 100644 packages/manager/apps/pci-public-ip/src/api/hooks/useSelectedGateway.ts diff --git a/packages/manager/apps/pci-public-ip/public/translations/order/Messages_fr_FR.json b/packages/manager/apps/pci-public-ip/public/translations/order/Messages_fr_FR.json index b5a93f389408..b56ad29accfc 100644 --- a/packages/manager/apps/pci-public-ip/public/translations/order/Messages_fr_FR.json +++ b/packages/manager/apps/pci-public-ip/public/translations/order/Messages_fr_FR.json @@ -28,7 +28,7 @@ "pci_additional_ip_create_step_select_region_description_floating_ip": "Vous ne trouvez pas la région que vous désirez dans la liste ? Pour en savoir plus sur la disponibilité des produits par région, cliquez ici.", "pci_additional_ip_create_step_attach_instance_description_floating_ip": "Seules les instances avec des réseaux privés sont affichées", "pci_additional_ip_create_no_instance_message_floating_ip": "Aucune instance avec réseau privé n'a été trouvée dans la région sélectionnée. Veuillez en créer un avant d'attacher une floating IP.", - "pci_additional_ip_create_summary_step_missing_components_description": "Nous avons détecté des composants manquants.", + "pci_additional_ip_create_summary_step_missing_components_description": "Nous avons détecté des composants manquants", "pci_additional_ip_create_summary_step_gateway_name": "Une nouvelle instance Gateway est en cours de création dans le datacenter {{ region }}.", "pci_additional_ip_create_summary_step_gateway_size_and_price": "La taille sélectionnée est : {{ size }}", "pci_additional_ip_create_summary_step_price": "au prix de", diff --git a/packages/manager/apps/pci-public-ip/src/api/hooks/useDefaultAvailableGateway.ts b/packages/manager/apps/pci-public-ip/src/api/hooks/useDefaultAvailableGateway.ts new file mode 100644 index 000000000000..e6595f77109b --- /dev/null +++ b/packages/manager/apps/pci-public-ip/src/api/hooks/useDefaultAvailableGateway.ts @@ -0,0 +1,47 @@ +import { useMemo } from 'react'; +import { TCatalog } from '@ovh-ux/manager-pci-common'; +import { useCloudCatalog } from './catalog/useCloudCatalog'; +import { useAvailableHourlyPlansRegion } from './useRegions'; + +const getGatewayWithLowestPrice = (catalog: TCatalog, plans: string[]) => { + const gatewayProducts = (catalog.addons || []) + .filter((addon) => plans.includes(addon.planCode)) + .sort( + ({ pricings: [{ price: priceA }] }, { pricings: [{ price: priceB }] }) => + Number(priceA) - Number(priceB), + ) + .filter( + ({ product }, _index: number, arr: { product: string }[]) => + product === arr[0].product, + ); + const [monthlyPriceObj] = + (gatewayProducts || [])?.find(({ planCode }) => planCode?.includes('month')) + ?.pricings || []; + const [hourlyPriceObj] = + (gatewayProducts || []).find(({ planCode }) => planCode.includes('hour')) + ?.pricings || []; + + const size = gatewayProducts[0]?.product + .split('-') + .slice(-1) + .join(); + const pricePerMonth = monthlyPriceObj?.price; + const pricePerHour = hourlyPriceObj?.price; + + return { + size, + price: { hour: Number(pricePerHour), month: Number(pricePerMonth) }, + }; +}; + +// TODO: similar use case in network and compute, think to move it to pci-common +export const useDefaultAvailableGateway = (region: string) => { + const { data } = useCloudCatalog(); + + const plans = useAvailableHourlyPlansRegion(region); + + return useMemo(() => (data ? getGatewayWithLowestPrice(data, plans) : null), [ + data, + plans, + ]); +}; diff --git a/packages/manager/apps/pci-public-ip/src/api/hooks/useRegions.ts b/packages/manager/apps/pci-public-ip/src/api/hooks/useRegions.ts index 71025cd703c1..d43fdb3a6139 100644 --- a/packages/manager/apps/pci-public-ip/src/api/hooks/useRegions.ts +++ b/packages/manager/apps/pci-public-ip/src/api/hooks/useRegions.ts @@ -1,4 +1,6 @@ +import { useMemo } from 'react'; import { fetchIcebergV6 } from '@ovh-ux/manager-core-api'; +import { useProductAvailability, useProject } from '@ovh-ux/manager-pci-common'; import { useQuery } from '@tanstack/react-query'; export interface Region { @@ -22,3 +24,20 @@ export const getRegionsQuery = (projectId: string) => ({ export const useRegions = (projectId: string) => useQuery(getRegionsQuery(projectId)); + +export const useAvailableHourlyPlansRegion = (regionName: string) => { + const { data: project } = useProject(); + const { data } = useProductAvailability(project.project_id, { + addonFamily: 'gateway', + }); + + return useMemo(() => { + const plans = data?.plans.filter(({ code }) => code.includes('hour')) || []; + const plansRegion = + plans.filter((plan) => + plan.regions.some((region) => region.name === regionName), + ) || []; + + return plansRegion.map((item) => item.code); + }, [data, regionName]); +}; diff --git a/packages/manager/apps/pci-public-ip/src/api/hooks/useSelectedGateway.ts b/packages/manager/apps/pci-public-ip/src/api/hooks/useSelectedGateway.ts deleted file mode 100644 index c871cce15600..000000000000 --- a/packages/manager/apps/pci-public-ip/src/api/hooks/useSelectedGateway.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { useEffect, useState } from 'react'; -import { useCloudCatalog } from './catalog/useCloudCatalog'; - -type TState = { - size: string; - price: { - month: number; - hour: number; - }; -}; - -export const useSelectedGateway = () => { - const { data, isPending } = useCloudCatalog(); - const [state, setState] = useState(null); - - useEffect(() => { - if (data) { - const gatewayProducts = (data?.addons || []) - .filter((addon) => addon.product?.startsWith('publiccloud-gateway')) - .sort( - ( - { pricings: [{ price: priceA }] }, - { pricings: [{ price: priceB }] }, - ) => Number(priceA) - Number(priceB), - ) - .filter( - ({ product }, _index: number, arr: { product: string }[]) => - product === arr[0].product, - ); - const [monthlyPriceObj] = - (gatewayProducts || [])?.find(({ planCode }) => - planCode?.includes('month'), - )?.pricings || []; - const [hourlyPriceObj] = - (gatewayProducts || []).find(({ planCode }) => - planCode.includes('hour'), - )?.pricings || []; - - const size = gatewayProducts[0].product - .split('-') - .slice(-1) - .join(); - const pricePerMonth = monthlyPriceObj.price; - const pricePerHour = hourlyPriceObj.price; - - setState(() => ({ - size, - price: { hour: Number(pricePerHour), month: Number(pricePerMonth) }, - })); - } - }, [data]); - - return { state, isPending }; -}; diff --git a/packages/manager/apps/pci-public-ip/src/pages/order/steps/FloatingIpSummary.tsx b/packages/manager/apps/pci-public-ip/src/pages/order/steps/FloatingIpSummary.tsx index 13de8b182214..426cbb599657 100644 --- a/packages/manager/apps/pci-public-ip/src/pages/order/steps/FloatingIpSummary.tsx +++ b/packages/manager/apps/pci-public-ip/src/pages/order/steps/FloatingIpSummary.tsx @@ -16,7 +16,7 @@ import { useMe } from '@/api/hooks/useMe'; import { useSubnets } from '@/api/hooks/useSubnets'; import { useGateways } from '@/api/hooks/useGateways'; import { TGateway } from '@/api/data/gateways'; -import { useSelectedGateway } from '@/api/hooks/useSelectedGateway'; +import { useDefaultAvailableGateway } from '@/api/hooks/useDefaultAvailableGateway'; import { CatalogPriceComponent } from '@/components/CatalogPrice.component'; export const FloatingIpSummary = ({ @@ -41,7 +41,7 @@ export const FloatingIpSummary = ({ projectId, networkId, ); - const { state: selectedGateway } = useSelectedGateway(); + const selectedGateway = useDefaultAvailableGateway(ipRegion); const { t: tOrder } = useTranslation('order'); @@ -96,20 +96,8 @@ export const FloatingIpSummary = ({ > {tOrder( 'pci_additional_ip_create_summary_step_missing_components_description', - )} - -

-

- - {tOrder( - 'pci_additional_ip_create_summary_step_gateway_name', - { - region: ipRegion, - }, - )} + )}{' '} + : Gateway.

{selectedGateway && ( @@ -125,14 +113,6 @@ export const FloatingIpSummary = ({ {tOrder( 'pci_additional_ip_create_summary_step_price', )}{' '} - {' '} - {tOrder('pci_additional_ip_create_summary_step_that_is')}{' '} - )*. + ).

)}