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:
JiWoong Sul
2025-07-30 19:03:28 +09:00
commit 85fde36157
237 changed files with 30953 additions and 0 deletions

View File

@@ -0,0 +1,164 @@
# AddRestaurantDialog JSON 스타일 UI 디자인
## 개요
네이버 URL에서 가져온 맛집 정보를 JSON 형식으로 보여주는 UI 디자인 명세서입니다.
## 디자인 컨셉
- **JSON 시각화**: 개발자 친화적인 JSON 형식으로 데이터를 표현
- **편집 가능**: 각 필드를 직접 수정할 수 있는 인터랙티브 UI
- **Material Design 3**: 최신 디자인 가이드라인 준수
- **다크모드 지원**: 라이트/다크 테마 완벽 지원
## 컴포넌트 구조
### 1. 메인 컨테이너
```dart
Container(
padding: EdgeInsets.all(16),
decoration: BoxDecoration(
color: isDark ? AppColors.darkBackground : AppColors.lightBackground.withOpacity(0.5),
borderRadius: BorderRadius.circular(12),
border: Border.all(
color: isDark ? AppColors.darkDivider : AppColors.lightDivider,
),
),
)
```
- 반투명 배경으로 깊이감 표현
- 둥근 모서리와 테두리로 구분
### 2. 헤더 영역
```dart
Row(
children: [
Icon(Icons.code, size: 20),
SizedBox(width: 8),
Text('가져온 정보', style: TextStyle(fontSize: 14, fontWeight: FontWeight.w600)),
],
)
```
- 코드 아이콘으로 JSON 데이터임을 시각적으로 표현
- 적절한 간격과 타이포그래피
### 3. JSON 필드 컴포넌트
각 필드는 `_buildJsonField` 메서드로 일관성 있게 구현:
#### 기본 필드 구조
```dart
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// 레이블
Row(
children: [
Icon(icon, size: 16), // 필드별 아이콘
SizedBox(width: 8),
Text('$label:', style: labelStyle),
],
),
SizedBox(height: 4),
// 입력 필드
TextFormField(
controller: controller,
style: TextStyle(
fontSize: 14,
fontFamily: isLink ? 'monospace' : null,
),
decoration: InputDecoration(
isDense: true,
contentPadding: EdgeInsets.symmetric(horizontal: 12, vertical: 8),
filled: true,
fillColor: isDark ? AppColors.darkSurface : Colors.white,
border: OutlineInputBorder(borderRadius: BorderRadius.circular(8)),
),
),
],
)
```
#### 좌표 필드 (특수 처리)
```dart
Row(
children: [
Expanded(child: TextFormField(...)), // 위도
Text(',', style: monoStyle),
Expanded(child: TextFormField(...)), // 경도
],
)
```
## 색상 팔레트
### 라이트 모드
- **배경**: `AppColors.lightBackground.withOpacity(0.5)`
- **테두리**: `AppColors.lightDivider`
- **필드 배경**: `Colors.white`
- **텍스트**: `AppColors.lightText`
- **보조 텍스트**: `AppColors.lightTextSecondary`
- **링크**: `AppColors.lightPrimary`
### 다크 모드
- **배경**: `AppColors.darkBackground`
- **테두리**: `AppColors.darkDivider`
- **필드 배경**: `AppColors.darkSurface`
- **텍스트**: `AppColors.darkText`
- **보조 텍스트**: `AppColors.darkTextSecondary`
- **링크**: `AppColors.lightPrimary` (동일)
## 아이콘 매핑
| 필드 | 아이콘 | 의미 |
|------|--------|------|
| 이름 | `Icons.store` | 가게/상점 |
| 카테고리 | `Icons.category` | 분류 |
| 세부 카테고리 | `Icons.label_outline` | 태그/라벨 |
| 주소 | `Icons.location_on` | 위치 |
| 전화 | `Icons.phone` | 연락처 |
| 설명 | `Icons.description` | 설명/문서 |
| 좌표 | `Icons.my_location` | GPS 좌표 |
| 링크 | `Icons.link` | 외부 링크 |
## 타이포그래피
- **레이블**: 13px, FontWeight.w500
- **값**: 14px, 일반
- **링크**: 14px, monospace 폰트, underline
- **좌표**: 14px, monospace 폰트
## 인터랙션
### 1. 가져오기 플로우
1. URL 입력
2. "가져오기" 버튼 클릭
3. 로딩 상태 표시
4. 성공 시: JSON 스타일 UI 표시
5. 실패 시: 에러 메시지 표시
### 2. 편집 플로우
1. 각 필드 직접 수정 가능
2. 좌표는 위도/경도 분리 입력
3. 링크는 monospace 폰트와 밑줄로 구분
### 3. 저장/초기화
- **초기화**: 모든 필드 클리어, UI 리셋
- **저장**: 수정된 데이터로 맛집 추가
## 반응형 디자인
- 최대 너비: 400px (Dialog 제약)
- 스크롤 가능한 영역
- 모바일/태블릿 최적화
## 접근성
- 적절한 대비율 유지
- 터치 타겟 최소 44x44px
- 키보드 네비게이션 지원
- 스크린 리더 호환
## 애니메이션
- 필드 포커스: 부드러운 테두리 전환
- 버튼 상태: 색상 페이드
- 로딩: CircularProgressIndicator
## 구현 고려사항
1. **상태 관리**: `_fetchedRestaurantData` Map으로 데이터 추적
2. **폼 검증**: 각 필드별 적절한 검증
3. **에러 처리**: 사용자 친화적 메시지
4. **성능**: 불필요한 리빌드 방지