added payment api for passes and more
This commit is contained in:
@@ -5,8 +5,6 @@ import '../../common_packages/app_bar.dart';
|
||||
import '../../common_packages/back_widget.dart';
|
||||
import '../models/my_postcard_model.dart';
|
||||
import '../../networkApiServices/api_urls.dart';
|
||||
import '../widgets/back_card_widget.dart';
|
||||
import '../widgets/front_card_widget.dart';
|
||||
|
||||
class MyPostcardPreviewView extends StatefulWidget {
|
||||
final MyPostCard postcard;
|
||||
@@ -40,9 +38,8 @@ class _MyPostcardPreviewViewState extends State<MyPostcardPreviewView> {
|
||||
),
|
||||
backWidget(context, "Preview", Colors.black),
|
||||
|
||||
SizedBox(height: 20.h),
|
||||
|
||||
// ================= POSTCARD NUMBER + ACTIONS =================
|
||||
SizedBox(height: 29.h),
|
||||
// Postcard Number with Action Icons
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 20.w),
|
||||
child: Row(
|
||||
@@ -58,83 +55,97 @@ class _MyPostcardPreviewViewState extends State<MyPostcardPreviewView> {
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Image.asset(
|
||||
'assets/icons/delete_icon.png',
|
||||
width: 24,
|
||||
height: 24,
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
// Delete functionality
|
||||
},
|
||||
child: Image.asset(
|
||||
'assets/icons/delete_icon.png',
|
||||
width: 24,
|
||||
height: 24,
|
||||
),
|
||||
),
|
||||
SizedBox(width: 16.w),
|
||||
Image.asset(
|
||||
'assets/icons/edit_icon.png',
|
||||
width: 24,
|
||||
height: 24,
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
// Edit functionality
|
||||
},
|
||||
child: Image.asset(
|
||||
'assets/icons/edit_icon.png',
|
||||
width: 24,
|
||||
height: 24,
|
||||
),
|
||||
),
|
||||
SizedBox(width: 16.w),
|
||||
Image.asset(
|
||||
'assets/icons/send_icon.png',
|
||||
width: 24,
|
||||
height: 24,
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
// Send functionality
|
||||
},
|
||||
child: Image.asset(
|
||||
'assets/icons/send_icon.png',
|
||||
width: 24,
|
||||
height: 24,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(height: 20.h),
|
||||
|
||||
SizedBox(height: 16.h),
|
||||
|
||||
// ================= FLIP BUTTONS =================
|
||||
// Flip buttons
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 20.w),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () => setState(() => showBack = false),
|
||||
onTap: () {
|
||||
setState(() {
|
||||
showBack = false;
|
||||
});
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.arrow_back,
|
||||
color: !showBack ? const Color(0xffF95F62) : Colors.grey[400],
|
||||
size: 20,
|
||||
color: !showBack
|
||||
? const Color(0xffF95F62)
|
||||
: Colors.grey[400],
|
||||
),
|
||||
SizedBox(width: 6.w),
|
||||
Text(
|
||||
'Flip',
|
||||
style: GoogleFonts.poppins(
|
||||
color: !showBack ? const Color(0xffF95F62) : Colors.grey[400],
|
||||
fontSize: 14.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: !showBack
|
||||
? const Color(0xffF95F62)
|
||||
: Colors.grey[400],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () => setState(() => showBack = true),
|
||||
onTap: () {
|
||||
setState(() {
|
||||
showBack = true;
|
||||
});
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
'Flip',
|
||||
style: GoogleFonts.poppins(
|
||||
color: showBack ? const Color(0xffF95F62) : Colors.grey[400],
|
||||
fontSize: 14.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: showBack
|
||||
? const Color(0xffF95F62)
|
||||
: Colors.grey[400],
|
||||
),
|
||||
),
|
||||
SizedBox(width: 6.w),
|
||||
Icon(
|
||||
Icons.arrow_forward,
|
||||
color: showBack ? const Color(0xffF95F62) : Colors.grey[400],
|
||||
size: 20,
|
||||
color: showBack
|
||||
? const Color(0xffF95F62)
|
||||
: Colors.grey[400],
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -143,41 +154,285 @@ class _MyPostcardPreviewViewState extends State<MyPostcardPreviewView> {
|
||||
),
|
||||
),
|
||||
|
||||
// ================= POSTCARD =================
|
||||
// Postcard Display
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(top: 40.h),
|
||||
child: Align(
|
||||
alignment: Alignment.topCenter,
|
||||
child: AnimatedSwitcher(
|
||||
duration: const Duration(milliseconds: 400),
|
||||
transitionBuilder: (child, animation) {
|
||||
return FadeTransition(
|
||||
opacity: animation,
|
||||
child: child,
|
||||
);
|
||||
},
|
||||
child: showBack
|
||||
? BackCardWidget(
|
||||
key: const ValueKey('back'),
|
||||
message: widget.postcard.pcContent,
|
||||
city: widget.postcard.cityName,
|
||||
state: widget.postcard.stateName,
|
||||
country: widget.postcard.countryName,
|
||||
)
|
||||
: FrontCardWidget(
|
||||
key: const ValueKey('front'),
|
||||
imageUrl:
|
||||
'${ApiUrls.baseUrl}${widget.postcard.pcImagePath}',
|
||||
),
|
||||
),
|
||||
child: Center(
|
||||
child: AnimatedSwitcher(
|
||||
duration: const Duration(milliseconds: 400),
|
||||
transitionBuilder: (Widget child, Animation<double> animation) {
|
||||
return FadeTransition(
|
||||
opacity: animation,
|
||||
child: child,
|
||||
);
|
||||
},
|
||||
child: showBack ? _buildBackSide() : _buildFrontSide(),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 40.h),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildFrontSide() {
|
||||
return Container(
|
||||
key: const ValueKey('front'),
|
||||
margin: EdgeInsets.symmetric(horizontal: 20.w),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.1),
|
||||
blurRadius: 10,
|
||||
offset: const Offset(0, 4),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
child: AspectRatio(
|
||||
aspectRatio: 1.5, // Standard postcard ratio
|
||||
child: Image.network(
|
||||
'${ApiUrls.baseUrl}${widget.postcard.pcImagePath}',
|
||||
fit: BoxFit.cover,
|
||||
loadingBuilder: (context, child, loadingProgress) {
|
||||
if (loadingProgress == null) return child;
|
||||
return Container(
|
||||
color: Colors.grey[300],
|
||||
child: Center(
|
||||
child: CircularProgressIndicator(
|
||||
color: const Color(0xffF95F62),
|
||||
value: loadingProgress.expectedTotalBytes != null
|
||||
? loadingProgress.cumulativeBytesLoaded /
|
||||
loadingProgress.expectedTotalBytes!
|
||||
: null,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
errorBuilder: (context, error, stackTrace) {
|
||||
return Container(
|
||||
color: Colors.grey[300],
|
||||
child: const Center(
|
||||
child: Icon(
|
||||
Icons.image_not_supported,
|
||||
size: 60,
|
||||
color: Colors.grey,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildBackSide() {
|
||||
return Container(
|
||||
key: const ValueKey('back'),
|
||||
margin: EdgeInsets.symmetric(horizontal: 20.w),
|
||||
decoration: BoxDecoration(
|
||||
gradient: const LinearGradient(
|
||||
colors: [
|
||||
Color(0xffE2D6C2),
|
||||
Color(0xffFFF5E6),
|
||||
Color(0xffFFF5E6),
|
||||
],
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
),
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
border: Border.all(
|
||||
color: const Color(0xff000000).withOpacity(0.12),
|
||||
width: 1,
|
||||
),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.08),
|
||||
blurRadius: 10,
|
||||
offset: const Offset(0, 4),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: AspectRatio(
|
||||
aspectRatio: 1.5,
|
||||
child: Row(
|
||||
children: [
|
||||
// ================= LEFT SIDE =================
|
||||
Expanded(
|
||||
flex: 55,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 14.h),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// Logo
|
||||
Image.asset(
|
||||
'assets/logo/logo_city_cards.png',
|
||||
height: 24.h, // adjust as needed
|
||||
fit: BoxFit.contain,
|
||||
),
|
||||
SizedBox(height: 2.h),
|
||||
Text(
|
||||
'POSTCARD',
|
||||
style: TextStyle(
|
||||
color: Colors.black45,
|
||||
fontSize: 6.sp,
|
||||
letterSpacing: 1.4,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
|
||||
SizedBox(height: 14.h),
|
||||
|
||||
// Message label
|
||||
Text(
|
||||
'MESSAGE PREVIEW',
|
||||
style: TextStyle(
|
||||
color: Colors.black,
|
||||
fontSize: 6.sp,
|
||||
letterSpacing: 1.4,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 8.h),
|
||||
|
||||
// Message text
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
child: Text(
|
||||
widget.postcard.pcContent,
|
||||
style: TextStyle(
|
||||
color: Colors.black87,
|
||||
fontSize: 13.sp,
|
||||
height: 1.45,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
SizedBox(height: 10.h),
|
||||
|
||||
// Footer
|
||||
Text(
|
||||
'CityCards.co',
|
||||
style: TextStyle(
|
||||
color: const Color(0xffF95F62),
|
||||
fontSize: 12.sp,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
// ================= DIVIDER =================
|
||||
Container(
|
||||
width: 4,
|
||||
margin: EdgeInsets.symmetric(vertical: 14.h),
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
colors: [
|
||||
Colors.black.withOpacity(0.05),
|
||||
Colors.black.withOpacity(0.30),
|
||||
Colors.black.withOpacity(0.05),
|
||||
],
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
// ================= RIGHT SIDE =================
|
||||
Expanded(
|
||||
flex: 45,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 14.w, vertical: 14.h),
|
||||
child: Column(
|
||||
children: [
|
||||
const Spacer(),
|
||||
|
||||
// Address with BORDER
|
||||
Container(
|
||||
width: double.infinity,
|
||||
padding: EdgeInsets.all(4.w),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
border: Border.all(
|
||||
color: Colors.black.withOpacity(0.15),
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
// ADDRESS label
|
||||
Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(
|
||||
'ADDRESS',
|
||||
style: TextStyle(
|
||||
color: Colors.black45,
|
||||
fontSize: 7.5.sp,
|
||||
letterSpacing: 1.6,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
SizedBox(height: 6.h),
|
||||
|
||||
// Address line 1
|
||||
Text(
|
||||
'${widget.postcard.cityName},',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: Colors.black87,
|
||||
fontSize: 13.sp,
|
||||
height: 1.5,
|
||||
),
|
||||
),
|
||||
|
||||
SizedBox(height: 6.h),
|
||||
|
||||
// State
|
||||
Text(
|
||||
'${widget.postcard.stateName},',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: Colors.black87,
|
||||
fontSize: 13.sp,
|
||||
height: 1.5,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 6.h),
|
||||
// Country
|
||||
Text(
|
||||
widget.postcard.countryName,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: Colors.black87,
|
||||
fontSize: 13.sp,
|
||||
height: 1.5,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
const Spacer(),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user