product and category loader

This commit is contained in:
efrilm
2025-10-25 00:13:43 +07:00
parent 7bcf54c555
commit 754048b565
16 changed files with 712 additions and 6 deletions
@@ -0,0 +1,47 @@
import 'package:flutter/material.dart';
import '../button/button.dart';
class ErrorCard extends StatelessWidget {
final String title;
final String message;
final Function() onTap;
const ErrorCard({
super.key,
required this.title,
required this.message,
required this.onTap,
});
@override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.error_outline, size: 48, color: Colors.red.shade400),
SizedBox(height: 16),
Text(
title,
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600),
),
SizedBox(height: 8),
Padding(
padding: EdgeInsets.symmetric(horizontal: 32),
child: Text(
message,
textAlign: TextAlign.center,
style: TextStyle(color: Colors.grey.shade600),
),
),
SizedBox(height: 16),
AppElevatedButton.filled(
width: 120,
onPressed: onTap,
label: 'Coba Lagi',
),
],
),
);
}
}
@@ -0,0 +1,110 @@
import 'package:flutter/material.dart';
import '../../../common/extension/extension.dart';
import '../../../common/theme/theme.dart';
import '../../../domain/product/product.dart';
import '../image/image.dart';
import '../spaces/space.dart';
class ProductCard extends StatelessWidget {
final Product product;
const ProductCard({super.key, required this.product});
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {},
child: Container(
decoration: BoxDecoration(
color: AppColor.white,
borderRadius: BorderRadius.circular(8.0),
border: Border.all(color: AppColor.disabled),
),
child: Stack(
children: [
Padding(
padding: const EdgeInsets.all(4.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(8.0)),
child: product.imageUrl == ""
? Container(
width: double.infinity,
height: 120,
decoration: BoxDecoration(
color: AppColor.disabled.withOpacity(0.4),
),
child: const Icon(
Icons.image,
color: AppColor.textSecondary,
),
)
: AppNetworkImage(
url: product.imageUrl,
fit: BoxFit.fill,
width: double.infinity,
height: 140,
),
),
const Spacer(),
Text(
product.name,
style: AppStyle.md.copyWith(fontWeight: FontWeight.w700),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
SpaceHeight(4),
Align(
alignment: Alignment.center,
child: Text(
product.price.currencyFormatRp,
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 12,
),
),
),
SpaceHeight(4),
],
),
),
Positioned(
top: 4,
right: 4,
child: Container(
width: 40,
height: 40,
padding: const EdgeInsets.all(6),
decoration: const BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(9.0)),
color: AppColor.primary,
),
child: Center(
child: Text(
0.toString(),
style: const TextStyle(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
),
),
),
if (product.isActive == false)
Container(
width: double.infinity,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(8.0)),
color: AppColor.disabled.withOpacity(0.5),
),
),
],
),
),
);
}
}