import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'dart:convert'; import 'youtube_player_page.dart'; // YoutubePlayerPage import // PlanDetailItem 클래스 class PlanDetailItem { final String lessonId; final String lessonTag; final String lessonUrl; final String thumbnail; PlanDetailItem({ required this.lessonId, required this.lessonTag, required this.lessonUrl, required this.thumbnail, }); factory PlanDetailItem.fromJson(Map json) { return PlanDetailItem( lessonId: json['casestudy lesson id'] ?? 'ID 없음', lessonTag: json['lesson tag'] ?? '태그 없음', lessonUrl: json['lesson url'] ?? 'URL 없음', thumbnail: json['thumbnail'] ?? '', ); } } class plan_page_detail extends StatefulWidget { // final int currentBottomNavIndex; // HomePage 등에서 전달받을 현재 탭 인덱스 const plan_page_detail({ super.key, // this.currentBottomNavIndex = 0, // 기본값 }); @override State createState() => _plan_page_detailState(); } class _plan_page_detailState extends State { String? _planId; Future>? _planDetails; late int _currentBottomNavIndex; // 하단 네비게이션 바 상태 @override void initState() { super.initState(); // 이전 페이지에서 전달받은 탭 인덱스로 초기화하거나 기본값 사용 // _currentBottomNavIndex = widget.currentBottomNavIndex; _currentBottomNavIndex = 0; // 예시: '홈' 탭을 기본으로 설정 } @override void didChangeDependencies() { super.didChangeDependencies(); if (_planId == null) { final Object? arguments = ModalRoute.of(context)?.settings.arguments; if (arguments is String) { _planId = arguments; if (_planId != null) { _planDetails = _fetchPlanDetails(_planId!); } } else { _planDetails = Future.error(Exception("Plan ID not provided or invalid.")); print("Error: Plan ID not provided or invalid."); } } } Future> _fetchPlanDetails(String planId) async { final response = await http .get(Uri.parse('https://helloworld1-ad2uqhckxq-uc.a.run.app/?id=$planId')); if (response.statusCode == 200) { final Map decodedJson = json.decode(response.body); if (decodedJson.containsKey('data') && decodedJson['data'] is List) { final List detailsJson = decodedJson['data']; return detailsJson.map((jsonItem) => PlanDetailItem.fromJson(jsonItem as Map)).toList(); } else { throw Exception('Invalid API response format: "data" field is missing or not a list.'); } } else { throw Exception('Failed to load plan details. Status code: ${response.statusCode}'); } } void _onBottomNavItemTapped(int index) { setState(() { _currentBottomNavIndex = index; }); // 페이지 이동 로직 (이전 답변 참고) if (index == 0) { Navigator.of(context).popUntil((route) => route.isFirst); } else if (index == 1) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Search (Not Implemented)')), ); } else if (index == 2) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Profile (Not Implemented)')), ); } } @override Widget build(BuildContext context) { return Scaffold( // 1. 상단 바 (AppBar) appBar: AppBar( title: Text(_planId != null ? 'Plan: $_planId' : 'Plan Details'), // 필요하다면 leading에 뒤로가기 버튼 명시적 추가 leading: Navigator.canPop(context) ? IconButton( icon: const Icon(Icons.arrow_back_ios_new), // 또는 Icons.arrow_back tooltip: 'Back', onPressed: () => Navigator.of(context).pop(), ) : null, ), body: _planId == null ? const Center( child: Text( 'Plan ID가 전달되지 않았습니다.', style: TextStyle(fontSize: 18, color: Colors.red), ), ) : FutureBuilder>( future: _planDetails, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return const Center(child: CircularProgressIndicator()); } else if (snapshot.hasError) { return Center(child: Text('Error: ${snapshot.error}')); } else if (!snapshot.hasData || snapshot.data!.isEmpty) { return const Center(child: Text('세부 계획 데이터가 없습니다.')); } else { final details = snapshot.data!; return ListView.builder( itemCount: details.length, itemBuilder: (context, index) { final item = details[index]; return Card( margin: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0), child: ListTile( leading: item.thumbnail.isNotEmpty ? SizedBox( width: 100, height: 100, child: Image.network( item.thumbnail, fit: BoxFit.cover, errorBuilder: (context, error, stackTrace) { return const Icon(Icons.broken_image, size: 40, color: Colors.grey); }, loadingBuilder: (BuildContext context, Widget child, ImageChunkEvent? loadingProgress) { if (loadingProgress == null) return child; return Center( child: CircularProgressIndicator( value: loadingProgress.expectedTotalBytes != null ? loadingProgress.cumulativeBytesLoaded / loadingProgress.expectedTotalBytes! : null, ), ); }, ), ) : Container( width: 100, height: 100, color: Colors.grey[200], child: const Icon(Icons.image_not_supported, size: 40, color: Colors.grey), ), title: Text(item.lessonTag, style: const TextStyle(fontWeight: FontWeight.bold)), subtitle: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ Text('ID: ${item.lessonId}', style: TextStyle(fontSize: 12, color: Colors.grey[700])), const SizedBox(height: 2), Text( item.lessonUrl, style: const TextStyle(fontSize: 12, color: Colors.blueAccent), overflow: TextOverflow.ellipsis, maxLines: 2, ), ], ), isThreeLine: true, onTap: () { if (item.lessonUrl.isNotEmpty && (item.lessonUrl.contains('youtube.com') || item.lessonUrl.contains('youtu.be'))) { Navigator.push( context, MaterialPageRoute( builder: (context) => YoutubePlayerPage( lessonUrl: item.lessonUrl, // currentBottomNavIndex: _currentBottomNavIndex, // 현재 탭 인덱스 전달 ), ), ); } else { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('유효한 YouTube URL이 아닙니다: ${item.lessonUrl}')), ); } }, ), ); }, ); } }, ), // 2. 하단 바 (BottomNavigationBar) ); } }