@autobusal/utilities 1.6.0 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/date.tsx +38 -1
- package/form.tsx +1 -1
- package/index.ts +5 -1
- package/package.json +1 -1
- package/serverErrors.ts +27 -0
package/date.tsx
CHANGED
|
@@ -102,4 +102,41 @@ export const futureDate = (days: number): string => {
|
|
|
102
102
|
dayAfter.setDate(today.getDate() + days);
|
|
103
103
|
|
|
104
104
|
return prepareDate(dayAfter);
|
|
105
|
-
};
|
|
105
|
+
};
|
|
106
|
+
/**
|
|
107
|
+
* A prepared d/m/Y date as the API's own Y-m-d.
|
|
108
|
+
*
|
|
109
|
+
* Claude - 2026-11-03. The calendar fields post d/m/Y, which the endpoints
|
|
110
|
+
* built for them validate with date_format:d/m/Y; the ones that take a plain
|
|
111
|
+
* `date` (a recorded payout, a settlement) read "31/12/2026" the American
|
|
112
|
+
* way and refuse it. Convert at the edge; anything that is not a prepared
|
|
113
|
+
* date is passed through untouched.
|
|
114
|
+
*/
|
|
115
|
+
export const isoDate = (prepared?: string | null): string => {
|
|
116
|
+
if (!isPreparedDate(prepared)) {
|
|
117
|
+
return prepared ?? '';
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const [ day, month, year ] = String(prepared).split('/');
|
|
121
|
+
|
|
122
|
+
return `${ year }-${ month }-${ day }`;
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* The other direction: a date input's yyyy-mm-dd as the d/m/Y most obtapi
|
|
127
|
+
* list filters parse (Carbon::createFromFormat('d/m/Y')).
|
|
128
|
+
*
|
|
129
|
+
* Claude - 2026-11-04 (dashboard simplification, wave 7). The shared Filters
|
|
130
|
+
* toolbar writes native date inputs (yyyy-mm-dd) into the URL; the invoice
|
|
131
|
+
* and API-log endpoints still read d/m/Y. Anything that is not yyyy-mm-dd -
|
|
132
|
+
* an old d/m/Y bookmark, an empty value - passes through untouched.
|
|
133
|
+
*/
|
|
134
|
+
export const dmyDate = (value?: string | null): string => {
|
|
135
|
+
const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(value ?? '');
|
|
136
|
+
|
|
137
|
+
if (match === null) {
|
|
138
|
+
return value ?? '';
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return `${ match[3] }/${ match[2] }/${ match[1] }`;
|
|
142
|
+
};
|
package/form.tsx
CHANGED
package/index.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { createDate, prepareDate, isPreparedDate, getFormattedShort, getDayParts, differenceYears, futureDate } from './date';
|
|
1
|
+
import { createDate, prepareDate, isPreparedDate, isoDate, dmyDate, getFormattedShort, getDayParts, differenceYears, futureDate } from './date';
|
|
2
2
|
import { Validate, Display } from './form';
|
|
3
|
+
import { serverErrors } from './serverErrors';
|
|
3
4
|
import { error, notify, success } from './notify';
|
|
4
5
|
import { getAllowed, getLanguages, getPayments } from './options';
|
|
5
6
|
import { getSex, getOptionsSex } from './passengers';
|
|
@@ -12,12 +13,15 @@ export {
|
|
|
12
13
|
sanitizeHtml,
|
|
13
14
|
Validate,
|
|
14
15
|
Display,
|
|
16
|
+
serverErrors,
|
|
15
17
|
error,
|
|
16
18
|
notify,
|
|
17
19
|
success,
|
|
18
20
|
createDate,
|
|
19
21
|
prepareDate,
|
|
20
22
|
isPreparedDate,
|
|
23
|
+
isoDate,
|
|
24
|
+
dmyDate,
|
|
21
25
|
getFormattedShort,
|
|
22
26
|
getDayParts,
|
|
23
27
|
differenceYears,
|
package/package.json
CHANGED
package/serverErrors.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The field errors of a failed save, keyed by field.
|
|
3
|
+
*
|
|
4
|
+
* Claude - 2026-11-03 (dashboard simplification, wave 0). Laravel answers a
|
|
5
|
+
* rejected form with 422 and `{ message, errors: { field: [text] } }`; the
|
|
6
|
+
* API client toasts the message and the fields stayed silent, so the admin
|
|
7
|
+
* had to guess which of forty inputs the server meant. Pure: an Axios error
|
|
8
|
+
* in, a flat map out (the first message per field - one is enough under an
|
|
9
|
+
* input), an empty map for anything that is not a 422. Viewer takes it as
|
|
10
|
+
* `errors` and puts each message under its own field.
|
|
11
|
+
*
|
|
12
|
+
* A nested Laravel key (title.en) is passed through unchanged -
|
|
13
|
+
* react-hook-form resolves dotted names itself.
|
|
14
|
+
*/
|
|
15
|
+
export const serverErrors = (error: unknown): Record<string, string> => {
|
|
16
|
+
const response = (error as { response?: { status?: number, data?: { errors?: Record<string, string[] | string> } } } | null | undefined)?.response;
|
|
17
|
+
|
|
18
|
+
if (response === undefined || response.status !== 422 || response.data?.errors === undefined || response.data.errors === null) {
|
|
19
|
+
return {};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return Object.fromEntries(
|
|
23
|
+
Object.entries(response.data.errors)
|
|
24
|
+
.map(([ field, messages ]) => [ field, Array.isArray(messages) ? String(messages[0] ?? '') : String(messages) ])
|
|
25
|
+
.filter(([ , message ]) => message !== '')
|
|
26
|
+
);
|
|
27
|
+
};
|