/// 일정 모델 library; /// 멤버 정보 class ScheduleMember { final int id; final String name; ScheduleMember({required this.id, required this.name}); factory ScheduleMember.fromJson(Map json) { return ScheduleMember( id: json['id'] as int, name: json['name'] as String, ); } } /// 관련 일정 (콘서트 회차 등) class RelatedDate { final int id; final String date; final String? time; RelatedDate({required this.id, required this.date, this.time}); factory RelatedDate.fromJson(Map json) { return RelatedDate( id: json['id'] as int, date: json['date'] as String, time: json['time'] as String?, ); } } /// 일정 상세 모델 class ScheduleDetail { final int id; final String title; final String date; final String? time; final String? description; final int categoryId; final String? categoryName; final String? categoryColor; final String? sourceUrl; final String? sourceName; final String? imageUrl; final List images; final String? locationName; final String? locationAddress; final String? locationLat; final String? locationLng; final List members; final List relatedDates; ScheduleDetail({ required this.id, required this.title, required this.date, this.time, this.description, required this.categoryId, this.categoryName, this.categoryColor, this.sourceUrl, this.sourceName, this.imageUrl, this.images = const [], this.locationName, this.locationAddress, this.locationLat, this.locationLng, this.members = const [], this.relatedDates = const [], }); factory ScheduleDetail.fromJson(Map json) { return ScheduleDetail( id: json['id'] as int, title: json['title'] as String, date: json['date'] as String, time: json['time'] as String?, description: json['description'] as String?, categoryId: json['category_id'] as int, categoryName: json['category_name'] as String?, categoryColor: json['category_color'] as String?, sourceUrl: json['source_url'] as String?, sourceName: json['source_name'] as String?, imageUrl: json['image_url'] as String?, images: (json['images'] as List?)?.cast() ?? [], locationName: json['location_name'] as String?, locationAddress: json['location_address'] as String?, locationLat: json['location_lat'] as String?, locationLng: json['location_lng'] as String?, members: (json['members'] as List?) ?.map((m) => ScheduleMember.fromJson(m)) .toList() ?? [], relatedDates: (json['related_dates'] as List?) ?.map((r) => RelatedDate.fromJson(r)) .toList() ?? [], ); } /// 시간 포맷 (HH:mm) String? get formattedTime { if (time == null) return null; return time!.length >= 5 ? time!.substring(0, 5) : time; } } class Schedule { final int id; final String title; final String date; final String? time; final int? categoryId; final String? categoryName; final String? categoryColor; final List members; final String? sourceName; final String? sourceUrl; Schedule({ required this.id, required this.title, required this.date, this.time, this.categoryId, this.categoryName, this.categoryColor, this.members = const [], this.sourceName, this.sourceUrl, }); factory Schedule.fromJson(Map json) { // category 중첩 객체 파싱 final category = json['category'] as Map?; // members 배열 파싱 final membersList = (json['members'] as List?) ?.map((m) => m is String ? m : m.toString()) .toList() ?? []; // source 중첩 객체 파싱 final source = json['source'] as Map?; return Schedule( id: json['id'] is String ? int.parse(json['id']) : json['id'] as int, title: json['title'] as String, date: json['date'] as String, time: json['time'] as String?, categoryId: category?['id'] as int?, categoryName: category?['name'] as String?, categoryColor: category?['color'] as String?, members: membersList, sourceName: source?['name'] as String?, sourceUrl: source?['url'] as String?, ); } /// 멤버 리스트 반환 List get memberList => members; /// 시간 포맷 (HH:mm) String? get formattedTime { if (time == null) return null; return time!.length >= 5 ? time!.substring(0, 5) : time; } }