Look at the
I have problem in logic i'm trying to achieve to select second price box of my UI for Basic Plan but not able to select it ,what would be the cause here .When i Did without API ,its was working fine ,now im having issues with price selection as i m able to select only vertically not able to select horizontal values .
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutterquiz/features/subscription/SubscriptionRepository.dart';
import 'package:flutterquiz/features/subscription/cubits/subscriptionProductCubit.dart';
import 'package:flutterquiz/ui/screens/subscription/widgets/payment_service.dart';
class SubscriptionOption {
final String? title;
final String durationUnit;
final String price;
final String description;
SubscriptionOption({
this.title,
required this.durationUnit,
required this.price,
required this.description,
});
factory SubscriptionOption.fromJson(Map<String, dynamic> json) {
return SubscriptionOption(
title: json['title'],
durationUnit: json['durationUnit'],
price: '₹${json['actualPrice']}',
description: '₹${json['actualPrice']} per ${json['durationUnit']}',
);
}
}
class Subscription extends StatefulWidget {
const Subscription({Key? key}) : super(key: key);
@override
State<Subscription> createState() => _SubscriptionState();
static Route<dynamic> route(RouteSettings routeSettings) {
return CupertinoPageRoute(
builder: (context) => MultiBlocProvider(
providers: [
BlocProvider<SubscriptionProductCubit>(
create: (_) => SubscriptionProductCubit(SubscriptionRepository()),
)
],
child: Subscription(),
),
);
}
}
class _SubscriptionState extends State<Subscription> {
late List<List<SubscriptionOption>> _subscriptionOptions = [];
late List<int> _selectedOptionIndices = [];
String _selectedOptionPrice = '';
bool isSelected = false;
int _selectedCardIndex = -1; // Initialize to -1 indicating no card selected
@override
void initState() {
super.initState();
// Initialize subscription options from API
_fetchSubscriptionOptions();
}
void _fetchSubscriptionOptions() {
context.read<SubscriptionProductCubit>().getSubscriptionProducts();
}
@override
Widget build(BuildContext context) {
return Scaffold(
bottomNavigationBar: _buildContinueButton(),
body: SafeArea(
child: BlocBuilder<SubscriptionProductCubit, SubscriptionProductState>(
builder: (context, state) {
if (state is SubscriptionProductInProgress) {
// Show loading indicator
return Center(child: CircularProgressIndicator());
} else if (state is SubscriptionProductSuccess) {
// Update subscription options with fetched data
_subscriptionOptions = state.productList.map((product) {
return product.subscriptionProductPriceViewModels!.map((price) {
return SubscriptionOption(
title: product.title,
durationUnit: '${price.duration} ${price.durationUnit}',
price: '₹${price.actualPrice}',
description:
'₹${price.actualPrice} per ${price.durationUnit}',
);
}).toList();
}).toList();
// Initialize selected option indices
_selectedOptionIndices =
List.filled(_subscriptionOptions.length, 0);
return SingleChildScrollView(
padding: EdgeInsets.symmetric(horizontal: 10),
child: Column(
children: List.generate(
_subscriptionOptions.length,
(index) => _buildCard(
index, _subscriptionOptions[index][0].title!),
),
),
);
} else if (state is SubscriptionProductFailure) {
// Show error message
return Center(child: Text(state.errorMessage));
}
return Container(); // Return empty container by default
},
),
),
);
}
Widget _buildCard(int cardIndex, String title) {
return Card(
elevation: 8.0,
child: Container(
decoration: BoxDecoration(
color: Theme.of(context).backgroundColor,
shape: BoxShape.rectangle,
borderRadius: BorderRadius.circular(10),
),
padding: EdgeInsets.all(8),
height: 250,
width: 400,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('$title'),
SizedBox(height: 10),
Divider(
height: 1,
color: Colors.blueGrey.shade300,
),
SizedBox(height: 20),
Row(
children: <Widget>[
_buildFeature(
"DailyQuiz Available ", "", "", Icons.phone_android),
_buildFeature(
"QuizZone Improve Level", "", "", Icons.laptop_mac)
],
),
SizedBox(
height: 80,
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: _subscriptionOptions[cardIndex]
.asMap()
.entries
.map(
(entry) => Padding(
padding: EdgeInsets.symmetric(
horizontal:
MediaQuery.of(context).size.width * .02),
child: _buildPrice(entry.value, entry.key, cardIndex),
),
)
.toList(),
),
),
),
],
),
),
);
}
Widget _buildFeature(
String title, String subtitle, String extra, IconData icon) {
return SizedBox(
width: 90,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Icon(icon),
Text(
title,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 12,
),
maxLines: 2,
),
Text(subtitle),
Text(extra),
],
),
);
}
Widget _buildPrice(SubscriptionOption option, int index, int cardIndex) {
isSelected = _selectedOptionIndices[cardIndex] == index &&
_selectedCardIndex == cardIndex;
IconData iconData =
isSelected ? Icons.check_circle : Icons.radio_button_unchecked;
return GestureDetector(
onTap: () {
setState(() {
_selectedOptionIndices[cardIndex] = index;
_selectedCardIndex = cardIndex;
});
},
child: Container(
width: 150,
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 5),
decoration: BoxDecoration(
color: isSelected
? Theme.of(context).primaryColorDark
: Colors.transparent,
border: Border.all(
color:
isSelected ? Theme.of(context).primaryColorDark : Colors.blue,
width: 2,
),
borderRadius: BorderRadius.circular(8),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
option.durationUnit,
style: TextStyle(
color: isSelected ? Colors.white : Colors.black,
fontSize: 12,
),
),
Icon(
iconData,
color: isSelected ? Colors.green : Colors.grey,
),
],
),
Text(
option.price,
style: TextStyle(
color: isSelected ? Colors.white : Colors.black,
fontSize: 16,
),
),
Text(
option.description,
style: TextStyle(
color: isSelected ? Colors.orange.shade400 : Colors.black,
fontSize: 12,
),
),
],
),
),
);
}
// Get the selected options for the active card
Widget _buildContinueButton() {
if (_selectedCardIndex == -1) {
// If no card is selected, display a message indicating so
return Container(
color: Colors.black87,
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 20),
child: Text(
'No plan selected',
style: TextStyle(fontSize: 16, color: Colors.white),
),
);
}
// Get the selected options for the active card
List<SubscriptionOption> selectedOptions =
_subscriptionOptions[_selectedCardIndex];
// Get the index of the selected option in the active card
int selectedIndex = _selectedOptionIndices[_selectedCardIndex];
// Extract the selected option
SubscriptionOption selectedOption = selectedOptions[selectedIndex];
return Container(
color: Colors.black87,
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 20),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
' ${selectedOption.title!} ',
style: TextStyle(fontSize: 16, color: Colors.white),
),
Text(
' Plan Price: ${selectedOption.price} ',
style: TextStyle(fontSize: 16, color: Colors.white),
),
],
),
ElevatedButton(
style: ElevatedButton.styleFrom(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
minimumSize: Size(190, 50),
),
onPressed: () {
// You can implement any functionality here
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
PaymentScreen(selectedOption: selectedOption),
),
);
},
child: Row(
children: [Text("Continue "), Icon(Icons.navigate_next)],
),
),
],
),
);
}
}
This Are two Images of My problem](https://i.stack.imgur.com/eu3iK.png)