Skip to content

Commit

Permalink
feat: yearly/monthly billing for cloudserver (#4781)
Browse files Browse the repository at this point in the history
* feat:yearly/monthly billing for cloudserver

* fix list servertype

* feat cost tip

* add tip

* add error tip
  • Loading branch information
zjy365 authored Jun 17, 2024
1 parent e8950db commit 02e12d6
Show file tree
Hide file tree
Showing 14 changed files with 294 additions and 140 deletions.
16 changes: 12 additions & 4 deletions frontend/providers/cloudserver/public/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@
"Quantity tips": "Quantity is {{amount1}} to {{amount2}}",
"ReStart": "Restart",
"Reference fee": "Reference fee",
"Reference fee disk tips": "{{price}}/GiB/hour",
"Reference fee tip": "{{price}}/hour",
"Reference fee bandwidth tips": "{{price}}/Mbps/hour",
"Reference fee disk tips": "{{price}}/GiB",
"Reference fee tip": "{{price}}",
"Reference fee bandwidth tips": "{{price}}/Mbps",
"Restarting": "Restarting",
"Set Password": "Set Password",
"Start": "Start",
Expand Down Expand Up @@ -111,5 +111,13 @@
"highPerformance": "High Performance",
"Public IP is not enabled": "Public IP is not enabled",
"interval": "Interval",
"sold out": "Sold Out"
"sold out": "Sold Out",
"month": "month",
"indivual": "indivual",
"year": "year",
"duration": "duration",
"total": "total",
"After the annual and monthly cloud hosting is sold": "After the annual and monthly cloud hosting is sold",
"No refund allowed": "No refund allowed,",
"Pay Confirm tips": "Clicking \"Confirm\" indicates that you have understood and agreed to this clause. If you do not agree to the clause \"No refunds are allowed after the annual or monthly cloud hosting is sold\", please click the \"Cancel\" button. If you do not agree, this purchase will be canceled and you will not be charged any fees."
}
18 changes: 13 additions & 5 deletions frontend/providers/cloudserver/public/locales/zh/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@
"Changing": "变更中",
"Restarting": "重启中",
"Reference fee": "参考费用",
"Reference fee tip": "{{price}}/小时",
"Reference fee tip": "{{price}}",
"Configuration fee details": "配置费用明细",
"Instance": "实例",
"storage fees": "存储费用",
Expand All @@ -85,8 +85,8 @@
"publicIpAssigned tips": "请注意:未分配独立公网IP地址的情况下无法使用外网IP地址对外进行互相通信。",
"Fee inquiry in progress": "费用查询中...",
"hour": "小时",
"Reference fee disk tips": "{{price}}/GiB/小时",
"Reference fee bandwidth tips": "{{price}}/Mbps/小时",
"Reference fee disk tips": "{{price}}/GiB",
"Reference fee bandwidth tips": "{{price}}/Mbps",
"Billing rules": "计费规则",
"The maximum number of instances is 20": "最大数量是20",
"Billing model": "计费模式",
Expand All @@ -111,5 +111,13 @@
"highPerformance": "计算型",
"Public IP is not enabled": "未开启公网IP",
"interval": "区间",
"sold out": "售空"
}
"sold out": "售空",
"month": "",
"indivual": "",
"year": "",
"duration": "时长",
"total": "总计",
"After the annual and monthly cloud hosting is sold": "包年包月云主机售卖后",
"No refund allowed": "不允许退费,",
"Pay Confirm tips": "点击“确认”表示您已知晓并同意此条款。如果您不同意“包年包月云主机售卖后不允许退费”的条款,请点击“取消”按钮。不同意后,本次购买将被撤销,您不会被收取任何费用。"
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const map = {
connection: require('./icons/connection.svg').default,
info: require('./icons/info.svg').default,
restore: require('./icons/restore.svg').default,
infoWarn: require('./icons/infoWarn.svg').default,
download: require('./icons/download.svg').default,
check: require('./icons/check.svg').default,
close: require('./icons/close.svg').default,
Expand Down
6 changes: 3 additions & 3 deletions frontend/providers/cloudserver/src/hooks/useConfirm.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useCallback, useRef } from 'react';
import { ReactNode, useCallback, useRef } from 'react';
import {
AlertDialog,
AlertDialogBody,
Expand All @@ -17,7 +17,7 @@ export const useConfirm = ({
confirmText = 'Confirm'
}: {
title?: string;
content: string;
content: ReactNode;
confirmText?: string;
}) => {
const { isOpen, onOpen, onClose } = useDisclosure();
Expand All @@ -41,7 +41,7 @@ export const useConfirm = ({
() => (
<AlertDialog isOpen={isOpen} leastDestructiveRef={cancelRef} onClose={onClose}>
<AlertDialogOverlay>
<AlertDialogContent>
<AlertDialogContent maxW={'600px'}>
<AlertDialogHeader fontSize="lg" fontWeight="bold">
{t(title)}
</AlertDialogHeader>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,20 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
zone: form.zone,
virtualMachineType: form.virtualMachineType,
virtualMachineArch: form.virtualMachineArch,
chareType: form.chargeType
chargeType: form.chargeType,
period: parseInt(form.period)
};

const { data } = await POST('/action/create', payload, {
const { data, error } = await POST('/action/create', payload, {
headers: {
Authorization: req.headers.authorization
}
});

if (error) {
return jsonRes(res, { code: 500, error: error });
}

return jsonRes(res, {
data: data
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
await verifyAccessToken(req);

const payload = req.body as ServerTypePayload;
console.log(payload);

const { data, error } = await POST('/action/get-virtual-machine-package', payload, {
headers: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
zone: form.zone,
virtualMachineType: form.virtualMachineType,
virtualMachineArch: form.virtualMachineArch,
chareType: form.chargeType
chargeType: form.chargeType,
period: parseInt(form.period)
};

const result = await POST('/action/get-price', payload, {
Expand All @@ -44,6 +45,6 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
data: result?.data
});
} catch (error) {
jsonRes(res, { code: 500, error: error });
jsonRes(res, { code: 500, error: 'error' });
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ const ErrorModal = ({
return (
<Modal isOpen={true} onClose={onClose}>
<ModalOverlay />
<ModalContent py={3}>
<ModalContent>
<ModalHeader display={'flex'} alignItems={'center'} color={'myRed.600'}>
<MyIcon name="warning"></MyIcon>
<Box ml={3} fontSize={'xl'}>
{title}
</Box>
</ModalHeader>
<ModalCloseButton color={'myRed.600'} fontSize={'16px'} transform={'translateY(10px)'} />
<ModalCloseButton color={'myRed.600'} fontSize={'16px'} />
<ModalBody maxH={'50vh'} overflow={'auto'} whiteSpace={'pre-wrap'}>
{content}
</ModalBody>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,13 @@ import MyIcon from '@/components/Icon';
import { MyTable, TableColumnsType } from '@/components/MyTable';
import MyTooltip from '@/components/MyTooltip';
import { CloudServerStatus, CloudServerType, EditForm, StorageType } from '@/types/cloudserver';
import { CVMArchType, CVMRegionType, CVMZoneType, VirtualMachineType } from '@/types/region';
import {
CVMArchType,
CVMChargeType,
CVMRegionType,
CVMZoneType,
VirtualMachineType
} from '@/types/region';
import {
Box,
Button,
Expand Down Expand Up @@ -261,6 +267,15 @@ function OuterTabs({ systemRegion }: { systemRegion: CVMRegionType[] }) {
onChange={(e) => {
const item = systemRegion[e];
formHook?.setValue('chargeType', item.chargeType);
formHook?.setValue('virtualMachineArch', item.zone[0].arch[0].arch);
formHook.setValue(
'virtualMachineType',
item.zone[0].arch[0].virtualMachineType[0].virtualMachineType
);
formHook.setValue(
'virtualMachinePackageFamily',
item.zone[0].arch[0].virtualMachineType[0].virtualMachinePackageFamily[0]
);
}}
>
<TabList alignItems={'center'}>
Expand Down Expand Up @@ -430,7 +445,10 @@ export default function Form({
item.status === CloudServerStatus.Unavailable ? 'grayModern.500' : 'brightBlue.700'
}
>
{t('Reference fee tip', { price: item.instancePrice })}{' '}
{t('Reference fee tip', { price: item.instancePrice })}/
{formHook.getValues('chargeType') === CVMChargeType.postPaidByHour
? t('hour')
: t('month')}
</Text>
);
}
Expand Down Expand Up @@ -555,6 +573,29 @@ export default function Form({
[getValues, register, removeStorages, setValue, t]
);

const monthsArray = useMemo(() => {
const months = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 24, 36];
return months.map((month) => {
let label;
if (month < 12) {
label = `${month} ${t('indivual')} ${t('month')}`;
} else if (month === 12) {
label = `1${t('year')}`;
} else {
const years = Math.floor(month / 12);
const remainingMonths = month % 12;
label =
remainingMonths === 0
? `${years} ${t('year')}`
: `${years} ${t('year')}${remainingMonths} ${t('indivual')} ${t('month')}`;
}
return {
value: month.toString(),
label: label
};
});
}, [t]);

return (
<Flex
height={'100%'}
Expand Down Expand Up @@ -846,6 +887,26 @@ export default function Form({
</Box>
)}
</Box>

{formHook.getValues('chargeType') === CVMChargeType.prePaid && (
<Flex alignItems={'center'} mb={'24px'} flex={1}>
<Label>
<Text>{t('duration')}</Text>
</Label>
<Box>
<MySelect
isInvalid={!!errors.period}
width={'200px'}
value={getValues('period')}
list={monthsArray}
onchange={(id: string) => {
setValue('period', id);
formHook.clearErrors();
}}
/>
</Box>
</Flex>
)}
</Box>
</Flex>
);
Expand Down
Loading

0 comments on commit 02e12d6

Please sign in to comment.