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')}{' '}
- )*.
+ ).
)}