Game Prize and Logout
This commit is contained in:
@@ -1,15 +1,40 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
import '../../../presentation/router/app_router.gr.dart';
|
||||
import '../../constant/local_storage_key.dart';
|
||||
import '../errors/unauthorized_error.dart';
|
||||
|
||||
class UnauthorizedInterceptor extends Interceptor {
|
||||
static final GlobalKey<NavigatorState> navigatorKey =
|
||||
GlobalKey<NavigatorState>();
|
||||
@override
|
||||
void onError(DioException err, ErrorInterceptorHandler handler) {
|
||||
void onError(DioException err, ErrorInterceptorHandler handler) async {
|
||||
if (err.response?.statusCode == 401 ||
|
||||
err.response?.statusCode == 403 ||
|
||||
err.response?.statusCode == 419) {
|
||||
await _handleTokenExpired();
|
||||
return super.onError(UnauthorizedError(err, null), handler);
|
||||
}
|
||||
super.onError(err, handler);
|
||||
}
|
||||
|
||||
Future<void> _handleTokenExpired() async {
|
||||
// Clear stored token
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.remove(LocalStorageKey.token);
|
||||
await prefs.remove(LocalStorageKey.user);
|
||||
await prefs.clear(); // Optional: clear all user data
|
||||
log('handleTokenExpired');
|
||||
// Navigate to login page
|
||||
final context = navigatorKey.currentContext;
|
||||
if (context != null) {
|
||||
// Option 1: Navigate and remove all previous routes
|
||||
context.router.replaceAll([LoginRoute()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
import '../../injection.dart';
|
||||
import '../constant/local_storage_key.dart';
|
||||
|
||||
void dismissKeyboard(BuildContext context) {
|
||||
final currentFocus = FocusScope.of(context);
|
||||
@@ -13,3 +17,10 @@ String getNormalizePhone(String phoneNumber) {
|
||||
: phoneNumber;
|
||||
return '62$normalizedPhone';
|
||||
}
|
||||
|
||||
Map<String, dynamic> getAuthorizationHeader() {
|
||||
return {
|
||||
'Authorization':
|
||||
'Bearer ${getIt<SharedPreferences>().getString(LocalStorageKey.token)}',
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,19 +1,22 @@
|
||||
import 'dart:math' as math;
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../presentation/pages/mini_games/ferris_wheel/data/model.dart';
|
||||
import '../../domain/game/game.dart';
|
||||
import '../theme/theme.dart';
|
||||
|
||||
class WheelPainter extends CustomPainter {
|
||||
final List<WheelSection> sections;
|
||||
final List<GamePrize> gamePrizes;
|
||||
final Color Function(GamePrize prize, int index) getPrizeColor;
|
||||
|
||||
WheelPainter({required this.sections});
|
||||
WheelPainter({required this.gamePrizes, required this.getPrizeColor});
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
if (gamePrizes.isEmpty) return;
|
||||
|
||||
final center = Offset(size.width / 2, size.height / 2);
|
||||
final radius = size.width / 2;
|
||||
final sectionAngle = 2 * math.pi / sections.length;
|
||||
final sectionAngle = 2 * math.pi / gamePrizes.length;
|
||||
|
||||
// Draw outer white border
|
||||
final outerBorderPaint = Paint()
|
||||
@@ -34,12 +37,13 @@ class WheelPainter extends CustomPainter {
|
||||
canvas.drawCircle(center, radius - 20, innerWhitePaint);
|
||||
|
||||
// Draw sections
|
||||
for (int i = 0; i < sections.length; i++) {
|
||||
for (int i = 0; i < gamePrizes.length; i++) {
|
||||
final prize = gamePrizes[i];
|
||||
final startAngle = i * sectionAngle - math.pi / 2;
|
||||
|
||||
// Section background
|
||||
final sectionPaint = Paint()
|
||||
..color = sections[i].color
|
||||
..color = getPrizeColor(prize, i)
|
||||
..style = PaintingStyle.fill;
|
||||
|
||||
canvas.drawArc(
|
||||
@@ -67,15 +71,16 @@ class WheelPainter extends CustomPainter {
|
||||
canvas.save();
|
||||
canvas.translate(iconPosition.dx, iconPosition.dy);
|
||||
|
||||
// Draw icon using TextPainter to simulate Icon widget
|
||||
final iconText = _getIconText(sections[i].icon);
|
||||
// Get icon from metadata or use default
|
||||
final iconData = _getIconFromMetadata(prize.metadata);
|
||||
final iconText = _getIconText(iconData);
|
||||
final iconTextPainter = TextPainter(
|
||||
text: TextSpan(
|
||||
text: iconText,
|
||||
style: TextStyle(
|
||||
fontFamily: 'MaterialIcons',
|
||||
fontSize: 20,
|
||||
color: sections[i].color,
|
||||
color: getPrizeColor(prize, i),
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
),
|
||||
@@ -103,7 +108,7 @@ class WheelPainter extends CustomPainter {
|
||||
|
||||
final textPainter = TextPainter(
|
||||
text: TextSpan(
|
||||
text: sections[i].prize,
|
||||
text: prize.name,
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 10,
|
||||
@@ -119,6 +124,42 @@ class WheelPainter extends CustomPainter {
|
||||
);
|
||||
|
||||
canvas.restore();
|
||||
|
||||
// Draw stock indicator if stock is low
|
||||
if (prize.stock <= 5 && prize.stock > 0) {
|
||||
final stockAngle = startAngle + sectionAngle / 2;
|
||||
final stockPosition = Offset(
|
||||
center.dx + (radius - 35) * math.cos(stockAngle),
|
||||
center.dy + (radius - 35) * math.sin(stockAngle),
|
||||
);
|
||||
|
||||
final stockPaint = Paint()
|
||||
..color = AppColor.error
|
||||
..style = PaintingStyle.fill;
|
||||
canvas.drawCircle(stockPosition, 8, stockPaint);
|
||||
|
||||
canvas.save();
|
||||
canvas.translate(stockPosition.dx, stockPosition.dy);
|
||||
|
||||
final stockTextPainter = TextPainter(
|
||||
text: TextSpan(
|
||||
text: '!',
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 10,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
textDirection: TextDirection.ltr,
|
||||
);
|
||||
stockTextPainter.layout();
|
||||
stockTextPainter.paint(
|
||||
canvas,
|
||||
Offset(-stockTextPainter.width / 2, -stockTextPainter.height / 2),
|
||||
);
|
||||
|
||||
canvas.restore();
|
||||
}
|
||||
}
|
||||
|
||||
// Draw white dots around the outer edge
|
||||
@@ -141,7 +182,7 @@ class WheelPainter extends CustomPainter {
|
||||
..style = PaintingStyle.stroke
|
||||
..strokeWidth = 2;
|
||||
|
||||
for (int i = 0; i < sections.length; i++) {
|
||||
for (int i = 0; i < gamePrizes.length; i++) {
|
||||
final angle = i * sectionAngle - math.pi / 2;
|
||||
final lineStart = Offset(
|
||||
center.dx + (radius - 130) * math.cos(angle),
|
||||
@@ -155,6 +196,34 @@ class WheelPainter extends CustomPainter {
|
||||
}
|
||||
}
|
||||
|
||||
IconData _getIconFromMetadata(Map<String, dynamic> metadata) {
|
||||
final iconName = metadata['icon'] as String?;
|
||||
switch (iconName?.toLowerCase()) {
|
||||
case 'card_giftcard':
|
||||
return Icons.card_giftcard;
|
||||
case 'monetization_on':
|
||||
return Icons.monetization_on;
|
||||
case 'redeem':
|
||||
return Icons.redeem;
|
||||
case 'attach_money':
|
||||
return Icons.attach_money;
|
||||
case 'account_balance_wallet':
|
||||
return Icons.account_balance_wallet;
|
||||
case 'diamond':
|
||||
return Icons.diamond;
|
||||
case 'star':
|
||||
return Icons.star;
|
||||
case 'emoji_events':
|
||||
return Icons.emoji_events;
|
||||
case 'refresh':
|
||||
return Icons.refresh;
|
||||
case 'visibility':
|
||||
return Icons.visibility;
|
||||
default:
|
||||
return Icons.card_giftcard; // Default icon
|
||||
}
|
||||
}
|
||||
|
||||
String _getIconText(IconData icon) {
|
||||
// Convert IconData to Unicode string for drawing
|
||||
switch (icon.codePoint) {
|
||||
@@ -174,11 +243,17 @@ class WheelPainter extends CustomPainter {
|
||||
return String.fromCharCode(0xe8a1);
|
||||
case 0xe57d: // Icons.monetization_on
|
||||
return String.fromCharCode(0xe57d);
|
||||
case 0xe5ca: // Icons.diamond
|
||||
return String.fromCharCode(0xe5ca);
|
||||
case 0xe838: // Icons.star
|
||||
return String.fromCharCode(0xe838);
|
||||
case 0xe2a3: // Icons.emoji_events
|
||||
return String.fromCharCode(0xe2a3);
|
||||
default:
|
||||
return String.fromCharCode(0xe87c); // Default star icon
|
||||
return String.fromCharCode(0xe151); // Default card_giftcard icon
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
|
||||
bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
|
||||
}
|
||||
|
||||
@@ -5,4 +5,7 @@ class ApiPath {
|
||||
static String setPassword = '/api/v1/customer-auth/register/set-password';
|
||||
static String login = '/api/v1/customer-auth/login';
|
||||
static String resend = '/api/v1/customer-auth/resend-otp';
|
||||
|
||||
// Marketing
|
||||
static String gamePrizeByGameId = '/api/v1/marketing/game-prizes/game';
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user