feat(directory): enhance contact card UI with improved layout and interaction elements
This commit is contained in:
parent
549d8cce3c
commit
becdec1a79
@ -2,10 +2,8 @@ import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:marco/controller/directory/directory_controller.dart';
|
||||
import 'package:marco/controller/project_controller.dart';
|
||||
import 'package:marco/helpers/widgets/my_card.dart';
|
||||
import 'package:marco/helpers/widgets/my_spacing.dart';
|
||||
import 'package:marco/helpers/widgets/my_text.dart';
|
||||
import 'package:marco/helpers/utils/my_shadow.dart';
|
||||
import 'package:marco/helpers/widgets/avatar.dart';
|
||||
import 'package:marco/helpers/widgets/my_custom_skeleton.dart';
|
||||
import 'package:marco/model/directory/directory_filter_bottom_sheet.dart';
|
||||
@ -31,7 +29,7 @@ class DirectoryMainScreen extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: const Color(0xFFF5F5F5),
|
||||
backgroundColor: Colors.white,
|
||||
appBar: PreferredSize(
|
||||
preferredSize: const Size.fromHeight(72),
|
||||
child: AppBar(
|
||||
@ -308,218 +306,145 @@ class DirectoryMainScreen extends StatelessWidget {
|
||||
final firstName = nameParts.first;
|
||||
final lastName = nameParts.length > 1 ? nameParts.last : "";
|
||||
final tags = contact.tags.map((tag) => tag.name).toList();
|
||||
return MyCard.bordered(
|
||||
margin: MySpacing.only(bottom: 2),
|
||||
paddingAll: 8,
|
||||
borderRadiusAll: 8,
|
||||
shadow: MyShadow(
|
||||
elevation: 1.5,
|
||||
position: MyShadowPosition.bottom,
|
||||
),
|
||||
return InkWell(
|
||||
onTap: () {
|
||||
Get.to(() => ContactDetailScreen(contact: contact));
|
||||
},
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 12.0, vertical: 10),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
// Leading Icon
|
||||
Avatar(
|
||||
firstName: firstName,
|
||||
lastName: lastName,
|
||||
size: 31,
|
||||
size: 45,
|
||||
),
|
||||
MySpacing.width(12),
|
||||
|
||||
// Middle Content
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
MyText.titleSmall(
|
||||
contact.name,
|
||||
fontWeight: 700,
|
||||
color: Colors.black87,
|
||||
fontWeight: 600,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
MyText.bodySmall(
|
||||
contact.organization,
|
||||
fontWeight: 500,
|
||||
color: Colors.grey[700],
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
Get.to(() =>
|
||||
ContactDetailScreen(contact: contact));
|
||||
},
|
||||
child: const Icon(Icons.arrow_forward_ios,
|
||||
color: Colors.black, size: 15),
|
||||
),
|
||||
MySpacing.width(4),
|
||||
],
|
||||
),
|
||||
const Divider(),
|
||||
if (contact.contactEmails.isNotEmpty ||
|
||||
contact.contactPhones.isNotEmpty)
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// Email Row
|
||||
if (contact.contactEmails.isNotEmpty)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 5),
|
||||
child: Row(
|
||||
MySpacing.height(6),
|
||||
|
||||
// Launcher Row
|
||||
Wrap(
|
||||
spacing: 12,
|
||||
runSpacing: 6,
|
||||
children: [
|
||||
if (email != '-')
|
||||
GestureDetector(
|
||||
onTap: () =>
|
||||
LauncherUtils.launchEmail(email),
|
||||
child: const Padding(
|
||||
padding:
|
||||
EdgeInsets.only(right: 8.0),
|
||||
child: Icon(Icons.email_outlined,
|
||||
color: Colors.blue, size: 25),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: GestureDetector(
|
||||
onTap: () =>
|
||||
LauncherUtils.launchEmail(
|
||||
email),
|
||||
onLongPress: () =>
|
||||
LauncherUtils.copyToClipboard(
|
||||
email,
|
||||
typeLabel: 'Email'),
|
||||
child: MyText.bodyMedium(
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Icon(Icons.email_outlined,
|
||||
size: 16,
|
||||
color: Colors.indigo),
|
||||
MySpacing.width(4),
|
||||
ConstrainedBox(
|
||||
constraints:
|
||||
const BoxConstraints(
|
||||
maxWidth: 120),
|
||||
child: MyText.labelSmall(
|
||||
email,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
color: Colors.blue,
|
||||
fontWeight: 600,
|
||||
textAlign: TextAlign.start,
|
||||
overflow:
|
||||
TextOverflow.ellipsis,
|
||||
color: Colors.indigo,
|
||||
decoration:
|
||||
TextDecoration.underline,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
// Phone Row with icons at the end
|
||||
if (contact.contactPhones.isNotEmpty)
|
||||
Row(
|
||||
children: [
|
||||
// Phone Icon
|
||||
Padding(
|
||||
padding:
|
||||
const EdgeInsets.only(right: 6.0),
|
||||
child: GestureDetector(
|
||||
onTap: () =>
|
||||
LauncherUtils.launchPhone(phone),
|
||||
child: const Icon(
|
||||
Icons.phone_outlined,
|
||||
color: Colors.blue,
|
||||
size: 25),
|
||||
),
|
||||
),
|
||||
|
||||
// Phone number text
|
||||
Expanded(
|
||||
child: GestureDetector(
|
||||
if (phone != '-')
|
||||
GestureDetector(
|
||||
onTap: () =>
|
||||
LauncherUtils.launchPhone(phone),
|
||||
onLongPress: () =>
|
||||
LauncherUtils.copyToClipboard(
|
||||
phone,
|
||||
typeLabel: 'Phone number'),
|
||||
child: MyText.bodyMedium(
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Icon(Icons.phone_outlined,
|
||||
size: 16,
|
||||
color: Colors.indigo),
|
||||
MySpacing.width(4),
|
||||
ConstrainedBox(
|
||||
constraints:
|
||||
const BoxConstraints(
|
||||
maxWidth: 100),
|
||||
child: MyText.labelSmall(
|
||||
phone,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
color: Colors.blue,
|
||||
fontWeight: 600,
|
||||
textAlign: TextAlign.start,
|
||||
overflow:
|
||||
TextOverflow.ellipsis,
|
||||
color: Colors.indigo,
|
||||
decoration:
|
||||
TextDecoration.underline,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
// WhatsApp Icon
|
||||
Padding(
|
||||
padding:
|
||||
const EdgeInsets.only(right: 6.0),
|
||||
child: GestureDetector(
|
||||
if (tags.isNotEmpty) ...[
|
||||
MySpacing.height(4),
|
||||
MyText.labelSmall(
|
||||
tags.join(', '),
|
||||
color: Colors.grey[500],
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
// WhatsApp launcher icon
|
||||
Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Icon(Icons.arrow_forward_ios,
|
||||
color: Colors.grey, size: 16),
|
||||
MySpacing.height(12),
|
||||
if (phone != '-')
|
||||
GestureDetector(
|
||||
onTap: () =>
|
||||
LauncherUtils.launchWhatsApp(
|
||||
phone),
|
||||
LauncherUtils.launchWhatsApp(phone),
|
||||
child: const FaIcon(
|
||||
FontAwesomeIcons.whatsapp,
|
||||
color: Colors.green,
|
||||
size: 25),
|
||||
size: 20,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
MySpacing.height(8),
|
||||
// Tags Section
|
||||
if (tags.isNotEmpty)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 2),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
reverse:
|
||||
true, // ensures scroll starts from right
|
||||
child: Row(
|
||||
children: tags.map((name) {
|
||||
return Container(
|
||||
margin:
|
||||
const EdgeInsets.only(left: 6),
|
||||
child: TextButton(
|
||||
onPressed: () {},
|
||||
style: TextButton.styleFrom(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(
|
||||
horizontal: 10,
|
||||
vertical: 4,
|
||||
),
|
||||
backgroundColor:
|
||||
const Color.fromARGB(
|
||||
255, 179, 207, 246),
|
||||
tapTargetSize:
|
||||
MaterialTapTargetSize
|
||||
.shrinkWrap,
|
||||
minimumSize: Size.zero,
|
||||
visualDensity:
|
||||
VisualDensity.standard,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius:
|
||||
BorderRadius.circular(5),
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
name,
|
||||
style: const TextStyle(
|
||||
fontSize: 10,
|
||||
color: Color.fromARGB(
|
||||
255, 0, 0, 0),
|
||||
height: 1.2,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
|
Loading…
x
Reference in New Issue
Block a user