feat: 초기 프로젝트 설정 및 LunchPick 앱 구현
LunchPick(오늘 뭐 먹Z?) Flutter 앱의 초기 구현입니다. 주요 기능: - 네이버 지도 연동 맛집 추가 - 랜덤 메뉴 추천 시스템 - 날씨 기반 거리 조정 - 방문 기록 관리 - Bluetooth 맛집 공유 - 다크모드 지원 기술 스택: - Flutter 3.8.1+ - Riverpod 상태 관리 - Hive 로컬 DB - Clean Architecture 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
163
lib/presentation/services/restaurant_form_validator.dart
Normal file
163
lib/presentation/services/restaurant_form_validator.dart
Normal file
@@ -0,0 +1,163 @@
|
||||
import '../../core/utils/validators.dart';
|
||||
import '../view_models/add_restaurant_view_model.dart';
|
||||
|
||||
/// 식당 폼 검증 서비스
|
||||
class RestaurantFormValidator {
|
||||
/// 폼 데이터 검증
|
||||
static Map<String, String?> validateFormData(RestaurantFormData formData) {
|
||||
final errors = <String, String?>{};
|
||||
|
||||
// 이름 검증
|
||||
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<String, String> toMap() {
|
||||
final map = <String, String>{};
|
||||
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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user