import '../../core/utils/validators.dart'; import '../view_models/add_restaurant_view_model.dart'; /// 식당 폼 검증 서비스 class RestaurantFormValidator { /// 폼 데이터 검증 static Map validateFormData(RestaurantFormData formData) { final errors = {}; // 이름 검증 if (formData.name.isEmpty) { errors['name'] = '가게 이름을 입력해주세요'; } // 카테고리 검증 if (formData.category.isEmpty) { errors['category'] = '카테고리를 입력해주세요'; } // 도로명 주소 검증 if (formData.roadAddress.isEmpty) { errors['roadAddress'] = '도로명 주소를 입력해주세요'; } // 위도 검증 if (formData.latitude.isNotEmpty) { final latitudeError = Validators.validateLatitude(formData.latitude); if (latitudeError != null) { errors['latitude'] = latitudeError; } } // 경도 검증 if (formData.longitude.isNotEmpty) { final longitudeError = Validators.validateLongitude(formData.longitude); if (longitudeError != null) { errors['longitude'] = longitudeError; } } return errors; } /// 네이버 URL 검증 static String? validateNaverUrl(String url) { if (url.trim().isEmpty) { return 'URL을 입력해주세요'; } // 네이버 지도 URL 패턴 검증 final naverMapRegex = RegExp( r'^https?://(map\.naver\.com|naver\.me)', caseSensitive: false, ); if (!naverMapRegex.hasMatch(url)) { return '네이버 지도 URL만 입력 가능합니다'; } return null; } /// 전화번호 형식 검증 static String? validatePhoneNumber(String? phoneNumber) { if (phoneNumber == null || phoneNumber.isEmpty) { return null; // 선택 필드 } // 전화번호 패턴: 02-1234-5678, 010-1234-5678 등 final phoneRegex = RegExp(r'^0\d{1,2}-?\d{3,4}-?\d{4}$'); if (!phoneRegex.hasMatch(phoneNumber.replaceAll(' ', ''))) { return '올바른 전화번호 형식이 아닙니다'; } return null; } /// 주소 형식 검증 static String? validateAddress(String? address) { if (address == null || address.isEmpty) { return '주소를 입력해주세요'; } // 최소 길이 검증 if (address.length < 5) { return '올바른 주소를 입력해주세요'; } return null; } /// 카테고리 검증 static String? validateCategory(String? category) { if (category == null || category.isEmpty) { return '카테고리를 입력해주세요'; } // 허용된 카테고리 목록 (필요시 추가) // final allowedCategories = [ // '한식', '중식', '일식', '양식', '아시안', // '카페', '디저트', '분식', '패스트푸드', '기타' // ]; // 정확한 매칭이 아니어도 허용 (사용자 입력 고려) // 필요시 더 엄격한 검증 추가 가능 return null; } /// 전체 폼 유효성 검사 static bool isFormValid(RestaurantFormData formData) { final errors = validateFormData(formData); return errors.isEmpty; } /// 필수 필드만 검증 static bool hasRequiredFields(RestaurantFormData formData) { return formData.name.isNotEmpty && formData.category.isNotEmpty && formData.roadAddress.isNotEmpty; } } /// 폼 필드 에러 메시지 클래스 class FormFieldErrors { final String? name; final String? category; final String? roadAddress; final String? latitude; final String? longitude; final String? phoneNumber; const FormFieldErrors({ this.name, this.category, this.roadAddress, this.latitude, this.longitude, this.phoneNumber, }); bool get hasErrors => name != null || category != null || roadAddress != null || latitude != null || longitude != null || phoneNumber != null; Map toMap() { final map = {}; if (name != null) map['name'] = name!; if (category != null) map['category'] = category!; if (roadAddress != null) map['roadAddress'] = roadAddress!; if (latitude != null) map['latitude'] = latitude!; if (longitude != null) map['longitude'] = longitude!; if (phoneNumber != null) map['phoneNumber'] = phoneNumber!; return map; } }