Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ant Design compatibility #70

Open
EncryptedCurse opened this issue Jun 25, 2021 · 3 comments
Open

Ant Design compatibility #70

EncryptedCurse opened this issue Jun 25, 2021 · 3 comments

Comments

@EncryptedCurse
Copy link

How can I use this library with Ant Design?

Attempting a minimal working example as follows...

<Input {...getCardNumberProps()} />

...produces this error:

Uncaught TypeError: Cannot read property 'match' of undefined
    at Object.formatCardNumber (formatter-b0b2372d.js:6)
    at usePaymentInputs.js:518
    at commitHookEffectListMount (react-dom.development.js:20573)
    at commitLifeCycles (react-dom.development.js:20634)
    at commitLayoutEffects (react-dom.development.js:23426)
    at HTMLUnknownElement.callCallback (react-dom.development.js:3945)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:3994)
    at invokeGuardedCallback (react-dom.development.js:4056)
    at commitRootImpl (react-dom.development.js:23151)
    at unstable_runWithPriority (scheduler.development.js:468)
    at runWithPriority$1 (react-dom.development.js:11276)
    at commitRoot (react-dom.development.js:22990)
    at performSyncWorkOnRoot (react-dom.development.js:22329)
    at react-dom.development.js:11327
    at unstable_runWithPriority (scheduler.development.js:468)
    at runWithPriority$1 (react-dom.development.js:11276)
    at flushSyncCallbackQueueImpl (react-dom.development.js:11322)
    at flushSyncCallbackQueue (react-dom.development.js:11309)
    at discreteUpdates$1 (react-dom.development.js:22420)
    at discreteUpdates (react-dom.development.js:3756)
    at dispatchDiscreteEvent (react-dom.development.js:5889)
@odragora
Copy link

odragora commented Aug 2, 2021

Would be awesome to have Ant Design compatibility.

@EncryptedCurse
Copy link
Author

EncryptedCurse commented Aug 2, 2021

@odragora I managed to come up with my own solution that may interest you. This is not a minimal working example and there's probably a better way to do it, but it works for my purpose. I used the card-validator library and my own custom icons (though you could swap them for something like Font Awesome without too much trouble).

Do note that it's definitely not as full-featured as react-payment-inputs, but it's capable of dynamically changing the card type icon as the number is typed and performing validation on it using the aforementioned library and the Form component built into Ant Design.

import { useState } from "react";
import * as cardValidator from "card-validator";

import visaIcon from "./payment/visa.png";
import mastercardInputIcon from "./payment/mastercard.png";
import maestroIcon from "./payment/maestro.png";
import amexIcon from "./payment/amex.png";

const cardIcons = {
	"visa": visaIcon,
	"american-express": amexIcon,
	"mastercard": mastercardInputIcon,
	"maestro": maestroIcon,
};

const cardExpirationDropdown = (type, text) => (
	<Tooltip title={text} placement="right" trigger={["hover"]}>
		<Form.Item name={["card", "expiration", type]} initialValue={text} rules={[{ required: true }]}>
			<Select>
				{cardExpirationData[type].map((value) => (
					<Select.Option key={value} value={value}>
						{value}
					</Select.Option>
				))}
			</Select>
		</Form.Item>
	</Tooltip>
);

export default function Example() {
	const [cardNumberSuffix, setCardNumberSuffix] = useState(null);

	...

	const cardFormGroup = () => {
		function validateCard(_, value) {
			const { card, isPotentiallyValid, isValid } = cardValidator.number(value);
			if (value) {
				setCardNumberSuffix(
					card && card in cardIcons ? (
						<img src={cardIcons[card.type]} title={card.niceType} width="32" />
					) : null
				);
				return (value.length >= 15 ? isValid : isPotentiallyValid)
					? Promise.resolve()
					: Promise.reject(new Error("Invalid"));
			} else {
				setCardNumberSuffix(null);
				return Promise.reject(new Error("Required"));
			}
		}

		const normalize = (value) => value.replace(/\D+/g, "");

		return (
			<>
				<Form.Item label="Name" name={["card", "name"]}>
					<Input />
				</Form.Item>
				<Form.Item
					label="Number"
					name={["card", "number"]}
					rules={[{ validator: validateCard }]}
					normalize={normalize}
				>
					<Input maxLength={16} suffix={<>{cardNumberSuffix}</>} />
				</Form.Item>
				<Form.Item
					label="CVV"
					name={["card", "cvv"]}
					rules={[{ required: true }]}
					normalize={normalize}
				>
					<Input maxLength={4} />
				</Form.Item>
				<Form.Item label="Expiration" required>
					<Row gutter={6}>
						<Col span={12}>{cardExpirationDropdown("month", "Month")}</Col>
						<Col span={12}>{cardExpirationDropdown("year", "Year")}</Col>
					</Row>
				</Form.Item>
			</>
		);
	};

	...

}

@odragora
Copy link

odragora commented Aug 2, 2021

Thank you very much @EncryptedCurse !
I think your code can save a lot of time for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants