Update selected item color in Pass menu
[ProtonMail-WebClient.git] / packages / pass / lib / validation / credit-card.ts
blobfd056d70f7623301729485f7df35f3e32b6421f1
1 import type { FormikErrors } from 'formik';
2 import { c } from 'ttag';
4 import { validateItemErrors } from './item';
6 export type CreditCardItemFormValues = {
7     shareId: string;
8     name: string;
9     cardholderName: string;
10     number: string;
11     expirationDate: string;
12     verificationNumber: string;
13     pin: string;
14     note: string;
17 /** Returns a tuple `[MM, YY|YYYY]` from a raw expiration date string.
18  * Supported date formats for extraction :
19  * - YYYY-MM
20  * - MMYY
21  * - MMYYYY
22  * - MM[seperator]YY
23  * - MM[seperator]YYYY */
24 const extractExpirationDateParts = (rawDate: string): [string, string] => {
25     /* account for YYYY-MM format */
26     if (/^(\d{4})-(\d{2})$/.test(rawDate)) return [rawDate.slice(-2), rawDate.slice(0, 4)];
28     const date = rawDate.replaceAll(/\/|-|\.|,|\s/g, '');
29     if (date.length === 4) return [date.slice(0, 2), date.slice(-2)];
30     if (date.length === 6) return [date.slice(0, 2), date.slice(-4)];
31     return ['', ''];
34 const isValidMonth = (maybeMonth: string): boolean => {
35     const month = parseInt(maybeMonth, 10);
36     return !isNaN(month) && month >= 1 && month <= 12;
38 const isValidYear = (maybeYear: string): boolean => {
39     const year = parseInt(maybeYear, 10);
40     return !isNaN(year) && year >= 0 && year <= 9999;
43 const isValidExpirationDate = (date: string): boolean => {
44     const [month, year] = extractExpirationDateParts(date);
45     return isValidMonth(month) && isValidYear(year);
48 export const formatExpirationDateMMYY = (date: string): string => {
49     const [month, year] = extractExpirationDateParts(date);
50     return isValidMonth(month) && isValidYear(year) ? `${month}${year.slice(-2)}` : '';
53 export const formatExpirationDateMMYYYY = (date: string): string => {
54     const [month, year] = extractExpirationDateParts(date);
56     if (isValidMonth(month) && isValidYear(year)) {
57         if (year.length === 4) return `${month}${year}`;
58         const yearBase = new Date().getFullYear().toString().slice(0, 2);
59         return `${month}${yearBase}${year}`;
60     }
62     return '';
65 /** Formats the provided date string as `YYYY-MM`.  */
66 export const formatExpirationDateYYYYMM = (date: string): string => {
67     const [month, year] = extractExpirationDateParts(date);
69     if (isValidMonth(month) && isValidYear(year)) {
70         if (year.length === 4) return `${year}-${month}`;
71         const yearBase = new Date().getFullYear().toString().slice(0, 2);
72         return `${yearBase}${year}-${month}`;
73     }
75     return '';
78 export const validateCreditCardForm = (values: CreditCardItemFormValues): FormikErrors<CreditCardItemFormValues> => {
79     const errors: FormikErrors<CreditCardItemFormValues> = validateItemErrors(values);
81     if (values.expirationDate.length && !isValidExpirationDate(values.expirationDate)) {
82         errors.expirationDate = c('Warning').t`Expiration Date is not in the format MM/YY`;
83     }
85     return { ...errors };