feat(app): add manual entry and sharing flows
This commit is contained in:
208
lib/data/sample/manual_restaurant_samples.dart
Normal file
208
lib/data/sample/manual_restaurant_samples.dart
Normal file
@@ -0,0 +1,208 @@
|
||||
import 'package:lunchpick/domain/entities/restaurant.dart';
|
||||
import 'package:lunchpick/domain/entities/visit_record.dart';
|
||||
|
||||
/// 샘플 맛집과 방문 이력을 함께 제공하는 데이터 모델
|
||||
class ManualSampleData {
|
||||
final Restaurant restaurant;
|
||||
final List<VisitRecord> visits;
|
||||
|
||||
const ManualSampleData({required this.restaurant, required this.visits});
|
||||
}
|
||||
|
||||
/// 수동 입력을 위한 기본 맛집 샘플 세트
|
||||
class ManualRestaurantSamples {
|
||||
static List<ManualSampleData> build() {
|
||||
return [
|
||||
_buildSample(
|
||||
id: 'sample-euljiro-jinmi',
|
||||
name: '을지로 진미식당',
|
||||
category: '한식',
|
||||
subCategory: '백반/한정식',
|
||||
description:
|
||||
'50년 전통의 정갈한 백반집으로 제철 반찬과 명란구이가 유명합니다. 점심 회전율이 빨라 예약 없이 방문 가능.',
|
||||
phoneNumber: '02-777-1234',
|
||||
roadAddress: '서울 중구 을지로12길 34',
|
||||
jibunAddress: '서울 중구 수표동 67-1',
|
||||
latitude: 37.56698,
|
||||
longitude: 127.00531,
|
||||
visitDaysAgo: [3, 14, 27],
|
||||
),
|
||||
_buildSample(
|
||||
id: 'sample-seongsu-butter',
|
||||
name: '성수연방 버터',
|
||||
category: '카페',
|
||||
subCategory: '디저트 카페',
|
||||
description: '버터 향이 진한 크루아상과 라즈베리 타르트를 파는 성수연방 내 디저트 카페. 아침 9시에 오픈.',
|
||||
phoneNumber: '02-6204-1231',
|
||||
roadAddress: '서울 성동구 성수이로14길 14',
|
||||
jibunAddress: '서울 성동구 성수동2가 320-10',
|
||||
latitude: 37.54465,
|
||||
longitude: 127.05692,
|
||||
visitDaysAgo: [1, 2, 5, 12],
|
||||
),
|
||||
_buildSample(
|
||||
id: 'sample-mangwon-ramen',
|
||||
name: '망원 라라멘',
|
||||
category: '일식',
|
||||
subCategory: '라멘',
|
||||
description: '돼지뼈 육수에 유자 오일을 더한 하카타 스타일 라멘. 저녁에는 한정 교자도 제공.',
|
||||
phoneNumber: '02-333-9086',
|
||||
roadAddress: '서울 마포구 포은로 78-1',
|
||||
jibunAddress: '서울 마포구 망원동 389-50',
|
||||
latitude: 37.55721,
|
||||
longitude: 126.90763,
|
||||
visitDaysAgo: [9],
|
||||
),
|
||||
_buildSample(
|
||||
id: 'sample-haebangchon-salsa',
|
||||
name: '해방촌 살사포차',
|
||||
category: '세계요리',
|
||||
subCategory: '멕시칸/타코',
|
||||
description: '직접 구운 토르티야 위에 매콤한 살사를 얹어주는 캐주얼 타코펍. 주말에는 살사 댄스 클래스 운영.',
|
||||
phoneNumber: '02-792-7764',
|
||||
roadAddress: '서울 용산구 신흥로 68',
|
||||
jibunAddress: '서울 용산구 용산동2가 22-16',
|
||||
latitude: 37.54241,
|
||||
longitude: 126.9862,
|
||||
visitDaysAgo: [30, 45],
|
||||
),
|
||||
_buildSample(
|
||||
id: 'sample-yeonnam-poke',
|
||||
name: '연남 그로서리 포케',
|
||||
category: '세계요리',
|
||||
subCategory: '포케/샐러드',
|
||||
description: '직접 고른 토핑으로 만드는 하와이안 포케 볼 전문점. 비건 토핑과 현미밥 선택 가능.',
|
||||
phoneNumber: '02-336-0214',
|
||||
roadAddress: '서울 마포구 동교로38길 33',
|
||||
jibunAddress: '서울 마포구 연남동 229-54',
|
||||
latitude: 37.55955,
|
||||
longitude: 126.92579,
|
||||
visitDaysAgo: [6, 21],
|
||||
),
|
||||
_buildSample(
|
||||
id: 'sample-jeongdong-brewery',
|
||||
name: '정동 브루어리',
|
||||
category: '주점',
|
||||
subCategory: '수제맥주펍',
|
||||
description: '소규모 양조 탱크를 갖춘 다운타운 브루펍. 시즈널 IPA와 훈제 플래터를 함께 즐길 수 있습니다.',
|
||||
phoneNumber: '02-720-8183',
|
||||
roadAddress: '서울 중구 정동길 21-15',
|
||||
jibunAddress: '서울 중구 정동 1-18',
|
||||
latitude: 37.56605,
|
||||
longitude: 126.97013,
|
||||
visitDaysAgo: [10, 60, 120],
|
||||
),
|
||||
_buildSample(
|
||||
id: 'sample-mokdong-lamb',
|
||||
name: '목동 참숯 양꼬치',
|
||||
category: '중식',
|
||||
subCategory: '양꼬치/바비큐',
|
||||
description: '매장에서 직접 손질한 어린양 꼬치를 참숯에 구워내는 곳. 마라볶음과 칭다오 생맥 조합 추천.',
|
||||
phoneNumber: '02-2653-4411',
|
||||
roadAddress: '서울 양천구 목동동로 377',
|
||||
jibunAddress: '서울 양천구 목동 907-2',
|
||||
latitude: 37.52974,
|
||||
longitude: 126.86455,
|
||||
visitDaysAgo: [2],
|
||||
),
|
||||
_buildSample(
|
||||
id: 'sample-busan-minrak-burger',
|
||||
name: '부산 민락 수제버거',
|
||||
category: '패스트푸드',
|
||||
subCategory: '수제버거',
|
||||
description:
|
||||
'광안리 바다가 내려다보이는 루프탑 버거 전문점. 패티를 미디엄으로 구워 치즈와 구운 파인애플을 올립니다.',
|
||||
phoneNumber: '051-754-2278',
|
||||
roadAddress: '부산 수영구 광안해변로 141',
|
||||
jibunAddress: '부산 수영구 민락동 181-5',
|
||||
latitude: 35.15302,
|
||||
longitude: 129.1183,
|
||||
visitDaysAgo: [15, 32],
|
||||
),
|
||||
_buildSample(
|
||||
id: 'sample-jeju-dongmun-pasta',
|
||||
name: '제주 동문 파스타바',
|
||||
category: '양식',
|
||||
subCategory: '파스타/와인바',
|
||||
description: '동문시장 골목의 오픈키친 파스타바. 한치 크림 파스타와 제주산 와인을 코스로 제공.',
|
||||
phoneNumber: '064-723-9012',
|
||||
roadAddress: '제주 제주시 관덕로14길 18',
|
||||
jibunAddress: '제주 제주시 일도일동 1113-4',
|
||||
latitude: 33.51227,
|
||||
longitude: 126.52686,
|
||||
visitDaysAgo: [4, 11, 19],
|
||||
),
|
||||
_buildSample(
|
||||
id: 'sample-daegu-market-sand',
|
||||
name: '대구 중앙시장 샌드',
|
||||
category: '카페',
|
||||
subCategory: '샌드위치/브런치',
|
||||
description:
|
||||
'직접 구운 식빵과 사과 절임으로 만드는 시그니처 에그샐러드 샌드. 평일 오전 8시부터 테이크아웃 가능.',
|
||||
phoneNumber: '053-256-8874',
|
||||
roadAddress: '대구 중구 중앙대로 363-1',
|
||||
jibunAddress: '대구 중구 남일동 135-1',
|
||||
latitude: 35.87053,
|
||||
longitude: 128.59404,
|
||||
visitDaysAgo: [7, 44, 90],
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
static ManualSampleData _buildSample({
|
||||
required String id,
|
||||
required String name,
|
||||
required String category,
|
||||
required String subCategory,
|
||||
required String description,
|
||||
required String phoneNumber,
|
||||
required String roadAddress,
|
||||
required String jibunAddress,
|
||||
required double latitude,
|
||||
required double longitude,
|
||||
required List<int> visitDaysAgo,
|
||||
}) {
|
||||
final now = DateTime.now();
|
||||
final visitDates =
|
||||
visitDaysAgo.map((days) => now.subtract(Duration(days: days))).toList()
|
||||
..sort((a, b) => b.compareTo(a)); // 최신순
|
||||
|
||||
final restaurant = Restaurant(
|
||||
id: id,
|
||||
name: name,
|
||||
category: category,
|
||||
subCategory: subCategory,
|
||||
description: description,
|
||||
phoneNumber: phoneNumber,
|
||||
roadAddress: roadAddress,
|
||||
jibunAddress: jibunAddress,
|
||||
latitude: latitude,
|
||||
longitude: longitude,
|
||||
lastVisitDate: visitDates.isNotEmpty ? visitDates.first : null,
|
||||
source: DataSource.USER_INPUT,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
naverPlaceId: null,
|
||||
naverUrl: null,
|
||||
businessHours: null,
|
||||
lastVisited: visitDates.isNotEmpty ? visitDates.first : null,
|
||||
visitCount: visitDates.length,
|
||||
);
|
||||
|
||||
final visits = <VisitRecord>[];
|
||||
for (var i = 0; i < visitDates.length; i++) {
|
||||
final visitDate = visitDates[i];
|
||||
visits.add(
|
||||
VisitRecord(
|
||||
id: '${id}_visit_$i',
|
||||
restaurantId: id,
|
||||
visitDate: visitDate,
|
||||
isConfirmed: true,
|
||||
createdAt: visitDate,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return ManualSampleData(restaurant: restaurant, visits: visits);
|
||||
}
|
||||
}
|
||||
27
lib/data/sample/sample_data_initializer.dart
Normal file
27
lib/data/sample/sample_data_initializer.dart
Normal file
@@ -0,0 +1,27 @@
|
||||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
import 'package:lunchpick/core/constants/app_constants.dart';
|
||||
import 'package:lunchpick/domain/entities/restaurant.dart';
|
||||
import 'package:lunchpick/domain/entities/visit_record.dart';
|
||||
|
||||
import 'manual_restaurant_samples.dart';
|
||||
|
||||
/// 초기 구동 시 샘플 데이터를 채워 넣는 도우미
|
||||
class SampleDataInitializer {
|
||||
static Future<void> seedManualRestaurantsIfNeeded() async {
|
||||
final restaurantBox = Hive.box<Restaurant>(AppConstants.restaurantBox);
|
||||
final visitBox = Hive.box<VisitRecord>(AppConstants.visitRecordBox);
|
||||
|
||||
// 이미 사용자 데이터가 있으면 샘플을 추가하지 않음
|
||||
if (restaurantBox.isNotEmpty || visitBox.isNotEmpty) {
|
||||
return;
|
||||
}
|
||||
|
||||
final samples = ManualRestaurantSamples.build();
|
||||
for (final sample in samples) {
|
||||
await restaurantBox.put(sample.restaurant.id, sample.restaurant);
|
||||
for (final visit in sample.visits) {
|
||||
await visitBox.put(visit.id, visit);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user