rewards_home_page.dart 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512
  1. import 'package:cpt_rewards/modules/rewards_address/rewards_address_page.dart';
  2. import 'package:cpt_rewards/modules/rewards_code/rewards_code_page.dart';
  3. import 'package:cpt_rewards/modules/rewards_detail/rewards_detail_page.dart';
  4. import 'package:cpt_rewards/modules/rewards_list/rewards_list_page.dart';
  5. import 'package:cpt_rewards/modules/rewards_my/rewards_my_page.dart';
  6. import 'package:cpt_rewards/modules/rewards_search/rewards_search_page.dart';
  7. import 'package:cs_resources/generated/assets.dart';
  8. import 'package:cs_resources/generated/l10n.dart';
  9. import 'package:cs_resources/theme/app_colors_theme.dart';
  10. import 'package:cs_resources/theme/theme_config.dart';
  11. import 'package:domain/entity/rewards_category_entity.dart';
  12. import 'package:domain/entity/rewards_home_entity.dart';
  13. import 'package:flutter/material.dart';
  14. import 'package:auto_route/auto_route.dart';
  15. import 'package:flutter/services.dart';
  16. import 'package:flutter_hooks/flutter_hooks.dart';
  17. import 'package:hooks_riverpod/hooks_riverpod.dart';
  18. import 'package:plugin_platform/engine/image/image_nine_grid.dart';
  19. import 'package:router/ext/auto_router_extensions.dart';
  20. import 'package:shared/utils/color_utils.dart';
  21. import 'package:shared/utils/log_utils.dart';
  22. import 'package:widgets/ext/ex_widget.dart';
  23. import 'package:widgets/load_state_layout.dart';
  24. import 'package:widgets/my_appbar.dart';
  25. import 'package:widgets/my_load_image.dart';
  26. import 'package:widgets/utils/dark_theme_util.dart';
  27. import '../../../router/page/rewards_page_router.dart';
  28. import './rewards_home_vm.dart';
  29. @RoutePage()
  30. class RewardsHomePage extends HookConsumerWidget {
  31. final int? points;
  32. const RewardsHomePage({Key? key, @PathParam('points') required this.points}) : super(key: key);
  33. //启动当前页面
  34. static void startInstance({
  35. BuildContext? context,
  36. int? points,
  37. }) {
  38. if (context != null) {
  39. context.router.push(RewardsHomePageRoute(points: points));
  40. } else {
  41. appRouter.push(RewardsHomePageRoute(points: points));
  42. }
  43. }
  44. Widget _buildTop(BuildContext context, WidgetRef ref, _vm) {
  45. int? point = points ?? 0;
  46. // String available = '$point'
  47. return Container(
  48. decoration: BoxDecoration(
  49. border: Border(
  50. bottom: BorderSide(
  51. color: context.appColors.btnBgDefault, // 设置bottom边框的颜色
  52. width: 45.0, // 设置bottom边框的宽度
  53. )),
  54. borderRadius: const BorderRadius.only(
  55. topLeft: Radius.circular(0.0),
  56. topRight: Radius.circular(0.0),
  57. bottomLeft: Radius.circular(30.0),
  58. bottomRight: Radius.circular(30.0),
  59. ), // 圆角
  60. ),
  61. child: Column(
  62. crossAxisAlignment: CrossAxisAlignment.start,
  63. children: [
  64. Row(
  65. crossAxisAlignment: CrossAxisAlignment.center,
  66. mainAxisAlignment: MainAxisAlignment.center,
  67. children: [
  68. Text(
  69. '$point ${S.current.available_points}',
  70. style: const TextStyle(fontSize: 18.0, color: Colors.white, fontWeight: FontWeight.w500), // 设置字体大小
  71. ).paddingOnly(left: 10, top: 0, bottom: 13),
  72. ],
  73. ),
  74. Row(
  75. crossAxisAlignment: CrossAxisAlignment.center,
  76. mainAxisAlignment: MainAxisAlignment.center,
  77. children: [
  78. Container(
  79. decoration: BoxDecoration(
  80. border: Border.all(color: Colors.white, width: 1), // 边框
  81. borderRadius: BorderRadius.circular(8), // 圆角
  82. ),
  83. child: Text(
  84. S.current.my_rewards,
  85. style: const TextStyle(fontSize: 15.0, color: Colors.white, fontWeight: FontWeight.w400), // 设置字体大小
  86. ).paddingOnly(left: 10, top: 7, bottom: 7, right: 10).onTap(() {
  87. RewardsMyPage.startInstance();
  88. }),
  89. ),
  90. // Row(
  91. // crossAxisAlignment: CrossAxisAlignment.center,
  92. // mainAxisAlignment: MainAxisAlignment.center,
  93. // children: [
  94. // const MyAssetImage(
  95. // Assets.rewardsRewardsY,
  96. // width: 26,
  97. // height: 26,
  98. // ),
  99. // Text(
  100. // 'Bronze',
  101. // style: TextStyle(
  102. // fontSize: 17.0,
  103. // color: ColorUtils.string2Color('#FFCC00'),
  104. // fontWeight: FontWeight.w500), // 设置字体大小
  105. // ).marginOnly(
  106. // left: 9,
  107. // right: 7,
  108. // ),
  109. // const MyAssetImage(
  110. // Assets.rewardsRewardsRight,
  111. // width: 7,
  112. // height: 12,
  113. // ),
  114. // ],
  115. // )
  116. ],
  117. ).paddingOnly(left: 10)
  118. ],
  119. )
  120. .paddingOnly(top: 8, left: 5, right: 15, bottom: 8)
  121. .border(bottom: 0, color: context.appColors.btnBgDefault)
  122. .backgroundColor(context.appColors.btnBgDefault),
  123. );
  124. }
  125. Widget _buildSearch(BuildContext context, WidgetRef ref, _vm) {
  126. // List itemsList = _vm.state.list.toList();
  127. return Container(
  128. width: MediaQuery.of(context).size.width - 30,
  129. height: 50,
  130. decoration: BoxDecoration(
  131. color: context.appColors.whiteSecondBG,
  132. borderRadius: BorderRadius.circular(10),
  133. ),
  134. child: Row(
  135. crossAxisAlignment: CrossAxisAlignment.center,
  136. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  137. children: [
  138. Text(
  139. S.current.search,
  140. style: TextStyle(fontSize: 15.0, color: ColorUtils.string2Color('#C7CDE3'), fontWeight: FontWeight.w500), // 设置字体大小
  141. ),
  142. const MyAssetImage(
  143. Assets.rewardsRewardsIndexSearch,
  144. width: 21,
  145. height: 21,
  146. ),
  147. ],
  148. ).paddingOnly(left: 15, right: 15),
  149. ).onTap(() {
  150. RewardsSearchPage.startInstance();
  151. });
  152. }
  153. Widget _buildSwiper(BuildContext context, WidgetRef ref, _vm) {
  154. // List itemsList = _vm.state.lists.toList();
  155. final state = ref.watch(rewardsHomeVmProvider);
  156. List<Map<String, dynamic>>? itemsList = state.categoryList;
  157. return Container(
  158. transform: Matrix4.translationValues(0.0, -10.0, 0.0),
  159. // color: Colors.white,
  160. height: 110,
  161. decoration: BoxDecoration(
  162. color: context.appColors.whiteBG,
  163. borderRadius: const BorderRadius.only(
  164. topLeft: Radius.circular(10.0),
  165. topRight: Radius.circular(0.0),
  166. bottomLeft: Radius.circular(10.0),
  167. bottomRight: Radius.circular(0.0),
  168. ),
  169. boxShadow: [BoxShadow(color: context.appColors.itemBGShadow)],
  170. ),
  171. child: ClipRect(
  172. child: SingleChildScrollView(
  173. scrollDirection: Axis.horizontal,
  174. physics: const BouncingScrollPhysics(),
  175. clipBehavior: Clip.none,
  176. child: Row(
  177. crossAxisAlignment: CrossAxisAlignment.center,
  178. mainAxisAlignment: MainAxisAlignment.center,
  179. children: List.generate(itemsList!.length, (index) {
  180. final item = itemsList[index];
  181. return Column(
  182. crossAxisAlignment: CrossAxisAlignment.center,
  183. mainAxisAlignment: MainAxisAlignment.center,
  184. children: [
  185. MyLoadImage(
  186. item['icon'] ?? '',
  187. width: 70,
  188. height: 70,
  189. ),
  190. Text(
  191. item['name']!,
  192. style: TextStyle(fontSize: 14.0, color: context.appColors.textBlack, fontWeight: FontWeight.w600), // 设置字体大小
  193. ),
  194. ],
  195. ).marginOnly(right: 5).onTap(() {
  196. RewardsListPage.startInstance();
  197. });
  198. }),
  199. ).marginOnly(left: 15, right: 15),
  200. )),
  201. ).paddingOnly(left: 15);
  202. }
  203. Widget _buildRecommend(BuildContext context, WidgetRef ref, _vm, list) {
  204. return list['rewards'].length > 0
  205. ? Container(
  206. child: Column(
  207. children: [
  208. Row(
  209. crossAxisAlignment: CrossAxisAlignment.center,
  210. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  211. children: [
  212. Text(
  213. list?['name'] ?? '',
  214. style: TextStyle(fontSize: 17.0, color: context.appColors.textBlack, fontWeight: FontWeight.w500), // 设置字体大小
  215. ),
  216. Text(
  217. S.current.see_all,
  218. style: TextStyle(fontSize: 17.0, color: context.appColors.textPrimary, fontWeight: FontWeight.w500), // 设置字体大小
  219. ).onTap(() {
  220. RewardsListPage.startInstance();
  221. }),
  222. ],
  223. ).marginOnly(bottom: 15),
  224. Row(
  225. crossAxisAlignment: CrossAxisAlignment.center,
  226. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  227. children: List.generate(list['rewards'].length, (index) {
  228. double hg = 70;
  229. return Container(
  230. width: MediaQuery.of(context).size.width / 2 - 25,
  231. height: 155,
  232. decoration: BoxDecoration(
  233. color: context.appColors.whiteBG,
  234. borderRadius: const BorderRadius.all(Radius.circular(6.0)),
  235. boxShadow: [BoxShadow(color: context.appColors.itemBGShadow)],
  236. ),
  237. child: ClipRRect(
  238. borderRadius: const BorderRadius.all(Radius.circular(6.0)),
  239. child: _buildItem(context, ref, _vm, hg, list['rewards'][index])));
  240. }))
  241. ],
  242. ),
  243. ).paddingOnly(left: 15, right: 15, top: 10)
  244. : Container();
  245. }
  246. Widget _buildHottest(BuildContext context, WidgetRef ref, _vm) {
  247. return Container(
  248. child: Column(
  249. children: [
  250. Row(
  251. crossAxisAlignment: CrossAxisAlignment.center,
  252. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  253. children: [
  254. Text(
  255. S.current.hottest,
  256. style: TextStyle(fontSize: 17.0, color: context.appColors.textBlack, fontWeight: FontWeight.w500), // 设置字体大小
  257. ),
  258. Text(
  259. S.current.see_all,
  260. style: TextStyle(fontSize: 17.0, color: context.appColors.textPrimary, fontWeight: FontWeight.w500), // 设置字体大小
  261. ).onTap(() {
  262. RewardsListPage.startInstance();
  263. }),
  264. ],
  265. ).marginOnly(bottom: 15),
  266. Row(
  267. crossAxisAlignment: CrossAxisAlignment.center,
  268. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  269. children: List.generate(2, (index) {
  270. double hg = 70;
  271. return Container(
  272. width: MediaQuery.of(context).size.width / 2 - 25,
  273. height: 185,
  274. decoration: BoxDecoration(
  275. color: context.appColors.whiteBG,
  276. borderRadius: const BorderRadius.all(Radius.circular(6.0)),
  277. boxShadow: [BoxShadow(color: context.appColors.itemBGShadow)],
  278. ),
  279. child: _buildItem(context, ref, _vm, hg, {}));
  280. }))
  281. ],
  282. ),
  283. ).paddingOnly(left: 15, right: 15, top: 10);
  284. }
  285. Widget _buildItem(BuildContext context, WidgetRef ref, _vm, height, item) {
  286. double hg = height;
  287. num point = item['point'] ?? 0;
  288. num originalPoint = item['original_point'] ?? 0;
  289. int id = item['id'];
  290. return Column(
  291. children: [
  292. MyLoadImage(
  293. item?['resources']?[0] ?? '',
  294. width: MediaQuery.of(context).size.width,
  295. height: hg,
  296. // cornerRadius:6,
  297. ),
  298. Column(
  299. crossAxisAlignment: CrossAxisAlignment.start,
  300. children: [
  301. Text(
  302. maxLines: 1, // 设置最大行数为2
  303. overflow: TextOverflow.ellipsis, // 超出部分用省略号表示
  304. item?['name'] ?? '',
  305. style: TextStyle(fontSize: 15.0, color: context.appColors.textBlack, fontWeight: FontWeight.w500),
  306. ).marginOnly(bottom: 5),
  307. Row(
  308. children: [
  309. Text(
  310. '$point',
  311. style: TextStyle(fontSize: 18.0, color: context.appColors.textBlack, fontWeight: FontWeight.w500),
  312. ),
  313. Text(
  314. '$originalPoint',
  315. style: TextStyle(
  316. decoration: TextDecoration.lineThrough,
  317. decorationColor: ColorUtils.string2Color('#808DAF'),
  318. decorationStyle: TextDecorationStyle.solid,
  319. fontSize: 13.0,
  320. color: DarkThemeUtil.multiColors(context, ColorUtils.string2Color('#808DAF'),darkColor: Colors.white),
  321. fontWeight: FontWeight.w400),
  322. ).marginOnly(left: 5, right: 5),
  323. Text(
  324. S.current.points,
  325. style: TextStyle(fontSize: 13.0, color: context.appColors.textBlack, fontWeight: FontWeight.w400),
  326. ),
  327. ],
  328. )
  329. ],
  330. ).paddingOnly(top: 12, left: 12, right: 12)
  331. ],
  332. ).onTap(() {
  333. RewardsDetailPage.startInstance(id: id);
  334. });
  335. }
  336. Widget _buildFood(BuildContext context, WidgetRef ref, _vm, list) {
  337. return list['rewards'].length > 0
  338. ? Container(
  339. child: Column(
  340. children: [
  341. Row(
  342. crossAxisAlignment: CrossAxisAlignment.center,
  343. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  344. children: [
  345. Text(
  346. list?['name'] ?? '',
  347. style: TextStyle(fontSize: 17.0, color: context.appColors.textBlack, fontWeight: FontWeight.w500), // 设置字体大小
  348. ),
  349. Text(
  350. S.current.see_all,
  351. style: TextStyle(fontSize: 17.0, color: context.appColors.textPrimary, fontWeight: FontWeight.w500), // 设置字体大小
  352. ).onTap(() {
  353. RewardsListPage.startInstance();
  354. }),
  355. ],
  356. ).marginOnly(bottom: 15),
  357. Row(
  358. crossAxisAlignment: CrossAxisAlignment.center,
  359. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  360. children: List.generate(list['rewards'].length, (index) {
  361. double hg = 70;
  362. return Container(
  363. width: MediaQuery.of(context).size.width / 2 - 25,
  364. height: 155,
  365. decoration: BoxDecoration(
  366. color: context.appColors.whiteBG,
  367. borderRadius: const BorderRadius.all(Radius.circular(6.0)),
  368. boxShadow: [BoxShadow(color: context.appColors.itemBGShadow)],
  369. ),
  370. child: ClipRRect(
  371. borderRadius: const BorderRadius.all(Radius.circular(6.0)), child: _buildItem(context, ref, _vm, hg, list['rewards'][index])));
  372. }))
  373. ],
  374. ),
  375. ).paddingOnly(left: 15, right: 15, top: 10)
  376. : Container();
  377. }
  378. Widget _buildBest(BuildContext context, WidgetRef ref, _vm, list) {
  379. return list['rewards'].length > 0
  380. ? Container(
  381. child: Column(
  382. children: [
  383. Row(
  384. crossAxisAlignment: CrossAxisAlignment.center,
  385. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  386. children: [
  387. Text(
  388. S.current.best_offers_in_singapore,
  389. style: TextStyle(fontSize: 17.0, color: context.appColors.textBlack, fontWeight: FontWeight.w500), // 设置字体大小
  390. ),
  391. Text(
  392. S.current.see_all,
  393. style: TextStyle(fontSize: 17.0, color: context.appColors.textPrimary, fontWeight: FontWeight.w500), // 设置字体大小
  394. ),
  395. ],
  396. ).marginOnly(bottom: 15),
  397. Column(
  398. crossAxisAlignment: CrossAxisAlignment.center,
  399. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  400. children: List.generate(list['rewards'].length, (index) {
  401. double hg = 140;
  402. return Container(
  403. // width: MediaQuery.of(context).size.width / 2 - 25,
  404. height: 220,
  405. decoration: BoxDecoration(
  406. color:context.appColors.whiteBG,
  407. borderRadius: const BorderRadius.all(Radius.circular(6.0)),
  408. boxShadow: [BoxShadow(color: context.appColors.itemBGShadow)],
  409. ),
  410. child: ClipRRect(
  411. borderRadius: const BorderRadius.all(Radius.circular(6.0)), child: _buildItem(context, ref, _vm, hg, list['rewards'][index])))
  412. .marginOnly(bottom: 13);
  413. }))
  414. ],
  415. ),
  416. ).paddingOnly(left: 15, right: 15, top: 10)
  417. : Container();
  418. }
  419. @override
  420. Widget build(BuildContext context, WidgetRef ref) {
  421. final _vm = ref.read(rewardsHomeVmProvider.notifier);
  422. final state = ref.watch(rewardsHomeVmProvider);
  423. useEffect(() {
  424. // 组件挂载时执行 - 执行接口请求
  425. Future.microtask(() => _vm.initPageData());
  426. return () {
  427. // 组件卸载时执行s
  428. Log.d("property_news_page 组件卸载时执行");
  429. };
  430. }, []);
  431. return Scaffold(
  432. appBar: MyAppBar.appBar(
  433. context,
  434. "",
  435. backIconPath: Assets.rewardsRewardsBack,
  436. backIconWidth: 32.0,
  437. backIconHeight: 32.0,
  438. titleColor: Colors.white,
  439. titleDarkColor: Colors.white,
  440. showBackButton: true,
  441. backgroundColor: context.appColors.btnBgDefault,
  442. systemUiOverlayStyle: MediaQuery.of(context).platformBrightness == Brightness.dark
  443. ? ThemeConfig.systemUiOverlayStyleDarkTheme
  444. : ThemeConfig.systemUiOverlayStyleLightThemeWhite,
  445. ),
  446. body: Column(children: [
  447. Expanded(
  448. child: LoadStateLayout(
  449. state: state.loadingState,
  450. errorMessage: state.errorMessage,
  451. errorRetry: () {
  452. _vm.retryRequest();
  453. },
  454. successWidget: SingleChildScrollView(
  455. scrollDirection: Axis.vertical,
  456. physics: const BouncingScrollPhysics(),
  457. clipBehavior: Clip.none,
  458. child: state.list.length > 0
  459. ? Column(
  460. children: [
  461. Stack(clipBehavior: Clip.none, children: <Widget>[
  462. _buildTop(context, ref, _vm),
  463. // GestureDetector(
  464. // onTap: () {
  465. // print('第二个元素被点击'); // 这个会被触发。
  466. // },
  467. // child:Container(
  468. // transform:Matrix4.translationValues(0.0,210.0,0.0),child: _buildSearch(context,ref,_vm)//使用负数
  469. // ).paddingOnly(left:15,right:15))
  470. // Container(
  471. // // transform: Matrix4.translationValues(0.0, -25.0, 0.0),
  472. // child: _buildSearch(context, ref, _vm), // 使用负数margin
  473. // ).paddingOnly(left: 15, right: 15),
  474. Positioned(
  475. // 通过 Positioned 来确保它在红色容器的上方。
  476. left: 0, // 根据需要调整位置。
  477. bottom: -12, // 根据需要调整位置。
  478. child: GestureDetector(
  479. onTap: () {
  480. RewardsSearchPage.startInstance();
  481. },
  482. child: _buildSearch(context, ref, _vm),
  483. ).paddingOnly(left: 15, right: 15),
  484. ),
  485. ]).paddingOnly(bottom: 42),
  486. _buildSwiper(context, ref, _vm),
  487. _buildRecommend(context, ref, _vm, state.list![0]).marginOnly(bottom: 15),
  488. // _buildHottest(context, ref, _vm).marginOnly(bottom: 15),
  489. _buildFood(context, ref, _vm, state.list![2]).marginOnly(bottom: 15),
  490. _buildBest(context, ref, _vm, state.list![1]).marginOnly(bottom: 15),
  491. ],
  492. )
  493. : const Column()),
  494. )),
  495. ]).backgroundColor(context.appColors.backgroundDark),
  496. );
  497. }
  498. }