updating UI inconsistency
This commit is contained in:
@@ -523,4 +523,4 @@ class _AccountBalanceWidgetState extends State<AccountBalanceWidget> {
|
||||
final formatter = NumberFormat('#,##0.00', 'en_US');
|
||||
return '\$${formatter.format(balance)}';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,6 +61,7 @@ GroupBatchItem _$GroupBatchItemFromJson(Map<String, dynamic> json) =>
|
||||
billProductName: json['billProductName'] as String?,
|
||||
providerLabel: json['providerLabel'] as String?,
|
||||
providerImage: json['providerImage'] as String?,
|
||||
creditAddress: json['creditAddress'] as String?,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$GroupBatchItemToJson(GroupBatchItem instance) =>
|
||||
@@ -79,6 +80,7 @@ Map<String, dynamic> _$GroupBatchItemToJson(GroupBatchItem instance) =>
|
||||
'billProductName': instance.billProductName,
|
||||
'providerLabel': instance.providerLabel,
|
||||
'providerImage': instance.providerImage,
|
||||
'creditAddress': instance.creditAddress,
|
||||
};
|
||||
|
||||
CreateBatchRequest _$CreateBatchRequestFromJson(Map<String, dynamic> json) =>
|
||||
|
||||
@@ -2467,7 +2467,7 @@ class _BatchDetailScreenState extends State<BatchDetailScreen>
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
color: isDark ? const Color(0xFF1A1A2E) : Colors.white,
|
||||
borderRadius: BorderRadius.circular(14),
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
border: Border.all(
|
||||
color: isDark
|
||||
? Colors.white.withValues(alpha: 0.06)
|
||||
@@ -2483,24 +2483,31 @@ class _BatchDetailScreenState extends State<BatchDetailScreen>
|
||||
),
|
||||
],
|
||||
),
|
||||
padding: const EdgeInsets.all(10),
|
||||
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 14),
|
||||
child: Row(
|
||||
children: [
|
||||
CircleAvatar(
|
||||
radius: 18,
|
||||
backgroundColor: theme.colorScheme.primary.withAlpha(25),
|
||||
child: Text(
|
||||
item.recipientName?.isNotEmpty == true
|
||||
? item.recipientName![0].toUpperCase()
|
||||
: '?',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: theme.colorScheme.primary,
|
||||
Container(
|
||||
width: 44,
|
||||
height: 44,
|
||||
padding: const EdgeInsets.all(10),
|
||||
decoration: BoxDecoration(
|
||||
color: theme.colorScheme.primary.withValues(alpha: 0.1),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Center(
|
||||
child: Text(
|
||||
item.recipientName?.isNotEmpty == true
|
||||
? item.recipientName![0].toUpperCase()
|
||||
: '?',
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: theme.colorScheme.primary,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
const SizedBox(width: 14),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@@ -2513,16 +2520,38 @@ class _BatchDetailScreenState extends State<BatchDetailScreen>
|
||||
color: isDark ? Colors.white : Colors.black87,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
Text(
|
||||
item.recipientAccount ?? '',
|
||||
style: TextStyle(fontSize: 12, color: Colors.grey.shade500),
|
||||
const SizedBox(height: 4),
|
||||
Row(
|
||||
children: [
|
||||
if (item.billProductName != null &&
|
||||
item.billProductName!.isNotEmpty) ...[
|
||||
Text(
|
||||
item.billProductName!,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: isDark ? Colors.white54 : Colors.grey.shade500,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
' • ',
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
color: isDark ? Colors.white24 : Colors.grey.shade400,
|
||||
),
|
||||
),
|
||||
],
|
||||
Text(
|
||||
item.recipientAccount ?? '',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: isDark ? Colors.white54 : Colors.grey.shade500,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
if (item.billName != null || item.billProductName != null)
|
||||
const SizedBox(height: 4),
|
||||
if (item.billName != null || item.billProductName != null)
|
||||
_buildBillInfoRow(item, isDark),
|
||||
if (item.creditAddress != null) Text(item.creditAddress ?? ''),
|
||||
Text(item.creditAddress ?? ''),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -2533,7 +2562,7 @@ class _BatchDetailScreenState extends State<BatchDetailScreen>
|
||||
Text(
|
||||
'${batch.currency ?? 'USD'} ${item.amount?.toStringAsFixed(2) ?? '—'}',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: isDark ? Colors.white : Colors.black87,
|
||||
),
|
||||
|
||||
@@ -315,6 +315,8 @@ class _GroupDetailScreenState extends State<GroupDetailScreen>
|
||||
}
|
||||
|
||||
Widget _buildMemberCard(RecipientGroupMember member) {
|
||||
final theme = Theme.of(context);
|
||||
final isDark = theme.brightness == Brightness.dark;
|
||||
final recipient = member.recipient;
|
||||
final name = recipient.name?.isNotEmpty == true
|
||||
? recipient.name!
|
||||
@@ -329,19 +331,26 @@ class _GroupDetailScreenState extends State<GroupDetailScreen>
|
||||
},
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
color: isDark ? const Color(0xFF1A1A2E) : Colors.white,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
border: Border.all(color: Colors.grey.shade200, width: 1),
|
||||
border: Border.all(
|
||||
color: isDark
|
||||
? Colors.white.withValues(alpha: 0.06)
|
||||
: Colors.grey.shade200,
|
||||
width: 1,
|
||||
),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withValues(alpha: 0.04),
|
||||
color: isDark
|
||||
? Colors.black.withValues(alpha: 0.2)
|
||||
: Colors.black.withValues(alpha: 0.03),
|
||||
blurRadius: 8,
|
||||
offset: const Offset(0, 2),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 14, horizontal: 14),
|
||||
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 14),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
@@ -353,22 +362,27 @@ class _GroupDetailScreenState extends State<GroupDetailScreen>
|
||||
children: [
|
||||
Text(
|
||||
name,
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.black87,
|
||||
color: isDark ? Colors.white : Colors.black87,
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
const SizedBox(height: 6),
|
||||
_buildMemberSubtitleRow(recipient, member.account),
|
||||
const SizedBox(height: 4),
|
||||
_buildMemberSubtitleRow(
|
||||
recipient,
|
||||
member.account,
|
||||
isDark,
|
||||
),
|
||||
if (recipient.phoneNumber != null &&
|
||||
recipient.phoneNumber!.isNotEmpty) ...[
|
||||
const SizedBox(height: 6),
|
||||
const SizedBox(height: 4),
|
||||
_buildContactLine(
|
||||
Icons.phone_outlined,
|
||||
recipient.phoneNumber!,
|
||||
isDark,
|
||||
),
|
||||
],
|
||||
if (recipient.email != null &&
|
||||
@@ -377,6 +391,7 @@ class _GroupDetailScreenState extends State<GroupDetailScreen>
|
||||
_buildContactLine(
|
||||
Icons.email_outlined,
|
||||
recipient.email!,
|
||||
isDark,
|
||||
),
|
||||
],
|
||||
],
|
||||
@@ -393,42 +408,29 @@ class _GroupDetailScreenState extends State<GroupDetailScreen>
|
||||
|
||||
Widget _buildMemberAvatar(String initials) {
|
||||
return Container(
|
||||
width: 48,
|
||||
height: 48,
|
||||
width: 44,
|
||||
height: 44,
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
colors: [
|
||||
Theme.of(context).colorScheme.primary,
|
||||
Theme.of(context).colorScheme.primary.withValues(alpha: 0.7),
|
||||
],
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
),
|
||||
shape: BoxShape.circle,
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.primary.withValues(alpha: 0.25),
|
||||
blurRadius: 6,
|
||||
offset: const Offset(0, 2),
|
||||
),
|
||||
],
|
||||
color: Theme.of(context).colorScheme.primary.withValues(alpha: 0.1),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
initials,
|
||||
style: const TextStyle(
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.white,
|
||||
letterSpacing: 0.5,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildMemberSubtitleRow(Recipient recipient, String? memberAccount) {
|
||||
Widget _buildMemberSubtitleRow(
|
||||
Recipient recipient,
|
||||
String? memberAccount,
|
||||
bool isDark,
|
||||
) {
|
||||
final account = memberAccount?.isNotEmpty == true
|
||||
? memberAccount
|
||||
: recipient.account;
|
||||
@@ -463,29 +465,38 @@ class _GroupDetailScreenState extends State<GroupDetailScreen>
|
||||
),
|
||||
),
|
||||
if (hasAccount)
|
||||
Text(
|
||||
account!,
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: Colors.grey.shade700,
|
||||
fontWeight: FontWeight.w500,
|
||||
Flexible(
|
||||
child: Text(
|
||||
account!,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: isDark ? Colors.white54 : Colors.grey.shade600,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildContactLine(IconData icon, String text) {
|
||||
Widget _buildContactLine(IconData icon, String text, bool isDark) {
|
||||
return Row(
|
||||
children: [
|
||||
Icon(icon, size: 13, color: Colors.grey.shade500),
|
||||
Icon(
|
||||
icon,
|
||||
size: 13,
|
||||
color: isDark ? Colors.white38 : Colors.grey.shade500,
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
Flexible(
|
||||
child: Text(
|
||||
text,
|
||||
style: TextStyle(fontSize: 12, color: Colors.grey.shade600),
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: isDark ? Colors.white54 : Colors.grey.shade600,
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
@@ -1127,131 +1138,166 @@ class _GroupDetailScreenState extends State<GroupDetailScreen>
|
||||
final status = batch.status ?? 'UNKNOWN';
|
||||
final createdAt = batch.createdAt;
|
||||
final parsedDate = createdAt != null ? DateTime.tryParse(createdAt) : null;
|
||||
return Card(
|
||||
elevation: 0,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
side: BorderSide(
|
||||
color: inSelectMode && isSelected
|
||||
? Theme.of(context).colorScheme.primary
|
||||
: Colors.black12.withAlpha(30),
|
||||
width: inSelectMode && isSelected ? 2 : 1,
|
||||
),
|
||||
),
|
||||
child: InkWell(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
onTap: inSelectMode
|
||||
? () => batchController.toggleBatchSelection(batch.id!)
|
||||
: () => context.push('/groups/batches/${batch.id}'),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: Row(
|
||||
children: [
|
||||
if (inSelectMode)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 8),
|
||||
child: Icon(
|
||||
isSelected
|
||||
? Icons.check_box
|
||||
: Icons.check_box_outline_blank,
|
||||
size: 20,
|
||||
color: isSelected
|
||||
? Theme.of(context).colorScheme.primary
|
||||
: Colors.grey.shade400,
|
||||
),
|
||||
final theme = Theme.of(context);
|
||||
final isDark = theme.brightness == Brightness.dark;
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8),
|
||||
child: Material(
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
onTap: inSelectMode
|
||||
? () => batchController.toggleBatchSelection(batch.id!)
|
||||
: () => context.push('/groups/batches/${batch.id}'),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 14),
|
||||
decoration: BoxDecoration(
|
||||
color: isDark ? const Color(0xFF1A1A2E) : Colors.white,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
border: Border.all(
|
||||
color: inSelectMode && isSelected
|
||||
? theme.colorScheme.primary
|
||||
: isDark
|
||||
? Colors.white.withValues(alpha: 0.06)
|
||||
: Colors.grey.shade200,
|
||||
width: inSelectMode && isSelected ? 2 : 1,
|
||||
),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: isDark
|
||||
? Colors.black.withValues(alpha: 0.2)
|
||||
: Colors.black.withValues(alpha: 0.03),
|
||||
blurRadius: 8,
|
||||
offset: const Offset(0, 2),
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
if (batch.description != null &&
|
||||
batch.description!.isNotEmpty)
|
||||
Flexible(
|
||||
child: Text(
|
||||
batch.description!,
|
||||
style: const TextStyle(
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.w700,
|
||||
],
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
if (inSelectMode)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 12),
|
||||
child: Icon(
|
||||
isSelected
|
||||
? Icons.check_box
|
||||
: Icons.check_box_outline_blank,
|
||||
size: 20,
|
||||
color: isSelected
|
||||
? theme.colorScheme.primary
|
||||
: Colors.grey.shade400,
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
if (batch.description != null &&
|
||||
batch.description!.isNotEmpty)
|
||||
Flexible(
|
||||
child: Text(
|
||||
batch.description!,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: isDark
|
||||
? Colors.white
|
||||
: const Color.fromARGB(221, 58, 58, 58),
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
StatusChip(status: status),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
'${batch.currency ?? 'USD'} ${batch.value?.toStringAsFixed(2) ?? '—'}',
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: isDark ? Colors.white : Colors.black87,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
StatusChip(status: status),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
'${batch.currency ?? 'USD'} ${batch.value?.toStringAsFixed(2) ?? '—'}',
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: Colors.grey.shade600,
|
||||
),
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
if (parsedDate != null)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 6),
|
||||
child: Text(
|
||||
if (parsedDate != null) ...[
|
||||
Text(
|
||||
' • ',
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
color: isDark
|
||||
? Colors.white24
|
||||
: Colors.grey.shade400,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
DateFormat.yMMMd().add_jm().format(parsedDate),
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Colors.grey.shade500,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: isDark
|
||||
? Colors.white54
|
||||
: Colors.grey.shade500,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (batch.count != null)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 4),
|
||||
child: Row(
|
||||
],
|
||||
const Spacer(),
|
||||
if (batch.count != null)
|
||||
Row(
|
||||
children: [
|
||||
_statIcon(
|
||||
Icons.people_outline,
|
||||
'${batch.count}',
|
||||
isDark,
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
const SizedBox(width: 6),
|
||||
_statIcon(
|
||||
Icons.check_circle_outline,
|
||||
'${batch.successfulCount ?? 0}',
|
||||
isDark,
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
const SizedBox(width: 6),
|
||||
_statIcon(
|
||||
Icons.cancel_outlined,
|
||||
'${batch.failedCount ?? 0}',
|
||||
isDark,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
if (!inSelectMode)
|
||||
Icon(Icons.chevron_right, color: Colors.grey.shade400),
|
||||
],
|
||||
if (!inSelectMode)
|
||||
Icon(Icons.chevron_right, color: Colors.grey.shade400),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _statIcon(IconData icon, String label) {
|
||||
Widget _statIcon(IconData icon, String label, bool isDark) {
|
||||
return Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(icon, size: 12, color: Colors.grey.shade500),
|
||||
Icon(
|
||||
icon,
|
||||
size: 12,
|
||||
color: isDark ? Colors.white38 : Colors.grey.shade500,
|
||||
),
|
||||
const SizedBox(width: 3),
|
||||
Text(
|
||||
label,
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
color: Colors.grey.shade600,
|
||||
color: isDark ? Colors.white54 : Colors.grey.shade600,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
|
||||
@@ -435,86 +435,112 @@ class _GroupsScreenState extends State<GroupsScreen> {
|
||||
}
|
||||
|
||||
Widget _buildGroupCard(RecipientGroup group) {
|
||||
final theme = Theme.of(context);
|
||||
final isDark = theme.brightness == Brightness.dark;
|
||||
final isSelected = controller.model.selectedGroupIds.contains(group.id);
|
||||
final inSelectMode = controller.model.selectMode;
|
||||
|
||||
return Card(
|
||||
elevation: 0,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
side: BorderSide(
|
||||
color: inSelectMode && isSelected
|
||||
? Theme.of(context).colorScheme.primary
|
||||
: Colors.black12.withAlpha(30),
|
||||
width: inSelectMode && isSelected ? 2 : 1,
|
||||
),
|
||||
),
|
||||
child: InkWell(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
onTap: inSelectMode
|
||||
? () => controller.toggleGroupSelection(group.id!)
|
||||
: () => context.push('/groups/${group.id}', extra: group),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Row(
|
||||
children: [
|
||||
if (inSelectMode)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 12),
|
||||
child: Icon(
|
||||
isSelected
|
||||
? Icons.check_box
|
||||
: Icons.check_box_outline_blank,
|
||||
color: isSelected
|
||||
? Theme.of(context).colorScheme.primary
|
||||
: Colors.grey.shade400,
|
||||
),
|
||||
),
|
||||
CircleAvatar(
|
||||
backgroundColor: Theme.of(
|
||||
context,
|
||||
).colorScheme.primary.withAlpha(30),
|
||||
child: Text(
|
||||
_getGroupAbbreviation(group.name),
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
fontWeight: FontWeight.w600,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8),
|
||||
child: Material(
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
onTap: inSelectMode
|
||||
? () => controller.toggleGroupSelection(group.id!)
|
||||
: () => context.push('/groups/${group.id}', extra: group),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 14),
|
||||
decoration: BoxDecoration(
|
||||
color: isDark ? const Color(0xFF1A1A2E) : Colors.white,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
border: Border.all(
|
||||
color: inSelectMode && isSelected
|
||||
? theme.colorScheme.primary
|
||||
: isDark
|
||||
? Colors.white.withValues(alpha: 0.06)
|
||||
: Colors.grey.shade200,
|
||||
width: inSelectMode && isSelected ? 2 : 1,
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
group.name,
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: isDark
|
||||
? Colors.black.withValues(alpha: 0.2)
|
||||
: Colors.black.withValues(alpha: 0.03),
|
||||
blurRadius: 8,
|
||||
offset: const Offset(0, 2),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
if (inSelectMode)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 12),
|
||||
child: Icon(
|
||||
isSelected
|
||||
? Icons.check_box
|
||||
: Icons.check_box_outline_blank,
|
||||
color: isSelected
|
||||
? theme.colorScheme.primary
|
||||
: Colors.grey.shade400,
|
||||
),
|
||||
),
|
||||
Container(
|
||||
width: 44,
|
||||
height: 44,
|
||||
decoration: BoxDecoration(
|
||||
color: theme.colorScheme.primary.withValues(alpha: 0.1),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Center(
|
||||
child: Text(
|
||||
_getGroupAbbreviation(group.name),
|
||||
style: TextStyle(
|
||||
color: theme.colorScheme.primary,
|
||||
fontWeight: FontWeight.w600,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
if (group.description != null &&
|
||||
group.description!.isNotEmpty)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 4),
|
||||
child: Text(
|
||||
group.description!,
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: Colors.grey.shade600,
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 14),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
group.name,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: isDark ? Colors.white : Colors.black87,
|
||||
),
|
||||
),
|
||||
],
|
||||
if (group.description != null &&
|
||||
group.description!.isNotEmpty)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 4),
|
||||
child: Text(
|
||||
group.description!,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: isDark
|
||||
? Colors.white54
|
||||
: Colors.grey.shade500,
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
if (!inSelectMode)
|
||||
Icon(Icons.chevron_right, color: Colors.grey.shade400),
|
||||
],
|
||||
if (!inSelectMode)
|
||||
Icon(Icons.chevron_right, color: Colors.grey.shade400),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user