Last active
November 17, 2025 14:52
-
-
Save abhaysood/8a27c211ec241108f008a21195c63d42 to your computer and use it in GitHub Desktop.
A demo checkout flutter page
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import 'package:flutter/material.dart'; | |
| void main() { | |
| runApp(const MyApp()); | |
| } | |
| class MyApp extends StatelessWidget { | |
| const MyApp({super.key}); | |
| @override | |
| Widget build(BuildContext context) { | |
| return MaterialApp( | |
| title: 'Payment Portal', | |
| theme: ThemeData( | |
| colorScheme: ColorScheme.fromSeed(seedColor: Colors.teal), | |
| useMaterial3: true, | |
| ), | |
| home: const CheckoutScreen(), | |
| debugShowCheckedModeBanner: false, | |
| ); | |
| } | |
| } | |
| class CheckoutScreen extends StatefulWidget { | |
| const CheckoutScreen({super.key}); | |
| @override | |
| State<CheckoutScreen> createState() => _CheckoutScreenState(); | |
| } | |
| class _CheckoutScreenState extends State<CheckoutScreen> { | |
| int selectedDiscount = 0; | |
| bool isOrderExpanded = false; | |
| final List<Map<String, dynamic>> discounts = [ | |
| {'amount': 0, 'points': 0}, | |
| {'amount': 15, 'points': 500}, | |
| {'amount': 30, 'points': 4500}, | |
| ]; | |
| final int balance = 1500; | |
| final double orderTotal = 125.00; | |
| final int earnRate = 12; | |
| final int pointsEarned = 1200; | |
| @override | |
| Widget build(BuildContext context) { | |
| return Scaffold( | |
| body: Container( | |
| decoration: const BoxDecoration( | |
| gradient: LinearGradient( | |
| begin: Alignment.topLeft, | |
| end: Alignment.bottomRight, | |
| colors: [Color(0xFF06b6d4), Color(0xFF3b82f6)], | |
| ), | |
| ), | |
| child: SafeArea( | |
| child: Center( | |
| child: Container( | |
| constraints: const BoxConstraints(maxWidth: 400), | |
| margin: const EdgeInsets.all(20), | |
| decoration: BoxDecoration( | |
| color: const Color(0xFF0f172a), | |
| borderRadius: BorderRadius.circular(24), | |
| boxShadow: [ | |
| BoxShadow( | |
| color: Colors.black.withOpacity(0.4), | |
| blurRadius: 60, | |
| offset: const Offset(0, 20), | |
| ), | |
| ], | |
| ), | |
| child: SingleChildScrollView( | |
| child: Padding( | |
| padding: const EdgeInsets.all(20), | |
| child: Column( | |
| crossAxisAlignment: CrossAxisAlignment.start, | |
| children: [ | |
| // Header | |
| _buildHeader(), | |
| const SizedBox(height: 24), | |
| // Account Section | |
| _buildAccountCard(), | |
| const SizedBox(height: 24), | |
| // Discount Selection | |
| const Text( | |
| 'Choose your reward', | |
| style: TextStyle( | |
| color: Colors.white, | |
| fontSize: 18, | |
| fontWeight: FontWeight.w600, | |
| ), | |
| ), | |
| const SizedBox(height: 16), | |
| _buildDiscountOptions(), | |
| const SizedBox(height: 32), | |
| // Order Section | |
| const Text( | |
| 'Purchase Details', | |
| style: TextStyle( | |
| color: Colors.white, | |
| fontSize: 18, | |
| fontWeight: FontWeight.w600, | |
| ), | |
| ), | |
| const SizedBox(height: 16), | |
| _buildOrderCard(), | |
| const SizedBox(height: 16), | |
| // Payment Details | |
| _buildPaymentDetails(), | |
| const SizedBox(height: 32), | |
| // Pay Button | |
| _buildPayButton(), | |
| ], | |
| ), | |
| ), | |
| ), | |
| ), | |
| ), | |
| ), | |
| ), | |
| ); | |
| } | |
| Widget _buildHeader() { | |
| return Row( | |
| mainAxisAlignment: MainAxisAlignment.spaceBetween, | |
| children: [ | |
| IconButton( | |
| icon: const Icon(Icons.close, color: Colors.white, size: 24), | |
| onPressed: () {}, | |
| padding: EdgeInsets.zero, | |
| constraints: const BoxConstraints(), | |
| ), | |
| Row( | |
| children: const [ | |
| Text( | |
| 'Checkout', | |
| style: TextStyle( | |
| color: Colors.white, | |
| fontSize: 18, | |
| fontWeight: FontWeight.w600, | |
| ), | |
| ), | |
| ], | |
| ), | |
| Container( | |
| padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), | |
| decoration: BoxDecoration( | |
| color: const Color(0xFF1e293b), | |
| borderRadius: BorderRadius.circular(16), | |
| ), | |
| child: Row( | |
| children: const [ | |
| Icon(Icons.circle, color: Color(0xFF14b8a6), size: 12), | |
| SizedBox(width: 6), | |
| Text( | |
| '28,750', | |
| style: TextStyle(color: Colors.white, fontSize: 14), | |
| ), | |
| ], | |
| ), | |
| ), | |
| ], | |
| ); | |
| } | |
| Widget _buildAccountCard() { | |
| return Container( | |
| padding: const EdgeInsets.all(16), | |
| decoration: BoxDecoration( | |
| color: const Color(0xFF1e293b), | |
| borderRadius: BorderRadius.circular(16), | |
| ), | |
| child: Row( | |
| children: [ | |
| const Text('🇺🇸', style: TextStyle(fontSize: 32)), | |
| const SizedBox(width: 12), | |
| Expanded( | |
| child: Column( | |
| crossAxisAlignment: CrossAxisAlignment.start, | |
| children: [ | |
| const Text( | |
| 'Premium · USD', | |
| style: TextStyle( | |
| color: Colors.white, | |
| fontSize: 16, | |
| fontWeight: FontWeight.w500, | |
| ), | |
| ), | |
| const SizedBox(height: 4), | |
| Text( | |
| 'Available: \$${balance.toString()}', | |
| style: const TextStyle( | |
| color: Color(0xFF94a3b8), | |
| fontSize: 14, | |
| ), | |
| ), | |
| ], | |
| ), | |
| ), | |
| ], | |
| ), | |
| ); | |
| } | |
| Widget _buildDiscountOptions() { | |
| return Row( | |
| children: List.generate( | |
| discounts.length, | |
| (index) => Expanded( | |
| child: Padding( | |
| padding: EdgeInsets.only( | |
| right: index < discounts.length - 1 ? 12 : 0, | |
| ), | |
| child: GestureDetector( | |
| onTap: () { | |
| setState(() { | |
| selectedDiscount = index; | |
| }); | |
| }, | |
| child: Container( | |
| padding: const EdgeInsets.symmetric( | |
| horizontal: 12, | |
| vertical: 16, | |
| ), | |
| decoration: BoxDecoration( | |
| color: selectedDiscount == index | |
| ? const Color(0xFF134e4a) | |
| : const Color(0xFF1e293b), | |
| border: Border.all( | |
| color: selectedDiscount == index | |
| ? const Color(0xFF14b8a6) | |
| : Colors.transparent, | |
| width: 2, | |
| ), | |
| borderRadius: BorderRadius.circular(16), | |
| ), | |
| child: Column( | |
| children: [ | |
| Text( | |
| '\$${discounts[index]['amount']} off', | |
| style: const TextStyle( | |
| color: Colors.white, | |
| fontSize: 16, | |
| fontWeight: FontWeight.w600, | |
| ), | |
| ), | |
| const SizedBox(height: 8), | |
| Row( | |
| mainAxisAlignment: MainAxisAlignment.center, | |
| children: [ | |
| const Icon( | |
| Icons.circle, | |
| color: Color(0xFF14b8a6), | |
| size: 12, | |
| ), | |
| const SizedBox(width: 4), | |
| Text( | |
| discounts[index]['points'].toString(), | |
| style: const TextStyle( | |
| color: Color(0xFF94a3b8), | |
| fontSize: 14, | |
| ), | |
| ), | |
| ], | |
| ), | |
| ], | |
| ), | |
| ), | |
| ), | |
| ), | |
| ), | |
| ), | |
| ); | |
| } | |
| Widget _buildOrderCard() { | |
| return GestureDetector( | |
| onTap: () { | |
| setState(() { | |
| isOrderExpanded = !isOrderExpanded; | |
| }); | |
| }, | |
| child: Container( | |
| padding: const EdgeInsets.all(16), | |
| decoration: BoxDecoration( | |
| color: const Color(0xFF1e293b), | |
| borderRadius: BorderRadius.circular(16), | |
| ), | |
| child: Row( | |
| children: [ | |
| const Text('🛒', style: TextStyle(fontSize: 28)), | |
| const SizedBox(width: 12), | |
| Expanded( | |
| child: Column( | |
| crossAxisAlignment: CrossAxisAlignment.start, | |
| children: [ | |
| Row( | |
| children: [ | |
| const Text( | |
| 'Transaction Details', | |
| style: TextStyle( | |
| color: Colors.white, | |
| fontSize: 16, | |
| fontWeight: FontWeight.w500, | |
| ), | |
| ), | |
| const SizedBox(width: 6), | |
| Icon( | |
| isOrderExpanded | |
| ? Icons.keyboard_arrow_up | |
| : Icons.keyboard_arrow_down, | |
| color: const Color(0xFF94a3b8), | |
| size: 16, | |
| ), | |
| ], | |
| ), | |
| const SizedBox(height: 4), | |
| const Text( | |
| 'TechMart Inc.', | |
| style: TextStyle(color: Color(0xFF94a3b8), fontSize: 14), | |
| ), | |
| ], | |
| ), | |
| ), | |
| Text( | |
| '\$${orderTotal.toStringAsFixed(2)}', | |
| style: const TextStyle( | |
| color: Colors.white, | |
| fontSize: 18, | |
| fontWeight: FontWeight.w600, | |
| ), | |
| ), | |
| ], | |
| ), | |
| ), | |
| ); | |
| } | |
| Widget _buildPaymentDetails() { | |
| return Column( | |
| children: [ | |
| // Pay row | |
| Container( | |
| padding: const EdgeInsets.all(16), | |
| decoration: const BoxDecoration( | |
| color: Color(0xFF1e293b), | |
| borderRadius: BorderRadius.only( | |
| topLeft: Radius.circular(16), | |
| topRight: Radius.circular(16), | |
| ), | |
| ), | |
| child: Row( | |
| mainAxisAlignment: MainAxisAlignment.spaceBetween, | |
| children: [ | |
| const Text( | |
| 'Total Amount', | |
| style: TextStyle(color: Colors.white, fontSize: 16), | |
| ), | |
| Text( | |
| '\$${orderTotal.toStringAsFixed(2)}', | |
| style: const TextStyle( | |
| color: Colors.white, | |
| fontSize: 16, | |
| fontWeight: FontWeight.w600, | |
| ), | |
| ), | |
| ], | |
| ), | |
| ), | |
| const SizedBox(height: 2), | |
| // Earn rate row | |
| Container( | |
| padding: const EdgeInsets.all(16), | |
| color: const Color(0xFF1e293b), | |
| child: Row( | |
| mainAxisAlignment: MainAxisAlignment.spaceBetween, | |
| children: [ | |
| const Text( | |
| 'Cashback Rate', | |
| style: TextStyle(color: Colors.white, fontSize: 16), | |
| ), | |
| Container( | |
| padding: const EdgeInsets.symmetric( | |
| horizontal: 12, | |
| vertical: 4, | |
| ), | |
| decoration: BoxDecoration( | |
| color: const Color(0xFF0d9488), | |
| borderRadius: BorderRadius.circular(12), | |
| ), | |
| child: Text( | |
| '${earnRate}%', | |
| style: const TextStyle( | |
| color: Colors.white, | |
| fontSize: 14, | |
| fontWeight: FontWeight.w600, | |
| ), | |
| ), | |
| ), | |
| ], | |
| ), | |
| ), | |
| const SizedBox(height: 2), | |
| // Points you earn row | |
| Container( | |
| padding: const EdgeInsets.all(16), | |
| decoration: const BoxDecoration( | |
| color: Color(0xFF1e293b), | |
| borderRadius: BorderRadius.only( | |
| bottomLeft: Radius.circular(16), | |
| bottomRight: Radius.circular(16), | |
| ), | |
| ), | |
| child: Row( | |
| mainAxisAlignment: MainAxisAlignment.spaceBetween, | |
| children: [ | |
| const Text( | |
| 'Points Balance', | |
| style: TextStyle(color: Colors.white, fontSize: 16), | |
| ), | |
| Row( | |
| children: [ | |
| const Icon(Icons.circle, color: Color(0xFF14b8a6), size: 12), | |
| const SizedBox(width: 6), | |
| Text( | |
| pointsEarned.toString(), | |
| style: const TextStyle( | |
| color: Colors.white, | |
| fontSize: 16, | |
| fontWeight: FontWeight.w600, | |
| ), | |
| ), | |
| ], | |
| ), | |
| ], | |
| ), | |
| ), | |
| ], | |
| ); | |
| } | |
| Widget _buildPayButton() { | |
| return SizedBox( | |
| width: double.infinity, | |
| child: ElevatedButton( | |
| onPressed: () {}, | |
| style: ElevatedButton.styleFrom( | |
| backgroundColor: const Color(0xFF14b8a6), | |
| foregroundColor: Colors.white, | |
| padding: const EdgeInsets.symmetric(vertical: 18), | |
| shape: RoundedRectangleBorder( | |
| borderRadius: BorderRadius.circular(28), | |
| ), | |
| elevation: 0, | |
| ), | |
| child: Text( | |
| 'Pay Now', | |
| style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w600), | |
| ), | |
| ), | |
| ); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment