Files
patbond-flutter/lib/widgets/common.dart
T
2026-07-21 17:41:01 +08:00

127 lines
3.0 KiB
Dart

import 'package:flutter/material.dart';
import 'package:patbond_flutter/core/theme/app_theme.dart';
class RemoteImage extends StatelessWidget {
const RemoteImage({
required this.url,
super.key,
this.width,
this.height,
this.fit = BoxFit.cover,
this.borderRadius = BorderRadius.zero,
});
final String url;
final double? width;
final double? height;
final BoxFit fit;
final BorderRadius borderRadius;
@override
Widget build(BuildContext context) {
return ClipRRect(
borderRadius: borderRadius,
child: Image.network(
url,
width: width,
height: height,
fit: fit,
loadingBuilder: (context, child, progress) {
if (progress == null) return child;
return ColoredBox(
color: const Color(0xFFF1F5F9),
child: SizedBox(
width: width,
height: height,
child: const Center(
child: CircularProgressIndicator(strokeWidth: 2),
),
),
);
},
errorBuilder: (context, error, stackTrace) {
return ColoredBox(
color: const Color(0xFFF1F5F9),
child: SizedBox(
width: width,
height: height,
child: const Center(
child: Icon(Icons.pets, color: AppColors.muted, size: 34),
),
),
);
},
),
);
}
}
class SectionCard extends StatelessWidget {
const SectionCard({required this.child, super.key, this.padding});
final Widget child;
final EdgeInsetsGeometry? padding;
@override
Widget build(BuildContext context) {
return Card(
child: Padding(
padding: padding ?? const EdgeInsets.all(18),
child: child,
),
);
}
}
class TagPill extends StatelessWidget {
const TagPill(this.label, {super.key, this.color = AppColors.primary});
final String label;
final Color color;
@override
Widget build(BuildContext context) {
return DecoratedBox(
decoration: BoxDecoration(
color: color.withAlpha(20),
borderRadius: BorderRadius.circular(99),
),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6),
child: Text(
label,
style: TextStyle(
color: color,
fontSize: 11,
fontWeight: FontWeight.w700,
),
),
),
);
}
}
class EmptyState extends StatelessWidget {
const EmptyState({required this.message, super.key});
final String message;
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 48),
child: Column(
children: [
const Icon(
Icons.search_off_rounded,
size: 42,
color: AppColors.muted,
),
const SizedBox(height: 12),
Text(message, style: Theme.of(context).textTheme.bodySmall),
],
),
);
}
}