4d936d2ee3
App Flutter de gestion de stock/prix pour tablette Android (100% local) : scan code-barres (OpenFoodFacts), prix au kilo/litre, packs, inventaire, prix d'achat + marge, filtres de tri, étiquettes PDF, design noir & blanc. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
63 lines
1.7 KiB
Dart
63 lines
1.7 KiB
Dart
import 'dart:io';
|
|
|
|
import 'package:cached_network_image/cached_network_image.dart';
|
|
import 'package:flutter/material.dart';
|
|
|
|
import '../services/photo_service.dart';
|
|
|
|
/// Vignette d'image produit : photo locale, image web (OpenFoodFacts) ou icône par défaut.
|
|
class ProduitImage extends StatelessWidget {
|
|
final String? url;
|
|
final double taille;
|
|
final double radius;
|
|
|
|
const ProduitImage({
|
|
super.key,
|
|
required this.url,
|
|
this.taille = 52,
|
|
this.radius = 12,
|
|
});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final scheme = Theme.of(context).colorScheme;
|
|
return ClipRRect(
|
|
borderRadius: BorderRadius.circular(radius),
|
|
child: Container(
|
|
width: taille,
|
|
height: taille,
|
|
color: scheme.surfaceContainerHighest,
|
|
child: _contenu(scheme),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _contenu(ColorScheme scheme) {
|
|
if (url == null || url!.isEmpty) {
|
|
return Icon(Icons.image_outlined,
|
|
color: scheme.onSurfaceVariant, size: taille * 0.42);
|
|
}
|
|
if (PhotoService.estLocale(url)) {
|
|
return Image.file(
|
|
File(url!),
|
|
fit: BoxFit.cover,
|
|
errorBuilder: (_, _, _) => Icon(Icons.broken_image_outlined,
|
|
color: scheme.onSurfaceVariant, size: taille * 0.42),
|
|
);
|
|
}
|
|
return CachedNetworkImage(
|
|
imageUrl: url!,
|
|
fit: BoxFit.cover,
|
|
placeholder: (_, _) => const Center(
|
|
child: SizedBox(
|
|
width: 18,
|
|
height: 18,
|
|
child: CircularProgressIndicator(strokeWidth: 2),
|
|
),
|
|
),
|
|
errorWidget: (_, _, _) => Icon(Icons.broken_image_outlined,
|
|
color: scheme.onSurfaceVariant, size: taille * 0.42),
|
|
);
|
|
}
|
|
}
|