@pi-spi/app 2.1.0 → 2.2.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 (314) hide show
  1. package/lib/module/l10n/app_localizations.js.map +1 -1
  2. package/lib/module/l10n/app_localizations_en.js +32 -8
  3. package/lib/module/l10n/app_localizations_en.js.map +1 -1
  4. package/lib/module/l10n/app_localizations_fr.js +41 -14
  5. package/lib/module/l10n/app_localizations_fr.js.map +1 -1
  6. package/lib/module/l10n/app_localizations_pt.js +33 -7
  7. package/lib/module/l10n/app_localizations_pt.js.map +1 -1
  8. package/lib/module/modules/alias/domain/models/alias_revendication.js +4 -2
  9. package/lib/module/modules/alias/domain/models/alias_revendication.js.map +1 -1
  10. package/lib/module/modules/alias/infra/alias_output_local.js +11 -0
  11. package/lib/module/modules/alias/infra/alias_output_local.js.map +1 -1
  12. package/lib/module/modules/alias/infra/alias_output_repository.js +9 -8
  13. package/lib/module/modules/alias/infra/alias_output_repository.js.map +1 -1
  14. package/lib/module/modules/alias/presentation/pages/alias_delete_btn_widget.js +14 -18
  15. package/lib/module/modules/alias/presentation/pages/alias_delete_btn_widget.js.map +1 -1
  16. package/lib/module/modules/alias/presentation/pages/alias_page_claim.js +113 -60
  17. package/lib/module/modules/alias/presentation/pages/alias_page_claim.js.map +1 -1
  18. package/lib/module/modules/alias/presentation/pages/alias_page_create_mbno_form.js +151 -76
  19. package/lib/module/modules/alias/presentation/pages/alias_page_create_mbno_form.js.map +1 -1
  20. package/lib/module/modules/alias/presentation/pages/alias_page_create_mbno_timer.js +38 -24
  21. package/lib/module/modules/alias/presentation/pages/alias_page_create_mbno_timer.js.map +1 -1
  22. package/lib/module/modules/alias/presentation/pages/alias_page_create_options.js +28 -26
  23. package/lib/module/modules/alias/presentation/pages/alias_page_create_options.js.map +1 -1
  24. package/lib/module/modules/alias/presentation/pages/alias_page_otp.js +27 -110
  25. package/lib/module/modules/alias/presentation/pages/alias_page_otp.js.map +1 -1
  26. package/lib/module/modules/categorie/domain/services/categorie_service.js +2 -1
  27. package/lib/module/modules/categorie/domain/services/categorie_service.js.map +1 -1
  28. package/lib/module/modules/categorie/presentation/pages/categorie_edit_icon_btn.js +38 -42
  29. package/lib/module/modules/categorie/presentation/pages/categorie_edit_icon_btn.js.map +1 -1
  30. package/lib/module/modules/categorie/presentation/pages/categorie_form_pages.js +88 -80
  31. package/lib/module/modules/categorie/presentation/pages/categorie_form_pages.js.map +1 -1
  32. package/lib/module/modules/categorie/presentation/pages/categorie_icon.js +39 -0
  33. package/lib/module/modules/categorie/presentation/pages/categorie_icon.js.map +1 -1
  34. package/lib/module/modules/categorie/presentation/pages/categorie_liste_widget.js +55 -27
  35. package/lib/module/modules/categorie/presentation/pages/categorie_liste_widget.js.map +1 -1
  36. package/lib/module/modules/categorie/presentation/pages/categorie_select_page.js +21 -81
  37. package/lib/module/modules/categorie/presentation/pages/categorie_select_page.js.map +1 -1
  38. package/lib/module/modules/categorie/presentation/pages/categorie_select_widget.js +53 -16
  39. package/lib/module/modules/categorie/presentation/pages/categorie_select_widget.js.map +1 -1
  40. package/lib/module/modules/config/domain/models/config_keys.js +2 -0
  41. package/lib/module/modules/config/domain/models/config_keys.js.map +1 -1
  42. package/lib/module/modules/contacts/domain/contact_pi.js +3 -5
  43. package/lib/module/modules/contacts/domain/contact_pi.js.map +1 -1
  44. package/lib/module/modules/contacts/presentation/bloc/contact_bloc.js +30 -14
  45. package/lib/module/modules/contacts/presentation/bloc/contact_bloc.js.map +1 -1
  46. package/lib/module/modules/contacts/presentation/pages/contact_actions_sheet.js +106 -0
  47. package/lib/module/modules/contacts/presentation/pages/contact_actions_sheet.js.map +1 -0
  48. package/lib/module/modules/contacts/presentation/pages/contact_list_alias_widget.js +17 -7
  49. package/lib/module/modules/contacts/presentation/pages/contact_list_alias_widget.js.map +1 -1
  50. package/lib/module/modules/contacts/presentation/pages/contact_list_phone_widget.js +5 -4
  51. package/lib/module/modules/contacts/presentation/pages/contact_list_phone_widget.js.map +1 -1
  52. package/lib/module/modules/contacts/presentation/pages/contact_list_widget_item.js +76 -67
  53. package/lib/module/modules/contacts/presentation/pages/contact_list_widget_item.js.map +1 -1
  54. package/lib/module/modules/contacts/presentation/pages/contact_section.js +14 -4
  55. package/lib/module/modules/contacts/presentation/pages/contact_section.js.map +1 -1
  56. package/lib/module/modules/contacts/presentation/pages/contact_select_page.js +131 -110
  57. package/lib/module/modules/contacts/presentation/pages/contact_select_page.js.map +1 -1
  58. package/lib/module/modules/contacts/presentation/pages/create/contact_create_page.js +118 -59
  59. package/lib/module/modules/contacts/presentation/pages/create/contact_create_page.js.map +1 -1
  60. package/lib/module/modules/home/presentation/pages/home_page.js +3 -13
  61. package/lib/module/modules/home/presentation/pages/home_page.js.map +1 -1
  62. package/lib/module/modules/introduction/presentation/pages/introduction.js +17 -4
  63. package/lib/module/modules/introduction/presentation/pages/introduction.js.map +1 -1
  64. package/lib/module/modules/introduction/presentation/pages/introduction_footer.js +15 -53
  65. package/lib/module/modules/introduction/presentation/pages/introduction_footer.js.map +1 -1
  66. package/lib/module/modules/introduction/presentation/pages/introduction_page.js +22 -4
  67. package/lib/module/modules/introduction/presentation/pages/introduction_page.js.map +1 -1
  68. package/lib/module/modules/profile/presentation/pages/parametre/profile_parametre_page_notifications.js +2 -2
  69. package/lib/module/modules/profile/presentation/pages/parametre/profile_parametre_page_notifications.js.map +1 -1
  70. package/lib/module/modules/profile/presentation/pages/parametre/profile_parametre_page_notifications_son.js +1 -1
  71. package/lib/module/modules/profile/presentation/pages/parametre/profile_parametre_page_notifications_son.js.map +1 -1
  72. package/lib/module/modules/profile/presentation/pages/profile_page_avatar.js +2 -2
  73. package/lib/module/modules/profile/presentation/pages/profile_page_avatar.js.map +1 -1
  74. package/lib/module/modules/profile/presentation/pages/profile_page_contacts.js +14 -52
  75. package/lib/module/modules/profile/presentation/pages/profile_page_contacts.js.map +1 -1
  76. package/lib/module/modules/profile/presentation/pages/profile_page_contacts_actions.js +11 -1
  77. package/lib/module/modules/profile/presentation/pages/profile_page_contacts_actions.js.map +1 -1
  78. package/lib/module/modules/qrcode/presentation/pages/qrcode_alias_page_share.js +3 -3
  79. package/lib/module/modules/qrcode/presentation/pages/qrcode_alias_page_share.js.map +1 -1
  80. package/lib/module/modules/search/domain/models/fonctionnalite.js +51 -0
  81. package/lib/module/modules/search/domain/models/fonctionnalite.js.map +1 -1
  82. package/lib/module/modules/search/presentation/pages/search_btn_widget.js +136 -0
  83. package/lib/module/modules/search/presentation/pages/search_btn_widget.js.map +1 -0
  84. package/lib/module/modules/search/presentation/pages/search_fonctionnalites.js +21 -1
  85. package/lib/module/modules/search/presentation/pages/search_fonctionnalites.js.map +1 -1
  86. package/lib/module/modules/search/presentation/pages/search_page.js +266 -97
  87. package/lib/module/modules/search/presentation/pages/search_page.js.map +1 -1
  88. package/lib/module/modules/subscription/presentation/pages/subscription_create/subscription_create_page.js +5 -3
  89. package/lib/module/modules/subscription/presentation/pages/subscription_create/subscription_create_page.js.map +1 -1
  90. package/lib/module/modules/subscription/presentation/pages/subscription_create/subscription_create_page_list.js +5 -6
  91. package/lib/module/modules/subscription/presentation/pages/subscription_create/subscription_create_page_list.js.map +1 -1
  92. package/lib/module/modules/subscription/presentation/pages/subscription_menu_widget.js +3 -3
  93. package/lib/module/modules/subscription/presentation/pages/subscription_menu_widget.js.map +1 -1
  94. package/lib/module/modules/transactions/domain/models/transaction_send/transaction_send_command_othr.js +1 -2
  95. package/lib/module/modules/transactions/domain/models/transaction_send/transaction_send_command_othr.js.map +1 -1
  96. package/lib/module/modules/transactions/presentation/bloc/transaction_send/transaction_send_bloc.js +17 -0
  97. package/lib/module/modules/transactions/presentation/bloc/transaction_send/transaction_send_bloc.js.map +1 -1
  98. package/lib/module/modules/transactions/presentation/pages/transaction_form/transaction_form_input_date.js +30 -23
  99. package/lib/module/modules/transactions/presentation/pages/transaction_form/transaction_form_input_date.js.map +1 -1
  100. package/lib/module/modules/transactions/presentation/pages/transaction_form/transaction_form_input_pays.js +6 -6
  101. package/lib/module/modules/transactions/presentation/pages/transaction_form/transaction_form_input_pays.js.map +1 -1
  102. package/lib/module/modules/transactions/presentation/pages/transaction_form/transaction_form_input_psp.js +6 -6
  103. package/lib/module/modules/transactions/presentation/pages/transaction_form/transaction_form_input_psp.js.map +1 -1
  104. package/lib/module/modules/transactions/presentation/pages/transaction_form/transaction_form_page.js +16 -4
  105. package/lib/module/modules/transactions/presentation/pages/transaction_form/transaction_form_page.js.map +1 -1
  106. package/lib/module/modules/transactions/presentation/pages/transaction_form/transaction_form_page_alias.js +11 -9
  107. package/lib/module/modules/transactions/presentation/pages/transaction_form/transaction_form_page_alias.js.map +1 -1
  108. package/lib/module/modules/transactions/presentation/pages/transaction_form/transaction_form_page_othr.js +9 -7
  109. package/lib/module/modules/transactions/presentation/pages/transaction_form/transaction_form_page_othr.js.map +1 -1
  110. package/lib/module/modules/transactions/presentation/pages/transaction_form/transaction_form_page_schedule.js +8 -10
  111. package/lib/module/modules/transactions/presentation/pages/transaction_form/transaction_form_page_schedule.js.map +1 -1
  112. package/lib/module/modules/transactions/presentation/pages/transaction_form/transaction_form_page_verification.js +127 -105
  113. package/lib/module/modules/transactions/presentation/pages/transaction_form/transaction_form_page_verification.js.map +1 -1
  114. package/lib/module/modules/transactions/presentation/pages/transaction_search/transaction_search_page.js +9 -15
  115. package/lib/module/modules/transactions/presentation/pages/transaction_search/transaction_search_page.js.map +1 -1
  116. package/lib/module/modules/transactions/presentation/pages/transaction_split/transaction_split_page_repartition.js +5 -11
  117. package/lib/module/modules/transactions/presentation/pages/transaction_split/transaction_split_page_repartition.js.map +1 -1
  118. package/lib/module/modules/transactions/presentation/pages/transaction_split/transaction_split_page_tx.js +9 -9
  119. package/lib/module/modules/transactions/presentation/pages/transaction_split/transaction_split_page_tx.js.map +1 -1
  120. package/lib/module/shared/widgets/alias_widget.js +33 -12
  121. package/lib/module/shared/widgets/alias_widget.js.map +1 -1
  122. package/lib/module/shared/widgets/auth_code_field.js +89 -0
  123. package/lib/module/shared/widgets/auth_code_field.js.map +1 -0
  124. package/lib/module/shared/widgets/calendar_date_picker.js +21 -16
  125. package/lib/module/shared/widgets/calendar_date_picker.js.map +1 -1
  126. package/lib/module/shared/widgets/confirm_action_sheet_widget.js +20 -1
  127. package/lib/module/shared/widgets/confirm_action_sheet_widget.js.map +1 -1
  128. package/lib/module/shared/widgets/emoji_select_widget.js +34 -39
  129. package/lib/module/shared/widgets/emoji_select_widget.js.map +1 -1
  130. package/lib/module/shared/widgets/frequence_input_widget.js +18 -29
  131. package/lib/module/shared/widgets/frequence_input_widget.js.map +1 -1
  132. package/lib/module/shared/widgets/frequence_select_widget.js +233 -140
  133. package/lib/module/shared/widgets/frequence_select_widget.js.map +1 -1
  134. package/lib/module/shared/widgets/image_select_widget.js +4 -4
  135. package/lib/module/shared/widgets/image_select_widget.js.map +1 -1
  136. package/lib/module/shared/widgets/input_text.js +1 -1
  137. package/lib/module/shared/widgets/input_text.js.map +1 -1
  138. package/lib/module/shared/widgets/notification_dialog.js +3 -2
  139. package/lib/module/shared/widgets/notification_dialog.js.map +1 -1
  140. package/lib/module/shared/widgets/pin_entete.js +114 -0
  141. package/lib/module/shared/widgets/pin_entete.js.map +1 -0
  142. package/lib/module/shared/widgets/select_date_widget.js +74 -59
  143. package/lib/module/shared/widgets/select_date_widget.js.map +1 -1
  144. package/lib/module/shared/widgets/selection.js +21 -16
  145. package/lib/module/shared/widgets/selection.js.map +1 -1
  146. package/lib/typescript/src/l10n/app_localizations.d.ts +59 -11
  147. package/lib/typescript/src/l10n/app_localizations.d.ts.map +1 -1
  148. package/lib/typescript/src/l10n/app_localizations_en.d.ts.map +1 -1
  149. package/lib/typescript/src/l10n/app_localizations_fr.d.ts.map +1 -1
  150. package/lib/typescript/src/l10n/app_localizations_pt.d.ts.map +1 -1
  151. package/lib/typescript/src/modules/alias/domain/models/alias_revendication.d.ts.map +1 -1
  152. package/lib/typescript/src/modules/alias/infra/alias_output_local.d.ts +5 -0
  153. package/lib/typescript/src/modules/alias/infra/alias_output_local.d.ts.map +1 -1
  154. package/lib/typescript/src/modules/alias/infra/alias_output_repository.d.ts.map +1 -1
  155. package/lib/typescript/src/modules/alias/presentation/pages/alias_delete_btn_widget.d.ts.map +1 -1
  156. package/lib/typescript/src/modules/alias/presentation/pages/alias_page_claim.d.ts.map +1 -1
  157. package/lib/typescript/src/modules/alias/presentation/pages/alias_page_create_mbno_form.d.ts.map +1 -1
  158. package/lib/typescript/src/modules/alias/presentation/pages/alias_page_create_mbno_timer.d.ts +1 -1
  159. package/lib/typescript/src/modules/alias/presentation/pages/alias_page_create_mbno_timer.d.ts.map +1 -1
  160. package/lib/typescript/src/modules/alias/presentation/pages/alias_page_create_options.d.ts +4 -1
  161. package/lib/typescript/src/modules/alias/presentation/pages/alias_page_create_options.d.ts.map +1 -1
  162. package/lib/typescript/src/modules/alias/presentation/pages/alias_page_otp.d.ts +9 -5
  163. package/lib/typescript/src/modules/alias/presentation/pages/alias_page_otp.d.ts.map +1 -1
  164. package/lib/typescript/src/modules/categorie/domain/services/categorie_service.d.ts.map +1 -1
  165. package/lib/typescript/src/modules/categorie/presentation/pages/categorie_edit_icon_btn.d.ts +3 -0
  166. package/lib/typescript/src/modules/categorie/presentation/pages/categorie_edit_icon_btn.d.ts.map +1 -1
  167. package/lib/typescript/src/modules/categorie/presentation/pages/categorie_form_pages.d.ts.map +1 -1
  168. package/lib/typescript/src/modules/categorie/presentation/pages/categorie_icon.d.ts +9 -0
  169. package/lib/typescript/src/modules/categorie/presentation/pages/categorie_icon.d.ts.map +1 -1
  170. package/lib/typescript/src/modules/categorie/presentation/pages/categorie_liste_widget.d.ts +7 -2
  171. package/lib/typescript/src/modules/categorie/presentation/pages/categorie_liste_widget.d.ts.map +1 -1
  172. package/lib/typescript/src/modules/categorie/presentation/pages/categorie_select_page.d.ts.map +1 -1
  173. package/lib/typescript/src/modules/categorie/presentation/pages/categorie_select_widget.d.ts +10 -2
  174. package/lib/typescript/src/modules/categorie/presentation/pages/categorie_select_widget.d.ts.map +1 -1
  175. package/lib/typescript/src/modules/config/domain/models/config_keys.d.ts +3 -1
  176. package/lib/typescript/src/modules/config/domain/models/config_keys.d.ts.map +1 -1
  177. package/lib/typescript/src/modules/contacts/domain/contact_pi.d.ts +0 -2
  178. package/lib/typescript/src/modules/contacts/domain/contact_pi.d.ts.map +1 -1
  179. package/lib/typescript/src/modules/contacts/presentation/bloc/contact_bloc.d.ts +7 -0
  180. package/lib/typescript/src/modules/contacts/presentation/bloc/contact_bloc.d.ts.map +1 -1
  181. package/lib/typescript/src/modules/contacts/presentation/pages/contact_actions_sheet.d.ts +14 -0
  182. package/lib/typescript/src/modules/contacts/presentation/pages/contact_actions_sheet.d.ts.map +1 -0
  183. package/lib/typescript/src/modules/contacts/presentation/pages/contact_list_alias_widget.d.ts +4 -2
  184. package/lib/typescript/src/modules/contacts/presentation/pages/contact_list_alias_widget.d.ts.map +1 -1
  185. package/lib/typescript/src/modules/contacts/presentation/pages/contact_list_phone_widget.d.ts.map +1 -1
  186. package/lib/typescript/src/modules/contacts/presentation/pages/contact_list_widget_item.d.ts +6 -4
  187. package/lib/typescript/src/modules/contacts/presentation/pages/contact_list_widget_item.d.ts.map +1 -1
  188. package/lib/typescript/src/modules/contacts/presentation/pages/contact_section.d.ts +3 -1
  189. package/lib/typescript/src/modules/contacts/presentation/pages/contact_section.d.ts.map +1 -1
  190. package/lib/typescript/src/modules/contacts/presentation/pages/contact_select_page.d.ts.map +1 -1
  191. package/lib/typescript/src/modules/contacts/presentation/pages/create/contact_create_page.d.ts.map +1 -1
  192. package/lib/typescript/src/modules/home/presentation/pages/home_page.d.ts.map +1 -1
  193. package/lib/typescript/src/modules/introduction/presentation/pages/introduction.d.ts.map +1 -1
  194. package/lib/typescript/src/modules/introduction/presentation/pages/introduction_footer.d.ts +5 -1
  195. package/lib/typescript/src/modules/introduction/presentation/pages/introduction_footer.d.ts.map +1 -1
  196. package/lib/typescript/src/modules/introduction/presentation/pages/introduction_page.d.ts.map +1 -1
  197. package/lib/typescript/src/modules/profile/presentation/pages/profile_page_contacts.d.ts.map +1 -1
  198. package/lib/typescript/src/modules/profile/presentation/pages/profile_page_contacts_actions.d.ts.map +1 -1
  199. package/lib/typescript/src/modules/search/domain/models/fonctionnalite.d.ts +20 -0
  200. package/lib/typescript/src/modules/search/domain/models/fonctionnalite.d.ts.map +1 -1
  201. package/lib/typescript/src/modules/search/presentation/pages/search_btn_widget.d.ts +11 -0
  202. package/lib/typescript/src/modules/search/presentation/pages/search_btn_widget.d.ts.map +1 -0
  203. package/lib/typescript/src/modules/search/presentation/pages/search_fonctionnalites.d.ts.map +1 -1
  204. package/lib/typescript/src/modules/search/presentation/pages/search_page.d.ts.map +1 -1
  205. package/lib/typescript/src/modules/subscription/presentation/pages/subscription_create/subscription_create_page.d.ts.map +1 -1
  206. package/lib/typescript/src/modules/transactions/domain/models/transaction_send/transaction_send_command_othr.d.ts.map +1 -1
  207. package/lib/typescript/src/modules/transactions/presentation/bloc/transaction_send/transaction_send_bloc.d.ts.map +1 -1
  208. package/lib/typescript/src/modules/transactions/presentation/pages/transaction_form/transaction_form_input_date.d.ts +4 -1
  209. package/lib/typescript/src/modules/transactions/presentation/pages/transaction_form/transaction_form_input_date.d.ts.map +1 -1
  210. package/lib/typescript/src/modules/transactions/presentation/pages/transaction_form/transaction_form_page_alias.d.ts +4 -0
  211. package/lib/typescript/src/modules/transactions/presentation/pages/transaction_form/transaction_form_page_alias.d.ts.map +1 -1
  212. package/lib/typescript/src/modules/transactions/presentation/pages/transaction_form/transaction_form_page_othr.d.ts.map +1 -1
  213. package/lib/typescript/src/modules/transactions/presentation/pages/transaction_form/transaction_form_page_schedule.d.ts.map +1 -1
  214. package/lib/typescript/src/modules/transactions/presentation/pages/transaction_form/transaction_form_page_verification.d.ts.map +1 -1
  215. package/lib/typescript/src/modules/transactions/presentation/pages/transaction_search/transaction_search_page.d.ts.map +1 -1
  216. package/lib/typescript/src/modules/transactions/presentation/pages/transaction_split/transaction_split_page_repartition.d.ts.map +1 -1
  217. package/lib/typescript/src/modules/transactions/presentation/pages/transaction_split/transaction_split_page_tx.d.ts.map +1 -1
  218. package/lib/typescript/src/shared/widgets/alias_widget.d.ts +2 -2
  219. package/lib/typescript/src/shared/widgets/alias_widget.d.ts.map +1 -1
  220. package/lib/typescript/src/shared/widgets/auth_code_field.d.ts +17 -0
  221. package/lib/typescript/src/shared/widgets/auth_code_field.d.ts.map +1 -0
  222. package/lib/typescript/src/shared/widgets/calendar_date_picker.d.ts.map +1 -1
  223. package/lib/typescript/src/shared/widgets/confirm_action_sheet_widget.d.ts +12 -1
  224. package/lib/typescript/src/shared/widgets/confirm_action_sheet_widget.d.ts.map +1 -1
  225. package/lib/typescript/src/shared/widgets/emoji_select_widget.d.ts.map +1 -1
  226. package/lib/typescript/src/shared/widgets/frequence_input_widget.d.ts +6 -3
  227. package/lib/typescript/src/shared/widgets/frequence_input_widget.d.ts.map +1 -1
  228. package/lib/typescript/src/shared/widgets/frequence_select_widget.d.ts +23 -5
  229. package/lib/typescript/src/shared/widgets/frequence_select_widget.d.ts.map +1 -1
  230. package/lib/typescript/src/shared/widgets/image_select_widget.d.ts +1 -1
  231. package/lib/typescript/src/shared/widgets/input_text.d.ts +2 -0
  232. package/lib/typescript/src/shared/widgets/input_text.d.ts.map +1 -1
  233. package/lib/typescript/src/shared/widgets/notification_dialog.d.ts +3 -1
  234. package/lib/typescript/src/shared/widgets/notification_dialog.d.ts.map +1 -1
  235. package/lib/typescript/src/shared/widgets/pin_entete.d.ts +15 -0
  236. package/lib/typescript/src/shared/widgets/pin_entete.d.ts.map +1 -0
  237. package/lib/typescript/src/shared/widgets/select_date_widget.d.ts +4 -0
  238. package/lib/typescript/src/shared/widgets/select_date_widget.d.ts.map +1 -1
  239. package/lib/typescript/src/shared/widgets/selection.d.ts +11 -7
  240. package/lib/typescript/src/shared/widgets/selection.d.ts.map +1 -1
  241. package/package.json +1 -1
  242. package/src/l10n/app_localizations.ts +59 -11
  243. package/src/l10n/app_localizations_en.ts +32 -8
  244. package/src/l10n/app_localizations_fr.ts +38 -14
  245. package/src/l10n/app_localizations_pt.ts +31 -7
  246. package/src/modules/alias/domain/models/alias_revendication.ts +4 -2
  247. package/src/modules/alias/infra/alias_output_local.ts +11 -0
  248. package/src/modules/alias/infra/alias_output_repository.ts +9 -8
  249. package/src/modules/alias/presentation/pages/alias_delete_btn_widget.tsx +17 -24
  250. package/src/modules/alias/presentation/pages/alias_page_claim.tsx +76 -48
  251. package/src/modules/alias/presentation/pages/alias_page_create_mbno_form.tsx +113 -65
  252. package/src/modules/alias/presentation/pages/alias_page_create_mbno_timer.tsx +34 -25
  253. package/src/modules/alias/presentation/pages/alias_page_create_options.tsx +29 -36
  254. package/src/modules/alias/presentation/pages/alias_page_otp.tsx +24 -88
  255. package/src/modules/categorie/domain/services/categorie_service.ts +2 -1
  256. package/src/modules/categorie/presentation/pages/categorie_edit_icon_btn.tsx +38 -28
  257. package/src/modules/categorie/presentation/pages/categorie_form_pages.tsx +71 -41
  258. package/src/modules/categorie/presentation/pages/categorie_icon.tsx +26 -0
  259. package/src/modules/categorie/presentation/pages/categorie_liste_widget.tsx +45 -24
  260. package/src/modules/categorie/presentation/pages/categorie_select_page.tsx +10 -46
  261. package/src/modules/categorie/presentation/pages/categorie_select_widget.tsx +54 -13
  262. package/src/modules/config/domain/models/config_keys.ts +3 -0
  263. package/src/modules/contacts/domain/contact_pi.ts +3 -6
  264. package/src/modules/contacts/presentation/bloc/contact_bloc.ts +37 -20
  265. package/src/modules/contacts/presentation/pages/contact_actions_sheet.tsx +69 -0
  266. package/src/modules/contacts/presentation/pages/contact_list_alias_widget.tsx +26 -4
  267. package/src/modules/contacts/presentation/pages/contact_list_phone_widget.tsx +3 -0
  268. package/src/modules/contacts/presentation/pages/contact_list_widget_item.tsx +54 -65
  269. package/src/modules/contacts/presentation/pages/contact_section.tsx +13 -3
  270. package/src/modules/contacts/presentation/pages/contact_select_page.tsx +106 -74
  271. package/src/modules/contacts/presentation/pages/create/contact_create_page.tsx +86 -47
  272. package/src/modules/home/presentation/pages/home_page.tsx +2 -9
  273. package/src/modules/introduction/presentation/pages/introduction.tsx +8 -0
  274. package/src/modules/introduction/presentation/pages/introduction_footer.tsx +16 -36
  275. package/src/modules/introduction/presentation/pages/introduction_page.tsx +17 -5
  276. package/src/modules/profile/presentation/pages/parametre/profile_parametre_page_notifications.tsx +2 -2
  277. package/src/modules/profile/presentation/pages/parametre/profile_parametre_page_notifications_son.tsx +1 -1
  278. package/src/modules/profile/presentation/pages/profile_page_avatar.tsx +2 -2
  279. package/src/modules/profile/presentation/pages/profile_page_contacts.tsx +12 -19
  280. package/src/modules/profile/presentation/pages/profile_page_contacts_actions.tsx +10 -1
  281. package/src/modules/qrcode/presentation/pages/qrcode_alias_page_share.tsx +3 -3
  282. package/src/modules/search/domain/models/fonctionnalite.ts +56 -0
  283. package/src/modules/search/presentation/pages/search_btn_widget.tsx +91 -0
  284. package/src/modules/search/presentation/pages/search_fonctionnalites.ts +21 -1
  285. package/src/modules/search/presentation/pages/search_page.tsx +166 -57
  286. package/src/modules/subscription/presentation/pages/subscription_create/subscription_create_page.tsx +4 -2
  287. package/src/modules/subscription/presentation/pages/subscription_create/subscription_create_page_list.tsx +5 -5
  288. package/src/modules/subscription/presentation/pages/subscription_menu_widget.tsx +3 -3
  289. package/src/modules/transactions/domain/models/transaction_send/transaction_send_command_othr.ts +1 -2
  290. package/src/modules/transactions/presentation/bloc/transaction_send/transaction_send_bloc.ts +17 -0
  291. package/src/modules/transactions/presentation/pages/transaction_form/transaction_form_input_date.tsx +26 -17
  292. package/src/modules/transactions/presentation/pages/transaction_form/transaction_form_input_pays.tsx +9 -9
  293. package/src/modules/transactions/presentation/pages/transaction_form/transaction_form_input_psp.tsx +9 -9
  294. package/src/modules/transactions/presentation/pages/transaction_form/transaction_form_page.tsx +20 -2
  295. package/src/modules/transactions/presentation/pages/transaction_form/transaction_form_page_alias.tsx +6 -8
  296. package/src/modules/transactions/presentation/pages/transaction_form/transaction_form_page_othr.tsx +5 -5
  297. package/src/modules/transactions/presentation/pages/transaction_form/transaction_form_page_schedule.tsx +5 -7
  298. package/src/modules/transactions/presentation/pages/transaction_form/transaction_form_page_verification.tsx +112 -103
  299. package/src/modules/transactions/presentation/pages/transaction_search/transaction_search_page.tsx +6 -10
  300. package/src/modules/transactions/presentation/pages/transaction_split/transaction_split_page_repartition.tsx +3 -6
  301. package/src/modules/transactions/presentation/pages/transaction_split/transaction_split_page_tx.tsx +5 -5
  302. package/src/shared/widgets/alias_widget.tsx +45 -18
  303. package/src/shared/widgets/auth_code_field.tsx +89 -0
  304. package/src/shared/widgets/calendar_date_picker.tsx +12 -11
  305. package/src/shared/widgets/confirm_action_sheet_widget.tsx +19 -1
  306. package/src/shared/widgets/emoji_select_widget.tsx +31 -29
  307. package/src/shared/widgets/frequence_input_widget.tsx +18 -24
  308. package/src/shared/widgets/frequence_select_widget.tsx +237 -117
  309. package/src/shared/widgets/image_select_widget.tsx +4 -4
  310. package/src/shared/widgets/input_text.tsx +3 -0
  311. package/src/shared/widgets/notification_dialog.tsx +4 -1
  312. package/src/shared/widgets/pin_entete.tsx +74 -0
  313. package/src/shared/widgets/select_date_widget.tsx +66 -34
  314. package/src/shared/widgets/selection.tsx +23 -12
@@ -1,12 +1,15 @@
1
- import { useRef, useState, type ReactNode } from 'react';
2
- import { Keyboard, StyleSheet, Text, TextInput, useWindowDimensions, View, type TextInputInstance } from 'react-native';
1
+ import type { ComponentProps, ReactNode } from 'react';
2
+ import { StyleSheet, View } from 'react-native';
3
+ import type { MaterialIcons } from '@expo/vector-icons';
3
4
 
4
- import { useTheme } from '../../../../core/theme';
5
+ import { AuthCodeField } from '../../../../shared/widgets/auth_code_field';
6
+ import { PinEntete, PinMessage } from '../../../../shared/widgets/pin_entete';
5
7
 
6
8
  /**
7
- * Saisie d'un code OTP en [pinLength] cases d'un chiffre : passage
8
- * automatique à la case suivante, retour à la précédente sur effacement,
9
- * collage du code entier dans la première case.
9
+ * Saisie d'un code reçu par SMS ou e-mail (alias par numéro de téléphone,
10
+ * refus d'une revendication, code PIN oublié) : en-tête centré, une case
11
+ * par chiffre avec la suggestion du code par le clavier, bandeau d'erreur
12
+ * et renvoi du code.
10
13
  */
11
14
  export function AliasPageOtp({
12
15
  pinLength,
@@ -17,6 +20,7 @@ export function AliasPageOtp({
17
20
  onOtpComplete,
18
21
  autoFocus = true,
19
22
  useInBottomSheet = false,
23
+ icone = 'sms',
20
24
  }: {
21
25
  pinLength: number;
22
26
  title: string;
@@ -26,95 +30,27 @@ export function AliasPageOtp({
26
30
  onOtpComplete: (otpCode: number[]) => void;
27
31
  autoFocus?: boolean;
28
32
  useInBottomSheet?: boolean;
33
+ /** Icône de la pastille de l'en-tête */
34
+ icone?: ComponentProps<typeof MaterialIcons>['name'];
29
35
  }) {
30
- const theme = useTheme();
31
- const { width: largeur } = useWindowDimensions();
32
- const [values, setValues] = useState<string[]>(() => Array(pinLength).fill(''));
33
- const inputs = useRef<(TextInputInstance | null)[]>([]);
34
-
35
- const isTablet = largeur >= 600;
36
- const paddingX = 20;
37
- const formWidth = largeur - (useInBottomSheet && isTablet ? 40 : 0) - paddingX * 2;
38
- const fieldWidth = formWidth / pinLength - 8;
39
-
40
- const verifyOtpCompletion = (next: string[]) => {
41
- const pin = next.filter((v) => /^\d$/.test(v)).map(Number);
42
- if (pin.length === pinLength) onOtpComplete(pin);
43
- };
44
-
45
- const handleOtpInputChange = (raw: string, index: number) => {
46
- const text = raw.replace(/\D/g, '');
47
- // Cas où l'utilisateur colle tout le code OTP dans le premier champ
48
- if (index === 0 && text.length === pinLength) {
49
- const next = text.split('');
50
- setValues(next);
51
- Keyboard.dismiss();
52
- verifyOtpCompletion(next);
53
- return;
54
- }
55
- const next = [...values];
56
- next[index] = text.slice(-1);
57
- setValues(next);
58
- if (next[index].length === 1 && index < pinLength - 1) {
59
- inputs.current[index + 1]?.focus();
60
- } else if (next[index].length === 0 && index > 0) {
61
- inputs.current[index - 1]?.focus();
62
- }
63
- verifyOtpCompletion(next);
64
- };
65
-
66
- const onKeyPress = (key: string, index: number) => {
67
- // Effacement sur une case déjà vide : retour à la case précédente
68
- if (key === 'Backspace' && values[index].length === 0 && index > 0) {
69
- const next = [...values];
70
- next[index - 1] = '';
71
- setValues(next);
72
- inputs.current[index - 1]?.focus();
73
- }
74
- };
75
-
76
- const input = theme.inputDecorationTheme;
77
36
  return (
78
37
  <View>
79
- <Text style={theme.textTheme.titleSmall}>{title}</Text>
80
- <View style={styles.gap5} />
81
- <Text style={theme.textTheme.displaySmall}>{subtitle}</Text>
82
- <View style={styles.gap32} />
83
- <View style={styles.row}>
84
- {values.map((value, index) => (
85
- <TextInput
86
- key={index}
87
- ref={(ref) => {
88
- inputs.current[index] = ref;
89
- }}
90
- value={value}
91
- keyboardType="number-pad"
92
- autoFocus={autoFocus && index === 0}
93
- maxLength={index === 0 ? pinLength : 1}
94
- onChangeText={(text) => handleOtpInputChange(text, index)}
95
- onKeyPress={({ nativeEvent }) => onKeyPress(nativeEvent.key, index)}
96
- textAlign="center"
97
- style={[
98
- theme.textTheme.headlineMedium,
99
- styles.field,
100
- { width: fieldWidth, backgroundColor: input.fillColor, borderRadius: input.borderRadius },
101
- ]}
102
- />
103
- ))}
104
- </View>
105
- <View style={styles.gap24} />
106
- {errorMessage != null && <Text style={[input.errorStyle, styles.error]}>{`⚠ ${errorMessage}`}</Text>}
38
+ {/* Dans une feuille : pastille plus petite */}
39
+ <PinEntete icone={icone} titre={title} sousTitre={subtitle} compact={useInBottomSheet} />
40
+ <View style={{ height: useInBottomSheet ? 20 : 28 }} />
41
+ <AuthCodeField
42
+ longueur={pinLength}
43
+ autoFocus={autoFocus}
44
+ erreur={errorMessage != null}
45
+ onChanged={() => undefined}
46
+ onComplete={(code) => onOtpComplete(code.split('').map(Number))}
47
+ />
48
+ <PinMessage message={errorMessage} />
107
49
  {countdownTimer != null && <View style={styles.timer}>{countdownTimer}</View>}
108
50
  </View>
109
51
  );
110
52
  }
111
53
 
112
54
  const styles = StyleSheet.create({
113
- gap5: { height: 5 },
114
- gap24: { height: 24 },
115
- gap32: { height: 32 },
116
- row: { flexDirection: 'row', justifyContent: 'space-between' },
117
- field: { height: 56, padding: 0 },
118
- error: { marginLeft: 8, marginTop: 2, marginBottom: 5 },
119
- timer: { flexDirection: 'row', justifyContent: 'flex-start' },
55
+ timer: { marginTop: 12, alignItems: 'center' },
120
56
  });
@@ -27,7 +27,8 @@ export class CategorieService implements CategorieInputPort {
27
27
  }
28
28
 
29
29
  async list(): Promise<Categorie[]> {
30
- return (await this.categorieOutputPort.list()).sort(byLabelDesc);
30
+ // Tri sur une copie : la liste reçue peut être non modifiable
31
+ return [...(await this.categorieOutputPort.list())].sort(byLabelDesc);
31
32
  }
32
33
 
33
34
  async update(categorie: Categorie): Promise<Categorie> {
@@ -1,22 +1,26 @@
1
1
  import { Image } from 'expo-image';
2
2
  import { useRef } from 'react';
3
- import { Pressable, ScrollView, StyleSheet, useWindowDimensions, View } from 'react-native';
4
- import { useSafeAreaInsets } from 'react-native-safe-area-context';
3
+ import { Pressable, ScrollView, StyleSheet, View } from 'react-native';
5
4
 
6
5
  import { Images } from '../../../../core/assets';
7
6
  import { useBloc } from '../../../../core/bloc_react';
8
- import { AppRouter, useAppRouter } from '../../../../core/router';
7
+ import { AppRouter, useAppRouter, type SdkRouter } from '../../../../core/router';
9
8
  import { useTheme } from '../../../../core/theme';
10
9
  import { useAppLocalizations } from '../../../../l10n/localizations';
11
10
  import { ElevatedButton } from '../../../../shared/material/buttons';
12
11
  import { showModalBottomSheet } from '../../../../shared/material/overlays';
13
12
  import { EmojiSelectWidget } from '../../../../shared/widgets/emoji_select_widget';
14
- import { SbSelectionOption, SelectionSheet } from '../../../../shared/widgets/selection';
13
+ import { SelectionOption, SelectionBoutons, SelectionSheet } from '../../../../shared/widgets/selection';
15
14
  import { CategorieIconType } from '../../domain/models/categorie';
16
15
  import { CategorieBloc } from '../bloc/categorie_bloc';
17
16
  import { CategorieAddValidationEvent, CategorieEditValidationEvent } from '../bloc/categorie_event';
18
17
  import { CategorieCreationState, CategorieEditState } from '../bloc/categorie_state';
19
18
 
19
+ /** Ouvre la feuille de choix de l'icône d'une catégorie (emoji ou galerie). */
20
+ export function ouvrirIconeCategorie(router: SdkRouter) {
21
+ void showModalBottomSheet(router, { builder: () => <CategorieEditIconOptions /> });
22
+ }
23
+
20
24
  /** Bouton d'édition de l'icône d'une catégorie (création ou modification). */
21
25
  export function CategorieEditIconBtn() {
22
26
  const theme = useTheme();
@@ -24,7 +28,7 @@ export function CategorieEditIconBtn() {
24
28
  return (
25
29
  <Pressable
26
30
  accessibilityRole="button"
27
- onPress={() => void showModalBottomSheet(router, { builder: () => <CategorieEditIconOptions /> })}
31
+ onPress={() => ouvrirIconeCategorie(router)}
28
32
  style={[styles.fab, { backgroundColor: theme.colorScheme.surface }]}
29
33
  >
30
34
  <Image source={Images.categorieImageSelect} style={styles.fabIcon} />
@@ -44,9 +48,9 @@ function CategorieEditIconOptions() {
44
48
  const edit = state instanceof CategorieEditState ? state : null;
45
49
  const command = creation?.command ?? edit?.command;
46
50
  if (!command) return;
51
+ // Nouvelle catégorie : pas encore d'icône ni de couleur
47
52
  const value = await showModalBottomSheet<{ emoji: string; color: number }>(router, {
48
- themed: true,
49
- builder: () => <CategorieEditIconEmoji icon={command.icon!} color={command.color!} />,
53
+ builder: () => <CategorieEditIconEmoji icon={command.icon ?? '🤩'} color={command.color ?? 0xfff9ebc2} />,
50
54
  });
51
55
  if (value == null) return;
52
56
  command.iconType = CategorieIconType.emoji;
@@ -64,14 +68,14 @@ function CategorieEditIconOptions() {
64
68
  contenu={
65
69
  <ScrollView bounces={false} contentContainerStyle={styles.optionsContent}>
66
70
  {/* Emoji */}
67
- <SbSelectionOption
71
+ <SelectionOption
68
72
  image={Images.categorieIconEmoji}
69
73
  titre={traductions.categorieFormIconSheetEmojiTitle}
70
74
  onPress={() => void selectEmoji()}
71
75
  />
72
76
  <View style={styles.gap10} />
73
77
  {/* Choisir dans la galerie (sans action, comme dans le SDK Flutter) */}
74
- <SbSelectionOption
78
+ <SelectionOption
75
79
  image={Images.categorieImageSelect}
76
80
  titre={traductions.categorieFormIconSheetGalleryTitle}
77
81
  onPress={() => undefined}
@@ -82,37 +86,43 @@ function CategorieEditIconOptions() {
82
86
  );
83
87
  }
84
88
 
85
- /** Feuille de choix de l'emoji et de la couleur ; retourne `{ emoji, color }`. */
89
+ /** Feuille de choix de l'emoji et de la couleur ; retourne `{ emoji, color }` à l'enregistrement. */
86
90
  function CategorieEditIconEmoji({ icon, color }: { icon: string; color: number }) {
87
91
  const traductions = useAppLocalizations();
88
- const theme = useTheme();
89
92
  const router = useAppRouter();
90
- const insets = useSafeAreaInsets();
91
- const { height } = useWindowDimensions();
92
93
  const selection = useRef<{ icon: string; color: number }>({ icon, color });
93
94
 
94
95
  return (
95
- <View style={[styles.sheet, { height: height * 0.8, backgroundColor: theme.colorScheme.surface, paddingBottom: insets.bottom }]}>
96
- <ScrollView contentContainerStyle={styles.sheetContent}>
97
- <EmojiSelectWidget icon={icon} color={color} onChanged={(value) => (selection.current = value)} />
98
- <View style={styles.saveBtn}>
99
- <ElevatedButton
100
- onPress={() => AppRouter.pop(router, { value: { emoji: selection.current.icon, color: selection.current.color } })}
101
- >
102
- {traductions.categorieFormSaveBtn}
103
- </ElevatedButton>
104
- </View>
105
- </ScrollView>
106
- </View>
96
+ <SelectionSheet
97
+ titre={traductions.categorieFormIconSheetEmojiTitle}
98
+ hauteurMax={0.9}
99
+ contenu={
100
+ <>
101
+ <ScrollView bounces={false} style={styles.flexShrink} contentContainerStyle={styles.sheetContent}>
102
+ {/* Emoji et couleur */}
103
+ <EmojiSelectWidget icon={icon} color={color} onChanged={(value) => (selection.current = value)} />
104
+ </ScrollView>
105
+ <SelectionBoutons
106
+ boutons={[
107
+ <ElevatedButton
108
+ key="enregistrer"
109
+ onPress={() => AppRouter.pop(router, { value: { emoji: selection.current.icon, color: selection.current.color } })}
110
+ >
111
+ {traductions.categorieFormSaveBtn}
112
+ </ElevatedButton>,
113
+ ]}
114
+ />
115
+ </>
116
+ }
117
+ />
107
118
  );
108
119
  }
109
120
 
110
121
  const styles = StyleSheet.create({
111
122
  fab: { width: 40, height: 40, borderRadius: 12, alignItems: 'center', justifyContent: 'center' },
112
123
  fabIcon: { width: 24, height: 24 },
113
- sheet: { borderRadius: 20, overflow: 'hidden' },
114
- sheetContent: { padding: 20 },
124
+ flexShrink: { flexShrink: 1 },
125
+ sheetContent: { paddingHorizontal: 20, paddingTop: 4, paddingBottom: 12 },
115
126
  optionsContent: { paddingHorizontal: 20, paddingTop: 8, paddingBottom: 16 },
116
127
  gap10: { height: 10 },
117
- saveBtn: { paddingVertical: 20, paddingHorizontal: 4 },
118
128
  });
@@ -1,16 +1,15 @@
1
1
  import { MaterialIcons } from '@expo/vector-icons';
2
- import { Image } from 'expo-image';
3
2
  import type { ReactNode } from 'react';
4
3
  import { Pressable, ScrollView, StyleSheet, Text, View } from 'react-native';
5
4
  import { useSafeAreaInsets } from 'react-native-safe-area-context';
6
5
 
7
- import { Images } from '../../../../core/assets';
8
6
  import { useBloc, useBlocBuilder, useBlocListener } from '../../../../core/bloc_react';
9
7
  import { AppRouter, useAppRouter } from '../../../../core/router';
10
8
  import { useTheme } from '../../../../core/theme';
11
9
  import { useAppLocalizations } from '../../../../l10n/localizations';
12
10
  import { ElevatedButton } from '../../../../shared/material/buttons';
13
11
  import { CustomTextInput } from '../../../../shared/widgets/input_text';
12
+ import { SelectionBoutons } from '../../../../shared/widgets/selection';
14
13
  import { Categorie } from '../../domain/models/categorie';
15
14
  import { CategorieCreateCommandError, CategorieUpdateCommandError } from '../../domain/models/categorie_commands';
16
15
  import { argbToCss } from '../../domain/models/categorie_icons';
@@ -23,26 +22,38 @@ import {
23
22
  CategorieUpdateEvent,
24
23
  } from '../bloc/categorie_event';
25
24
  import { CategorieCreationState, CategorieEditState, CategorieInitialState } from '../bloc/categorie_state';
26
- import { CategorieEditIconBtn } from './categorie_edit_icon_btn';
27
- import { CategorieIcon } from './categorie_icon';
25
+ import { ouvrirIconeCategorie } from './categorie_edit_icon_btn';
26
+ import { CategoriePastille } from './categorie_icon';
28
27
 
29
- /** Squelette commun : en-tête coloré (icône + titre + bouton icône), formulaire, bouton. */
28
+ /** Couleur ARGB d'une catégorie avec l'opacité [alpha] (0 à 1), en CSS. */
29
+ function argbAvecAlpha(argb: number | null | undefined, alpha: number): string | undefined {
30
+ const rgb = (argb ?? 0xfff9ebc2) & 0xffffff;
31
+ return argbToCss(((Math.round(alpha * 255) << 24) | rgb) >>> 0);
32
+ }
33
+
34
+ /**
35
+ * Squelette commun : aperçu de l'icône (toucher pour la changer), titre,
36
+ * formulaire, puis bouton fixé en bas.
37
+ */
30
38
  function CategorieFormLayout({
31
- header,
39
+ icon,
40
+ couleur,
32
41
  title,
33
42
  form,
34
43
  button,
35
44
  }: {
36
- header: ReactNode;
45
+ icon?: string | null;
46
+ couleur?: number | null;
37
47
  title: string;
38
48
  form: ReactNode;
39
49
  button: ReactNode;
40
50
  }) {
41
51
  const theme = useTheme();
52
+ const router = useAppRouter();
42
53
  const insets = useSafeAreaInsets();
43
54
  const categorieBloc = useBloc(CategorieBloc);
44
55
  return (
45
- <View style={[styles.flex, { backgroundColor: theme.secondaryHeaderColor }]}>
56
+ <View style={[styles.flex, { paddingBottom: insets.bottom }]}>
46
57
  <View style={styles.backRow}>
47
58
  <Pressable
48
59
  accessibilityRole="button"
@@ -53,23 +64,22 @@ function CategorieFormLayout({
53
64
  <MaterialIcons name="arrow-back" size={24} color={theme.colorScheme.onSurface} />
54
65
  </Pressable>
55
66
  </View>
56
- {/* Icône et titre */}
57
- <View style={styles.header}>
58
- <View style={styles.center}>{header}</View>
59
- <View style={styles.titleRow}>
60
- <Text numberOfLines={1} style={[theme.textTheme.titleSmall, styles.flex]}>
61
- {title}
62
- </Text>
63
- <CategorieEditIconBtn />
64
- </View>
65
- </View>
66
- {/* Formulaire */}
67
- <ScrollView style={[styles.flex, { backgroundColor: theme.scaffoldBackgroundColor }]} contentContainerStyle={styles.form}>
67
+ <ScrollView style={styles.flex} contentContainerStyle={styles.form}>
68
+ {/* Aperçu de l'icône, toucher pour la changer */}
69
+ <Pressable accessibilityRole="button" onPress={() => ouvrirIconeCategorie(router)} style={styles.apercu}>
70
+ <CategoriePastille icon={icon} bgColor={couleur} taille={112} />
71
+ {/* Badge modifier */}
72
+ <View style={[styles.badge, { backgroundColor: theme.colorScheme.primary, borderColor: theme.scaffoldBackgroundColor }]}>
73
+ <MaterialIcons name="edit" size={16} color={theme.colorScheme.onPrimary} />
74
+ </View>
75
+ </Pressable>
76
+ {/* Titre */}
77
+ <Text numberOfLines={1} style={[theme.textTheme.titleSmall, styles.titre]}>
78
+ {title}
79
+ </Text>
68
80
  {form}
69
81
  </ScrollView>
70
- <View style={[styles.button, { backgroundColor: theme.scaffoldBackgroundColor, paddingBottom: 20 + insets.bottom }]}>
71
- {button}
72
- </View>
82
+ <SelectionBoutons boutons={[button]} />
73
83
  </View>
74
84
  );
75
85
  }
@@ -89,7 +99,8 @@ export function CategorieAddPage() {
89
99
 
90
100
  return (
91
101
  <CategorieFormLayout
92
- header={<Image source={Images.categorie} style={styles.addIllustration} contentFit="contain" />}
102
+ icon={command.icon}
103
+ couleur={command.color}
93
104
  title={traductions.categorieCustomAdd}
94
105
  form={
95
106
  <>
@@ -122,9 +133,16 @@ export function CategorieAddPage() {
122
133
  command.color = c.bgColor;
123
134
  categorieBloc.add(new CategorieAddValidationEvent(command));
124
135
  }}
125
- style={[styles.chip, { backgroundColor: theme.secondaryHeaderColor, borderRadius: theme.chipTheme.borderRadius }]}
136
+ style={[
137
+ styles.chip,
138
+ {
139
+ backgroundColor: argbAvecAlpha(c.bgColor, 0.18),
140
+ borderColor: argbAvecAlpha(c.bgColor, 0.6),
141
+ },
142
+ ]}
126
143
  >
127
- <Text style={theme.chipTheme.labelStyle}>{c.label}</Text>
144
+ <CategoriePastille icon={c.icon} bgColor={c.bgColor} taille={26} />
145
+ <Text style={[theme.textTheme.displayMedium, styles.chipTexte]}>{c.label}</Text>
128
146
  </Pressable>
129
147
  ))}
130
148
  </View>
@@ -132,6 +150,7 @@ export function CategorieAddPage() {
132
150
  }
133
151
  button={
134
152
  <ElevatedButton
153
+ key="creer"
135
154
  onPress={() => {
136
155
  if (command.isValid()) categorieBloc.add(new CategorieCreateEvent(command));
137
156
  }}
@@ -156,13 +175,7 @@ export function CategorieEditPage() {
156
175
  const { categorie, command } = state;
157
176
 
158
177
  return (
159
- <CategorieFormLayout
160
- header={
161
- <View style={[styles.editIcon, { backgroundColor: argbToCss(command.color) }]}>
162
- <CategorieIcon icon={command.icon!} size={96} emojiSize={64} />
163
- </View>
164
- }
165
- title={categorie.label}
178
+ <CategorieFormLayout icon={command.icon} couleur={command.color} title={categorie.label}
166
179
  form={
167
180
  <View style={styles.input}>
168
181
  <CustomTextInput
@@ -178,6 +191,7 @@ export function CategorieEditPage() {
178
191
  }
179
192
  button={
180
193
  <ElevatedButton
194
+ key="enregistrer"
181
195
  onPress={() => {
182
196
  if (command.isValid()) categorieBloc.add(new CategorieUpdateEvent(command, categorie));
183
197
  }}
@@ -193,14 +207,30 @@ const styles = StyleSheet.create({
193
207
  flex: { flex: 1 },
194
208
  backRow: { flexDirection: 'row' },
195
209
  back: { padding: 12 },
196
- header: { height: 200, paddingHorizontal: 20, paddingBottom: 20, justifyContent: 'space-between' },
197
- center: { alignItems: 'center' },
198
- titleRow: { flexDirection: 'row', alignItems: 'center' },
199
- addIllustration: { width: 128, height: 110 },
200
- editIcon: { borderRadius: 999, paddingVertical: 10, paddingHorizontal: 15, alignItems: 'center', justifyContent: 'center' },
201
210
  form: { paddingHorizontal: 20, paddingBottom: 20 },
202
- input: { paddingVertical: 20 },
211
+ apercu: { alignSelf: 'center' },
212
+ badge: {
213
+ position: 'absolute',
214
+ right: 0,
215
+ bottom: 0,
216
+ width: 36,
217
+ height: 36,
218
+ borderRadius: 18,
219
+ borderWidth: 3,
220
+ alignItems: 'center',
221
+ justifyContent: 'center',
222
+ },
223
+ titre: { textAlign: 'center', marginTop: 14 },
224
+ input: { paddingTop: 24, paddingBottom: 16 },
203
225
  chips: { flexDirection: 'row', flexWrap: 'wrap', gap: 8 },
204
- chip: { paddingHorizontal: 12, paddingVertical: 8 },
205
- button: { padding: 20 },
226
+ chip: {
227
+ flexDirection: 'row',
228
+ alignItems: 'center',
229
+ paddingLeft: 4,
230
+ paddingRight: 12,
231
+ paddingVertical: 4,
232
+ borderRadius: 999,
233
+ borderWidth: 1,
234
+ },
235
+ chipTexte: { marginLeft: 8, fontWeight: '600' },
206
236
  });
@@ -1,6 +1,8 @@
1
1
  import { Image } from 'expo-image';
2
2
  import { StyleSheet, Text, View } from 'react-native';
3
3
 
4
+ import { Images } from '../../../../core/assets';
5
+ import { useTheme } from '../../../../core/theme';
4
6
  import { argbToCss, categorieIconSource, isAssetIcon } from '../../domain/models/categorie_icons';
5
7
 
6
8
  /** Icône d'une catégorie (image ou emoji), éventuellement dans un cercle coloré. */
@@ -33,6 +35,30 @@ export function CategorieIconCircle({ icon, bgColor }: { icon: string; bgColor?:
33
35
  );
34
36
  }
35
37
 
38
+ /**
39
+ * Pastille ronde d'une catégorie : [icon] (image ou emoji) sur sa
40
+ * [bgColor]. Sans [icon], l'illustration par défaut des catégories.
41
+ */
42
+ export function CategoriePastille({ icon, bgColor, taille = 44 }: { icon?: string | null; bgColor?: number | null; taille?: number }) {
43
+ const theme = useTheme();
44
+ return (
45
+ <View
46
+ style={[
47
+ styles.pastille,
48
+ { width: taille, height: taille, borderRadius: taille / 2 },
49
+ { backgroundColor: bgColor != null ? argbToCss(bgColor) : theme.colorScheme.surface },
50
+ ]}
51
+ >
52
+ {icon == null ? (
53
+ <Image source={Images.categorie} style={{ width: taille * 0.7, height: taille * 0.7 }} contentFit="contain" />
54
+ ) : (
55
+ <CategorieIcon icon={icon} size={taille * 0.5} emojiSize={taille * 0.48} />
56
+ )}
57
+ </View>
58
+ );
59
+ }
60
+
36
61
  const styles = StyleSheet.create({
62
+ pastille: { alignItems: 'center', justifyContent: 'center' },
37
63
  circle: { width: 45, height: 45, borderRadius: 22.5, alignItems: 'center', justifyContent: 'center' },
38
64
  });
@@ -5,27 +5,34 @@ import { Pressable, StyleSheet, Text, View } from 'react-native';
5
5
  import { useBloc } from '../../../../core/bloc_react';
6
6
  import { Themer, useTheme } from '../../../../core/theme';
7
7
  import { useAppLocalizations } from '../../../../l10n/localizations';
8
- import { TextButton } from '../../../../shared/material/buttons';
9
8
  import { Card } from '../../../../shared/material/card';
9
+ import { withAlpha } from '../../../../shared/utils/color';
10
10
  import type { Categorie } from '../../domain/models/categorie';
11
11
  import { CategorieBloc } from '../bloc/categorie_bloc';
12
12
  import { CategorieEditEvent } from '../bloc/categorie_event';
13
- import { CategorieIconCircle } from './categorie_icon';
13
+ import { CategoriePastille } from './categorie_icon';
14
14
 
15
- /** Liste de catégories à cocher (avec bouton « Modifier » si [editable]). */
15
+ /**
16
+ * Liste de catégories dans une carte : pastille, nom, bouton de
17
+ * modification si [editable] et, en sélection multiple, rond coché. En
18
+ * [selectionUnique], toucher une ligne la choisit (sans rond).
19
+ */
16
20
  export function CategorieListeWidget({
17
21
  liste,
18
22
  defaultSelectedCategories,
19
23
  onSelectionChanged,
20
24
  editable,
25
+ selectionUnique = false,
21
26
  }: {
22
27
  liste: readonly Categorie[];
23
28
  defaultSelectedCategories: string[];
24
29
  onSelectionChanged: (categorie: Categorie, checked: boolean) => void;
25
30
  editable?: boolean;
31
+ selectionUnique?: boolean;
26
32
  }) {
27
33
  const traductions = useAppLocalizations();
28
34
  const theme = useTheme();
35
+ const primaire = theme.colorScheme.primary;
29
36
  const categorieBloc = useBloc(CategorieBloc);
30
37
  // Catégories sélectionnées
31
38
  const [selected, setSelected] = useState<string[]>(() =>
@@ -33,39 +40,51 @@ export function CategorieListeWidget({
33
40
  );
34
41
 
35
42
  return (
36
- <Card>
43
+ <Card style={styles.carte}>
37
44
  <View style={styles.list}>
38
45
  {liste.map((categorie) => {
39
46
  const checked = selected.includes(categorie.id);
47
+ const marquee = checked && !selectionUnique;
40
48
  return (
41
49
  <Pressable
42
50
  key={categorie.id}
43
- accessibilityRole="checkbox"
51
+ accessibilityRole={selectionUnique ? 'button' : 'checkbox'}
44
52
  accessibilityState={{ checked }}
45
53
  onPress={() => {
46
- const value = !checked;
54
+ const value = selectionUnique ? true : !checked;
47
55
  setSelected((s) => (value ? [...s, categorie.id] : s.filter((id) => id !== categorie.id)));
48
56
  onSelectionChanged(categorie, value);
49
57
  }}
50
- style={styles.row}
58
+ style={({ pressed }) => [
59
+ styles.row,
60
+ { backgroundColor: marquee ? withAlpha(primaire, 0.08) : pressed ? theme.colorScheme.secondary : 'transparent' },
61
+ ]}
51
62
  >
52
- <MaterialIcons
53
- name={checked ? 'check-box' : 'check-box-outline-blank'}
54
- size={24}
55
- color={checked ? theme.colorScheme.primary : Themer.neural02Color}
56
- />
57
- <View style={styles.gap12} />
58
- <CategorieIconCircle icon={categorie.icon} bgColor={categorie.bgColor} />
59
- <View style={styles.gap12} />
63
+ <CategoriePastille icon={categorie.icon} bgColor={categorie.bgColor} />
60
64
  {/* Libellé */}
61
- <Text numberOfLines={1} style={[theme.textTheme.headlineSmall, styles.flex]}>
62
- {` ${categorie.label}`}
65
+ <Text numberOfLines={1} style={[theme.textTheme.displayLarge, styles.label, { fontWeight: marquee ? '700' : '500' }]}>
66
+ {categorie.label}
63
67
  </Text>
64
68
  {/* Bouton modifier */}
65
69
  {editable === true && (
66
- <TextButton onPress={() => categorieBloc.add(new CategorieEditEvent(categorie))}>
67
- {traductions.categorieEditBtn}
68
- </TextButton>
70
+ <Pressable
71
+ accessibilityRole="button"
72
+ accessibilityLabel={traductions.categorieEditBtn}
73
+ hitSlop={8}
74
+ style={styles.modifier}
75
+ onPress={() => categorieBloc.add(new CategorieEditEvent(categorie))}
76
+ >
77
+ <MaterialIcons name="edit" size={20} color={Themer.neural03Color} />
78
+ </Pressable>
79
+ )}
80
+ {/* Sélection multiple : rond coché */}
81
+ {!selectionUnique && (
82
+ <MaterialIcons
83
+ name={checked ? 'check-circle' : 'radio-button-unchecked'}
84
+ size={22}
85
+ color={checked ? primaire : Themer.neural03Color}
86
+ style={styles.coche}
87
+ />
69
88
  )}
70
89
  </Pressable>
71
90
  );
@@ -76,8 +95,10 @@ export function CategorieListeWidget({
76
95
  }
77
96
 
78
97
  const styles = StyleSheet.create({
79
- list: { paddingVertical: 8 },
80
- row: { flexDirection: 'row', alignItems: 'center', paddingHorizontal: 16, paddingVertical: 8 },
81
- gap12: { width: 12 },
82
- flex: { flex: 1 },
98
+ carte: { margin: 0 },
99
+ list: { padding: 6 },
100
+ row: { flexDirection: 'row', alignItems: 'center', marginVertical: 1, paddingHorizontal: 8, paddingVertical: 8, borderRadius: 14 },
101
+ label: { flex: 1, marginLeft: 14 },
102
+ modifier: { padding: 8 },
103
+ coche: { marginHorizontal: 4 },
83
104
  });