Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

page.tsx 6.1KB

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