LunchPick(오늘 뭐 먹Z?) Flutter 앱의 초기 구현입니다. 주요 기능: - 네이버 지도 연동 맛집 추가 - 랜덤 메뉴 추천 시스템 - 날씨 기반 거리 조정 - 방문 기록 관리 - Bluetooth 맛집 공유 - 다크모드 지원 기술 스택: - Flutter 3.8.1+ - Riverpod 상태 관리 - Hive 로컬 DB - Clean Architecture 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
164 lines
4.6 KiB
Markdown
164 lines
4.6 KiB
Markdown
# 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. **성능**: 불필요한 리빌드 방지 |