fix
This commit is contained in:
@@ -193,6 +193,7 @@ class AuthRemoteDataSource {
|
||||
'customer': 1,
|
||||
},
|
||||
'limit_page_length': 0,
|
||||
'order_by': 'custom_line_no asc'
|
||||
},
|
||||
options: Options(
|
||||
headers: {
|
||||
|
||||
@@ -71,14 +71,50 @@ class _BusinessUnitSelectionPageState extends State<BusinessUnitSelectionPage> {
|
||||
name: 'LPKD',
|
||||
description: 'Đơn vị kinh doanh LPKD',
|
||||
),
|
||||
const BusinessUnit(
|
||||
id: '2',
|
||||
code: 'HSKD',
|
||||
name: 'HSKD',
|
||||
description: 'Đơn vị kinh doanh HSKD',
|
||||
),
|
||||
const BusinessUnit(
|
||||
id: '3',
|
||||
code: 'LPKD',
|
||||
name: 'LPKD',
|
||||
description: 'Đơn vị kinh doanh LPKD',
|
||||
),
|
||||
const BusinessUnit(
|
||||
id: '2',
|
||||
code: 'HSKD',
|
||||
name: 'HSKD',
|
||||
description: 'Đơn vị kinh doanh HSKD',
|
||||
),
|
||||
const BusinessUnit(
|
||||
id: '3',
|
||||
code: 'LPKD',
|
||||
name: 'LPKD',
|
||||
description: 'Đơn vị kinh doanh LPKD',
|
||||
),
|
||||
const BusinessUnit(
|
||||
id: '2',
|
||||
code: 'HSKD',
|
||||
name: 'HSKD',
|
||||
description: 'Đơn vị kinh doanh HSKD',
|
||||
),
|
||||
const BusinessUnit(
|
||||
id: '3',
|
||||
code: 'LPKD',
|
||||
name: 'LPKD',
|
||||
description: 'Đơn vị kinh doanh LPKD',
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
void _handleContinue() {
|
||||
if (_selectedUnit == null) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: const Text('Vui lòng chọn đơn vị kinh doanh'),
|
||||
const SnackBar(
|
||||
content: Text('Vui lòng chọn đơn vị kinh doanh'),
|
||||
backgroundColor: AppColors.danger,
|
||||
),
|
||||
);
|
||||
@@ -146,249 +182,252 @@ class _BusinessUnitSelectionPageState extends State<BusinessUnitSelectionPage> {
|
||||
const SizedBox(width: AppSpacing.sm),
|
||||
],
|
||||
),
|
||||
body: SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(AppSpacing.lg),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
// Logo Section
|
||||
Center(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(20),
|
||||
decoration: BoxDecoration(
|
||||
gradient: const LinearGradient(
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
colors: [AppColors.primaryBlue, AppColors.lightBlue],
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(AppSpacing.lg),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
// Logo Section
|
||||
Center(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(20),
|
||||
decoration: BoxDecoration(
|
||||
gradient: const LinearGradient(
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
colors: [AppColors.primaryBlue, AppColors.lightBlue],
|
||||
),
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
child: const Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
'DBIZ',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 32,
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
),
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
child: const Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
'DBIZ',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 32,
|
||||
fontWeight: FontWeight.w700,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
'Worker App',
|
||||
style: TextStyle(color: Colors.white, fontSize: 12),
|
||||
),
|
||||
],
|
||||
),
|
||||
Text(
|
||||
'Worker App',
|
||||
style: TextStyle(color: Colors.white, fontSize: 12),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
const SizedBox(height: AppSpacing.xl),
|
||||
const SizedBox(height: AppSpacing.xl),
|
||||
|
||||
// Welcome Message
|
||||
const Text(
|
||||
'Chọn đơn vị kinh doanh để tiếp tục',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(color: AppColors.grey500, fontSize: 14),
|
||||
// Welcome Message
|
||||
const Text(
|
||||
'Chọn đơn vị kinh doanh để tiếp tục',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(color: AppColors.grey500, fontSize: 14),
|
||||
),
|
||||
|
||||
const SizedBox(height: 40),
|
||||
|
||||
const Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: AppSpacing.sm),
|
||||
child: Text(
|
||||
'Đơn vị kinh doanh',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: AppColors.grey900,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: AppSpacing.md),
|
||||
|
||||
const SizedBox(height: 40),
|
||||
|
||||
// Business Unit Selection List
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: AppSpacing.sm),
|
||||
child: Text(
|
||||
'Đơn vị kinh doanh',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: AppColors.grey900,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: AppSpacing.md),
|
||||
// Business Unit List Tiles
|
||||
...(_availableUnits.asMap().entries.map((entry) {
|
||||
final index = entry.key;
|
||||
final unit = entry.value;
|
||||
final isSelected = _selectedUnit?.id == unit.id;
|
||||
final isFirst = index == 0;
|
||||
final isLast = index == _availableUnits.length - 1;
|
||||
|
||||
return Container(
|
||||
margin: EdgeInsets.only(
|
||||
bottom: isLast ? 0 : AppSpacing.xs,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.white,
|
||||
border: Border.all(
|
||||
color: isSelected
|
||||
? AppColors.primaryBlue
|
||||
: AppColors.grey100,
|
||||
width: isSelected ? 2 : 1,
|
||||
// Business Unit Selection List
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// Business Unit List Tiles
|
||||
...(_availableUnits.asMap().entries.map((entry) {
|
||||
final index = entry.key;
|
||||
final unit = entry.value;
|
||||
final isSelected = _selectedUnit?.id == unit.id;
|
||||
final isFirst = index == 0;
|
||||
final isLast = index == _availableUnits.length - 1;
|
||||
|
||||
return Container(
|
||||
margin: EdgeInsets.only(
|
||||
bottom: isLast ? 0 : AppSpacing.xs,
|
||||
),
|
||||
borderRadius: BorderRadius.vertical(
|
||||
top: isFirst
|
||||
? const Radius.circular(
|
||||
InputFieldSpecs.borderRadius,
|
||||
)
|
||||
: Radius.zero,
|
||||
bottom: isLast
|
||||
? const Radius.circular(
|
||||
InputFieldSpecs.borderRadius,
|
||||
)
|
||||
: Radius.zero,
|
||||
),
|
||||
boxShadow: isSelected
|
||||
? [
|
||||
BoxShadow(
|
||||
color: AppColors.primaryBlue.withValues(
|
||||
alpha: 0.1,
|
||||
),
|
||||
blurRadius: 8,
|
||||
offset: const Offset(0, 2),
|
||||
),
|
||||
]
|
||||
: null,
|
||||
),
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
_selectedUnit = unit;
|
||||
});
|
||||
},
|
||||
borderRadius: BorderRadius.vertical(
|
||||
top: isFirst
|
||||
? const Radius.circular(
|
||||
InputFieldSpecs.borderRadius,
|
||||
)
|
||||
: Radius.zero,
|
||||
bottom: isLast
|
||||
? const Radius.circular(
|
||||
InputFieldSpecs.borderRadius,
|
||||
)
|
||||
: Radius.zero,
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: AppSpacing.lg,
|
||||
vertical: AppSpacing.md,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.white,
|
||||
border: Border.all(
|
||||
color: isSelected
|
||||
? AppColors.primaryBlue
|
||||
: AppColors.grey100,
|
||||
width: isSelected ? 2 : 1,
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
// Icon
|
||||
Container(
|
||||
width: 40,
|
||||
height: 40,
|
||||
decoration: BoxDecoration(
|
||||
color: isSelected
|
||||
? AppColors.primaryBlue.withValues(
|
||||
alpha: 0.1,
|
||||
)
|
||||
: AppColors.grey50,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Icon(
|
||||
Icons.business,
|
||||
color: isSelected
|
||||
? AppColors.primaryBlue
|
||||
: AppColors.grey500,
|
||||
size: 20,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: AppSpacing.md),
|
||||
// Unit Name
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
unit.name,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: isSelected
|
||||
? FontWeight.w600
|
||||
: FontWeight.w500,
|
||||
color: isSelected
|
||||
? AppColors.primaryBlue
|
||||
: AppColors.grey900,
|
||||
),
|
||||
borderRadius: BorderRadius.vertical(
|
||||
top: isFirst
|
||||
? const Radius.circular(
|
||||
InputFieldSpecs.borderRadius,
|
||||
)
|
||||
: Radius.zero,
|
||||
bottom: isLast
|
||||
? const Radius.circular(
|
||||
InputFieldSpecs.borderRadius,
|
||||
)
|
||||
: Radius.zero,
|
||||
),
|
||||
boxShadow: isSelected
|
||||
? [
|
||||
BoxShadow(
|
||||
color: AppColors.primaryBlue.withValues(
|
||||
alpha: 0.1,
|
||||
),
|
||||
if (unit.description != null) ...[
|
||||
const SizedBox(height: 2),
|
||||
Text(
|
||||
unit.description!,
|
||||
style: const TextStyle(
|
||||
fontSize: 12,
|
||||
color: AppColors.grey500,
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
// Radio indicator
|
||||
Container(
|
||||
width: 20,
|
||||
height: 20,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(
|
||||
blurRadius: 8,
|
||||
offset: const Offset(0, 2),
|
||||
),
|
||||
]
|
||||
: null,
|
||||
),
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
_selectedUnit = unit;
|
||||
});
|
||||
},
|
||||
borderRadius: BorderRadius.vertical(
|
||||
top: isFirst
|
||||
? const Radius.circular(
|
||||
InputFieldSpecs.borderRadius,
|
||||
)
|
||||
: Radius.zero,
|
||||
bottom: isLast
|
||||
? const Radius.circular(
|
||||
InputFieldSpecs.borderRadius,
|
||||
)
|
||||
: Radius.zero,
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: AppSpacing.lg,
|
||||
vertical: AppSpacing.md,
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
// Icon
|
||||
Container(
|
||||
width: 40,
|
||||
height: 40,
|
||||
decoration: BoxDecoration(
|
||||
color: isSelected
|
||||
? AppColors.primaryBlue.withValues(
|
||||
alpha: 0.1,
|
||||
)
|
||||
: AppColors.grey50,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Icon(
|
||||
Icons.business,
|
||||
color: isSelected
|
||||
? AppColors.primaryBlue
|
||||
: AppColors.grey500,
|
||||
width: 2,
|
||||
size: 20,
|
||||
),
|
||||
color: isSelected
|
||||
? AppColors.primaryBlue
|
||||
: Colors.transparent,
|
||||
),
|
||||
child: isSelected
|
||||
? const Icon(
|
||||
Icons.circle,
|
||||
size: 10,
|
||||
color: AppColors.white,
|
||||
)
|
||||
: null,
|
||||
),
|
||||
],
|
||||
const SizedBox(width: AppSpacing.md),
|
||||
// Unit Name
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
unit.name,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: isSelected
|
||||
? FontWeight.w600
|
||||
: FontWeight.w500,
|
||||
color: isSelected
|
||||
? AppColors.primaryBlue
|
||||
: AppColors.grey900,
|
||||
),
|
||||
),
|
||||
if (unit.description != null) ...[
|
||||
const SizedBox(height: 2),
|
||||
Text(
|
||||
unit.description!,
|
||||
style: const TextStyle(
|
||||
fontSize: 12,
|
||||
color: AppColors.grey500,
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
// Radio indicator
|
||||
Container(
|
||||
width: 20,
|
||||
height: 20,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(
|
||||
color: isSelected
|
||||
? AppColors.primaryBlue
|
||||
: AppColors.grey500,
|
||||
width: 2,
|
||||
),
|
||||
color: isSelected
|
||||
? AppColors.primaryBlue
|
||||
: Colors.transparent,
|
||||
),
|
||||
child: isSelected
|
||||
? const Icon(
|
||||
Icons.circle,
|
||||
size: 10,
|
||||
color: AppColors.white,
|
||||
)
|
||||
: null,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}).toList()),
|
||||
],
|
||||
),
|
||||
|
||||
const SizedBox(height: AppSpacing.xl),
|
||||
|
||||
// Continue Button
|
||||
SizedBox(
|
||||
height: ButtonSpecs.height,
|
||||
child: ElevatedButton(
|
||||
onPressed: _handleContinue,
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: AppColors.primaryBlue,
|
||||
foregroundColor: Colors.white,
|
||||
elevation: 0,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(
|
||||
ButtonSpecs.borderRadius,
|
||||
),
|
||||
),
|
||||
),
|
||||
child: const Text(
|
||||
'Tiếp tục',
|
||||
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600),
|
||||
),
|
||||
);
|
||||
}).toList()),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
const SizedBox(height: AppSpacing.xl),
|
||||
// Continue Button
|
||||
SizedBox(
|
||||
height: ButtonSpecs.height,
|
||||
child: ElevatedButton(
|
||||
onPressed: _handleContinue,
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: AppColors.primaryBlue,
|
||||
foregroundColor: Colors.white,
|
||||
elevation: 0,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(
|
||||
ButtonSpecs.borderRadius,
|
||||
),
|
||||
),
|
||||
),
|
||||
child: const Text(
|
||||
'Tiếp tục',
|
||||
style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: AppSpacing.xl),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -10,7 +10,6 @@ import 'package:intl/intl.dart';
|
||||
import 'package:shimmer/shimmer.dart';
|
||||
import 'package:worker/core/constants/ui_constants.dart';
|
||||
import 'package:worker/core/theme/colors.dart';
|
||||
import 'package:worker/features/favorites/presentation/providers/favorites_provider.dart';
|
||||
import 'package:worker/features/products/domain/entities/product.dart';
|
||||
import 'package:worker/generated/l10n/app_localizations.dart';
|
||||
|
||||
@@ -38,7 +37,7 @@ class ProductCard extends ConsumerWidget {
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final l10n = AppLocalizations.of(context);
|
||||
final isFavorited = ref.watch(isFavoriteProvider(product.productId));
|
||||
// final isFavorited = ref.watch(isFavoriteProvider(product.productId));
|
||||
|
||||
return Card(
|
||||
elevation: ProductCardSpecs.elevation,
|
||||
@@ -135,64 +134,64 @@ class ProductCard extends ConsumerWidget {
|
||||
),
|
||||
|
||||
// Favorite Button (bottom-left corner)
|
||||
Positioned(
|
||||
bottom: AppSpacing.sm,
|
||||
left: AppSpacing.sm,
|
||||
child: Material(
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
onTap: () async {
|
||||
// Capture current state before toggle
|
||||
final wasfavorited = isFavorited;
|
||||
|
||||
// Toggle favorite
|
||||
await ref
|
||||
.read(favoritesProvider.notifier)
|
||||
.toggleFavorite(product.productId);
|
||||
|
||||
// Show feedback with correct message
|
||||
if (context.mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(
|
||||
wasfavorited
|
||||
? 'Đã xóa khỏi yêu thích'
|
||||
: 'Đã thêm vào yêu thích',
|
||||
),
|
||||
duration: const Duration(seconds: 1),
|
||||
behavior: SnackBarBehavior.floating,
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
child: Container(
|
||||
width: 36,
|
||||
height: 36,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.white,
|
||||
shape: BoxShape.circle,
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withValues(alpha: 0.15),
|
||||
blurRadius: 6,
|
||||
offset: const Offset(0, 2),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Icon(
|
||||
isFavorited
|
||||
? Icons.favorite
|
||||
: Icons.favorite_border,
|
||||
color: isFavorited
|
||||
? AppColors.danger
|
||||
: AppColors.grey500,
|
||||
size: 20,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
// Positioned(
|
||||
// bottom: AppSpacing.sm,
|
||||
// left: AppSpacing.sm,
|
||||
// child: Material(
|
||||
// color: Colors.transparent,
|
||||
// child: InkWell(
|
||||
// onTap: () async {
|
||||
// // Capture current state before toggle
|
||||
// final wasfavorited = isFavorited;
|
||||
//
|
||||
// // Toggle favorite
|
||||
// await ref
|
||||
// .read(favoritesProvider.notifier)
|
||||
// .toggleFavorite(product.productId);
|
||||
//
|
||||
// // Show feedback with correct message
|
||||
// if (context.mounted) {
|
||||
// ScaffoldMessenger.of(context).showSnackBar(
|
||||
// SnackBar(
|
||||
// content: Text(
|
||||
// wasfavorited
|
||||
// ? 'Đã xóa khỏi yêu thích'
|
||||
// : 'Đã thêm vào yêu thích',
|
||||
// ),
|
||||
// duration: const Duration(seconds: 1),
|
||||
// behavior: SnackBarBehavior.floating,
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
// },
|
||||
// borderRadius: BorderRadius.circular(20),
|
||||
// child: Container(
|
||||
// width: 36,
|
||||
// height: 36,
|
||||
// decoration: BoxDecoration(
|
||||
// color: AppColors.white,
|
||||
// shape: BoxShape.circle,
|
||||
// boxShadow: [
|
||||
// BoxShadow(
|
||||
// color: Colors.black.withValues(alpha: 0.15),
|
||||
// blurRadius: 6,
|
||||
// offset: const Offset(0, 2),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// child: Icon(
|
||||
// isFavorited
|
||||
// ? Icons.favorite
|
||||
// : Icons.favorite_border,
|
||||
// color: isFavorited
|
||||
// ? AppColors.danger
|
||||
// : AppColors.grey500,
|
||||
// size: 20,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user