rewards_home_page.dart 21 KB

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