feat(schedule): 달력 UI 개선 및 검색 준비
- ExpandablePageView로 달력 높이 동적 조절 (월별 주 수에 따라) - 데이트픽커 년도 변경 시 스와이프 애니메이션 추가 - 달력 월 변경 시 일정 점 비동기 업데이트 (캐시 기반) - 모든 달력/데이트픽커 텍스트에 Pretendard 폰트 적용 - 데이트픽커 화살표 터치 영역 확대 및 ripple effect 추가 - 데이트픽커 펼침 시 툴바 좌우 화살표 숨김 (페이드 애니메이션) - expandable_page_view 패키지 추가 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
895d9c26a3
commit
c4cbdc7d33
4 changed files with 557 additions and 298 deletions
|
|
@ -15,12 +15,15 @@ class ScheduleState {
|
|||
final List<Schedule> schedules;
|
||||
final bool isLoading;
|
||||
final String? error;
|
||||
// 달력용 월별 일정 캐시 (key: "yyyy-MM")
|
||||
final Map<String, List<Schedule>> calendarCache;
|
||||
|
||||
const ScheduleState({
|
||||
required this.selectedDate,
|
||||
this.schedules = const [],
|
||||
this.isLoading = false,
|
||||
this.error,
|
||||
this.calendarCache = const {},
|
||||
});
|
||||
|
||||
/// 상태 복사 (불변성 유지)
|
||||
|
|
@ -29,12 +32,14 @@ class ScheduleState {
|
|||
List<Schedule>? schedules,
|
||||
bool? isLoading,
|
||||
String? error,
|
||||
Map<String, List<Schedule>>? calendarCache,
|
||||
}) {
|
||||
return ScheduleState(
|
||||
selectedDate: selectedDate ?? this.selectedDate,
|
||||
schedules: schedules ?? this.schedules,
|
||||
isLoading: isLoading ?? this.isLoading,
|
||||
error: error,
|
||||
calendarCache: calendarCache ?? this.calendarCache,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -45,11 +50,29 @@ class ScheduleState {
|
|||
}
|
||||
|
||||
/// 특정 날짜의 일정 (점 표시용, 최대 3개)
|
||||
/// 캐시에서 먼저 찾고, 없으면 현재 schedules에서 찾음
|
||||
List<Schedule> getDaySchedules(DateTime date) {
|
||||
final dateStr = DateFormat('yyyy-MM-dd').format(date);
|
||||
final cacheKey = DateFormat('yyyy-MM').format(date);
|
||||
|
||||
// 캐시에 있으면 캐시에서 가져옴
|
||||
if (calendarCache.containsKey(cacheKey)) {
|
||||
return calendarCache[cacheKey]!
|
||||
.where((s) => s.date.split('T')[0] == dateStr)
|
||||
.take(3)
|
||||
.toList();
|
||||
}
|
||||
|
||||
// 캐시에 없으면 현재 schedules에서 찾음
|
||||
return schedules.where((s) => s.date.split('T')[0] == dateStr).take(3).toList();
|
||||
}
|
||||
|
||||
/// 특정 월의 일정이 캐시에 있는지 확인
|
||||
bool hasMonthCache(int year, int month) {
|
||||
final cacheKey = '$year-${month.toString().padLeft(2, '0')}';
|
||||
return calendarCache.containsKey(cacheKey);
|
||||
}
|
||||
|
||||
/// 해당 달의 모든 날짜 배열
|
||||
List<DateTime> get daysInMonth {
|
||||
final year = selectedDate.year;
|
||||
|
|
@ -79,12 +102,38 @@ class ScheduleController extends Notifier<ScheduleState> {
|
|||
state.selectedDate.year,
|
||||
state.selectedDate.month,
|
||||
);
|
||||
state = state.copyWith(schedules: schedules, isLoading: false);
|
||||
// 현재 월 일정을 캐시에도 저장
|
||||
final cacheKey = '${state.selectedDate.year}-${state.selectedDate.month.toString().padLeft(2, '0')}';
|
||||
final newCache = Map<String, List<Schedule>>.from(state.calendarCache);
|
||||
newCache[cacheKey] = schedules;
|
||||
state = state.copyWith(
|
||||
schedules: schedules,
|
||||
isLoading: false,
|
||||
calendarCache: newCache,
|
||||
);
|
||||
} catch (e) {
|
||||
state = state.copyWith(isLoading: false, error: e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/// 달력용 특정 월의 일정 비동기 로드 (UI 블로킹 없음)
|
||||
Future<void> loadCalendarMonth(int year, int month) async {
|
||||
final cacheKey = '$year-${month.toString().padLeft(2, '0')}';
|
||||
|
||||
// 이미 캐시에 있으면 스킵
|
||||
if (state.calendarCache.containsKey(cacheKey)) return;
|
||||
|
||||
try {
|
||||
final schedules = await getSchedules(year, month);
|
||||
// 비동기 완료 후 캐시 업데이트
|
||||
final newCache = Map<String, List<Schedule>>.from(state.calendarCache);
|
||||
newCache[cacheKey] = schedules;
|
||||
state = state.copyWith(calendarCache: newCache);
|
||||
} catch (e) {
|
||||
// 에러는 무시 (달력 점 표시가 안될 뿐)
|
||||
}
|
||||
}
|
||||
|
||||
/// 날짜 선택
|
||||
void selectDate(DateTime date) {
|
||||
state = state.copyWith(selectedDate: date);
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -169,6 +169,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
expandable_page_view:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: expandable_page_view
|
||||
sha256: "2d2c9e6fbbaa153f761054200c199eb69dc45948c8018b98a871212c67b60608"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
fake_async:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ dependencies:
|
|||
modal_bottom_sheet: ^3.0.0
|
||||
video_player: ^2.9.2
|
||||
chewie: ^1.8.5
|
||||
expandable_page_view: ^1.0.17
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue