diff --git a/packages/manager/modules/manager-pci-common/src/components/region-selector/RegionGlobalzoneChip.component.spec.tsx b/packages/manager/modules/manager-pci-common/src/components/region-selector/RegionGlobalzoneChip.component.spec.tsx
index 10c5b447d2e5..bcc878e5223e 100644
--- a/packages/manager/modules/manager-pci-common/src/components/region-selector/RegionGlobalzoneChip.component.spec.tsx
+++ b/packages/manager/modules/manager-pci-common/src/components/region-selector/RegionGlobalzoneChip.component.spec.tsx
@@ -10,6 +10,7 @@ import {
} from './RegionGlobalzoneChip.component';
import { wrapper } from '@/wrapperRenders';
import { URL_INFO } from '@/components/region-selector/constants';
+import { useHas3AZ } from '@/hooks/useHas3AZ/useHas3AZ';
vi.mock('@ovh-ux/manager-react-components', async (importOriginal) => {
const module = await importOriginal<
@@ -18,6 +19,8 @@ vi.mock('@ovh-ux/manager-react-components', async (importOriginal) => {
return { ...module, useFeatureAvailability: vi.fn() };
});
+vi.mock('@/hooks/useHas3AZ/useHas3AZ');
+
enum ExpectedType {
GLOBAL_REGIONS = 'GLOBAL_REGIONS',
'1AZ_REGIONS' = '1AZ_REGIONS',
@@ -87,4 +90,40 @@ describe('RegionGlobalzoneChip', () => {
}
},
);
+
+ it.each([
+ ['render', true, true],
+ ['not render', true, undefined],
+ ['not render', false, true],
+ ])(
+ 'should %s 3AZ tooltip text when feature availability is %s and 3AZ availability is %s',
+ (expected: string, show1AZ: boolean, has3AZ: boolean) => {
+ vi.mocked(useFeatureAvailability).mockImplementationOnce(
+ (features) =>
+ ({
+ data: {
+ ...Object.fromEntries(
+ features.map((feature) => [feature, false]),
+ ),
+ [FEATURE_REGION_1AZ]: show1AZ,
+ },
+ isLoading: false,
+ } as UseFeatureAvailabilityResult),
+ );
+
+ vi.mocked(useHas3AZ).mockReturnValue(has3AZ);
+
+ render(, { wrapper });
+
+ if (expected === 'render') {
+ expect(
+ screen.getByText('pci_project_flavors_zone_1AZ_with_3AZ_tooltip'),
+ ).toBeInTheDocument();
+ } else {
+ expect(
+ screen.queryByText('pci_project_flavors_zone_1AZ_with_3AZ_tooltip'),
+ ).not.toBeInTheDocument();
+ }
+ },
+ );
});
diff --git a/packages/manager/modules/manager-pci-common/src/components/region-selector/RegionGlobalzoneChip.component.tsx b/packages/manager/modules/manager-pci-common/src/components/region-selector/RegionGlobalzoneChip.component.tsx
index 3f0d02ca09cd..9dda7b3c6d9a 100644
--- a/packages/manager/modules/manager-pci-common/src/components/region-selector/RegionGlobalzoneChip.component.tsx
+++ b/packages/manager/modules/manager-pci-common/src/components/region-selector/RegionGlobalzoneChip.component.tsx
@@ -23,6 +23,7 @@ import {
import { OdsHTMLAnchorElementTarget } from '@ovhcloud/ods-common-core';
import { useTranslation } from 'react-i18next';
import { URL_INFO } from './constants';
+import { useHas3AZ } from '../../hooks/useHas3AZ/useHas3AZ';
export const FEATURE_REGION_1AZ = 'public-cloud:region-1AZ';
@@ -42,6 +43,8 @@ export function RegionGlobalzoneChip({
const tooltipUrl =
URL_INFO[linkType][ovhSubsidiary] || URL_INFO[linkType].DEFAULT;
+ const has3AZ = useHas3AZ();
+
const chip = (
- {t(
- `pci_project_flavors_zone_${
- data?.[FEATURE_REGION_1AZ] ? '1AZ' : 'globalregions'
- }_tooltip`,
- )}
+ {has3AZ && data?.[FEATURE_REGION_1AZ]
+ ? t('pci_project_flavors_zone_1AZ_with_3AZ_tooltip')
+ : t(
+ `pci_project_flavors_zone_${
+ data?.[FEATURE_REGION_1AZ] ? '1AZ' : 'globalregions'
+ }_tooltip`,
+ )}
+ | undefined;
+
+/**
+ * Use {usePCICommonContextFactory} for general usage.
+ *
+ * Use this to override previously set properties
+ */
+export const PCICommonContext = createContext(undefined);
diff --git a/packages/manager/modules/manager-pci-common/src/hooks/useHas3AZ/useHas3AZ.spec.tsx b/packages/manager/modules/manager-pci-common/src/hooks/useHas3AZ/useHas3AZ.spec.tsx
new file mode 100644
index 000000000000..e1831d4e4b70
--- /dev/null
+++ b/packages/manager/modules/manager-pci-common/src/hooks/useHas3AZ/useHas3AZ.spec.tsx
@@ -0,0 +1,32 @@
+import { renderHook } from '@testing-library/react';
+import { useHas3AZ } from './useHas3AZ';
+import { PCICommonContext } from '../../contexts/PCICommonContext/PCICommonContext';
+import { usePCICommonContextFactory } from '../usePCICommonContextFactory/usePCICommonContextFactory';
+
+describe('useHas3AZ', () => {
+ it.each([
+ [false, undefined],
+ [false, {}],
+ [false, { has3AZ: false }],
+ [false, { has3AZ: 'whatever' }],
+ [false, { has3AZ: null }],
+ [true, { has3AZ: true }],
+ ])(
+ 'should return %s when meta is %o',
+ (expected: boolean, meta: { has3AZ: boolean | string } | undefined) => {
+ const { result } = renderHook(() => useHas3AZ(), {
+ wrapper: ({ children }) => {
+ const pciCommonContext = usePCICommonContextFactory(meta);
+
+ return (
+
+ {children}
+
+ );
+ },
+ });
+
+ expect(result.current).toBe(expected);
+ },
+ );
+});
diff --git a/packages/manager/modules/manager-pci-common/src/hooks/useHas3AZ/useHas3AZ.ts b/packages/manager/modules/manager-pci-common/src/hooks/useHas3AZ/useHas3AZ.ts
new file mode 100644
index 000000000000..76deafa37225
--- /dev/null
+++ b/packages/manager/modules/manager-pci-common/src/hooks/useHas3AZ/useHas3AZ.ts
@@ -0,0 +1,10 @@
+import { useContext } from 'react';
+import { PCICommonContext } from '../../contexts/PCICommonContext/PCICommonContext';
+
+export const useHas3AZ = (): boolean => {
+ const meta = useContext(PCICommonContext);
+
+ return meta && 'has3AZ' in meta && typeof meta.has3AZ === 'boolean'
+ ? meta.has3AZ
+ : false;
+};
diff --git a/packages/manager/modules/manager-pci-common/src/hooks/usePCICommonContextFactory/usePCICommonContextFactory.spec.tsx b/packages/manager/modules/manager-pci-common/src/hooks/usePCICommonContextFactory/usePCICommonContextFactory.spec.tsx
new file mode 100644
index 000000000000..92be56629f55
--- /dev/null
+++ b/packages/manager/modules/manager-pci-common/src/hooks/usePCICommonContextFactory/usePCICommonContextFactory.spec.tsx
@@ -0,0 +1,116 @@
+import { renderHook } from '@testing-library/react';
+import { PropsWithChildren, useContext } from 'react';
+import { PCICommonContext } from '@/contexts/PCICommonContext/PCICommonContext';
+import { usePCICommonContextFactory } from './usePCICommonContextFactory';
+
+const myVarChildren = {
+ myVar: 'children',
+};
+
+const TestChildrenMerge = ({ children }: PropsWithChildren) => {
+ const pciCommonContext = usePCICommonContextFactory(myVarChildren);
+
+ return (
+
+ {children}
+
+ );
+};
+
+const TestChildrenOverride = ({ children }: PropsWithChildren) => (
+
+ {children}
+
+);
+
+const ParentWithoutProvider = ({ children }: PropsWithChildren) => (
+ {children}
+);
+
+const myVarParent = {
+ myVar: 'parent',
+};
+
+const ParentWithMyVar = ({ children }: PropsWithChildren) => {
+ const pciCommonContext = usePCICommonContextFactory(myVarParent);
+
+ return (
+
+ {children}
+
+ );
+};
+
+const myVar2Parent = {
+ myVar2: 'parent',
+};
+
+const ParentWithMyVar2 = ({ children }: PropsWithChildren) => {
+ const pciCommonContext = usePCICommonContextFactory(myVar2Parent);
+
+ return (
+
+ {children}
+
+ );
+};
+
+const ParentWithEmptyFactory = ({ children }: PropsWithChildren) => {
+ const pciCommonContext = usePCICommonContextFactory();
+
+ return (
+
+ {children}
+
+ );
+};
+
+describe('usePCICommonContextFactory', () => {
+ it('should set value', () => {
+ const { result } = renderHook(() => useContext(PCICommonContext), {
+ wrapper: ParentWithoutProvider,
+ });
+
+ expect(result.current).toEqual({ myVar: 'children' });
+ });
+
+ it('should override previously set value', () => {
+ const { result } = renderHook(() => useContext(PCICommonContext), {
+ wrapper: ParentWithMyVar,
+ });
+
+ expect(result.current).toEqual({ myVar: 'children' });
+ });
+
+ it('should merge with old value', () => {
+ const { result } = renderHook(() => useContext(PCICommonContext), {
+ wrapper: ({ children }) => (
+
+ {children}
+
+ ),
+ });
+
+ expect(result.current).toEqual({ myVar: 'children', myVar2: 'parent' });
+ });
+
+ it('should override old value', () => {
+ const { result } = renderHook(() => useContext(PCICommonContext), {
+ wrapper: ({ children }) => (
+
+ {children}
+
+ ),
+ });
+
+ expect(result.current).toEqual({ myVar: 'children' });
+ });
+
+ it('should work with no values', () => {
+ const { result } = renderHook(() => useContext(PCICommonContext), {
+ wrapper: ParentWithEmptyFactory,
+ });
+
+ expect(result.current).toEqual({});
+ });
+});
diff --git a/packages/manager/modules/manager-pci-common/src/hooks/usePCICommonContextFactory/usePCICommonContextFactory.ts b/packages/manager/modules/manager-pci-common/src/hooks/usePCICommonContextFactory/usePCICommonContextFactory.ts
new file mode 100644
index 000000000000..4c913f94bc3c
--- /dev/null
+++ b/packages/manager/modules/manager-pci-common/src/hooks/usePCICommonContextFactory/usePCICommonContextFactory.ts
@@ -0,0 +1,17 @@
+import { useContext, useMemo } from 'react';
+import {
+ PCICommonContext,
+ PCICommonMetaType,
+} from '../../contexts/PCICommonContext/PCICommonContext';
+
+/**
+ * Use this to merge meta properties with previously set properties (merge is only on level 1)
+ *
+ * To override all properties use the provider directly
+ * @param meta Be sure to create it outside your component or memoize it to avoid performance issues
+ */
+export function usePCICommonContextFactory(meta?: PCICommonMetaType) {
+ const base = useContext(PCICommonContext);
+
+ return useMemo(() => ({ ...(base || {}), ...(meta || {}) }), [base, meta]);
+}
diff --git a/packages/manager/modules/manager-pci-common/src/index.ts b/packages/manager/modules/manager-pci-common/src/index.ts
index a5bed219b64b..23d3d2cff55c 100644
--- a/packages/manager/modules/manager-pci-common/src/index.ts
+++ b/packages/manager/modules/manager-pci-common/src/index.ts
@@ -13,6 +13,8 @@ export * from './components/region-selector/RegionLocalzoneChip.component';
export * from './components/region-selector/Region3AZChip.component';
export * from './hooks';
export * from './constants';
+export { PCICommonContext } from './contexts/PCICommonContext/PCICommonContext';
+export { usePCICommonContextFactory } from './hooks/usePCICommonContextFactory/usePCICommonContextFactory';
export * from './components/quantity-selector';
export * from './components/Pricing';
export * from './components/shape-input/ShapeInput.component';
diff --git a/packages/manager/modules/manager-pci-common/src/translations/region-selector/Messages_fr_FR.json b/packages/manager/modules/manager-pci-common/src/translations/region-selector/Messages_fr_FR.json
index 6f8235d82f65..a60a0d19e720 100644
--- a/packages/manager/modules/manager-pci-common/src/translations/region-selector/Messages_fr_FR.json
+++ b/packages/manager/modules/manager-pci-common/src/translations/region-selector/Messages_fr_FR.json
@@ -12,6 +12,7 @@
"pci_project_flavors_zone_localzone_tooltip": "Les Local Zones sont un nouveau type de localisation, qui prennent en charge une partie de notre portefeuille de produits Public Cloud. Nous allons progressivement augmenter le nombre total de Local Zones dans le monde au cours des prochaines années.",
"pci_project_flavors_zone_localzone_1AZ_tooltip": "Une Local Zone correspond à un mode de déploiement des produits Public Cloud d’OVHcloud dans des datacenters situés au plus près des utilisateurs finaux.",
"pci_project_flavors_zone_globalregions_tooltip": "Les Régions sont supportées par un ou plusieurs datacenters gérés par OVHCloud. Chaque région fournit une ou plusieurs Availability Zone avec le portefeuille complet de services OVHCloud.",
+ "pci_project_flavors_zone_1AZ_with_3AZ_tooltip": "Avec l'arrivée prochaine des régions 3-AZ, le type de déploiement 'Régions' change de nom ! Une région 1-AZ (zone de disponibilité) regroupe un ou plusieurs datacenters localisés sur un même site.",
"pci_project_flavors_zone_1AZ_tooltip": "Une région 1-AZ (zone de disponibilité) regroupe un ou plusieurs datacenters localisés sur un même site.",
"pci_project_flavors_zone_3AZ_tooltip": "Une région 3-AZ comprend trois zones de disponibilités situées dans une même aire métropolitaine, séparées par quelques kilomètres. Elle répond aux exigences les plus élevées en matière de résilience tout en garantissant une latence extrêmement faible entre les AZ.",
"pci_project_flavors_zone_tooltip_link": "En savoir plus"