diff --git a/lib/widgets/car_card.dart b/lib/widgets/car_card.dart index a01a0e7..baa40a3 100644 --- a/lib/widgets/car_card.dart +++ b/lib/widgets/car_card.dart @@ -4,7 +4,7 @@ import '../services/storage_service.dart'; import '../theme/app_colors.dart'; /// A styled card for displaying a single die-cast car in the garage. -class CarCard extends StatelessWidget { +class CarCard extends StatefulWidget { final String hwId; final String? name; final String? series; @@ -36,22 +36,50 @@ class CarCard extends StatelessWidget { this.isSelected = false, }); + @override + State createState() => _CarCardState(); +} + +class _CarCardState extends State { + Future? _signedUrlFuture; + + @override + void initState() { + super.initState(); + _initSignedUrlFuture(); + } + + @override + void didUpdateWidget(CarCard oldWidget) { + super.didUpdateWidget(oldWidget); + if (oldWidget.imagePath != widget.imagePath) { + _initSignedUrlFuture(); + } + } + + void _initSignedUrlFuture() { + final hasImagePath = widget.imagePath != null && widget.imagePath!.isNotEmpty; + _signedUrlFuture = hasImagePath + ? StorageService.createSignedUrl(widget.imagePath!) + : null; + } + @override Widget build(BuildContext context) { final theme = Theme.of(context); final isDark = theme.brightness == Brightness.dark; - final resolvedImageUrl = imageUrl; + final resolvedImageUrl = widget.imageUrl; final hasResolvedUrl = resolvedImageUrl != null && resolvedImageUrl.isNotEmpty; - final hasImagePath = imagePath != null && imagePath!.isNotEmpty; + final hasImagePath = widget.imagePath != null && widget.imagePath!.isNotEmpty; return Card( clipBehavior: Clip.antiAlias, - color: isSelected + color: widget.isSelected ? AppColors.orange.withValues(alpha: 0.18) : Theme.of(context).cardTheme.color, child: InkWell( - onTap: onTap, - onLongPress: onLongPress, + onTap: widget.onTap, + onLongPress: widget.onLongPress, borderRadius: BorderRadius.circular(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -79,13 +107,13 @@ class CarCard extends StatelessWidget { fadeInDuration: Duration.zero, fadeOutDuration: Duration.zero, errorWidget: (context, url, error) { - onImageError?.call(); + widget.onImageError?.call(); return _PlaceholderIcon(isDark: isDark); }, ) : hasImagePath ? FutureBuilder( - future: StorageService.createSignedUrl(imagePath), + future: _signedUrlFuture, builder: (context, snapshot) { final signedUrl = snapshot.data; if (signedUrl == null || signedUrl.isEmpty) { @@ -97,7 +125,7 @@ class CarCard extends StatelessWidget { fadeInDuration: Duration.zero, fadeOutDuration: Duration.zero, errorWidget: (context, url, error) { - onImageError?.call(); + widget.onImageError?.call(); return _PlaceholderIcon(isDark: isDark); }, ); @@ -113,7 +141,7 @@ class CarCard extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - if (isSelected) + if (widget.isSelected) Padding( padding: const EdgeInsets.only(bottom: 6), child: Row( @@ -141,7 +169,7 @@ class CarCard extends StatelessWidget { borderRadius: BorderRadius.circular(6), ), child: Text( - hwId, + widget.hwId, style: const TextStyle( fontSize: 13, fontWeight: FontWeight.w700, @@ -154,19 +182,19 @@ class CarCard extends StatelessWidget { Row( children: [ Icon( - isVerified + widget.isVerified ? Icons.verified : Icons.hourglass_bottom, size: 12, - color: isVerified + color: widget.isVerified ? AppColors.success : AppColors.textHint, ), const SizedBox(width: 4), Text( - isVerified ? 'Verified' : 'Pending', + widget.isVerified ? 'Verified' : 'Pending', style: theme.textTheme.bodySmall?.copyWith( - color: isVerified + color: widget.isVerified ? AppColors.success : AppColors.textHint, fontWeight: FontWeight.w600, @@ -174,10 +202,10 @@ class CarCard extends StatelessWidget { ), ], ), - if (name != null && name!.isNotEmpty) ...[ + if (widget.name != null && widget.name!.isNotEmpty) ...[ const SizedBox(height: 6), Text( - name!, + widget.name!, maxLines: 1, overflow: TextOverflow.ellipsis, style: theme.textTheme.titleSmall?.copyWith( @@ -185,10 +213,10 @@ class CarCard extends StatelessWidget { ), ), ], - if (series != null && series!.isNotEmpty) ...[ + if (widget.series != null && widget.series!.isNotEmpty) ...[ const SizedBox(height: 2), Text( - series!, + widget.series!, maxLines: 1, overflow: TextOverflow.ellipsis, style: theme.textTheme.bodySmall?.copyWith( @@ -196,7 +224,7 @@ class CarCard extends StatelessWidget { ), ), ], - if (year != null) ...[ + if (widget.year != null) ...[ const SizedBox(height: 4), Row( children: [ @@ -204,7 +232,7 @@ class CarCard extends StatelessWidget { size: 12, color: AppColors.textHint), const SizedBox(width: 4), Text( - '$year', + '${widget.year}', style: theme.textTheme.bodySmall?.copyWith( color: AppColors.textHint, ),