feat: Update comment task bottom sheet layout and enhance comment display with improved spacing and attachment handling
This commit is contained in:
parent
1f784d96f4
commit
daf132c3b5
@ -252,8 +252,8 @@ class _CommentTaskBottomSheetState extends State<CommentTaskBottomSheet>
|
||||
child: ListView.separated(
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemCount: images.length,
|
||||
separatorBuilder: (_, __) =>
|
||||
MySpacing.width(12),
|
||||
separatorBuilder: (context, index) =>
|
||||
SizedBox(height: 12),
|
||||
itemBuilder: (context, index) {
|
||||
final file = images[index];
|
||||
return Stack(
|
||||
@ -445,236 +445,240 @@ class _CommentTaskBottomSheetState extends State<CommentTaskBottomSheet>
|
||||
return SizedBox(
|
||||
height: 300,
|
||||
child: ListView.builder(
|
||||
itemCount: comments.length,
|
||||
itemBuilder: (context, index) {
|
||||
final comment = comments[index];
|
||||
final commentText =
|
||||
comment['text'] ?? '-';
|
||||
final commentedBy =
|
||||
comment['commentedBy'] ?? 'Unknown';
|
||||
final relativeTime =
|
||||
timeAgo(comment['date'] ?? '');
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical:
|
||||
8), // Added padding around the list
|
||||
itemCount: comments.length,
|
||||
itemBuilder: (context, index) {
|
||||
final comment = comments[index];
|
||||
final commentText = comment['text'] ?? '-';
|
||||
final commentedBy =
|
||||
comment['commentedBy'] ?? 'Unknown';
|
||||
final relativeTime =
|
||||
timeAgo(comment['date'] ?? '');
|
||||
|
||||
// Dummy image URLs (simulate as if coming from backend)
|
||||
final imageUrls = [
|
||||
'https://picsum.photos/seed/${index}a/100',
|
||||
'https://picsum.photos/seed/${index}b/100',
|
||||
'https://picsum.photos/seed/${index}a/100',
|
||||
'https://picsum.photos/seed/${index}b/100',
|
||||
'https://picsum.photos/seed/${index}a/100',
|
||||
'https://picsum.photos/seed/${index}b/100',
|
||||
];
|
||||
// Dummy image URLs (simulate as if coming from backend)
|
||||
final imageUrls = [
|
||||
'https://picsum.photos/seed/${index}a/100',
|
||||
'https://picsum.photos/seed/${index}b/100',
|
||||
'https://picsum.photos/seed/${index}a/100',
|
||||
'https://picsum.photos/seed/${index}b/100',
|
||||
'https://picsum.photos/seed/${index}a/100',
|
||||
'https://picsum.photos/seed/${index}b/100',
|
||||
];
|
||||
|
||||
return Container(
|
||||
margin: EdgeInsets.symmetric(
|
||||
vertical: 0, horizontal: 0),
|
||||
padding: EdgeInsets.all(12),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey.shade200,
|
||||
borderRadius:
|
||||
BorderRadius.circular(12),
|
||||
),
|
||||
child: Row(
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.start,
|
||||
children: [
|
||||
// 🔹 Top Row: Avatar + Name + Time
|
||||
Row(
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment
|
||||
.center,
|
||||
children: [
|
||||
Avatar(
|
||||
firstName: commentedBy
|
||||
.split(' ')
|
||||
.first,
|
||||
lastName: commentedBy
|
||||
.split(' ')
|
||||
.length >
|
||||
1
|
||||
? commentedBy
|
||||
.split(' ')
|
||||
.last
|
||||
: '',
|
||||
size: 32,
|
||||
),
|
||||
SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment
|
||||
.spaceBetween,
|
||||
children: [
|
||||
MyText.bodyMedium(
|
||||
commentedBy,
|
||||
fontWeight: 700,
|
||||
color: Colors
|
||||
.black87,
|
||||
),
|
||||
MyText.bodySmall(
|
||||
relativeTime,
|
||||
fontSize: 12,
|
||||
color: Colors
|
||||
.black54,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
SizedBox(height: 12),
|
||||
// 🔹 Comment text below attachments
|
||||
Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment
|
||||
.spaceBetween,
|
||||
children: [
|
||||
MyText.bodyMedium(
|
||||
commentText,
|
||||
fontWeight: 500,
|
||||
color: Colors.black87,
|
||||
),
|
||||
]),
|
||||
SizedBox(height: 12),
|
||||
|
||||
// 🔹 Attachments row: full width below top row
|
||||
if (imageUrls.isNotEmpty) ...[
|
||||
Row(
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment
|
||||
.start,
|
||||
return Container(
|
||||
margin: const EdgeInsets.symmetric(
|
||||
vertical: 8), // Spacing between items
|
||||
padding: const EdgeInsets.all(12),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey.shade200,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Row(
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.start,
|
||||
children: [
|
||||
// 🔹 Top Row: Avatar + Name + Time
|
||||
Row(
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.center,
|
||||
children: [
|
||||
Avatar(
|
||||
firstName: commentedBy
|
||||
.split(' ')
|
||||
.first,
|
||||
lastName: commentedBy
|
||||
.split(' ')
|
||||
.length >
|
||||
1
|
||||
? commentedBy
|
||||
.split(' ')
|
||||
.last
|
||||
: '',
|
||||
size: 32,
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment
|
||||
.spaceBetween,
|
||||
children: [
|
||||
Icon(
|
||||
Icons
|
||||
.attach_file_outlined,
|
||||
size: 18,
|
||||
color: Colors
|
||||
.grey[700]),
|
||||
MyText.bodyMedium(
|
||||
'Attachments',
|
||||
fontWeight: 600,
|
||||
commentedBy,
|
||||
fontWeight: 700,
|
||||
color:
|
||||
Colors.black87,
|
||||
),
|
||||
]),
|
||||
SizedBox(height: 8),
|
||||
SizedBox(
|
||||
height: 60,
|
||||
child: ListView.separated(
|
||||
padding: EdgeInsets
|
||||
.symmetric(
|
||||
horizontal: 0),
|
||||
scrollDirection:
|
||||
Axis.horizontal,
|
||||
itemCount:
|
||||
imageUrls.length,
|
||||
itemBuilder: (context,
|
||||
imageIndex) {
|
||||
final imageUrl =
|
||||
imageUrls[
|
||||
imageIndex];
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
showDialog(
|
||||
context:
|
||||
context,
|
||||
barrierColor:
|
||||
Colors
|
||||
.black54,
|
||||
builder: (_) =>
|
||||
ImageViewerDialog(
|
||||
imageSources:
|
||||
imageUrls,
|
||||
initialIndex:
|
||||
imageIndex,
|
||||
MyText.bodySmall(
|
||||
relativeTime,
|
||||
fontSize: 12,
|
||||
color:
|
||||
Colors.black54,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
// 🔹 Comment text below attachments
|
||||
Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment
|
||||
.spaceBetween,
|
||||
children: [
|
||||
MyText.bodyMedium(
|
||||
commentText,
|
||||
fontWeight: 500,
|
||||
color: Colors.black87,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
// 🔹 Attachments row: full width below top row
|
||||
if (imageUrls.isNotEmpty) ...[
|
||||
Row(
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment
|
||||
.start,
|
||||
children: [
|
||||
Icon(
|
||||
Icons
|
||||
.attach_file_outlined,
|
||||
size: 18,
|
||||
color:
|
||||
Colors.grey[700]),
|
||||
MyText.bodyMedium(
|
||||
'Attachments',
|
||||
fontWeight: 600,
|
||||
color: Colors.black87,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
SizedBox(
|
||||
height: 60,
|
||||
child: ListView.separated(
|
||||
padding: const EdgeInsets
|
||||
.symmetric(
|
||||
horizontal: 0),
|
||||
scrollDirection:
|
||||
Axis.horizontal,
|
||||
itemCount:
|
||||
imageUrls.length,
|
||||
itemBuilder: (context,
|
||||
imageIndex) {
|
||||
final imageUrl =
|
||||
imageUrls[
|
||||
imageIndex];
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierColor:
|
||||
Colors
|
||||
.black54,
|
||||
builder: (_) =>
|
||||
ImageViewerDialog(
|
||||
imageSources:
|
||||
imageUrls,
|
||||
initialIndex:
|
||||
imageIndex,
|
||||
),
|
||||
);
|
||||
},
|
||||
child: Stack(
|
||||
children: [
|
||||
Container(
|
||||
width: 60,
|
||||
height: 60,
|
||||
decoration:
|
||||
BoxDecoration(
|
||||
borderRadius:
|
||||
BorderRadius
|
||||
.circular(
|
||||
12),
|
||||
color: Colors
|
||||
.grey[
|
||||
100],
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors
|
||||
.black26,
|
||||
blurRadius:
|
||||
6,
|
||||
offset:
|
||||
Offset(
|
||||
2,
|
||||
2),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
child: Stack(
|
||||
children: [
|
||||
Container(
|
||||
width: 60,
|
||||
height: 60,
|
||||
decoration:
|
||||
BoxDecoration(
|
||||
borderRadius:
|
||||
BorderRadius.circular(
|
||||
12),
|
||||
color: Colors
|
||||
.grey[
|
||||
100],
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors
|
||||
.black26,
|
||||
blurRadius:
|
||||
6,
|
||||
offset: Offset(
|
||||
2,
|
||||
2),
|
||||
),
|
||||
],
|
||||
),
|
||||
child:
|
||||
ClipRRect(
|
||||
borderRadius:
|
||||
BorderRadius.circular(
|
||||
12),
|
||||
child: Image
|
||||
.network(
|
||||
imageUrl,
|
||||
fit: BoxFit
|
||||
.cover,
|
||||
errorBuilder: (context,
|
||||
error,
|
||||
stackTrace) =>
|
||||
Container(
|
||||
color: Colors
|
||||
.grey[300],
|
||||
child: Icon(
|
||||
Icons
|
||||
.broken_image,
|
||||
color:
|
||||
Colors.grey[700]),
|
||||
),
|
||||
child:
|
||||
ClipRRect(
|
||||
borderRadius:
|
||||
BorderRadius
|
||||
.circular(
|
||||
12),
|
||||
child: Image
|
||||
.network(
|
||||
imageUrl,
|
||||
fit: BoxFit
|
||||
.cover,
|
||||
errorBuilder: (context,
|
||||
error,
|
||||
stackTrace) =>
|
||||
Container(
|
||||
color: Colors
|
||||
.grey[
|
||||
300],
|
||||
child: Icon(
|
||||
Icons
|
||||
.broken_image,
|
||||
color:
|
||||
Colors.grey[700]),
|
||||
),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
right: 4,
|
||||
bottom: 4,
|
||||
child: Icon(
|
||||
Icons
|
||||
.zoom_in,
|
||||
color: Colors
|
||||
.white70,
|
||||
size: 16),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
separatorBuilder: (_,
|
||||
__) =>
|
||||
SizedBox(width: 12),
|
||||
),
|
||||
),
|
||||
const Positioned(
|
||||
right: 4,
|
||||
bottom: 4,
|
||||
child: Icon(
|
||||
Icons
|
||||
.zoom_in,
|
||||
color: Colors
|
||||
.white70,
|
||||
size: 16),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
separatorBuilder:
|
||||
(_, __) =>
|
||||
const SizedBox(
|
||||
width: 12),
|
||||
),
|
||||
SizedBox(height: 12),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
@ -124,7 +124,12 @@ class _DailyProgressReportFilterState extends State<DailyProgressReportFilter> {
|
||||
),
|
||||
child: const Text('Apply Filter'),
|
||||
onPressed: () {
|
||||
Navigator.pop(context, {});
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
Navigator.pop(context, {
|
||||
'startDate': widget.controller.startDateTask,
|
||||
'endDate': widget.controller.endDateTask,
|
||||
});
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
|
Loading…
x
Reference in New Issue
Block a user