選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

page.tsx 5.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. "use client";
  2. import { useState } from 'react'
  3. import PageTitle from '@/components/ui/PageTitle';
  4. import { Typography, Button, Input, Form, Select, Switch } from 'antd'
  5. import Link from 'next/link';
  6. import { BankFilled, WalletFilled } from '@ant-design/icons';
  7. import type { PaymentType } from '@/types/payment';
  8. import { useQuery } from '@tanstack/react-query';
  9. import { getPaymentType } from '@/app/api/general/paymentService';
  10. const { Text, Title } = Typography;
  11. const iconMapper = {
  12. "card": <WalletFilled className='!text-white !text-xl' />,
  13. "bank": <BankFilled className='!text-white !text-xl' />
  14. };
  15. const CreatePersona: React.FC = () => {
  16. const [selectedPaymentID, setSelectedPaymentID] = useState<number | undefined>()
  17. const [companyName, setCompanyName] = useState("")
  18. const [cardNumber, setCardNumber] = useState("")
  19. const [cvc, setCvc] = useState("")
  20. const { data: paymentType, error, isLoading } = useQuery<PaymentType[] | undefined>({
  21. queryKey: ["getPaymentType"],
  22. queryFn: () => getPaymentType()
  23. });
  24. if (isLoading) {
  25. return <p>Loading...</p>;
  26. }
  27. return (
  28. <div className="flex flex-col bg-white">
  29. <PageTitle title='PAYMENT' />
  30. <div className='p-4 px-8 '>
  31. <div className='flex flex-col gap-5 mb-8'>
  32. <div className='text-xs'>
  33. <p className='font-semibold'>Enter your payment details</p>
  34. <p className='font-semibold italic'>
  35. By continuing you agree to our <Link href="/">Terms</Link>
  36. </p>
  37. </div>
  38. </div>
  39. <div className='flex flex-row flex-wrap gap-2'>
  40. {paymentType?.map(({ id, type, description, icon_id }) => (
  41. <div
  42. key={id}
  43. className={`${selectedPaymentID === id ? 'bg-blue-950' : 'bg-gray-200'} hover:bg-blue-950 transition-all ease-in-out rounded-lg p-4 max-w-[160px] cursor-pointer`}
  44. onClick={() => setSelectedPaymentID(id)}
  45. >
  46. {iconMapper[icon_id]}
  47. <p className='text-white'>{`Transfer via card number`}</p>
  48. </div>
  49. ))}
  50. </div>
  51. <div className="px-2 mt-4">
  52. <Form layout="vertical">
  53. <div className="grid grid-cols-1 sm:grid-cols-2">
  54. <Form.Item label={<Text className='!italic !text-xs !font-semibold'>Company Name</Text>}>
  55. <Input
  56. placeholder="Company Name"
  57. value={companyName}
  58. onChange={(e) => setCompanyName(e.target.value)}
  59. />
  60. </Form.Item>
  61. <Form.Item label={<Text className='!italic !text-xs !font-semibold'>Card Number</Text>}>
  62. <Input
  63. value={cardNumber}
  64. onChange={(e) => {
  65. const rawValue = e.target.value.replace(/\D/g, '').slice(0, 16);
  66. const formattedValue = rawValue.replace(/(.{4})/g, '$1 ').trim();
  67. setCardNumber(formattedValue);
  68. }}
  69. />
  70. </Form.Item>
  71. <div className='flex flex-row gap-5'>
  72. <Form.Item label={<Text className='!italic !text-xs !font-semibold'>Exp Month</Text>} className="w-full">
  73. <Select
  74. allowClear
  75. style={{ width: '100%' }}
  76. placeholder="Please select"
  77. options={
  78. Array.from({ length: 12 }, (_, i) => {
  79. const month = String(i + 1).padStart(2, '0');
  80. return { label: month, value: month };
  81. })
  82. }
  83. />
  84. </Form.Item>
  85. <Form.Item label={<Text className='!italic !text-xs !font-semibold'>Exp Year</Text>} className="w-full">
  86. <Select
  87. allowClear
  88. style={{ width: '100%' }}
  89. placeholder="Please select"
  90. options={
  91. Array.from({ length: 10 }, (_, i) => {
  92. const year = new Date().getFullYear() + i;
  93. return { label: String(year), value: String(year) };
  94. })
  95. }
  96. />
  97. </Form.Item>
  98. </div>
  99. <Form.Item label={<Text className='!italic !text-xs !font-semibold'>CVC</Text>}>
  100. <div className='flex gap-6 items-center'>
  101. <Input
  102. placeholder="123"
  103. className='!max-w-[50px]'
  104. value={cvc}
  105. onChange={(e) => {
  106. const rawValue = e.target.value.replace(/\D/g, '').slice(0, 4);
  107. setCvc(rawValue);
  108. }}
  109. />
  110. <p className='text-gray-300 max-w-[160px]' style={{ fontSize: 10 }}>
  111. 3 or 4 digits usually found on the signature strips
  112. </p>
  113. </div>
  114. </Form.Item>
  115. <Form.Item>
  116. <div className='flex flex-row items-center gap-2'>
  117. <Switch checked={true} onChange={() => { }} />
  118. <Text className='!text-xs font-semibold'>SET AS DEFAULT</Text>
  119. </div>
  120. </Form.Item>
  121. </div>
  122. <Button type="primary" className='!w-full !py-3'>CONFIRM</Button>
  123. </Form>
  124. </div>
  125. </div>
  126. </div>
  127. )
  128. }
  129. export default CreatePersona;