@autobusal/common 1.33.12 → 1.33.14

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 CHANGED
@@ -1,5 +1,15 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.33.14 (2026-08-26)
4
+
5
+ - ChooseSeat: seat-selection add-on mode - `optional` + `fee` props; unpicked state shows the free-auto note, a made choice gets a back-to-automatic control. Default behaviour (required free pick) unchanged.
6
+
7
+ ## 1.33.13
8
+
9
+ ### Fixed
10
+
11
+ - **`RouteItem` no longer advertises "From 0.00"**: zero-fare rows are unpriced legs search never sells, so they no longer count toward the cheapest-of figure. (Audit RT-11b.)
12
+
3
13
  ## 1.33.12
4
14
 
5
15
  ### Added
@@ -25,8 +25,12 @@ const RouteItem = ({ type, route, t }: Props): JSX.Element => {
25
25
  // reformatting `adult` itself - the server already applied this label's
26
26
  // currency symbol/decimal convention, and re-deriving that here would
27
27
  // risk disagreeing with every other price on the site.
28
- const cheapest = route.prices.length > 0
29
- ? route.prices.reduce((min, price) => (price.adult < min.adult ? price : min))
28
+ // Claude - 2026-08-22 (audit finding RT-11b): zero-fare rows are
29
+ // unpriced legs search never sells - see RouteView's matching note.
30
+ const priced = route.prices.filter(price => price.adult > 0);
31
+
32
+ const cheapest = priced.length > 0
33
+ ? priced.reduce((min, price) => (price.adult < min.adult ? price : min))
30
34
  : null;
31
35
 
32
36
  return (
@@ -6,7 +6,7 @@ import { MdEventSeat } from 'react-icons/md';
6
6
  import { Validate } from '@autobusal/utilities';
7
7
  import Unavailable from './Unavailable';
8
8
  import Preview from './Preview';
9
- import { ButtonSeat } from './styles';
9
+ import { ButtonSeat, AutoNote, ClearChoice } from './styles';
10
10
  import { OccupiedData } from '@autobusal/providers/types/buses';
11
11
  import { PersonData } from '@autobusal/providers/types/persons';
12
12
 
@@ -17,12 +17,29 @@ interface Props {
17
17
  bus: OccupiedData
18
18
  picked: number[]
19
19
  validation: string
20
+ /**
21
+ * Edited: Claude - Date: 2026-08-26
22
+ *
23
+ * The seat-selection ADD-ON mode. When the brand sells seat choice
24
+ * (settings addons.seats.available), picking becomes optional: the
25
+ * unpicked state is honest ("a seat is assigned automatically, free"),
26
+ * the call to action carries the fee, and a made choice can be taken
27
+ * back. When absent, this component behaves exactly as it always has -
28
+ * a required, free pick - which is what every brand still on the old
29
+ * model gets.
30
+ *
31
+ * `fee` is the DISPLAY string ("1.5 EUR"), already formatted by the
32
+ * caller; the figure actually charged is the server's own
33
+ * (obtapi Orders\Make\Addons), never this.
34
+ */
35
+ optional?: boolean
36
+ fee?: string
20
37
  t: TFunction<'common'>
21
38
  refs: UseFormRegister<PersonData | any>
22
39
  onUpdate: (name: string, type: ('from' | 'to'), value: number, previous: number) => void
23
40
  }
24
41
 
25
- const ChooseSeat = ({ name, type, defaultValue, bus, picked, validation, t, refs, onUpdate }: Props): JSX.Element => {
42
+ const ChooseSeat = ({ name, type, defaultValue, bus, picked, validation, optional, fee, t, refs, onUpdate }: Props): JSX.Element => {
26
43
  const [ show, setShow ] = useState<boolean>(false);
27
44
  const [ selected, setSelected ] = useState<number>(defaultValue ?? 0);
28
45
 
@@ -41,14 +58,35 @@ const ChooseSeat = ({ name, type, defaultValue, bus, picked, validation, t, refs
41
58
  }
42
59
  };
43
60
 
61
+ // back to the free automatic assignment - the parent drops the seat from
62
+ // its picked list and the form value goes to 0, which the order submission
63
+ // strips entirely (the API auto-assigns absent fields)
64
+ const onClear = (): void => {
65
+ onUpdate(name, type, 0, selected);
66
+
67
+ setSelected(0);
68
+ };
69
+
44
70
  return (
45
71
  <div>
46
72
  <ButtonSeat type="button" $selected={ selected > 0 } onClick={ () => setShow(true) }>
47
73
  { selected > 0
48
74
  ? <><FaCheck /> { t('seats.chosen', { ns: 'common', number: selected }) }</>
49
- : <><MdEventSeat /> { t('seats.choose', { ns: 'common' }) }</> }
75
+ : <><MdEventSeat /> { (optional && fee)
76
+ ? t('seats.choose_fee', { ns: 'common', price: fee })
77
+ : t('seats.choose', { ns: 'common' }) }</> }
50
78
  </ButtonSeat>
51
79
 
80
+ { (optional && selected === 0) && (
81
+ <AutoNote>{ t('seats.auto', { ns: 'common' }) }</AutoNote>
82
+ ) }
83
+
84
+ { (optional && selected > 0) && (
85
+ <ClearChoice type="button" onClick={ onClear }>
86
+ { t('seats.clear', { ns: 'common' }) }
87
+ </ClearChoice>
88
+ ) }
89
+
52
90
  { (show && bus.bus !== undefined) && (
53
91
  <Preview
54
92
  bus={ bus.bus }
@@ -66,4 +104,4 @@ const ChooseSeat = ({ name, type, defaultValue, bus, picked, validation, t, refs
66
104
  );
67
105
  };
68
106
 
69
- export default ChooseSeat;
107
+ export default ChooseSeat;
package/Seats/styles.ts CHANGED
@@ -25,6 +25,29 @@ export const ButtonSeat = styled.button<{ $selected: boolean }>`
25
25
  ` }
26
26
  `;
27
27
 
28
+ // Edited: Claude - Date: 2026-08-26 - the two states of the seat-selection
29
+ // ADD-ON mode (see ChooseSeat): the honest "you get a seat anyway, free"
30
+ // note under an unpicked button, and the way back out of a paid choice.
31
+ export const AutoNote = styled.div`
32
+ margin-top: 3px;
33
+ font-size: ${ props => props.theme.size.xs };
34
+ color: ${ props => props.theme.font.faded };
35
+ `;
36
+
37
+ export const ClearChoice = styled.button`
38
+ margin-top: 3px;
39
+ padding: 0;
40
+ font-size: ${ props => props.theme.size.xs };
41
+ color: ${ props => props.theme.font.faded };
42
+ background: none;
43
+ text-decoration: underline;
44
+ transition: all 0.3s ease;
45
+
46
+ &:hover {
47
+ color: ${ props => props.theme.font.error };
48
+ }
49
+ `;
50
+
28
51
  export const Seats = styled.div`
29
52
  overflow-x: auto;
30
53
  `;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autobusal/common",
3
- "version": "1.33.12",
3
+ "version": "1.33.14",
4
4
  "author": "Ferjolt Ozuni",
5
5
  "type": "module",
6
6
  "main": "index.ts"