Skip to content

Instantly share code, notes, and snippets.

@EsinShadrach
Created September 24, 2025 23:29
Show Gist options
  • Select an option

  • Save EsinShadrach/65822e4b44133a4d1f80b760bc65202e to your computer and use it in GitHub Desktop.

Select an option

Save EsinShadrach/65822e4b44133a4d1f80b760bc65202e to your computer and use it in GitHub Desktop.
import 'package:playcope/lib.dart';
class GamesAddedCounter extends StatefulWidget {
const GamesAddedCounter({
super.key,
this.isVisible = true,
required this.controller,
this.offsetY = 0,
this.date,
});
final bool isVisible;
final NewCustomBetBuilder controller;
final double offsetY;
final DateTime? date;
@override
State<GamesAddedCounter> createState() => _GamesAddedCounterState();
}
class _GamesAddedCounterState extends State<GamesAddedCounter> {
@override
Widget build(BuildContext context) {
return ListenableBuilder(
listenable: widget.controller,
builder: (context, _) {
final slipCount = widget.controller.count;
final isLoading = widget.controller.isLoading;
return TweenAnimationBuilder<double>(
duration: const Duration(milliseconds: 300),
curve: Curves.easeInOut,
tween: Tween(begin: 0, end: widget.isVisible ? 0 : 100),
builder: (context, value, child) {
return Transform.translate(
offset: Offset(0, value + widget.offsetY),
child: child,
);
},
child: Focus(
canRequestFocus: widget.isVisible,
child: GestureDetector(
onTap: () {
final viewGamesSheet = ViewCustomGamesSheet();
if (context.isApple) {
showCupertinoSheet(
context: context,
builder: (context) {
return viewGamesSheet;
},
);
} else {
showGradientBottomSheet(
context,
builder: (context) {
return Container(
decoration: BoxDecoration(
color: context.colorScheme.surfaceContainerHighest,
),
constraints: BoxConstraints(
maxHeight: context.screenHeight * 0.9,
minHeight: context.screenHeight * 0.65,
),
child: viewGamesSheet,
);
},
);
}
},
child:
Container(
padding: EdgeInsets.symmetric(horizontal: 10, vertical: 8),
decoration: ShapeDecoration(
color: context.colorScheme.surface,
shape: StadiumBorder(
side: BorderSide(
color: context.colorScheme.outlineVariant.withValues(
alpha: 0.5,
),
width: 1.5,
),
),
),
child: Row(
spacing: 10,
children: [
// negate to test code
if (isLoading) ...[
Stack(
children: [
CircleAvatar(
radius: 15,
backgroundColor:
slipCount == 0
? context.colorScheme.outlineVariant
: context.colorScheme.primary,
child: Transform.translate(
offset: Offset(0, -2.0),
child: SmoothCounter(
curve: Curves.bounceOut,
count: slipCount,
textStyle: GoogleFonts.spaceGrotesk(
fontSize: 16,
color:
slipCount == 0
? context
.colorScheme
.onSurfaceVariant
: context.colorScheme.onPrimary,
fontWeight: FontWeight.w900,
),
),
),
).positionFill(),
CircularProgressIndicator().withSizedBox(
dimension: 35,
),
],
),
] else ...[
Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
color:
slipCount == 0
? context.colorScheme.outlineVariant
: context.colorScheme.primary,
width: 1.5,
),
),
padding: const EdgeInsets.all(3),
child: CircleAvatar(
radius: 15,
backgroundColor:
slipCount == 0
? context.colorScheme.outlineVariant
: context.colorScheme.primary,
child: Transform.translate(
offset: Offset(0, -2.0),
child: SmoothCounter(
curve: Curves.bounceOut,
count: slipCount,
textStyle: GoogleFonts.spaceGrotesk(
fontSize: 16,
color:
slipCount == 0
? context
.colorScheme
.onSurfaceVariant
: context.colorScheme.onPrimary,
fontWeight: FontWeight.w900,
),
),
),
),
),
],
AnimatedDefaultTextStyle(
duration: const Duration(milliseconds: 300),
curve: Curves.bounceOut,
style: GoogleFonts.spaceGrotesk(
fontSize: 14,
color:
slipCount == 0
? context.colorScheme.outlineVariant
: context.colorScheme.onSurfaceVariant,
fontWeight: FontWeight.bold,
),
child: Text(
pluralizeWithFormat(
slipCount,
"Game",
"Added",
displayCount: false,
),
),
).withSizedBox(width: 100),
],
),
).intrinsicWidth,
),
),
);
},
);
}
}
class ViewCustomGamesSheet extends StatefulWidget {
const ViewCustomGamesSheet({super.key});
@override
State<ViewCustomGamesSheet> createState() => _ViewCustomGamesSheetState();
}
class _ViewCustomGamesSheetState extends State<ViewCustomGamesSheet>
with
ReferralService,
RequestHandlerMixin<ViewCustomGamesSheet, UserReferralStat> {
final GlobalKey _shareKey = GlobalKey();
@override
void initState() {
super.initState();
handleRequest(
eventName: "get-referral-stat",
requestFunction: getReferralStat,
);
}
VoidCallback? get onShare {
final bool hasCode = data?.data?.code != null;
final bool hasBets = betBuilderController.items?.isNotEmpty ?? false;
if (!hasCode && !hasBets) return null;
return () async {
await toImage(
key: _shareKey,
text:
"Locked in my football predictions on Playcope! Think I've got a winner?",
);
};
}
@override
Widget build(BuildContext context) {
final customBets = betBuilderController;
return Stack(
children: [
ClipRect(
clipBehavior: Clip.antiAlias,
child: OverflowBox(
maxWidth: double.infinity,
maxHeight: double.infinity,
child:
RepaintBoundary(
key: _shareKey,
child: ShareGamesCard(
slips: customBets.slips,
risk: "low",
referralCode: data?.data?.code ?? "--",
),
).centered,
),
),
Material(
child: Visibility(
visible: true,
child: Column(
children: [
SlipsSheetHeader(
disabled: customBets.count == 0,
title: "Games",
slipCount: customBets.count,
).withPadding(horizontal: 14, vertical: 10),
ListView.separated(
itemCount: customBets.items?.length ?? 0,
padding: EdgeInsets.symmetric(horizontal: 14, vertical: 10),
separatorBuilder: (_, _) => YBox(10),
itemBuilder: (_, index) {
final slip = customBets.items?[index];
return SwipeActionWidget(
onSwipeAction: () async {
//
},
showInstructions: false,
actionIcon: IconsaxPlusBold.trash,
child: AdviceTile(
hasBeenSwiped: false,
slipInfoItem: SlipInfoItem(
matchId: slip?.id,
advice: slip?.advice,
homeScore: slip?.homeScore,
awayScore: slip?.awayScore,
awayTeamFlag: slip?.awayTeamLogo,
awayTeamName: slip?.awayTeamName,
homeTeamFlag: slip?.homeTeamLogo,
homeTeamName: slip?.homeTeamName,
fixtureId: slip?.fixtureId,
leagueName: slip?.leagueName,
startsOn: slip?.fixtureDatetime,
entered: slip?.entered,
),
),
);
},
).expanded,
Divider(
height: 0,
color: context.colorScheme.onSurfaceVariant.withValues(
alpha: 0.2,
),
),
Padding(
padding: EdgeInsets.symmetric(
vertical: context.isApple ? 0 : 20,
horizontal: 14,
).copyWith(top: 10),
child: Row(
spacing: 10,
children: [
OutlinedButton.icon(
style: OutlinedButton.styleFrom(
textStyle: context.textTheme.labelLarge?.copyWith(
fontWeight: FontWeight.bold,
),
side: BorderSide(
color:
requestState.isLoading
? context.colorScheme.outlineVariant
: context.colorScheme.primary,
),
shape: RoundedSuperellipseBorder(
borderRadius: BorderRadius.circular(8),
),
),
onPressed: onShare,
icon: Icon(IconsaxPlusBold.receipt_2),
label: Text("Share Prediction"),
).withSizedBox(height: 50).expanded,
FilledButton(
onPressed: customBets.save,
style: FilledButton.styleFrom(
textStyle: context.textTheme.labelLarge?.copyWith(
fontWeight: FontWeight.bold,
),
shape: RoundedSuperellipseBorder(
borderRadius: BorderRadius.circular(8),
),
),
child: Text("Save"),
).withSizedBox(height: 50).expanded,
],
),
).withSafeArea(top: false),
],
),
),
),
],
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment