bookmywages/lib/view/user_main_screens/package_screen.dart
2025-10-16 11:21:52 +05:30

371 lines
13 KiB
Dart

import 'package:bookmywages/consts_widgets/app_assets.dart';
import 'package:bookmywages/model/package_model.dart';
import 'package:bookmywages/model/plan_sucess_model.dart';
import 'package:bookmywages/routers/consts_router.dart';
import 'package:bookmywages/view/user_main_screens/main_contoller.dart';
import 'package:bookmywages/viewmodel/api_controller.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:get/get.dart';
import 'package:shared_preferences/shared_preferences.dart';
class PackageScreen extends ConsumerStatefulWidget {
const PackageScreen({super.key});
@override
ConsumerState<PackageScreen> createState() => _PackageScreenState();
}
class _PackageScreenState extends ConsumerState<PackageScreen> {
bool _isMounted = false;
@override
void initState() {
super.initState();
_isMounted = true;
}
@override
void dispose() {
_isMounted = false;
super.dispose();
}
@override
Widget build(BuildContext context) {
final packageAsyncValue = ref.watch(pacakgeProvider);
final indexController = InheritedIndexController.of(context);
return PopScope(
onPopInvoked: (didPop) {
if (didPop) {
// Reset main controller index to 0 when going back
final indexController = InheritedIndexController.of(context);
indexController?.changeIndex(0);
}
},
child: Scaffold(
appBar: AppBar(
backgroundColor: Colors.transparent,
elevation: 0,
leading: IconButton(
icon: const Icon(
Icons.arrow_back_ios_new_sharp,
color: Colors.black,
),
onPressed: () => Navigator.pop(context),
),
centerTitle: true,
title: const Text(
"Subscription Plan",
style: TextStyle(color: Colors.black, fontWeight: FontWeight.bold),
),
),
extendBodyBehindAppBar: true,
body: LayoutBuilder(
builder: (context, constraints) {
final isSmallScreen = constraints.maxWidth < 360;
final cardWidth = constraints.maxWidth * 0.8;
final cardHeight = constraints.maxHeight * 0.4;
return Container(
height: double.infinity,
width: double.infinity,
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage(AppAssets.background),
fit: BoxFit.cover,
),
),
child: SafeArea(
child: Padding(
padding: EdgeInsets.symmetric(
horizontal: constraints.maxWidth * 0.04,
vertical: constraints.maxHeight * 0.02,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
ConstrainedBox(
constraints: BoxConstraints(
maxHeight: constraints.maxHeight * 0.2,
),
child: Image.asset(
AppAssets.subscriptionimage,
fit: BoxFit.contain,
),
),
SizedBox(height: constraints.maxHeight * 0.02),
Text(
"Choose your right plan",
textAlign: TextAlign.center,
style: TextStyle(
fontFamily: 'Gilroy-Bold',
fontWeight: FontWeight.w400,
fontSize: isSmallScreen ? 24 : 32,
height: 1.0,
letterSpacing: 0.32,
color: Colors.black,
),
),
SizedBox(height: constraints.maxHeight * 0.01),
Padding(
padding: EdgeInsets.symmetric(
horizontal: constraints.maxWidth * 0.05,
),
child: Text(
"Make upgrade your plan and get more advantages of services",
textAlign: TextAlign.center,
style: TextStyle(
fontFamily: 'Gilroy-Bold',
fontWeight: FontWeight.w700,
fontSize: isSmallScreen ? 13 : 15,
height: 1.71,
letterSpacing: 0.15,
color: Colors.black,
),
),
),
SizedBox(height: constraints.maxHeight * 0.02),
Expanded(
child: packageAsyncValue.when(
data: (packages) {
final filteredPackages = packages
.where((pkg) => pkg.type == 1)
.toList();
return Center(
child: SizedBox(
height: cardHeight,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: filteredPackages.length,
itemBuilder: (context, index) {
final PackageModel package =
filteredPackages[index];
return Container(
width: cardWidth,
margin: EdgeInsets.symmetric(
horizontal: constraints.maxWidth * 0.02,
),
constraints: BoxConstraints(
maxHeight: cardHeight,
),
decoration: BoxDecoration(
color: const Color(0xFF334E95),
borderRadius: BorderRadius.circular(30),
border: Border.all(
color: const Color(0xFF334E95),
width: 1,
),
boxShadow: const [
BoxShadow(
color: Color(0x40828282),
offset: Offset(0, 5),
blurRadius: 4,
),
],
),
child: _PackageCard(
package: package,
onSubscribe: () => _subscribeToPlan(
package,
indexController,
),
isSmallScreen: isSmallScreen,
),
);
},
),
),
);
},
loading: () =>
const Center(child: CircularProgressIndicator()),
error: (error, stack) => Center(
child: Text(
'Error loading packages: $error',
style: const TextStyle(color: Colors.red),
),
),
),
),
],
),
),
),
);
},
),
),
);
}
Future<void> _subscribeToPlan(
PackageModel package,
InheritedIndexController? indexController,
) async {
try {
final prefs = await SharedPreferences.getInstance();
final userId = prefs.getString('userId') ?? '';
final model = PlanSuccessModel(
userId: userId,
planId: package.id.toString(),
duration: package.duration,
type: package.type,
);
final result = await ref.read(planSuccessProvider(model).future);
if (_isMounted) {
if (result) {
await showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text('Success'),
content: const Text('Plan subscribed successfully!'),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop();
indexController?.changeIndex(0);
ref.invalidate(expiredPlanProvider);
Get.toNamed(RouterConts.homescreen);
},
child: const Text('OK'),
),
],
),
);
} else {
Fluttertoast.showToast(
msg: 'Failed to subscribe to plan',
toastLength: Toast.LENGTH_LONG,
gravity: ToastGravity.BOTTOM,
backgroundColor: Colors.red,
textColor: Colors.white,
);
}
}
} catch (error) {
if (_isMounted) {
Fluttertoast.showToast(
msg: 'Error: ${error.toString()}',
toastLength: Toast.LENGTH_LONG,
gravity: ToastGravity.BOTTOM,
backgroundColor: Colors.red,
textColor: Colors.white,
);
}
}
}
}
class _PackageCard extends StatelessWidget {
final PackageModel package;
final VoidCallback onSubscribe;
final bool isSmallScreen;
const _PackageCard({
required this.package,
required this.onSubscribe,
required this.isSmallScreen,
});
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.all(MediaQuery.of(context).size.width * 0.04),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Center(
child: Text(
package.name,
style: TextStyle(
fontFamily: 'Gilroy-Bold',
fontWeight: FontWeight.w700,
fontSize: isSmallScreen ? 16 : 18,
height: 1.0,
letterSpacing: 0.32,
color: Colors.white,
),
),
),
const SizedBox(height: 8),
_buildFeatureRow(package.description),
const SizedBox(height: 16),
_buildFeatureRow(_getFormattedDuration(package.duration)),
const SizedBox(height: 16),
_buildFeatureRow('${package.noOfService} book service'),
],
),
const Divider(color: Colors.white),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
package.price,
style: TextStyle(
fontSize: isSmallScreen ? 14 : 16,
color: Colors.white,
fontWeight: FontWeight.w600,
),
),
GestureDetector(
onTap: onSubscribe,
child: Container(
width: 30,
height: 30,
decoration: const BoxDecoration(
color: Colors.white,
shape: BoxShape.circle,
),
child: const Icon(Icons.arrow_forward, color: Colors.black),
),
),
],
),
],
),
);
}
Widget _buildFeatureRow(String text) {
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const CircleAvatar(radius: 8, backgroundColor: Color(0xFFF9E369)),
const SizedBox(width: 6),
Expanded(
child: Text(
text,
style: TextStyle(
fontSize: isSmallScreen ? 12 : 14,
color: Colors.white,
),
),
),
],
);
}
String _getFormattedDuration(int duration) {
if (duration < 30) {
return '$duration days';
} else {
int months = duration ~/ 30;
return '$months month${months > 1 ? 's' : ''}';
}
}
}