guru_sdk/guru_ui/lib/pages/subscription/subscription_card.dart

633 lines
24 KiB
Dart
Raw Normal View History

import 'package:auto_size_text/auto_size_text.dart';
import 'package:design/design.dart';
import 'package:flutter/material.dart';
import 'package:guru_app/financial/iap/iap_model.dart';
import 'package:guru_ui/pages/subscription/subscription_page.dart';
import 'package:guru_ui/widget/image/adaptive_image.dart';
import 'package:guru_widgets/button/single_tap_widget.dart';
import 'package:guru_widgets/theme/guru_theme.dart';
part 'subscription_card.g.dart';
@DesignSpec(width: 242, height: 320, nestedSpec: true)
abstract class SubscriptionMainCardDesignSpec implements BasicDesignSpec {
@SpecSize(SpecWidth(242), SpecHeight(58))
Size get decorationSize;
@SpecRadius.only(topStart: SpecHeight(24), topEnd: SpecHeight(24))
BorderRadiusDirectional get premiumCenterCardDecorationRadius;
@SpecAbsoluteFontSize(22)
double get decorationFontSize;
@SpecHeight(4)
double get cardBorderWidth;
@SpecRadius.circular(SpecHeight(24))
BorderRadiusDirectional get cardRadius;
@SpecEdgeInsets.only(
top: SpecHeight(40), start: SpecWidth(16), end: SpecWidth(16))
EdgeInsetsDirectional get titleMargin;
@SpecAbsoluteFontSize(38)
double get titleFontSize;
@SpecEdgeInsets.only(
top: SpecHeight(10), start: SpecWidth(16), end: SpecWidth(16))
EdgeInsetsDirectional get subTitleMargin;
@SpecAbsoluteFontSize(20)
double get subTitleFontSize;
@SpecEdgeInsets.only(
bottom: SpecHeight(6), start: SpecWidth(16), end: SpecWidth(16))
EdgeInsetsDirectional get thenMargin;
@SpecAbsoluteFontSize(20)
double get thenFontSize;
@SpecEdgeInsets.only(
bottom: SpecHeight(32), start: SpecWidth(16), end: SpecWidth(16))
EdgeInsetsDirectional get priceMargin;
@SpecAbsoluteFontSize(24)
double get priceFontSize;
@SpecHeight(-30)
double get cardLabelTopSpcing;
@SpecHeight(-20)
double get cardLabelRightSpcing;
@SpecHeight(112)
double get cardLabelSize;
static SubscriptionMainCardDesignSpec create(Size size,
{Offset offset = Offset.zero}) =>
_SubscriptionMainCardDesignSpec.from(size, offset: offset);
}
@DesignSpec(width: 206, height: 268, nestedSpec: true)
abstract class SubscriptionEdgeCardDesignSpec implements BasicDesignSpec {
@SpecHeight(4)
double get cardBorderWidth;
@SpecRadius.circular(SpecHeight(24))
BorderRadiusDirectional get cardRadius;
@SpecEdgeInsets.only(
top: SpecHeight(40), start: SpecWidth(16), end: SpecWidth(16))
EdgeInsetsDirectional get titleMargin;
@SpecAbsoluteFontSize(32)
double get titleFontSize;
@SpecEdgeInsets.only(
top: SpecHeight(10), start: SpecWidth(16), end: SpecWidth(16))
EdgeInsetsDirectional get subTitleMargin;
@SpecAbsoluteFontSize(20)
double get subTitleFontSize;
@SpecEdgeInsets.only(
bottom: SpecHeight(4), start: SpecWidth(16), end: SpecWidth(16))
EdgeInsetsDirectional get thenMargin;
@SpecAbsoluteFontSize(17)
double get thenFontSize;
@SpecEdgeInsets.only(
bottom: SpecHeight(32), start: SpecWidth(16), end: SpecWidth(16))
EdgeInsetsDirectional get priceMargin;
@SpecAbsoluteFontSize(24)
double get priceFontSize;
@SpecHeight(-30)
double get cardLabelTopSpcing;
@SpecHeight(-20)
double get cardLabelRightSpcing;
@SpecHeight(112)
double get cardLabelSize;
static SubscriptionEdgeCardDesignSpec create(Size size,
{Offset offset = Offset.zero}) =>
_SubscriptionEdgeCardDesignSpec.from(size, offset: offset);
}
@DesignSpec(width: 650, height: 124, nestedSpec: true)
abstract class SubscriptionListCardDesignSpec implements BasicDesignSpec {
@SpecRadius.circular(SpecHeight(24))
BorderRadiusDirectional get cardRadius;
@SpecEdgeInsets.only(start: SpecWidth(40), end: SpecWidth(40))
EdgeInsetsDirectional get cardPadding;
@SpecAbsoluteFontSize(32)
double get titleFontSize;
@SpecEdgeInsets.only(top: SpecWidth(10))
EdgeInsetsDirectional get subTitleMargin;
@SpecAbsoluteFontSize(22)
double get subTitleFontSize;
@SpecAbsoluteFontSize(26)
double get priceFontSize;
@SpecHeight(-12)
double get cardLabelTopSpcing;
@SpecHeight(20)
double get cardLabelRightSpcing;
@SpecSize(SpecWidth(126), SpecHeight(36))
Size get cardLabelSize;
static SubscriptionListCardDesignSpec create(Size size,
{Offset offset = Offset.zero}) =>
_SubscriptionListCardDesignSpec.from(size, offset: offset);
}
class SubscriptionMainCardModel {
final IapProduct? product;
final SubscriptionCardItem cardItem;
final SubscriptionTheme subscriptionTheme;
final GuruColorScheme? colorScheme;
final SubscriptionMainCardDesignSpec designSpec;
final VoidCallback onTap;
final bool selected;
SubscriptionMainCardModel(
{required this.product,
required this.cardItem,
required this.subscriptionTheme,
this.colorScheme,
required this.designSpec,
required this.onTap,
this.selected = false});
}
class SubscriptionMainCard extends StatelessWidget {
final SubscriptionMainCardModel model;
IapProduct? get product => model.product;
SubscriptionCardItem get cardItem => model.cardItem;
SubscriptionTheme get subscriptionTheme => model.subscriptionTheme;
GuruColorScheme? get colorScheme => model.colorScheme;
SubscriptionMainCardDesignSpec get designSpec => model.designSpec;
bool get selected => model.selected;
const SubscriptionMainCard({Key? key, required this.model}) : super(key: key);
@override
Widget build(BuildContext context) {
final activeTheme = subscriptionTheme.activeCardStyle;
final defaultTheme = subscriptionTheme.cardStyle;
final activeDecoration = activeTheme?.decoration ??
BoxDecoration(
color: colorScheme?.primaryContentColor,
borderRadius: designSpec.cardRadius,
border: Border.all(
color: colorScheme?.primaryColor ?? const Color(0xFF07B25E),
width: designSpec.cardBorderWidth,
strokeAlign: BorderSide.strokeAlignCenter, //StrokeAlign.inside,
),
);
final defaultDecoration = defaultTheme?.decoration ??
BoxDecoration(
color: colorScheme?.primaryContentColor,
borderRadius: designSpec.cardRadius);
final decoration = selected ? activeDecoration : defaultDecoration;
return TapWidget(
onTap: () {
model.onTap();
},
child: Container(
decoration: decoration,
width: designSpec.measuredSize.width,
height: designSpec.measuredSize.height,
child: Stack(clipBehavior: Clip.none, children: [
Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
if (cardItem.labelText != null)
Container(
width: designSpec.decorationSize.width,
height: designSpec.decorationSize.height,
decoration: BoxDecoration(
borderRadius:
designSpec.premiumCenterCardDecorationRadius,
color: selected
? const Color(0xFF07B25E)
: const Color(0x12FFFFFF),
),
alignment: Alignment.center,
padding: EdgeInsetsDirectional.only(
top: designSpec.cardBorderWidth),
child: AutoSizeText(
cardItem.labelText!,
stepGranularity: 0.1,
minFontSize: 5,
maxLines: 1,
style: TextStyle(
color: selected
? Colors.white
: const Color(0x4DFFFFFF),
fontSize: designSpec.decorationFontSize,
fontWeight: GuruTheme.fwSemiBold,
),
),
),
Padding(
padding: designSpec.titleMargin,
child: AutoSizeText(
cardItem.title,
maxLines: 2,
minFontSize: 5,
textAlign: TextAlign.center,
style: TextStyle(
height: 1.236,
color: selected
? (activeTheme?.cardTitleColor ??
Colors.white)
: (defaultTheme?.cardTitleColor ??
const Color(0xE6FFFFFF)),
fontSize: designSpec.titleFontSize,
fontWeight: GuruTheme.fwBold),
),
),
],
),
Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
if (cardItem.thenTexg != null)
Padding(
padding: designSpec.thenMargin,
child: Text(
cardItem.thenTexg!,
style: TextStyle(
height: 1.25,
color: selected
? (activeTheme?.cardSubTitleColor ??
const Color(0xE6FFFFFF))
: (defaultTheme?.cardSubTitleColor ??
const Color(0xB3FFFFFF)),
fontSize: designSpec.thenFontSize,
fontWeight: GuruTheme.fwMedium,
),
),
),
Padding(
padding: designSpec.priceMargin,
child: AutoSizeText(
product?.details.price ?? "?",
minFontSize: 5,
style: TextStyle(
height: 1.25,
color: selected
? (activeTheme?.cardPriceColor ??
const Color(0xE6FFFFFF))
: (defaultTheme?.cardPriceColor ??
const Color(0xB3FFFFFF)),
fontSize: designSpec.priceFontSize,
fontWeight: GuruTheme.fwSemiBold,
),
),
),
])
],
),
if (cardItem.labelImage != null)
Positioned.directional(
textDirection: Directionality.of(context),
top: designSpec.cardLabelTopSpcing,
end: designSpec.cardLabelRightSpcing,
child: AdaptiveImage(cardItem.labelImage!,
height: designSpec.cardLabelSize))
])));
}
}
class SubscriptionEdgeCardModel {
final IapProduct? product;
final SubscriptionCardItem cardItem;
final SubscriptionTheme subscriptionTheme;
final GuruColorScheme? colorScheme;
final SubscriptionEdgeCardDesignSpec designSpec;
final VoidCallback onTap;
final bool selected;
SubscriptionEdgeCardModel(
{required this.product,
required this.cardItem,
required this.subscriptionTheme,
this.colorScheme,
required this.designSpec,
required this.onTap,
this.selected = false});
}
class SubscriptionEdgeCard extends StatelessWidget {
final SubscriptionEdgeCardModel model;
IapProduct? get product => model.product;
SubscriptionCardItem get cardItem => model.cardItem;
SubscriptionTheme get subscriptionTheme => model.subscriptionTheme;
GuruColorScheme? get colorScheme => model.colorScheme;
SubscriptionEdgeCardDesignSpec get designSpec => model.designSpec;
bool get selected => model.selected;
const SubscriptionEdgeCard({Key? key, required this.model}) : super(key: key);
@override
Widget build(BuildContext context) {
final activeTheme = subscriptionTheme.activeCardStyle;
final defaultTheme = subscriptionTheme.cardStyle;
final activeDecoration = activeTheme?.decoration ??
BoxDecoration(
color: colorScheme?.primaryContentColor,
borderRadius: designSpec.cardRadius,
border: Border.all(
color: colorScheme?.primaryColor ?? const Color(0xFF07B25E),
width: designSpec.cardBorderWidth,
strokeAlign: BorderSide.strokeAlignInside, //StrokeAlign.inside,
),
);
final defaultDecoration = defaultTheme?.decoration ??
BoxDecoration(
color: colorScheme?.primaryContentColor ?? const Color(0xff252525),
borderRadius: designSpec.cardRadius);
final decoration = selected ? activeDecoration : defaultDecoration;
return TapWidget(
onTap: () {
model.onTap();
},
child: Container(
decoration: decoration,
width: designSpec.measuredSize.width,
height: designSpec.measuredSize.height,
child:
Stack(fit: StackFit.expand, clipBehavior: Clip.none, children: [
Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(
padding: designSpec.titleMargin,
child: AutoSizeText(
cardItem.title,
maxLines: 2,
minFontSize: 5,
textAlign: TextAlign.center,
style: TextStyle(
height: 1.25,
color: selected
? (activeTheme?.cardTitleColor ??
Colors.white)
: (defaultTheme?.cardTitleColor ??
const Color(0xE6FFFFFF)),
fontSize: designSpec.titleFontSize,
fontWeight: GuruTheme.fwBold),
),
),
if (cardItem.subTitle != null)
Padding(
padding: designSpec.subTitleMargin,
child: Text(
cardItem.subTitle!,
maxLines: 2,
textAlign: TextAlign.center,
style: TextStyle(
height: 1.25,
color: selected
? (activeTheme?.cardSubTitleColor ??
const Color(0xE6FFFFFF))
: (defaultTheme?.cardSubTitleColor ??
const Color(0xB3FFFFFF)),
fontSize: designSpec.subTitleFontSize,
fontWeight: GuruTheme.fwMedium),
),
),
],
),
Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
if (cardItem.thenTexg != null)
Padding(
padding: designSpec.thenMargin,
child: Text(
cardItem.thenTexg!,
style: TextStyle(
height: 1.29,
color: selected
? const Color(0xE6FFFFFF)
: const Color(0xB3FFFFFF),
fontSize: designSpec.thenFontSize,
fontWeight: GuruTheme.fwMedium,
),
),
),
Padding(
padding: designSpec.priceMargin,
child: AutoSizeText(
product?.details.price ?? "?",
minFontSize: 5,
maxLines: 1,
style: TextStyle(
height: 1.25,
color: selected
? (activeTheme?.cardPriceColor ??
const Color(0xE6FFFFFF))
: (defaultTheme?.cardPriceColor ??
const Color(0xB3FFFFFF)),
fontSize: designSpec.priceFontSize,
fontWeight: GuruTheme.fwSemiBold,
),
),
),
])
],
),
if (cardItem.labelImage != null)
Positioned.directional(
textDirection: Directionality.of(context),
top: designSpec.cardLabelTopSpcing,
end: designSpec.cardLabelRightSpcing,
child: AdaptiveImage(cardItem.labelImage!,
height: designSpec.cardLabelSize))
])));
}
}
class SubscriptionListCardModel {
final IapProduct? product;
final SubscriptionCardItem cardItem;
final SubscriptionTheme subscriptionTheme;
final GuruColorScheme? colorScheme;
final SubscriptionListCardDesignSpec designSpec;
final VoidCallback onTap;
final bool selected;
SubscriptionListCardModel(
{required this.product,
required this.cardItem,
required this.subscriptionTheme,
this.colorScheme,
required this.designSpec,
required this.onTap,
this.selected = false});
}
class SubscriptionListCard extends StatelessWidget {
final SubscriptionListCardModel model;
IapProduct? get product => model.product;
SubscriptionCardItem get cardItem => model.cardItem;
SubscriptionTheme get subscriptionTheme => model.subscriptionTheme;
GuruColorScheme? get colorScheme => model.colorScheme;
SubscriptionListCardDesignSpec get designSpec => model.designSpec;
bool get selected => model.selected;
const SubscriptionListCard({Key? key, required this.model}) : super(key: key);
@override
Widget build(BuildContext context) {
final activeTheme = subscriptionTheme.activeCardStyle;
final defaultTheme = subscriptionTheme.cardStyle;
final activeDecoration = activeTheme?.decoration ??
BoxDecoration(
color: colorScheme?.primaryContentColor,
borderRadius: designSpec.cardRadius,
border: Border.all(
color: colorScheme?.primaryColor ?? const Color(0xFF07B25E),
width: 2,
strokeAlign: BorderSide.strokeAlignInside, //StrokeAlign.inside,
),
);
final defaultDecoration = defaultTheme?.decoration ??
BoxDecoration(
color: colorScheme?.primaryContentColor ?? const Color(0xff252525),
borderRadius: designSpec.cardRadius);
final decoration = selected ? activeDecoration : defaultDecoration;
return TapWidget(
onTap: () {
model.onTap();
},
child: Container(
decoration: decoration,
width: designSpec.measuredSize.width,
height: designSpec.measuredSize.height,
child:
Stack(fit: StackFit.expand, clipBehavior: Clip.none, children: [
Padding(
padding: designSpec.cardPadding,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
AutoSizeText(
cardItem.title,
maxLines: 1,
minFontSize: 5,
textAlign: TextAlign.center,
style: TextStyle(
height: 1.25,
color: selected
? (activeTheme?.cardTitleColor ??
Colors.white)
: (defaultTheme?.cardTitleColor ??
const Color(0xE6FFFFFF)),
fontSize: designSpec.titleFontSize,
fontWeight: GuruTheme.fwBold),
),
if (cardItem.subTitle != null)
Padding(
padding: designSpec.subTitleMargin,
child: Text(
cardItem.subTitle!,
maxLines: 2,
textAlign: TextAlign.center,
style: TextStyle(
height: 1.25,
color: selected
? (activeTheme?.cardSubTitleColor ??
const Color(0xE6FFFFFF))
: (defaultTheme?.cardSubTitleColor ??
const Color(0xB3FFFFFF)),
fontSize: designSpec.subTitleFontSize,
fontWeight: GuruTheme.fwMedium),
),
),
],
),
Text(
product?.details.price ?? "?",
style: TextStyle(
height: 1.25,
color: selected
? (activeTheme?.cardPriceColor ??
const Color(0xE6FFFFFF))
: (defaultTheme?.cardPriceColor ??
const Color(0xB3FFFFFF)),
fontSize: designSpec.priceFontSize,
fontWeight: GuruTheme.fwSemiBold,
),
),
],
),
),
if (cardItem.labelImage != null)
Positioned.directional(
textDirection: Directionality.of(context),
top: designSpec.cardLabelTopSpcing,
end: designSpec.cardLabelRightSpcing,
child: AdaptiveImage(
cardItem.labelImage!,
height: designSpec.cardLabelSize.height,
width: designSpec.cardLabelSize.width,
))
])));
}
}