create-du-app 0.1.2 → 0.1.4

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 (421) hide show
  1. package/README.md +56 -36
  2. package/package.json +6 -5
  3. package/src/generate.js +246 -15
  4. package/src/index.js +8 -8
  5. package/src/prompts.js +1 -1
  6. package/src/registry.js +3 -1
  7. package/templates/mobile/expo/.env.example +5 -0
  8. package/templates/mobile/expo/.eslintrc.js +7 -0
  9. package/templates/mobile/expo/.prettierrc.js +7 -0
  10. package/templates/mobile/expo/.svgrrc.js +9 -0
  11. package/templates/mobile/expo/README.md +42 -7
  12. package/templates/mobile/expo/_gitignore +20 -0
  13. package/templates/mobile/expo/_package.json +62 -1
  14. package/templates/mobile/expo/app.json +18 -0
  15. package/templates/mobile/expo/babel.config.js +21 -0
  16. package/templates/mobile/expo/index.js +5 -0
  17. package/templates/mobile/expo/metro.config.js +31 -0
  18. package/templates/mobile/expo/src/app/App.tsx +24 -0
  19. package/templates/mobile/expo/src/app/app-provider.tsx +36 -0
  20. package/templates/mobile/expo/src/app/config/translation.ts +26 -0
  21. package/templates/mobile/expo/src/app/index.ts +1 -0
  22. package/templates/mobile/expo/src/app/navigation/app-route-type.ts +27 -0
  23. package/templates/mobile/expo/src/app/navigation/bottom-tabs.tsx +34 -0
  24. package/templates/mobile/expo/src/app/navigation/index.tsx +14 -0
  25. package/templates/mobile/expo/src/app/stores/auth.store.ts +33 -0
  26. package/templates/mobile/expo/src/app/stores/common.store.ts +19 -0
  27. package/templates/mobile/expo/src/app/stores/index.ts +3 -0
  28. package/templates/mobile/expo/src/app/stores/loading.store.ts +22 -0
  29. package/templates/mobile/expo/src/assets/Images/empty-list.png +0 -0
  30. package/templates/mobile/expo/src/assets/Images/index.ts +5 -0
  31. package/templates/mobile/expo/src/assets/Images/screen-bg-gradian.png +0 -0
  32. package/templates/mobile/expo/src/assets/i18n/en.json +12 -0
  33. package/templates/mobile/expo/src/assets/i18n/fr.json +12 -0
  34. package/templates/mobile/expo/src/assets/lotties/index.ts +3 -0
  35. package/templates/mobile/expo/src/assets/lotties/loading.json +1 -0
  36. package/templates/mobile/expo/src/assets/svgs/arrow-left.svg +3 -0
  37. package/templates/mobile/expo/src/assets/svgs/arrow-right.svg +3 -0
  38. package/templates/mobile/expo/src/assets/svgs/calendar.svg +12 -0
  39. package/templates/mobile/expo/src/assets/svgs/check.svg +3 -0
  40. package/templates/mobile/expo/src/assets/svgs/close.svg +3 -0
  41. package/templates/mobile/expo/src/assets/svgs/eye-hide.svg +3 -0
  42. package/templates/mobile/expo/src/assets/svgs/eye.svg +4 -0
  43. package/templates/mobile/expo/src/assets/svgs/index.ts +29 -0
  44. package/templates/mobile/expo/src/assets/svgs/minus.svg +3 -0
  45. package/templates/mobile/expo/src/assets/svgs/plus.svg +3 -0
  46. package/templates/mobile/expo/src/assets/svgs/search.svg +3 -0
  47. package/templates/mobile/expo/src/assets/svgs/toast-error.svg +5 -0
  48. package/templates/mobile/expo/src/assets/svgs/toast-success.svg +4 -0
  49. package/templates/mobile/expo/src/core/api/endpoints.ts +8 -0
  50. package/templates/mobile/expo/src/core/api/example.api.ts +53 -0
  51. package/templates/mobile/expo/src/core/api/index.ts +4 -0
  52. package/templates/mobile/expo/src/core/components/common/index.ts +1 -0
  53. package/templates/mobile/expo/src/core/components/common/list-empty/index.ts +2 -0
  54. package/templates/mobile/expo/src/core/components/common/list-empty/list-empty.tsx +30 -0
  55. package/templates/mobile/expo/src/core/components/common/list-empty/list-empty.type.ts +5 -0
  56. package/templates/mobile/expo/src/core/components/forms/hf-date-time.tsx +301 -0
  57. package/templates/mobile/expo/src/core/components/forms/hf-password-input.tsx +153 -0
  58. package/templates/mobile/expo/src/core/components/forms/hf-text-input.tsx +59 -0
  59. package/templates/mobile/expo/src/core/components/forms/hf-time-picker.tsx +117 -0
  60. package/templates/mobile/expo/src/core/components/forms/index.ts +4 -0
  61. package/templates/mobile/expo/src/core/components/index.ts +5 -0
  62. package/templates/mobile/expo/src/core/components/loading/index.ts +1 -0
  63. package/templates/mobile/expo/src/core/components/loading/loading-app/index.ts +1 -0
  64. package/templates/mobile/expo/src/core/components/loading/loading-app/loading-app.tsx +50 -0
  65. package/templates/mobile/expo/src/core/components/offline/index.ts +1 -0
  66. package/templates/mobile/expo/src/core/components/offline/offline-banner.tsx +186 -0
  67. package/templates/mobile/expo/src/core/components/screen/index.ts +1 -0
  68. package/templates/mobile/expo/src/core/components/screen/screen-container/index.ts +1 -0
  69. package/templates/mobile/expo/src/core/components/screen/screen-container/screen-container.tsx +252 -0
  70. package/templates/mobile/expo/src/core/components/splash/index.ts +1 -0
  71. package/templates/mobile/expo/src/core/components/splash/splash-overlay/index.ts +1 -0
  72. package/templates/mobile/expo/src/core/components/splash/splash-overlay/splash-overlay.tsx +93 -0
  73. package/templates/mobile/expo/src/core/components/ui/animated-list-item/animated-list-item.tsx +48 -0
  74. package/templates/mobile/expo/src/core/components/ui/animated-list-item/animated-list-item.type.ts +10 -0
  75. package/templates/mobile/expo/src/core/components/ui/animated-list-item/index.ts +2 -0
  76. package/templates/mobile/expo/src/core/components/ui/app-image/app-image.tsx +104 -0
  77. package/templates/mobile/expo/src/core/components/ui/app-image/app-image.type.ts +19 -0
  78. package/templates/mobile/expo/src/core/components/ui/app-image/index.ts +2 -0
  79. package/templates/mobile/expo/src/core/components/ui/asset-placeholder/asset-placeholder.tsx +76 -0
  80. package/templates/mobile/expo/src/core/components/ui/asset-placeholder/index.ts +1 -0
  81. package/templates/mobile/expo/src/core/components/ui/avatar-image/avatar-image.tsx +90 -0
  82. package/templates/mobile/expo/src/core/components/ui/avatar-image/index.ts +1 -0
  83. package/templates/mobile/expo/src/core/components/ui/bottom-sheet/bottom-sheet.tsx +145 -0
  84. package/templates/mobile/expo/src/core/components/ui/bottom-sheet/bottom-sheet.type.ts +10 -0
  85. package/templates/mobile/expo/src/core/components/ui/bottom-sheet/index.ts +2 -0
  86. package/templates/mobile/expo/src/core/components/ui/button/button.style.ts +146 -0
  87. package/templates/mobile/expo/src/core/components/ui/button/button.tsx +97 -0
  88. package/templates/mobile/expo/src/core/components/ui/button/button.type.ts +47 -0
  89. package/templates/mobile/expo/src/core/components/ui/button/index.ts +4 -0
  90. package/templates/mobile/expo/src/core/components/ui/checkbox/checkbox.tsx +127 -0
  91. package/templates/mobile/expo/src/core/components/ui/checkbox/checkbox.type.ts +24 -0
  92. package/templates/mobile/expo/src/core/components/ui/checkbox/index.ts +2 -0
  93. package/templates/mobile/expo/src/core/components/ui/collapsible-section/collapsible-section.tsx +141 -0
  94. package/templates/mobile/expo/src/core/components/ui/collapsible-section/collapsible-section.type.ts +10 -0
  95. package/templates/mobile/expo/src/core/components/ui/collapsible-section/index.ts +2 -0
  96. package/templates/mobile/expo/src/core/components/ui/components.registry.json +313 -0
  97. package/templates/mobile/expo/src/core/components/ui/field/field-frame.tsx +62 -0
  98. package/templates/mobile/expo/src/core/components/ui/field/field.shared.ts +31 -0
  99. package/templates/mobile/expo/src/core/components/ui/header/header.tsx +196 -0
  100. package/templates/mobile/expo/src/core/components/ui/header/header.type.ts +30 -0
  101. package/templates/mobile/expo/src/core/components/ui/header/index.ts +2 -0
  102. package/templates/mobile/expo/src/core/components/ui/icon-button/icon-button.style.ts +23 -0
  103. package/templates/mobile/expo/src/core/components/ui/icon-button/icon-button.tsx +66 -0
  104. package/templates/mobile/expo/src/core/components/ui/icon-button/icon-button.type.ts +25 -0
  105. package/templates/mobile/expo/src/core/components/ui/icon-button/index.ts +2 -0
  106. package/templates/mobile/expo/src/core/components/ui/image-slider/image-slider.tsx +107 -0
  107. package/templates/mobile/expo/src/core/components/ui/image-slider/image-slider.type.ts +10 -0
  108. package/templates/mobile/expo/src/core/components/ui/image-slider/index.ts +2 -0
  109. package/templates/mobile/expo/src/core/components/ui/index.ts +25 -0
  110. package/templates/mobile/expo/src/core/components/ui/label/index.ts +2 -0
  111. package/templates/mobile/expo/src/core/components/ui/label/label.tsx +36 -0
  112. package/templates/mobile/expo/src/core/components/ui/label/label.type.ts +12 -0
  113. package/templates/mobile/expo/src/core/components/ui/modal/index.ts +2 -0
  114. package/templates/mobile/expo/src/core/components/ui/modal/modal.tsx +62 -0
  115. package/templates/mobile/expo/src/core/components/ui/modal/modal.type.ts +11 -0
  116. package/templates/mobile/expo/src/core/components/ui/otp-input/index.ts +2 -0
  117. package/templates/mobile/expo/src/core/components/ui/otp-input/otp-input.tsx +129 -0
  118. package/templates/mobile/expo/src/core/components/ui/otp-input/otp-input.type.ts +20 -0
  119. package/templates/mobile/expo/src/core/components/ui/page-dots/index.ts +1 -0
  120. package/templates/mobile/expo/src/core/components/ui/page-dots/page-dots.tsx +60 -0
  121. package/templates/mobile/expo/src/core/components/ui/radio/index.ts +2 -0
  122. package/templates/mobile/expo/src/core/components/ui/radio/radio.tsx +121 -0
  123. package/templates/mobile/expo/src/core/components/ui/radio/radio.type.ts +20 -0
  124. package/templates/mobile/expo/src/core/components/ui/screen/index.ts +1 -0
  125. package/templates/mobile/expo/src/core/components/ui/screen/screen-gradient.tsx +33 -0
  126. package/templates/mobile/expo/src/core/components/ui/search-box/index.ts +2 -0
  127. package/templates/mobile/expo/src/core/components/ui/search-box/search-box.tsx +162 -0
  128. package/templates/mobile/expo/src/core/components/ui/search-box/search-box.type.ts +26 -0
  129. package/templates/mobile/expo/src/core/components/ui/segmented-control/index.ts +2 -0
  130. package/templates/mobile/expo/src/core/components/ui/segmented-control/segmented-control.tsx +86 -0
  131. package/templates/mobile/expo/src/core/components/ui/segmented-control/segmented-control.type.ts +22 -0
  132. package/templates/mobile/expo/src/core/components/ui/skeleton/index.ts +2 -0
  133. package/templates/mobile/expo/src/core/components/ui/skeleton/skeleton.tsx +106 -0
  134. package/templates/mobile/expo/src/core/components/ui/skeleton/skeleton.type.ts +8 -0
  135. package/templates/mobile/expo/src/core/components/ui/success-state/index.ts +1 -0
  136. package/templates/mobile/expo/src/core/components/ui/success-state/success-state.tsx +68 -0
  137. package/templates/mobile/expo/src/core/components/ui/tabs/index.ts +2 -0
  138. package/templates/mobile/expo/src/core/components/ui/tabs/tabs.tsx +273 -0
  139. package/templates/mobile/expo/src/core/components/ui/tabs/tabs.type.ts +21 -0
  140. package/templates/mobile/expo/src/core/components/ui/tag-input/index.ts +2 -0
  141. package/templates/mobile/expo/src/core/components/ui/tag-input/tag-input.tsx +146 -0
  142. package/templates/mobile/expo/src/core/components/ui/tag-input/tag-input.type.ts +22 -0
  143. package/templates/mobile/expo/src/core/components/ui/text-area/index.ts +2 -0
  144. package/templates/mobile/expo/src/core/components/ui/text-area/text-area.tsx +90 -0
  145. package/templates/mobile/expo/src/core/components/ui/text-area/text-area.type.ts +20 -0
  146. package/templates/mobile/expo/src/core/components/ui/text-field/index.ts +2 -0
  147. package/templates/mobile/expo/src/core/components/ui/text-field/text-field.tsx +116 -0
  148. package/templates/mobile/expo/src/core/components/ui/text-field/text-field.type.ts +21 -0
  149. package/templates/mobile/expo/src/core/components/ui/toggle/index.ts +2 -0
  150. package/templates/mobile/expo/src/core/components/ui/toggle/toggle.tsx +110 -0
  151. package/templates/mobile/expo/src/core/components/ui/toggle/toggle.type.ts +19 -0
  152. package/templates/mobile/expo/src/core/constants/external-urls.constant.ts +5 -0
  153. package/templates/mobile/expo/src/core/constants/hard-data.constant.ts +0 -0
  154. package/templates/mobile/expo/src/core/constants/index.ts +2 -0
  155. package/templates/mobile/expo/src/core/constants/type.constant.ts +3 -0
  156. package/templates/mobile/expo/src/core/context/index.ts +1 -0
  157. package/templates/mobile/expo/src/core/context/shared-transition-context.tsx +35 -0
  158. package/templates/mobile/expo/src/core/hook/index.ts +8 -0
  159. package/templates/mobile/expo/src/core/hook/useActiveRouteName.ts +63 -0
  160. package/templates/mobile/expo/src/core/hook/useAppNavigation.tsx +7 -0
  161. package/templates/mobile/expo/src/core/hook/useBottomInset.tsx +26 -0
  162. package/templates/mobile/expo/src/core/hook/useDebounce.tsx +16 -0
  163. package/templates/mobile/expo/src/core/hook/useEndReached.tsx +46 -0
  164. package/templates/mobile/expo/src/core/hook/useManualRefetch.ts +56 -0
  165. package/templates/mobile/expo/src/core/hook/useNetworkStatus.ts +68 -0
  166. package/templates/mobile/expo/src/core/hook/useTimeout.tsx +30 -0
  167. package/templates/mobile/expo/src/core/index.ts +7 -0
  168. package/templates/mobile/expo/src/core/services/api.service.ts +230 -0
  169. package/templates/mobile/expo/src/core/services/device-id.service.ts +23 -0
  170. package/templates/mobile/expo/src/core/services/index.ts +3 -0
  171. package/templates/mobile/expo/src/core/services/session-end.bridge.ts +26 -0
  172. package/templates/mobile/expo/src/core/theme/dark.theme.ts +10 -0
  173. package/templates/mobile/expo/src/core/theme/index.ts +5 -0
  174. package/templates/mobile/expo/src/core/theme/light.theme.ts +44 -0
  175. package/templates/mobile/expo/src/core/theme/theme-context.tsx +82 -0
  176. package/templates/mobile/expo/src/core/theme/theme.types.ts +26 -0
  177. package/templates/mobile/expo/src/core/theme/use-themed-styles.ts +25 -0
  178. package/templates/mobile/expo/src/core/utils/color.util.tsx +198 -0
  179. package/templates/mobile/expo/src/core/utils/date.util.ts +97 -0
  180. package/templates/mobile/expo/src/core/utils/device-locale.util.ts +22 -0
  181. package/templates/mobile/expo/src/core/utils/emitter/index.ts +161 -0
  182. package/templates/mobile/expo/src/core/utils/emitter/type.ts +40 -0
  183. package/templates/mobile/expo/src/core/utils/enum.util.tsx +15 -0
  184. package/templates/mobile/expo/src/core/utils/font.util.tsx +42 -0
  185. package/templates/mobile/expo/src/core/utils/func.util.ts +48 -0
  186. package/templates/mobile/expo/src/core/utils/greeting.util.ts +20 -0
  187. package/templates/mobile/expo/src/core/utils/image-format.util.ts +117 -0
  188. package/templates/mobile/expo/src/core/utils/image-picker.util.ts +84 -0
  189. package/templates/mobile/expo/src/core/utils/index.ts +18 -0
  190. package/templates/mobile/expo/src/core/utils/linking.util.ts +16 -0
  191. package/templates/mobile/expo/src/core/utils/navigation.util.tsx +100 -0
  192. package/templates/mobile/expo/src/core/utils/number-format.ts +28 -0
  193. package/templates/mobile/expo/src/core/utils/query-client.util.ts +35 -0
  194. package/templates/mobile/expo/src/core/utils/query-persister.util.ts +36 -0
  195. package/templates/mobile/expo/src/core/utils/schema.util.tsx +2713 -0
  196. package/templates/mobile/expo/src/core/utils/size.util.tsx +74 -0
  197. package/templates/mobile/expo/src/core/utils/storage.util.tsx +53 -0
  198. package/templates/mobile/expo/src/core/utils/toast.util.tsx +151 -0
  199. package/templates/mobile/expo/src/core/utils/translator.util.tsx +23 -0
  200. package/templates/mobile/expo/src/core/utils/typography.util.tsx +69 -0
  201. package/templates/mobile/expo/src/core/utils/validate.util.tsx +13 -0
  202. package/templates/mobile/expo/src/declarations.d.ts +54 -0
  203. package/templates/mobile/expo/src/modules/home/home.screen.tsx +33 -0
  204. package/templates/mobile/expo/src/modules/profile/profile.screen.tsx +29 -0
  205. package/templates/mobile/expo/src/scripts/link-fonts.js +60 -0
  206. package/templates/mobile/expo/src/scripts/sync-images.js +56 -0
  207. package/templates/mobile/expo/src/scripts/sync-svgs.js +50 -0
  208. package/templates/mobile/expo/src/types/models.d.ts +24 -0
  209. package/templates/mobile/expo/tsconfig.json +19 -0
  210. package/templates/mobile/rn/.env.example +5 -0
  211. package/templates/mobile/rn/.eslintrc.js +7 -0
  212. package/templates/mobile/rn/.prettierrc.js +7 -0
  213. package/templates/mobile/rn/.svgrrc.js +9 -0
  214. package/templates/mobile/rn/README.md +40 -7
  215. package/templates/mobile/rn/_gitignore +24 -0
  216. package/templates/mobile/rn/_package.json +67 -1
  217. package/templates/mobile/rn/app.json +4 -0
  218. package/templates/mobile/rn/babel.config.js +18 -0
  219. package/templates/mobile/rn/index.js +8 -0
  220. package/templates/mobile/rn/metro.config.js +33 -0
  221. package/templates/mobile/rn/src/app/App.tsx +24 -0
  222. package/templates/mobile/rn/src/app/app-provider.tsx +36 -0
  223. package/templates/mobile/rn/src/app/config/translation.ts +26 -0
  224. package/templates/mobile/rn/src/app/index.ts +1 -0
  225. package/templates/mobile/rn/src/app/navigation/app-route-type.ts +27 -0
  226. package/templates/mobile/rn/src/app/navigation/bottom-tabs.tsx +34 -0
  227. package/templates/mobile/rn/src/app/navigation/index.tsx +14 -0
  228. package/templates/mobile/rn/src/app/stores/auth.store.ts +33 -0
  229. package/templates/mobile/rn/src/app/stores/common.store.ts +19 -0
  230. package/templates/mobile/rn/src/app/stores/index.ts +3 -0
  231. package/templates/mobile/rn/src/app/stores/loading.store.ts +22 -0
  232. package/templates/mobile/rn/src/assets/Images/empty-list.png +0 -0
  233. package/templates/mobile/rn/src/assets/Images/index.ts +5 -0
  234. package/templates/mobile/rn/src/assets/Images/screen-bg-gradian.png +0 -0
  235. package/templates/mobile/rn/src/assets/i18n/en.json +12 -0
  236. package/templates/mobile/rn/src/assets/i18n/fr.json +12 -0
  237. package/templates/mobile/rn/src/assets/lotties/index.ts +3 -0
  238. package/templates/mobile/rn/src/assets/lotties/loading.json +1 -0
  239. package/templates/mobile/rn/src/assets/svgs/arrow-left.svg +3 -0
  240. package/templates/mobile/rn/src/assets/svgs/arrow-right.svg +3 -0
  241. package/templates/mobile/rn/src/assets/svgs/calendar.svg +12 -0
  242. package/templates/mobile/rn/src/assets/svgs/check.svg +3 -0
  243. package/templates/mobile/rn/src/assets/svgs/close.svg +3 -0
  244. package/templates/mobile/rn/src/assets/svgs/eye-hide.svg +3 -0
  245. package/templates/mobile/rn/src/assets/svgs/eye.svg +4 -0
  246. package/templates/mobile/rn/src/assets/svgs/index.ts +29 -0
  247. package/templates/mobile/rn/src/assets/svgs/minus.svg +3 -0
  248. package/templates/mobile/rn/src/assets/svgs/plus.svg +3 -0
  249. package/templates/mobile/rn/src/assets/svgs/search.svg +3 -0
  250. package/templates/mobile/rn/src/assets/svgs/toast-error.svg +5 -0
  251. package/templates/mobile/rn/src/assets/svgs/toast-success.svg +4 -0
  252. package/templates/mobile/rn/src/core/api/endpoints.ts +8 -0
  253. package/templates/mobile/rn/src/core/api/example.api.ts +53 -0
  254. package/templates/mobile/rn/src/core/api/index.ts +4 -0
  255. package/templates/mobile/rn/src/core/components/common/index.ts +1 -0
  256. package/templates/mobile/rn/src/core/components/common/list-empty/index.ts +2 -0
  257. package/templates/mobile/rn/src/core/components/common/list-empty/list-empty.tsx +30 -0
  258. package/templates/mobile/rn/src/core/components/common/list-empty/list-empty.type.ts +5 -0
  259. package/templates/mobile/rn/src/core/components/forms/hf-date-time.tsx +301 -0
  260. package/templates/mobile/rn/src/core/components/forms/hf-password-input.tsx +153 -0
  261. package/templates/mobile/rn/src/core/components/forms/hf-text-input.tsx +59 -0
  262. package/templates/mobile/rn/src/core/components/forms/hf-time-picker.tsx +117 -0
  263. package/templates/mobile/rn/src/core/components/forms/index.ts +4 -0
  264. package/templates/mobile/rn/src/core/components/index.ts +5 -0
  265. package/templates/mobile/rn/src/core/components/loading/index.ts +1 -0
  266. package/templates/mobile/rn/src/core/components/loading/loading-app/index.ts +1 -0
  267. package/templates/mobile/rn/src/core/components/loading/loading-app/loading-app.tsx +50 -0
  268. package/templates/mobile/rn/src/core/components/offline/index.ts +1 -0
  269. package/templates/mobile/rn/src/core/components/offline/offline-banner.tsx +186 -0
  270. package/templates/mobile/rn/src/core/components/screen/index.ts +1 -0
  271. package/templates/mobile/rn/src/core/components/screen/screen-container/index.ts +1 -0
  272. package/templates/mobile/rn/src/core/components/screen/screen-container/screen-container.tsx +252 -0
  273. package/templates/mobile/rn/src/core/components/splash/index.ts +1 -0
  274. package/templates/mobile/rn/src/core/components/splash/splash-overlay/index.ts +1 -0
  275. package/templates/mobile/rn/src/core/components/splash/splash-overlay/splash-overlay.tsx +93 -0
  276. package/templates/mobile/rn/src/core/components/ui/animated-list-item/animated-list-item.tsx +48 -0
  277. package/templates/mobile/rn/src/core/components/ui/animated-list-item/animated-list-item.type.ts +10 -0
  278. package/templates/mobile/rn/src/core/components/ui/animated-list-item/index.ts +2 -0
  279. package/templates/mobile/rn/src/core/components/ui/app-image/app-image.tsx +104 -0
  280. package/templates/mobile/rn/src/core/components/ui/app-image/app-image.type.ts +19 -0
  281. package/templates/mobile/rn/src/core/components/ui/app-image/index.ts +2 -0
  282. package/templates/mobile/rn/src/core/components/ui/asset-placeholder/asset-placeholder.tsx +76 -0
  283. package/templates/mobile/rn/src/core/components/ui/asset-placeholder/index.ts +1 -0
  284. package/templates/mobile/rn/src/core/components/ui/avatar-image/avatar-image.tsx +90 -0
  285. package/templates/mobile/rn/src/core/components/ui/avatar-image/index.ts +1 -0
  286. package/templates/mobile/rn/src/core/components/ui/bottom-sheet/bottom-sheet.tsx +145 -0
  287. package/templates/mobile/rn/src/core/components/ui/bottom-sheet/bottom-sheet.type.ts +10 -0
  288. package/templates/mobile/rn/src/core/components/ui/bottom-sheet/index.ts +2 -0
  289. package/templates/mobile/rn/src/core/components/ui/button/button.style.ts +146 -0
  290. package/templates/mobile/rn/src/core/components/ui/button/button.tsx +97 -0
  291. package/templates/mobile/rn/src/core/components/ui/button/button.type.ts +47 -0
  292. package/templates/mobile/rn/src/core/components/ui/button/index.ts +4 -0
  293. package/templates/mobile/rn/src/core/components/ui/checkbox/checkbox.tsx +127 -0
  294. package/templates/mobile/rn/src/core/components/ui/checkbox/checkbox.type.ts +24 -0
  295. package/templates/mobile/rn/src/core/components/ui/checkbox/index.ts +2 -0
  296. package/templates/mobile/rn/src/core/components/ui/collapsible-section/collapsible-section.tsx +141 -0
  297. package/templates/mobile/rn/src/core/components/ui/collapsible-section/collapsible-section.type.ts +10 -0
  298. package/templates/mobile/rn/src/core/components/ui/collapsible-section/index.ts +2 -0
  299. package/templates/mobile/rn/src/core/components/ui/components.registry.json +313 -0
  300. package/templates/mobile/rn/src/core/components/ui/field/field-frame.tsx +62 -0
  301. package/templates/mobile/rn/src/core/components/ui/field/field.shared.ts +31 -0
  302. package/templates/mobile/rn/src/core/components/ui/header/header.tsx +196 -0
  303. package/templates/mobile/rn/src/core/components/ui/header/header.type.ts +30 -0
  304. package/templates/mobile/rn/src/core/components/ui/header/index.ts +2 -0
  305. package/templates/mobile/rn/src/core/components/ui/icon-button/icon-button.style.ts +23 -0
  306. package/templates/mobile/rn/src/core/components/ui/icon-button/icon-button.tsx +66 -0
  307. package/templates/mobile/rn/src/core/components/ui/icon-button/icon-button.type.ts +25 -0
  308. package/templates/mobile/rn/src/core/components/ui/icon-button/index.ts +2 -0
  309. package/templates/mobile/rn/src/core/components/ui/image-slider/image-slider.tsx +107 -0
  310. package/templates/mobile/rn/src/core/components/ui/image-slider/image-slider.type.ts +10 -0
  311. package/templates/mobile/rn/src/core/components/ui/image-slider/index.ts +2 -0
  312. package/templates/mobile/rn/src/core/components/ui/index.ts +25 -0
  313. package/templates/mobile/rn/src/core/components/ui/label/index.ts +2 -0
  314. package/templates/mobile/rn/src/core/components/ui/label/label.tsx +36 -0
  315. package/templates/mobile/rn/src/core/components/ui/label/label.type.ts +12 -0
  316. package/templates/mobile/rn/src/core/components/ui/modal/index.ts +2 -0
  317. package/templates/mobile/rn/src/core/components/ui/modal/modal.tsx +62 -0
  318. package/templates/mobile/rn/src/core/components/ui/modal/modal.type.ts +11 -0
  319. package/templates/mobile/rn/src/core/components/ui/otp-input/index.ts +2 -0
  320. package/templates/mobile/rn/src/core/components/ui/otp-input/otp-input.tsx +129 -0
  321. package/templates/mobile/rn/src/core/components/ui/otp-input/otp-input.type.ts +20 -0
  322. package/templates/mobile/rn/src/core/components/ui/page-dots/index.ts +1 -0
  323. package/templates/mobile/rn/src/core/components/ui/page-dots/page-dots.tsx +60 -0
  324. package/templates/mobile/rn/src/core/components/ui/radio/index.ts +2 -0
  325. package/templates/mobile/rn/src/core/components/ui/radio/radio.tsx +121 -0
  326. package/templates/mobile/rn/src/core/components/ui/radio/radio.type.ts +20 -0
  327. package/templates/mobile/rn/src/core/components/ui/screen/index.ts +1 -0
  328. package/templates/mobile/rn/src/core/components/ui/screen/screen-gradient.tsx +33 -0
  329. package/templates/mobile/rn/src/core/components/ui/search-box/index.ts +2 -0
  330. package/templates/mobile/rn/src/core/components/ui/search-box/search-box.tsx +162 -0
  331. package/templates/mobile/rn/src/core/components/ui/search-box/search-box.type.ts +26 -0
  332. package/templates/mobile/rn/src/core/components/ui/segmented-control/index.ts +2 -0
  333. package/templates/mobile/rn/src/core/components/ui/segmented-control/segmented-control.tsx +86 -0
  334. package/templates/mobile/rn/src/core/components/ui/segmented-control/segmented-control.type.ts +22 -0
  335. package/templates/mobile/rn/src/core/components/ui/skeleton/index.ts +2 -0
  336. package/templates/mobile/rn/src/core/components/ui/skeleton/skeleton.tsx +106 -0
  337. package/templates/mobile/rn/src/core/components/ui/skeleton/skeleton.type.ts +8 -0
  338. package/templates/mobile/rn/src/core/components/ui/success-state/index.ts +1 -0
  339. package/templates/mobile/rn/src/core/components/ui/success-state/success-state.tsx +68 -0
  340. package/templates/mobile/rn/src/core/components/ui/tabs/index.ts +2 -0
  341. package/templates/mobile/rn/src/core/components/ui/tabs/tabs.tsx +273 -0
  342. package/templates/mobile/rn/src/core/components/ui/tabs/tabs.type.ts +21 -0
  343. package/templates/mobile/rn/src/core/components/ui/tag-input/index.ts +2 -0
  344. package/templates/mobile/rn/src/core/components/ui/tag-input/tag-input.tsx +146 -0
  345. package/templates/mobile/rn/src/core/components/ui/tag-input/tag-input.type.ts +22 -0
  346. package/templates/mobile/rn/src/core/components/ui/text-area/index.ts +2 -0
  347. package/templates/mobile/rn/src/core/components/ui/text-area/text-area.tsx +90 -0
  348. package/templates/mobile/rn/src/core/components/ui/text-area/text-area.type.ts +20 -0
  349. package/templates/mobile/rn/src/core/components/ui/text-field/index.ts +2 -0
  350. package/templates/mobile/rn/src/core/components/ui/text-field/text-field.tsx +116 -0
  351. package/templates/mobile/rn/src/core/components/ui/text-field/text-field.type.ts +21 -0
  352. package/templates/mobile/rn/src/core/components/ui/toggle/index.ts +2 -0
  353. package/templates/mobile/rn/src/core/components/ui/toggle/toggle.tsx +110 -0
  354. package/templates/mobile/rn/src/core/components/ui/toggle/toggle.type.ts +19 -0
  355. package/templates/mobile/rn/src/core/constants/external-urls.constant.ts +5 -0
  356. package/templates/mobile/rn/src/core/constants/hard-data.constant.ts +0 -0
  357. package/templates/mobile/rn/src/core/constants/index.ts +2 -0
  358. package/templates/mobile/rn/src/core/constants/type.constant.ts +3 -0
  359. package/templates/mobile/rn/src/core/context/index.ts +1 -0
  360. package/templates/mobile/rn/src/core/context/shared-transition-context.tsx +35 -0
  361. package/templates/mobile/rn/src/core/hook/index.ts +8 -0
  362. package/templates/mobile/rn/src/core/hook/useActiveRouteName.ts +63 -0
  363. package/templates/mobile/rn/src/core/hook/useAppNavigation.tsx +7 -0
  364. package/templates/mobile/rn/src/core/hook/useBottomInset.tsx +26 -0
  365. package/templates/mobile/rn/src/core/hook/useDebounce.tsx +16 -0
  366. package/templates/mobile/rn/src/core/hook/useEndReached.tsx +46 -0
  367. package/templates/mobile/rn/src/core/hook/useManualRefetch.ts +56 -0
  368. package/templates/mobile/rn/src/core/hook/useNetworkStatus.ts +68 -0
  369. package/templates/mobile/rn/src/core/hook/useTimeout.tsx +30 -0
  370. package/templates/mobile/rn/src/core/index.ts +7 -0
  371. package/templates/mobile/rn/src/core/services/api.service.ts +230 -0
  372. package/templates/mobile/rn/src/core/services/device-id.service.ts +23 -0
  373. package/templates/mobile/rn/src/core/services/index.ts +3 -0
  374. package/templates/mobile/rn/src/core/services/session-end.bridge.ts +26 -0
  375. package/templates/mobile/rn/src/core/theme/dark.theme.ts +10 -0
  376. package/templates/mobile/rn/src/core/theme/index.ts +5 -0
  377. package/templates/mobile/rn/src/core/theme/light.theme.ts +44 -0
  378. package/templates/mobile/rn/src/core/theme/theme-context.tsx +82 -0
  379. package/templates/mobile/rn/src/core/theme/theme.types.ts +26 -0
  380. package/templates/mobile/rn/src/core/theme/use-themed-styles.ts +25 -0
  381. package/templates/mobile/rn/src/core/utils/color.util.tsx +198 -0
  382. package/templates/mobile/rn/src/core/utils/date.util.ts +97 -0
  383. package/templates/mobile/rn/src/core/utils/device-locale.util.ts +22 -0
  384. package/templates/mobile/rn/src/core/utils/emitter/index.ts +161 -0
  385. package/templates/mobile/rn/src/core/utils/emitter/type.ts +40 -0
  386. package/templates/mobile/rn/src/core/utils/enum.util.tsx +15 -0
  387. package/templates/mobile/rn/src/core/utils/font.util.tsx +42 -0
  388. package/templates/mobile/rn/src/core/utils/func.util.ts +48 -0
  389. package/templates/mobile/rn/src/core/utils/greeting.util.ts +20 -0
  390. package/templates/mobile/rn/src/core/utils/image-format.util.ts +117 -0
  391. package/templates/mobile/rn/src/core/utils/image-picker.util.ts +84 -0
  392. package/templates/mobile/rn/src/core/utils/index.ts +18 -0
  393. package/templates/mobile/rn/src/core/utils/linking.util.ts +16 -0
  394. package/templates/mobile/rn/src/core/utils/navigation.util.tsx +100 -0
  395. package/templates/mobile/rn/src/core/utils/number-format.ts +28 -0
  396. package/templates/mobile/rn/src/core/utils/query-client.util.ts +35 -0
  397. package/templates/mobile/rn/src/core/utils/query-persister.util.ts +36 -0
  398. package/templates/mobile/rn/src/core/utils/schema.util.tsx +2713 -0
  399. package/templates/mobile/rn/src/core/utils/size.util.tsx +74 -0
  400. package/templates/mobile/rn/src/core/utils/storage.util.tsx +53 -0
  401. package/templates/mobile/rn/src/core/utils/toast.util.tsx +151 -0
  402. package/templates/mobile/rn/src/core/utils/translator.util.tsx +23 -0
  403. package/templates/mobile/rn/src/core/utils/typography.util.tsx +69 -0
  404. package/templates/mobile/rn/src/core/utils/validate.util.tsx +13 -0
  405. package/templates/mobile/rn/src/declarations.d.ts +54 -0
  406. package/templates/mobile/rn/src/modules/home/home.screen.tsx +33 -0
  407. package/templates/mobile/rn/src/modules/profile/profile.screen.tsx +29 -0
  408. package/templates/mobile/rn/src/scripts/link-fonts.js +60 -0
  409. package/templates/mobile/rn/src/scripts/sync-images.js +56 -0
  410. package/templates/mobile/rn/src/scripts/sync-svgs.js +50 -0
  411. package/templates/mobile/rn/src/types/models.d.ts +24 -0
  412. package/templates/mobile/rn/tsconfig.json +21 -0
  413. package/templates/shared/README.md +21 -6
  414. package/templates/shared/_package.json +26 -4
  415. package/templates/shared/src/api-endpoints.ts +8 -0
  416. package/templates/shared/src/enums.ts +34 -0
  417. package/templates/shared/src/external-urls.ts +5 -0
  418. package/templates/shared/src/index.ts +15 -0
  419. package/templates/shared/tsconfig.json +8 -0
  420. package/templates/shared/tsup.config.ts +9 -0
  421. package/templates/shared/index.js +0 -4
@@ -0,0 +1,2713 @@
1
+ import * as yup from 'yup';
2
+ import type { StringSchema } from 'yup';
3
+ import { FeeMode } from './enum.util';
4
+ import { regexEmail, regexNumber } from './validate.util';
5
+ import { Translator } from './translator.util';
6
+
7
+ // ─── DPE/GES Schema Helpers ──────────────────────────────────────────────
8
+ // Reusable conditional validators for the 7 DPE/GES fields that all depend
9
+ // on subject_dpe === 'yes'. Each property type schema uses these instead of
10
+ // repeating the same .when('subject_dpe', { … }) block 7 times.
11
+
12
+ type NullableStringSchema = StringSchema<
13
+ string | null | undefined,
14
+ Record<string, any>,
15
+ string | null | undefined
16
+ >;
17
+
18
+ const dpeWhenSubject = (
19
+ base: NullableStringSchema,
20
+ messageKey?: string,
21
+ extraTest?: (s: NullableStringSchema) => NullableStringSchema,
22
+ ) => {
23
+ let chain: NullableStringSchema = base;
24
+ if (extraTest) chain = extraTest(chain);
25
+ if (messageKey) {
26
+ return chain.when('subject_dpe', {
27
+ is: 'yes',
28
+ then: (s: NullableStringSchema) => s.required(Translator.translate(messageKey)),
29
+ otherwise: (s: NullableStringSchema) => s.nullable(),
30
+ });
31
+ }
32
+ return chain.when('subject_dpe', {
33
+ is: 'yes',
34
+ then: (s: NullableStringSchema) => s.required(),
35
+ otherwise: (s: NullableStringSchema) => s.nullable(),
36
+ });
37
+ };
38
+
39
+ const validNumberTest = (s: NullableStringSchema) =>
40
+ s.test('is-valid-number', '', v => !v || !isNaN(Number(v)));
41
+
42
+ export const dpeGradeSchema = (messageKey: string) =>
43
+ dpeWhenSubject(yup.string().nullable(), messageKey);
44
+
45
+ export const dpeDateSchema = (messageKey: string) =>
46
+ dpeWhenSubject(yup.string().nullable(), messageKey);
47
+
48
+ export const dpeNumericSchema = (messageKey: string) =>
49
+ dpeWhenSubject(yup.string().nullable(), messageKey, validNumberTest);
50
+
51
+ export const gesGradeSchema = (messageKey: string) =>
52
+ dpeWhenSubject(yup.string().nullable(), messageKey);
53
+
54
+ export const gesDateSchema = (messageKey: string) =>
55
+ dpeWhenSubject(yup.string().nullable(), messageKey);
56
+
57
+ export const gesNumericSchema = (messageKey: string) =>
58
+ dpeWhenSubject(yup.string().nullable(), messageKey, validNumberTest);
59
+
60
+ export const dpeGradeSchemaSimple = () =>
61
+ dpeWhenSubject(yup.string().nullable());
62
+
63
+ export const dpeDateSchemaSimple = () =>
64
+ dpeWhenSubject(yup.string().nullable());
65
+
66
+ export const dpeNumericSchemaSimple = () =>
67
+ dpeWhenSubject(yup.string().nullable(), undefined, validNumberTest);
68
+
69
+ export const gesGradeSchemaSimple = () =>
70
+ dpeWhenSubject(yup.string().nullable());
71
+
72
+ export const gesDateSchemaSimple = () =>
73
+ dpeWhenSubject(yup.string().nullable());
74
+
75
+ export const gesNumericSchemaSimple = () =>
76
+ dpeWhenSubject(yup.string().nullable(), undefined, validNumberTest);
77
+
78
+ const regexPhone = /^[0-9+\s\-().]{7,}$/;
79
+
80
+ export const contactSupportSchema = () => {
81
+ return yup.object().shape({
82
+ name: yup.string().nullable().trim(),
83
+ phone: yup
84
+ .string()
85
+ .nullable()
86
+ .trim()
87
+ .test('phone-format', Translator.translate('contactSupport.phoneInvalid'), v =>
88
+ !v || regexPhone.test(v),
89
+ ),
90
+ email: yup
91
+ .string()
92
+ .nullable()
93
+ .trim()
94
+ .test('email-format', Translator.translate('contactSupport.emailInvalid'), v =>
95
+ !v || regexEmail.test(v),
96
+ ),
97
+ message: yup.string().nullable().trim(),
98
+ });
99
+ };
100
+
101
+ export const loginSchema = () => {
102
+ return yup.object().shape({
103
+ email: yup
104
+ .string()
105
+ .nullable()
106
+ .trim()
107
+ .required(Translator.translate('signin.emailRequired'))
108
+ .email(Translator.translate('signin.emailInvalid'))
109
+ .matches(regexEmail, Translator.translate('signin.emailInvalid')),
110
+ password: yup
111
+ .string()
112
+ .nullable()
113
+ .required(Translator.translate('signin.passwordRequired'))
114
+ .min(8, Translator.translate('signin.passwordMin'))
115
+ .max(32, Translator.translate('signin.passwordMax')),
116
+ });
117
+ };
118
+
119
+ export const forgotPasswordSchema = () => {
120
+ return yup.object().shape({
121
+ email: yup
122
+ .string()
123
+ .nullable()
124
+ .trim()
125
+ .required(Translator.translate('forgotPassword.emailRequired'))
126
+ .email(Translator.translate('forgotPassword.emailInvalid'))
127
+ .matches(
128
+ regexEmail,
129
+ Translator.translate('forgotPassword.emailInvalid'),
130
+ ),
131
+ });
132
+ };
133
+
134
+ export const resetPasswordSchema = () => {
135
+ return yup.object().shape({
136
+ newPassword: yup
137
+ .string()
138
+ .nullable()
139
+ .required(Translator.translate('resetPassword.newPasswordRequired'))
140
+ .min(8, Translator.translate('resetPassword.newPasswordMin'))
141
+ .max(32, Translator.translate('resetPassword.newPasswordMax')),
142
+ confirmPassword: yup
143
+ .string()
144
+ .nullable()
145
+ .required(
146
+ Translator.translate('resetPassword.confirmPasswordRequired'),
147
+ )
148
+ .min(8, Translator.translate('resetPassword.confirmPasswordMin'))
149
+ .max(32, Translator.translate('resetPassword.confirmPasswordMax'))
150
+ .oneOf(
151
+ [yup.ref('newPassword'), null],
152
+ Translator.translate('resetPassword.confirmPasswordMatch'),
153
+ ),
154
+ });
155
+ };
156
+
157
+ export const changePasswordSchema = () => {
158
+ return yup.object().shape({
159
+ currentPassword: yup
160
+ .string()
161
+ .nullable()
162
+ .required(
163
+ Translator.translate('changePassword.currentPasswordRequired'),
164
+ ),
165
+ newPassword: yup
166
+ .string()
167
+ .nullable()
168
+ .required(
169
+ Translator.translate('changePassword.newPasswordRequired'),
170
+ )
171
+ .min(8, Translator.translate('changePassword.newPasswordMin'))
172
+ .max(32, Translator.translate('changePassword.newPasswordMax')),
173
+ confirmPassword: yup
174
+ .string()
175
+ .nullable()
176
+ .required(
177
+ Translator.translate('changePassword.confirmPasswordRequired'),
178
+ )
179
+ .min(8, Translator.translate('changePassword.confirmPasswordMin'))
180
+ .max(32, Translator.translate('changePassword.confirmPasswordMax'))
181
+ .oneOf(
182
+ [yup.ref('newPassword'), null],
183
+ Translator.translate('changePassword.confirmPasswordMatch'),
184
+ ),
185
+ });
186
+ };
187
+
188
+ export const signupSchema = () => {
189
+ return yup.object().shape({
190
+ full_name: yup
191
+ .string()
192
+ .nullable()
193
+ .required(Translator.translate('signup.nameRequired'))
194
+ .min(3, Translator.translate('signup.nameMin'))
195
+ .max(32, Translator.translate('signup.nameMax')),
196
+ email: yup
197
+ .string()
198
+ .nullable()
199
+ .trim()
200
+ .required(Translator.translate('signup.emailRequired'))
201
+ .email(Translator.translate('signup.emailInvalid'))
202
+ .matches(
203
+ regexEmail,
204
+ Translator.translate('signup.emailInvalid'),
205
+ ),
206
+ password: yup
207
+ .string()
208
+ .nullable()
209
+ .required(Translator.translate('signup.passwordRequired'))
210
+ .min(8, Translator.translate('signup.passwordMin'))
211
+ .max(32, Translator.translate('signup.passwordMax')),
212
+ });
213
+ };
214
+
215
+ export const buyerPersonalPropertySchema = () => {
216
+ return yup.object().shape({
217
+ property_type_id: yup
218
+ .string()
219
+ .nullable()
220
+ .required(
221
+ Translator.translate(
222
+ 'buyerPersonalProperty.propertyTypeRequired',
223
+ ),
224
+ ),
225
+ search_description: yup.string().nullable(),
226
+ });
227
+ };
228
+
229
+ export const buyerDescribeProfileSchema = () => {
230
+ return yup.object().shape({
231
+ buying_status: yup.string().nullable(),
232
+ family_situation: yup.string().nullable(),
233
+ purchase_objective: yup.string().nullable(),
234
+ description: yup.string().nullable(),
235
+ });
236
+ };
237
+
238
+ export const buyerEditProfileSchema = () => {
239
+ return yup.object().shape({
240
+ full_name: yup
241
+ .string()
242
+ .nullable()
243
+ .required(Translator.translate('searchSettings.nameRequired'))
244
+ .min(2, Translator.translate('searchSettings.nameMin')),
245
+ });
246
+ };
247
+
248
+ export const sellerEditProfileSchema = () => {
249
+ return yup.object().shape({
250
+ full_name: yup
251
+ .string()
252
+ .nullable()
253
+ .required(Translator.translate('searchSettings.nameRequired'))
254
+ .min(2, Translator.translate('searchSettings.nameMin')),
255
+ seller_type: yup
256
+ .string()
257
+ .nullable()
258
+ .required(Translator.translate('searchSettings.typeRequired')),
259
+ phone: yup.string().nullable(),
260
+ location: yup.string().nullable(),
261
+ });
262
+ };
263
+
264
+ export const agentEditProfileSchema = () => {
265
+ return yup.object().shape({
266
+ full_name: yup
267
+ .string()
268
+ .nullable()
269
+ .trim()
270
+ .required(Translator.translate('agentSignup.lastNameRequired')),
271
+ siret_number: yup.string().nullable().trim(),
272
+ activity_start_date: yup.string().nullable(),
273
+ card_number: yup.string().nullable().trim(),
274
+ agency_website_url: yup
275
+ .string()
276
+ .nullable()
277
+ .trim()
278
+ .url(Translator.translate('agentSignup.websiteInvalid')),
279
+ phone: yup.string().nullable().trim(),
280
+ });
281
+ };
282
+
283
+ export const buyerBudgetSchema = () => {
284
+ return yup.object().shape({
285
+ budget_min: yup
286
+ .number()
287
+ .nullable()
288
+ .typeError(Translator.translate('buyerPersonalBudget.budgetMustBeNumber'))
289
+ .positive(Translator.translate('buyerPersonalBudget.budgetMinRequired'))
290
+ .required(Translator.translate('buyerPersonalBudget.budgetMinRequired')),
291
+ budget_max: yup
292
+ .number()
293
+ .nullable()
294
+ .typeError(Translator.translate('buyerPersonalBudget.budgetMustBeNumber'))
295
+ .positive(Translator.translate('buyerPersonalBudget.budgetMaxRequired'))
296
+ .required(Translator.translate('buyerPersonalBudget.budgetMaxRequired'))
297
+ .min(
298
+ yup.ref('budget_min'),
299
+ Translator.translate('buyerPersonalBudget.budgetMaxLessThanMin'),
300
+ ),
301
+ budget_global: yup
302
+ .number()
303
+ .nullable()
304
+ .transform((value, originalValue) =>
305
+ originalValue === '' || originalValue === null || originalValue === undefined
306
+ ? null
307
+ : value,
308
+ )
309
+ .typeError(Translator.translate('buyerPersonalBudget.budgetMustBeNumber'))
310
+ .positive(Translator.translate('buyerPersonalBudget.budgetGlobalRequired'))
311
+ .min(
312
+ yup.ref('budget_min'),
313
+ Translator.translate('buyerPersonalBudget.budgetGlobalLessThanMin'),
314
+ )
315
+ .optional(),
316
+ has_property_to_sell: yup
317
+ .boolean()
318
+ .nullable()
319
+ .required(
320
+ Translator.translate(
321
+ 'buyerPersonalBudget.hasSellPropertyRequired',
322
+ ),
323
+ ),
324
+ property_city: yup
325
+ .string()
326
+ .nullable()
327
+ .when('has_property_to_sell', {
328
+ is: true,
329
+ then: schema => schema.required(Translator.translate('buyerPersonalBudget.cityRequired')),
330
+ otherwise: schema => schema.optional(),
331
+ }),
332
+ });
333
+ };
334
+
335
+
336
+ export const buyerInvestmentStrategySchema = () => {
337
+ return yup.object().shape({
338
+ budget_max: yup
339
+ .number()
340
+ .nullable()
341
+ .typeError(Translator.translate('buyerPersonalBudget.budgetMustBeNumber'))
342
+ .positive(Translator.translate('buyerPersonalBudget.budgetMaxRequired'))
343
+ .required(Translator.translate('buyerPersonalBudget.budgetMaxRequired')),
344
+ requires_renovation: yup
345
+ .string()
346
+ .required(Translator.translate('buyerInvestmentStrategy.requiresRenovationRequired')),
347
+ expected_return_rate: yup
348
+ .number()
349
+ .nullable()
350
+ .typeError(Translator.translate('validation.mustBeNumber'))
351
+ .required(Translator.translate('buyerInvestmentStrategy.expectedReturnRequired')),
352
+ });
353
+ };
354
+
355
+ export const buyerFinancialTermsSchema = () => {
356
+ return yup.object().shape({
357
+ financing_mode: yup
358
+ .string()
359
+ .nullable()
360
+ .required(Translator.translate('buyerFinancialTerms.financingModeRequired')),
361
+ description: yup
362
+ .string()
363
+ .nullable()
364
+ .optional(),
365
+ });
366
+ };
367
+
368
+ export const buyerHousePropertySchema = () => {
369
+ return yup.object().shape({
370
+ living_area_min: yup
371
+ .string()
372
+ .nullable()
373
+ .test(
374
+ 'valid-number',
375
+ Translator.translate('buyerHouseProperty.livingAreaMinInvalid'),
376
+ value => !value || regexNumber.test(String(value)),
377
+ ),
378
+ living_area_max: yup
379
+ .string()
380
+ .nullable()
381
+ .test(
382
+ 'valid-number',
383
+ Translator.translate('buyerHouseProperty.livingAreaMaxInvalid'),
384
+ value => !value || regexNumber.test(String(value)),
385
+ )
386
+ .test(
387
+ 'min-max',
388
+ Translator.translate('buyerHouseProperty.livingAreaMaxLessThanMin'),
389
+ function (value) {
390
+ const { living_area_min } = this.parent;
391
+ if (!value || !living_area_min) return true;
392
+ return Number(value) >= Number(living_area_min);
393
+ },
394
+ ),
395
+ garden_min: yup
396
+ .string()
397
+ .nullable()
398
+ .test(
399
+ 'valid-number',
400
+ Translator.translate('buyerHouseProperty.gardenMinInvalid'),
401
+ value => !value || regexNumber.test(String(value)),
402
+ ),
403
+ garden_max: yup
404
+ .string()
405
+ .nullable()
406
+ .test(
407
+ 'valid-number',
408
+ Translator.translate('buyerHouseProperty.gardenMaxInvalid'),
409
+ value => !value || regexNumber.test(String(value)),
410
+ )
411
+ .test(
412
+ 'min-max',
413
+ Translator.translate('buyerHouseProperty.gardenMaxLessThanMin'),
414
+ function (value) {
415
+ const { garden_min } = this.parent;
416
+ if (!value || !garden_min) return true;
417
+ return Number(value) >= Number(garden_min);
418
+ },
419
+ ),
420
+ });
421
+ };
422
+
423
+ export const buyerApartmentPropertySchema = () => {
424
+ return yup.object().shape({
425
+ living_area_min: yup
426
+ .string()
427
+ .nullable()
428
+ .test(
429
+ 'valid-number',
430
+ Translator.translate('buyerHouseProperty.livingAreaMinInvalid'),
431
+ value => !value || regexNumber.test(String(value)),
432
+ ),
433
+ living_area_max: yup
434
+ .string()
435
+ .nullable()
436
+ .test(
437
+ 'valid-number',
438
+ Translator.translate('buyerHouseProperty.livingAreaMaxInvalid'),
439
+ value => !value || regexNumber.test(String(value)),
440
+ )
441
+ .test(
442
+ 'min-max',
443
+ Translator.translate('buyerHouseProperty.livingAreaMaxLessThanMin'),
444
+ function (value) {
445
+ const { living_area_min } = this.parent;
446
+ if (!value || !living_area_min) return true;
447
+ return Number(value) >= Number(living_area_min);
448
+ },
449
+ ),
450
+ });
451
+ };
452
+
453
+ export const buyerGitePropertySchema = () => {
454
+ return yup.object().shape({
455
+ living_area_min: yup
456
+ .string()
457
+ .nullable()
458
+ .test(
459
+ 'valid-number',
460
+ Translator.translate('buyerHouseProperty.livingAreaMinInvalid'),
461
+ value => !value || regexNumber.test(String(value)),
462
+ ),
463
+ living_area_max: yup
464
+ .string()
465
+ .nullable()
466
+ .test(
467
+ 'valid-number',
468
+ Translator.translate('buyerHouseProperty.livingAreaMaxInvalid'),
469
+ value => !value || regexNumber.test(String(value)),
470
+ )
471
+ .test(
472
+ 'min-max',
473
+ Translator.translate('buyerHouseProperty.livingAreaMaxLessThanMin'),
474
+ function (value) {
475
+ const { living_area_min } = this.parent;
476
+ if (!value || !living_area_min) return true;
477
+ return Number(value) >= Number(living_area_min);
478
+ },
479
+ ),
480
+ garden_min: yup
481
+ .string()
482
+ .nullable()
483
+ .test(
484
+ 'valid-number',
485
+ Translator.translate('buyerHouseProperty.gardenMinInvalid'),
486
+ value => !value || regexNumber.test(String(value)),
487
+ ),
488
+ garden_max: yup
489
+ .string()
490
+ .nullable()
491
+ .test(
492
+ 'valid-number',
493
+ Translator.translate('buyerHouseProperty.gardenMaxInvalid'),
494
+ value => !value || regexNumber.test(String(value)),
495
+ )
496
+ .test(
497
+ 'min-max',
498
+ Translator.translate('buyerHouseProperty.gardenMaxLessThanMin'),
499
+ function (value) {
500
+ const { garden_min } = this.parent;
501
+ if (!value || !garden_min) return true;
502
+ return Number(value) >= Number(garden_min);
503
+ },
504
+ ),
505
+ });
506
+ };
507
+
508
+ export const buyerLandPropertySchema = () => {
509
+ return yup.object().shape({
510
+ garden_min: yup
511
+ .string()
512
+ .nullable()
513
+ .test(
514
+ 'valid-number',
515
+ Translator.translate('buyerHouseProperty.gardenMinInvalid'),
516
+ value => !value || regexNumber.test(String(value)),
517
+ ),
518
+ garden_max: yup
519
+ .string()
520
+ .nullable()
521
+ .test(
522
+ 'valid-number',
523
+ Translator.translate('buyerHouseProperty.gardenMaxInvalid'),
524
+ value => !value || regexNumber.test(String(value)),
525
+ )
526
+ .test(
527
+ 'min-max',
528
+ Translator.translate('buyerHouseProperty.gardenMaxLessThanMin'),
529
+ function (value) {
530
+ const { garden_min } = this.parent;
531
+ if (!value || !garden_min) return true;
532
+ return Number(value) >= Number(garden_min);
533
+ },
534
+ ),
535
+ });
536
+ };
537
+
538
+ export const buyerGarageParkingPropertySchema = () => {
539
+ return yup.object().shape({
540
+ living_area_min: yup
541
+ .string()
542
+ .nullable()
543
+ .test(
544
+ 'valid-number',
545
+ Translator.translate('buyerHouseProperty.livingAreaMinInvalid'),
546
+ value => !value || regexNumber.test(String(value)),
547
+ ),
548
+ });
549
+ };
550
+
551
+ export const buyerBuildingPropertySchema = () => {
552
+ return yup.object().shape({
553
+ living_area_min: yup
554
+ .string()
555
+ .nullable()
556
+ .test(
557
+ 'valid-number',
558
+ Translator.translate('buyerHouseProperty.livingAreaMinInvalid'),
559
+ value => !value || regexNumber.test(String(value)),
560
+ ),
561
+ living_area_max: yup
562
+ .string()
563
+ .nullable()
564
+ .test(
565
+ 'valid-number',
566
+ Translator.translate('buyerHouseProperty.livingAreaMaxInvalid'),
567
+ value => !value || regexNumber.test(String(value)),
568
+ )
569
+ .test(
570
+ 'min-max',
571
+ Translator.translate('buyerHouseProperty.livingAreaMaxLessThanMin'),
572
+ function (value) {
573
+ const { living_area_min } = this.parent;
574
+ if (!value || !living_area_min) return true;
575
+ return Number(value) >= Number(living_area_min);
576
+ },
577
+ ),
578
+ rooms_min: yup.number().nullable().min(0).max(10),
579
+ rooms_max: yup
580
+ .number()
581
+ .nullable()
582
+ .min(0)
583
+ .max(10)
584
+ .test(
585
+ 'min-max',
586
+ Translator.translate('buyerHouseProperty.roomsMaxLessThanMin'),
587
+ function (value) {
588
+ const { rooms_min } = this.parent;
589
+ if (value == null || rooms_min == null) return true;
590
+ return value >= rooms_min;
591
+ },
592
+ ),
593
+ });
594
+ };
595
+
596
+ export const buyerOfficePropertySchema = () => {
597
+ return yup.object().shape({
598
+ living_area_min: yup
599
+ .string()
600
+ .nullable()
601
+ .test(
602
+ 'valid-number',
603
+ Translator.translate('buyerHouseProperty.livingAreaMinInvalid'),
604
+ value => !value || regexNumber.test(String(value)),
605
+ ),
606
+ living_area_max: yup
607
+ .string()
608
+ .nullable()
609
+ .test(
610
+ 'valid-number',
611
+ Translator.translate('buyerHouseProperty.livingAreaMaxInvalid'),
612
+ value => !value || regexNumber.test(String(value)),
613
+ )
614
+ .test(
615
+ 'min-max',
616
+ Translator.translate('buyerHouseProperty.livingAreaMaxLessThanMin'),
617
+ function (value) {
618
+ const { living_area_min } = this.parent;
619
+ if (!value || !living_area_min) return true;
620
+ return Number(value) >= Number(living_area_min);
621
+ },
622
+ ),
623
+ rooms_min: yup.number().nullable().min(0).max(20),
624
+ });
625
+ };
626
+
627
+ export const buyerCommercialPropertySchema = () => {
628
+ return yup.object().shape({
629
+ living_area_min: yup
630
+ .string()
631
+ .nullable()
632
+ .test(
633
+ 'valid-number',
634
+ Translator.translate('buyerHouseProperty.livingAreaMinInvalid'),
635
+ value => !value || regexNumber.test(String(value)),
636
+ ),
637
+ living_area_max: yup
638
+ .string()
639
+ .nullable()
640
+ .test(
641
+ 'valid-number',
642
+ Translator.translate('buyerHouseProperty.livingAreaMaxInvalid'),
643
+ value => !value || regexNumber.test(String(value)),
644
+ )
645
+ .test(
646
+ 'min-max',
647
+ Translator.translate('buyerHouseProperty.livingAreaMaxLessThanMin'),
648
+ function (value) {
649
+ const { living_area_min } = this.parent;
650
+ if (!value || !living_area_min) return true;
651
+ return Number(value) >= Number(living_area_min);
652
+ },
653
+ ),
654
+ window_surface_min: yup
655
+ .string()
656
+ .nullable()
657
+ .test(
658
+ 'valid-number',
659
+ Translator.translate('buyerHouseProperty.livingAreaMinInvalid'),
660
+ value => !value || regexNumber.test(String(value)),
661
+ ),
662
+ window_surface_max: yup
663
+ .string()
664
+ .nullable()
665
+ .test(
666
+ 'valid-number',
667
+ Translator.translate('buyerHouseProperty.livingAreaMaxInvalid'),
668
+ value => !value || regexNumber.test(String(value)),
669
+ )
670
+ .test(
671
+ 'min-max',
672
+ Translator.translate('buyerHouseProperty.windowSurfaceMaxLessThanMin'),
673
+ function (value) {
674
+ const { window_surface_min } = this.parent;
675
+ if (!value || !window_surface_min) return true;
676
+ return Number(value) >= Number(window_surface_min);
677
+ },
678
+ ),
679
+ });
680
+ };
681
+
682
+ export const buyerViagerPropertySchema = () => {
683
+ return yup.object().shape({
684
+ living_area_min: yup
685
+ .string()
686
+ .nullable()
687
+ .test(
688
+ 'valid-number',
689
+ Translator.translate('buyerHouseProperty.livingAreaMinInvalid'),
690
+ value => !value || regexNumber.test(String(value)),
691
+ ),
692
+ living_area_max: yup
693
+ .string()
694
+ .nullable()
695
+ .test(
696
+ 'valid-number',
697
+ Translator.translate('buyerHouseProperty.livingAreaMaxInvalid'),
698
+ value => !value || regexNumber.test(String(value)),
699
+ )
700
+ .test(
701
+ 'min-max',
702
+ Translator.translate('buyerHouseProperty.livingAreaMaxLessThanMin'),
703
+ function (value) {
704
+ const { living_area_min } = this.parent;
705
+ if (!value || !living_area_min) return true;
706
+ return Number(value) >= Number(living_area_min);
707
+ },
708
+ ),
709
+ rooms_min: yup.number().nullable().min(0).max(10),
710
+ max_bouquet: yup
711
+ .string()
712
+ .nullable()
713
+ .test(
714
+ 'valid-number',
715
+ Translator.translate('buyerHouseProperty.livingAreaMinInvalid'),
716
+ value => !value || regexNumber.test(String(value)),
717
+ ),
718
+ });
719
+ };
720
+
721
+ export const sellerDateSellSchema = () => {
722
+ return yup.object().shape({
723
+ published_at: yup
724
+ .string()
725
+ .nullable()
726
+ .required(Translator.translate('sellerDateSell.dateRequired')),
727
+ });
728
+ };
729
+
730
+ export const sellerPricePositionSchema = () => {
731
+ return yup.object().shape({
732
+ price_initial: yup
733
+ .number()
734
+ .nullable()
735
+ .typeError(Translator.translate('buyerPersonalBudget.budgetMustBeNumber'))
736
+ .required(
737
+ Translator.translate(
738
+ 'sellerPricePosition.initialPriceRequired',
739
+ ),
740
+ ),
741
+ });
742
+ };
743
+
744
+ export const sellerResalePricePositionSchema = () => {
745
+ return yup.object().shape({
746
+ price_initial: yup
747
+ .number()
748
+ .nullable()
749
+ .typeError(Translator.translate('buyerPersonalBudget.budgetMustBeNumber'))
750
+ .required(
751
+ Translator.translate(
752
+ 'sellerPricePosition.initialPriceRequired',
753
+ ),
754
+ ),
755
+ adjusted_price: yup
756
+ .boolean()
757
+ .nullable()
758
+ .required(
759
+ Translator.translate(
760
+ 'sellerPricePosition.hasAdjustedPriceRequired',
761
+ ),
762
+ ),
763
+ price_current: yup
764
+ .number()
765
+ .nullable()
766
+ .typeError(Translator.translate('buyerPersonalBudget.budgetMustBeNumber'))
767
+ .when('adjusted_price', {
768
+ is: true,
769
+ then: schema =>
770
+ schema.required(
771
+ Translator.translate(
772
+ 'sellerPricePosition.currentPriceRequired',
773
+ ),
774
+ ),
775
+ otherwise: schema => schema.nullable(),
776
+ }),
777
+ });
778
+ };
779
+
780
+ export const agentRegisterPriceAndFeeSchema = () => {
781
+ return yup.object().shape({
782
+ net_selling_price: yup
783
+ .string()
784
+ .nullable()
785
+ .required(
786
+ Translator.translate(
787
+ 'agentRegisterPriceAndFee.netSellingPriceRequired',
788
+ ),
789
+ ),
790
+ fee_mode: yup
791
+ .string()
792
+ .nullable()
793
+ .required(
794
+ Translator.translate(
795
+ 'agentRegisterPriceAndFee.feeModeRequired',
796
+ ),
797
+ )
798
+ .oneOf(
799
+ [FeeMode.BUYER_PAYS, FeeMode.SELLER_PAYS],
800
+ Translator.translate(
801
+ 'agentRegisterPriceAndFee.feeModeRequired',
802
+ ),
803
+ ),
804
+ total_fees_ttc: yup
805
+ .string()
806
+ .nullable()
807
+ .when('fee_mode', {
808
+ is: (value: string) => value !== '' && value !== null && value !== undefined,
809
+ then: schema =>
810
+ schema.required(
811
+ Translator.translate(
812
+ 'agentRegisterPriceAndFee.totalFeesTTCRequired',
813
+ ),
814
+ ),
815
+ otherwise: schema => schema.nullable(),
816
+ }),
817
+ fee_rate: yup
818
+ .string()
819
+ .nullable()
820
+ .notRequired(),
821
+ price_current: yup
822
+ .string()
823
+ .nullable()
824
+ .notRequired(),
825
+ selling_price: yup
826
+ .string()
827
+ .nullable()
828
+ .notRequired(),
829
+ });
830
+ };
831
+
832
+ export const agentTypeOfMandateSchema = () => {
833
+ return yup.object().shape({
834
+ has_sales_mandate: yup
835
+ .boolean()
836
+ .nullable()
837
+ .required(
838
+ Translator.translate(
839
+ 'agentTypeOfMandate.hasSalesMandateRequired',
840
+ ),
841
+ ),
842
+ mandate_type: yup
843
+ .string()
844
+ .nullable()
845
+ .when('has_sales_mandate', {
846
+ is: true,
847
+ then: schema =>
848
+ schema.required(
849
+ Translator.translate(
850
+ 'agentTypeOfMandate.mandateTypeRequired',
851
+ ),
852
+ ),
853
+ otherwise: schema => schema.nullable(),
854
+ }),
855
+ });
856
+ };
857
+
858
+ export const agentHousePropertySchema = () => {
859
+ return yup.object().shape({
860
+ living_area: yup
861
+ .string()
862
+ .nullable()
863
+ .required(
864
+ Translator.translate('agentHouseProperty.livingAreaRequired'),
865
+ )
866
+ .test('is-valid-number', '', v => !v || !isNaN(Number(v)))
867
+ .test(
868
+ 'living-area-lte-total-surface',
869
+ Translator.translate('agentHouseProperty.livingAreaGreaterThanTotalArea'),
870
+ function (value) {
871
+ const { total_surface } = this.parent;
872
+ if (!value || !total_surface) return true;
873
+ return Number(value) <= Number(total_surface);
874
+ },
875
+ ),
876
+ total_surface: yup
877
+ .string()
878
+ .nullable()
879
+ .test('is-valid-number', '', v => !v || !isNaN(Number(v)))
880
+ .test(
881
+ 'total-surface-gte-living-area',
882
+ Translator.translate('agentHouseProperty.totalAreaLessThanLivingArea'),
883
+ function (value) {
884
+ const { living_area } = this.parent;
885
+ if (!value || !living_area) return true;
886
+ return Number(value) >= Number(living_area);
887
+ },
888
+ ),
889
+ rooms_count: yup
890
+ .number()
891
+ .nullable()
892
+ .required(
893
+ Translator.translate('agentHouseProperty.bedroomsRequired'),
894
+ )
895
+ .min(0),
896
+ shower_rooms: yup.number().nullable().min(0),
897
+ bathrooms: yup.number().nullable().min(0),
898
+ ground_floor: yup.mixed().nullable(),
899
+ has_garage: yup.mixed().nullable(),
900
+ pool: yup.mixed().nullable(),
901
+ heating_system: yup.string().nullable(),
902
+ property_condition: yup
903
+ .string()
904
+ .nullable()
905
+ .required(
906
+ Translator.translate(
907
+ 'agentHouseProperty.propertyConditionRequired',
908
+ ),
909
+ ),
910
+ freeOrRented: yup
911
+ .string()
912
+ .nullable()
913
+ .required(
914
+ Translator.translate('agentHouseProperty.freeOrRentedRequired'),
915
+ ),
916
+ monthly_rent: yup
917
+ .string()
918
+ .nullable()
919
+ .when('freeOrRented', {
920
+ is: 'rented',
921
+ then: schema =>
922
+ schema.required(
923
+ Translator.translate(
924
+ 'agentHouseProperty.monthlyRentRequired',
925
+ ),
926
+ ),
927
+ otherwise: schema => schema.notRequired().nullable(),
928
+ }),
929
+ annual_tax: yup
930
+ .string()
931
+ .nullable()
932
+ .when('freeOrRented', {
933
+ is: 'rented',
934
+ then: schema =>
935
+ schema.required(
936
+ Translator.translate(
937
+ 'agentHouseProperty.annualPropertyTaxRequired',
938
+ ),
939
+ ),
940
+ otherwise: schema => schema.notRequired().nullable(),
941
+ }),
942
+ subject_dpe: yup
943
+ .string()
944
+ .nullable()
945
+ .oneOf(
946
+ ['yes', 'no'],
947
+ Translator.translate('agentHouseProperty.subjectToDPERequired'),
948
+ )
949
+ .required(
950
+ Translator.translate('agentHouseProperty.subjectToDPERequired'),
951
+ ),
952
+ is_dpe_blank: yup
953
+ .string()
954
+ .nullable()
955
+ .oneOf(
956
+ ['yes', 'no'],
957
+ Translator.translate('agentHouseProperty.virginDPERequired'),
958
+ )
959
+ .required(
960
+ Translator.translate('agentHouseProperty.virginDPERequired'),
961
+ ),
962
+ dpe_grade: dpeGradeSchema('common.dpeClassRequired'),
963
+ dpe_date: dpeDateSchema('common.dpeDateRequired'),
964
+ primary_energy_consumption: dpeNumericSchema('common.primaryEnergyConsumptionRequired'),
965
+ estimated_annual_energy_cost: dpeNumericSchema('common.estimatedAnnualCostsRequired'),
966
+ ges_grade: gesGradeSchema('common.gesClassRequired'),
967
+ ges_date: gesDateSchema('common.gesDateRequired'),
968
+ greenhouse_gas_emissions: gesNumericSchema('common.greenhouseGasEmissionRequired'),
969
+ construction_year: yup.string().nullable(),
970
+ is_land_divisible: yup.mixed().nullable(),
971
+ sanitation: yup.string().nullable(),
972
+ available_at: yup.string().nullable(),
973
+ });
974
+ };
975
+
976
+ export const sellerPropertyTypeSchema = () => {
977
+ return yup.object().shape({
978
+ propertyType: yup
979
+ .string()
980
+ .nullable()
981
+ .required(
982
+ Translator.translate('sellerPropertyType.propertyTypeRequired'),
983
+ ),
984
+ });
985
+ };
986
+
987
+ export const sellerResalePropertyTypeSchema = () => {
988
+ return yup.object().shape({
989
+ property_type_id: yup
990
+ .string()
991
+ .required(
992
+ Translator.translate('sellerPropertyType.propertyTypeRequired'),
993
+ ),
994
+ });
995
+ };
996
+
997
+ export const sellerViagerPropertyTypeSchema = () => {
998
+ return yup.object().shape({
999
+ property_type_id: yup
1000
+ .string()
1001
+ .required(
1002
+ Translator.translate('sellerPropertyType.propertyTypeRequired'),
1003
+ ),
1004
+ });
1005
+ };
1006
+
1007
+ export const sellerViagerPropertyDescriptionSchema = () => {
1008
+ return yup.object().shape({
1009
+ sale_type: yup
1010
+ .string()
1011
+ .nullable()
1012
+ .required(
1013
+ Translator.translate(
1014
+ 'sellerPropertyDescription.saleTypeRequired',
1015
+ ),
1016
+ ),
1017
+ address: yup
1018
+ .string()
1019
+ .nullable()
1020
+ .required(
1021
+ Translator.translate(
1022
+ 'sellerPropertyDescription.fullAddressRequired',
1023
+ ),
1024
+ ),
1025
+ street: yup
1026
+ .string()
1027
+ .nullable()
1028
+ .required(
1029
+ Translator.translate(
1030
+ 'sellerPropertyDescription.streetRequired',
1031
+ ),
1032
+ ),
1033
+ postal_code: yup
1034
+ .string()
1035
+ .nullable()
1036
+ .required(
1037
+ Translator.translate(
1038
+ 'sellerPropertyDescription.postalCodeRequired',
1039
+ ),
1040
+ )
1041
+ .matches(
1042
+ regexNumber,
1043
+ Translator.translate(
1044
+ 'sellerPropertyDescription.postalCodeInvalid',
1045
+ ),
1046
+ ),
1047
+ city: yup
1048
+ .string()
1049
+ .nullable()
1050
+ .required(
1051
+ Translator.translate('sellerPropertyDescription.cityRequired'),
1052
+ ),
1053
+ });
1054
+ };
1055
+
1056
+ export const sellerPropertyDescriptionSchema = () => {
1057
+ return yup.object().shape({
1058
+ sale_type: yup
1059
+ .string()
1060
+ .nullable()
1061
+ .required(
1062
+ Translator.translate(
1063
+ 'sellerPropertyDescription.saleTypeRequired',
1064
+ ),
1065
+ ),
1066
+ address: yup
1067
+ .string()
1068
+ .nullable()
1069
+ .required(
1070
+ Translator.translate(
1071
+ 'sellerPropertyDescription.fullAddressRequired',
1072
+ ),
1073
+ ),
1074
+ street: yup
1075
+ .string()
1076
+ .nullable()
1077
+ .required(
1078
+ Translator.translate(
1079
+ 'sellerPropertyDescription.streetRequired',
1080
+ ),
1081
+ ),
1082
+ postal_code: yup
1083
+ .string()
1084
+ .nullable()
1085
+ .required(
1086
+ Translator.translate(
1087
+ 'sellerPropertyDescription.postalCodeRequired',
1088
+ ),
1089
+ )
1090
+ .matches(
1091
+ regexNumber,
1092
+ Translator.translate(
1093
+ 'sellerPropertyDescription.postalCodeInvalid',
1094
+ ),
1095
+ ),
1096
+ city: yup
1097
+ .string()
1098
+ .nullable()
1099
+ .required(
1100
+ Translator.translate('sellerPropertyDescription.cityRequired'),
1101
+ ),
1102
+ exact_address: yup
1103
+ .boolean()
1104
+ .nullable()
1105
+ .required(
1106
+ Translator.translate(
1107
+ 'sellerPropertyDescription.geolocationRequired',
1108
+ ),
1109
+ ),
1110
+ scope_selection: yup
1111
+ .string()
1112
+ .nullable()
1113
+ .when('exact_address', {
1114
+ is: false,
1115
+ then: schema =>
1116
+ schema.required(
1117
+ Translator.translate(
1118
+ 'sellerPropertyDescription.perimeterRequired',
1119
+ ),
1120
+ ),
1121
+ otherwise: schema => schema.nullable(),
1122
+ }),
1123
+ });
1124
+ };
1125
+
1126
+ export const sellerPropertyPhotosSchema = () => {
1127
+ return yup.object().shape({
1128
+ short_description: yup
1129
+ .string()
1130
+ .nullable()
1131
+ // .required(
1132
+ // Translator.translate(
1133
+ // 'sellerPropertyPhotos.descriptionRequired',
1134
+ // ),
1135
+ // ),
1136
+ });
1137
+ };
1138
+
1139
+ export const sellerVisitSlotsSchema = () => {
1140
+ return yup.object().shape({
1141
+ // Schema is minimal since days and time slots are managed in component state
1142
+ // Validation is handled in the component's isButtonEnabled logic
1143
+ });
1144
+ };
1145
+
1146
+ export const sellerHousePropertySchema = () => {
1147
+ return yup.object().shape({
1148
+ living_area: yup
1149
+ .string()
1150
+ .nullable()
1151
+ .required(
1152
+ Translator.translate('sellerHouseProperty.livingAreaRequired'),
1153
+ )
1154
+ .test('is-valid-number', '', v => !v || !isNaN(Number(v)))
1155
+ .test(
1156
+ 'living-area-lte-total-surface',
1157
+ Translator.translate('sellerHouseProperty.livingAreaGreaterThanTotalArea'),
1158
+ function (value) {
1159
+ const { total_surface } = this.parent;
1160
+ if (!value || !total_surface) return true;
1161
+ return Number(value) <= Number(total_surface);
1162
+ },
1163
+ ),
1164
+ total_surface: yup
1165
+ .string()
1166
+ .nullable()
1167
+ .test('is-valid-number', '', v => !v || !isNaN(Number(v)))
1168
+ .test(
1169
+ 'total-surface-gte-living-area',
1170
+ Translator.translate('sellerHouseProperty.totalAreaLessThanLivingArea'),
1171
+ function (value) {
1172
+ const { living_area } = this.parent;
1173
+ if (!value || !living_area) return true;
1174
+ return Number(value) >= Number(living_area);
1175
+ },
1176
+ ),
1177
+ rooms_count: yup
1178
+ .number()
1179
+ .nullable()
1180
+ .required(
1181
+ Translator.translate('sellerHouseProperty.bedroomsRequired'),
1182
+ )
1183
+ .min(0),
1184
+ shower_rooms: yup.number().nullable().min(0),
1185
+ bathrooms: yup.number().nullable().min(0),
1186
+ ground_floor: yup.mixed().nullable(),
1187
+ has_garage: yup.mixed().nullable(),
1188
+ pool: yup.mixed().nullable(),
1189
+ heating_system: yup.string().nullable(),
1190
+ property_condition: yup
1191
+ .string()
1192
+ .nullable()
1193
+ .required(
1194
+ Translator.translate(
1195
+ 'sellerHouseProperty.propertyConditionRequired',
1196
+ ),
1197
+ ),
1198
+ freeOrRented: yup
1199
+ .string()
1200
+ .nullable()
1201
+ .required(
1202
+ Translator.translate(
1203
+ 'sellerHouseProperty.freeOrRentedRequired',
1204
+ ),
1205
+ ),
1206
+ monthly_rent: yup
1207
+ .string()
1208
+ .nullable()
1209
+ .when('freeOrRented', {
1210
+ is: 'rented',
1211
+ then: schema =>
1212
+ schema.required(
1213
+ Translator.translate(
1214
+ 'sellerHouseProperty.monthlyRentRequired',
1215
+ ),
1216
+ ),
1217
+ otherwise: schema => schema.notRequired().nullable(),
1218
+ }),
1219
+ annual_tax: yup
1220
+ .string()
1221
+ .nullable()
1222
+ .when('freeOrRented', {
1223
+ is: 'rented',
1224
+ then: schema =>
1225
+ schema.required(
1226
+ Translator.translate(
1227
+ 'sellerHouseProperty.annualPropertyTaxRequired',
1228
+ ),
1229
+ ),
1230
+ otherwise: schema => schema.notRequired().nullable(),
1231
+ }),
1232
+ subject_dpe: yup
1233
+ .mixed()
1234
+ .nullable()
1235
+ .required(
1236
+ Translator.translate(
1237
+ 'sellerHouseProperty.subjectToDPERequired',
1238
+ ),
1239
+ ),
1240
+ is_dpe_blank: yup
1241
+ .mixed()
1242
+ .nullable()
1243
+ .required(
1244
+ Translator.translate('sellerHouseProperty.virginDPERequired'),
1245
+ ),
1246
+ dpe_grade: dpeGradeSchema('common.dpeClassRequired'),
1247
+ dpe_date: dpeDateSchema('common.dpeDateRequired'),
1248
+ primary_energy_consumption: dpeNumericSchema('common.primaryEnergyConsumptionRequired'),
1249
+ estimated_annual_energy_cost: dpeNumericSchema('common.estimatedAnnualCostsRequired'),
1250
+ ges_grade: gesGradeSchema('common.gesClassRequired'),
1251
+ ges_date: gesDateSchema('common.gesDateRequired'),
1252
+ greenhouse_gas_emissions: gesNumericSchema('common.greenhouseGasEmissionRequired'),
1253
+ construction_year: yup.string().nullable(),
1254
+ is_land_divisible: yup.mixed().nullable(),
1255
+ sanitation: yup.string().nullable(),
1256
+ available_at: yup.string().nullable(),
1257
+ });
1258
+ };
1259
+
1260
+ export const sellerViagerHousePropertySchema = () => {
1261
+ return sellerHousePropertySchema()
1262
+ .shape({
1263
+ is_dpe_blank: yup
1264
+ .mixed()
1265
+ .nullable()
1266
+ .when('subject_dpe', {
1267
+ is: 'yes',
1268
+ then: schema =>
1269
+ schema.required(
1270
+ Translator.translate(
1271
+ 'sellerHouseProperty.virginDPERequired',
1272
+ ),
1273
+ ),
1274
+ otherwise: schema => schema.nullable(),
1275
+ }),
1276
+ bouquet_price: yup
1277
+ .string()
1278
+ .nullable()
1279
+ .required(
1280
+ Translator.translate(
1281
+ 'sellerHouseProperty.bouquetPriceRequired',
1282
+ ),
1283
+ )
1284
+ .test('is-valid-number', '', v => !v || !isNaN(Number(v))),
1285
+ desired_annuity: yup
1286
+ .string()
1287
+ .nullable()
1288
+ .required(
1289
+ Translator.translate(
1290
+ 'sellerHouseProperty.desiredAnnuityRequired',
1291
+ ),
1292
+ )
1293
+ .test('is-valid-number', '', v => !v || !isNaN(Number(v))),
1294
+ annuitant_gender: yup
1295
+ .string()
1296
+ .nullable()
1297
+ .required(
1298
+ Translator.translate('sellerHouseProperty.viagerHeadRequired'),
1299
+ ),
1300
+ annuitant_male_age: yup
1301
+ .string()
1302
+ .nullable()
1303
+ .when('annuitant_gender', {
1304
+ is: (val: string) =>
1305
+ val === 'male' ||
1306
+ val === 'couple' ||
1307
+ val === 'man' ||
1308
+ val === 'both',
1309
+ then: schema =>
1310
+ schema.required(
1311
+ Translator.translate(
1312
+ 'sellerHouseProperty.manAgeRequired',
1313
+ ),
1314
+ ),
1315
+ otherwise: schema => schema.nullable(),
1316
+ })
1317
+ .test('is-valid-number', '', v => !v || !isNaN(Number(v))),
1318
+ annuitant_female_age: yup
1319
+ .string()
1320
+ .nullable()
1321
+ .when('annuitant_gender', {
1322
+ is: (val: string) =>
1323
+ val === 'female' ||
1324
+ val === 'couple' ||
1325
+ val === 'woman' ||
1326
+ val === 'both',
1327
+ then: schema =>
1328
+ schema.required(
1329
+ Translator.translate(
1330
+ 'sellerHouseProperty.womanAgeRequired',
1331
+ ),
1332
+ ),
1333
+ otherwise: schema => schema.nullable(),
1334
+ })
1335
+ .test('is-valid-number', '', v => !v || !isNaN(Number(v))),
1336
+ });
1337
+ };
1338
+
1339
+ export const sellerApartmentPropertySchema = () => {
1340
+ return yup.object().shape({
1341
+ living_area: yup
1342
+ .string()
1343
+ .nullable()
1344
+ .required(
1345
+ Translator.translate(
1346
+ 'sellerApartmentProperty.livingAreaRequired',
1347
+ ),
1348
+ )
1349
+ .test('is-valid-number', '', v => !v || !isNaN(Number(v))),
1350
+ rooms: yup.number().nullable().min(0),
1351
+ rooms_count: yup
1352
+ .number()
1353
+ .nullable()
1354
+ .required(
1355
+ Translator.translate(
1356
+ 'sellerApartmentProperty.bedroomsRequired',
1357
+ ),
1358
+ )
1359
+ .min(0),
1360
+ shower_rooms: yup.number().nullable().min(0),
1361
+ bathrooms: yup.number().nullable().min(0),
1362
+ building_floors_count: yup.number().nullable().min(0),
1363
+ property_condition: yup
1364
+ .string()
1365
+ .nullable()
1366
+ .required(
1367
+ Translator.translate(
1368
+ 'sellerApartmentProperty.propertyConditionRequired',
1369
+ ),
1370
+ ),
1371
+ has_parking: yup.mixed().nullable(),
1372
+ has_garage: yup.mixed().nullable(),
1373
+ orientation: yup.string().nullable(),
1374
+ heating_system: yup.string().nullable(),
1375
+ is_copropriety: yup.mixed().nullable(),
1376
+ co_owned_lots_count: yup.string().nullable(),
1377
+ annual_service_charges: yup.string().nullable(),
1378
+ freeOrRented: yup
1379
+ .string()
1380
+ .nullable()
1381
+ .required(
1382
+ Translator.translate(
1383
+ 'sellerApartmentProperty.freeOrRentedRequired',
1384
+ ),
1385
+ ),
1386
+ monthly_rent: yup
1387
+ .string()
1388
+ .nullable()
1389
+ .when('freeOrRented', {
1390
+ is: 'rented',
1391
+ then: schema =>
1392
+ schema.required(
1393
+ Translator.translate(
1394
+ 'sellerApartmentProperty.monthlyRentRequired',
1395
+ ),
1396
+ ),
1397
+ otherwise: schema => schema.notRequired().nullable(),
1398
+ }),
1399
+ annual_tax: yup
1400
+ .string()
1401
+ .nullable()
1402
+ .when('freeOrRented', {
1403
+ is: 'rented',
1404
+ then: schema =>
1405
+ schema.required(
1406
+ Translator.translate(
1407
+ 'sellerApartmentProperty.annualPropertyTaxRequired',
1408
+ ),
1409
+ ),
1410
+ otherwise: schema => schema.notRequired().nullable(),
1411
+ }),
1412
+ subject_dpe: yup
1413
+ .mixed()
1414
+ .nullable()
1415
+ .required(
1416
+ Translator.translate(
1417
+ 'sellerApartmentProperty.subjectToDPERequired',
1418
+ ),
1419
+ ),
1420
+ is_dpe_blank: yup
1421
+ .mixed()
1422
+ .nullable()
1423
+ .required(
1424
+ Translator.translate(
1425
+ 'sellerApartmentProperty.virginDPERequired',
1426
+ ),
1427
+ ),
1428
+ dpe_grade: dpeGradeSchema('common.dpeClassRequired'),
1429
+ dpe_date: dpeDateSchema('common.dpeDateRequired'),
1430
+ primary_energy_consumption: dpeNumericSchema('common.primaryEnergyConsumptionRequired'),
1431
+ estimated_annual_energy_cost: dpeNumericSchema('common.estimatedAnnualCostsRequired'),
1432
+ ges_grade: gesGradeSchema('common.gesClassRequired'),
1433
+ ges_date: gesDateSchema('common.gesDateRequired'),
1434
+ greenhouse_gas_emissions: gesNumericSchema('common.greenhouseGasEmissionRequired'),
1435
+ available_at: yup.string().nullable(),
1436
+ construction_year: yup.string().nullable(),
1437
+ is_extension_possible: yup.mixed().nullable(),
1438
+ sanitation: yup.string().nullable(),
1439
+ });
1440
+ };
1441
+
1442
+ export const sellerViagerApartmentPropertySchema = () => {
1443
+ return sellerApartmentPropertySchema()
1444
+ .shape({
1445
+ is_dpe_blank: yup
1446
+ .mixed()
1447
+ .nullable()
1448
+ .when('subject_dpe', {
1449
+ is: 'yes',
1450
+ then: schema =>
1451
+ schema.required(
1452
+ Translator.translate(
1453
+ 'sellerApartmentProperty.virginDPERequired',
1454
+ ),
1455
+ ),
1456
+ otherwise: schema => schema.nullable(),
1457
+ }),
1458
+ bouquet_price: yup
1459
+ .string()
1460
+ .nullable()
1461
+ .required(
1462
+ Translator.translate(
1463
+ 'sellerHouseProperty.bouquetPriceRequired',
1464
+ ),
1465
+ )
1466
+ .test('is-valid-number', '', v => !v || !isNaN(Number(v))),
1467
+ desired_annuity: yup
1468
+ .string()
1469
+ .nullable()
1470
+ .required(
1471
+ Translator.translate(
1472
+ 'sellerHouseProperty.desiredAnnuityRequired',
1473
+ ),
1474
+ )
1475
+ .test('is-valid-number', '', v => !v || !isNaN(Number(v))),
1476
+ annuitant_gender: yup
1477
+ .string()
1478
+ .nullable()
1479
+ .required(
1480
+ Translator.translate(
1481
+ 'sellerHouseProperty.viagerHeadRequired',
1482
+ ),
1483
+ ),
1484
+ annuitant_male_age: yup
1485
+ .string()
1486
+ .nullable()
1487
+ .test('is-valid-number', '', v => !v || !isNaN(Number(v))),
1488
+ annuitant_female_age: yup
1489
+ .string()
1490
+ .nullable()
1491
+ .test('is-valid-number', '', v => !v || !isNaN(Number(v))),
1492
+ });
1493
+ };
1494
+
1495
+ export const sellerResaleApartmentPropertySchema = () => {
1496
+ return yup.object().shape({
1497
+ livingArea: yup
1498
+ .string()
1499
+ .nullable()
1500
+ .required(
1501
+ Translator.translate(
1502
+ 'sellerApartmentProperty.livingAreaRequired',
1503
+ ),
1504
+ ),
1505
+ bedrooms: yup
1506
+ .number()
1507
+ .nullable()
1508
+ .required(
1509
+ Translator.translate(
1510
+ 'sellerApartmentProperty.bedroomsRequired',
1511
+ ),
1512
+ )
1513
+ .min(0),
1514
+ showerRooms: yup.number().nullable().min(0),
1515
+ bathrooms: yup.number().nullable().min(0),
1516
+ buildingFloors: yup.number().nullable().min(0),
1517
+ propertyCondition: yup
1518
+ .string()
1519
+ .nullable()
1520
+ .required(
1521
+ Translator.translate(
1522
+ 'sellerApartmentProperty.propertyConditionRequired',
1523
+ ),
1524
+ ),
1525
+ parkingSpace: yup.string().nullable(),
1526
+ garage: yup.string().nullable(),
1527
+ exposure: yup.string().nullable(),
1528
+ heatingSystem: yup.string().nullable(),
1529
+ coOwnership: yup.string().nullable(),
1530
+ numberOfLots: yup.string().nullable(),
1531
+ annualCoOwnershipCharges: yup.string().nullable(),
1532
+ freeOrRented: yup
1533
+ .string()
1534
+ .nullable()
1535
+ .required(
1536
+ Translator.translate(
1537
+ 'sellerApartmentProperty.freeOrRentedRequired',
1538
+ ),
1539
+ ),
1540
+ monthly_rent: yup
1541
+ .string()
1542
+ .nullable()
1543
+ .when('freeOrRented', {
1544
+ is: 'rented',
1545
+ then: schema =>
1546
+ schema.required(
1547
+ Translator.translate(
1548
+ 'sellerHouseProperty.monthlyRentRequired',
1549
+ ),
1550
+ ),
1551
+ otherwise: schema => schema.nullable(),
1552
+ }),
1553
+ annual_tax: yup
1554
+ .string()
1555
+ .nullable()
1556
+ .when('freeOrRented', {
1557
+ is: 'rented',
1558
+ then: schema =>
1559
+ schema.required(
1560
+ Translator.translate(
1561
+ 'sellerApartmentProperty.annualPropertyTaxRequired',
1562
+ ),
1563
+ ),
1564
+ otherwise: schema => schema.nullable(),
1565
+ }),
1566
+ subjectToDPE: yup
1567
+ .string()
1568
+ .nullable()
1569
+ .required(
1570
+ Translator.translate(
1571
+ 'sellerApartmentProperty.subjectToDPERequired',
1572
+ ),
1573
+ ),
1574
+ virginDPE: yup
1575
+ .string()
1576
+ .nullable()
1577
+ .required(
1578
+ Translator.translate(
1579
+ 'sellerApartmentProperty.virginDPERequired',
1580
+ ),
1581
+ ),
1582
+ dpeClass: yup.string().nullable(),
1583
+ dpeDate: yup.string().nullable(),
1584
+ primaryEnergyConsumption: yup.string().nullable(),
1585
+ estimatedAnnualCosts: yup.string().nullable(),
1586
+ gesClass: yup.string().nullable(),
1587
+ gesDate: yup.string().nullable(),
1588
+ greenhouseGasEmission: yup.string().nullable(),
1589
+ propertyAvailability: yup.string().nullable(),
1590
+ constructionYear: yup.string().nullable(),
1591
+ possibleExtensions: yup.string().nullable(),
1592
+ sanitationType: yup.string().nullable(),
1593
+ bouquetPrice: yup
1594
+ .string()
1595
+ .nullable()
1596
+ .required(
1597
+ Translator.translate(
1598
+ 'sellerHouseProperty.bouquetPriceRequired',
1599
+ ),
1600
+ ),
1601
+ desiredAnnuity: yup
1602
+ .string()
1603
+ .nullable()
1604
+ .required(
1605
+ Translator.translate(
1606
+ 'sellerHouseProperty.desiredAnnuityRequired',
1607
+ ),
1608
+ ),
1609
+ viagerHead: yup
1610
+ .string()
1611
+ .nullable()
1612
+ .required(
1613
+ Translator.translate('sellerHouseProperty.viagerHeadRequired'),
1614
+ ),
1615
+ manAge: yup
1616
+ .string()
1617
+ .nullable()
1618
+ .when('viagerHead', {
1619
+ is: (val: string) => val === 'man' || val === 'both',
1620
+ then: schema =>
1621
+ schema.required(
1622
+ Translator.translate(
1623
+ 'sellerHouseProperty.manAgeRequired',
1624
+ ),
1625
+ ),
1626
+ otherwise: schema => schema.nullable(),
1627
+ }),
1628
+ womanAge: yup
1629
+ .string()
1630
+ .nullable()
1631
+ .when('viagerHead', {
1632
+ is: (val: string) => val === 'woman' || val === 'both',
1633
+ then: schema =>
1634
+ schema.required(
1635
+ Translator.translate(
1636
+ 'sellerHouseProperty.womanAgeRequired',
1637
+ ),
1638
+ ),
1639
+ otherwise: schema => schema.nullable(),
1640
+ }),
1641
+ });
1642
+ };
1643
+
1644
+ export const sellerLandPropertySchema = () => {
1645
+ return yup.object().shape({
1646
+ land_type: yup
1647
+ .string()
1648
+ .nullable()
1649
+ .required(
1650
+ Translator.translate('sellerLandProperty.landTypeRequired'),
1651
+ ),
1652
+ land_area: yup
1653
+ .string()
1654
+ .nullable()
1655
+ .required(
1656
+ Translator.translate('sellerLandProperty.landSurfaceRequired'),
1657
+ )
1658
+ .test('is-valid-number', '', v => !v || !isNaN(Number(v))),
1659
+ is_builder_free: yup
1660
+ .mixed()
1661
+ .nullable()
1662
+ .required(
1663
+ Translator.translate('sellerLandProperty.freeBuilderRequired'),
1664
+ ),
1665
+ is_serviced: yup
1666
+ .mixed()
1667
+ .nullable()
1668
+ .required(
1669
+ Translator.translate('sellerLandProperty.servicedRequired'),
1670
+ ),
1671
+ plu_zone: yup.string().nullable(),
1672
+ is_demarcated: yup
1673
+ .mixed()
1674
+ .nullable()
1675
+ .required(
1676
+ Translator.translate(
1677
+ 'sellerLandProperty.boundaryDemarcationRequired',
1678
+ ),
1679
+ ),
1680
+ annual_tax: yup.string().nullable().test('is-valid-number', '', v => !v || !isNaN(Number(v))),
1681
+ available_at: yup.string().nullable(),
1682
+ });
1683
+ };
1684
+
1685
+ export const sellerBuildingPropertySchema = () => {
1686
+ return yup.object().shape({
1687
+ units_count: yup
1688
+ .number()
1689
+ .nullable()
1690
+ .required(
1691
+ Translator.translate(
1692
+ 'sellerBuildingProperty.numberOfDwellingsRequired',
1693
+ ),
1694
+ )
1695
+ .min(0),
1696
+ total_surface: yup
1697
+ .string()
1698
+ .nullable()
1699
+ .required(
1700
+ Translator.translate(
1701
+ 'sellerBuildingProperty.totalBuildingAreaRequired',
1702
+ ),
1703
+ )
1704
+ .test('is-valid-number', '', v => !v || !isNaN(Number(v))),
1705
+ is_copropriety: yup.mixed().nullable(),
1706
+ co_owned_lots_count: yup.string().nullable(),
1707
+ annual_service_charges: yup
1708
+ .string()
1709
+ .nullable()
1710
+ .test('is-valid-number', '', v => !v || !isNaN(Number(v))),
1711
+ has_garage: yup.mixed().nullable(),
1712
+ has_parking: yup.mixed().nullable(),
1713
+ orientation: yup.string().nullable(),
1714
+ heating_system: yup.string().nullable(),
1715
+ property_condition: yup
1716
+ .string()
1717
+ .nullable()
1718
+ .required(
1719
+ Translator.translate(
1720
+ 'sellerBuildingProperty.propertyConditionRequired',
1721
+ ),
1722
+ ),
1723
+ occupancy_status: yup
1724
+ .string()
1725
+ .nullable()
1726
+ .required(
1727
+ Translator.translate(
1728
+ 'sellerBuildingProperty.freeOrRentedRequired',
1729
+ ),
1730
+ ),
1731
+ annual_revenue: yup
1732
+ .string()
1733
+ .nullable()
1734
+ .when('occupancy_status', {
1735
+ is: 'rented',
1736
+ then: schema =>
1737
+ schema.required(
1738
+ Translator.translate(
1739
+ 'sellerBuildingProperty.annualIncomeRequired',
1740
+ ),
1741
+ ),
1742
+ otherwise: schema => schema.notRequired().nullable(),
1743
+ }),
1744
+ annual_tax: yup
1745
+ .string()
1746
+ .nullable()
1747
+ .when('occupancy_status', {
1748
+ is: 'rented',
1749
+ then: schema =>
1750
+ schema.required(
1751
+ Translator.translate(
1752
+ 'sellerBuildingProperty.annualPropertyTaxRequired',
1753
+ ),
1754
+ ),
1755
+ otherwise: schema => schema.notRequired().nullable(),
1756
+ }),
1757
+ subject_dpe: yup
1758
+ .string()
1759
+ .nullable()
1760
+ .oneOf(['yes', 'no'])
1761
+ .required(
1762
+ Translator.translate(
1763
+ 'sellerBuildingProperty.subjectToDPERequired',
1764
+ ),
1765
+ ),
1766
+ is_dpe_blank: yup
1767
+ .string()
1768
+ .nullable()
1769
+ .oneOf(['yes', 'no'])
1770
+ .required(
1771
+ Translator.translate(
1772
+ 'sellerBuildingProperty.virginDPERequired',
1773
+ ),
1774
+ ),
1775
+ dpe_grade: dpeGradeSchema('common.dpeClassRequired'),
1776
+ dpe_date: dpeDateSchema('common.dpeDateRequired'),
1777
+ primary_energy_consumption: dpeNumericSchema('common.primaryEnergyConsumptionRequired'),
1778
+ estimated_annual_energy_cost: dpeNumericSchema('common.estimatedAnnualCostsRequired'),
1779
+ ges_grade: gesGradeSchema('common.gesClassRequired'),
1780
+ ges_date: gesDateSchema('common.gesDateRequired'),
1781
+ greenhouse_gas_emissions: gesNumericSchema('common.greenhouseGasEmissionRequired'),
1782
+ is_extension_possible: yup.mixed().nullable(),
1783
+ available_at: yup.string().nullable(),
1784
+ sanitation: yup.string().nullable(),
1785
+ });
1786
+ };
1787
+
1788
+ export const sellerOfficePropertySchema = () => {
1789
+ return yup.object().shape({
1790
+ total_surface: yup
1791
+ .string()
1792
+ .nullable()
1793
+ .required(
1794
+ Translator.translate(
1795
+ 'sellerOfficeProperty.totalOfficeAreaRequired',
1796
+ ),
1797
+ )
1798
+ .test('is-valid-number', '', v => !v || !isNaN(Number(v))),
1799
+ separated_offices_count: yup
1800
+ .number()
1801
+ .nullable()
1802
+ .required(
1803
+ Translator.translate(
1804
+ 'sellerOfficeProperty.numberOfOfficesRequired',
1805
+ ),
1806
+ )
1807
+ .min(0),
1808
+ is_open_space: yup.mixed().nullable(),
1809
+ floor_level: yup.string().nullable(),
1810
+ has_elevator: yup.mixed().nullable(),
1811
+ has_sanitary_facilities: yup.mixed().nullable(),
1812
+ has_parking: yup.mixed().nullable(),
1813
+ has_garage: yup.mixed().nullable(),
1814
+ property_condition: yup
1815
+ .string()
1816
+ .nullable()
1817
+ .required(
1818
+ Translator.translate(
1819
+ 'sellerOfficeProperty.propertyConditionRequired',
1820
+ ),
1821
+ ),
1822
+ is_disabled_accessible: yup.mixed().nullable(),
1823
+ heating_system: yup.string().nullable(),
1824
+ occupancy_status: yup
1825
+ .string()
1826
+ .nullable()
1827
+ .required(
1828
+ Translator.translate(
1829
+ 'sellerOfficeProperty.freeOrRentedRequired',
1830
+ ),
1831
+ ),
1832
+ annual_revenue: yup
1833
+ .string()
1834
+ .nullable()
1835
+ .when('occupancy_status', {
1836
+ is: 'rented',
1837
+ then: (schema) =>
1838
+ schema.required(
1839
+ Translator.translate(
1840
+ 'sellerOfficeProperty.annualIncomeRequired',
1841
+ ),
1842
+ ),
1843
+ otherwise: (schema) => schema.nullable(),
1844
+ }),
1845
+ annual_tax: yup
1846
+ .string()
1847
+ .nullable()
1848
+ .when('occupancy_status', {
1849
+ is: 'rented',
1850
+ then: (schema) =>
1851
+ schema.required(
1852
+ Translator.translate(
1853
+ 'sellerOfficeProperty.annualPropertyTaxRequired',
1854
+ ),
1855
+ ),
1856
+ otherwise: (schema) => schema.nullable(),
1857
+ }),
1858
+ subject_dpe: yup
1859
+ .string()
1860
+ .nullable()
1861
+ .oneOf(['yes', 'no'])
1862
+ .required(
1863
+ Translator.translate(
1864
+ 'sellerOfficeProperty.subjectToDPERequired',
1865
+ ),
1866
+ ),
1867
+ is_dpe_blank: yup
1868
+ .string()
1869
+ .nullable()
1870
+ .oneOf(['yes', 'no'])
1871
+ .required(
1872
+ Translator.translate('sellerOfficeProperty.virginDPERequired'),
1873
+ ),
1874
+ dpe_grade: dpeGradeSchema('common.dpeClassRequired'),
1875
+ dpe_date: dpeDateSchema('common.dpeDateRequired'),
1876
+ primary_energy_consumption: dpeNumericSchema('common.primaryEnergyConsumptionRequired'),
1877
+ estimated_annual_energy_cost: dpeNumericSchema('common.estimatedAnnualCostsRequired'),
1878
+ ges_grade: gesGradeSchema('common.gesClassRequired'),
1879
+ ges_date: gesDateSchema('common.gesDateRequired'),
1880
+ greenhouse_gas_emissions: gesNumericSchema('common.greenhouseGasEmissionRequired'),
1881
+ is_copropriety: yup.mixed().nullable(),
1882
+ co_owned_lots_count: yup.string().nullable(),
1883
+ annual_service_charges: yup
1884
+ .string()
1885
+ .nullable()
1886
+ .test('is-valid-number', '', v => !v || !isNaN(Number(v))),
1887
+ construction_year: yup.string().nullable(),
1888
+ available_at: yup.string().nullable(),
1889
+ sanitation: yup.string().nullable(),
1890
+ });
1891
+ };
1892
+
1893
+ export const sellerCottagePropertySchema = () => {
1894
+ return yup.object().shape({
1895
+ gite_type: yup
1896
+ .string()
1897
+ .nullable()
1898
+ .required(
1899
+ Translator.translate(
1900
+ 'sellerCottageProperty.propertyTypeRequired',
1901
+ ),
1902
+ ),
1903
+ gites_count: yup.number().nullable().min(1),
1904
+ living_area: yup
1905
+ .string()
1906
+ .nullable()
1907
+ .required(
1908
+ Translator.translate(
1909
+ 'sellerCottageProperty.totalLivingAreaRequired',
1910
+ ),
1911
+ )
1912
+ .test('is-valid-number', '', v => !v || !isNaN(Number(v)))
1913
+ .test(
1914
+ 'living-area-lt-land-area',
1915
+ Translator.translate('sellerCottageProperty.livingAreaGreaterThanLandArea'),
1916
+ function (value) {
1917
+ const { land_area } = this.parent;
1918
+ if (!value || !land_area) return true;
1919
+ return Number(value) < Number(land_area);
1920
+ },
1921
+ ),
1922
+ land_area: yup
1923
+ .string()
1924
+ .nullable()
1925
+ .test('is-valid-number', '', v => !v || !isNaN(Number(v)))
1926
+ .test(
1927
+ 'land-area-gt-living-area',
1928
+ Translator.translate('sellerCottageProperty.landAreaLessThanLivingArea'),
1929
+ function (value) {
1930
+ const { living_area } = this.parent;
1931
+ if (!value || !living_area) return true;
1932
+ return Number(value) > Number(living_area);
1933
+ },
1934
+ ),
1935
+ rooms_count: yup.number().nullable().min(0),
1936
+ shower_rooms: yup.number().nullable().min(0),
1937
+ bathrooms: yup.number().nullable().min(0),
1938
+ ground_floor: yup.mixed().nullable(),
1939
+ has_garage: yup.mixed().nullable(),
1940
+ pool: yup.mixed().nullable(),
1941
+ heating_system: yup.string().nullable(),
1942
+ property_condition: yup
1943
+ .string()
1944
+ .nullable()
1945
+ .required(
1946
+ Translator.translate(
1947
+ 'sellerCottageProperty.propertyConditionRequired',
1948
+ ),
1949
+ ),
1950
+ annual_revenue: yup
1951
+ .string()
1952
+ .nullable()
1953
+ .required(
1954
+ Translator.translate(
1955
+ 'sellerCottageProperty.annualIncomeRequired',
1956
+ ),
1957
+ )
1958
+ .test('is-valid-number', '', v => !v || !isNaN(Number(v))),
1959
+ has_private_housing: yup.mixed().nullable(),
1960
+ occupancy_status: yup
1961
+ .string()
1962
+ .nullable()
1963
+ .required(
1964
+ Translator.translate(
1965
+ 'sellerCottageProperty.freeOrRentedRequired',
1966
+ ),
1967
+ ),
1968
+ monthly_rent: yup
1969
+ .string()
1970
+ .nullable()
1971
+ .when('occupancy_status', {
1972
+ is: 'rented',
1973
+ then: schema =>
1974
+ schema.required(
1975
+ Translator.translate(
1976
+ 'sellerCottageProperty.monthlyRentRequired',
1977
+ ),
1978
+ ),
1979
+ otherwise: schema => schema.notRequired().nullable(),
1980
+ }),
1981
+
1982
+ annual_tax: yup
1983
+ .string()
1984
+ .nullable()
1985
+ .when('occupancy_status', {
1986
+ is: 'rented',
1987
+ then: schema =>
1988
+ schema.required(
1989
+ Translator.translate(
1990
+ 'sellerCottageProperty.annualPropertyTaxRequired',
1991
+ ),
1992
+ ),
1993
+ otherwise: schema => schema.notRequired().nullable(),
1994
+ }),
1995
+ subject_dpe: yup
1996
+ .mixed()
1997
+ .nullable()
1998
+ .required(
1999
+ Translator.translate(
2000
+ 'sellerCottageProperty.subjectToDPERequired',
2001
+ ),
2002
+ ),
2003
+ is_dpe_blank: yup
2004
+ .mixed()
2005
+ .nullable()
2006
+ .required(
2007
+ Translator.translate('sellerCottageProperty.virginDPERequired'),
2008
+ ),
2009
+ dpe_grade: dpeGradeSchema('common.dpeClassRequired'),
2010
+ dpe_date: dpeDateSchema('common.dpeDateRequired'),
2011
+ primary_energy_consumption: dpeNumericSchema('common.primaryEnergyConsumptionRequired'),
2012
+ estimated_annual_energy_cost: dpeNumericSchema('common.estimatedAnnualCostsRequired'),
2013
+ ges_grade: gesGradeSchema('common.gesClassRequired'),
2014
+ ges_date: gesDateSchema('common.gesDateRequired'),
2015
+ greenhouse_gas_emissions: gesNumericSchema('common.greenhouseGasEmissionRequired'),
2016
+ available_at: yup.string().nullable(),
2017
+ construction_year: yup.string().nullable(),
2018
+ is_extension_possible: yup.mixed().nullable(),
2019
+ sanitation: yup.string().nullable(),
2020
+ });
2021
+ };
2022
+
2023
+ export const sellerGarageParkingPropertySchema = () => {
2024
+ return yup.object().shape({
2025
+ parking_type: yup
2026
+ .string()
2027
+ .nullable()
2028
+ .required(
2029
+ Translator.translate(
2030
+ 'sellerGarageParkingProperty.parkingTypeRequired',
2031
+ ),
2032
+ ),
2033
+ intended_use: yup.string().nullable(),
2034
+ parking_surface: yup
2035
+ .string()
2036
+ .nullable()
2037
+ .required(
2038
+ Translator.translate(
2039
+ 'sellerGarageParkingProperty.totalAreaRequired',
2040
+ ),
2041
+ )
2042
+ .test('is-valid-number', '', v => !v || !isNaN(Number(v))),
2043
+ occupancy_status: yup
2044
+ .string()
2045
+ .nullable()
2046
+ .required(
2047
+ Translator.translate(
2048
+ 'sellerGarageParkingProperty.freeOrRentedRequired',
2049
+ ),
2050
+ ),
2051
+ monthly_rent: yup
2052
+ .string()
2053
+ .nullable()
2054
+ .when('occupancy_status', {
2055
+ is: 'rented',
2056
+ then: schema =>
2057
+ schema.required(
2058
+ Translator.translate(
2059
+ 'sellerGarageParkingProperty.monthlyRentRequired',
2060
+ ),
2061
+ ),
2062
+ otherwise: schema => schema.nullable(),
2063
+ }),
2064
+ annual_tax: yup
2065
+ .string()
2066
+ .nullable()
2067
+ .when('occupancy_status', {
2068
+ is: 'rented',
2069
+ then: schema =>
2070
+ schema.required(
2071
+ Translator.translate(
2072
+ 'sellerGarageParkingProperty.annualPropertyTaxRequired',
2073
+ ),
2074
+ ),
2075
+ otherwise: schema => schema.nullable(),
2076
+ }),
2077
+ available_at: yup.string().nullable(),
2078
+ construction_year: yup.string().nullable(),
2079
+ });
2080
+ };
2081
+
2082
+ export const sellerCommercialPropertySchema = () => {
2083
+ return yup.object().shape({
2084
+ total_surface: yup
2085
+ .string()
2086
+ .nullable()
2087
+ .required(
2088
+ Translator.translate(
2089
+ 'sellerCommercialProperty.totalSurfaceRequired',
2090
+ ),
2091
+ )
2092
+ .test('is-valid-number', '', v => !v || !isNaN(Number(v))),
2093
+ shop_front_length: yup
2094
+ .string()
2095
+ .nullable()
2096
+ .required(
2097
+ Translator.translate(
2098
+ 'sellerCommercialProperty.windowSurfaceRequired',
2099
+ ),
2100
+ )
2101
+ .test('is-valid-number', '', v => !v || !isNaN(Number(v))),
2102
+ is_prime_location: yup.mixed().nullable(),
2103
+ parking_surface: yup
2104
+ .string()
2105
+ .nullable()
2106
+ .test('is-valid-number', '', v => !v || !isNaN(Number(v))),
2107
+ property_condition: yup
2108
+ .string()
2109
+ .nullable()
2110
+ .required(
2111
+ Translator.translate(
2112
+ 'sellerCommercialProperty.propertyConditionRequired',
2113
+ ),
2114
+ ),
2115
+ occupancy_status: yup
2116
+ .string()
2117
+ .nullable()
2118
+ .required(
2119
+ Translator.translate(
2120
+ 'sellerCommercialProperty.freeOrRentedRequired',
2121
+ ),
2122
+ ),
2123
+ monthly_rent: yup
2124
+ .string()
2125
+ .nullable()
2126
+ .when('occupancy_status', {
2127
+ is: 'rented',
2128
+ then: schema =>
2129
+ schema.required(
2130
+ Translator.translate(
2131
+ 'sellerCommercialProperty.monthlyRentRequired',
2132
+ ),
2133
+ ),
2134
+ otherwise: schema => schema.notRequired().nullable(),
2135
+ }),
2136
+ annual_tax: yup
2137
+ .string()
2138
+ .nullable()
2139
+ .when('occupancy_status', {
2140
+ is: 'rented',
2141
+ then: schema =>
2142
+ schema.required(
2143
+ Translator.translate(
2144
+ 'sellerCommercialProperty.annualPropertyTaxRequired',
2145
+ ),
2146
+ ),
2147
+ otherwise: schema => schema.notRequired().nullable(),
2148
+ }),
2149
+ is_disabled_accessible: yup.mixed().nullable(),
2150
+ is_copropriety: yup.mixed().nullable(),
2151
+ construction_year: yup.string().nullable(),
2152
+ co_owned_lots_count: yup.string().nullable(),
2153
+ annual_service_charges: yup.string().nullable(),
2154
+ });
2155
+ };
2156
+
2157
+ export const agentImmobilierSignUpSchema = () => {
2158
+ return yup.object().shape({
2159
+ email: yup
2160
+ .string()
2161
+ .nullable()
2162
+ .trim()
2163
+ .required(Translator.translate('signup.emailRequired'))
2164
+ .email(Translator.translate('signup.emailInvalid'))
2165
+ .matches(
2166
+ regexEmail,
2167
+ Translator.translate('signup.emailInvalid'),
2168
+ ),
2169
+ siret_number: yup
2170
+ .string()
2171
+ .nullable()
2172
+ .trim()
2173
+ .required(
2174
+ Translator.translate('agentImmobilierInfo.siretSirenRequired'),
2175
+ )
2176
+ .length(14, Translator.translate('agentSignup.siretLength')),
2177
+ card_number: yup
2178
+ .string()
2179
+ .nullable()
2180
+ .trim()
2181
+ .required(
2182
+ Translator.translate(
2183
+ 'agentImmobilierInfo.professionalCardNumberRequired',
2184
+ ),
2185
+ ),
2186
+ last_name: yup
2187
+ .string()
2188
+ .nullable()
2189
+ .trim()
2190
+ .required(Translator.translate('agentSignup.lastNameRequired')),
2191
+ first_name: yup
2192
+ .string()
2193
+ .nullable()
2194
+ .trim()
2195
+ .required(Translator.translate('agentSignup.firstNameRequired')),
2196
+ agency_website_url: yup
2197
+ .string()
2198
+ .nullable()
2199
+ .trim()
2200
+ .url(Translator.translate('agentSignup.websiteInvalid')),
2201
+ brand_name: yup
2202
+ .string()
2203
+ .nullable()
2204
+ .trim()
2205
+ .required(
2206
+ Translator.translate('agentImmobilierInfo.brandNameRequired'),
2207
+ ),
2208
+ property_prefix: yup
2209
+ .string()
2210
+ .nullable()
2211
+ .trim()
2212
+ .max(2, Translator.translate('agentSignup.prefixMax')),
2213
+ password: yup
2214
+ .string()
2215
+ .nullable()
2216
+ .required(Translator.translate('signup.passwordRequired'))
2217
+ .min(8, Translator.translate('signup.passwordMin'))
2218
+ .max(32, Translator.translate('signup.passwordMax'))
2219
+ .matches(
2220
+ /^(?=.*[A-Za-z])(?=.*\d).+$/,
2221
+ Translator.translate('agentSignup.passwordAlphaNumeric'),
2222
+ ),
2223
+ });
2224
+ };
2225
+
2226
+
2227
+ export const agentCommercialSignUpSchema = () => {
2228
+ return yup.object().shape({
2229
+ email: yup
2230
+ .string()
2231
+ .nullable()
2232
+ .trim()
2233
+ .required(Translator.translate('signup.emailRequired'))
2234
+ .email(Translator.translate('signup.emailInvalid'))
2235
+ .matches(
2236
+ regexEmail,
2237
+ Translator.translate('signup.emailInvalid'),
2238
+ ),
2239
+ siret_number: yup
2240
+ .string()
2241
+ .nullable()
2242
+ .trim()
2243
+ .test(
2244
+ 'is-valid-siret',
2245
+ Translator.translate('agentSignup.siretLength'),
2246
+ value => !value || /^\d{14}$/.test(value),
2247
+ ),
2248
+ last_name: yup
2249
+ .string()
2250
+ .nullable()
2251
+ .trim()
2252
+ .required(Translator.translate('agentSignup.lastNameRequired')),
2253
+ first_name: yup
2254
+ .string()
2255
+ .nullable()
2256
+ .trim()
2257
+ .required(Translator.translate('agentSignup.firstNameRequired')),
2258
+ agency_website_url: yup
2259
+ .string()
2260
+ .nullable()
2261
+ .trim()
2262
+ .url(Translator.translate('agentSignup.websiteInvalid')),
2263
+ brand_name: yup
2264
+ .string()
2265
+ .nullable()
2266
+ .trim()
2267
+ .required(
2268
+ Translator.translate('agentImmobilierInfo.brandNameRequired'),
2269
+ ),
2270
+ property_prefix: yup
2271
+ .string()
2272
+ .nullable()
2273
+ .trim()
2274
+ .max(2, Translator.translate('agentSignup.prefixMax')),
2275
+ password: yup
2276
+ .string()
2277
+ .nullable()
2278
+ .required(Translator.translate('signup.passwordRequired'))
2279
+ .min(8, Translator.translate('signup.passwordMin'))
2280
+ .max(32, Translator.translate('signup.passwordMax'))
2281
+ .matches(
2282
+ /^(?=.*[A-Za-z])(?=.*\d).+$/,
2283
+ Translator.translate('agentSignup.passwordAlphaNumeric'),
2284
+ ),
2285
+ });
2286
+ };
2287
+
2288
+ export const agentAgencySetupSchema = () => {
2289
+ return yup.object().shape({
2290
+ brand_name: yup
2291
+ .string()
2292
+ .nullable()
2293
+ .trim()
2294
+ .required(Translator.translate('agentAgencySetup.brandNameRequired')),
2295
+ agency_website_url: yup
2296
+ .string()
2297
+ .nullable()
2298
+ .trim()
2299
+ .url(Translator.translate('agentSignup.websiteInvalid')),
2300
+ property_prefix: yup
2301
+ .string()
2302
+ .nullable()
2303
+ .trim()
2304
+ .required(Translator.translate('agentAgencySetup.prefixRequired'))
2305
+ .max(2, Translator.translate('agentSignup.prefixMax')),
2306
+ });
2307
+ };
2308
+
2309
+ export const agentImmobilierInfoSchema = () => {
2310
+ return yup.object().shape({
2311
+ agencyName: yup
2312
+ .string()
2313
+ .nullable()
2314
+ .required(
2315
+ Translator.translate('agentImmobilierInfo.agencyNameRequired'),
2316
+ ),
2317
+ siretSiren: yup
2318
+ .string()
2319
+ .nullable()
2320
+ .required(
2321
+ Translator.translate('agentImmobilierInfo.siretSirenRequired'),
2322
+ ),
2323
+ phoneNumber: yup.string().nullable(),
2324
+ professionalCardNumber: yup
2325
+ .string()
2326
+ .nullable()
2327
+ .required(
2328
+ Translator.translate(
2329
+ 'agentImmobilierInfo.professionalCardNumberRequired',
2330
+ ),
2331
+ ),
2332
+ brandName: yup
2333
+ .string()
2334
+ .nullable()
2335
+ .required(
2336
+ Translator.translate('agentImmobilierInfo.brandNameRequired'),
2337
+ ),
2338
+ });
2339
+ };
2340
+
2341
+ export const agentApartmentPropertySchema = () =>
2342
+ yup.object().shape({
2343
+ living_area: yup.string().required(),
2344
+ rooms: yup.number().required(),
2345
+ rooms_count: yup.number().required(),
2346
+ shower_rooms: yup.number().nullable(),
2347
+ bathrooms: yup.number().nullable(),
2348
+ building_floors_count: yup.number().nullable(),
2349
+
2350
+ property_condition: yup.string().required(),
2351
+ has_parking: yup.string().nullable(),
2352
+ has_garage: yup.string().nullable(),
2353
+ orientation: yup.string().nullable(),
2354
+ heating_system: yup.string().nullable(),
2355
+
2356
+ is_copropriety: yup.string().nullable(),
2357
+ co_owned_lots_count: yup.string().when('is_copropriety', {
2358
+ is: 'yes',
2359
+ then: schema => schema.required(),
2360
+ otherwise: schema => schema.nullable(),
2361
+ }),
2362
+ annual_service_charges: yup.string().when('is_copropriety', {
2363
+ is: 'yes',
2364
+ then: schema => schema.required(),
2365
+ otherwise: schema => schema.nullable(),
2366
+ }),
2367
+ no_ongoing_proceedings: yup.string().when('is_copropriety', {
2368
+ is: 'yes',
2369
+ then: schema => schema.required(),
2370
+ otherwise: schema => schema.nullable(),
2371
+ }),
2372
+
2373
+ freeOrRented: yup.string().required(),
2374
+ monthly_rent: yup.string().when('freeOrRented', {
2375
+ is: 'rented',
2376
+ then: schema => schema.required(),
2377
+ otherwise: schema => schema.nullable(),
2378
+ }),
2379
+ annual_tax: yup.string().when('freeOrRented', {
2380
+ is: 'rented',
2381
+ then: schema => schema.required(),
2382
+ otherwise: schema => schema.nullable(),
2383
+ }),
2384
+
2385
+ subject_dpe: yup
2386
+ .string()
2387
+ .nullable()
2388
+ .oneOf(['yes', 'no'])
2389
+ .required(),
2390
+ is_dpe_blank: yup
2391
+ .string()
2392
+ .nullable()
2393
+ .oneOf(['yes', 'no'])
2394
+ .required(),
2395
+
2396
+ dpe_grade: dpeGradeSchemaSimple(),
2397
+ dpe_date: dpeDateSchemaSimple(),
2398
+ primary_energy_consumption: dpeNumericSchemaSimple(),
2399
+ estimated_annual_energy_cost: dpeNumericSchemaSimple(),
2400
+ ges_grade: gesGradeSchemaSimple(),
2401
+ ges_date: gesDateSchemaSimple(),
2402
+ greenhouse_gas_emissions: gesNumericSchemaSimple(),
2403
+
2404
+ available_at: yup.string().nullable(),
2405
+ construction_year: yup.string().nullable(),
2406
+ is_extension_possible: yup.string().nullable(),
2407
+ sanitation: yup.string().nullable(),
2408
+ });
2409
+
2410
+ export const agentLandPropertySchema = () => {
2411
+ return yup.object().shape({
2412
+ land_type: yup
2413
+ .string()
2414
+ .nullable()
2415
+ .required(
2416
+ Translator.translate('sellerLandProperty.landTypeRequired'),
2417
+ ),
2418
+ land_area: yup
2419
+ .string()
2420
+ .nullable()
2421
+ .required(
2422
+ Translator.translate('sellerLandProperty.landSurfaceRequired'),
2423
+ )
2424
+ .test('is-valid-number', '', v => !v || !isNaN(Number(v))),
2425
+ is_builder_free: yup
2426
+ .mixed()
2427
+ .nullable()
2428
+ .required(
2429
+ Translator.translate('sellerLandProperty.freeBuilderRequired'),
2430
+ ),
2431
+ is_serviced: yup
2432
+ .mixed()
2433
+ .nullable()
2434
+ .required(
2435
+ Translator.translate('sellerLandProperty.servicedRequired'),
2436
+ ),
2437
+ plu_zone: yup.string().nullable(),
2438
+ is_demarcated: yup
2439
+ .mixed()
2440
+ .nullable()
2441
+ .required(
2442
+ Translator.translate(
2443
+ 'sellerLandProperty.boundaryDemarcationRequired',
2444
+ ),
2445
+ ),
2446
+ annual_tax: yup.string().nullable().test('is-valid-number', '', v => !v || !isNaN(Number(v))),
2447
+ available_at: yup.string().nullable(),
2448
+ });
2449
+ };
2450
+
2451
+ export const agentBuildingPropertySchema = () =>
2452
+ yup.object().shape({
2453
+ units_count: yup.number().required(),
2454
+ total_surface: yup.string().required(),
2455
+
2456
+ is_copropriety: yup.string().nullable(),
2457
+ co_owned_lots_count: yup.string().when('is_copropriety', {
2458
+ is: 'yes',
2459
+ then: schema => schema.required(),
2460
+ otherwise: schema => schema.nullable(),
2461
+ }),
2462
+ annual_service_charges: yup.string().when('is_copropriety', {
2463
+ is: 'yes',
2464
+ then: schema => schema.required(),
2465
+ otherwise: schema => schema.nullable(),
2466
+ }),
2467
+ no_ongoing_proceedings: yup.string().when('is_copropriety', {
2468
+ is: 'yes',
2469
+ then: schema => schema.required(),
2470
+ otherwise: schema => schema.nullable(),
2471
+ }),
2472
+
2473
+ has_garage: yup.string().nullable(),
2474
+ has_parking: yup.string().nullable(),
2475
+ orientation: yup.string().nullable(),
2476
+ heating_system: yup.string().nullable(),
2477
+ property_condition: yup.string().required(),
2478
+
2479
+ occupancy_status: yup.string().required(),
2480
+ monthly_rent: yup.string().when('occupancy_status', {
2481
+ is: 'rented',
2482
+ then: schema => schema.required(),
2483
+ otherwise: schema => schema.nullable(),
2484
+ }),
2485
+ annual_tax: yup.string().when('occupancy_status', {
2486
+ is: 'rented',
2487
+ then: schema => schema.required(),
2488
+ otherwise: schema => schema.nullable(),
2489
+ }),
2490
+
2491
+ subject_dpe: yup
2492
+ .string()
2493
+ .nullable()
2494
+ .oneOf(['yes', 'no'])
2495
+ .required(),
2496
+ is_dpe_blank: yup
2497
+ .string()
2498
+ .nullable()
2499
+ .oneOf(['yes', 'no'])
2500
+ .required(),
2501
+ dpe_grade: dpeGradeSchemaSimple(),
2502
+ dpe_date: dpeDateSchemaSimple(),
2503
+ primary_energy_consumption: dpeNumericSchemaSimple(),
2504
+ estimated_annual_energy_cost: dpeNumericSchemaSimple(),
2505
+ ges_grade: gesGradeSchemaSimple(),
2506
+ ges_date: gesDateSchemaSimple(),
2507
+ greenhouse_gas_emissions: gesNumericSchemaSimple(),
2508
+
2509
+ is_extension_possible: yup.string().nullable(),
2510
+ available_at: yup.string().nullable(),
2511
+ sanitation: yup.string().nullable(),
2512
+ });
2513
+
2514
+ export const agentCommercialPropertySchema = () =>
2515
+ yup.object().shape({
2516
+ total_surface: yup.string().required(),
2517
+ shop_front_length: yup.string().required(),
2518
+ is_prime_location: yup.string().nullable(),
2519
+ parking_surface: yup.string().nullable(),
2520
+ property_condition: yup.string().required(),
2521
+
2522
+ occupancy_status: yup.string().required(),
2523
+ monthly_rent: yup.string().when('occupancy_status', {
2524
+ is: 'rented',
2525
+ then: schema => schema.required(),
2526
+ otherwise: schema => schema.nullable(),
2527
+ }),
2528
+ annual_tax: yup.string().when('occupancy_status', {
2529
+ is: 'rented',
2530
+ then: schema => schema.required(),
2531
+ otherwise: schema => schema.nullable(),
2532
+ }),
2533
+
2534
+ is_disabled_accessible: yup.string().nullable(),
2535
+ is_copropriety: yup.string().nullable(),
2536
+ co_owned_lots_count: yup.string().when('is_copropriety', {
2537
+ is: 'yes',
2538
+ then: schema => schema.required(),
2539
+ otherwise: schema => schema.nullable(),
2540
+ }),
2541
+ annual_service_charges: yup.string().when('is_copropriety', {
2542
+ is: 'yes',
2543
+ then: schema => schema.required(),
2544
+ otherwise: schema => schema.nullable(),
2545
+ }),
2546
+ no_ongoing_proceedings: yup.string().when('is_copropriety', {
2547
+ is: 'yes',
2548
+ then: schema => schema.required(),
2549
+ otherwise: schema => schema.nullable(),
2550
+ }),
2551
+
2552
+ construction_year: yup.string().nullable(),
2553
+ });
2554
+
2555
+ export const agentParkingPropertySchema = () =>
2556
+ yup.object().shape({
2557
+ parking_type: yup.string().required(),
2558
+ intended_use: yup.string().nullable(),
2559
+ parking_surface: yup.string().required(),
2560
+ occupancy_status: yup.string().required(),
2561
+ monthly_rent: yup.string().when('occupancy_status', {
2562
+ is: 'rented',
2563
+ then: schema => schema.required(),
2564
+ otherwise: schema => schema.nullable(),
2565
+ }),
2566
+ annual_tax: yup.string().when('occupancy_status', {
2567
+ is: 'rented',
2568
+ then: schema => schema.required(),
2569
+ otherwise: schema => schema.nullable(),
2570
+ }),
2571
+ available_at: yup.string().nullable(),
2572
+ construction_year: yup.string().nullable(),
2573
+ });
2574
+
2575
+ export const agentGitePropertySchema = () =>
2576
+ yup.object().shape({
2577
+ gite_type: yup.string().required(),
2578
+ gites_count: yup.number().required(),
2579
+ living_area: yup
2580
+ .string()
2581
+ .required()
2582
+ .test(
2583
+ 'living-area-lt-land-area',
2584
+ Translator.translate('agentGiteProperty.livingAreaGreaterThanLandArea'),
2585
+ function (value) {
2586
+ const { land_area } = this.parent;
2587
+ if (!value || !land_area) return true;
2588
+ if (isNaN(Number(value)) || isNaN(Number(land_area))) {
2589
+ return true;
2590
+ }
2591
+ return Number(value) < Number(land_area);
2592
+ },
2593
+ ),
2594
+ land_area: yup
2595
+ .string()
2596
+ .nullable()
2597
+ .test(
2598
+ 'land-area-gt-living-area',
2599
+ Translator.translate('agentGiteProperty.landAreaLessThanLivingArea'),
2600
+ function (value) {
2601
+ const { living_area } = this.parent;
2602
+ if (!value || !living_area) return true;
2603
+ if (isNaN(Number(value)) || isNaN(Number(living_area))) {
2604
+ return true;
2605
+ }
2606
+ return Number(value) > Number(living_area);
2607
+ },
2608
+ ),
2609
+ rooms_count: yup.number().nullable(),
2610
+ shower_rooms: yup.number().nullable(),
2611
+ bathrooms: yup.number().nullable(),
2612
+ ground_floor: yup.string().nullable(),
2613
+ has_garage: yup.string().nullable(),
2614
+ pool: yup.string().nullable(),
2615
+ heating_system: yup.string().nullable(),
2616
+ property_condition: yup.string().required(),
2617
+ annual_revenue: yup.string().required(),
2618
+ has_private_housing: yup.string().nullable(),
2619
+ occupancy_status: yup.string().required(),
2620
+ monthly_rent: yup.string().when('occupancy_status', {
2621
+ is: 'rented',
2622
+ then: schema => schema.required(),
2623
+ otherwise: schema => schema.nullable(),
2624
+ }),
2625
+ annual_tax: yup.string().when('occupancy_status', {
2626
+ is: 'rented',
2627
+ then: schema => schema.required(),
2628
+ otherwise: schema => schema.nullable(),
2629
+ }),
2630
+ subject_dpe: yup
2631
+ .string()
2632
+ .nullable()
2633
+ .oneOf(['yes', 'no'])
2634
+ .required(),
2635
+ is_dpe_blank: yup
2636
+ .string()
2637
+ .nullable()
2638
+ .oneOf(['yes', 'no'])
2639
+ .required(),
2640
+ dpe_grade: dpeGradeSchemaSimple(),
2641
+ dpe_date: dpeDateSchemaSimple(),
2642
+ primary_energy_consumption: dpeNumericSchemaSimple(),
2643
+ estimated_annual_energy_cost: dpeNumericSchemaSimple(),
2644
+ ges_grade: gesGradeSchemaSimple(),
2645
+ ges_date: gesDateSchemaSimple(),
2646
+ greenhouse_gas_emissions: gesNumericSchemaSimple(),
2647
+ available_at: yup.string().nullable(),
2648
+ construction_year: yup.string().nullable(),
2649
+ is_extension_possible: yup.string().nullable(),
2650
+ sanitation: yup.string().nullable(),
2651
+ });
2652
+
2653
+ export const agentOfficePropertySchema = () =>
2654
+ yup.object().shape({
2655
+ total_surface: yup.string().required(),
2656
+ separated_offices_count: yup.number().required(),
2657
+ is_open_space: yup.string().nullable(),
2658
+ floor_level: yup.string().nullable(),
2659
+ has_elevator: yup.string().nullable(),
2660
+ has_sanitary_facilities: yup.string().nullable(),
2661
+ has_parking: yup.string().nullable(),
2662
+ has_garage: yup.string().nullable(),
2663
+ property_condition: yup.string().required(),
2664
+ disabled_accessibility_preference: yup.string().nullable(),
2665
+ heating_system: yup.string().nullable(),
2666
+ occupancy_status: yup.string().required(),
2667
+ monthly_rent: yup.string().when('occupancy_status', {
2668
+ is: 'rented',
2669
+ then: schema => schema.required(),
2670
+ otherwise: schema => schema.nullable(),
2671
+ }),
2672
+ annual_tax: yup.string().when('occupancy_status', {
2673
+ is: 'rented',
2674
+ then: schema => schema.required(),
2675
+ otherwise: schema => schema.nullable(),
2676
+ }),
2677
+ subject_dpe: yup
2678
+ .string()
2679
+ .nullable()
2680
+ .oneOf(['yes', 'no'])
2681
+ .required(),
2682
+ is_dpe_blank: yup
2683
+ .string()
2684
+ .nullable()
2685
+ .oneOf(['yes', 'no'])
2686
+ .required(),
2687
+ dpe_grade: dpeGradeSchemaSimple(),
2688
+ dpe_date: dpeDateSchemaSimple(),
2689
+ primary_energy_consumption: dpeNumericSchemaSimple(),
2690
+ estimated_annual_energy_cost: dpeNumericSchemaSimple(),
2691
+ ges_grade: gesGradeSchemaSimple(),
2692
+ ges_date: gesDateSchemaSimple(),
2693
+ greenhouse_gas_emissions: gesNumericSchemaSimple(),
2694
+ is_copropriety: yup.string().nullable(),
2695
+ co_owned_lots_count: yup.string().when('is_copropriety', {
2696
+ is: 'yes',
2697
+ then: schema => schema.required(),
2698
+ otherwise: schema => schema.nullable(),
2699
+ }),
2700
+ annual_service_charges: yup.string().when('is_copropriety', {
2701
+ is: 'yes',
2702
+ then: schema => schema.required(),
2703
+ otherwise: schema => schema.nullable(),
2704
+ }),
2705
+ no_ongoing_proceedings: yup.string().when('is_copropriety', {
2706
+ is: 'yes',
2707
+ then: schema => schema.required(),
2708
+ otherwise: schema => schema.nullable(),
2709
+ }),
2710
+ construction_year: yup.string().nullable(),
2711
+ available_at: yup.string().nullable(),
2712
+ sanitation: yup.string().nullable(),
2713
+ });