From 48c22d76d00a4048f68009dc143b8bf16112f2b8 Mon Sep 17 00:00:00 2001 From: JiWoong Sul Date: Wed, 28 Jan 2026 18:54:44 +0900 Subject: [PATCH] =?UTF-8?q?fix(form):=20=ED=8F=BC=20=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=84=B0=20=EC=83=9D=EC=84=B1=20=EC=8B=9C=20URL=20=EC=B6=94?= =?UTF-8?q?=EC=B6=9C=20=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - RestaurantFormData.fromControllers에 _extractNaverUrl 추가 - 공유 텍스트에서 순수 URL만 추출하여 저장 - 폼 필드 변경 시에도 올바른 URL 유지 --- .../add_restaurant_view_model.dart | 39 +++++++++++++++---- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/lib/presentation/view_models/add_restaurant_view_model.dart b/lib/presentation/view_models/add_restaurant_view_model.dart index cd34f01..b0a5568 100644 --- a/lib/presentation/view_models/add_restaurant_view_model.dart +++ b/lib/presentation/view_models/add_restaurant_view_model.dart @@ -8,6 +8,15 @@ import '../providers/di_providers.dart'; import '../providers/restaurant_provider.dart'; import '../providers/location_provider.dart'; +/// 지오코딩 실패 시 발생하는 예외 +class GeocodingException implements Exception { + final String message; + const GeocodingException(this.message); + + @override + String toString() => message; +} + /// 식당 추가 화면의 상태 모델 class AddRestaurantState { final bool isLoading; @@ -128,10 +137,23 @@ class RestaurantFormData { jibunAddress: jibunAddressController.text.trim(), latitude: latitudeController.text.trim(), longitude: longitudeController.text.trim(), - naverUrl: naverUrlController.text.trim(), + naverUrl: _extractNaverUrl(naverUrlController.text.trim()), ); } + /// 공유 텍스트에서 네이버 지도 URL만 추출 + static String _extractNaverUrl(String text) { + if (text.isEmpty) return ''; + + // URL 패턴 추출 + final urlRegex = RegExp( + r'(https?://(?:map\.naver\.com|naver\.me)[^\s]+)', + caseSensitive: false, + ); + final match = urlRegex.firstMatch(text); + return match?.group(0) ?? text; + } + /// Restaurant 엔티티로부터 폼 데이터 생성 factory RestaurantFormData.fromRestaurant(Restaurant restaurant) { return RestaurantFormData( @@ -351,7 +373,11 @@ class AddRestaurantViewModel extends StateNotifier { state = state.copyWith(isLoading: false); return true; } catch (e) { - state = state.copyWith(isLoading: false, errorMessage: e.toString()); + // GeocodingException은 이미 사용자 친화적 메시지가 설정됨 + final message = e is GeocodingException + ? e.message + : '저장 중 오류가 발생했습니다. 다시 시도해주세요.'; + state = state.copyWith(isLoading: false, errorMessage: message); return false; } } @@ -474,12 +500,9 @@ class AddRestaurantViewModel extends StateNotifier { ); if (!allowFallbackWhenGeocodingFails) { - state = state.copyWith( - errorMessage: - '주소가 지도에서 인식되지 않습니다. ' - '도로명 주소 전체를 정확히 입력했는지 확인해 주세요.', - ); - throw Exception('지오코딩 실패: $address'); + const userMessage = '위치 정보를 가져올 수 없습니다. 주소를 확인해주세요.'; + state = state.copyWith(errorMessage: userMessage); + throw GeocodingException(userMessage); } } }