import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:proxibuy/core/gen/assets.gen.dart'; import 'package:proxibuy/data/models/offer_model.dart'; class OfferCard extends StatefulWidget { final OfferModel offer; final VoidCallback? onTap; final double width; const OfferCard({ super.key, required this.offer, this.onTap, this.width = 150, }); @override State createState() => _OfferCardState(); } class _OfferCardState extends State { @override Widget build(BuildContext context) { final textTheme = Theme.of(context).textTheme; return SizedBox( width: 270, child: GestureDetector( onTap: widget.onTap, child: Padding( padding: const EdgeInsets.only(bottom: 10), child: Column( children: [ Stack(children: [_buildOfferImage()]), _buildInfoContainer(textTheme), ], ), ), ), ); } Widget _buildOfferImage() { return ClipRRect( borderRadius: const BorderRadius.only( topLeft: Radius.circular(12), topRight: Radius.circular(12), ), child: CachedNetworkImage( imageUrl: widget.offer.coverImageUrl, height: 140, width: double.infinity, fit: BoxFit.cover, placeholder: (context, url) => Container( height: 140, color: Colors.grey[300], child: const Center(child: CircularProgressIndicator()), ), errorWidget: (context, url, error) => Container( height: 140, color: Colors.grey[300], child: const Icon(Icons.broken_image, color: Colors.grey), ), ), ); } Widget _buildInfoContainer(TextTheme textTheme) { return Container( padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: Colors.white, borderRadius: const BorderRadius.only( bottomLeft: Radius.circular(12), bottomRight: Radius.circular(12), ), boxShadow: [ BoxShadow( // ignore: deprecated_member_use color: Colors.grey.withOpacity(0.2), spreadRadius: 2, blurRadius: 5, offset: const Offset(0, 3), ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ SvgPicture.asset(Assets.icons.shop.path), const SizedBox(width: 4), Text( widget.offer.storeName, style: textTheme.titleMedium?.copyWith( fontWeight: FontWeight.bold, ), ), ], ), const SizedBox(height: 8), Row( children: [ SvgPicture.asset(Assets.icons.shoppingCart.path), const SizedBox(width: 4), Text( widget.offer.title, style: textTheme.bodySmall, maxLines: 1, overflow: TextOverflow.ellipsis, ), ], ), const SizedBox(height: 10), // ================== شروع تغییرات ================== Row( children: [ SvgPicture.asset(Assets.icons.location.path), const SizedBox(width: 4), // ویجت Flexible باعث می‌شود که آدرس، فضای باقی‌مانده را پر کند // و در صورت طولانی بودن، کوتاه شود. Flexible( child: Text( widget.offer.address, style: textTheme.bodySmall, maxLines: 1, overflow: TextOverflow.ellipsis, // نمایش سه نقطه در انتهای متن طولانی ), ), const SizedBox(width: 4), // این بخش همیشه به طور کامل نمایش داده می‌شود Text( '(${widget.offer.distanceInMeters.toString()}متر تا تخفیف)', style: textTheme.bodySmall, ), ], ), const SizedBox(height: 10), Row( children: [ SvgPicture.asset(Assets.icons.routing.path), const SizedBox(width: 4), Text( 'نوع تخفیف : ${widget.offer.discount} ${widget.offer.discountType}', style: const TextStyle(color: Color.fromARGB(255, 183, 28, 28),fontSize: 14), maxLines: 1, overflow: TextOverflow.ellipsis, ), ], ), ], ), ); } }