@pi-spi/app 2.0.0 → 2.1.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.
Files changed (146) hide show
  1. package/lib/module/core/api.js +14 -5
  2. package/lib/module/core/api.js.map +1 -1
  3. package/lib/module/l10n/app_localizations.js.map +1 -1
  4. package/lib/module/l10n/app_localizations_en.js +8 -0
  5. package/lib/module/l10n/app_localizations_en.js.map +1 -1
  6. package/lib/module/l10n/app_localizations_fr.js +8 -0
  7. package/lib/module/l10n/app_localizations_fr.js.map +1 -1
  8. package/lib/module/l10n/app_localizations_pt.js +8 -0
  9. package/lib/module/l10n/app_localizations_pt.js.map +1 -1
  10. package/lib/module/modules/categorie/presentation/pages/categorie_edit_icon_btn.js +25 -35
  11. package/lib/module/modules/categorie/presentation/pages/categorie_edit_icon_btn.js.map +1 -1
  12. package/lib/module/modules/profile/presentation/pages/profile_page_avatar.js +6 -28
  13. package/lib/module/modules/profile/presentation/pages/profile_page_avatar.js.map +1 -1
  14. package/lib/module/modules/profile/presentation/pages/profile_page_contacts.js +0 -1
  15. package/lib/module/modules/profile/presentation/pages/profile_page_contacts.js.map +1 -1
  16. package/lib/module/modules/profile/presentation/pages/profile_page_contacts_actions.js +122 -162
  17. package/lib/module/modules/profile/presentation/pages/profile_page_contacts_actions.js.map +1 -1
  18. package/lib/module/modules/qrcode/presentation/pages/qrcode_alias_page.js +0 -1
  19. package/lib/module/modules/qrcode/presentation/pages/qrcode_alias_page.js.map +1 -1
  20. package/lib/module/modules/qrcode/presentation/pages/qrcode_alias_page_share.js +26 -38
  21. package/lib/module/modules/qrcode/presentation/pages/qrcode_alias_page_share.js.map +1 -1
  22. package/lib/module/modules/subscription/presentation/pages/subscription_details/subscription_details_page.js +0 -1
  23. package/lib/module/modules/subscription/presentation/pages/subscription_details/subscription_details_page.js.map +1 -1
  24. package/lib/module/modules/subscription/presentation/pages/subscription_details/subscription_details_page_actions.js +0 -1
  25. package/lib/module/modules/subscription/presentation/pages/subscription_details/subscription_details_page_actions.js.map +1 -1
  26. package/lib/module/modules/subscription/presentation/pages/subscription_details/subscription_details_page_note_sheet.js +38 -93
  27. package/lib/module/modules/subscription/presentation/pages/subscription_details/subscription_details_page_note_sheet.js.map +1 -1
  28. package/lib/module/modules/subscription/presentation/pages/subscription_list/subscription_list_empty_widget.js +0 -1
  29. package/lib/module/modules/subscription/presentation/pages/subscription_list/subscription_list_empty_widget.js.map +1 -1
  30. package/lib/module/modules/subscription/presentation/pages/subscription_list/subscription_list_widget.js +0 -1
  31. package/lib/module/modules/subscription/presentation/pages/subscription_list/subscription_list_widget.js.map +1 -1
  32. package/lib/module/modules/subscription/presentation/pages/subscription_menu_widget.js +23 -42
  33. package/lib/module/modules/subscription/presentation/pages/subscription_menu_widget.js.map +1 -1
  34. package/lib/module/modules/transactions/infra/transaction_output_remote.js +2 -1
  35. package/lib/module/modules/transactions/infra/transaction_output_remote.js.map +1 -1
  36. package/lib/module/modules/transactions/presentation/pages/transaction_details/transaction_details_page_actions.js +0 -1
  37. package/lib/module/modules/transactions/presentation/pages/transaction_details/transaction_details_page_actions.js.map +1 -1
  38. package/lib/module/modules/transactions/presentation/pages/transaction_details/transaction_details_page_actions_cancel.js +34 -61
  39. package/lib/module/modules/transactions/presentation/pages/transaction_details/transaction_details_page_actions_cancel.js.map +1 -1
  40. package/lib/module/modules/transactions/presentation/pages/transaction_details/transaction_details_page_actions_return.js +49 -62
  41. package/lib/module/modules/transactions/presentation/pages/transaction_details/transaction_details_page_actions_return.js.map +1 -1
  42. package/lib/module/modules/transactions/presentation/pages/transaction_details/transaction_details_page_ticket.js +68 -88
  43. package/lib/module/modules/transactions/presentation/pages/transaction_details/transaction_details_page_ticket.js.map +1 -1
  44. package/lib/module/modules/transactions/presentation/pages/transaction_form/transaction_form_input_pays.js +77 -0
  45. package/lib/module/modules/transactions/presentation/pages/transaction_form/transaction_form_input_pays.js.map +1 -0
  46. package/lib/module/modules/transactions/presentation/pages/transaction_form/transaction_form_input_psp.js +49 -155
  47. package/lib/module/modules/transactions/presentation/pages/transaction_form/transaction_form_input_psp.js.map +1 -1
  48. package/lib/module/modules/transactions/presentation/pages/transaction_form/transaction_form_page_othr.js +8 -28
  49. package/lib/module/modules/transactions/presentation/pages/transaction_form/transaction_form_page_othr.js.map +1 -1
  50. package/lib/module/modules/transactions/presentation/pages/transaction_form/transaction_form_page_verification.js +0 -1
  51. package/lib/module/modules/transactions/presentation/pages/transaction_form/transaction_form_page_verification.js.map +1 -1
  52. package/lib/module/modules/transactions/presentation/pages/transaction_recents/transaction_recents_nombre_widget.js +50 -42
  53. package/lib/module/modules/transactions/presentation/pages/transaction_recents/transaction_recents_nombre_widget.js.map +1 -1
  54. package/lib/module/modules/transactions/presentation/pages/transaction_recents/transaction_recents_widget.js +0 -1
  55. package/lib/module/modules/transactions/presentation/pages/transaction_recents/transaction_recents_widget.js.map +1 -1
  56. package/lib/module/modules/transactions/presentation/pages/transaction_rtp/transaction_rtp_page_actions.js +0 -1
  57. package/lib/module/modules/transactions/presentation/pages/transaction_rtp/transaction_rtp_page_actions.js.map +1 -1
  58. package/lib/module/modules/transactions/presentation/pages/transaction_rtp/transaction_rtp_page_actions_reject.js +37 -67
  59. package/lib/module/modules/transactions/presentation/pages/transaction_rtp/transaction_rtp_page_actions_reject.js.map +1 -1
  60. package/lib/module/shared/widgets/confirm_action_sheet_widget.js +34 -67
  61. package/lib/module/shared/widgets/confirm_action_sheet_widget.js.map +1 -1
  62. package/lib/module/shared/widgets/image_select_widget.js +43 -107
  63. package/lib/module/shared/widgets/image_select_widget.js.map +1 -1
  64. package/lib/module/shared/widgets/notification_dialog.js +25 -35
  65. package/lib/module/shared/widgets/notification_dialog.js.map +1 -1
  66. package/lib/module/shared/widgets/selection.js +381 -5
  67. package/lib/module/shared/widgets/selection.js.map +1 -1
  68. package/lib/typescript/src/core/api.d.ts +6 -0
  69. package/lib/typescript/src/core/api.d.ts.map +1 -1
  70. package/lib/typescript/src/l10n/app_localizations.d.ts +16 -0
  71. package/lib/typescript/src/l10n/app_localizations.d.ts.map +1 -1
  72. package/lib/typescript/src/l10n/app_localizations_en.d.ts.map +1 -1
  73. package/lib/typescript/src/l10n/app_localizations_fr.d.ts.map +1 -1
  74. package/lib/typescript/src/l10n/app_localizations_pt.d.ts.map +1 -1
  75. package/lib/typescript/src/modules/categorie/presentation/pages/categorie_edit_icon_btn.d.ts.map +1 -1
  76. package/lib/typescript/src/modules/profile/presentation/pages/profile_page_avatar.d.ts.map +1 -1
  77. package/lib/typescript/src/modules/profile/presentation/pages/profile_page_contacts.d.ts.map +1 -1
  78. package/lib/typescript/src/modules/profile/presentation/pages/profile_page_contacts_actions.d.ts.map +1 -1
  79. package/lib/typescript/src/modules/qrcode/presentation/pages/qrcode_alias_page.d.ts.map +1 -1
  80. package/lib/typescript/src/modules/qrcode/presentation/pages/qrcode_alias_page_share.d.ts.map +1 -1
  81. package/lib/typescript/src/modules/subscription/presentation/pages/subscription_details/subscription_details_page.d.ts.map +1 -1
  82. package/lib/typescript/src/modules/subscription/presentation/pages/subscription_details/subscription_details_page_actions.d.ts.map +1 -1
  83. package/lib/typescript/src/modules/subscription/presentation/pages/subscription_details/subscription_details_page_note_sheet.d.ts +2 -2
  84. package/lib/typescript/src/modules/subscription/presentation/pages/subscription_details/subscription_details_page_note_sheet.d.ts.map +1 -1
  85. package/lib/typescript/src/modules/subscription/presentation/pages/subscription_menu_widget.d.ts.map +1 -1
  86. package/lib/typescript/src/modules/transactions/infra/transaction_output_remote.d.ts.map +1 -1
  87. package/lib/typescript/src/modules/transactions/presentation/pages/transaction_details/transaction_details_page_actions.d.ts.map +1 -1
  88. package/lib/typescript/src/modules/transactions/presentation/pages/transaction_details/transaction_details_page_actions_cancel.d.ts.map +1 -1
  89. package/lib/typescript/src/modules/transactions/presentation/pages/transaction_details/transaction_details_page_actions_return.d.ts.map +1 -1
  90. package/lib/typescript/src/modules/transactions/presentation/pages/transaction_form/transaction_form_input_pays.d.ts +17 -0
  91. package/lib/typescript/src/modules/transactions/presentation/pages/transaction_form/transaction_form_input_pays.d.ts.map +1 -0
  92. package/lib/typescript/src/modules/transactions/presentation/pages/transaction_form/transaction_form_input_psp.d.ts +6 -2
  93. package/lib/typescript/src/modules/transactions/presentation/pages/transaction_form/transaction_form_input_psp.d.ts.map +1 -1
  94. package/lib/typescript/src/modules/transactions/presentation/pages/transaction_form/transaction_form_page_othr.d.ts.map +1 -1
  95. package/lib/typescript/src/modules/transactions/presentation/pages/transaction_form/transaction_form_page_verification.d.ts.map +1 -1
  96. package/lib/typescript/src/modules/transactions/presentation/pages/transaction_recents/transaction_recents_nombre_widget.d.ts.map +1 -1
  97. package/lib/typescript/src/modules/transactions/presentation/pages/transaction_rtp/transaction_rtp_page_actions.d.ts.map +1 -1
  98. package/lib/typescript/src/modules/transactions/presentation/pages/transaction_rtp/transaction_rtp_page_actions_reject.d.ts.map +1 -1
  99. package/lib/typescript/src/shared/widgets/confirm_action_sheet_widget.d.ts +4 -1
  100. package/lib/typescript/src/shared/widgets/confirm_action_sheet_widget.d.ts.map +1 -1
  101. package/lib/typescript/src/shared/widgets/image_select_widget.d.ts +6 -4
  102. package/lib/typescript/src/shared/widgets/image_select_widget.d.ts.map +1 -1
  103. package/lib/typescript/src/shared/widgets/notification_dialog.d.ts +2 -2
  104. package/lib/typescript/src/shared/widgets/notification_dialog.d.ts.map +1 -1
  105. package/lib/typescript/src/shared/widgets/selection.d.ts +69 -2
  106. package/lib/typescript/src/shared/widgets/selection.d.ts.map +1 -1
  107. package/package.json +1 -1
  108. package/src/core/api.ts +11 -2
  109. package/src/l10n/app_localizations.ts +16 -0
  110. package/src/l10n/app_localizations_en.ts +8 -0
  111. package/src/l10n/app_localizations_fr.ts +8 -0
  112. package/src/l10n/app_localizations_pt.ts +8 -0
  113. package/src/modules/categorie/presentation/pages/categorie_edit_icon_btn.tsx +25 -27
  114. package/src/modules/profile/presentation/pages/profile_page_avatar.tsx +6 -12
  115. package/src/modules/profile/presentation/pages/profile_page_contacts.tsx +0 -1
  116. package/src/modules/profile/presentation/pages/profile_page_contacts_actions.tsx +111 -117
  117. package/src/modules/qrcode/presentation/pages/qrcode_alias_page.tsx +0 -1
  118. package/src/modules/qrcode/presentation/pages/qrcode_alias_page_share.tsx +32 -40
  119. package/src/modules/subscription/presentation/pages/subscription_details/subscription_details_page.tsx +0 -1
  120. package/src/modules/subscription/presentation/pages/subscription_details/subscription_details_page_actions.tsx +0 -1
  121. package/src/modules/subscription/presentation/pages/subscription_details/subscription_details_page_note_sheet.tsx +20 -59
  122. package/src/modules/subscription/presentation/pages/subscription_list/subscription_list_empty_widget.tsx +1 -1
  123. package/src/modules/subscription/presentation/pages/subscription_list/subscription_list_widget.tsx +1 -1
  124. package/src/modules/subscription/presentation/pages/subscription_menu_widget.tsx +25 -39
  125. package/src/modules/transactions/infra/transaction_output_remote.ts +6 -1
  126. package/src/modules/transactions/presentation/pages/transaction_details/transaction_details_page_actions.tsx +0 -1
  127. package/src/modules/transactions/presentation/pages/transaction_details/transaction_details_page_actions_cancel.tsx +39 -41
  128. package/src/modules/transactions/presentation/pages/transaction_details/transaction_details_page_actions_return.tsx +41 -46
  129. package/src/modules/transactions/presentation/pages/transaction_details/transaction_details_page_ticket.tsx +46 -40
  130. package/src/modules/transactions/presentation/pages/transaction_form/transaction_form_input_pays.tsx +92 -0
  131. package/src/modules/transactions/presentation/pages/transaction_form/transaction_form_input_psp.tsx +48 -94
  132. package/src/modules/transactions/presentation/pages/transaction_form/transaction_form_page_othr.tsx +4 -17
  133. package/src/modules/transactions/presentation/pages/transaction_form/transaction_form_page_verification.tsx +0 -1
  134. package/src/modules/transactions/presentation/pages/transaction_recents/transaction_recents_nombre_widget.tsx +49 -42
  135. package/src/modules/transactions/presentation/pages/transaction_recents/transaction_recents_widget.tsx +1 -1
  136. package/src/modules/transactions/presentation/pages/transaction_rtp/transaction_rtp_page_actions.tsx +0 -1
  137. package/src/modules/transactions/presentation/pages/transaction_rtp/transaction_rtp_page_actions_reject.tsx +47 -48
  138. package/src/shared/widgets/confirm_action_sheet_widget.tsx +30 -34
  139. package/src/shared/widgets/image_select_widget.tsx +46 -61
  140. package/src/shared/widgets/notification_dialog.tsx +66 -70
  141. package/src/shared/widgets/selection.tsx +292 -4
  142. package/lib/module/modules/transactions/presentation/pages/transaction_details/sheet_box.js +0 -47
  143. package/lib/module/modules/transactions/presentation/pages/transaction_details/sheet_box.js.map +0 -1
  144. package/lib/typescript/src/modules/transactions/presentation/pages/transaction_details/sheet_box.d.ts +0 -10
  145. package/lib/typescript/src/modules/transactions/presentation/pages/transaction_details/sheet_box.d.ts.map +0 -1
  146. package/src/modules/transactions/presentation/pages/transaction_details/sheet_box.tsx +0 -30
@@ -1,11 +1,9 @@
1
- import { ScrollView, Share, StyleSheet, Text, useWindowDimensions, View } from 'react-native';
2
- import { useSafeAreaInsets } from 'react-native-safe-area-context';
1
+ import { ScrollView, Share, StyleSheet, View } from 'react-native';
3
2
 
4
3
  import { Images } from '../../../../core/assets';
5
4
  import { AppRouter, useAppRouter } from '../../../../core/router';
6
- import { useTheme } from '../../../../core/theme';
7
5
  import { useAppLocalizations } from '../../../../l10n/localizations';
8
- import { MenuActionItem, MenuActionsWidget } from '../../../../shared/widgets/menu_actions_widget';
6
+ import { SbSelectionOption, SelectionSheet } from '../../../../shared/widgets/selection';
9
7
 
10
8
  /** Feuille « Partager » : le QR code (image) ou l'alias (texte). */
11
9
  export function QrcodeAliasPageShare({
@@ -18,47 +16,41 @@ export function QrcodeAliasPageShare({
18
16
  shareQrcode: () => void;
19
17
  }) {
20
18
  const traductions = useAppLocalizations();
21
- const theme = useTheme();
22
19
  const router = useAppRouter();
23
- const insets = useSafeAreaInsets();
24
- const { height } = useWindowDimensions();
25
20
 
26
21
  return (
27
- <View style={[styles.box, { backgroundColor: theme.colorScheme.surface, maxHeight: height * 0.6 }]}>
28
- <ScrollView contentContainerStyle={[styles.content, { paddingBottom: 20 + insets.bottom }]}>
29
- <Text style={theme.textTheme.headlineMedium}>{traductions.qrcodePagePartageTitle}</Text>
30
- <View style={styles.gap20} />
31
- <MenuActionsWidget
32
- items={[
33
- new MenuActionItem(
34
- Images.homeFooterQrcode,
35
- traductions.qrcodePagePartageQrCodeTitle,
36
- traductions.qrcodePagePartageQrCodeSubTitle,
37
- () => {
38
- AppRouter.pop(router);
39
- shareQrcode();
40
- },
41
- { iconSize: 20 },
42
- ),
43
- new MenuActionItem(
44
- Images.iconsCircleUser,
45
- traductions.qrcodePagePartageAliasTitle,
46
- traductions.qrcodePagePartageAliasSubTitle,
47
- () => {
48
- AppRouter.pop(router);
49
- void Share.share({ title: traductions.qrcodePagePartageAliasMessage(username), message: alias });
50
- },
51
- { iconSize: 20 },
52
- ),
53
- ]}
54
- />
55
- </ScrollView>
56
- </View>
22
+ <SelectionSheet
23
+ titre={traductions.qrcodePagePartageTitle}
24
+ contenu={
25
+ <ScrollView bounces={false} contentContainerStyle={styles.content}>
26
+ {/* Partager le QR code */}
27
+ <SbSelectionOption
28
+ image={Images.homeFooterQrcode}
29
+ titre={traductions.qrcodePagePartageQrCodeTitle}
30
+ sousTitre={traductions.qrcodePagePartageQrCodeSubTitle}
31
+ onPress={() => {
32
+ AppRouter.pop(router);
33
+ shareQrcode();
34
+ }}
35
+ />
36
+ <View style={styles.gap10} />
37
+ {/* Partager l'alias */}
38
+ <SbSelectionOption
39
+ image={Images.iconsCircleUser}
40
+ titre={traductions.qrcodePagePartageAliasTitle}
41
+ sousTitre={traductions.qrcodePagePartageAliasSubTitle}
42
+ onPress={() => {
43
+ AppRouter.pop(router);
44
+ void Share.share({ title: traductions.qrcodePagePartageAliasMessage(username), message: alias });
45
+ }}
46
+ />
47
+ </ScrollView>
48
+ }
49
+ />
57
50
  );
58
51
  }
59
52
 
60
53
  const styles = StyleSheet.create({
61
- box: { borderRadius: 20, overflow: 'hidden' },
62
- content: { padding: 20 },
63
- gap20: { height: 20 },
54
+ content: { paddingHorizontal: 20, paddingTop: 8, paddingBottom: 16 },
55
+ gap10: { height: 10 },
64
56
  });
@@ -116,7 +116,6 @@ export function SubscriptionDetailsPage({
116
116
 
117
117
  const editNote = async () => {
118
118
  const value = await showModalBottomSheet<string>(router, {
119
- themed: true,
120
119
  builder: () => <SubscriptionDetailsPageNoteSheet note={subscription.motif} />,
121
120
  });
122
121
  if (value != null && value !== subscription.motif) bloc.add(new SubscriptionDetailsNoteUpdateEvent(value));
@@ -25,7 +25,6 @@ import { SubscriptionAction, SubscriptionDetailsPageActionsConfirm } from './sub
25
25
 
26
26
  function confirm(router: SdkRouter, action: SubscriptionAction, subscription: Subscription): Promise<boolean | undefined> {
27
27
  return showModalBottomSheet<boolean>(router, {
28
- themed: true,
29
28
  builder: () => <SubscriptionDetailsPageActionsConfirm action={action} isSubcription={subscription.frequence != null} />,
30
29
  });
31
30
  }
@@ -1,13 +1,11 @@
1
- import { useEffect, useRef, useState } from 'react';
2
- import { Animated, Easing, Keyboard, Pressable, ScrollView, StyleSheet, Text, useWindowDimensions, View } from 'react-native';
3
- import { useSafeAreaInsets } from 'react-native-safe-area-context';
1
+ import { useState } from 'react';
2
+ import { Keyboard, ScrollView, StyleSheet, View } from 'react-native';
4
3
 
5
4
  import { AppRouter, useAppRouter } from '../../../../../core/router';
6
- import { useTheme } from '../../../../../core/theme';
7
5
  import { useAppLocalizations } from '../../../../../l10n/localizations';
8
6
  import { ElevatedButton } from '../../../../../shared/material/buttons';
9
7
  import { CustomTextMultipleInput } from '../../../../../shared/widgets/input_text_multiple';
10
- import { MyPageContainer } from '../../../../../shared/widgets/my_page_container';
8
+ import { SelectionSheet } from '../../../../../shared/widgets/selection';
11
9
  import {
12
10
  TransactionSendCommandMotif,
13
11
  TransactionSendCommandMotifError,
@@ -15,35 +13,15 @@ import {
15
13
 
16
14
  /**
17
15
  * Modifier la note de l'abonnement (feuille du bas, se ferme avec la
18
- * nouvelle note). Comme le `AnimatedContainer` Flutter, la feuille prend
19
- * 70 % de l'écran quand le champ a le focus, sa hauteur naturelle sinon.
16
+ * nouvelle note). La note défile, Enregistrer reste visible au-dessus du
17
+ * clavier.
20
18
  */
21
19
  export function SubscriptionDetailsPageNoteSheet({ note }: { note?: string | null }) {
22
20
  const traductions = useAppLocalizations();
23
- const theme = useTheme();
24
21
  const router = useAppRouter();
25
- const insets = useSafeAreaInsets();
26
- const { height: screenHeight } = useWindowDimensions();
27
- const maxHeight = screenHeight * 0.7;
28
22
 
29
23
  const [command] = useState(() => new TransactionSendCommandMotif({ value: note ?? undefined }));
30
24
  const [, setVersion] = useState(0);
31
- const [focused, setFocused] = useState(false);
32
- const [contentHeight, setContentHeight] = useState<number | null>(null);
33
- const height = useRef(new Animated.Value(0)).current;
34
- const measured = useRef(false);
35
-
36
- const naturalHeight = contentHeight == null ? 0 : Math.min(contentHeight, maxHeight);
37
- useEffect(() => {
38
- if (contentHeight == null) return;
39
- const target = focused ? maxHeight : naturalHeight;
40
- if (!measured.current) {
41
- measured.current = true;
42
- height.setValue(target);
43
- return;
44
- }
45
- Animated.timing(height, { toValue: target, duration: 300, easing: Easing.inOut(Easing.ease), useNativeDriver: false }).start();
46
- }, [focused, contentHeight, naturalHeight, maxHeight, height]);
47
25
 
48
26
  const canSave = command.value != null && command.value.length > 0 && command.isValid() && command.value !== note;
49
27
 
@@ -53,52 +31,35 @@ export function SubscriptionDetailsPageNoteSheet({ note }: { note?: string | nul
53
31
  };
54
32
 
55
33
  return (
56
- <Animated.View
57
- style={[
58
- styles.box,
59
- { backgroundColor: theme.colorScheme.surface, maxHeight },
60
- contentHeight != null ? { height } : null,
61
- ]}
62
- >
63
- {/* Avant la mesure du contenu, la feuille prend sa hauteur naturelle (pas de flex) */}
64
- <Pressable style={contentHeight != null ? styles.flex : null} onPress={Keyboard.dismiss} accessible={false}>
65
- <MyPageContainer style={contentHeight != null ? null : styles.noFlex}>
66
- <ScrollView
67
- keyboardShouldPersistTaps="handled"
68
- onContentSizeChange={(_w, h) => setContentHeight(h)}
69
- contentContainerStyle={[styles.content, { paddingBottom: 20 + insets.bottom }]}
70
- >
71
- {/* Titre */}
72
- <Text style={theme.textTheme.headlineLarge}>{traductions.transactionFormMotifLabel}</Text>
73
- <View style={styles.gap15} />
34
+ <SelectionSheet
35
+ titre={traductions.transactionFormMotifLabel}
36
+ contenu={
37
+ <>
38
+ <ScrollView keyboardShouldPersistTaps="handled" style={styles.defile} contentContainerStyle={styles.content}>
74
39
  <CustomTextMultipleInput
75
40
  defaultValue={note ?? undefined}
76
41
  labelText={traductions.transactionFormMotifHint}
77
42
  // Message d'erreur à afficher
78
43
  messageError={command.error === TransactionSendCommandMotifError.invalid ? traductions.transactionFormMotifInvalid : null}
79
- onFocusChange={setFocused}
80
44
  onChange={(value) => {
81
45
  command.value = value;
82
46
  command.isValid();
83
47
  setVersion((v) => v + 1);
84
48
  }}
85
49
  />
86
- {/* Bouton */}
87
- <View style={styles.btn}>
88
- <ElevatedButton onPress={canSave ? () => saveNote(command.value!) : undefined}>{traductions.btnTextSave}</ElevatedButton>
89
- </View>
90
50
  </ScrollView>
91
- </MyPageContainer>
92
- </Pressable>
93
- </Animated.View>
51
+ {/* Enregistrer, toujours visible au-dessus du clavier */}
52
+ <View style={styles.btn}>
53
+ <ElevatedButton onPress={canSave ? () => saveNote(command.value!) : undefined}>{traductions.btnTextSave}</ElevatedButton>
54
+ </View>
55
+ </>
56
+ }
57
+ />
94
58
  );
95
59
  }
96
60
 
97
61
  const styles = StyleSheet.create({
98
- flex: { flex: 1 },
99
- noFlex: { flex: 0 },
100
- box: { borderTopLeftRadius: 20, borderTopRightRadius: 20, overflow: 'hidden' },
101
- content: { paddingTop: 20 },
102
- gap15: { height: 15 },
103
- btn: { paddingVertical: 16 },
62
+ defile: { flexShrink: 1 },
63
+ content: { paddingHorizontal: 20, paddingTop: 8, paddingBottom: 16 },
64
+ btn: { paddingHorizontal: 20, paddingBottom: 12 },
104
65
  });
@@ -29,7 +29,7 @@ export function SubscriptionListEmptyWidget() {
29
29
  <Text style={[theme.textTheme.displaySmall, styles.flex]}>{traductions.subscriptionEmptySubTitle}</Text>
30
30
  <ElevatedButton
31
31
  style={styles.btn}
32
- onPress={() => void showModalBottomSheet(router, { themed: true, builder: () => <SubscriptionMenuWidget /> })}
32
+ onPress={() => void showModalBottomSheet(router, { builder: () => <SubscriptionMenuWidget /> })}
33
33
  >
34
34
  {traductions.subscriptionEmptyBtnCreate}
35
35
  </ElevatedButton>
@@ -36,7 +36,7 @@ export function SubscriptionListWidget() {
36
36
  if (state instanceof SubscriptionListLoadingState) return <SubscriptionListLoadingWidget />;
37
37
 
38
38
  const { subscriptions, paiementProgramme } = state;
39
- const openMenu = () => void showModalBottomSheet(router, { themed: true, builder: () => <SubscriptionMenuWidget /> });
39
+ const openMenu = () => void showModalBottomSheet(router, { builder: () => <SubscriptionMenuWidget /> });
40
40
 
41
41
  const section = (title: string, liste: Subscription[], createFn: () => void) => (
42
42
  <View>
@@ -1,60 +1,46 @@
1
- import { ScrollView, StyleSheet, Text, useWindowDimensions, View } from 'react-native';
2
- import { useSafeAreaInsets } from 'react-native-safe-area-context';
1
+ import { ScrollView, StyleSheet, View } from 'react-native';
3
2
 
4
3
  import { Images } from '../../../../core/assets';
5
4
  import { AppRouter, useAppRouter } from '../../../../core/router';
6
- import { useTheme } from '../../../../core/theme';
7
5
  import { useAppLocalizations } from '../../../../l10n/localizations';
8
- import { Card } from '../../../../shared/material/card';
9
- import { MenuActionItem, MenuActionsWidget } from '../../../../shared/widgets/menu_actions_widget';
6
+ import { SbSelectionOption, SelectionSheet } from '../../../../shared/widgets/selection';
10
7
 
11
8
  /** Menu de création : programmer un paiement ou souscrire à un abonnement (feuille du bas) */
12
9
  export function SubscriptionMenuWidget() {
13
10
  const traductions = useAppLocalizations();
14
- const theme = useTheme();
15
11
  const router = useAppRouter();
16
- const { height } = useWindowDimensions();
17
- const insets = useSafeAreaInsets();
18
12
  // Fermer le menu avant d'ouvrir la page : sinon il reste affiché par-dessus
19
13
  const open = (location: string) => {
20
14
  AppRouter.pop(router);
21
15
  void AppRouter.push(router, location);
22
16
  };
23
17
  return (
24
- <View style={[styles.box, { maxHeight: height * 0.4, backgroundColor: theme.colorScheme.surface }]}>
25
- <ScrollView contentContainerStyle={[styles.content, { paddingBottom: 20 + insets.bottom }]}>
26
- {/* Titre */}
27
- <Text style={theme.textTheme.headlineMedium}>{traductions.subscriptionEmptyBtnCreate}</Text>
28
- <View style={styles.gap20} />
29
- <Card>
30
- <MenuActionsWidget
31
- items={[
32
- // Programmer
33
- new MenuActionItem(
34
- Images.homeFooterTransfer,
35
- traductions.subscriptionMenuScheduleTitle,
36
- traductions.subscriptionMenuScheduleSubtitle,
37
- () => open(AppRouter.subscriptionSchedule),
38
- { iconSize: 20 },
39
- ),
40
- // Souscrire à un abonnement
41
- new MenuActionItem(
42
- Images.iconRepeat,
43
- traductions.subscriptionMenuSubscribeTitle,
44
- traductions.subscriptionMenuSubscribeSubtitle,
45
- () => open(AppRouter.subscriptionSubscribe),
46
- { iconSize: 20 },
47
- ),
48
- ]}
18
+ <SelectionSheet
19
+ titre={traductions.subscriptionEmptyBtnCreate}
20
+ contenu={
21
+ <ScrollView bounces={false} contentContainerStyle={styles.content}>
22
+ {/* Programmer */}
23
+ <SbSelectionOption
24
+ image={Images.homeFooterTransfer}
25
+ titre={traductions.subscriptionMenuScheduleTitle}
26
+ sousTitre={traductions.subscriptionMenuScheduleSubtitle}
27
+ onPress={() => open(AppRouter.subscriptionSchedule)}
49
28
  />
50
- </Card>
51
- </ScrollView>
52
- </View>
29
+ <View style={styles.gap10} />
30
+ {/* Souscrire à un abonnement */}
31
+ <SbSelectionOption
32
+ image={Images.iconRepeat}
33
+ titre={traductions.subscriptionMenuSubscribeTitle}
34
+ sousTitre={traductions.subscriptionMenuSubscribeSubtitle}
35
+ onPress={() => open(AppRouter.subscriptionSubscribe)}
36
+ />
37
+ </ScrollView>
38
+ }
39
+ />
53
40
  );
54
41
  }
55
42
 
56
43
  const styles = StyleSheet.create({
57
- box: { borderRadius: 20, overflow: 'hidden' },
58
- content: { padding: 20 },
59
- gap20: { height: 20 },
44
+ content: { paddingHorizontal: 20, paddingTop: 8, paddingBottom: 16 },
45
+ gap10: { height: 10 },
60
46
  });
@@ -78,7 +78,12 @@ export class TransactionOutputRemote {
78
78
 
79
79
  /** En-têtes communs des requêtes SSE */
80
80
  private sseHeaders(): Record<string, string> {
81
- return { Accept: 'text/event-stream', 'Cache-Control': 'no-cache', Authorization: `Bearer ${Api.accessToken}` };
81
+ return {
82
+ Accept: 'text/event-stream',
83
+ 'Cache-Control': 'no-cache',
84
+ Authorization: `Bearer ${Api.accessToken}`,
85
+ ...Api.apiKeyHeaders(),
86
+ };
82
87
  }
83
88
 
84
89
  /** Confirmer une transaction : la réponse finale (irrévocable/rejetée) arrive par SSE. */
@@ -52,7 +52,6 @@ export function TransactionDetailsPageActions({ transaction }: { transaction: Tr
52
52
  /** Ouvre une feuille ayant accès au bloc du détail */
53
53
  const showSheet = (content: ReactNode) =>
54
54
  void showModalBottomSheet(router, {
55
- themed: true,
56
55
  builder: () => <BlocProvider blocs={[transactionDetailsBloc]}>{content}</BlocProvider>,
57
56
  });
58
57
 
@@ -1,16 +1,15 @@
1
- import { MaterialIcons } from '@expo/vector-icons';
2
1
  import { useState } from 'react';
3
- import { Pressable, StyleSheet, Text, View } from 'react-native';
2
+ import { ScrollView, StyleSheet, Text } from 'react-native';
4
3
 
5
4
  import { useBloc } from '../../../../../core/bloc_react';
6
- import { useTheme } from '../../../../../core/theme';
5
+ import { Themer, useTheme } from '../../../../../core/theme';
7
6
  import { useAppLocalizations } from '../../../../../l10n/localizations';
8
7
  import { ElevatedButton } from '../../../../../shared/material/buttons';
8
+ import { SelectionBoutons, SelectionChoix, SelectionSheet } from '../../../../../shared/widgets/selection';
9
9
  import { TransactionCancelReason } from '../../../domain/models/transaction_cancel_reason';
10
10
  import { TransactionDetailsBloc } from '../../bloc/transaction_details/transaction_details_bloc';
11
11
  import { TransactionCancelSendEvent } from '../../bloc/transaction_details/transaction_details_event';
12
12
  import { TransactionCancelReasonText } from '../transaction_cancel/transaction_cancel_reason_text';
13
- import { SheetBox } from './sheet_box';
14
13
 
15
14
  /** Feuille « Demander l'annulation » : choix du motif puis envoi de la demande. */
16
15
  export function TransactionDetailsPageActionsCancel() {
@@ -22,45 +21,44 @@ export function TransactionDetailsPageActionsCancel() {
22
21
  const tx = bloc.state.transaction!;
23
22
 
24
23
  return (
25
- <SheetBox>
26
- {/* Title */}
27
- <Text style={theme.textTheme.headlineLarge}>{traductions.transactionDetailsCancelTitle}</Text>
28
- <View style={styles.gap20} />
29
- {/* SubTitle */}
30
- <Text style={theme.textTheme.displaySmall}>{traductions.transactionDetailsCancelSubTitle}</Text>
31
- <View style={styles.gap10} />
32
- {/* Raisons de la demande d'annulation */}
33
- {TransactionCancelReason.values().map((motif) => (
34
- <View key={motif} style={styles.chipRow}>
35
- <Pressable
36
- accessibilityRole="button"
37
- onPress={() => setReason(motif)}
38
- style={[styles.chip, { backgroundColor: theme.secondaryHeaderColor }]}
39
- >
40
- {reason === motif && (
41
- <MaterialIcons name="check" size={18} color={theme.colorScheme.onSurface} style={styles.check} />
42
- )}
43
- <Text style={theme.textTheme.bodyMedium}>{TransactionCancelReasonText.label(motif, traductions)}</Text>
44
- </Pressable>
45
- </View>
46
- ))}
47
- {/* Bouton Demander l'annulation */}
48
- <View style={styles.gap10} />
49
- <ElevatedButton
50
- style={styles.button}
51
- onPress={reason != null ? () => bloc.add(new TransactionCancelSendEvent(tx, reason)) : undefined}
52
- >
53
- {traductions.transactionDetailsCancelBtnSend}
54
- </ElevatedButton>
55
- </SheetBox>
24
+ <SelectionSheet
25
+ titre={traductions.transactionDetailsCancelTitle}
26
+ entete={
27
+ <Text style={[theme.textTheme.displaySmall, { color: Themer.neural03Color }]}>
28
+ {traductions.transactionDetailsCancelSubTitle}
29
+ </Text>
30
+ }
31
+ contenu={
32
+ <>
33
+ {/* Raisons de la demande d'annulation */}
34
+ <ScrollView bounces={false} style={styles.defile} contentContainerStyle={styles.content}>
35
+ {TransactionCancelReason.values().map((motif) => (
36
+ <SelectionChoix
37
+ key={motif}
38
+ texte={TransactionCancelReasonText.label(motif, traductions)}
39
+ choisi={reason === motif}
40
+ onPress={() => setReason(motif)}
41
+ />
42
+ ))}
43
+ </ScrollView>
44
+ {/* Bouton Demander l'annulation */}
45
+ <SelectionBoutons
46
+ boutons={[
47
+ <ElevatedButton
48
+ key="envoyer"
49
+ onPress={reason != null ? () => bloc.add(new TransactionCancelSendEvent(tx, reason)) : undefined}
50
+ >
51
+ {traductions.transactionDetailsCancelBtnSend}
52
+ </ElevatedButton>,
53
+ ]}
54
+ />
55
+ </>
56
+ }
57
+ />
56
58
  );
57
59
  }
58
60
 
59
61
  const styles = StyleSheet.create({
60
- gap10: { height: 10 },
61
- gap20: { height: 20 },
62
- chipRow: { paddingVertical: 10, alignItems: 'flex-start' },
63
- chip: { flexDirection: 'row', alignItems: 'center', borderRadius: 8, paddingHorizontal: 12, minHeight: 32 },
64
- check: { marginRight: 8 },
65
- button: { height: 56 },
62
+ defile: { flexShrink: 1 },
63
+ content: { paddingHorizontal: 20, paddingTop: 4, paddingBottom: 16 },
66
64
  });
@@ -1,21 +1,19 @@
1
- import { StyleSheet, Text, View } from 'react-native';
1
+ import { ScrollView, StyleSheet, View } from 'react-native';
2
2
 
3
3
  import { useBloc, useBlocBuilder } from '../../../../../core/bloc_react';
4
4
  import { Di } from '../../../../../core/di';
5
5
  import { AppRouter, useAppRouter } from '../../../../../core/router';
6
- import { useTheme } from '../../../../../core/theme';
7
6
  import { useAppLocalizations } from '../../../../../l10n/localizations';
8
7
  import { ElevatedButton, FilledTonalButton } from '../../../../../shared/material/buttons';
9
8
  import { InputAmount } from '../../../../../shared/widgets/input_amount';
10
9
  import { CustomTextInput } from '../../../../../shared/widgets/input_text';
10
+ import { SelectionBoutons, SelectionSheet } from '../../../../../shared/widgets/selection';
11
11
  import { TransactionDetailsBloc } from '../../bloc/transaction_details/transaction_details_bloc';
12
12
  import { TransactionReturnSendEvent } from '../../bloc/transaction_details/transaction_details_event';
13
- import { SheetBox } from './sheet_box';
14
13
 
15
14
  /** Feuille « Retourner les fonds » d'un transfert reçu, si le solde le permet. */
16
15
  export function TransactionDetailsPageActionsReturn() {
17
16
  const traductions = useAppLocalizations();
18
- const theme = useTheme();
19
17
  const router = useAppRouter();
20
18
  const bloc = useBloc(TransactionDetailsBloc);
21
19
  const state = useBlocBuilder(bloc);
@@ -30,50 +28,47 @@ export function TransactionDetailsPageActionsReturn() {
30
28
  };
31
29
 
32
30
  return (
33
- <SheetBox>
34
- {/* Titre */}
35
- <Text style={[theme.textTheme.titleSmall, styles.center]}>{traductions.transactionDetailsReturnTitle}</Text>
36
- <View style={styles.gap20} />
37
- {/* EndToEndId */}
38
- <CustomTextInput labelText={traductions.transactionDetailsIdentifiant} value={tx.endToEndId} readOnly />
39
- <View style={styles.gap20} />
40
- {/* Nom du payeur */}
41
- <CustomTextInput labelText={traductions.transactionDetailsPayeurLabel} value={tx.clientNom} readOnly />
42
- <View style={styles.gap20} />
43
- {/* Montant */}
44
- <InputAmount
45
- key={solde}
46
- solde={solde}
47
- hintText={traductions.transactionFormAmountHint}
48
- value={String(Math.trunc(tx.montant))}
49
- readOnly
50
- messageError={isSoldeInsuffisant ? traductions.transactionFormAmountInvalid : null}
51
- />
52
- <View style={styles.gap20} />
53
- <View style={styles.buttons}>
54
- {/* Non je ne retourne pas */}
55
- <View style={styles.flex}>
56
- <FilledTonalButton style={styles.button} onPress={() => AppRouter.pop(router)}>
57
- {traductions.btnTextNo}
58
- </FilledTonalButton>
59
- </View>
60
- <View style={styles.gap16} />
61
- {/* Oui je retourne les fonds */}
62
- <View style={styles.flex}>
63
- <ElevatedButton style={styles.button} onPress={!isSoldeInsuffisant ? () => void confirmReturn() : undefined}>
64
- {traductions.btnTextYes}
65
- </ElevatedButton>
66
- </View>
67
- </View>
68
- </SheetBox>
31
+ <SelectionSheet
32
+ titre={traductions.transactionDetailsReturnTitle}
33
+ contenu={
34
+ <>
35
+ <ScrollView keyboardShouldPersistTaps="handled" bounces={false} style={styles.defile} contentContainerStyle={styles.content}>
36
+ {/* EndToEndId */}
37
+ <CustomTextInput labelText={traductions.transactionDetailsIdentifiant} value={tx.endToEndId} readOnly />
38
+ <View style={styles.gap12} />
39
+ {/* Nom du payeur */}
40
+ <CustomTextInput labelText={traductions.transactionDetailsPayeurLabel} value={tx.clientNom} readOnly />
41
+ <View style={styles.gap12} />
42
+ {/* Montant */}
43
+ <InputAmount
44
+ key={solde}
45
+ solde={solde}
46
+ hintText={traductions.transactionFormAmountHint}
47
+ value={String(Math.trunc(tx.montant))}
48
+ readOnly
49
+ messageError={isSoldeInsuffisant ? traductions.transactionFormAmountInvalid : null}
50
+ />
51
+ </ScrollView>
52
+ <SelectionBoutons
53
+ boutons={[
54
+ // Non je ne retourne pas
55
+ <FilledTonalButton key="non" onPress={() => AppRouter.pop(router)}>
56
+ {traductions.btnTextNo}
57
+ </FilledTonalButton>,
58
+ // Oui je retourne les fonds
59
+ <ElevatedButton key="oui" onPress={!isSoldeInsuffisant ? () => void confirmReturn() : undefined}>
60
+ {traductions.btnTextYes}
61
+ </ElevatedButton>,
62
+ ]}
63
+ />
64
+ </>
65
+ }
66
+ />
69
67
  );
70
68
  }
71
69
 
72
70
  const styles = StyleSheet.create({
73
- center: { textAlign: 'center' },
74
- gap16: { width: 16 },
75
- gap20: { height: 20 },
76
- buttons: { flexDirection: 'row', height: 56 },
77
- flex: { flex: 1 },
78
- button: { height: 56 },
71
+ defile: { flexShrink: 1 },
72
+ content: { paddingHorizontal: 20, paddingTop: 8, paddingBottom: 16 },
73
+ gap12: { height: 12 },
79
74
  });