|
1 | 1 | import 'package:flutter/material.dart'; |
| 2 | +import 'package:flutter_bloc/flutter_bloc.dart'; |
2 | 3 | import 'package:flutter_screenutil/flutter_screenutil.dart'; |
3 | 4 | import 'package:flutter_svg/svg.dart'; |
| 5 | +import 'package:flutter_web_browser/flutter_web_browser.dart'; |
4 | 6 | import 'package:intl/intl.dart'; |
5 | 7 |
|
6 | 8 | import '../../../data/constants/assets.dart'; |
| 9 | +import '../../../data/constants/colors.dart'; |
7 | 10 | import '../../../data/constants/styles.dart'; |
| 11 | +import '../../../data/services/remote/notification_service.dart'; |
8 | 12 | import '../../../domain/models/contest.dart'; |
9 | 13 | import '../../../utils/contest_util.dart'; |
| 14 | +import '../bloc/contests_bloc.dart'; |
10 | 15 |
|
11 | 16 | class ContestCard extends StatelessWidget { |
12 | | - const ContestCard({ |
| 17 | + ContestCard({ |
| 18 | + required this.isReminderSet, |
13 | 19 | this.upcoming, |
14 | 20 | this.ongoing, |
15 | 21 | Key? key, |
16 | 22 | }) : assert(upcoming != null || ongoing != null, ''), |
17 | | - super(key: key); |
| 23 | + super(key: key) { |
| 24 | + _notifier = ValueNotifier(isReminderSet); |
| 25 | + } |
18 | 26 | final Upcoming? upcoming; |
19 | 27 | final Ongoing? ongoing; |
| 28 | + final bool isReminderSet; |
| 29 | + late final ValueNotifier<bool> _notifier; |
| 30 | + final ValueNotifier<int> _remindNotifer = ValueNotifier(2); |
20 | 31 |
|
21 | 32 | @override |
22 | 33 | Widget build(BuildContext context) { |
23 | 34 | return InkWell( |
24 | | - onTap: () {}, |
| 35 | + onTap: () { |
| 36 | + FlutterWebBrowser.openWebPage( |
| 37 | + url: upcoming?.url ?? ongoing!.url, |
| 38 | + customTabsOptions: const CustomTabsOptions( |
| 39 | + defaultColorSchemeParams: CustomTabsColorSchemeParams( |
| 40 | + toolbarColor: AppColors.primary, |
| 41 | + ), |
| 42 | + ), |
| 43 | + ); |
| 44 | + }, |
25 | 45 | child: Padding( |
26 | 46 | padding: EdgeInsets.symmetric( |
27 | 47 | vertical: 10.h, |
@@ -72,9 +92,193 @@ class ContestCard extends StatelessWidget { |
72 | 92 | ], |
73 | 93 | ), |
74 | 94 | ), |
75 | | - IconButton( |
76 | | - onPressed: () {}, |
77 | | - icon: SvgPicture.asset(AppAssets.bell), |
| 95 | + ValueListenableBuilder<bool>( |
| 96 | + valueListenable: _notifier, |
| 97 | + builder: (context, value, _) { |
| 98 | + return IconButton( |
| 99 | + onPressed: () { |
| 100 | + final _bloc = context.read<ContestsBloc>(); |
| 101 | + showDialog( |
| 102 | + context: context, |
| 103 | + builder: (context) { |
| 104 | + return AlertDialog( |
| 105 | + titlePadding: EdgeInsets.zero, |
| 106 | + contentPadding: EdgeInsets.zero, |
| 107 | + shape: RoundedRectangleBorder( |
| 108 | + borderRadius: BorderRadius.vertical( |
| 109 | + top: Radius.circular(5.r), |
| 110 | + ), |
| 111 | + ), |
| 112 | + title: Container( |
| 113 | + padding: EdgeInsets.symmetric(vertical: 10.h), |
| 114 | + decoration: BoxDecoration( |
| 115 | + color: AppColors.grey7, |
| 116 | + borderRadius: BorderRadius.vertical( |
| 117 | + top: Radius.circular(5.r), |
| 118 | + ), |
| 119 | + ), |
| 120 | + child: Text( |
| 121 | + 'Set Reminder', |
| 122 | + style: AppStyles.h6.copyWith( |
| 123 | + color: AppColors.primaryBlack, |
| 124 | + ), |
| 125 | + textAlign: TextAlign.center, |
| 126 | + ), |
| 127 | + ), |
| 128 | + content: Visibility( |
| 129 | + visible: upcoming != null, |
| 130 | + replacement: Padding( |
| 131 | + padding: EdgeInsets.all(30.r), |
| 132 | + child: const Text( |
| 133 | + 'The selected contest has already started. 😔 ', |
| 134 | + textAlign: TextAlign.center, |
| 135 | + ), |
| 136 | + ), |
| 137 | + child: SizedBox( |
| 138 | + height: 120.h, |
| 139 | + child: Column( |
| 140 | + children: [ |
| 141 | + Padding( |
| 142 | + padding: EdgeInsets.symmetric( |
| 143 | + horizontal: 30.w, |
| 144 | + vertical: 10.h, |
| 145 | + ), |
| 146 | + child: Text( |
| 147 | + 'You will be reminded before the contest starts. Set the timer', |
| 148 | + style: AppStyles.h6.copyWith( |
| 149 | + color: AppColors.primaryBlack, |
| 150 | + fontSize: 12.sp, |
| 151 | + ), |
| 152 | + textAlign: TextAlign.center, |
| 153 | + ), |
| 154 | + ), |
| 155 | + Row( |
| 156 | + mainAxisAlignment: MainAxisAlignment.center, |
| 157 | + children: [ |
| 158 | + ValueListenableBuilder<int>( |
| 159 | + valueListenable: _remindNotifer, |
| 160 | + builder: (context, value, _) { |
| 161 | + return SizedBox( |
| 162 | + height: 60.h, |
| 163 | + width: 30.w, |
| 164 | + child: ListWheelScrollView( |
| 165 | + controller: |
| 166 | + FixedExtentScrollController( |
| 167 | + initialItem: value, |
| 168 | + ), |
| 169 | + itemExtent: 25, |
| 170 | + useMagnifier: true, |
| 171 | + magnification: 1.3, |
| 172 | + onSelectedItemChanged: (val) { |
| 173 | + _remindNotifer.value = val; |
| 174 | + }, |
| 175 | + children: List.generate( |
| 176 | + 6, |
| 177 | + (index) { |
| 178 | + return Text( |
| 179 | + '${5 * (index + 1)}', |
| 180 | + style: |
| 181 | + AppStyles.h6.copyWith( |
| 182 | + color: index == value |
| 183 | + ? AppColors.primary |
| 184 | + : AppColors |
| 185 | + .primaryBlack, |
| 186 | + ), |
| 187 | + ); |
| 188 | + }, |
| 189 | + ).toList(), |
| 190 | + ), |
| 191 | + ); |
| 192 | + }, |
| 193 | + ), |
| 194 | + SizedBox(width: 4.w), |
| 195 | + Text( |
| 196 | + 'minutes', |
| 197 | + style: AppStyles.h6.copyWith( |
| 198 | + color: AppColors.primary, |
| 199 | + ), |
| 200 | + ), |
| 201 | + ], |
| 202 | + ), |
| 203 | + ], |
| 204 | + ), |
| 205 | + ), |
| 206 | + ), |
| 207 | + actions: [ |
| 208 | + if (upcoming != null) |
| 209 | + TextButton( |
| 210 | + onPressed: () { |
| 211 | + _notifier.value = false; |
| 212 | + _bloc.pendingNotification |
| 213 | + .remove(upcoming!.name); |
| 214 | + |
| 215 | + NotificationService.cancelNotification( |
| 216 | + name: upcoming!.name); |
| 217 | + |
| 218 | + Navigator.pop(context); |
| 219 | + }, |
| 220 | + child: Container( |
| 221 | + padding: EdgeInsets.symmetric( |
| 222 | + horizontal: 40.w, |
| 223 | + vertical: 10.h, |
| 224 | + ), |
| 225 | + color: AppColors.grey10, |
| 226 | + child: Text( |
| 227 | + 'Cancel', |
| 228 | + style: AppStyles.h6.copyWith( |
| 229 | + fontSize: 12.sp, |
| 230 | + ), |
| 231 | + ), |
| 232 | + ), |
| 233 | + ), |
| 234 | + TextButton( |
| 235 | + onPressed: () { |
| 236 | + if (upcoming != null) { |
| 237 | + _notifier.value = true; |
| 238 | + if (!_bloc.pendingNotification |
| 239 | + .contains(upcoming!.name)) { |
| 240 | + _bloc.pendingNotification |
| 241 | + .add(upcoming!.name); |
| 242 | + } |
| 243 | + NotificationService.setNotification( |
| 244 | + scheduledDate: upcoming!.startTime.subtract( |
| 245 | + Duration( |
| 246 | + minutes: (_remindNotifer.value + 1) * 6, |
| 247 | + ), |
| 248 | + ), |
| 249 | + title: upcoming!.name, |
| 250 | + body: 'Contest Starts at ' |
| 251 | + '${DateFormat('hh:mm a dd, MMMM yyyy').format(upcoming!.startTime)}', |
| 252 | + ); |
| 253 | + } |
| 254 | + |
| 255 | + Navigator.pop(context); |
| 256 | + }, |
| 257 | + child: Container( |
| 258 | + padding: EdgeInsets.symmetric( |
| 259 | + horizontal: 40.w, |
| 260 | + vertical: 10.h, |
| 261 | + ), |
| 262 | + color: AppColors.primary, |
| 263 | + child: Text( |
| 264 | + 'Okay', |
| 265 | + style: AppStyles.h6.copyWith( |
| 266 | + color: AppColors.white, |
| 267 | + fontSize: 12.sp, |
| 268 | + ), |
| 269 | + ), |
| 270 | + ), |
| 271 | + ), |
| 272 | + ], |
| 273 | + ); |
| 274 | + }, |
| 275 | + ); |
| 276 | + }, |
| 277 | + icon: SvgPicture.asset( |
| 278 | + value ? AppAssets.selectedBell : AppAssets.bell, |
| 279 | + ), |
| 280 | + ); |
| 281 | + }, |
78 | 282 | ), |
79 | 283 | ], |
80 | 284 | ), |
|
0 commit comments