feat(app): stabilize recommendation flow

This commit is contained in:
JiWoong Sul
2025-12-01 17:22:21 +09:00
parent d05e378569
commit c1aa16c521
12 changed files with 422 additions and 260 deletions

View File

@@ -3,6 +3,7 @@ import 'dart:async';
import 'package:flutter/material.dart';
import 'package:lunchpick/core/constants/app_colors.dart';
import 'package:lunchpick/core/constants/app_typography.dart';
import 'package:lunchpick/core/utils/distance_calculator.dart';
import 'package:lunchpick/domain/entities/restaurant.dart';
enum RecommendationDialogResult { confirm, reroll, autoConfirm }
@@ -10,11 +11,15 @@ enum RecommendationDialogResult { confirm, reroll, autoConfirm }
class RecommendationResultDialog extends StatefulWidget {
final Restaurant restaurant;
final Duration autoConfirmDuration;
final double? currentLatitude;
final double? currentLongitude;
const RecommendationResultDialog({
super.key,
required this.restaurant,
this.autoConfirmDuration = const Duration(seconds: 12),
this.currentLatitude,
this.currentLongitude,
});
@override
@@ -26,10 +31,12 @@ class _RecommendationResultDialogState
extends State<RecommendationResultDialog> {
Timer? _autoConfirmTimer;
bool _didComplete = false;
double? _distanceKm;
@override
void initState() {
super.initState();
_calculateDistance();
_startAutoConfirmTimer();
}
@@ -47,6 +54,27 @@ class _RecommendationResultDialogState
});
}
void _calculateDistance() {
final lat = widget.currentLatitude;
final lon = widget.currentLongitude;
if (lat == null || lon == null) return;
_distanceKm = DistanceCalculator.calculateDistance(
lat1: lat,
lon1: lon,
lat2: widget.restaurant.latitude,
lon2: widget.restaurant.longitude,
);
}
String _formatDistance(double distanceKm) {
final meters = distanceKm * 1000;
if (meters >= 1000) {
return '${distanceKm.toStringAsFixed(1)} km';
}
return '${meters.round()} m';
}
Future<void> _handleResult(RecommendationDialogResult result) async {
if (_didComplete) return;
_didComplete = true;
@@ -177,6 +205,26 @@ class _RecommendationResultDialogState
),
],
),
if (_distanceKm != null) ...[
const SizedBox(height: 8),
Row(
children: [
Icon(
Icons.place,
size: 20,
color: AppColors.lightPrimary,
),
const SizedBox(width: 8),
Text(
_formatDistance(_distanceKm!),
style: AppTypography.body2(isDark).copyWith(
color: AppColors.lightPrimary,
fontWeight: FontWeight.w600,
),
),
],
),
],
if (widget.restaurant.phoneNumber != null) ...[
const SizedBox(height: 8),
Row(
@@ -237,14 +285,14 @@ class _RecommendationResultDialogState
borderRadius: BorderRadius.circular(8),
),
),
child: const Text('닫기'),
child: const Text('오늘의 선택!'),
),
),
],
),
const SizedBox(height: 8),
Text(
'조용히 두면 자동으로 방문 처리되고 알림이 예약됩니다.',
'앱을 종료하면 자동으로 선택이 확정됩니다.',
style: AppTypography.caption(isDark),
textAlign: TextAlign.center,
),