import 'dart:io'; import 'package:flutter/material.dart'; class VehicleImagePicker extends StatelessWidget { final dynamic images; // Can be List or File? final Function(int) onImagePick; final String? title; final int maxImages; const VehicleImagePicker({ Key? key, required this.images, required this.onImagePick, this.title, this.maxImages = 4, }) : super(key: key); // Helper method to safely get image list List get _imageList { if (images is List) { return images as List; } else if (images is List) { // Handle List case return (images as List).cast(); } else if (images is File?) { // Single file case - convert to list return [images as File?]; } else { // Default case - return empty list with proper size return List.filled(maxImages, null); } } // Helper method to get max image count int get _maxImageCount { if (images is List) { return maxImages; } else { return 1; // Single image case } } // Helper method to check if this is a single image picker bool get _isSingleImage { return images is File? && images is! List; } @override Widget build(BuildContext context) { return Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: Colors.grey.withOpacity(0.1), spreadRadius: 1, blurRadius: 6, offset: const Offset(0, 2), ), ], ), padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ if (title != null) ...[ Text( title!, style: const TextStyle( fontSize: 16, fontWeight: FontWeight.w500, color: Colors.black87, ), ), const SizedBox(height: 12), ], _isSingleImage ? _buildSingleImage() : _buildImageGrid(), ], ), ); } Widget _buildSingleImage() { final File? singleImage = images as File?; return GestureDetector( onTap: () => onImagePick(0), child: Container( height: 120, width: double.infinity, decoration: BoxDecoration( border: Border.all( color: Colors.grey.shade300, style: BorderStyle.solid, width: 1, ), borderRadius: BorderRadius.circular(8), color: Colors.grey.shade50, ), child: singleImage != null ? ClipRRect( borderRadius: BorderRadius.circular(8), child: Image.file( singleImage, fit: BoxFit.cover, ), ) : const Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.add_photo_alternate_outlined, size: 32, color: Colors.grey, ), SizedBox(height: 8), Text( 'Tap to add photo', style: TextStyle( color: Colors.grey, fontSize: 14, ), ), ], ), ), ); } Widget _buildImageGrid() { final imageList = _imageList; final maxCount = _maxImageCount; return GridView.builder( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, crossAxisSpacing: 12, mainAxisSpacing: 12, childAspectRatio: 1.2, ), itemCount: maxCount, itemBuilder: (context, index) { final bool hasImage = index < imageList.length && imageList[index] != null; return GestureDetector( onTap: () => onImagePick(index), child: Container( decoration: BoxDecoration( border: Border.all( color: Colors.grey.shade300, style: BorderStyle.solid, width: 1, ), borderRadius: BorderRadius.circular(8), color: Colors.grey.shade50, ), child: hasImage ? ClipRRect( borderRadius: BorderRadius.circular(8), child: Stack( children: [ Image.file( imageList[index]!, fit: BoxFit.cover, width: double.infinity, height: double.infinity, ), Positioned( top: 4, right: 4, child: GestureDetector( onTap: () => _removeImage(index), child: Container( padding: const EdgeInsets.all(2), decoration: const BoxDecoration( color: Colors.red, shape: BoxShape.circle, ), child: const Icon( Icons.close, color: Colors.white, size: 16, ), ), ), ), ], ), ) : const Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.add_photo_alternate_outlined, size: 32, color: Colors.grey, ), SizedBox(height: 8), Text( 'Add Photo', style: TextStyle( color: Colors.grey, fontSize: 12, ), ), ], ), ), ); }, ); } void _removeImage(int index) { // This would need to be handled by the parent widget // You might want to add an onImageRemove callback } }