Skip to content

Commit 2ef5c3f

Browse files
committed
Merge feature/meal-api (excluding main.dart)
2 parents dd612de + 5e4aa04 commit 2ef5c3f

File tree

11 files changed

+148
-48
lines changed

11 files changed

+148
-48
lines changed

CHANGELOG.md

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
# Changelog
2-
3-
## [1.0.0+1] - 2025-04-15
4-
- 최초 공개
5-
- 학교 정보 및 급식 API 지원
1+
## [1.0.1] - 2025-04-16
2+
- school 로직 수정
63

74
## [1.0.0+2] - 2025-04-16
85
- README.md 문서 개선

lib/flutter_neis.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ export 'src/neis.dart';
66

77
export 'src/models/school_info.dart';
88

9-
export 'src/services/school_service.dart';
9+
export 'src/services/school/school_service.dart';
1010

1111
export 'src/models/meal_info.dart';
1212

13-
export 'src/services/meal_service.dart';
13+
export 'src/services/meal/meal_service.dart';

lib/main.dart

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:flutter_neis/flutter_neis.dart';
3+
import 'package:intl/intl.dart'; // 날짜 포맷을 위해 사용
4+
5+
void main() {
6+
runApp(const MyApp());
7+
}
8+
9+
class MyApp extends StatelessWidget {
10+
const MyApp({super.key});
11+
12+
@override
13+
Widget build(BuildContext context) {
14+
return MaterialApp(
15+
home: const HomeScreen(),
16+
debugShowCheckedModeBanner: false,
17+
);
18+
}
19+
}
20+
21+
class HomeScreen extends StatefulWidget {
22+
const HomeScreen({super.key});
23+
24+
@override
25+
State<HomeScreen> createState() => _HomeScreenState();
26+
}
27+
28+
class _HomeScreenState extends State<HomeScreen> {
29+
final neis = Neis(apiKey: '4cb39a23104d459ebe0d394f9900cf5c');
30+
bool _loading = true;
31+
List<String> lunchMenu = [];
32+
33+
@override
34+
void initState() {
35+
super.initState();
36+
_load();
37+
}
38+
39+
Future<void> _load() async {
40+
await neis.loadSchoolInfo('경북소프트웨어마이스터고등학교');
41+
42+
final today = DateFormat('yyyyMMdd').format(DateTime.now());
43+
final lunch = await neis.meal.dinner[today];
44+
45+
setState(() {
46+
lunchMenu = lunch?.dishes ?? ['중식 정보 없음'];
47+
_loading = false;
48+
});
49+
}
50+
51+
@override
52+
Widget build(BuildContext context) {
53+
return Scaffold(
54+
appBar: AppBar(title: Text(neis.schoolName)),
55+
body:
56+
_loading
57+
? const Center(child: CircularProgressIndicator())
58+
: Padding(
59+
padding: const EdgeInsets.all(16),
60+
child: Column(
61+
crossAxisAlignment: CrossAxisAlignment.start,
62+
children: [
63+
const Text(
64+
'🍱 오늘의 중식',
65+
style: TextStyle(
66+
fontSize: 20,
67+
fontWeight: FontWeight.bold,
68+
),
69+
),
70+
const SizedBox(height: 12),
71+
...lunchMenu.map((dish) => Text(dish)).toList(),
72+
],
73+
),
74+
),
75+
);
76+
}
77+
}

lib/src/models/meal_info.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
class MealInfo {
22
final String date;
3-
final String type; // 조식/중식/석식
3+
final String type; // '조식', '중식', '석식'
44
final List<String> dishes;
55

66
MealInfo({required this.date, required this.type, required this.dishes});

lib/src/neis.dart

Lines changed: 14 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,26 @@
1-
import 'neis_client.dart';
2-
import 'models/school_info.dart';
3-
import 'models/meal_info.dart';
1+
import 'package:flutter_neis/flutter_neis.dart';
2+
import 'package:flutter_neis/src/services/meal/meal_manager.dart';
43

54
class Neis {
65
final NeisClient _client;
76
SchoolInfo? _school;
8-
List<MealInfo> _meals = [];
7+
MealManager? _meal;
98

109
Neis({required String apiKey}) : _client = NeisClient(apiKey: apiKey);
1110

1211
Future<void> loadSchoolInfo(String name) async {
13-
final result = await _client.fetchSchools(schoolName: name);
14-
if (result.isEmpty) throw Exception('학교를 찾을 수 없습니다.');
15-
_school = result.first;
16-
17-
// 오늘 날짜 형식: YYYYMMDD
18-
final today = DateTime.now();
19-
final date = '${today.year}${_two(today.month)}${_two(today.day)}';
20-
21-
_meals = await _client.fetchMeals(
22-
officeCode: _school!.officeCode,
23-
schoolCode: _school!.schoolCode,
24-
date: date,
25-
);
12+
final schools = await _client.fetchSchools(schoolName: name);
13+
if (schools.isEmpty) throw Exception('학교를 찾을 수 없습니다.');
14+
_school = schools.first;
15+
_meal = MealManager(client: _client, school: _school!);
2616
}
2717

28-
// getter: 학교 정보
29-
String get officeCode => _school?.officeCode ?? '';
30-
String get schoolCode => _school?.schoolCode ?? '';
18+
// Getter로 쉽게 접근
3119
String get schoolName => _school?.schoolName ?? '';
32-
List<MealInfo> get meals => _meals;
33-
34-
// 끼니별 getter
35-
MealInfo? get breakfast => _meals.firstWhere(
36-
(e) => e.type == '조식',
37-
orElse: () => MealInfo(date: '', type: '조식', dishes: []),
38-
);
39-
MealInfo? get lunch => _meals.firstWhere(
40-
(e) => e.type == '중식',
41-
orElse: () => MealInfo(date: '', type: '중식', dishes: []),
42-
);
43-
MealInfo? get dinner => _meals.firstWhere(
44-
(e) => e.type == '석식',
45-
orElse: () => MealInfo(date: '', type: '석식', dishes: []),
46-
);
47-
48-
String _two(int n) => n.toString().padLeft(2, '0');
20+
MealManager get meal {
21+
if (_meal == null) {
22+
throw Exception('먼저 loadSchoolInfo()를 호출하세요.');
23+
}
24+
return _meal!;
25+
}
4926
}

lib/src/neis_client.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import 'services/school_service.dart';
1+
import 'services/school/school_service.dart';
22
import 'package:flutter_neis/flutter_neis.dart';
33

44
class NeisClient {
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import 'package:flutter_neis/flutter_neis.dart';
2+
3+
class MealManager {
4+
final NeisClient client;
5+
final SchoolInfo school;
6+
final Map<String, List<MealInfo>> _cache = {};
7+
8+
MealManager({required this.client, required this.school});
9+
10+
Future<List<MealInfo>> _getMeals(String date) async {
11+
if (!_cache.containsKey(date)) {
12+
final meals = await client.fetchMeals(
13+
officeCode: school.officeCode,
14+
schoolCode: school.schoolCode,
15+
date: date,
16+
);
17+
_cache[date] = meals;
18+
}
19+
return _cache[date]!;
20+
}
21+
22+
MealTypeGetter get breakfast => MealTypeGetter(this, '조식');
23+
MealTypeGetter get lunch => MealTypeGetter(this, '중식');
24+
MealTypeGetter get dinner => MealTypeGetter(this, '석식');
25+
}
26+
27+
class MealTypeGetter {
28+
final MealManager manager;
29+
final String type;
30+
31+
MealTypeGetter(this.manager, this.type);
32+
33+
Future<MealInfo?> operator [](String date) async {
34+
final list = await manager._getMeals(date);
35+
return list.firstWhere(
36+
(m) => m.type == type,
37+
orElse: () => MealInfo(date: date, type: type, dishes: []),
38+
);
39+
}
40+
}

lib/src/services/meal_service.dart renamed to lib/src/services/meal/meal_service.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import 'dart:convert';
22
import 'package:http/http.dart' as http;
3-
import '../models/meal_info.dart';
3+
import '../../models/meal_info.dart';
44

55
class MealService {
66
final String apiKey;

lib/src/services/school_service.dart renamed to lib/src/services/school/school_service.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import 'dart:convert';
22
import 'package:http/http.dart' as http;
3-
import '../models/school_info.dart';
3+
import '../../models/school_info.dart';
44

55
class SchoolService {
66
final String apiKey;

pubspec.lock

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,14 @@ packages:
9191
url: "https://pub.dev"
9292
source: hosted
9393
version: "4.1.2"
94+
intl:
95+
dependency: "direct main"
96+
description:
97+
name: intl
98+
sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5"
99+
url: "https://pub.dev"
100+
source: hosted
101+
version: "0.20.2"
94102
leak_tracker:
95103
dependency: transitive
96104
description:

0 commit comments

Comments
 (0)