Files
CityCards_Customer_Flutter/lib/attractions/widget/attraction_card.dart

173 lines
5.6 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:google_fonts/google_fonts.dart';
import '../../common_packages/common_app_texts.dart';
import '../../core/route_constants.dart';
import '../models/attraction_model.dart';
class AttractionCard extends StatelessWidget {
final Attraction attraction;
const AttractionCard({super.key, required this.attraction});
@override
Widget build(BuildContext context) {
/// CARD TITLES (instead of categories)
final List<String> tags = attraction.cards
.map((e) => e.title)
.where((e) => e.isNotEmpty)
.toList();
/// GALLERY IMAGE (handled safely in model)
final String imageUrl = attraction.coverImageUrl;
return InkWell(
onTap: () {
Navigator.of(context).pushNamed(
RouteConstants.attractionDetails,
arguments: attraction.id,
);
},
child: Container(
margin: EdgeInsets.symmetric(vertical: 8.h, horizontal: 8.w),
padding: EdgeInsets.all(12.w),
decoration: BoxDecoration(
border: Border.all(color: const Color(0xffFDCDCE)),
borderRadius: BorderRadius.circular(15.r),
color: const Color(0xffFFF5F5),
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
/// IMAGE (network with fallback)
ClipRRect(
borderRadius: BorderRadius.circular(8.r),
child: imageUrl.isNotEmpty
? Image.network(
imageUrl,
height: 94.h,
width: 94.w,
fit: BoxFit.cover,
errorBuilder: (_, __, ___) => _imageFallback(),
)
: _imageFallback(),
),
SizedBox(width: 10.w),
/// CONTENT
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
attraction.title,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w500,
),
),
SizedBox(height: 6.h),
Text(
attraction.address,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: GoogleFonts.poppins(
fontSize: 12.sp,
fontWeight: FontWeight.w400,
color: const Color(0xff464646),
),
),
SizedBox(height: 6.h),
Text.rich(
TextSpan(
children: [
TextSpan(
text: "\$${attraction.ticketPriceAdult}",
style: TextStyle(
fontSize: 12.sp,
fontWeight: FontWeight.w600,
color: Colors.black,
),
),
TextSpan(
text: "/person",
style: TextStyle(
fontSize: 10.sp,
color: Colors.black,
fontWeight: FontWeight.w400,
),
),
],
),
),
SizedBox(height: 6.h),
/// TAGS (CARD TITLES)
Wrap(
spacing: 6.w,
runSpacing: 6.h,
children: tags
.map(
(tag) => Container(
padding: EdgeInsets.symmetric(
horizontal: 10.w,
vertical: 4.h,
),
decoration: BoxDecoration(
color: tag ==
"${CommonAppText.selectiveCard} Card"
? const Color(0xffF95FAF)
.withOpacity(0.1)
: const Color(0xffF95F62)
.withOpacity(0.1),
border: Border.all(
color: tag ==
"${CommonAppText.selectiveCard} Card"
? const Color(0xffF95FAF)
: const Color(0xffF95F62),
),
borderRadius:
BorderRadius.circular(20.r),
),
child: Text(
tag,
style: GoogleFonts.poppins(
fontSize: 11.sp,
color: const Color(0xff1A1A1A),
fontWeight: FontWeight.w400,
),
),
),
)
.toList(),
)
],
),
),
],
),
),
);
}
/// SAME PLACEHOLDER AS BEFORE
Widget _imageFallback() {
return Container(
height: 94.h,
width: 94.w,
color: Colors.grey.shade200,
child: Icon(
Icons.image_not_supported_outlined,
size: 28.sp,
color: Colors.grey,
),
);
}
}