Files
social-app/apps/lib/features/contacts/ui/screens/add_contact_screen.dart
T
qzl 8d4a14150b feat(apps): update UI screens and shared components
- Update home screen with new composer and interactions
- Update settings screens with new profile flow
- Update calendar share dialog
- Update contacts screen
- Add new shared widgets: confirm_sheet, phone_prefix_selector
- Add new formatters: phone_display_formatter
- Update tests for modified components
2026-03-19 18:43:08 +08:00

192 lines
5.4 KiB
Dart

import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import '../../../../core/theme/design_tokens.dart';
import '../../../../shared/widgets/back_title_page_header.dart';
import '../../../../shared/widgets/app_input.dart';
import '../../../../shared/widgets/link_button.dart';
import '../../../../shared/widgets/toast/toast.dart';
import '../../../../shared/widgets/toast/toast_type.dart';
class AddContactScreen extends StatefulWidget {
final String? contactId;
const AddContactScreen({super.key, this.contactId});
@override
State<AddContactScreen> createState() => _AddContactScreenState();
}
class _AddContactScreenState extends State<AddContactScreen> {
final _nameController = TextEditingController();
final _phoneController = TextEditingController();
final _remarkController = TextEditingController();
bool get isEditing => widget.contactId != null;
@override
void dispose() {
_nameController.dispose();
_phoneController.dispose();
_remarkController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppColors.surfaceSecondary,
resizeToAvoidBottomInset: false,
body: SafeArea(
maintainBottomViewPadding: true,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
BackTitlePageHeader(
title: isEditing ? '编辑联系人' : '添加联系人',
onBack: () => context.pop(),
trailing: _buildConfirmButton(),
),
Expanded(
child: SingleChildScrollView(
padding: const EdgeInsets.fromLTRB(20, 8, 20, 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
_buildAvatarSection(),
const SizedBox(height: 14),
_buildFormCard(),
if (isEditing) ...[
const SizedBox(height: 14),
_buildDeleteRow(),
],
],
),
),
),
],
),
),
);
}
Widget _buildConfirmButton() {
return SizedBox(
width: AppSpacing.xxl * 2,
height: AppSpacing.xxl * 2,
child: TextButton(
onPressed: _handleConfirm,
style: TextButton.styleFrom(
padding: const EdgeInsets.all(AppSpacing.none),
backgroundColor: AppColors.surfaceInfo,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(AppRadius.full),
side: const BorderSide(color: AppColors.borderQuaternary),
),
),
child: const Icon(
Icons.check,
size: AppSpacing.lg,
color: AppColors.blue600,
),
),
);
}
Widget _buildAvatarSection() {
return Center(
child: Container(
width: 72,
height: 72,
decoration: BoxDecoration(
color: AppColors.surfaceInfoLight,
borderRadius: BorderRadius.circular(36),
border: Border.all(color: Colors.transparent),
),
child: const Icon(
Icons.person_outline,
size: 24,
color: AppColors.slate400,
),
),
);
}
Widget _buildFormCard() {
return Container(
padding: const EdgeInsets.all(14),
decoration: BoxDecoration(
color: AppColors.white,
borderRadius: BorderRadius.circular(16),
border: Border.all(color: AppColors.messageCardBorder),
),
child: Column(
children: [
AppInput(label: '昵称', hint: '请输入昵称', controller: _nameController),
const SizedBox(height: 14),
AppInput(
label: '手机号',
hint: '+86 请输入 11 位手机号',
controller: _phoneController,
keyboardType: TextInputType.phone,
),
const SizedBox(height: 14),
AppInput(
label: '备注',
hint: '请输入备注',
controller: _remarkController,
maxLines: 3,
),
],
),
);
}
Widget _buildDeleteRow() {
return Padding(
padding: const EdgeInsets.only(bottom: AppSpacing.sm),
child: LinkButton(
text: '删除联系人',
onTap: _handleDelete,
foregroundColor: AppColors.red600,
),
);
}
void _handleConfirm() {
final name = _nameController.text.trim();
final phone = _phoneController.text.trim();
if (name.isEmpty || phone.isEmpty) {
Toast.show(context, '请填写昵称和手机号', type: ToastType.warning);
return;
}
// TODO: Implement save logic
context.pop();
}
void _handleDelete() {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text('删除联系人'),
content: const Text('确定要删除此联系人吗?'),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: const Text('取消'),
),
TextButton(
onPressed: () {
Navigator.pop(context);
// TODO: Implement delete logic
context.pop();
},
child: const Text('删除', style: TextStyle(color: AppColors.red600)),
),
],
),
);
}
}