@autobusal/common 1.21.0 → 1.23.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/CHANGELOG.md +30 -0
- package/Calendar/Days.tsx +3 -0
- package/Calendar/Picker.tsx +6 -1
- package/Calendar/styles.ts +18 -0
- package/Calendar/utilities/settings.ts +41 -1
- package/index.ts +2 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,36 @@ All notable changes to `@autobusal/common` are documented here. This project fol
|
|
|
6
6
|
> Note: 1.10.0 through 1.15.1 were published without changelog entries. The
|
|
7
7
|
> gap is left as-is rather than reconstructed after the fact.
|
|
8
8
|
|
|
9
|
+
## 1.23.0
|
|
10
|
+
|
|
11
|
+
An unbookable date is inert, not merely faded.
|
|
12
|
+
|
|
13
|
+
It was dimmed and otherwise fully interactive: the pointer cursor and the
|
|
14
|
+
hover highlight still invited a click, and the click was answered with a
|
|
15
|
+
browser alert saying the date was invalid. The calendar offered a day, let
|
|
16
|
+
somebody reach for it, then told them off for taking the offer.
|
|
17
|
+
|
|
18
|
+
`pointer-events: none` removes it from the conversation entirely — no cursor
|
|
19
|
+
change, no hover, no click to refuse — alongside the `aria-disabled` and
|
|
20
|
+
`tabIndex=-1` already on the element. Unreachable by mouse, keyboard and
|
|
21
|
+
screen reader alike, and the alert is gone with it.
|
|
22
|
+
|
|
23
|
+
## 1.22.0
|
|
24
|
+
|
|
25
|
+
The booking calendar floors on the SERVER's date, not the browser's.
|
|
26
|
+
|
|
27
|
+
`new Date()` is the buyer's device clock, which says nothing about where they
|
|
28
|
+
are travelling. Somebody in Shanghai at 06:00 on the 5th, looking at an
|
|
29
|
+
Italian coach that does not leave until the evening of the 4th, had that day
|
|
30
|
+
greyed out — while the server would have sold them the seat quite happily. The
|
|
31
|
+
calendar was refusing a sale the API accepted.
|
|
32
|
+
|
|
33
|
+
It also makes the picker agree with the date strip beside it, which has always
|
|
34
|
+
been built server-side; the two used to disagree about which day came first.
|
|
35
|
+
|
|
36
|
+
A date of birth keeps the local clock, because that one genuinely is about the
|
|
37
|
+
person in front of the screen.
|
|
38
|
+
|
|
9
39
|
## 1.21.0
|
|
10
40
|
|
|
11
41
|
`reply` joins the table actions with its own icon and label. The operator
|
package/Calendar/Days.tsx
CHANGED
|
@@ -19,6 +19,9 @@ const Days = ({ type, value, selected, minDate, onSelected }: Props): JSX.Elemen
|
|
|
19
19
|
setCalendar(getCalendar(value));
|
|
20
20
|
}, [value]);
|
|
21
21
|
|
|
22
|
+
// Edited: Ferjolt Ozuni - Date: 2026-08-03
|
|
23
|
+
// Only used to mark which cell is "today" visually - the FLOOR comes from
|
|
24
|
+
// getLimits below, which for a booking picker follows the server.
|
|
22
25
|
const today = prepareDate(new Date());
|
|
23
26
|
|
|
24
27
|
const limits = getLimits(type);
|
package/Calendar/Picker.tsx
CHANGED
|
@@ -19,8 +19,13 @@ const Picker = ({ type, value, selected, minDate, t, onClick }: Props): (JSX.Ele
|
|
|
19
19
|
const [ prepared, setPrepared ] = useState<string>(value);
|
|
20
20
|
|
|
21
21
|
const onSelected = (prepared: string, disabled: boolean): void => {
|
|
22
|
+
// Edited: Ferjolt Ozuni - Date: 2026-08-03
|
|
23
|
+
// Silently, not with an alert. A disabled day is now inert in CSS as
|
|
24
|
+
// well (see Day in styles), so this can only be reached by something
|
|
25
|
+
// focusing the element programmatically - and a control that cannot be
|
|
26
|
+
// used should not interrupt somebody to say so.
|
|
22
27
|
if (disabled) {
|
|
23
|
-
return
|
|
28
|
+
return;
|
|
24
29
|
}
|
|
25
30
|
|
|
26
31
|
onClick(prepared);
|
package/Calendar/styles.ts
CHANGED
|
@@ -51,8 +51,26 @@ export const Day = styled.div<{
|
|
|
51
51
|
color: ${ props => props.theme.primary.normal };
|
|
52
52
|
` }
|
|
53
53
|
|
|
54
|
+
/**
|
|
55
|
+
* Edited: Ferjolt Ozuni - Date: 2026-08-03
|
|
56
|
+
*
|
|
57
|
+
* A date that cannot be booked is INERT, not merely faded.
|
|
58
|
+
*
|
|
59
|
+
* It was dimmed and otherwise fully interactive: the pointer cursor and
|
|
60
|
+
* the hover highlight still invited a click, and the click was answered
|
|
61
|
+
* with a browser alert saying the date was invalid. So the calendar
|
|
62
|
+
* offered a day, let somebody reach for it, and then told them off for
|
|
63
|
+
* taking the offer.
|
|
64
|
+
*
|
|
65
|
+
* pointer-events: none removes it from the conversation entirely - no
|
|
66
|
+
* cursor change, no hover, no click to refuse. Together with the
|
|
67
|
+
* aria-disabled and tabIndex=-1 already on the element, it is unreachable
|
|
68
|
+
* by mouse, keyboard and screen reader alike.
|
|
69
|
+
*/
|
|
54
70
|
${ props => props.$disabled === true && css`
|
|
55
71
|
opacity: .3;
|
|
72
|
+
cursor: default;
|
|
73
|
+
pointer-events: none;
|
|
56
74
|
` }
|
|
57
75
|
|
|
58
76
|
${ props => props.$selected && css`
|
|
@@ -1,8 +1,48 @@
|
|
|
1
1
|
import { createDate } from '@autobusal/utilities';
|
|
2
2
|
import { CalendarLimit, DatesLimit, CalendarData } from '../types';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* The earliest bookable date, as the server reckons it.
|
|
6
|
+
*
|
|
7
|
+
* Edited: Ferjolt Ozuni - Date: 2026-08-03
|
|
8
|
+
*
|
|
9
|
+
* Set once at startup from the settings payload. A module-level value rather
|
|
10
|
+
* than a prop threaded through four components: every calendar in the app
|
|
11
|
+
* wants the same answer, and the alternative was passing it through Picker
|
|
12
|
+
* and Days to reach the one function that needs it.
|
|
13
|
+
*/
|
|
14
|
+
let serverToday: Date | null = null;
|
|
15
|
+
|
|
16
|
+
export const setServerToday = (value?: string): void => {
|
|
17
|
+
if (!value) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const [ day, month, year ] = value.split('/').map(Number);
|
|
22
|
+
|
|
23
|
+
if (!day || !month || !year) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
serverToday = new Date(year, month - 1, day, 0, 0, 0, 0);
|
|
28
|
+
};
|
|
29
|
+
|
|
4
30
|
export const getLimits = (type: ('picker' | 'dob' | 'date')): CalendarLimit => {
|
|
5
|
-
|
|
31
|
+
// Edited: Ferjolt Ozuni - Date: 2026-08-03
|
|
32
|
+
//
|
|
33
|
+
// The BOOKING floor comes from the server; a date of birth does not.
|
|
34
|
+
//
|
|
35
|
+
// `new Date()` is the buyer's device clock, which has nothing to do with
|
|
36
|
+
// where they are travelling: somebody in Shanghai at 06:00 on the 5th
|
|
37
|
+
// looking at an Italian coach leaving on the evening of the 4th had that
|
|
38
|
+
// day greyed out, because their phone said it was past. The server would
|
|
39
|
+
// have sold them the seat; the calendar would not let them ask.
|
|
40
|
+
//
|
|
41
|
+
// A date of birth genuinely is about the person in front of the screen,
|
|
42
|
+
// so that one keeps the local clock.
|
|
43
|
+
const today = (type === 'picker' && serverToday)
|
|
44
|
+
? new Date(serverToday.getTime())
|
|
45
|
+
: new Date();
|
|
6
46
|
|
|
7
47
|
today.setHours(0, 0, 0, 0);
|
|
8
48
|
|
package/index.ts
CHANGED
|
@@ -26,6 +26,7 @@ import Paragraph from './Loading/Paragraph';
|
|
|
26
26
|
import Passengers from './Passengers/Passengers';
|
|
27
27
|
import Password from './Password/Password';
|
|
28
28
|
import Rating from './Rating/Rating';
|
|
29
|
+
import { setServerToday } from './Calendar/utilities/settings';
|
|
29
30
|
import Policy from './Policy/Policy';
|
|
30
31
|
import Report from './Report/Report';
|
|
31
32
|
import RouteFeature from './RouteFeature/RouteFeature';
|
|
@@ -75,6 +76,7 @@ export {
|
|
|
75
76
|
Passengers,
|
|
76
77
|
Password,
|
|
77
78
|
Rating,
|
|
79
|
+
setServerToday,
|
|
78
80
|
Policy,
|
|
79
81
|
Report,
|
|
80
82
|
RouteFeature,
|