facility_detail_page.dart 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. import 'package:cs_resources/generated/assets.dart';
  2. import 'package:cs_resources/generated/l10n.dart';
  3. import 'package:cs_resources/theme/app_colors_theme.dart';
  4. import 'package:flutter/material.dart';
  5. import 'package:auto_route/auto_route.dart';
  6. import 'package:flutter_hooks/flutter_hooks.dart';
  7. import 'package:hooks_riverpod/hooks_riverpod.dart';
  8. import 'package:router/ext/auto_router_extensions.dart';
  9. import 'package:widgets/ext/ex_widget.dart';
  10. import 'package:widgets/my_appbar.dart';
  11. import 'package:widgets/my_button.dart';
  12. import 'package:widgets/my_load_image.dart';
  13. import 'package:widgets/my_text_view.dart';
  14. import 'package:widgets/utils/dark_theme_util.dart';
  15. import '../../router/page/facility_page_router.dart';
  16. import 'facility_detail_view_model.dart';
  17. @RoutePage()
  18. class FacilityDetailPage extends HookConsumerWidget {
  19. final String? bookingId;
  20. const FacilityDetailPage({Key? key, required this.bookingId}) : super(key: key);
  21. //启动当前页面
  22. static void startInstance({BuildContext? context, required String? bookingId}) {
  23. if (context != null) {
  24. context.router.push(FacilityDetailPageRoute(bookingId: bookingId));
  25. } else {
  26. appRouter.push(FacilityDetailPageRoute(bookingId: bookingId));
  27. }
  28. }
  29. //启动当前页面并回退至设施首页
  30. static void startWithPop2Main({required String? bookingId}) {
  31. appRouter.pushAndPopUntil(
  32. FacilityDetailPageRoute(bookingId: bookingId),
  33. predicate: (route) {
  34. return route.settings.name == 'FacilityPageRoute';
  35. },
  36. );
  37. }
  38. @override
  39. Widget build(BuildContext context, WidgetRef ref) {
  40. final viewModel = ref.watch(facilityDetailViewModelProvider.notifier);
  41. final state = ref.watch(facilityDetailViewModelProvider);
  42. useEffect(() {
  43. // 组件挂载时执行 - 执行接口请求
  44. Future.microtask(() => viewModel.fetchFacilityDetail(bookingId));
  45. return () {
  46. // 组件卸载时执行
  47. };
  48. }, []);
  49. return Scaffold(
  50. appBar: MyAppBar.appBar(context, state.detail?.facility?.type?.name ?? "", backgroundColor: context.appColors.backgroundWhite),
  51. backgroundColor: context.appColors.backgroundDark,
  52. body: Column(children: [
  53. SingleChildScrollView(
  54. scrollDirection: Axis.vertical,
  55. physics: const BouncingScrollPhysics(),
  56. child: Column(
  57. mainAxisSize: MainAxisSize.max,
  58. crossAxisAlignment: CrossAxisAlignment.center,
  59. children: [
  60. //顶部的信息展示
  61. state.detail?.order?.paymentStatus == 1 ? _buildHeaderWidget(context, ref) : const SizedBox.shrink(),
  62. //预定
  63. _buildDetailItem(
  64. context,
  65. ref,
  66. S.current.book,
  67. Assets.facilityConfirmDateIcon,
  68. 28.5,
  69. 29,
  70. state.detail?.booking?.date ?? "",
  71. null,
  72. "${state.detail?.booking?.start ?? ""}-${state.detail?.booking?.end ?? ""}",
  73. null,
  74. ),
  75. //设施
  76. _buildDetailItem(
  77. context,
  78. ref,
  79. S.current.facility,
  80. Assets.facilityConfirmFacilityIcon,
  81. 25.0,
  82. 30.5,
  83. state.detail?.facility?.type?.name ?? "",
  84. null,
  85. state.detail?.facility?.name ?? "",
  86. null,
  87. ),
  88. //付款
  89. _buildDetailItem(
  90. context,
  91. ref,
  92. S.current.payment,
  93. Assets.facilityConfirmPaymentIcon,
  94. 27.0,
  95. 22.0,
  96. S.current.booking_fee,
  97. state.detail?.timePeriod?.price ?? "",
  98. S.current.total,
  99. "\$${state.detail?.timePeriod?.price ?? ""}",
  100. ),
  101. // 押金
  102. _buildDetailItem(
  103. context,
  104. ref,
  105. S.current.deposit,
  106. Assets.facilityConfirmDepositIcon,
  107. 28.0,
  108. 26.5,
  109. S.current.on_hold,
  110. "\$${state.detail?.timePeriod?.deposit ?? ""}",
  111. null,
  112. null,
  113. ),
  114. ],
  115. ),
  116. ).expanded(),
  117. // 底部按钮
  118. Visibility(
  119. visible: state.detail?.order?.paymentStatus != 1,
  120. child: MyButton(
  121. onPressed: () {
  122. viewModel.doPaymentOrder(state.detail?.order?.id ?? "");
  123. },
  124. text: S.current.proceed_with_payment,
  125. textColor: Colors.white,
  126. backgroundColor: context.appColors.btnBgDefault,
  127. fontWeight: FontWeight.w500,
  128. type: ClickType.throttle,
  129. fontSize: 16,
  130. minHeight: 50,
  131. radius: 0,
  132. ).marginOnly(top: 15),
  133. ),
  134. ]),
  135. );
  136. }
  137. Widget _buildHeaderWidget(BuildContext context, WidgetRef ref) {
  138. final state = ref.watch(facilityDetailViewModelProvider);
  139. return Container(
  140. width: double.infinity,
  141. color: context.appColors.whiteBG,
  142. margin: const EdgeInsets.only(bottom: 7.5),
  143. child: Column(
  144. children: [
  145. //成功图片
  146. MyAssetImage(
  147. Assets.facilityPaymentSuccessIcon,
  148. width: 54,
  149. height: 54,
  150. color: DarkThemeUtil.multiColors(context, AppColorsTheme.colorPrimary, darkColor: Colors.white),
  151. ).marginOnly(top: 11, bottom: 13),
  152. //支付成功
  153. MyTextView(
  154. S.current.booking_successful,
  155. fontSize: 18,
  156. marginBottom: 3,
  157. isFontMedium: true,
  158. textColor: context.appColors.textPrimary,
  159. ),
  160. MyTextView(
  161. S.current.have_fun,
  162. fontSize: 18,
  163. marginBottom: 19,
  164. isFontMedium: true,
  165. textColor: context.appColors.textPrimary,
  166. ),
  167. //支付金额
  168. MyTextView(
  169. S.current.fee_paid,
  170. fontSize: 15,
  171. isFontRegular: true,
  172. textColor: context.appColors.textBlack,
  173. ),
  174. MyTextView(
  175. "\$${state.detail?.timePeriod?.price ?? ""}",
  176. fontSize: 15,
  177. isFontRegular: true,
  178. textColor: context.appColors.textPrimary,
  179. ),
  180. //付款类型与时间
  181. // Row(
  182. // mainAxisSize: MainAxisSize.min,
  183. // children: [
  184. // MyTextView(
  185. // "Master card ending",
  186. // fontSize: 15,
  187. // isFontRegular: true,
  188. // textColor: context.appColors.textBlack,
  189. // ),
  190. // MyTextView(
  191. // "9423",
  192. // fontSize: 15,
  193. // isFontMedium: true,
  194. // textColor: context.appColors.textBlack,
  195. // ),
  196. // ],
  197. // ).marginOnly(top: 12),
  198. Row(
  199. mainAxisSize: MainAxisSize.min,
  200. children: [
  201. MyTextView(
  202. S.current.paid_on,
  203. fontSize: 15,
  204. isFontRegular: true,
  205. textColor: context.appColors.textBlack,
  206. ),
  207. MyTextView(
  208. " ${state.detail?.booking?.date ?? ""}",
  209. fontSize: 15,
  210. isFontMedium: true,
  211. textColor: context.appColors.textBlack,
  212. ),
  213. ],
  214. ).marginOnly(top: 5),
  215. //退还押金的布局展示
  216. Visibility(
  217. visible: state.detail?.booking?.depositRefund != "0.00",
  218. child: Column(
  219. children: [
  220. Divider(height: 0.5, color: context.appColors.dividerDefault).marginOnly(top: 14, bottom: 14),
  221. //退还的押金
  222. MyTextView(
  223. S.current.deposit_released_caps,
  224. fontSize: 15,
  225. isFontRegular: true,
  226. textColor: context.appColors.textBlack,
  227. ),
  228. MyTextView(
  229. "\$${state.detail?.booking?.depositRefund ?? ""}",
  230. fontSize: 15,
  231. marginTop: 5,
  232. isFontRegular: true,
  233. textColor: context.appColors.textPrimary,
  234. ),
  235. Divider(height: 0.5, color: context.appColors.dividerDefault).marginOnly(top: 14, bottom: 14),
  236. //押金付款于时间
  237. Row(
  238. mainAxisSize: MainAxisSize.min,
  239. children: [
  240. MyTextView(
  241. S.current.hold_started_on,
  242. fontSize: 15,
  243. isFontRegular: true,
  244. textColor: context.appColors.textBlack,
  245. ),
  246. MyTextView(
  247. " ${state.detail?.booking?.date ?? ""}",
  248. fontSize: 15,
  249. isFontMedium: true,
  250. textColor: context.appColors.textBlack,
  251. ),
  252. ],
  253. ).marginOnly(top: 5),
  254. //押金退款于时间
  255. Row(
  256. mainAxisSize: MainAxisSize.min,
  257. children: [
  258. MyTextView(
  259. S.current.released_on,
  260. fontSize: 15,
  261. isFontRegular: true,
  262. textColor: context.appColors.textBlack,
  263. ),
  264. MyTextView(
  265. " ${state.detail?.booking?.depositRefundAt ?? ""}",
  266. fontSize: 15,
  267. isFontMedium: true,
  268. textColor: context.appColors.textBlack,
  269. ),
  270. ],
  271. ).marginOnly(top: 5),
  272. ],
  273. ),
  274. ),
  275. const SizedBox(height: 23),
  276. ],
  277. ),
  278. );
  279. }
  280. //Item的列表
  281. Widget _buildDetailItem(
  282. BuildContext context,
  283. WidgetRef ref,
  284. String title,
  285. String iconPath,
  286. double iconWidth,
  287. double iconHeight,
  288. String line1Txt,
  289. String? line1Content,
  290. String? line2Txt,
  291. String? line2Content,
  292. ) {
  293. return Container(
  294. width: double.infinity,
  295. height: 92.5,
  296. padding: const EdgeInsets.only(left: 20, right: 20),
  297. margin: const EdgeInsets.only(left: 15, right: 15, top: 7.5, bottom: 7.5),
  298. decoration: BoxDecoration(
  299. color: context.appColors.whiteBG,
  300. borderRadius: BorderRadius.circular(6.0), // 圆角
  301. boxShadow: [
  302. BoxShadow(
  303. color: context.appColors.itemBGShadow, // 阴影颜色
  304. offset: const Offset(0, 3), // 阴影的偏移量
  305. blurRadius: 8.0, // 模糊半径
  306. spreadRadius: 3.0, // 扩散半径
  307. ),
  308. ],
  309. ),
  310. child: Center(
  311. child: Column(
  312. crossAxisAlignment: CrossAxisAlignment.start,
  313. mainAxisSize: MainAxisSize.min,
  314. children: [
  315. MyTextView(
  316. title,
  317. textColor: context.appColors.textBlack,
  318. fontSize: 16,
  319. marginBottom: 7,
  320. isFontMedium: true,
  321. ),
  322. Row(
  323. mainAxisSize: MainAxisSize.max,
  324. children: [
  325. MyAssetImage(
  326. iconPath,
  327. width: iconWidth,
  328. height: iconHeight,
  329. color: DarkThemeUtil.multiColors(context, AppColorsTheme.colorPrimary, darkColor: Colors.white),
  330. ).marginOnly(right: 15),
  331. Column(
  332. mainAxisSize: MainAxisSize.min,
  333. children: [
  334. Row(
  335. children: [
  336. MyTextView(
  337. line1Txt,
  338. textColor: context.appColors.textBlack,
  339. fontSize: 14,
  340. isFontRegular: true,
  341. ).expanded(),
  342. MyTextView(
  343. line1Content ?? "",
  344. textColor: context.appColors.textBlack,
  345. fontSize: 14,
  346. isFontRegular: true,
  347. ),
  348. ],
  349. ),
  350. Visibility(
  351. visible: line2Txt != null,
  352. child: Row(
  353. children: [
  354. MyTextView(
  355. line2Txt ?? "",
  356. textColor: context.appColors.textBlack,
  357. fontSize: 14,
  358. isFontRegular: true,
  359. ).expanded(),
  360. MyTextView(
  361. line2Content ?? "",
  362. textColor: context.appColors.textBlack,
  363. fontSize: 14,
  364. isFontRegular: true,
  365. ),
  366. ],
  367. ).marginOnly(top: 6),
  368. ),
  369. ],
  370. ).expanded(),
  371. ],
  372. ),
  373. ],
  374. ),
  375. ),
  376. );
  377. }
  378. }