proxibuy/lib/presentation/offer/bloc/widgets/offer_card.dart

159 lines
4.6 KiB
Dart

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<OfferCard> createState() => _OfferCardState();
}
class _OfferCardState extends State<OfferCard> {
@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: [
Hero(
tag: 'offer_image_${widget.offer.id}',
child: _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(
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(
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),
Flexible(
child: Text(
'نوع تخفیف : ${(100 - widget.offer.finalPrice / widget.offer.originalPrice * 100).toInt()}% ${widget.offer.discountType}',
style: const TextStyle(
color: Color.fromARGB(255, 183, 28, 28), fontSize: 13),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
),
],
),
],
),
);
}
}