Skip to content

Commit

Permalink
feat(pci-billing): add history billing section
Browse files Browse the repository at this point in the history
ref: DTCORE-2797
Signed-off-by: LIDRISSI Hamid <[email protected]>
  • Loading branch information
seven-amid committed Nov 21, 2024
1 parent 65ebb9a commit c574985
Show file tree
Hide file tree
Showing 16 changed files with 387 additions and 78 deletions.
36 changes: 36 additions & 0 deletions packages/manager/apps/pci-billing/src/api/data/history.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { v6 } from '@ovh-ux/manager-core-api';
import { TCurrentUsage } from './consumption';

export type TUsageHistoryPeriod = {
id: string;
lastUpdate: string;
period: {
from: string;
to: string;
};
};

export const getUsageHistoryPeriod = async (
projectId: string,
from: string,
to: string,
): Promise<TUsageHistoryPeriod[]> => {
const { data } = await v6.get<TUsageHistoryPeriod[]>(
`/cloud/project/${projectId}/usage/history?from=${from}&to=${to}`,
);

return data;
};

export type THistoryUsage = TCurrentUsage;

export const getUsageHistory = async (
projectId: string,
usageId: string,
): Promise<THistoryUsage> => {
const { data } = await v6.get<THistoryUsage>(
`/cloud/project/${projectId}/usage/history/${usageId}`,
);

return data;
};
Original file line number Diff line number Diff line change
Expand Up @@ -318,8 +318,6 @@ export type TSnapshot = {
};

export type TConsumptionDetail = {
hourlyBilling: TCurrentUsage;
monthlyBilling: TCurrentUsage;
hourlyInstances: TInstance[];
monthlyInstances: TInstance[];
objectStorages: TStorage[];
Expand Down Expand Up @@ -370,7 +368,7 @@ export type TConsumptionDetail = {
};
};

const getConsumptionDetails = (usage: TCurrentUsage) => {
export const getConsumptionDetails = (usage: TCurrentUsage) => {
const resourceMap = [
{ type: 'registry', key: 'privateRegistry' },
{ type: 'loadbalancer', key: 'kubernetesLoadBalancer' },
Expand Down Expand Up @@ -445,8 +443,6 @@ const getConsumptionDetails = (usage: TCurrentUsage) => {
const finalTotal = roundPrice(totals.hourly.total + totals.monthly.total);

return {
hourlyBilling: usage,
monthlyBilling: usage,
hourlyInstances: hourlyInstanceList,
monthlyInstances: monthlyInstanceList,
objectStorages: objectStorageList,
Expand All @@ -466,9 +462,10 @@ export const useGeTCurrentUsage = (projectId: string) =>
useQuery({
queryKey: [projectId, 'current', 'usage'],
queryFn: async () => {
const usageData = await getCurrentUsage(projectId);
return getConsumptionDetails(usageData);
const currentUsage = await getCurrentUsage(projectId);
return currentUsage;
},
select: (data) => getConsumptionDetails(data),
});

type ActivateMonthlyBillingProps = {
Expand Down
38 changes: 38 additions & 0 deletions packages/manager/apps/pci-billing/src/api/hook/useHistory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { useQuery } from '@tanstack/react-query';
import { isSameMonth } from 'date-fns';
import { useComputeDate } from '@/components/history/useComputeDate.hook';
import { getCurrentUsage } from '../data/consumption';
import { getUsageHistory, getUsageHistoryPeriod } from '../data/history';
import { getConsumptionDetails } from './useConsumption';

export const useUsageHistoryPeriod = (
projectId: string,
from: string,
to: string,
) =>
useQuery({
queryKey: [projectId, from, to, 'history', 'usage'],
queryFn: async () => {
const historyPeriod = await getUsageHistoryPeriod(projectId, from, to);
return historyPeriod?.length ? historyPeriod[0] : {};
},
});

export const useGetUsageHistory = (projectId: string, usageId: string) => {
const { currentDate } = useComputeDate();

return useQuery({
queryKey: [projectId, usageId, 'history', 'usage'],
queryFn: async () => {
const historyUsage = await getUsageHistory(projectId, usageId);

if (isSameMonth(new Date(), currentDate)) {
const { monthlyUsage } = await getCurrentUsage(projectId);
return { ...historyUsage, monthlyUsage };
}
return historyUsage;
},
enabled: !!usageId,
select: (data) => getConsumptionDetails(data),
});
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { ODS_THEME_COLOR_INTENT } from '@ovhcloud/ods-common-theming';
import {
ODS_BUTTON_SIZE,
ODS_BUTTON_TYPE,
ODS_BUTTON_VARIANT,
ODS_ICON_NAME,
ODS_ICON_SIZE,
ODS_TEXT_LEVEL,
ODS_TEXT_SIZE,
} from '@ovhcloud/ods-components';
import { OsdsButton, OsdsIcon, OsdsText } from '@ovhcloud/ods-components/react';
import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom';
import { isSameDay, startOfMonth } from 'date-fns';
import { useComputeDate } from './useComputeDate.hook';

export default function HistoryHeader() {
const { t } = useTranslation('history');

const {
currentDate,
prevMonthDate,
nextMonthDate,
translationValues,
} = useComputeDate();

const isLimitReached = isSameDay(currentDate, startOfMonth(new Date()));

const navigate = useNavigate();
const navigateToMonth = (date: Date) => {
navigate(`../history/${date.getFullYear()}/${date.getMonth() + 1}`);
};

return (
<div className="mb-5 flex justify-between items-center">
<OsdsButton
color={ODS_THEME_COLOR_INTENT.primary}
type={ODS_BUTTON_TYPE.button}
size={ODS_BUTTON_SIZE.sm}
variant={ODS_BUTTON_VARIANT.ghost}
onClick={() => navigateToMonth(prevMonthDate)}
className="flex"
>
<OsdsIcon
name={ODS_ICON_NAME.CHEVRON_LEFT}
size={ODS_ICON_SIZE.xxs}
color={ODS_THEME_COLOR_INTENT.primary}
className="mr-4"
/>
{t('cpbh_previous_month')}
</OsdsButton>

<OsdsText
size={ODS_TEXT_SIZE._500}
level={ODS_TEXT_LEVEL.heading}
color={ODS_THEME_COLOR_INTENT.text}
slot="summary"
>
{t('cpbh_current_month', { ...translationValues })}
</OsdsText>

<OsdsButton
color={ODS_THEME_COLOR_INTENT.primary}
type={ODS_BUTTON_TYPE.button}
size={ODS_BUTTON_SIZE.sm}
variant={ODS_BUTTON_VARIANT.ghost}
onClick={() => navigateToMonth(nextMonthDate)}
disabled={isLimitReached || undefined}
className="flex"
>
{t('cpbh_next_month')}
<OsdsIcon
name={ODS_ICON_NAME.CHEVRON_RIGHT}
size={ODS_ICON_SIZE.xxs}
color={ODS_THEME_COLOR_INTENT.primary}
className="ml-4"
/>
</OsdsButton>
</div>
);
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { Links, LinkType } from '@ovh-ux/manager-react-components';
import { ShellContext } from '@ovh-ux/manager-react-shell-client';
import { OdsHTMLAnchorElementTarget } from '@ovhcloud/ods-common-core';
import { ODS_THEME_COLOR_INTENT } from '@ovhcloud/ods-common-theming';
import { ODS_TEXT_LEVEL, ODS_TEXT_SIZE } from '@ovhcloud/ods-components';
import { OsdsText } from '@ovhcloud/ods-components/react';
import { useContext, useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useComputeDate } from './useComputeDate.hook';

type HistoryResumeProps = {
totalPrice: number;
isPostPaidUsageBilling: boolean;
};

export default function HistoryResume({
totalPrice,
isPostPaidUsageBilling,
}: Readonly<HistoryResumeProps>) {
const { t } = useTranslation('history');

const [billingUrl, setBillingUrl] = useState('');

const {
shell: { navigation },
environment,
} = useContext(ShellContext);

const { translationValues } = useComputeDate();

useEffect(() => {
navigation
.getURL('dedicated', '#/billing/history', {})
.then((data) => setBillingUrl(data as string));
}, [navigation]);

return (
<div className="my-4 p-4 bg-[--ods-color-default-050] border border-solid border-[--ods-color-default-200]">
<OsdsText
size={ODS_TEXT_SIZE._400}
level={ODS_TEXT_LEVEL.heading}
color={ODS_THEME_COLOR_INTENT.text}
className="block"
>
{t('cpbhd_monthly_bill_header', { ...translationValues })}
</OsdsText>

{isPostPaidUsageBilling && (
<OsdsText
size={ODS_TEXT_SIZE._400}
level={ODS_TEXT_LEVEL.body}
color={ODS_THEME_COLOR_INTENT.text}
className="mb-5"
>
{t('cpbhd_monthly_bill_description', {
...translationValues,
})}
</OsdsText>
)}

<OsdsText
size={ODS_TEXT_SIZE._700}
level={ODS_TEXT_LEVEL.heading}
color={ODS_THEME_COLOR_INTENT.text}
className="block my-4"
>
{`${totalPrice?.toFixed(2)} ${environment?.getUser()?.currency.symbol}`}
</OsdsText>

<Links
type={LinkType.next}
href={billingUrl}
label={t('cpbhd_bill_link')}
target={OdsHTMLAnchorElementTarget._top}
/>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { getDateFnsLocale } from '@ovh-ux/manager-core-utils';
import { addMonths, format, subMonths } from 'date-fns';
import * as dateFnsLocales from 'date-fns/locale';
import { useRef } from 'react';
import { useTranslation } from 'react-i18next';
import { useParams } from 'react-router-dom';

export const useComputeDate = () => {
const { i18n } = useTranslation('history');
const locales = useRef({ ...dateFnsLocales }).current;
const userLocale = getDateFnsLocale(i18n.language);

const { year, month } = useParams();

const currentYear = parseInt(year, 10);
const currentMonth = parseInt(month, 10) - 1; // month is 0-based in Date
const currentDate = new Date(currentYear, currentMonth, 1);

const prevMonthDate = subMonths(currentDate, 1);
const nextMonthDate = addMonths(currentDate, 1);

const translationValues = {
month: format(currentDate, 'MMMM', { locale: locales[userLocale] }),
year: currentYear,
lastMonth: format(prevMonthDate, 'MMMM', { locale: locales[userLocale] }),
previousYear: prevMonthDate.getFullYear(),
};

return {
currentDate,
prevMonthDate,
nextMonthDate,
translationValues,
};
};
Loading

0 comments on commit c574985

Please sign in to comment.