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, )) ]))); } }