rup-project/app/lib/widgets/common/pet_selection_header.dart

257 lines
9.2 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_svg/flutter_svg.dart';
import '../../models/pet_model.dart';
import '../../theme/app_colors.dart';
class PetSelectionHeader extends StatelessWidget {
final List<Pet> pets;
final Pet? selectedPet;
final ValueChanged<Pet> onPetSelected;
final VoidCallback onAddPetPressed;
const PetSelectionHeader({
super.key,
required this.pets,
required this.selectedPet,
required this.onPetSelected,
required this.onAddPetPressed,
});
@override
Widget build(BuildContext context) {
// If no pet selected (and list is empty), show Add Pet UI or minimal hint
if (pets.isEmpty) {
// Returning null or minimal UI might be better, but user asked for "Consistent Header"
// The HomeScreen shows a "Register Pet + " button if empty.
// Let's implement that logic here for consistency if pets are empty.
return Material(
color: Colors.transparent,
child: InkWell(
borderRadius: BorderRadius.circular(8.r),
onTap: onAddPetPressed,
child: Padding(
padding: EdgeInsets.symmetric(vertical: 4.h, horizontal: 12.w),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Image.asset(
'assets/img/profile.png',
width: 40.w,
height: 40.h,
),
SizedBox(width: 6.w),
Text(
'반려동물 등록 +',
style: TextStyle(
fontFamily: 'SCDream',
fontWeight: FontWeight.w500,
fontSize: 15.sp,
letterSpacing: 0.45.sp,
color: const Color(0xFF1f1f1f),
),
),
],
),
),
),
);
}
// Default display pet
final displayPet = selectedPet ?? pets.first;
return Material(
color: Colors.transparent,
child: InkWell(
borderRadius: BorderRadius.circular(8.r),
onTap: () {
final RenderBox button = context.findRenderObject() as RenderBox;
final RenderBox overlay =
Navigator.of(context).overlay!.context.findRenderObject()
as RenderBox;
final RelativeRect position = RelativeRect.fromRect(
Rect.fromPoints(
button.localToGlobal(Offset(0, 50.h), ancestor: overlay),
button.localToGlobal(
button.size.bottomRight(Offset.zero),
ancestor: overlay,
),
),
Offset.zero & overlay.size,
);
showMenu<dynamic>(
context: context,
position: position,
elevation: 3,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12.r),
),
color: Colors.white,
surfaceTintColor: Colors.white,
items: [
...pets.map(
(pet) => PopupMenuItem<Pet>(
value: pet,
child: Row(
children: [
Container(
width: 32.w,
height: 32.w,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.grey[200],
),
clipBehavior: Clip.hardEdge,
child: pet.profileImageUrl != null
? Image.network(
pet.profileImageUrl!,
fit: BoxFit.cover,
errorBuilder: (context, error, stackTrace) {
return Center(
child: SvgPicture.asset(
'assets/icons/profile_icon.svg',
width: 16.w,
colorFilter: ColorFilter.mode(
Colors.grey[400]!,
BlendMode.srcIn,
),
),
);
},
)
: Center(
child: SvgPicture.asset(
'assets/icons/profile_icon.svg',
width: 16.w,
colorFilter: ColorFilter.mode(
Colors.grey[400]!,
BlendMode.srcIn,
),
),
),
),
SizedBox(width: 10.w),
Text(
pet.name,
style: TextStyle(
fontFamily: 'SCDream',
fontSize: 14.sp,
fontWeight: pet.id == displayPet.id
? FontWeight.bold
: FontWeight.normal,
color: pet.id == displayPet.id
? AppColors.highlight
: Colors.black,
),
),
if (pet.id == displayPet.id) ...[
const Spacer(),
const Icon(
Icons.check,
color: AppColors.highlight,
size: 16,
),
],
],
),
),
),
const PopupMenuDivider(),
PopupMenuItem<String>(
value: 'add_pet',
child: Row(
children: [
Container(
padding: EdgeInsets.all(4.w),
decoration: BoxDecoration(
color: Colors.grey[100],
shape: BoxShape.circle,
),
child: Icon(Icons.add, size: 16.w, color: Colors.black54),
),
SizedBox(width: 10.w),
Text(
'반려동물 추가하기',
style: TextStyle(
fontFamily: 'SCDream',
fontSize: 14.sp,
fontWeight: FontWeight.w500,
),
),
],
),
),
],
).then((value) {
if (value != null) {
if (value is Pet) {
onPetSelected(value);
} else if (value == 'add_pet') {
onAddPetPressed();
}
}
});
},
child: Padding(
padding: EdgeInsets.symmetric(vertical: 4.h, horizontal: 12.w),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Container(
width: 40.w,
height: 40.w,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.grey[200],
),
clipBehavior: Clip.hardEdge,
child: displayPet.profileImageUrl != null
? Image.network(
displayPet.profileImageUrl!,
fit: BoxFit.cover,
errorBuilder: (context, error, stackTrace) {
return Center(
child: SvgPicture.asset(
'assets/icons/profile_icon.svg',
width: 20.w,
colorFilter: ColorFilter.mode(
Colors.grey[400]!,
BlendMode.srcIn,
),
),
);
},
)
: Center(
child: SvgPicture.asset(
'assets/icons/profile_icon.svg',
width: 20.w,
colorFilter: ColorFilter.mode(
Colors.grey[400]!,
BlendMode.srcIn,
),
),
),
),
SizedBox(width: 10.w),
Text(
displayPet.name,
style: TextStyle(
fontFamily: 'SCDream',
fontWeight: FontWeight.bold,
fontSize: 18.sp,
color: Colors.black,
),
),
SizedBox(width: 4.w),
Icon(Icons.keyboard_arrow_down, size: 24.w, color: Colors.black),
],
),
),
),
);
}
}