diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 9200564..8640a8f 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -7,9 +7,9 @@ { File? _imageFile; final ImagePicker _picker = ImagePicker(); + String? _kakaoProfileImageUrl; + String? _apiProfileImageUrl; + + @override + void initState() { + super.initState(); + _loadProfileImage(); // 프로필 이미지 로드 + } + + Future _loadProfileImage() async { + await _loadKakaoProfile(); + await _getApiProfileImage(); // API로 프로필 이미지 불러오기 + } + + Future _getApiProfileImage() async { + const url = 'http://15.164.88.94/users/isFirst'; + + try { + // API 호출을 위한 GET 요청 + final response = await http.get( + Uri.parse(url), + headers: {'Authorization': 'Bearer $token'}, // 토큰 추가 + ); + + if (response.statusCode == 200) { + // 서버로부터 응답을 받은 경우 + final data = json.decode(response.body); + setState(() { + _apiProfileImageUrl = data['profileImage']; // API에서 프로필 이미지 URL 받아오기 + }); + } else { + print('Failed to get profile image: ${response.statusCode}'); + } + } catch (e) { + print('Error during profile image fetch: $e'); + } + } + + // 카카오 프로필 이미지 불러오기 + Future _loadKakaoProfile() async { + try { + User user = await UserApi.instance.me(); // 카카오 사용자 정보 불러오기 + setState(() { + _kakaoProfileImageUrl = + user.kakaoAccount?.profile?.profileImageUrl; // 프로필 이미지 URL 저장 + }); + } catch (error) { + print('Failed to load Kakao profile: $error'); + setState(() { + _kakaoProfileImageUrl = null; + }); + } + } Future _pickImage() async { final pickedFile = await _picker.pickImage(source: ImageSource.gallery); @@ -62,13 +115,13 @@ class _ProfileSettingState extends State { } Future _registerUserInfo() async { - const url = 'http://15.164.88.94/users/infos'; // API URL + const url = 'http://15.164.88.94/users/infos'; // POST 요청 준비 final request = http.MultipartRequest('POST', Uri.parse(url)); // 토큰 확인 및 추가 - if (token == null || token.isEmpty) { + if (token.isEmpty) { print('Token is missing.'); ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('토큰이 없습니다. 다시 로그인해주세요.')), @@ -85,7 +138,8 @@ class _ProfileSettingState extends State { // 선택한 이미지가 있으면 파일로 추가 if (_imageFile != null) { - request.files.add(await http.MultipartFile.fromPath('image', _imageFile!.path)); + request.files + .add(await http.MultipartFile.fromPath('image', _imageFile!.path)); } try { @@ -108,11 +162,12 @@ class _ProfileSettingState extends State { } else { // 실패 시 서버에서 보낸 오류 메시지 출력 final errorBody = utf8.decode(responseData.bodyBytes); - print('Failed to register user info. Status code: ${response.statusCode}'); + print( + 'Failed to register user info. Status code: ${response.statusCode}'); print('Response body: $errorBody'); ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('정보 등록 실패: 이미 사용 중인 닉네임입니다.')), + const SnackBar(content: Text('정보 등록 실패: 이미 사용 중인 닉네임입니다.')), ); } } catch (e) { @@ -123,7 +178,6 @@ class _ProfileSettingState extends State { } } - @override Widget build(BuildContext context) { return Scaffold( @@ -159,8 +213,15 @@ class _ProfileSettingState extends State { radius: 50, backgroundImage: _imageFile != null ? FileImage(_imageFile!) - : const AssetImage('assets/images/defaultProfile.png') - as ImageProvider, + : (_kakaoProfileImageUrl != null && + _kakaoProfileImageUrl!.isNotEmpty + ? NetworkImage(_kakaoProfileImageUrl!) + : (_apiProfileImageUrl != null && + _apiProfileImageUrl!.isNotEmpty + ? NetworkImage(_apiProfileImageUrl!) + : const AssetImage( + 'assets/images/defaultProfile.png'))) + as ImageProvider, ), Positioned( bottom: 0, @@ -192,13 +253,13 @@ class _ProfileSettingState extends State { counterText: '', // 글자수 카운터 삭제 border: OutlineInputBorder( borderRadius: BorderRadius.circular(10.0), - borderSide: BorderSide( + borderSide: const BorderSide( color: Colors.black, // 기본 테두리 검은색 ), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(10.0), - borderSide: BorderSide( + borderSide: const BorderSide( color: Colors.black, // 포커스 시 테두리 검은색 width: 2.0, ), @@ -234,13 +295,13 @@ class _ProfileSettingState extends State { counterText: '', // 글자수 카운터 삭제 border: OutlineInputBorder( borderRadius: BorderRadius.circular(10.0), - borderSide: BorderSide( + borderSide: const BorderSide( color: Colors.black, // 기본 테두리 검은색 ), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(10.0), - borderSide: BorderSide( + borderSide: const BorderSide( color: Colors.black, // 포커스 시 테두리 검은색 width: 2.0, ), diff --git a/lib/RoutineAdeIntro/RoutineAde1.dart b/lib/RoutineAdeIntro/RoutineAde1.dart index d287bcc..68fbd89 100644 --- a/lib/RoutineAdeIntro/RoutineAde1.dart +++ b/lib/RoutineAdeIntro/RoutineAde1.dart @@ -27,10 +27,10 @@ class RoutineAde1 extends StatefulWidget { class _RoutineAde1State extends State { final List imgList = [ - "assets/images/tap-bar/routine02.png", - "assets/images/tap-bar/group02.png", - "assets/images/tap-bar/statistics02.png", - "assets/images/tap-bar/more02.png", + "assets/images/new-icons/onBoarding1.png", + "assets/images/new-icons/onBoarding2.png", + "assets/images/new-icons/onBoarding3.png", + "assets/images/new-icons/onBoarding4.png", ]; int _currentIndex = 0; // 현재 선택된 이미지 인덱스 @@ -45,30 +45,7 @@ class _RoutineAde1State extends State { crossAxisAlignment: CrossAxisAlignment.center, children: [ const Spacer(), - // Image.asset( - // 'assets/images/new-icons/RoutineAde.png', - // width: 100, - // height: 100, - // ), - // const SizedBox(height: 20), - // const Text( - // '더 나은 하루, 루틴 에이드', - // style: TextStyle( - // fontSize: 18, - // fontWeight: FontWeight.bold, - // color: Colors.black, - // ), - // ), - // const SizedBox(height: 8), - // Text( - // '루틴으로 더 나은 일상을\n함께 관리해보세요!', - // textAlign: TextAlign.center, - // style: TextStyle( - // fontSize: 14, - // color: Colors.grey[700], - // ), - // ), - const SizedBox(height: 50), + const SizedBox(height: 100), // Carousel Slider 부분 CarouselSlider( @@ -81,19 +58,24 @@ class _RoutineAde1State extends State { _currentIndex = index; // 슬라이드가 바뀔 때 현재 인덱스 업데이트 }); }, + enableInfiniteScroll: false, // 무한 스크롤 비활성화 ), - items: imgList.map((item) => Container( - child: Center( - child: Image.asset( - item, - fit: BoxFit.contain, - width: 1000, - ), - ), - )).toList(), + items: imgList + .map((item) => Container( + child: Center( + child: Image.asset( + item, + fit: BoxFit.contain, + width: 1000, + ), + ), + )) + .toList(), ), - SizedBox(height: 50,), + const SizedBox( + height: 50, + ), // 인디케이터 부분 Row( @@ -106,24 +88,32 @@ class _RoutineAde1State extends State { child: Container( width: 12.0, height: 12.0, - margin: const EdgeInsets.symmetric(vertical: 10.0, horizontal: 4.0), + margin: const EdgeInsets.symmetric( + vertical: 10.0, horizontal: 4.0), decoration: BoxDecoration( shape: BoxShape.circle, color: _currentIndex == entry.key - ? Colors.blueAccent // 현재 인덱스일 경우 채워진 동그라미 - : Colors.grey, // 그렇지 않은 경우 빈 동그라미 + ? Colors.grey // 현재 인덱스일 경우 채워진 동그라미 + : Colors.grey[300], // 그렇지 않은 경우 빈 동그라미 ), ), ); }).toList(), ), - const Spacer(), + const SizedBox(height: 10), + const Text( + "sns로 간편 가입하기 !", + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + color: Colors.grey), + ), Padding( - padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 20), + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 0), child: SizedBox( width: double.infinity, - height: 150, + height: 100, child: GestureDetector( onTap: () { // WebView 페이지로 이동 @@ -135,13 +125,16 @@ class _RoutineAde1State extends State { }, child: Image.asset( "assets/images/new-icons/kakaoTalk.png", - width: 200, + width: 250, height: 200, fit: BoxFit.contain, ), ), ), ), + const SizedBox( + height: 10, + ), ], ), ), diff --git a/lib/RoutineAdeIntro/WebViewPage.dart b/lib/RoutineAdeIntro/WebViewPage.dart index e1fe023..540bc0f 100644 --- a/lib/RoutineAdeIntro/WebViewPage.dart +++ b/lib/RoutineAdeIntro/WebViewPage.dart @@ -1,7 +1,10 @@ import 'package:flutter/material.dart'; +import 'package:http/http.dart' as http; import 'package:routine_ade/RoutineAdeIntro/ProfileSetting.dart'; +import 'package:routine_ade/routine_home/MyRoutinePage.dart'; import 'package:webview_flutter/webview_flutter.dart'; import '../routine_user/token.dart'; +import 'dart:convert'; class WebViewPage extends StatefulWidget { const WebViewPage({super.key}); @@ -16,11 +19,10 @@ class _WebViewPageState extends State { @override void initState() { super.initState(); - // 웹뷰 초기화 전에 SharedPreferences에서 토큰을 불러옴. _loadToken(); } - // 토큰을 불러와서 출력 (필요시 다른 처리) + // 토큰을 불러오는 메서드 Future _loadToken() async { String? token = await TokenManager.getToken(); if (token != null) { @@ -30,43 +32,72 @@ class _WebViewPageState extends State { } } + // 최초 로그인 여부를 확인하는 메서드 + Future _checkIfFirstLogin(String token) async { + final response = await http.get( + Uri.parse('http://15.164.88.94/users/isFirst'), + headers: { + 'Authorization': 'Bearer $token', + 'Content-Type': 'application/json; charset=UTF-8', + }, + ); + + if (response.statusCode == 200) { + final responseBody = json.decode(utf8.decode(response.bodyBytes)); + bool isFirst = responseBody['isFirst'] ?? false; + print('isFirst: $isFirst'); + + // 최초 로그인 여부에 따라 페이지 이동 + if (isFirst) { + print("ProfileSetting 페이지로 이동"); + Navigator.pushReplacement( + context, + MaterialPageRoute(builder: (context) => const ProfileSetting()), + // ProfileSetting 페이지로 이동 + ); + } else { + print("MyRoutinePage로 이동"); + Navigator.pushReplacement( + context, + MaterialPageRoute(builder: (context) => const MyRoutinePage()), + ); + } + } else { + print('최초 로그인 확인 실패: ${response.statusCode}'); + // 오류 처리 + } + } + @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: const Text('Kakao Login WebView'), + title: const Text('카카오앱으로 로그인하기'), ), body: WebView( initialUrl: - 'https://kauth.kakao.com/oauth/authorize?response_type=code&client_id=25a0f887ecba2fdb77884c01ca0325b0&redirect_uri=http://15.164.88.94/users/login/kakao', + 'https://kauth.kakao.com/oauth/authorize?response_type=code&client_id=25a0f887ecba2fdb77884c01ca0325b0&redirect_uri=http://15.164.88.94/users/login/kakao', javascriptMode: JavascriptMode.unrestricted, onWebViewCreated: (WebViewController webViewController) { _controller = webViewController; }, onPageFinished: (String url) async { - // 페이지 로딩이 끝나면 URL을 확인 if (url.contains('token=')) { final tokenStartIndex = url.indexOf('token=') + 6; // 'token='의 시작 위치 final token = url.substring(tokenStartIndex); - // URL이 정상적으로 응답하지 않을 때 예외 처리 if (token.isNotEmpty) { print('OAuth 토큰: $token'); // 콘솔에 토큰 출력 - // 추출한 토큰을 SharedPreferences에 저장 - await TokenManager.saveToken(token); - print('토큰 저장 완료'); + // 추출한 토큰으로 최초 로그인 확인 + await _checkIfFirstLogin(token); } else { print('토큰이 유효하지 않습니다.'); } - Navigator.pushReplacement( - context, - MaterialPageRoute(builder: (context) => const ProfileSetting()), - ); } }, ), ); } -} \ No newline at end of file +} diff --git a/lib/RoutineAdelntro/ProfileSetting.dart b/lib/RoutineAdelntro/ProfileSetting.dart deleted file mode 100644 index fb1e60e..0000000 --- a/lib/RoutineAdelntro/ProfileSetting.dart +++ /dev/null @@ -1,182 +0,0 @@ -import 'dart:io'; -import 'package:flutter/material.dart'; -import 'package:image_picker/image_picker.dart'; -import 'package:permission_handler/permission_handler.dart'; - -import '../routine_home/MyRoutinePage.dart'; - -class ProfileSetting extends StatefulWidget { - const ProfileSetting({super.key}); - - @override - _ProfileSettingState createState() => _ProfileSettingState(); -} - -class _ProfileSettingState extends State { - File? _imageFile; - final ImagePicker _picker = ImagePicker(); - - Future _pickImage() async { - final pickedFile = await _picker.pickImage(source: ImageSource.gallery); - - if (pickedFile != null) { - setState(() { - _imageFile = File(pickedFile.path); - }); - } else { - print('No image selected.'); - } - } - - final TextEditingController _nicknameController = TextEditingController(); - final TextEditingController _bioController = TextEditingController(); - bool _isNicknameValid = true; - String _nicknameErrorMessage = ''; - - void _validateNickname(String value) { - setState(() { - if (value.length > 10) { - _isNicknameValid = false; - _nicknameErrorMessage = '10글자 이내로 입력해주세요.'; - } else { - _isNicknameValid = true; - _nicknameErrorMessage = ''; - } - }); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - resizeToAvoidBottomInset: false, - appBar: AppBar( - backgroundColor: const Color(0xFF8DCCFF), - centerTitle: true, - title: const Text( - '프로필 설정', - style: TextStyle( - color: Colors.white, fontSize: 25, fontWeight: FontWeight.bold), - ), - leading: IconButton( - icon: const Icon(Icons.arrow_back, color: Colors.white), - onPressed: () { - Navigator.of(context).pop(); - }, - ), - ), - body: Stack( - children: [ - Padding( - padding: const EdgeInsets.all(20.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const SizedBox(height: 20), - GestureDetector( - onTap: _pickImage, // 프로필 사진을 클릭했을 때 이미지 선택 기능 실행 - child: Stack( - children: [ - CircleAvatar( - radius: 50, - backgroundImage: _imageFile != null - ? FileImage(_imageFile!) - : const AssetImage( - 'assets/images/default_profile.png') - as ImageProvider, - ), - Positioned( - bottom: 0, - right: 0, - child: GestureDetector( - onTap: _pickImage, // 카메라 아이콘 클릭 시 이미지 선택 기능 실행 - child: const CircleAvatar( - backgroundColor: Colors.white, - radius: 16, - child: Icon(Icons.camera_alt, color: Colors.grey), - ), - ), - ), - ], - ), - ), - const SizedBox(height: 50), - const Align( - alignment: Alignment.centerLeft, - child: Text("닉네임"), - ), - const SizedBox(height: 10), - TextField( - controller: _nicknameController, - onChanged: _validateNickname, - decoration: InputDecoration( - hintText: '닉네임', - errorText: !_isNicknameValid - ? _nicknameErrorMessage - : '10글자 이내로 입력해주세요.', - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(10.0), - borderSide: BorderSide( - color: _isNicknameValid ? Colors.red : Colors.grey, - ), - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(10.0), - borderSide: BorderSide( - color: _isNicknameValid ? Colors.blue : Colors.red, - ), - ), - ), - maxLength: 10, - ), - const SizedBox(height: 20), - const Align( - alignment: Alignment.centerLeft, - child: Text("한 줄 소개"), - ), - const SizedBox(height: 10), - TextField( - controller: _bioController, - decoration: InputDecoration( - hintText: '한 줄 소개', - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(10.0), - ), - ), - ), - ], - ), - ), - Positioned( - bottom: 20, - left: 10, - right: 10, - child: SizedBox( - width: double.infinity, - height: 50, - child: ElevatedButton( - style: ElevatedButton.styleFrom( - backgroundColor: const Color(0xFF8DCCFF), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), - ), - onPressed: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => const MyRoutinePage(), - ), - ); - }, - child: const Text( - '완료', - style: TextStyle(fontSize: 16, color: Colors.white), - ), - ), - ), - ), - ], - ), - ); - } -} diff --git a/lib/RoutineAdelntro/ProfileSetting2.dart b/lib/RoutineAdelntro/ProfileSetting2.dart deleted file mode 100644 index 99f57ed..0000000 --- a/lib/RoutineAdelntro/ProfileSetting2.dart +++ /dev/null @@ -1,81 +0,0 @@ -// import 'dart:io'; -// -// import 'package:flutter/material.dart'; -// import 'package:image_picker/image_picker.dart'; -// -// -// class ProfileSetting2 extends StatefulWidget { -// const ProfileSetting2({Key? key}) : super(key: key); -// -// @override -// State createState() => _MyAppState(); -// } -// -// class _MyAppState extends State { -// XFile? _image; //이미지를 담을 변수 선언 -// final ImagePicker picker = ImagePicker(); //ImagePicker 초기화 -// -// //이미지를 가져오는 함수 -// Future getImage(ImageSource imageSource) async { -// //pickedFile에 ImagePicker로 가져온 이미지가 담긴다. -// final XFile? pickedFile = await picker.pickImage(source: imageSource); -// if (pickedFile != null) { -// setState(() { -// _image = XFile(pickedFile.path); //가져온 이미지를 _image에 저장 -// }); -// } -// } -// -// @override -// Widget build(BuildContext context) { -// return MaterialApp( -// home: Scaffold( -// appBar: AppBar(title: Text("Camera Test")), -// body: Column( -// crossAxisAlignment: CrossAxisAlignment.center, -// children: [ -// SizedBox(height: 30, width: double.infinity), -// _buildPhotoArea(), -// SizedBox(height: 20), -// _buildButton(), -// ], -// ), -// ), -// ); -// } -// -// Widget _buildPhotoArea() { -// return _image != null -// ? Container( -// width: 300, -// height: 300, -// child: Image.file(File(_image!.path)), //가져온 이미지를 화면에 띄워주는 코드 -// ) -// : Container( -// width: 300, -// height: 300, -// color: Colors.grey, -// ); -// } -// -// Widget _buildButton() { -// return Row( -// mainAxisAlignment: MainAxisAlignment.center, -// children: [ -// ElevatedButton( -// onPressed: () { -// getImage(ImageSource.camera); //getImage 함수를 호출해서 카메라로 찍은 사진 가져오기 -// }, -// child: Text("카메라"), -// ), -// SizedBox(width: 30), -// ElevatedButton( -// onPressed: () { -// getImage(ImageSource.gallery); //getImage 함수를 호출해서 갤러리에서 사진 가져오기 -// }, -// child: Text("갤러리"), -// ), -// ], -// ); -// } -// } \ No newline at end of file diff --git a/lib/RoutineAdelntro/RoutineAde1.dart b/lib/RoutineAdelntro/RoutineAde1.dart deleted file mode 100644 index 642625b..0000000 --- a/lib/RoutineAdelntro/RoutineAde1.dart +++ /dev/null @@ -1,79 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:routine_ade/RoutineAdelntro/ProfileSetting.dart'; -// import 'Pro'; -import 'package:routine_ade/routine_home/MyRoutinePage.dart'; - -import 'ProfileSetting2.dart'; - -class RoutineAde1 extends StatelessWidget { - const RoutineAde1({super.key}); - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: Colors.white, // Set the background color - body: SafeArea( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Spacer(), // Pushes content towards the center - Image.asset( - 'assets/images/new-icons/RoutineAde.png', - width: 100, // Adjust width as needed - height: 100, // Adjust height as needed - ), - const SizedBox(height: 20), // Spacing between image and text - const Text( - '더 나은 하루, 루틴 에이드', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: Colors.black, - ), - ), - const SizedBox(height: 8), - Text( - '루틴으로 더 나은 일상을\n함께 관리해보세요!', - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 14, - color: Colors.grey[700], - ), - ), - const Spacer(), // Pushes content towards the center - Padding( - padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 20), - child: SizedBox( - width: double.infinity, - height: 50, - child: ElevatedButton( - style: ElevatedButton.styleFrom( - backgroundColor: const Color(0xFF8DCCFF), // Button color - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), // Rounded corners - ), - ), - onPressed: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => const ProfileSetting()), - ); - }, - child: const Text( - '시작하기', - style: TextStyle( - fontSize: 16, - color: Colors.white, - ), - ), - ), - ), - ), - ], - ), - ), - ); - } -} diff --git a/lib/main.dart b/lib/main.dart index 01e411e..762a65a 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -4,9 +4,15 @@ import 'RoutineAdeIntro/RoutineAde1.dart'; import 'routine_home/MyRoutinePage.dart'; import 'package:http/http.dart' as http; import 'routine_group/GroupMainPage.dart'; +import 'package:kakao_flutter_sdk_common/kakao_flutter_sdk_common.dart'; void main() async { + // WidgetsFlutterBinding.ensureInitialized(); + + // KakaoSdk.init(nativeAppKey: '90e5f5e8125f01adae4434fd72182a74'); //네이티브 앱 키 + await initializeDateFormatting(); + runApp(const MyApp()); } @@ -20,4 +26,4 @@ class MyApp extends StatelessWidget { home: RoutineAde1(), ); } -} \ No newline at end of file +} diff --git a/lib/routine_group/AddGroupPage.dart b/lib/routine_group/AddGroupPage.dart index a522a3e..c14035e 100644 --- a/lib/routine_group/AddGroupPage.dart +++ b/lib/routine_group/AddGroupPage.dart @@ -2,6 +2,7 @@ import 'dart:convert'; import 'package:http/http.dart' as http; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; +import 'package:routine_ade/routine_group/GroupMainPage.dart'; import 'GroupType.dart'; import 'package:routine_ade/routine_user/token.dart'; @@ -16,7 +17,7 @@ class _AddGroupPageState extends State { final TextEditingController _groupNameController = TextEditingController(); final TextEditingController _passwordController = TextEditingController(); final TextEditingController _groupDescriptionController = - TextEditingController(); + TextEditingController(); int _selectedMemberCount = 0; // 카테고리 선택 (한번에 하나만) @@ -49,7 +50,7 @@ class _AddGroupPageState extends State { // 비밀번호 값 설정 final groupPassword = - _passwordController.text.isEmpty ? null : _passwordController.text; + _passwordController.text.isEmpty ? null : _passwordController.text; // 요청 바디 준비 final url = Uri.parse('http://15.164.88.94/groups'); @@ -71,7 +72,8 @@ class _AddGroupPageState extends State { print('Response body: ${response.body}'); if (response.statusCode == 200 || response.statusCode == 201) { - _showDialog('성공', '그룹이 성공적으로 추가되었습니다.'); + Navigator.pushReplacement(context, + MaterialPageRoute(builder: (ctx) => const GroupMainPage())); } else { _showDialog('오류', '그룹 추가에 실패했습니다: ${response.body}'); } @@ -193,7 +195,7 @@ class _AddGroupPageState extends State { borderSide: BorderSide.none, ), contentPadding: - EdgeInsets.symmetric(vertical: 15), // 세로 여백 조정 + EdgeInsets.symmetric(vertical: 15), // 세로 여백 조정 counterText: "", // 글자 수 표시 없애기 ), ), @@ -209,13 +211,13 @@ class _AddGroupPageState extends State { borderSide: BorderSide.none, ), contentPadding: - EdgeInsets.symmetric(vertical: 15), // 세로 여백 조정 + EdgeInsets.symmetric(vertical: 15), // 세로 여백 조정 ), ), Container( color: Colors.white, padding: - const EdgeInsets.only(left: 10, right: 10, top: 10), + const EdgeInsets.only(left: 10, right: 10, top: 10), margin: const EdgeInsets.only(top: 30), child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -236,7 +238,7 @@ class _AddGroupPageState extends State { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: List.generate( 5, - (index) => GestureDetector( + (index) => GestureDetector( onTap: () { setState(() { selectedCategoryIndex = index; @@ -359,4 +361,4 @@ class _AddGroupPageState extends State { ), ); } -} +} \ No newline at end of file diff --git a/lib/routine_group/GroupMainPage.dart b/lib/routine_group/GroupMainPage.dart index 0beaba4..eac2bc3 100644 --- a/lib/routine_group/GroupMainPage.dart +++ b/lib/routine_group/GroupMainPage.dart @@ -164,16 +164,6 @@ class _GroupMainPageState extends State { backgroundColor: isExpanded ? Colors.grey[600] : const Color(0xFF8DCCFF), automaticallyImplyLeading: false, // 뒤로가기 제거 - // actions: [ - // Padding( - // padding: const EdgeInsets.only(right: 16.0), - // child: Image.asset( - // "assets/images/bell.png", - // width: 35, - // height: 35, - // ), - // ), - // ], ), body: DarkOverlay( isDark: isExpanded, // 눌렀을때만 어둡게 @@ -186,11 +176,26 @@ class _GroupMainPageState extends State { color: const Color(0xFFF8F8EF), child: Column( children: [ - const SizedBox( - height: 20, - ), Expanded( - child: ListView.builder( + child: groups.isEmpty + ? const Center( + child: Column( + children: [ + SizedBox(height: 200,), + Image( + image: AssetImage('assets/images/new-icons/ice.png'), + width: 150, // 원하는 크기로 설정 + height: 150, + ), + Text( + ' 아래 + 버튼을 눌러 \n 새로운 그룹에 가입해보세요', + style: TextStyle(fontSize: 20, color: Colors.grey, fontWeight: FontWeight.bold), + textAlign: TextAlign.center, // 텍스트 중앙 정렬 + ), + ], + ), + ) + : ListView.builder( itemCount: groups.length, itemBuilder: (context, index) { final group = groups[index]; @@ -223,8 +228,7 @@ class _GroupMainPageState extends State { ), if (!group.isPublic) Padding( - padding: - const EdgeInsets.only(left: 8.0), + padding: const EdgeInsets.only(left: 8.0), child: Image.asset( "assets/images/lock.png", width: 20, @@ -238,7 +242,6 @@ class _GroupMainPageState extends State { ), const SizedBox(height: 8.0), Row( - // mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ const Text("대표 카테고리 "), Text(group.groupCategory, @@ -304,7 +307,6 @@ class _GroupMainPageState extends State { ), GestureDetector( onTap: () { - // 통계 버튼 클릭 시 동작할 코드 Navigator.push( context, MaterialPageRoute( @@ -319,7 +321,6 @@ class _GroupMainPageState extends State { ), GestureDetector( onTap: () { - // 더보기 버튼 클릭 시 동작할 코드 Navigator.push( context, MaterialPageRoute(builder: (context) => const MyInfo()), @@ -359,7 +360,7 @@ class _GroupMainPageState extends State { onPressed: () { Navigator.push(context, MaterialPageRoute( builder: (context) { - return const GroupRoutinePage(); // 그룹 루틴 페이지 이동 바꿔야함 + return const GroupRoutinePage(); }, )); }, @@ -424,4 +425,5 @@ class _GroupMainPageState extends State { ), ); } + } \ No newline at end of file diff --git a/lib/routine_group/GroupRoutinePage.dart b/lib/routine_group/GroupRoutinePage.dart index 9c7ece7..2b253c9 100644 --- a/lib/routine_group/GroupRoutinePage.dart +++ b/lib/routine_group/GroupRoutinePage.dart @@ -118,7 +118,7 @@ class _GroupRoutinePageState extends State { children: [ Text(Egroup.groupTitle, style: const TextStyle(color: Colors.black)), - const SizedBox(height: 1.0), //그룹 여백 + const SizedBox(height: 1.0), Text("그룹 코드 #${Egroup.groupId}", textAlign: TextAlign.center, style: const TextStyle(color: Colors.grey, fontSize: 13)), @@ -129,7 +129,7 @@ class _GroupRoutinePageState extends State { mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, children: [ - const SizedBox(height: 0), //그룹 코드와 대표 카테고리 사이의 여백 + const SizedBox(height: 0), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ @@ -175,19 +175,24 @@ class _GroupRoutinePageState extends State { child: const Text("취소", style: TextStyle( color: Color.fromARGB(255, 128, 121, 121))), - onPressed: () { + onPressed: () async { Navigator.of(context).pop(); }, ), TextButton( child: const Text("그룹 가입", style: TextStyle(color: Color(0xff8DCCFF))), - onPressed: () { - Navigator.of(context).pop(); + onPressed: () async { + Navigator.of(context).pop(); // 다이얼로그 닫기 if (Egroup.isPublic) { - print("참여 성공!"); + bool joinSuccess = await _joinGroup(Egroup.groupId); + if (joinSuccess) { + navigateToGroupPage(Egroup.groupId); // 가입 성공 시 페이지 이동 + } else { + print("그룹 참여 실패!"); + } } else { - _showPasswordDialog(Egroup); + _showPasswordDialog(Egroup); // 비밀번호 입력 필요 시 다이얼로그 표시 } }, ), diff --git a/lib/routine_group/OnClickGroupPage.dart b/lib/routine_group/OnClickGroupPage.dart index b4cfd4d..e36e924 100644 --- a/lib/routine_group/OnClickGroupPage.dart +++ b/lib/routine_group/OnClickGroupPage.dart @@ -8,6 +8,7 @@ import 'package:routine_ade/routine_groupLeader/AddGroupRoutinePage.dart'; import 'package:routine_ade/routine_group/ChatScreen.dart'; import 'package:routine_ade/routine_group/GroupMainPage.dart'; import 'package:routine_ade/routine_group/GroupRoutinePage.dart'; +import 'package:routine_ade/routine_groupLeader/groupEdit.dart'; import 'package:routine_ade/routine_home/MyRoutinePage.dart'; import 'package:http/http.dart' as http; import 'groupType.dart'; @@ -334,8 +335,8 @@ class _OnClickGroupPageState extends State Navigator.push( context, MaterialPageRoute( - builder: (context) => - OtherUserRoutinePage(userId: groupmember.userId), + builder: (context) => OtherUserRoutinePage( + userId: groupmember.userId, groupId: widget.groupId), ), ); }, diff --git a/lib/routine_groupLeader/AddGroupRoutinePage.dart b/lib/routine_groupLeader/AddGroupRoutinePage.dart index 7fb0e4c..db25149 100644 --- a/lib/routine_groupLeader/AddGroupRoutinePage.dart +++ b/lib/routine_groupLeader/AddGroupRoutinePage.dart @@ -5,6 +5,7 @@ import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter/cupertino.dart'; +import 'package:routine_ade/routine_groupLeader/glOnClickGroupPage.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:intl/intl.dart'; //날짜 포맷팅 init 패키지 import 'package:http/http.dart' as http; @@ -96,7 +97,12 @@ class _AddRoutinePageState extends State { print('Response body: ${utf8.decode(response.bodyBytes)}'); if (response.statusCode == 200 || response.statusCode == 201) { - _showDialog('성공', '루틴이 성공적으로 추가되었습니다.'); + Navigator.pushReplacement( + context, + MaterialPageRoute( + builder: (ctx) => glOnClickGroupPage( + groupId: widget.groupId, + ))); } else { _showDialog('오류', '루틴 추가에 실패했습니다: ${utf8.decode(response.bodyBytes)}'); } diff --git a/lib/routine_groupLeader/glOnClickGroupPage.dart b/lib/routine_groupLeader/glOnClickGroupPage.dart index 8fcb4a6..949d3cd 100644 --- a/lib/routine_groupLeader/glOnClickGroupPage.dart +++ b/lib/routine_groupLeader/glOnClickGroupPage.dart @@ -44,7 +44,7 @@ class glOnClickGroupPage extends StatefulWidget { class _glOnClickGroupPageState extends State with SingleTickerProviderStateMixin { final GlobalKey _scaffoldKey = GlobalKey(); - bool _isSwitchOn = false; + final bool _isSwitchOn = false; late TabController _tabController; late Future futureGroupResponse; bool _isFloatingActionButtonVisible = true; @@ -365,7 +365,8 @@ class _glOnClickGroupPageState extends State Navigator.push( context, MaterialPageRoute( - builder: (context) => OtherUserRoutinePage(userId: member.userId), + builder: (context) => OtherUserRoutinePage( + userId: member.userId, groupId: widget.groupId), ), ); }, diff --git a/lib/routine_groupLeader/groupRoutineEditPage.dart b/lib/routine_groupLeader/groupRoutineEditPage.dart index 6b26112..1db0be2 100644 --- a/lib/routine_groupLeader/groupRoutineEditPage.dart +++ b/lib/routine_groupLeader/groupRoutineEditPage.dart @@ -308,7 +308,7 @@ class _groupRoutineEditPageState extends State { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: List.generate( 5, - (index) => GestureDetector( + (index) => GestureDetector( onTap: () { setState(() { selectedCategoryIndex = index; @@ -353,7 +353,7 @@ class _groupRoutineEditPageState extends State { onPressed: _ModifiedRoutine, style: ButtonStyle( backgroundColor: - WidgetStateProperty.all(const Color(0xFFB4DDFF)), + WidgetStateProperty.all(const Color(0xFFB4DDFF)), shape: WidgetStateProperty.all( RoundedRectangleBorder( borderRadius: BorderRadius.circular(10.0), @@ -396,4 +396,4 @@ class _groupRoutineEditPageState extends State { return ''; } } -} \ No newline at end of file +} diff --git a/lib/routine_groupLeader/groupType.dart b/lib/routine_groupLeader/groupType.dart index 309f5c4..8b13789 100644 --- a/lib/routine_groupLeader/groupType.dart +++ b/lib/routine_groupLeader/groupType.dart @@ -1,465 +1 @@ -import 'dart:convert'; -import 'package:flutter/material.dart'; -import 'package:http/http.dart' as http; -import 'package:routine_ade/routine_user/token.dart'; -class GroupRoutinePage extends StatefulWidget { - const GroupRoutinePage({super.key}); - - @override - _GroupRoutinePageState createState() => _GroupRoutinePageState(); -} - -class _GroupRoutinePageState extends State { - final TextEditingController _searchController = TextEditingController(); - final TextEditingController _passwordController = TextEditingController(); - List allGroups = []; - List filteredGroups = []; - bool _isSearching = false; - bool _isPasswordIncorrect = false; - bool _isLoading = false; - int _currentPage = 1; - final int _pageSize = 10; - String? selectedCategory = '전체'; - - @override - void initState() { - super.initState(); - // _fetchGroups(); - } - - Future _fetchGroups({bool loadMore = false, String? category}) async { - if (loadMore) { - _currentPage++; - } else { - setState(() { - _isLoading = true; - _currentPage = 1; - allGroups.clear(); - }); - } - - String categoryQuery = category != null && category != '전체' - ? 'groupCategory=${Uri.encodeComponent(category)}' - : 'groupCategory=%EC%A0%84%EC%B2%B4'; - final url = Uri.parse('http://15.164.88.94/groups?$categoryQuery'); - final response = await http.get(url, headers: { - 'Content-Type': 'application/json', - 'Authorization': 'Bearer $token', - }); - - if (response.statusCode == 200) { - final decodedResponse = utf8.decode(response.bodyBytes); - final data = jsonDecode(decodedResponse); - - setState(() { - if (data is Map && data.containsKey('groups')) { - final newGroups = (data['groups'] as List) - .map((json) => EntireGroup.fromJson(json)) - .toList(); - allGroups.addAll(newGroups); - } - - filteredGroups = allGroups; - _sortGroupsByGroupIdDescending(); // 그룹 정렬 추가 - _isLoading = false; - }); - } else { - setState(() { - _isLoading = false; - }); - print("그룹 불러오기를 실패하였습니다."); - print("Status Code: ${response.statusCode}"); - print("Response Body: ${response.body}"); - } - } - - Color getCategoryColor(String category) { - switch (category) { - case "전체": - return Colors.black; - case "건강": - return const Color(0xff6ACBF3); - case "자기개발": - return const Color(0xff7BD7C6); - case "일상": - return const Color(0xffF5A77B); - case "자기관리": - return const Color(0xffC69FEC); - default: - return const Color(0xffF4A2D8); - } - } - - void toggleSearch() { - setState(() { - _isSearching = !_isSearching; - if (!_isSearching) { - _searchController.clear(); - filterGroups(''); - } - }); - } - - void _sortGroupsByGroupIdDescending() { - filteredGroups.sort((a, b) => b.groupId.compareTo(a.groupId)); - } - - void filterGroups(String query) { - setState(() { - if (query.isNotEmpty) { - filteredGroups = allGroups - .where((group) => - group.groupTitle.toLowerCase().contains(query.toLowerCase())) - .toList(); - } else { - filteredGroups = allGroups; - } - _sortGroupsByGroupIdDescending(); // 필터 후 정렬 유지 - }); - } - - void _showGroupDialog(EntireGroup Egroup) { - if (Egroup.isPublic) { - showDialog( - context: context, - builder: (BuildContext context) { - return AlertDialog( - backgroundColor: Colors.white, // 배경색을 하얀색으로 설정 - title: Center(child: Text(Egroup.groupTitle)), // 가운데 정렬 - content: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.center, // 가운데 정렬 - children: [ - Text("그룹 코드 #${Egroup.groupId}"), - Text("대표 카테고리 ${Egroup.groupCategory}"), - Text("루틴장 ${Egroup.createdUserNickname}"), - Text("인원 ${Egroup.joinMemberCount}/${Egroup.maxMemberCount}명"), - ], - ), - actions: [ - OverflowBar( - alignment: MainAxisAlignment.end, // 버튼들을 오른쪽에 정렬 - children: [ - TextButton( - child: const Text("가입하기"), - onPressed: () { - Navigator.of(context).pop(); - }, - ), - TextButton( - child: const Text("취소"), - onPressed: () { - Navigator.of(context).pop(); - // 참여 로직 추가 가능 - }, - ), - ], - ), - ], - ); - }, - ); - } else { - _showPasswordDialog(Egroup); - } - } - - void _showPasswordDialog(EntireGroup group) { - showDialog( - context: context, - builder: (BuildContext context) { - return AlertDialog( - backgroundColor: Colors.white, // 배경색을 하얀색으로 설정 - title: const Center(child: Text("비공개 그룹")), // 가운데 정렬 - content: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.center, // 가운데 정렬 - children: [ - TextField( - controller: _passwordController, - obscureText: true, - decoration: InputDecoration( - labelText: "비밀번호 4자리 입력", - errorText: _isPasswordIncorrect ? "비밀번호가 틀렸습니다." : null, - ), - ), - ], - ), - actions: [ - OverflowBar( - alignment: MainAxisAlignment.end, // 버튼들을 오른쪽에 정렬 - children: [ - TextButton( - child: const Text("취소"), - onPressed: () { - Navigator.of(context).pop(); - _passwordController.clear(); - _isPasswordIncorrect = false; - }, - ), - TextButton( - child: const Text("확인"), - onPressed: () { - _checkPassword(group); - }, - ), - ], - ), - ], - ); - }, - ); - } - - void _checkPassword(EntireGroup group) { - setState(() { - if (_passwordController.text == group.groupPassword) { - Navigator.of(context).pop(); - _passwordController.clear(); - _isPasswordIncorrect = false; - // 비밀번호가 맞으면, 참여 로직 추가 가능 - print("참여 성공!"); - } else { - _isPasswordIncorrect = true; - } - }); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: _isSearching - ? TextField( - controller: _searchController, - decoration: const InputDecoration( - hintText: " 그룹명을 입력하세요", - fillColor: Colors.white, - filled: true, - contentPadding: EdgeInsets.symmetric( - vertical: 12.0, - ), - ), - onChanged: (value) { - filterGroups(value); - }, - ) - : const Text( - "루틴 그룹", - style: TextStyle( - color: Colors.black, - fontSize: 23, - fontWeight: FontWeight.bold), - ), - centerTitle: true, - backgroundColor: Colors.grey[200], - actions: [ - IconButton( - icon: _isSearching - ? const Icon(Icons.close) - : Image.asset("assets/images/search.png", - width: 27, height: 27), - onPressed: toggleSearch, - ), - ], - ), - body: Stack( - children: [ - Container( - color: Colors.grey[200], - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 7.0), - child: Container( - color: Colors.grey[200], - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Container( - color: Colors.grey[200], - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 1.0), - child: SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - children: ['전체', '일상', '건강', '자기개발', '자기관리', '기타'] - .map((category) { - bool isSelected = selectedCategory == category; - return Padding( - padding: - const EdgeInsets.symmetric(horizontal: 3.0), - child: ElevatedButton( - onPressed: () { - setState(() { - selectedCategory = category; - }); - _fetchGroups(category: category); - }, - style: ButtonStyle( - backgroundColor: WidgetStateProperty.all( - isSelected - ? Colors.white - : const Color(0xE8E8E8EF), - ), - ), - child: Text( - category, - style: TextStyle( - color: getCategoryColor( - category), // Always set the color based on the category - ), - ), - ), - ); - }).toList(), - ), - ), - ), - ), - Expanded( - child: _isLoading - ? const Center(child: CircularProgressIndicator()) - // : (!_isSearching && filteredGroups.isEmpty) - : filteredGroups.isEmpty - ? const Center(child: Text('검색 결과가 없습니다.')) - : (!_isSearching) - ? const Center(child: Text('그룹을 검색하세요.')) - : ListView.builder( - itemCount: filteredGroups.length, - itemBuilder: (context, index) { - final group = filteredGroups[index]; - Color textColor = getCategoryColor( - group.groupCategory); - return InkWell( - onTap: () { - _showGroupDialog(group); - }, - child: Card( - margin: const EdgeInsets.all(8.0), - color: Colors.white, - child: Padding( - padding: - const EdgeInsets.all(16.0), - child: Column( - crossAxisAlignment: - CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: - MainAxisAlignment - .spaceBetween, - children: [ - Row( - children: [ - Text( - group.groupTitle, - style: - const TextStyle( - fontSize: 18, - fontWeight: - FontWeight - .bold, - ), - ), - if (!group.isPublic) - Padding( - padding: - const EdgeInsets - .only( - left: - 8.0), - child: - Image.asset( - "assets/images/lock.png", - width: 20, - height: 20, - ), - ), - ], - ), - ], - ), - const SizedBox(height: 8.0), - Row( - children: [ - const Text("대표 카테고리 "), - Text(group.groupCategory, - style: TextStyle( - color: - textColor)), - Expanded( - child: Container()), - Align( - alignment: Alignment - .centerRight, - child: Text( - "인원 ${group.joinMemberCount}/${group.maxMemberCount}명"), - ), - ], - ), - const SizedBox(height: 8.0), - Row( - mainAxisAlignment: - MainAxisAlignment - .spaceBetween, - children: [ - Text( - "루틴장 ${group.createdUserNickname}"), - Text( - "그룹코드 ${group.groupId}"), - ], - ), - ], - ), - ), - ), - ); - }, - ), - ), - ], - ), - ), - ), - ), - ], - ), - ); - } -} - -class EntireGroup { - final int groupId; - final String groupTitle; - final String groupCategory; - final String createdUserNickname; - final int maxMemberCount; - final int joinMemberCount; - final bool isPublic; - final String? groupPassword; - - EntireGroup({ - required this.groupId, - required this.groupTitle, - required this.groupCategory, - required this.createdUserNickname, - required this.maxMemberCount, - required this.joinMemberCount, - required this.isPublic, - this.groupPassword, - }); - - factory EntireGroup.fromJson(Map json) { - return EntireGroup( - groupId: json['groupId'] ?? 0, - groupTitle: json['groupTitle'] ?? 'Unknown', - groupCategory: json['groupCategory'] ?? '기타', - createdUserNickname: json['createdUserNickname'] ?? 'Unknown', - maxMemberCount: json['maxMemberCount'] ?? 0, - joinMemberCount: json['joinMemberCount'] ?? 0, - isPublic: json['isPublic'] ?? true, - groupPassword: json['groupPassword'], - ); - } -} \ No newline at end of file diff --git a/lib/routine_home/AddRoutinePage.dart b/lib/routine_home/AddRoutinePage.dart index cb4db22..b6a06f9 100644 --- a/lib/routine_home/AddRoutinePage.dart +++ b/lib/routine_home/AddRoutinePage.dart @@ -99,7 +99,8 @@ class _AddRoutinePageState extends State { print('Response body: ${response.body}'); if (response.statusCode == 200 || response.statusCode == 201) { - _showDialog('성공', '루틴이 성공적으로 추가되었습니다.'); + Navigator.pushReplacement(context, + MaterialPageRoute(builder: (ctx) => const MyRoutinePage())); } else { _showDialog('오류', '루틴 추가에 실패했습니다: ${response.body}'); } @@ -302,7 +303,7 @@ class _AddRoutinePageState extends State { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: List.generate( 5, - (index) => GestureDetector( + (index) => GestureDetector( onTap: () { setState(() { selectedCategoryIndex = index; @@ -320,7 +321,7 @@ class _AddRoutinePageState extends State { : const Color(0xFFF0F0F0), borderRadius: BorderRadius.circular(20), border: - Border.all(color: const Color(0xFFF0F0F0)), + Border.all(color: const Color(0xFFF0F0F0)), ), alignment: Alignment.center, child: Text( @@ -449,7 +450,7 @@ class _AddRoutinePageState extends State { onPressed: _addRoutine, style: ButtonStyle( backgroundColor: - WidgetStateProperty.all(const Color(0xffB4DDFF)), + WidgetStateProperty.all(const Color(0xffB4DDFF)), shape: WidgetStateProperty.all( RoundedRectangleBorder( borderRadius: BorderRadius.circular(10.0), //테두리 둥글게 @@ -494,4 +495,4 @@ class _AddRoutinePageState extends State { return ''; } } -} +} \ No newline at end of file diff --git a/lib/routine_home/MyRoutinePage.dart b/lib/routine_home/MyRoutinePage.dart index 480fd9c..1de2665 100644 --- a/lib/routine_home/MyRoutinePage.dart +++ b/lib/routine_home/MyRoutinePage.dart @@ -173,6 +173,7 @@ class _MyRoutinePageState extends State style: const TextStyle(fontSize: 20), ), ), + const SizedBox(height: 25), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ @@ -346,15 +347,30 @@ class _MyRoutinePageState extends State return const Center(child: CircularProgressIndicator()); } else if (snapshot.hasError) { return Center( - child: Text('루틴을 불러오는 중 오류가 발생했습니다: ${snapshot.error}')); + child: + Text('루틴을 불러오는 중 오류가 발생했습니다: ${snapshot.error}')); } else if (!snapshot.hasData || - (snapshot.data!.personalRoutines.isEmpty && snapshot.data!.groupRoutines.isEmpty)) { + (snapshot.data!.personalRoutines.isEmpty && + snapshot.data!.groupRoutines.isEmpty)) { // 개인 루틴과 그룹 루틴이 모두 비어있을 때 문구 표시 return const Center( - child: Text( - '\n\t\t\t\t\t\t\t\t 아래 + 버튼을 눌러 \n 새로운 루틴을 추가해보세요', - style: TextStyle(fontSize: 20, color: Colors.grey), - )); + child: Column( + children: [ + SizedBox(height: 100,), + Image( + image: AssetImage('assets/images/new-icons/ice.png'), + width: 150, // 원하는 크기로 설정 + height: 150, + ), + Text( + ' 아래 + 버튼을 눌러 \n 새로운 루틴을 추가해보세요', + style: TextStyle(fontSize: 20, color: Colors.grey, fontWeight: FontWeight.bold), + textAlign: TextAlign.center, // 텍스트 중앙 정렬 + ), + ], + ), + ); + } // 감정 상태를 업데이트 @@ -369,7 +385,8 @@ class _MyRoutinePageState extends State padding: const EdgeInsets.fromLTRB(10, 5, 10, 5), decoration: BoxDecoration( color: const Color(0xFFE6F5F8), // 배경색 설정 - borderRadius: BorderRadius.circular(12), // 둥근 모서리 설정 + borderRadius: + BorderRadius.circular(12), // 둥근 모서리 설정 ), child: Theme( data: Theme.of(context).copyWith( @@ -381,16 +398,21 @@ class _MyRoutinePageState extends State fontSize: 20, color: Colors.black)), // 텍스트 색상 변경 initiallyExpanded: true, // 초기상태를 펼친상태로 변경 - children: snapshot.data!.personalRoutines.map((category) { + children: snapshot.data!.personalRoutines + .map((category) { return Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Padding( - padding: const EdgeInsets.only(left: 10, top: 5), + padding: const EdgeInsets.only( + left: 10, top: 5), child: Container( decoration: BoxDecoration( - color: const Color.fromARGB(255, 255, 255, 255), - borderRadius: BorderRadius.circular(20.0), + color: const Color.fromARGB( + 255, 255, 255, 255), + borderRadius: + BorderRadius.circular(20.0), ), padding: const EdgeInsets.symmetric( horizontal: 10, vertical: 1), @@ -407,7 +429,8 @@ class _MyRoutinePageState extends State ), // 카테고리 밑에 루틴 추가 ...category.routines.map((routine) { - return _buildRoutineTile(routine); // 기존 _buildRoutineTile 메서드 사용 + return _buildRoutineTile( + routine); // 기존 _buildRoutineTile 메서드 사용 }), ], ); @@ -424,7 +447,8 @@ class _MyRoutinePageState extends State return Padding( padding: const EdgeInsets.only(bottom: 10), child: Container( - padding: const EdgeInsets.fromLTRB(10, 5, 10, 5), + padding: + const EdgeInsets.fromLTRB(10, 5, 10, 5), decoration: BoxDecoration( color: const Color(0xFFE6F5F8), borderRadius: BorderRadius.circular(12), @@ -435,8 +459,10 @@ class _MyRoutinePageState extends State ), child: ExpansionTile( title: Row( - mainAxisAlignment: MainAxisAlignment.start, // 시작 부분에 배치 - crossAxisAlignment: CrossAxisAlignment.center, // 수직 중앙 정렬 + mainAxisAlignment: + MainAxisAlignment.start, // 시작 부분에 배치 + crossAxisAlignment: + CrossAxisAlignment.center, // 수직 중앙 정렬 children: [ Text( group.groupTitle, @@ -445,8 +471,10 @@ class _MyRoutinePageState extends State color: Colors.black, ), ), - const SizedBox(width: 8), // 제목과 아이콘 사이 간격 - if (group.isAlarmEnabled) // 알림이 활성화된 경우에만 벨 아이콘 표시 + const SizedBox( + width: 8), // 제목과 아이콘 사이 간격 + if (group + .isAlarmEnabled) // 알림이 활성화된 경우에만 벨 아이콘 표시 Image.asset( 'assets/images/bell.png', // bell.png 이미지 경로 width: 20, @@ -454,26 +482,37 @@ class _MyRoutinePageState extends State ), ], ), - children: group.groupRoutines.map((categoryGroup) { + children: group.groupRoutines + .map((categoryGroup) { return Column( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, children: [ Padding( - padding: const EdgeInsets.only(left: 10), + padding: + const EdgeInsets.only(left: 10), child: Container( decoration: BoxDecoration( - color: const Color.fromARGB(255, 255, 255, 255), - borderRadius: BorderRadius.circular(20.0), + color: const Color.fromARGB( + 255, 255, 255, 255), + borderRadius: + BorderRadius.circular(20.0), ), - padding: const EdgeInsets.symmetric( - horizontal: 10.0, vertical: 1), + padding: + const EdgeInsets.symmetric( + horizontal: 10.0, + vertical: 1), child: Column( children: [ Text( - categoryGroup.routineCategory, // 카테고리 이름 + categoryGroup + .routineCategory, // 카테고리 이름 style: TextStyle( - color: _getCategoryColor(categoryGroup.routineCategory), - fontWeight: FontWeight.bold, + color: _getCategoryColor( + categoryGroup + .routineCategory), + fontWeight: + FontWeight.bold, fontSize: 18, ), ), @@ -482,7 +521,8 @@ class _MyRoutinePageState extends State ), ), ...categoryGroup.routines.map( - (routine) => _buildRoutineTile2(routine)), // 루틴 목록 + (routine) => _buildRoutineTile2( + routine)), // 루틴 목록 ], ); }).toList(), @@ -499,7 +539,6 @@ class _MyRoutinePageState extends State ), ), ) - ], ), ); diff --git a/lib/routine_otherUser/OtherUserRoutinePage.dart b/lib/routine_otherUser/OtherUserRoutinePage.dart index f23ca3d..e2a36f0 100644 --- a/lib/routine_otherUser/OtherUserRoutinePage.dart +++ b/lib/routine_otherUser/OtherUserRoutinePage.dart @@ -4,12 +4,12 @@ import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_calendar_week/flutter_calendar_week.dart'; -import 'package:intl/date_symbol_data_local.dart'; -import 'package:routine_ade/routine_myInfo/MyInfo.dart'; -import 'package:routine_ade/routine_group/GroupType.dart'; -import 'package:routine_ade/routine_group/GroupMainPage.dart'; -import 'package:routine_ade/routine_home/AlarmListPage.dart'; -import 'package:routine_ade/routine_home/ModifiedRoutinePage.dart'; +// import 'package:intl/date_symbol_data_local.dart'; +// import 'package:routine_ade/routine_myInfo/MyInfo.dart'; +// import 'package:routine_ade/routine_group/GroupType.dart'; +// import 'package:routine_ade/routine_group/GroupMainPage.dart'; +// import 'package:routine_ade/routine_home/AlarmListPage.dart'; +// import 'package:routine_ade/routine_home/ModifiedRoutinePage.dart'; import 'dart:convert'; import 'package:http/http.dart' as http; import 'package:intl/intl.dart'; @@ -20,7 +20,10 @@ import 'package:routine_ade/routine_statistics/StaticsCalendar.dart'; class OtherUserRoutinePage extends StatefulWidget { final int userId; - const OtherUserRoutinePage({required this.userId, super.key}); + final int groupId; + + const OtherUserRoutinePage( + {required this.userId, required this.groupId, super.key}); @override State createState() => _OtherUserRoutinePageState(); @@ -47,8 +50,10 @@ class _OtherUserRoutinePageState extends State super.initState(); _controller = CalendarWeekController(); + String todayDate = DateFormat('yyyy.MM.dd').format(DateTime.now()); // 여기서 widget.userId로 접근해야 함 - futureRoutineResponse2 = fetchRoutinesByUserId(widget.userId); + futureRoutineResponse2 = + fetchRoutinesByUserId(widget.userId, widget.groupId, todayDate); _tabController = TabController(length: 3, vsync: this); } @@ -98,7 +103,7 @@ class _OtherUserRoutinePageState extends State final nickname = snapshot.data?.nickname ?? 'No nickname available'; final intro = snapshot.data?.intro ?? 'No intro available'; final userEmotion = snapshot.data?.userEmotion ?? 'null'; - final personalRoutines = snapshot.data?.personalRoutines ?? []; + // final personalRoutines = snapshot.data?.personalRoutines ?? []; final groupRoutines = snapshot.data?.groupRoutines ?? []; return Column( @@ -114,7 +119,7 @@ class _OtherUserRoutinePageState extends State backgroundImage: profileImage.isNotEmpty ? NetworkImage(profileImage) : const AssetImage('assets/profile_placeholder.png') - as ImageProvider, + as ImageProvider, ), const SizedBox(width: 20), Column( @@ -154,7 +159,7 @@ class _OtherUserRoutinePageState extends State unselectedLabelColor: Colors.grey, indicator: const UnderlineTabIndicator( borderSide: - BorderSide(width: 3.0, color: Color(0xFF8DCCFF)), + BorderSide(width: 3.0, color: Color(0xFF8DCCFF)), insets: EdgeInsets.symmetric(horizontal: 90.0), ), ), @@ -190,17 +195,17 @@ class _OtherUserRoutinePageState extends State children: [ const SizedBox(width: 10), userEmotion.isNotEmpty && - getImageEmotion(userEmotion) != null + getImageEmotion(userEmotion) != null ? Image.asset( - getImageEmotion(userEmotion)!, - fit: BoxFit.cover, - width: 50, - height: 50, - ) + getImageEmotion(userEmotion)!, + fit: BoxFit.cover, + width: 50, + height: 50, + ) : Image.asset( - "assets/images/new-icons/김외롭.png", - width: 50, - height: 50), + "assets/images/emotion/no-emotion.png", + width: 50, + height: 50), const SizedBox(width: 10), Expanded( child: RichText( @@ -208,7 +213,7 @@ class _OtherUserRoutinePageState extends State style: const TextStyle( fontSize: 18, color: Colors.black), children: - _buildEmotionText(userEmotion), + _buildEmotionText(userEmotion), ), ), ), @@ -220,28 +225,27 @@ class _OtherUserRoutinePageState extends State Expanded( child: Container( color: const Color(0xFFF8F8EF), - child: personalRoutines.isEmpty && - groupRoutines.isEmpty + child: groupRoutines.isEmpty ? const Center( - child: Text( - ' 등록된 루틴이 없습니다.', - style: TextStyle( - fontSize: 20, color: Colors.grey), - ), - ) + child: Text( + ' 등록된 루틴이 없습니다.', + style: TextStyle( + fontSize: 20, color: Colors.grey), + ), + ) : ListView( - padding: const EdgeInsets.fromLTRB( - 24, 10, 24, 16), - children: [ - _buildRoutineSection( - "개인 루틴", personalRoutines), - const SizedBox(height: 10), - ...groupRoutines.map((group) { - return _buildGroupRoutineSection(group); - }), - const SizedBox(height: 10), - ], - ), + padding: const EdgeInsets.fromLTRB( + 24, 10, 24, 16), + children: [ + // _buildRoutineSection( + // "개인 루틴", personalRoutines), + const SizedBox(height: 10), + ...groupRoutines.map((group) { + return _buildGroupRoutineSection(group); + }), + const SizedBox(height: 10), + ], + ), ), ), ], @@ -297,7 +301,7 @@ class _OtherUserRoutinePageState extends State const TextSpan( text: '나쁜', style: - TextStyle(fontWeight: FontWeight.bold, color: Colors.redAccent), + TextStyle(fontWeight: FontWeight.bold, color: Colors.redAccent), ), const TextSpan(text: ' 날이에요') ]; @@ -311,59 +315,6 @@ class _OtherUserRoutinePageState extends State } } -// 개인 루틴 섹션 빌드 - Widget _buildRoutineSection( - String title, List routines) { - return routines.isNotEmpty - ? Container( - padding: const EdgeInsets.all(10), - decoration: BoxDecoration( - color: const Color(0xFFE6F5F8), - borderRadius: BorderRadius.circular(12), - ), - child: Theme( - data: - Theme.of(context).copyWith(dividerColor: Colors.transparent), - child: ExpansionTile( - title: Text( - title, - style: const TextStyle(fontSize: 20, color: Colors.black), - ), - children: routines.map((category) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.only(left: 10, top: 5), - child: Container( - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(20), - ), - padding: const EdgeInsets.symmetric( - horizontal: 10, vertical: 1), - child: Text( - category.routineCategory, - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: - _getCategoryColor(category.routineCategory), - ), - ), - ), - ), - ...category.routines - .map((routine) => _buildRoutineTile(routine)), - ], - ); - }).toList(), - ), - ), - ) - : Container(); // 빈 루틴 섹션 처리 - } - // 그룹 루틴 섹션 빌드 Widget _buildGroupRoutineSection(Group2 group) { return Container( @@ -372,24 +323,36 @@ class _OtherUserRoutinePageState extends State color: const Color(0xFFE6F5F8), borderRadius: BorderRadius.circular(12), ), - child: Theme( - data: Theme.of(context).copyWith(dividerColor: Colors.transparent), - child: ExpansionTile( - title: Text(group.groupTitle, - style: const TextStyle(fontSize: 20, color: Colors.black)), - children: group.groupRoutines.map((categoryGroup) { + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // 그룹 제목 표시 + Padding( + padding: const EdgeInsets.only(left: 10), + child: Text( + group.groupTitle, + style: const TextStyle( + fontSize: 20, + color: Colors.black, + fontWeight: FontWeight.bold), + ), + ), + const SizedBox(height: 15), + + // 그룹 루틴 카테고리 및 루틴 항목들 표시 + ...group.groupRoutines.map((categoryGroup) { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( - padding: const EdgeInsets.only(left: 10), + padding: const EdgeInsets.only(left: 10, bottom: 5), child: Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(20), ), padding: - const EdgeInsets.symmetric(horizontal: 10, vertical: 1), + const EdgeInsets.symmetric(horizontal: 10, vertical: 5), child: Text( categoryGroup.routineCategory, style: TextStyle( @@ -404,8 +367,8 @@ class _OtherUserRoutinePageState extends State .map((routine) => _buildRoutineTile2(routine)), ], ); - }).toList(), - ), + }), + ], ), ); } @@ -466,12 +429,12 @@ class _OtherUserRoutinePageState extends State activeColor: const Color(0xFF8DCCFF), checkColor: Colors.white, fillColor: WidgetStateProperty.resolveWith( - (Set states) { - if (states.contains(WidgetState.selected)) { - return const Color(0xFF8DCCFF); - } - return Colors.transparent; - }), + (Set states) { + if (states.contains(WidgetState.selected)) { + return const Color(0xFF8DCCFF); + } + return Colors.transparent; + }), ), ), ), @@ -507,69 +470,21 @@ class _OtherUserRoutinePageState extends State ), ); } - - Widget _buildRoutineTile(Routine routine) { - Color categoryColor = _getCategoryColor(routine.routineCategory); - -//개인루틴 - return Padding( - padding: const EdgeInsets.symmetric(vertical: 0), - child: ListTile( - contentPadding: const EdgeInsets.symmetric(horizontal: 20), // 좌우 여백 조절 - minLeadingWidth: 0, - leading: const Icon( - Icons.brightness_1, - size: 8, - color: Colors.black, - ), - title: Row( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: - MainAxisAlignment.start, // Align elements to the start of the row - children: [ - Text(routine.routineTitle, - style: const TextStyle(fontWeight: FontWeight.bold)), - const SizedBox(width: 3), // Adjust the width as needed - if (routine.isAlarmEnabled) // Conditionally display the bell icon - GestureDetector( - onTap: () { - // Do nothing when the image is tapped3 - }, - child: Image.asset('assets/images/bell.png', - width: 20, height: 20), - ), - ], - ), - trailing: Transform.scale( - scale: 1.2, // Checkbox size increased by 1.5 times - child: Checkbox( - value: routine.isCompletion, - onChanged: (bool? value) {}, - activeColor: const Color(0xFF8DCCFF), - checkColor: Colors.white, - fillColor: WidgetStateProperty.resolveWith( - (Set states) { - if (states.contains(WidgetState.selected)) { - return const Color(0xFF8DCCFF); - } - return Colors.transparent; - }), - ), - ), - ), - ); - } } //루틴, 감정 조회 -Future fetchRoutinesByUserId(int userId) async { +Future fetchRoutinesByUserId( + int userId, int groupId, String routineDate) async { + print('사용할 토큰: $token'); // 요청 전에 토큰을 출력하여 확인 print('API 요청 사용자 ID: $userId'); // 요청할 사용자 ID를 출력하여 확인 + print('요청그룹: $groupId '); try { final response = await http.get( - Uri.parse('http://15.164.88.94/users/$userId/routines'), // userId로 조회 + Uri.parse( + 'http://15.164.88.94/groups/$groupId/users/$userId/routines?routineDate=$routineDate'), headers: { - 'Authorization': 'Bearer $token', // 적절한 토큰 사용 + 'Authorization': 'Bearer $token', 'Content-Type': 'application/json; charset=UTF-8', // UTF-8 설정 }, ); @@ -605,7 +520,7 @@ String? getImageEmotion(String emotion) { case 'ANGRY': return 'assets/images/emotion/angry.png'; default: - return "assets/images/new-icons/김외롭.png"; // 기본 이미지 + return "assets/images/emotion/no-emotion.png"; // 기본 이미지 } } @@ -620,8 +535,8 @@ String getTextForEmotion(String emotion) { return '이 날은 기분이 우중충한 날이에요'; case 'ANGRY': return '이 날은 기분이 나쁜 날이에요'; - // case 'null': - // return '기분을 추가해보세요!'; + // case 'null': + // return '기분을 추가해보세요!'; default: return '기분을 추가해보세요!'; // 기본 텍스트 } @@ -633,10 +548,10 @@ class RoutineResponse2 { final String profileImage; final String nickname; final String intro; - final List personalRoutines; - final List groupRoutines; + // final List personalRoutines; + final List groupRoutines; //userGroupInfo final String userEmotion; - final List routines; + // final List routines; // final List groupRoutineCategories; RoutineResponse2({ @@ -644,10 +559,10 @@ class RoutineResponse2 { required this.profileImage, required this.nickname, required this.intro, - required this.personalRoutines, + // required this.personalRoutines, required this.groupRoutines, required this.userEmotion, - required this.routines, + // required this.routines, // required this.groupRoutineCategories, }); @@ -657,75 +572,11 @@ class RoutineResponse2 { profileImage: json['profileImage'] ?? '', // 한국어로 된 필드명을 사용하여 데이터를 파싱 nickname: json['nickname'] ?? '기타', intro: json['intro'] ?? '기타', - personalRoutines: (json['personalRoutines'] as List?) - ?.map((item) => - UserRoutineCategory.fromJson(item as Map)) - .toList() ?? - [], - groupRoutines: (json['groupRoutines'] as List?) - ?.map((item) => Group2.fromJson(item as Map)) - .toList() ?? + groupRoutines: (json['userGroupInfo'] as List?) + ?.map((item) => Group2.fromJson(item as Map)) + .toList() ?? [], userEmotion: json['userEmotion'] ?? 'null', - routines: (json['routines'] as List?) - ?.map((item) => - UserRoutineCategory.fromJson(item as Map)) - .toList() ?? - [], - ); - } -} - -// 개인 루틴 -class Routine { - final int routineId; - final String routineTitle; - final String routineCategory; - bool isAlarmEnabled; // isAlarmEnabled를 mutable로 변경 - final String startDate; - final List repeatDays; - bool isCompletion; - - Routine( - {required this.routineId, - required this.routineTitle, - required this.routineCategory, - required this.isAlarmEnabled, - required this.startDate, - required this.repeatDays, - this.isCompletion = false}); - - factory Routine.fromJson(Map json) { - return Routine( - routineId: json['routineId'] ?? 0, //기본값 설정 - routineTitle: json['routineTitle'] ?? '', // 한국어로 된 필드명을 사용하여 데이터를 파싱 - routineCategory: json['routineCategory'] ?? '기타', - isAlarmEnabled: json['isAlarmEnabled'] ?? false, - startDate: - json["startDate"] ?? DateFormat('yyyy.MM.dd').format(DateTime.now()), - repeatDays: List.from(json["repeatDays"] ?? []), - isCompletion: json['isCompletion'] ?? false, - ); - } -} - -// 개인 카테고리 그룹 -class UserRoutineCategory { - final String routineCategory; - final List routines; - - UserRoutineCategory({ - required this.routineCategory, - required this.routines, - }); - - factory UserRoutineCategory.fromJson(Map json) { - return UserRoutineCategory( - routineCategory: json['routineCategory'] ?? '', - routines: (json['routines'] as List) - .map((item) => Routine.fromJson(item)) - .toList() ?? - [], ); } } @@ -795,4 +646,4 @@ class Group2 { .toList(), ); } -} +} \ No newline at end of file diff --git a/lib/routine_statistics/StaticsCalendar.dart b/lib/routine_statistics/StaticsCalendar.dart index eaf4542..01e617d 100644 --- a/lib/routine_statistics/StaticsCalendar.dart +++ b/lib/routine_statistics/StaticsCalendar.dart @@ -164,8 +164,7 @@ class _StaticsCalendarState extends State // 더보기 버튼 클릭 시 동작할 코드 Navigator.push( context, - MaterialPageRoute( - builder: (context) => const MyInfo()), + MaterialPageRoute(builder: (context) => const MyInfo()), ); }, child: SizedBox( diff --git a/lib/routine_user/token.dart b/lib/routine_user/token.dart index 537a01f..5704b31 100644 --- a/lib/routine_user/token.dart +++ b/lib/routine_user/token.dart @@ -10,7 +10,7 @@ class TokenManager { // 토큰을 저장하고 전역 변수 업데이트 static Future saveToken(String newToken) async { final prefs = - await SharedPreferences.getInstance(); // SharedPreferences에 저장 + await SharedPreferences.getInstance(); // SharedPreferences에 저장 await prefs.setString('authToken', newToken); token = newToken; // 전역 변수 업데이트 @@ -19,7 +19,7 @@ class TokenManager { // 저장된 토큰을 불러오고 전역 변수 업데이트 static Future getToken() async { final prefs = - await SharedPreferences.getInstance(); // SharedPreferences에서 불러오기 + await SharedPreferences.getInstance(); // SharedPreferences에서 불러오기 String? storedToken = prefs.getString('authToken'); if (storedToken != null) { @@ -32,8 +32,8 @@ class TokenManager { // 토큰을 삭제 static Future clearToken() async { final prefs = - await SharedPreferences.getInstance(); // SharedPreferences에서 삭제 + await SharedPreferences.getInstance(); // SharedPreferences에서 삭제 await prefs.remove('authToken'); token = ''; // 전역 변수 초기화 } -} \ No newline at end of file +} diff --git a/pubspec.lock b/pubspec.lock index a225998..2932bbe 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -149,10 +149,10 @@ packages: dependency: transitive description: name: file - sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" + sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 url: "https://pub.dev" source: hosted - version: "7.0.0" + version: "7.0.1" file_selector_linux: dependency: transitive description: @@ -369,7 +369,7 @@ packages: source: hosted version: "1.4.2" kakao_flutter_sdk_common: - dependency: transitive + dependency: "direct main" description: name: kakao_flutter_sdk_common sha256: "76eccd72a4e94db9c6be69b670477528d958d2bf38f50a2158dfd306640c7abf" @@ -425,7 +425,7 @@ packages: source: hosted version: "1.4.2" kakao_flutter_sdk_user: - dependency: transitive + dependency: "direct main" description: name: kakao_flutter_sdk_user sha256: "168bff0eb2742a352cbf3b64c60dff88deb89d959cf7375ea3e0e8416ab138e4" @@ -436,18 +436,18 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a" + sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05" url: "https://pub.dev" source: hosted - version: "10.0.4" + version: "10.0.5" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8" + sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806" url: "https://pub.dev" source: hosted - version: "3.0.3" + version: "3.0.5" leak_tracker_testing: dependency: transitive description: @@ -476,18 +476,18 @@ packages: dependency: transitive description: name: material_color_utilities - sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec url: "https://pub.dev" source: hosted - version: "0.8.0" + version: "0.11.1" meta: dependency: transitive description: name: meta - sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136" + sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 url: "https://pub.dev" source: hosted - version: "1.12.0" + version: "1.15.0" mime: dependency: "direct main" description: @@ -761,10 +761,10 @@ packages: dependency: transitive description: name: test_api - sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f" + sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb" url: "https://pub.dev" source: hosted - version: "0.7.0" + version: "0.7.2" typed_data: dependency: transitive description: @@ -801,10 +801,10 @@ packages: dependency: "direct main" description: name: url_launcher - sha256: "21b704ce5fa560ea9f3b525b43601c678728ba46725bab9b01187b4831377ed3" + sha256: "9d06212b1362abc2f0f0d78e6f09f726608c74e3b9462e8368bb03314aa8d603" url: "https://pub.dev" source: hosted - version: "6.3.0" + version: "6.3.1" url_launcher_android: dependency: transitive description: @@ -873,10 +873,10 @@ packages: dependency: transitive description: name: vm_service - sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec" + sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d" url: "https://pub.dev" source: hosted - version: "14.2.1" + version: "14.2.5" web: dependency: transitive description: @@ -942,5 +942,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: "3.4.4" + dart: "3.5.3" flutter: ">=3.22.0" diff --git a/pubspec.yaml b/pubspec.yaml index 9fe039a..260441b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -4,7 +4,7 @@ description: "A new Flutter project." version: 1.0.0+1 environment: - sdk: '3.4.4' + sdk: "3.5.3" dependencies: flutter: @@ -14,10 +14,9 @@ dependencies: image: ^3.0.1 permission_handler: ^10.2.0 - #추가한 패키지 + # 추가한 패키지 flutter_calendar_week: ^3.0.1 intl: ^0.18.0 - cupertino_icons: ^1.0.6 json_annotation: ^4.0.1 shelf_swagger_ui: ^1.0.0+2 @@ -27,7 +26,10 @@ dependencies: shared_preferences: ^2.0.8 table_calendar: ^3.0.0 fl_chart: ^0.69.0 - kakao_flutter_sdk: ^1.1.0 #카카오로그인 + kakao_flutter_sdk: ^1.1.0 # 카카오 로그인 + kakao_flutter_sdk_user: ^1.2.0 + kakao_flutter_sdk_common: ^1.0.0 + url_launcher: ^6.0.20 # 카카오 로그인 webview_flutter: ^3.0.4 uni_links: ^0.5.1 @@ -36,9 +38,16 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - flutter_lints: ^3.0.0 +# Flutter Icons 설정 추가 +flutter_icons: + android: true + ios: true + image_path: "assets/images/new-icons/routineade.png" + adaptive_icon_background: "#FFFFFF" # 안드로이드용 Adaptive 아이콘 배경색 + adaptive_icon_foreground: "assets/images/new-icons/RoutineAde.png" # 안드로이드 Adaptive 아이콘 + flutter: uses-material-design: true @@ -53,4 +62,4 @@ fonts: fonts: - asset: assets/fonts/NotoSansKR-Regular.otf - asset: assets/fonts/NotoSansKR-Bold.otf - - asset: assets/fonts/NotoSansKR-Medium.otf \ No newline at end of file + - asset: assets/fonts/NotoSansKR-Medium.otf