227 lines
9.5 KiB
Dart
227 lines
9.5 KiB
Dart
import 'package:flutter/material.dart';
|
||
import 'package:marco/helpers/widgets/my_text.dart';
|
||
import 'package:marco/helpers/widgets/avatar.dart';
|
||
import 'package:marco/model/directory/contact_bucket_list_model.dart';
|
||
|
||
class TeamMembersBottomSheet {
|
||
static void show(
|
||
BuildContext context,
|
||
ContactBucket bucket,
|
||
List<dynamic> members, {
|
||
bool canEdit = false,
|
||
VoidCallback? onEdit,
|
||
}) {
|
||
// Ensure the owner is at the top of the list
|
||
final ownerId = bucket.createdBy.id;
|
||
members.sort((a, b) {
|
||
if (a.id == ownerId) return -1;
|
||
if (b.id == ownerId) return 1;
|
||
return 0;
|
||
});
|
||
|
||
showModalBottomSheet(
|
||
context: context,
|
||
isScrollControlled: true,
|
||
backgroundColor: Colors.transparent,
|
||
isDismissible: true,
|
||
enableDrag: true,
|
||
builder: (context) {
|
||
return SafeArea(
|
||
child: Container(
|
||
decoration: const BoxDecoration(
|
||
color: Colors.white,
|
||
borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
|
||
),
|
||
child: DraggableScrollableSheet(
|
||
expand: false,
|
||
initialChildSize: 0.7,
|
||
minChildSize: 0.5,
|
||
maxChildSize: 0.95,
|
||
builder: (context, scrollController) {
|
||
return Column(
|
||
children: [
|
||
const SizedBox(height: 6),
|
||
Container(
|
||
width: 36,
|
||
height: 4,
|
||
decoration: BoxDecoration(
|
||
color: Colors.grey.shade300,
|
||
borderRadius: BorderRadius.circular(2),
|
||
),
|
||
),
|
||
const SizedBox(height: 10),
|
||
|
||
MyText.titleMedium(
|
||
'Bucket Details',
|
||
fontWeight: 700,
|
||
),
|
||
|
||
const SizedBox(height: 12),
|
||
|
||
// Header with title and edit
|
||
Padding(
|
||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||
child: Row(
|
||
children: [
|
||
Expanded(
|
||
child: MyText.titleMedium(
|
||
bucket.name,
|
||
fontWeight: 700,
|
||
),
|
||
),
|
||
if (canEdit)
|
||
IconButton(
|
||
onPressed: onEdit,
|
||
icon: const Icon(Icons.edit, color: Colors.red),
|
||
tooltip: 'Edit Bucket',
|
||
),
|
||
],
|
||
),
|
||
),
|
||
|
||
// Info
|
||
Padding(
|
||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||
child: Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
if (bucket.description.isNotEmpty)
|
||
Padding(
|
||
padding: const EdgeInsets.only(bottom: 6),
|
||
child: MyText.bodySmall(
|
||
bucket.description,
|
||
color: Colors.grey[700],
|
||
),
|
||
),
|
||
Row(
|
||
children: [
|
||
const Icon(Icons.contacts_outlined,
|
||
size: 14, color: Colors.grey),
|
||
const SizedBox(width: 4),
|
||
MyText.labelSmall(
|
||
'${bucket.numberOfContacts} contact(s)',
|
||
fontWeight: 600,
|
||
color: Colors.red,
|
||
),
|
||
const SizedBox(width: 12),
|
||
const Icon(Icons.ios_share_outlined,
|
||
size: 14, color: Colors.grey),
|
||
const SizedBox(width: 4),
|
||
MyText.labelSmall(
|
||
'Shared with (${members.length})',
|
||
fontWeight: 600,
|
||
color: Colors.indigo,
|
||
),
|
||
],
|
||
),
|
||
Padding(
|
||
padding: const EdgeInsets.only(top: 8),
|
||
child: Row(
|
||
children: [
|
||
const Icon(Icons.edit_outlined,
|
||
size: 14, color: Colors.grey),
|
||
const SizedBox(width: 4),
|
||
MyText.labelSmall(
|
||
canEdit
|
||
? 'Can be edited by you'
|
||
: 'You don’t have edit access',
|
||
fontWeight: 600,
|
||
color: canEdit ? Colors.green : Colors.grey,
|
||
),
|
||
],
|
||
),
|
||
),
|
||
const SizedBox(height: 8),
|
||
const Divider(thickness: 1),
|
||
const SizedBox(height: 6),
|
||
MyText.labelLarge(
|
||
'Shared with',
|
||
fontWeight: 700,
|
||
color: Colors.black,
|
||
),
|
||
],
|
||
),
|
||
),
|
||
|
||
const SizedBox(height: 4),
|
||
|
||
Expanded(
|
||
child: Padding(
|
||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||
child: members.isEmpty
|
||
? Center(
|
||
child: MyText.bodySmall(
|
||
"No team members found.",
|
||
fontWeight: 600,
|
||
color: Colors.grey,
|
||
),
|
||
)
|
||
: ListView.separated(
|
||
controller: scrollController,
|
||
itemCount: members.length,
|
||
separatorBuilder: (_, __) =>
|
||
const SizedBox(height: 4),
|
||
itemBuilder: (context, index) {
|
||
final member = members[index];
|
||
final firstName = member.firstName ?? '';
|
||
final lastName = member.lastName ?? '';
|
||
final isOwner =
|
||
member.id == bucket.createdBy.id;
|
||
|
||
return ListTile(
|
||
dense: true,
|
||
contentPadding: EdgeInsets.zero,
|
||
leading: Avatar(
|
||
firstName: firstName,
|
||
lastName: lastName,
|
||
size: 32,
|
||
),
|
||
title: Row(
|
||
children: [
|
||
Expanded(
|
||
child: MyText.bodyMedium(
|
||
'${firstName.isNotEmpty ? firstName : 'Unnamed'} ${lastName.isNotEmpty ? lastName : ''}',
|
||
fontWeight: 600,
|
||
),
|
||
),
|
||
if (isOwner)
|
||
Container(
|
||
margin:
|
||
const EdgeInsets.only(left: 6),
|
||
padding: const EdgeInsets.symmetric(
|
||
horizontal: 6, vertical: 2),
|
||
decoration: BoxDecoration(
|
||
color: Colors.red.shade50,
|
||
borderRadius:
|
||
BorderRadius.circular(4),
|
||
),
|
||
child: MyText.labelSmall(
|
||
"Owner",
|
||
fontWeight: 600,
|
||
color: Colors.red,
|
||
),
|
||
),
|
||
],
|
||
),
|
||
subtitle: MyText.bodySmall(
|
||
member.jobRole ?? '',
|
||
color: Colors.grey.shade600,
|
||
),
|
||
);
|
||
},
|
||
),
|
||
),
|
||
),
|
||
|
||
const SizedBox(height: 8),
|
||
],
|
||
);
|
||
},
|
||
),
|
||
),
|
||
);
|
||
},
|
||
);
|
||
}
|
||
}
|