chore(app): 추천 기록 탭 대응과 스플래시 대기 제한
- RecommendationRecordCard에 onTap 콜백을 추가하고 카드 전체를 InkWell로 감싸 탭 제스처를 받을 수 있게 함\n- _navigateToHome에서 권한 요청 Future를 5초 타임아웃으로 감싸 스플래시에서 무한 대기를 막고, 완료 여부와 관계없이 홈으로 이동하도록 정리\n- 변경 의도 주석을 추가해 동작 맥락을 명시
This commit is contained in:
@@ -10,11 +10,15 @@ class RecommendationRecordCard extends ConsumerWidget {
|
|||||||
final VoidCallback onConfirmVisit;
|
final VoidCallback onConfirmVisit;
|
||||||
final VoidCallback onDelete;
|
final VoidCallback onDelete;
|
||||||
|
|
||||||
|
/// 카드 전체 탭(tap) 시 실행할 콜백.
|
||||||
|
final VoidCallback? onTap;
|
||||||
|
|
||||||
const RecommendationRecordCard({
|
const RecommendationRecordCard({
|
||||||
super.key,
|
super.key,
|
||||||
required this.recommendation,
|
required this.recommendation,
|
||||||
required this.onConfirmVisit,
|
required this.onConfirmVisit,
|
||||||
required this.onDelete,
|
required this.onDelete,
|
||||||
|
this.onTap,
|
||||||
});
|
});
|
||||||
|
|
||||||
String _formatTime(DateTime dateTime) {
|
String _formatTime(DateTime dateTime) {
|
||||||
@@ -43,130 +47,137 @@ class RecommendationRecordCard extends ConsumerWidget {
|
|||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
),
|
),
|
||||||
child: Padding(
|
child: InkWell(
|
||||||
padding: const EdgeInsets.all(16),
|
onTap: onTap,
|
||||||
child: Column(
|
borderRadius: BorderRadius.circular(12),
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
child: Padding(
|
||||||
children: [
|
padding: const EdgeInsets.all(16),
|
||||||
Row(
|
child: Column(
|
||||||
children: [
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
Container(
|
children: [
|
||||||
width: 40,
|
Row(
|
||||||
height: 40,
|
children: [
|
||||||
decoration: BoxDecoration(
|
Container(
|
||||||
color: Colors.orange.withValues(alpha: 0.1),
|
width: 40,
|
||||||
shape: BoxShape.circle,
|
height: 40,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.orange.withValues(alpha: 0.1),
|
||||||
|
shape: BoxShape.circle,
|
||||||
|
),
|
||||||
|
child: const Icon(
|
||||||
|
Icons.whatshot,
|
||||||
|
color: Colors.orange,
|
||||||
|
size: 24,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
child: const Icon(
|
const SizedBox(width: 16),
|
||||||
Icons.whatshot,
|
Expanded(
|
||||||
color: Colors.orange,
|
child: Column(
|
||||||
size: 24,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
),
|
children: [
|
||||||
),
|
Text(
|
||||||
const SizedBox(width: 16),
|
restaurant.name,
|
||||||
Expanded(
|
style: AppTypography.body1(
|
||||||
child: Column(
|
isDark,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
).copyWith(fontWeight: FontWeight.bold),
|
||||||
children: [
|
maxLines: 1,
|
||||||
Text(
|
overflow: TextOverflow.ellipsis,
|
||||||
restaurant.name,
|
),
|
||||||
style: AppTypography.body1(
|
const SizedBox(height: 4),
|
||||||
isDark,
|
Row(
|
||||||
).copyWith(fontWeight: FontWeight.bold),
|
children: [
|
||||||
maxLines: 1,
|
Icon(
|
||||||
overflow: TextOverflow.ellipsis,
|
Icons.category_outlined,
|
||||||
),
|
size: 14,
|
||||||
const SizedBox(height: 4),
|
color: isDark
|
||||||
Row(
|
? AppColors.darkTextSecondary
|
||||||
children: [
|
: AppColors.lightTextSecondary,
|
||||||
Icon(
|
|
||||||
Icons.category_outlined,
|
|
||||||
size: 14,
|
|
||||||
color: isDark
|
|
||||||
? AppColors.darkTextSecondary
|
|
||||||
: AppColors.lightTextSecondary,
|
|
||||||
),
|
|
||||||
const SizedBox(width: 4),
|
|
||||||
Text(
|
|
||||||
restaurant.category,
|
|
||||||
style: AppTypography.caption(isDark),
|
|
||||||
),
|
|
||||||
const SizedBox(width: 8),
|
|
||||||
Icon(
|
|
||||||
Icons.access_time,
|
|
||||||
size: 14,
|
|
||||||
color: isDark
|
|
||||||
? AppColors.darkTextSecondary
|
|
||||||
: AppColors.lightTextSecondary,
|
|
||||||
),
|
|
||||||
const SizedBox(width: 4),
|
|
||||||
Text(
|
|
||||||
_formatTime(recommendation.recommendationDate),
|
|
||||||
style: AppTypography.caption(isDark),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
const SizedBox(height: 8),
|
|
||||||
Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
const Icon(
|
|
||||||
Icons.info_outline,
|
|
||||||
size: 16,
|
|
||||||
color: Colors.orange,
|
|
||||||
),
|
|
||||||
const SizedBox(width: 6),
|
|
||||||
Expanded(
|
|
||||||
child: Text(
|
|
||||||
'추천만 받은 상태입니다. 방문 후 확인을 눌러 주세요.',
|
|
||||||
style: AppTypography.caption(isDark).copyWith(
|
|
||||||
color: Colors.orange,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
),
|
|
||||||
softWrap: true,
|
|
||||||
maxLines: 3,
|
|
||||||
overflow: TextOverflow.visible,
|
|
||||||
),
|
),
|
||||||
),
|
const SizedBox(width: 4),
|
||||||
],
|
Text(
|
||||||
),
|
restaurant.category,
|
||||||
],
|
style: AppTypography.caption(isDark),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
Icon(
|
||||||
|
Icons.access_time,
|
||||||
|
size: 14,
|
||||||
|
color: isDark
|
||||||
|
? AppColors.darkTextSecondary
|
||||||
|
: AppColors.lightTextSecondary,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 4),
|
||||||
|
Text(
|
||||||
|
_formatTime(
|
||||||
|
recommendation.recommendationDate,
|
||||||
|
),
|
||||||
|
style: AppTypography.caption(isDark),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const Icon(
|
||||||
|
Icons.info_outline,
|
||||||
|
size: 16,
|
||||||
|
color: Colors.orange,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 6),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
'추천만 받은 상태입니다. 방문 후 확인을 눌러 주세요.',
|
||||||
|
style: AppTypography.caption(isDark)
|
||||||
|
.copyWith(
|
||||||
|
color: Colors.orange,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
),
|
||||||
|
softWrap: true,
|
||||||
|
maxLines: 3,
|
||||||
|
overflow: TextOverflow.visible,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
const SizedBox(width: 12),
|
||||||
const SizedBox(width: 12),
|
ElevatedButton(
|
||||||
ElevatedButton(
|
onPressed: onConfirmVisit,
|
||||||
onPressed: onConfirmVisit,
|
style: ElevatedButton.styleFrom(
|
||||||
style: ElevatedButton.styleFrom(
|
backgroundColor: AppColors.lightPrimary,
|
||||||
backgroundColor: AppColors.lightPrimary,
|
foregroundColor: Colors.white,
|
||||||
foregroundColor: Colors.white,
|
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
minimumSize: const Size(0, 40),
|
||||||
minimumSize: const Size(0, 40),
|
),
|
||||||
|
child: const Text('방문 확인'),
|
||||||
),
|
),
|
||||||
child: const Text('방문 확인'),
|
],
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
const SizedBox(height: 10),
|
|
||||||
Container(
|
|
||||||
height: 1,
|
|
||||||
color: isDark
|
|
||||||
? AppColors.darkDivider
|
|
||||||
: AppColors.lightDivider,
|
|
||||||
),
|
|
||||||
Align(
|
|
||||||
alignment: Alignment.centerRight,
|
|
||||||
child: TextButton(
|
|
||||||
onPressed: onDelete,
|
|
||||||
style: TextButton.styleFrom(
|
|
||||||
foregroundColor: Colors.redAccent,
|
|
||||||
padding: const EdgeInsets.only(top: 6),
|
|
||||||
minimumSize: const Size(0, 32),
|
|
||||||
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
|
||||||
),
|
|
||||||
child: const Text('삭제'),
|
|
||||||
),
|
),
|
||||||
),
|
const SizedBox(height: 10),
|
||||||
],
|
Container(
|
||||||
|
height: 1,
|
||||||
|
color: isDark
|
||||||
|
? AppColors.darkDivider
|
||||||
|
: AppColors.lightDivider,
|
||||||
|
),
|
||||||
|
Align(
|
||||||
|
alignment: Alignment.centerRight,
|
||||||
|
child: TextButton(
|
||||||
|
onPressed: onDelete,
|
||||||
|
style: TextButton.styleFrom(
|
||||||
|
foregroundColor: Colors.redAccent,
|
||||||
|
padding: const EdgeInsets.only(top: 6),
|
||||||
|
minimumSize: const Size(0, 32),
|
||||||
|
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||||
|
),
|
||||||
|
child: const Text('삭제'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -247,13 +247,18 @@ class _SplashScreenState extends State<SplashScreen>
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _navigateToHome() {
|
void _navigateToHome() {
|
||||||
|
// 권한 요청이 지연되어도 스플래시(Splash) 화면이 멈추지 않도록 최대 5초만 대기한다.
|
||||||
|
final permissionFuture = _ensurePermissions().timeout(
|
||||||
|
const Duration(seconds: 5),
|
||||||
|
onTimeout: () {},
|
||||||
|
);
|
||||||
|
|
||||||
Future.wait([
|
Future.wait([
|
||||||
_ensurePermissions(),
|
permissionFuture,
|
||||||
Future.delayed(AppConstants.splashAnimationDuration),
|
Future.delayed(AppConstants.splashAnimationDuration),
|
||||||
]).then((_) {
|
]).whenComplete(() {
|
||||||
if (mounted) {
|
if (!mounted) return;
|
||||||
context.go('/home');
|
context.go('/home');
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user