diff --git a/assets/images/academy_screen/play_arrow.png b/assets/images/academy_screen/play_arrow.png new file mode 100644 index 0000000..3e9cf1d Binary files /dev/null and b/assets/images/academy_screen/play_arrow.png differ diff --git a/assets/images/portfolio_screen/card_bg.png b/assets/images/portfolio_screen/card_bg.png new file mode 100644 index 0000000..298e0ab Binary files /dev/null and b/assets/images/portfolio_screen/card_bg.png differ diff --git a/lib/core/routes/routes.dart b/lib/core/routes/routes.dart index d4f431e..aee7798 100644 --- a/lib/core/routes/routes.dart +++ b/lib/core/routes/routes.dart @@ -2,8 +2,7 @@ import 'package:go_router/go_router.dart'; import 'package:tanami_app/core/routes/route_name.dart'; -import 'package:tanami_app/features/MainScreens/Academy/presentation/pages/detailsScreen.dart'; -import 'package:tanami_app/features/MainScreens/MainScreen.dart'; +import 'package:tanami_app/features/MainScreens/Academy/presentation/pages/academy_details_screen.dart'; import 'package:tanami_app/features/MainScreens/Portfolio/presentation/pages/portfolio_details_screen.dart'; @@ -17,6 +16,7 @@ import 'package:tanami_app/features/register/presentation/pages/register_step_sc import 'package:tanami_app/features/securePin/presentation/pages/pin_screen.dart'; import 'package:tanami_app/features/welcome/presentation/pages/weclome_screen.dart'; +import '../../features/MainScreens/main_screen.dart'; import '../../features/forgotPassword/presentation/pages/restore_password_phone_verification_screen.dart'; import '../../features/login/presentation/pages/login_screen.dart'; import '../../features/register/presentation/pages/register_user_details_screen.dart'; diff --git a/lib/core/styles/app_color.dart b/lib/core/styles/app_color.dart index 50cf8bb..3f22566 100644 --- a/lib/core/styles/app_color.dart +++ b/lib/core/styles/app_color.dart @@ -58,4 +58,15 @@ class AppColor { static const Color negativePercentageColor = Color(0xFFde9595); static const Color statusTextColor = Color(0xFF0FA4A4); static const Color portoflioCardTextColor = Color(0xFF535353); + static const Color documentCardBgColor = Color(0xFFF4F4F4); + static const Color stausBgColor = Color(0xFF59B7B7); + + //bottom navigation bar + static const Color selectedItemColor = Color(0xFF0B8933); + static const Color unselectedItemColor = Color(0xFF676767); + + //Academy Color + + static const Color academyCardBgColor = Color(0xFFF8F8F8); + static const Color academyCardTextColor = Color(0xFFD8D8D8); } diff --git a/lib/core/styles/app_images.dart b/lib/core/styles/app_images.dart index 4165fde..c6a70fc 100644 --- a/lib/core/styles/app_images.dart +++ b/lib/core/styles/app_images.dart @@ -63,4 +63,17 @@ class AppImages { 'assets/images/portfolio_screen/clock.png'; static const String portfolioClockOff = 'assets/images/portfolio_screen/clock_off.png'; + static const String documentIcon = + 'assets/images/portfolio_screen/document.png'; + static const String donwloadIcon = + 'assets/images/portfolio_screen/download.png'; + static const String portfolioCardBg = + 'assets/images/portfolio_screen/card_bg.png'; + + //Academy + static const String academyCardOverlay = + 'assets/images/academy_screen/dark_overlay.png'; + static const String videoIcon = 'assets/images/academy_screen/video.png'; + static const String videoPlayIcon = + 'assets/images/academy_screen/play_arrow.png'; } diff --git a/lib/core/styles/app_text.dart b/lib/core/styles/app_text.dart index 17fcef8..730d709 100644 --- a/lib/core/styles/app_text.dart +++ b/lib/core/styles/app_text.dart @@ -87,6 +87,7 @@ class AppText { //Academy static const String videosTitle = "Videos"; + static const String academyText = "Academy"; //Dialog static const String exitText = "Exit"; diff --git a/lib/features/MainScreens/Academy/presentation/pages/academyScreen.dart b/lib/features/MainScreens/Academy/presentation/pages/academyScreen.dart deleted file mode 100644 index ad343c5..0000000 --- a/lib/features/MainScreens/Academy/presentation/pages/academyScreen.dart +++ /dev/null @@ -1,239 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:google_fonts/google_fonts.dart'; -import 'package:tanami_app/core/routes/route_name.dart'; -import 'package:tanami_app/core/routes/routes.dart'; - -class AcademyScreen extends StatefulWidget { - const AcademyScreen({super.key}); - - @override - State createState() => _AcademyScreenState(); -} - -class _AcademyScreenState extends State { - List data = [ - { - 'img_path': 'assets/images/academy_screen/bg1.jpg', - 'date': 'July / 10 / 2025', - 'title': 'Article ', - 'videos': '3', - 'desc': - 'Forem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio mattis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur tempus urna at turpis condimentum lobortis.' - }, - { - 'img_path': 'assets/images/academy_screen/bg2.jpg', - 'date': 'July / 10 / 2025', - 'title': 'Article ', - 'videos': '3', - 'desc': - 'Forem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio mattis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur tempus urna at turpis condimentum lobortis.' - }, - { - 'img_path': 'assets/images/academy_screen/bg3.jpg', - 'date': 'July / 10 / 2025', - 'videos': '3', - 'title': 'Article ', - 'desc': - 'Forem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio mattis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur tempus urna at turpis condimentum lobortis.' - }, - { - 'img_path': 'assets/images/academy_screen/bg4.jpg', - 'date': 'July / 10 / 2025', - 'videos': '3', - 'title': 'Article ', - 'desc': - 'Forem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio mattis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur tempus urna at turpis condimentum lobortis.', - }, - { - 'img_path': 'assets/images/academy_screen/bg5.jpg', - 'date': 'July / 10 / 2025', - 'videos': '3', - 'title': 'Article ', - 'desc': - 'Forem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio mattis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur tempus urna at turpis condimentum lobortis.', - }, - { - 'img_path': 'assets/images/academy_screen/bg4.jpg', - 'date': 'July / 10 / 2025', - 'videos': '3', - 'title': 'Article ', - 'desc': - 'Forem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio mattis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur tempus urna at turpis condimentum lobortis.', - }, - { - 'img_path': 'assets/images/academy_screen/bg4.jpg', - 'date': 'July / 10 / 2025', - 'videos': '3', - 'title': 'Article ', - 'desc': - 'Forem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio mattis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur tempus urna at turpis condimentum lobortis.', - }, - { - 'img_path': 'assets/images/academy_screen/bg4.jpg', - 'date': 'July / 10 / 2025', - 'videos': '3', - 'title': 'Article ', - 'desc': - 'Forem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio mattis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur tempus urna at turpis condimentum lobortis.', - }, - ]; - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: Colors.white, - appBar: AppBar( - backgroundColor: Colors.white, - elevation: 0, - scrolledUnderElevation: 0, - automaticallyImplyLeading: false, - title: Text( - 'Academy', - style: GoogleFonts.dmSans( - color: const Color(0xFF272727), - fontSize: 22.sp, - fontWeight: FontWeight.w700, - ), - ), - titleSpacing: 16, - ), - body: ListView.builder( - itemCount: data.length, - itemBuilder: (context, index) { - return Padding( - padding: - const EdgeInsets.symmetric(vertical: 10.0, horizontal: 16.0), - child: GestureDetector( - onTap: () { - goRouter.goNamed(RouteName.academyDetails); - }, - child: Container( - height: 140.h, - width: double.infinity, - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.all(Radius.circular(20.0)), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.15), - spreadRadius: 2, - blurRadius: 10, - offset: Offset(0, 3), // changes position of shadow - ), - ], - ), - child: Row( - children: [ - Container( - height: 140.h, - width: 164.w, - decoration: const BoxDecoration( - color: Color(0xFFF8F8F8), - borderRadius: BorderRadius.all( - Radius.circular(20.0), - ), - ), - child: Stack( - children: [ - ClipRRect( - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(20.0), - bottomLeft: Radius.circular(20.0), - ), - child: Image.asset( - data[index]['img_path'], - fit: BoxFit.cover, - height: double.infinity, - alignment: Alignment.topCenter, - ), - ), - Positioned( - bottom: 0.0, - child: ClipRRect( - borderRadius: const BorderRadius.only( - bottomLeft: Radius.circular(20.0), - ), - child: Image.asset( - 'assets/images/academy_screen/dark_overlay.png', - ), - ), - ), - Positioned( - bottom: 8.0, left: 12.0, - // alignment: Alignment.bottomLeft, - child: Row( - children: [ - Image.asset( - 'assets/images/academy_screen/video.png', - height: 15.sp, - ), - SizedBox( - width: 5.w, - ), - Text( - '${data[index]['videos']} videos', - style: GoogleFonts.dmSans( - color: const Color(0xFFD8D8D8), - fontSize: 12.sp, - fontWeight: FontWeight.w700, - ), - ), - ], - ), - ), - ], - ), - ), - Padding( - padding: const EdgeInsets.symmetric( - vertical: 20.0, horizontal: 16.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - data[index]['date'], - style: GoogleFonts.dmSans( - color: const Color(0xFF8D8D8D), - fontSize: 11.sp, - fontWeight: FontWeight.w500, - ), - ), - SizedBox( - height: 4.h, - ), - Text( - data[index]['title'], - style: GoogleFonts.dmSans( - color: Colors.black, - fontSize: 17.sp, - fontWeight: FontWeight.w700, - ), - ), - SizedBox( - height: 12.h, - ), - SizedBox( - width: 158.w, - child: Text( - data[index]['desc'], - maxLines: 2, - overflow: TextOverflow.ellipsis, - style: GoogleFonts.dmSans( - color: const Color(0xFF8D8D8D), - fontSize: 11.sp, - fontWeight: FontWeight.w500, - ), - ), - ), - ], - ), - ) - ], - ), - ), - ), - ); - }), - ); - } -} diff --git a/lib/features/MainScreens/Academy/presentation/pages/academy_details_layout.dart b/lib/features/MainScreens/Academy/presentation/pages/academy_details_layout.dart new file mode 100644 index 0000000..037152b --- /dev/null +++ b/lib/features/MainScreens/Academy/presentation/pages/academy_details_layout.dart @@ -0,0 +1,27 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:gap/gap.dart'; +import '../widgets/academy_detail_section.dart'; +import '../widgets/academy_video_section.dart'; + +class AcademyDetailsLayout extends StatelessWidget { + const AcademyDetailsLayout({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 20.0), + child: Column( + children: [ + const AcademyDetailSection(), + Gap(12.h), + const AcademyVideoSection(), + ], + ), + ), + ), + ); + } +} diff --git a/lib/features/MainScreens/Academy/presentation/pages/academy_details_screen.dart b/lib/features/MainScreens/Academy/presentation/pages/academy_details_screen.dart new file mode 100644 index 0000000..095bab3 --- /dev/null +++ b/lib/features/MainScreens/Academy/presentation/pages/academy_details_screen.dart @@ -0,0 +1,24 @@ +import 'package:flutter/material.dart'; +import 'package:tanami_app/features/MainScreens/Academy/presentation/pages/academy_details_layout.dart'; + +import '../../../../../shared/components/appbar_widget.dart'; + +class AcademyDetailsScreen extends StatefulWidget { + const AcademyDetailsScreen({super.key}); + + @override + State createState() => _AcademyDetailsScreenState(); +} + +class _AcademyDetailsScreenState extends State { + @override + Widget build(BuildContext context) { + return const Scaffold( + appBar: AppBarWidget( + height: 50, + titleTxt: "Article Name", + ), + body: AcademyDetailsLayout(), + ); + } +} diff --git a/lib/features/MainScreens/Academy/presentation/pages/academy_layout.dart b/lib/features/MainScreens/Academy/presentation/pages/academy_layout.dart new file mode 100644 index 0000000..e5b4a6a --- /dev/null +++ b/lib/features/MainScreens/Academy/presentation/pages/academy_layout.dart @@ -0,0 +1,84 @@ +import 'package:flutter/material.dart'; +import 'package:tanami_app/features/MainScreens/Academy/presentation/widgets/academy_card.dart'; + +class AcademyLayout extends StatelessWidget { + const AcademyLayout({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: ListView.builder( + itemCount: data.length, + itemBuilder: (context, index) { + return academyCard(data[index]); + }), + ); + } +} + +List data = [ + { + 'img_path': 'assets/images/academy_screen/bg1.jpg', + 'date': 'July / 10 / 2025', + 'title': 'Article ', + 'videos': '3', + 'desc': + 'Forem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio mattis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur tempus urna at turpis condimentum lobortis.' + }, + { + 'img_path': 'assets/images/academy_screen/bg2.jpg', + 'date': 'July / 10 / 2025', + 'title': 'Article ', + 'videos': '3', + 'desc': + 'Forem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio mattis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur tempus urna at turpis condimentum lobortis.' + }, + { + 'img_path': 'assets/images/academy_screen/bg3.jpg', + 'date': 'July / 10 / 2025', + 'videos': '3', + 'title': 'Article ', + 'desc': + 'Forem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio mattis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur tempus urna at turpis condimentum lobortis.' + }, + { + 'img_path': 'assets/images/academy_screen/bg4.jpg', + 'date': 'July / 10 / 2025', + 'videos': '3', + 'title': 'Article ', + 'desc': + 'Forem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio mattis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur tempus urna at turpis condimentum lobortis.', + }, + { + 'img_path': 'assets/images/academy_screen/bg5.jpg', + 'date': 'July / 10 / 2025', + 'videos': '3', + 'title': 'Article ', + 'desc': + 'Forem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio mattis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur tempus urna at turpis condimentum lobortis.', + }, + { + 'img_path': 'assets/images/academy_screen/bg4.jpg', + 'date': 'July / 10 / 2025', + 'videos': '3', + 'title': 'Article ', + 'desc': + 'Forem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio mattis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur tempus urna at turpis condimentum lobortis.', + }, + { + 'img_path': 'assets/images/academy_screen/bg4.jpg', + 'date': 'July / 10 / 2025', + 'videos': '3', + 'title': 'Article ', + 'desc': + 'Forem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio mattis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur tempus urna at turpis condimentum lobortis.', + }, + { + 'img_path': 'assets/images/academy_screen/bg4.jpg', + 'date': 'July / 10 / 2025', + 'videos': '3', + 'title': 'Article ', + 'desc': + 'Forem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio mattis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur tempus urna at turpis condimentum lobortis.', + }, +]; diff --git a/lib/features/MainScreens/Academy/presentation/pages/academy_screen.dart b/lib/features/MainScreens/Academy/presentation/pages/academy_screen.dart new file mode 100644 index 0000000..0ea69d6 --- /dev/null +++ b/lib/features/MainScreens/Academy/presentation/pages/academy_screen.dart @@ -0,0 +1,32 @@ +import 'package:flutter/material.dart'; +import 'package:tanami_app/core/styles/app_color.dart'; +import 'package:tanami_app/features/MainScreens/Academy/presentation/pages/academy_layout.dart'; +import 'package:tanami_app/shared/components/text_widget.dart'; + +import '../../../../../core/styles/app_text.dart'; + +class AcademyScreen extends StatefulWidget { + const AcademyScreen({super.key}); + + @override + State createState() => _AcademyScreenState(); +} + +class _AcademyScreenState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + backgroundColor: Colors.white, + elevation: 0, + scrolledUnderElevation: 0, + automaticallyImplyLeading: false, + title: TextWidget().text22W700( + AppText.academyText, + clr: AppColor.charcoalColor, + ), + titleSpacing: 16, + ), + body: const AcademyLayout()); + } +} diff --git a/lib/features/MainScreens/Academy/presentation/pages/detailsScreen.dart b/lib/features/MainScreens/Academy/presentation/pages/detailsScreen.dart deleted file mode 100644 index 92072f8..0000000 --- a/lib/features/MainScreens/Academy/presentation/pages/detailsScreen.dart +++ /dev/null @@ -1,199 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:google_fonts/google_fonts.dart'; -import 'package:tanami_app/core/styles/app_text.dart'; - -class AcademyDetailsScreen extends StatefulWidget { - const AcademyDetailsScreen({super.key}); - - @override - State createState() => _AcademyDetailsScreenState(); -} - -class _AcademyDetailsScreenState extends State { - List videos = [ - 'assets/images/academy_screen/vd_bg.jpg', - 'assets/images/academy_screen/vd_bg.jpg', - 'assets/images/academy_screen/vd_bg.jpg' - ]; - - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: Colors.white, - appBar: AppBar( - elevation: 0, - scrolledUnderElevation: 0.0, - backgroundColor: Colors.white, - centerTitle: true, - title: Text( - 'Article name', - style: GoogleFonts.dmSans( - color: const Color(0xFF272727), // Text color similar to your image - fontSize: 20.sp, - fontWeight: FontWeight.w700, - ), - ), - ), - body: SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 20.0), - child: Column( - children: [ - Container( - decoration: BoxDecoration( - color: Colors.white, - borderRadius: const BorderRadius.all(Radius.circular(20.0)), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.15), - spreadRadius: 2, - blurRadius: 10, - offset: const Offset(0, 3), // changes position of shadow - ), - ], - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Stack( - children: [ - ClipRRect( - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(20.0), - topRight: Radius.circular(20.0), - ), - child: Image.asset( - 'assets/images/academy_screen/bg2.jpg', - fit: BoxFit.cover, - width: double.infinity, - height: 190.h, - alignment: Alignment.center, - ), - ), - Positioned( - bottom: 0.0, - child: Image.asset( - 'assets/images/academy_screen/dark_overlay.png', - ), - ), - Positioned( - bottom: 8.0, - left: 12.0, - child: Row( - children: [ - Image.asset( - 'assets/images/academy_screen/video.png', - height: 15.sp, - ), - SizedBox( - width: 5.w, - ), - Text( - '3 videos', - style: GoogleFonts.dmSans( - color: const Color(0xFFD8D8D8), - fontSize: 12.sp, - fontWeight: FontWeight.w700, - ), - ), - ], - ), - ), - ], - ), - Padding( - padding: const EdgeInsets.symmetric( - horizontal: 16.0, vertical: 20.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Jul / 10 / 2025', - style: GoogleFonts.dmSans( - color: const Color(0xFF8D8D8D), - fontSize: 11.sp, - fontWeight: FontWeight.w500, - ), - ), - SizedBox( - height: 12.h, - ), - Text( - 'Forem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio mattis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur tempus urna at turpis condimentum lobortis.', - style: GoogleFonts.dmSans( - color: Colors.grey, - fontSize: 14.sp, - fontWeight: FontWeight.w400, - ), - ), - ], - ), - ), - ], - ), - ), - SizedBox( - height: 12.h, - ), - Container( - decoration: BoxDecoration( - color: Colors.white, - borderRadius: const BorderRadius.all(Radius.circular(20.0)), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.15), - spreadRadius: 2, - blurRadius: 10, - offset: const Offset(0, 3), // changes position of shadow - ), - ], - ), - child: Padding( - padding: const EdgeInsets.symmetric( - vertical: 20.0, horizontal: 16.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - AppText.videosTitle, - style: GoogleFonts.dmSans( - color: Colors.black, - fontSize: 15.sp, - fontWeight: FontWeight.w700, - ), - ), - SizedBox( - height: 12.h, - ), - ListView.builder( - physics: const NeverScrollableScrollPhysics(), - shrinkWrap: true, - itemCount: videos.length, - itemBuilder: (context, index) { - return Padding( - padding: const EdgeInsets.only(bottom: 18.0), - child: ClipRRect( - borderRadius: const BorderRadius.all( - Radius.circular(18.0), - ), - child: Image.asset( - videos[index], - fit: BoxFit.cover, - height: 160.h, - ), - ), - ); - }, - ) - ], - ), - ), - ), - ], - ), - ), - ), - ); - } -} diff --git a/lib/features/MainScreens/Academy/presentation/widgets/academy_card.dart b/lib/features/MainScreens/Academy/presentation/widgets/academy_card.dart new file mode 100644 index 0000000..a348bcf --- /dev/null +++ b/lib/features/MainScreens/Academy/presentation/widgets/academy_card.dart @@ -0,0 +1,128 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:gap/gap.dart'; +import 'package:tanami_app/core/styles/app_color.dart'; +import 'package:tanami_app/core/styles/app_images.dart'; +import 'package:tanami_app/shared/components/text_widget.dart'; + +import '../../../../../core/routes/route_name.dart'; +import '../../../../../core/routes/routes.dart'; + +Widget academyCard(dynamic data) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 10.0, horizontal: 16.0), + child: GestureDetector( + onTap: () { + goRouter.pushNamed(RouteName.academyDetails); + }, + child: Container( + height: 140.h, + width: double.infinity, + decoration: BoxDecoration( + color: AppColor.plainWhite, + borderRadius: const BorderRadius.all(Radius.circular(20.0)), + boxShadow: [ + BoxShadow( + color: AppColor.plainBlack.withOpacity(0.15), + spreadRadius: 2, + blurRadius: 10, + offset: const Offset(0, 3), // changes position of shadow + ), + ], + ), + child: Row( + children: [ + Container( + height: 140.h, + width: 164.w, + decoration: const BoxDecoration( + color: AppColor.academyCardBgColor, + borderRadius: BorderRadius.all( + Radius.circular(20.0), + ), + ), + child: Stack( + children: [ + ClipRRect( + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(20.0), + bottomLeft: Radius.circular(20.0), + ), + child: Image.asset( + data['img_path'], + fit: BoxFit.cover, + height: double.infinity, + alignment: Alignment.topCenter, + ), + ), + Positioned( + bottom: 0.0, + child: ClipRRect( + borderRadius: const BorderRadius.only( + bottomLeft: Radius.circular(20.0), + ), + child: Image.asset( + AppImages.academyCardOverlay, + ), + ), + ), + Positioned( + bottom: 8.0, left: 12.0, + // alignment: Alignment.bottomLeft, + child: Row( + children: [ + Image.asset( + AppImages.videoIcon, + height: 15.sp, + ), + Gap( + 5.w, + ), + TextWidget().text12W700( + '${data['videos']} videos', + clr: AppColor.academyCardTextColor, + ), + ], + ), + ), + ], + ), + ), + Padding( + padding: + const EdgeInsets.symmetric(vertical: 20.0, horizontal: 16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + TextWidget().text13W500( + data['date'], + clr: AppColor.academyCardTextColor, + ), + Gap( + 4.h, + ), + TextWidget().text17W600( + data['title'], + clr: AppColor.plainBlack, + ), + Gap( + 12.h, + ), + SizedBox( + width: 158.w, + child: TextWidget().text14W400( + data['desc'], + maxLine: 2, + txtAlign: TextAlign.start, + clr: AppColor.academyCardTextColor, + ), + ), + ], + ), + ) + ], + ), + ), + ), + ); +} diff --git a/lib/features/MainScreens/Academy/presentation/widgets/academy_detail_section.dart b/lib/features/MainScreens/Academy/presentation/widgets/academy_detail_section.dart new file mode 100644 index 0000000..7b3818a --- /dev/null +++ b/lib/features/MainScreens/Academy/presentation/widgets/academy_detail_section.dart @@ -0,0 +1,92 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:gap/gap.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:tanami_app/core/styles/app_color.dart'; +import 'package:tanami_app/core/styles/app_images.dart'; +import 'package:tanami_app/core/styles/app_text.dart'; +import 'package:tanami_app/shared/components/text_widget.dart'; + +class AcademyDetailSection extends StatelessWidget { + const AcademyDetailSection({super.key}); + + @override + Widget build(BuildContext context) { + return Container( + decoration: BoxDecoration( + color: AppColor.plainWhite, + borderRadius: const BorderRadius.all(Radius.circular(20.0)), + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.15), + spreadRadius: 2, + blurRadius: 10, + offset: const Offset(0, 3), // changes position of shadow + ), + ], + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Stack( + children: [ + ClipRRect( + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(20.0), + topRight: Radius.circular(20.0), + ), + child: Image.asset( + 'assets/images/academy_screen/bg2.jpg', + fit: BoxFit.cover, + width: double.infinity, + height: 190.h, + alignment: Alignment.center, + ), + ), + Positioned( + bottom: 0.0, + child: Image.asset( + AppImages.academyCardOverlay, + ), + ), + Positioned( + bottom: 8.0, + left: 12.0, + child: Row( + children: [ + Image.asset( + AppImages.videoIcon, + height: 15.sp, + ), + Gap(5.w), + TextWidget().text12W700( + '3 ${AppText.videosTitle}', + clr: AppColor.academyCardTextColor, + ), + ], + ), + ), + ], + ), + Padding( + padding: + const EdgeInsets.symmetric(horizontal: 16.0, vertical: 20.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + TextWidget() + .text11W500('Jul / 10 / 2025', clr: AppColor.hintTextColor), + Gap(12.h), + TextWidget().text14W400( + 'Forem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio mattis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur tempus urna at turpis condimentum lobortis.', + clr: Colors.grey, + txtAlign: TextAlign.start, + ) + ], + ), + ), + ], + ), + ); + } +} diff --git a/lib/features/MainScreens/Academy/presentation/widgets/academy_video_section.dart b/lib/features/MainScreens/Academy/presentation/widgets/academy_video_section.dart new file mode 100644 index 0000000..b0f6842 --- /dev/null +++ b/lib/features/MainScreens/Academy/presentation/widgets/academy_video_section.dart @@ -0,0 +1,89 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:tanami_app/core/styles/app_images.dart'; + +import '../../../../../core/styles/app_text.dart'; + +class AcademyVideoSection extends StatelessWidget { + const AcademyVideoSection({super.key}); + + @override + Widget build(BuildContext context) { + return Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: const BorderRadius.all(Radius.circular(20.0)), + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.15), + spreadRadius: 2, + blurRadius: 10, + offset: const Offset(0, 3), // changes position of shadow + ), + ], + ), + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 20.0, horizontal: 16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + AppText.videosTitle, + style: GoogleFonts.dmSans( + color: Colors.black, + fontSize: 15.sp, + fontWeight: FontWeight.w700, + ), + ), + SizedBox( + height: 12.h, + ), + ListView.builder( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemCount: videos.length, + itemBuilder: (context, index) { + return Padding( + padding: const EdgeInsets.only(bottom: 18.0), + child: ClipRRect( + borderRadius: const BorderRadius.all( + Radius.circular(18.0), + ), + child: Stack( + children: [ + Image.asset( + videos[index], + fit: BoxFit.cover, + height: 160.h, + width: 1.sw, + ), + Positioned( + bottom: 0.0, + child: Image.asset( + AppImages.academyCardOverlay, + ), + ), + Positioned.fill( + child: Image.asset( + AppImages.videoPlayIcon, + ), + ) + ], + ), + ), + ); + }, + ) + ], + ), + ), + ); + } +} + +List videos = [ + 'assets/images/academy_screen/vd_bg.jpg', + 'assets/images/academy_screen/vd_bg.jpg', + 'assets/images/academy_screen/vd_bg.jpg' +]; diff --git a/lib/features/MainScreens/Portfolio/presentation/bloc/carousel/carousel_bloc.dart b/lib/features/MainScreens/Portfolio/presentation/bloc/carousel/carousel_bloc.dart new file mode 100644 index 0000000..3ce32ca --- /dev/null +++ b/lib/features/MainScreens/Portfolio/presentation/bloc/carousel/carousel_bloc.dart @@ -0,0 +1,12 @@ +import 'package:flutter_bloc/flutter_bloc.dart'; + +import 'carousel_event.dart'; +import 'carousel_state.dart'; + +class CarouselBloc extends Bloc { + CarouselBloc() : super(CarouselInitial()) { + on((event, emit) { + emit(CarouselPageState(event.index)); + }); + } +} diff --git a/lib/features/MainScreens/Portfolio/presentation/bloc/carousel/carousel_event.dart b/lib/features/MainScreens/Portfolio/presentation/bloc/carousel/carousel_event.dart new file mode 100644 index 0000000..02bf28e --- /dev/null +++ b/lib/features/MainScreens/Portfolio/presentation/bloc/carousel/carousel_event.dart @@ -0,0 +1,7 @@ +abstract class CarouselEvent {} + +class PageChanged extends CarouselEvent { + final int index; + + PageChanged(this.index); +} diff --git a/lib/features/MainScreens/Portfolio/presentation/bloc/carousel/carousel_state.dart b/lib/features/MainScreens/Portfolio/presentation/bloc/carousel/carousel_state.dart new file mode 100644 index 0000000..85b6936 --- /dev/null +++ b/lib/features/MainScreens/Portfolio/presentation/bloc/carousel/carousel_state.dart @@ -0,0 +1,9 @@ +abstract class CarouselState {} + +class CarouselInitial extends CarouselState {} + +class CarouselPageState extends CarouselState { + final int currentIndex; + + CarouselPageState(this.currentIndex); +} diff --git a/lib/features/MainScreens/Portfolio/presentation/pages/portfolioScreen.dart b/lib/features/MainScreens/Portfolio/presentation/pages/portfolioScreen.dart deleted file mode 100644 index 3f2aebb..0000000 --- a/lib/features/MainScreens/Portfolio/presentation/pages/portfolioScreen.dart +++ /dev/null @@ -1,342 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:google_fonts/google_fonts.dart'; -import 'package:tanami_app/core/routes/route_name.dart'; -import 'package:tanami_app/core/routes/routes.dart'; -import 'package:tanami_app/core/styles/app_text.dart'; - -class PortfolioScreen extends StatefulWidget { - const PortfolioScreen({super.key}); - - @override - State createState() => _PortfolioScreenState(); -} - -class _PortfolioScreenState extends State { - @override - Widget build(BuildContext context) { - return Scaffold( - backgroundColor: Colors.white, - body: CustomScrollView( - slivers: [ - SliverAppBar( - elevation: 0, - scrolledUnderElevation: 0, - expandedHeight: 230.0, - automaticallyImplyLeading: false, - snap: false, - pinned: true, - floating: false, - flexibleSpace: LayoutBuilder( - builder: (BuildContext context, BoxConstraints constraints) { - var top = constraints.biggest.height; - var percentage = - ((top - kToolbarHeight) / (200.0 - kToolbarHeight)) - .clamp(0.0, 1.0); - var opacity = (1 - percentage).clamp(0.0, 1.0); - return FlexibleSpaceBar( - // centerTitle: true, - titlePadding: - const EdgeInsets.only(left: 30, top: 0, bottom: 15), - title: Opacity( - opacity: opacity, - child: Row( - children: [ - Text( - AppText.portfolio, - style: GoogleFonts.dmSans( - color: const Color(0xFF888888), - fontSize: 12.sp, - fontWeight: FontWeight.w700, - ), - ), - Text( - 'SAR 178,000', - style: GoogleFonts.dmSans( - color: Colors.black, - fontSize: 14.sp, - fontWeight: FontWeight.w700, - ), - ), - ], - ), - ), - background: Stack( - fit: StackFit.expand, - children: [ - Image.asset( - 'assets/images/portfolio_screen/bg.png', // Replace with your image asset - fit: BoxFit.cover, - ), - Padding( - padding: const EdgeInsets.only(left: 40.0), - child: Opacity( - opacity: percentage, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - AppText.portfolio, - style: GoogleFonts.dmSans( - color: const Color(0xFFC9D9CB), - fontSize: 14.sp, - fontWeight: FontWeight.w700, - ), - ), - SizedBox( - height: 8.h, - ), - Text( - 'SAR 178,000', - style: GoogleFonts.dmSans( - color: Colors.white, - fontSize: 28.sp, - fontWeight: FontWeight.w700, - ), - ), - ], - ), - ), - ), - ], - ), - ); - }), - backgroundColor: Colors.white, - ), - SliverList( - delegate: SliverChildBuilderDelegate( - (context, index) => Padding( - padding: const EdgeInsets.all(10.0), - child: GestureDetector( - onTap: () { - goRouter.pushNamed(RouteName.porfolioDetails); - }, - child: Container( - decoration: BoxDecoration( - color: Colors.white, - - borderRadius: const BorderRadius.all(Radius.circular(20.0)), - - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.15), - spreadRadius: 2, - blurRadius: 10, - offset: - const Offset(0, 3), // changes position of shadow - ), - ], - ), - child: Column( - children: [ - Padding( - padding: const EdgeInsets.symmetric( - horizontal: 20.0, vertical: 16.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Image.asset( - (index == 2) - ? 'assets/images/portfolio_screen/clock_off.png' - : 'assets/images/portfolio_screen/clock.png', - height: 25.sp, - ), - SizedBox( - width: 5.w, - ), - Text( - 'Mar 01 2024', - style: GoogleFonts.dmSans( - color: const Color(0xFF004717), - fontSize: 12.sp, - fontWeight: FontWeight.w500, - ), - ), - ], - ), - Text( - (index == 2) ? 'Exited' : 'Pending', - style: GoogleFonts.dmSans( - color: (index == 2) - ? const Color(0xFF8D8D8D) - : const Color(0xFF0FA4A4), - fontSize: 14.sp, - fontWeight: FontWeight.w700, - ), - ) - ], - ), - SizedBox( - height: 8.h, - ), - Text( - (index == 2) - ? 'Real Estate III' - : 'Private equity portfolio I', - style: GoogleFonts.dmSans( - color: Colors.black, - fontSize: 17.sp, - fontWeight: FontWeight.w700, - ), - ), - ], - ), - ), - Container( - decoration: const BoxDecoration( - color: Color(0xFFF8F8F8), - borderRadius: BorderRadius.only( - bottomLeft: Radius.circular(20.0), - bottomRight: Radius.circular(20.0), - ), - ), - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 20.0, vertical: 16.0), - child: Column( - children: [ - Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - AppText.investmentamount, - style: GoogleFonts.dmSans( - color: (index == 2) - ? const Color(0xFF8D8D8D) - : const Color(0xFF535353), - fontSize: 14.sp, - fontWeight: FontWeight.w500, - ), - ), - Column( - crossAxisAlignment: - CrossAxisAlignment.end, - children: [ - Text( - 'SAR 100,000', - style: GoogleFonts.dmSans( - color: (index == 2) - ? const Color(0xFF8D8D8D) - : Colors.black, - fontSize: 14.sp, - fontWeight: FontWeight.w700, - ), - ), - Text( - ' \$ 26,700', - style: GoogleFonts.dmSans( - color: (index == 2) - ? const Color(0xFF8D8D8D) - : Colors.black, - fontSize: 11.sp, - fontWeight: FontWeight.w400, - ), - ), - ], - ) - ], - ), - SizedBox( - height: 8.h, - ), - Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - AppText.currentval, - style: GoogleFonts.dmSans( - color: (index == 2) - ? const Color(0xFF8D8D8D) - : const Color(0xFF535353), - fontSize: 14.sp, - fontWeight: FontWeight.w500, - ), - ), - Column( - crossAxisAlignment: - CrossAxisAlignment.end, - children: [ - Text( - 'SAR 100,000', - style: GoogleFonts.dmSans( - color: (index == 2) - ? const Color(0xFF8D8D8D) - : Colors.black, - fontSize: 14.sp, - fontWeight: FontWeight.w700, - ), - ), - Text( - ' \$ 26,700', - style: GoogleFonts.dmSans( - color: (index == 2) - ? const Color(0xFF8D8D8D) - : Colors.black, - fontSize: 11.sp, - fontWeight: FontWeight.w400, - ), - ), - ], - ) - ], - ), - SizedBox( - height: 8.h, - ), - Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - AppText.totalreturn, - style: GoogleFonts.dmSans( - color: (index == 2) - ? const Color(0xFF8D8D8D) - : const Color(0xFF535353), - fontSize: 14.sp, - fontWeight: FontWeight.w500, - ), - ), - Text( - (index == 2) ? '- 20.0%' : '+ 20.0%', - style: GoogleFonts.dmSans( - color: (index == 2) - ? const Color(0xFFde9595) - : const Color(0xFF066123), - fontSize: 14.sp, - fontWeight: FontWeight.w700, - ), - ) - ], - ) - ], - ), - ), - ) - ], - ), - ), - ), - ), - childCount: 3, - ), //SliverChildBuildDelegate - ), - ], - ), - ); - } -} diff --git a/lib/features/MainScreens/Portfolio/presentation/pages/portfolio_details_layout.dart b/lib/features/MainScreens/Portfolio/presentation/pages/portfolio_details_layout.dart index e69de29..664df9f 100644 --- a/lib/features/MainScreens/Portfolio/presentation/pages/portfolio_details_layout.dart +++ b/lib/features/MainScreens/Portfolio/presentation/pages/portfolio_details_layout.dart @@ -0,0 +1,49 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:gap/gap.dart'; +import 'package:tanami_app/core/styles/app_color.dart'; + +import '../widgets/details_section.dart'; +import '../widgets/included_documents_section.dart'; +import '../widgets/portfolio_image_carousel.dart'; + +class PortfolioDetailsLayout extends StatelessWidget { + const PortfolioDetailsLayout({super.key}); + + @override + Widget build(BuildContext context) { + return SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 20.0), + child: Column( + children: [ + Container( + decoration: BoxDecoration( + color: AppColor.plainWhite, + borderRadius: const BorderRadius.all(Radius.circular(20.0)), + boxShadow: [ + BoxShadow( + color: AppColor.plainBlack.withOpacity(0.15), + spreadRadius: 2, + blurRadius: 10, + offset: const Offset(0, 3), + ), + ], + ), + child: Column( + children: [ + CarouselView(), + const DetailsSection(), + ], + ), + ), + Gap( + 20.h, + ), + const IncludedDocumentsSection(), + ], + ), + ), + ); + } +} diff --git a/lib/features/MainScreens/Portfolio/presentation/pages/portfolio_details_screen.dart b/lib/features/MainScreens/Portfolio/presentation/pages/portfolio_details_screen.dart index db54ad3..4edd012 100644 --- a/lib/features/MainScreens/Portfolio/presentation/pages/portfolio_details_screen.dart +++ b/lib/features/MainScreens/Portfolio/presentation/pages/portfolio_details_screen.dart @@ -1,477 +1,28 @@ -import 'package:carousel_slider/carousel_slider.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:google_fonts/google_fonts.dart'; -import 'package:tanami_app/core/styles/app_text.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:tanami_app/features/MainScreens/Portfolio/presentation/pages/portfolio_details_layout.dart'; -class DetailsScreen extends StatefulWidget { +import '../../../../../shared/components/appbar_widget.dart'; +import '../bloc/carousel/carousel_bloc.dart'; + +class DetailsScreen extends StatelessWidget { const DetailsScreen({super.key}); - @override - State createState() => _DetailsScreenState(); -} - -class _DetailsScreenState extends State { - int _current = 0; - final CarouselController _controller = CarouselController(); - final List imgList = [ - {'id': 1, 'img_path': 'assets/images/portfolio_screen/detailsbg.png'}, - {'id': 2, 'img_path': 'assets/images/portfolio_screen/detailsbg.png'}, - {'id': 3, 'img_path': 'assets/images/portfolio_screen/detailsbg.png'}, - {'id': 4, 'img_path': 'assets/images/portfolio_screen/detailsbg.png'}, - {'id': 5, 'img_path': 'assets/images/portfolio_screen/detailsbg.png'}, - ]; - @override Widget build(BuildContext context) { return Scaffold( - backgroundColor: Colors.white, - appBar: AppBar( - backgroundColor: Colors.white, - ), - body: SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 20.0), - child: Column( - children: [ - Container( - decoration: BoxDecoration( - color: Colors.white, - borderRadius: const BorderRadius.all(Radius.circular(20.0)), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.15), - spreadRadius: 2, - blurRadius: 10, - offset: const Offset(0, 3), // changes position of shadow - ), - ], - ), - child: Column( - children: [ - Container( - height: 190.h, - decoration: const BoxDecoration( - color: Color(0xFFF8F8F8), - borderRadius: BorderRadius.only( - topLeft: Radius.circular(20.0), - topRight: Radius.circular(20.0), - ), - ), - child: Stack( - children: [ - ClipRRect( - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(20.0), - topRight: Radius.circular(20.0), - ), - child: CarouselSlider( - items: imgList - .map( - (item) => Image.asset( - item['img_path'], - fit: BoxFit.cover, - width: double.infinity, - alignment: Alignment.topCenter, - ), - ) - .toList(), - carouselController: _controller, - options: CarouselOptions( - scrollPhysics: const BouncingScrollPhysics(), - autoPlay: true, - aspectRatio: 2, - viewportFraction: 1, - onPageChanged: (index, reason) { - setState(() { - _current = index; - }); - }), - ), - ), - Align( - alignment: Alignment.bottomCenter, - child: Padding( - padding: const EdgeInsets.only(bottom: 17.0), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: - imgList.asMap().entries.map((entry) { - return GestureDetector( - onTap: () => - _controller.animateToPage(entry.key), - child: Container( - width: 20.w, - height: 7.h, - margin: const EdgeInsets.symmetric( - horizontal: 3.0), - decoration: BoxDecoration( - borderRadius: - BorderRadius.circular(10), - color: (_current == entry.key) - ? Colors.white - : Colors.grey, - ), - ), - ); - }).toList(), - ), - )), - Positioned( - top: 20, - left: 20, - child: Container( - padding: const EdgeInsets.symmetric( - horizontal: 15.0, vertical: 10.0), - decoration: BoxDecoration( - color: const Color( - 0xFFE4F5E9), // Background color similar to your image - borderRadius: BorderRadius.circular( - 30.0), // Large border radius for rounded corners - ), - child: Text( - 'Asset Class', - style: GoogleFonts.dmSans( - color: const Color( - 0xFF0B8933), // Text color similar to your image - fontSize: 12.sp, - fontWeight: FontWeight.w700, - ), - ), - ), - ), - Positioned( - top: 20, - right: 20, - child: Container( - padding: const EdgeInsets.symmetric( - horizontal: 15.0, vertical: 10.0), - decoration: BoxDecoration( - color: Colors - .white, // Background color similar to your image - borderRadius: BorderRadius.circular( - 30.0), // Large border radius for rounded corners - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Image.asset( - 'assets/images/portfolio_screen/clock.png', - height: 15.h, - ), - SizedBox( - width: 5.w, - ), - Text( - 'Jul 10 2025', - style: GoogleFonts.dmSans( - color: Colors - .black, // Text color similar to your image - fontSize: 12.sp, - fontWeight: FontWeight.w500, - ), - ), - ], - ), - ), - ) - ], - ), - ), - Container( - color: Colors.white, - child: Padding( - padding: const EdgeInsets.all(20.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Multi Family Residental', - style: GoogleFonts.dmSans( - color: Colors.black, - fontSize: 17.sp, - fontWeight: FontWeight.w700, - ), - ), - SizedBox( - height: 10.h, - ), - Text( - 'Forem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio mattis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur tempus urna at turpis condimentum lobortis.', - style: GoogleFonts.dmSans( - color: Colors.grey, - fontSize: 14.sp, - fontWeight: FontWeight.w400, - ), - ), - ], - ), - ), - ), - Container( - decoration: const BoxDecoration( - color: Color(0xFFF8F8F8), - borderRadius: BorderRadius.only( - bottomLeft: Radius.circular(20.0), - bottomRight: Radius.circular(20.0), - ), - ), - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 20.0, vertical: 16.0), - child: Column( - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox( - width: 150.w, - child: Text( - AppText.investmentamount, - style: GoogleFonts.dmSans( - color: const Color(0xFF535353), - fontSize: 14.sp, - fontWeight: FontWeight.w500, - ), - ), - ), - Column( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Text( - 'SAR 100,000', - style: GoogleFonts.dmSans( - color: Colors.black, - fontSize: 14.sp, - fontWeight: FontWeight.w700, - ), - ), - Text( - ' \$ 26,700', - style: GoogleFonts.dmSans( - color: Colors.black, - fontSize: 11.sp, - fontWeight: FontWeight.w400, - ), - ), - ], - ) - ], - ), - SizedBox( - height: 8.h, - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox( - width: 150.w, - child: Text( - AppText.currentval, - style: GoogleFonts.dmSans( - color: const Color(0xFF535353), - fontSize: 14.sp, - fontWeight: FontWeight.w500, - ), - ), - ), - Column( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Text( - 'SAR 100,000', - style: GoogleFonts.dmSans( - color: Colors.black, - fontSize: 14.sp, - fontWeight: FontWeight.w700, - ), - ), - Text( - ' \$ 26,700', - style: GoogleFonts.dmSans( - color: Colors.black, - fontSize: 11.sp, - fontWeight: FontWeight.w400, - ), - ), - ], - ) - ], - ), - SizedBox( - height: 8.h, - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox( - width: 150.w, - child: Text( - AppText.disttodate, - style: GoogleFonts.dmSans( - color: const Color(0xFF535353), - fontSize: 14.sp, - fontWeight: FontWeight.w500, - ), - ), - ), - Text( - '20.0%', - style: GoogleFonts.dmSans( - color: Colors.black, - fontSize: 14.sp, - fontWeight: FontWeight.w700, - ), - ) - ], - ), - SizedBox( - height: 8.h, - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - AppText.totalreturn, - style: GoogleFonts.dmSans( - color: const Color(0xFF535353), - fontSize: 14.sp, - fontWeight: FontWeight.w500, - ), - ), - Text( - '+ 20.0%', - style: GoogleFonts.dmSans( - color: const Color(0xFF066123), - fontSize: 14.sp, - fontWeight: FontWeight.w700, - ), - ) - ], - ) - ], - ), - ), - ) - ], - ), - ), - SizedBox( - height: 20.h, - ), - Container( - width: double.infinity, - decoration: BoxDecoration( - color: Colors.white, - borderRadius: const BorderRadius.all(Radius.circular(20.0)), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.15), - spreadRadius: 2, - blurRadius: 10, - offset: const Offset(0, 3), // changes position of shadow - ), - ], - ), - child: Padding( - padding: const EdgeInsets.all(20.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - AppText.includeddocs, - style: GoogleFonts.dmSans( - color: Colors.black, - fontSize: 15.sp, - fontWeight: FontWeight.w700, - ), - ), - SizedBox( - height: 16.h, - ), - GridView.count( - shrinkWrap: true, - childAspectRatio: 1.7, - mainAxisSpacing: 10.h, - crossAxisSpacing: 10.w, - crossAxisCount: 2, // Number of columns - children: List.generate( - 6, - (index) { - return Center( - child: Container( - decoration: const BoxDecoration( - color: Color(0xFFF4F4F4), - borderRadius: - BorderRadius.all(Radius.circular(10.0)), - ), - padding: const EdgeInsets.all(20.0), - child: Column( - children: [ - Row( - children: [ - Image.asset( - 'assets/images/portfolio_screen/document.png', - height: 16.sp, - ), - SizedBox( - width: 7.w, - ), - Text( - "Filename.pdf", - style: GoogleFonts.dmSans( - color: Colors.black, - fontSize: 12.sp, - fontWeight: FontWeight.w700, - ), - ), - ], - ), - SizedBox( - height: 14.h, - ), - Row( - crossAxisAlignment: - CrossAxisAlignment.end, - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Text( - "512 Mb", - style: GoogleFonts.dmSans( - color: const Color(0xFF535353), - fontSize: 12.sp, - fontWeight: FontWeight.w700, - ), - ), - SizedBox( - width: 7.w, - ), - Image.asset( - 'assets/images/portfolio_screen/download.png', - height: 20.sp, - ), - ], - ), - ], - ), - ), - ); - }, - ), - ) - ], - ), - ), - ), - ], - ), + appBar: const AppBarWidget( + height: 45, + titleTxt: "", ), - ), - ); + body: MultiBlocProvider( + providers: [ + BlocProvider( + // Create an instance of the OnboardingBloc + create: (context) => CarouselBloc(), + ), + ], + child: const PortfolioDetailsLayout(), + )); } } diff --git a/lib/features/MainScreens/Portfolio/presentation/pages/portfolio_layout.dart b/lib/features/MainScreens/Portfolio/presentation/pages/portfolio_layout.dart index 9fdd72d..454c470 100644 --- a/lib/features/MainScreens/Portfolio/presentation/pages/portfolio_layout.dart +++ b/lib/features/MainScreens/Portfolio/presentation/pages/portfolio_layout.dart @@ -12,7 +12,7 @@ import '../../../../../core/styles/app_text.dart'; class PortfolioLayout extends StatelessWidget { const PortfolioLayout({super.key}); -//2339.712 - 2326.866 + @override Widget build(BuildContext context) { return Scaffold( diff --git a/lib/features/MainScreens/Portfolio/presentation/pages/portfolio_screen.dart b/lib/features/MainScreens/Portfolio/presentation/pages/portfolio_screen.dart index bd8c978..08aae14 100644 --- a/lib/features/MainScreens/Portfolio/presentation/pages/portfolio_screen.dart +++ b/lib/features/MainScreens/Portfolio/presentation/pages/portfolio_screen.dart @@ -1,14 +1,10 @@ import 'package:flutter/material.dart'; -import 'package:tanami_app/features/MainScreens/Portfolio/presentation/pages/portfolio_layout.dart'; -class PortfolioScreen extends StatefulWidget { +import 'portfolio_layout.dart'; + +class PortfolioScreen extends StatelessWidget { const PortfolioScreen({super.key}); - @override - State createState() => _PortfolioScreenState(); -} - -class _PortfolioScreenState extends State { @override Widget build(BuildContext context) { return const Scaffold(body: PortfolioLayout()); diff --git a/lib/features/MainScreens/Portfolio/presentation/widgets/details_section.dart b/lib/features/MainScreens/Portfolio/presentation/widgets/details_section.dart new file mode 100644 index 0000000..b6dfbd4 --- /dev/null +++ b/lib/features/MainScreens/Portfolio/presentation/widgets/details_section.dart @@ -0,0 +1,158 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:gap/gap.dart'; +import 'package:tanami_app/core/styles/app_color.dart'; +import '../../../../../core/styles/app_text.dart'; +import '../../../../../shared/components/text_widget.dart'; + +class DetailsSection extends StatelessWidget { + const DetailsSection({super.key}); + + @override + Widget build(BuildContext context) { + return Column( + children: [ + Container( + color: AppColor.plainWhite, + child: Padding( + padding: const EdgeInsets.all(20.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + TextWidget().text17W700( + 'Multi Family Residental', + clr: AppColor.plainBlack, + ), + Gap( + 10.h, + ), + TextWidget().text14W400( + 'Forem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio mattis. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur tempus urna at turpis condimentum lobortis.', + clr: Colors.grey, + txtAlign: TextAlign.start, + ) + ], + ), + ), + ), + Container( + decoration: const BoxDecoration( + color: AppColor.portfolioCardBgColor, + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular(20.0), + bottomRight: Radius.circular(20.0), + ), + ), + child: Padding( + padding: + const EdgeInsets.symmetric(horizontal: 20.0, vertical: 16.0), + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + width: 150.w, + child: TextWidget().text14W500( + AppText.investmentamount, + clr: AppColor.portoflioCardTextColor, + txtAlign: TextAlign.start, + ), + ), + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + TextWidget().text14W700( + 'SAR 100,000', + clr: AppColor.plainBlack, + txtAlign: TextAlign.end, + ), + TextWidget().text11W400( + ' \$ 26,700', + clr: AppColor.plainBlack, + ), + ], + ) + ], + ), + SizedBox( + height: 8.h, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + width: 150.w, + child: TextWidget().text14W500( + AppText.currentval, + clr: AppColor.portoflioCardTextColor, + txtAlign: TextAlign.start, + ), + ), + Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + TextWidget().text14W700( + 'SAR 100,000', + clr: AppColor.plainBlack, + txtAlign: TextAlign.end, + ), + TextWidget().text11W400( + ' \$ 26,700', + clr: AppColor.plainBlack, + ), + ], + ) + ], + ), + SizedBox( + height: 8.h, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + width: 150.w, + child: TextWidget().text14W500( + AppText.disttodate, + clr: AppColor.portoflioCardTextColor, + txtAlign: TextAlign.start, + ), + ), + TextWidget().text14W700( + '20.0%', + clr: AppColor.plainBlack, + txtAlign: TextAlign.end, + ), + ], + ), + SizedBox( + height: 8.h, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + TextWidget().text14W500( + AppText.totalreturn, + clr: AppColor.portoflioCardTextColor, + txtAlign: TextAlign.start, + ), + TextWidget().text14W700( + '+ 20.0%', + clr: AppColor.selectedItemColor, + txtAlign: TextAlign.end, + ), + ], + ) + ], + ), + ), + ) + ], + ); + } +} diff --git a/lib/features/MainScreens/Portfolio/presentation/widgets/exited_card.dart b/lib/features/MainScreens/Portfolio/presentation/widgets/exited_card.dart index 638d3f1..959d77c 100644 --- a/lib/features/MainScreens/Portfolio/presentation/widgets/exited_card.dart +++ b/lib/features/MainScreens/Portfolio/presentation/widgets/exited_card.dart @@ -65,9 +65,19 @@ class ExitedCard extends StatelessWidget { ), ], ), - TextWidget().text14W700( - portfolioModel.status, - clr: AppColor.hintTextColor, + Container( + padding: const EdgeInsets.symmetric( + horizontal: 15, + vertical: 3, + ), + decoration: BoxDecoration( + color: AppColor.appBarIconColor, + borderRadius: BorderRadius.circular(15), + ), + child: TextWidget().text14W700( + portfolioModel.status, + clr: AppColor.plainWhite, + ), ), ], ), @@ -82,8 +92,11 @@ class ExitedCard extends StatelessWidget { ), ), Container( + width: 1.sw, decoration: const BoxDecoration( - color: AppColor.portfolioCardBgColor, + image: DecorationImage( + image: AssetImage(AppImages.portfolioCardBg), + fit: BoxFit.cover), borderRadius: BorderRadius.only( bottomLeft: Radius.circular(20.0), bottomRight: Radius.circular(20.0), @@ -100,18 +113,18 @@ class ExitedCard extends StatelessWidget { children: [ TextWidget().text14W500( AppText.investmentamount, - clr: AppColor.hintTextColor, + clr: AppColor.portoflioCardTextColor, ), Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ TextWidget().text14W700( portfolioModel.investmentAmountSAR, - clr: AppColor.hintTextColor, + clr: AppColor.plainBlack, ), TextWidget().text11W400( '\$ ${portfolioModel.investmentAmountUSD}', - clr: AppColor.hintTextColor, + clr: AppColor.plainBlack, ), ], ) @@ -126,18 +139,18 @@ class ExitedCard extends StatelessWidget { children: [ TextWidget().text14W500( AppText.currentval, - clr: AppColor.hintTextColor, + clr: AppColor.portoflioCardTextColor, ), Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ TextWidget().text14W700( portfolioModel.currentValuationSAR, - clr: AppColor.hintTextColor, + clr: AppColor.plainBlack, ), TextWidget().text11W400( '\$ ${portfolioModel.currentValuationUSD}', - clr: AppColor.hintTextColor, + clr: AppColor.plainBlack, ), ], ) @@ -152,11 +165,11 @@ class ExitedCard extends StatelessWidget { children: [ TextWidget().text14W500( AppText.totalreturn, - clr: AppColor.hintTextColor, + clr: AppColor.portoflioCardTextColor, ), TextWidget().text14W700( '- ${portfolioModel.totalReturnPercentage}', - clr: AppColor.negativePercentageColor, + clr: AppColor.txtErrorColor, ), ], ) diff --git a/lib/features/MainScreens/Portfolio/presentation/widgets/included_documents_section.dart b/lib/features/MainScreens/Portfolio/presentation/widgets/included_documents_section.dart new file mode 100644 index 0000000..e1fd7f6 --- /dev/null +++ b/lib/features/MainScreens/Portfolio/presentation/widgets/included_documents_section.dart @@ -0,0 +1,103 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:gap/gap.dart'; +import 'package:tanami_app/core/styles/app_color.dart'; +import 'package:tanami_app/core/styles/app_images.dart'; +import 'package:tanami_app/shared/components/text_widget.dart'; + +import '../../../../../core/styles/app_text.dart'; + +class IncludedDocumentsSection extends StatelessWidget { + const IncludedDocumentsSection({super.key}); + + @override + Widget build(BuildContext context) { + return Container( + width: double.infinity, + decoration: BoxDecoration( + color: AppColor.plainWhite, + borderRadius: const BorderRadius.all(Radius.circular(20.0)), + boxShadow: [ + BoxShadow( + color: AppColor.plainBlack.withOpacity(0.15), + spreadRadius: 2, + blurRadius: 10, + offset: const Offset(0, 3), // changes position of shadow + ), + ], + ), + child: Padding( + padding: const EdgeInsets.all(20.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + TextWidget().text15W700( + AppText.includeddocs, + clr: AppColor.plainBlack, + ), + Gap( + 16.h, + ), + GridView.count( + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + childAspectRatio: 1.7, + mainAxisSpacing: 10.h, + crossAxisSpacing: 10.w, + crossAxisCount: 2, // Number of columns + children: List.generate( + 6, + (index) { + return Center( + child: Container( + decoration: const BoxDecoration( + color: AppColor.documentCardBgColor, + borderRadius: BorderRadius.all(Radius.circular(10.0)), + ), + padding: const EdgeInsets.all(20.0), + child: Column( + children: [ + Row( + children: [ + Image.asset( + AppImages.documentIcon, + height: 16.sp, + ), + Gap( + 7.w, + ), + TextWidget().text12W700("Filename.pdf", + clr: AppColor.plainBlack), + ], + ), + Gap( + 14.h, + ), + Row( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + TextWidget().text12W700("512 Mb", + clr: AppColor.portoflioCardTextColor), + Gap( + 7.w, + ), + Image.asset( + AppImages.donwloadIcon, + height: 20.sp, + ), + ], + ), + ], + ), + ), + ); + }, + ), + ) + ], + ), + ), + ); + } +} diff --git a/lib/features/MainScreens/Portfolio/presentation/widgets/pending_card.dart b/lib/features/MainScreens/Portfolio/presentation/widgets/pending_card.dart index 6ee14dd..a053349 100644 --- a/lib/features/MainScreens/Portfolio/presentation/widgets/pending_card.dart +++ b/lib/features/MainScreens/Portfolio/presentation/widgets/pending_card.dart @@ -65,9 +65,19 @@ class PendingCard extends StatelessWidget { ), ], ), - TextWidget().text14W700( - portfolioModel.status, - clr: AppColor.statusTextColor, + Container( + padding: const EdgeInsets.symmetric( + horizontal: 15, + vertical: 3, + ), + decoration: BoxDecoration( + color: AppColor.stausBgColor, + borderRadius: BorderRadius.circular(15), + ), + child: TextWidget().text14W700( + portfolioModel.status, + clr: AppColor.plainWhite, + ), ), ], ), @@ -82,8 +92,11 @@ class PendingCard extends StatelessWidget { ), ), Container( + width: 1.sw, decoration: const BoxDecoration( - color: AppColor.portfolioCardBgColor, + image: DecorationImage( + image: AssetImage(AppImages.portfolioCardBg), + fit: BoxFit.cover), borderRadius: BorderRadius.only( bottomLeft: Radius.circular(20.0), bottomRight: Radius.circular(20.0), @@ -111,7 +124,7 @@ class PendingCard extends StatelessWidget { ), TextWidget().text11W400( ' \$ ${portfolioModel.investmentAmountUSD}', - clr: Colors.black, + clr: AppColor.plainBlack, ), ], ) diff --git a/lib/features/MainScreens/Portfolio/presentation/widgets/portfolio_image_carousel.dart b/lib/features/MainScreens/Portfolio/presentation/widgets/portfolio_image_carousel.dart new file mode 100644 index 0000000..146fdcc --- /dev/null +++ b/lib/features/MainScreens/Portfolio/presentation/widgets/portfolio_image_carousel.dart @@ -0,0 +1,148 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:carousel_slider/carousel_slider.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:gap/gap.dart'; +import 'package:tanami_app/core/styles/app_color.dart'; +import 'package:tanami_app/core/styles/app_images.dart'; +import 'package:tanami_app/shared/components/text_widget.dart'; + +import '../bloc/carousel/carousel_bloc.dart'; +import '../bloc/carousel/carousel_event.dart'; +import '../bloc/carousel/carousel_state.dart'; + +final List imgList = [ + {'id': 1, 'img_path': 'assets/images/portfolio_screen/detailsbg.png'}, + {'id': 2, 'img_path': 'assets/images/portfolio_screen/detailsbg.png'}, + {'id': 3, 'img_path': 'assets/images/portfolio_screen/detailsbg.png'}, + {'id': 4, 'img_path': 'assets/images/portfolio_screen/detailsbg.png'}, + {'id': 5, 'img_path': 'assets/images/portfolio_screen/detailsbg.png'}, +]; + +class CarouselView extends StatelessWidget { + final CarouselController _controller = CarouselController(); + + CarouselView({super.key}); + + @override + Widget build(BuildContext context) { + return Container( + height: 190.h, + decoration: const BoxDecoration( + color: AppColor.portfolioCardBgColor, + borderRadius: BorderRadius.only( + topLeft: Radius.circular(20.0), + topRight: Radius.circular(20.0), + ), + ), + child: Stack( + children: [ + ClipRRect( + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(20.0), + topRight: Radius.circular(20.0), + ), + child: CarouselSlider( + items: imgList + .map( + (item) => Image.asset( + item['img_path'], + fit: BoxFit.cover, + width: double.infinity, + alignment: Alignment.topCenter, + ), + ) + .toList(), + carouselController: _controller, + options: CarouselOptions( + scrollPhysics: const BouncingScrollPhysics(), + autoPlay: true, + aspectRatio: 2, + viewportFraction: 1, + onPageChanged: (index, reason) { + context.read().add(PageChanged(index)); + }), + ), + ), + Align( + alignment: Alignment.bottomCenter, + child: Padding( + padding: const EdgeInsets.only(bottom: 17.0), + child: BlocBuilder( + builder: (context, state) { + int currentIndex = 0; + if (state is CarouselPageState) { + currentIndex = state.currentIndex; + } + return Row( + mainAxisAlignment: MainAxisAlignment.center, + children: imgList.asMap().entries.map((entry) { + return GestureDetector( + onTap: () => _controller.animateToPage(entry.key), + child: Container( + width: 20.w, + height: 7.h, + margin: const EdgeInsets.symmetric(horizontal: 3.0), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: (currentIndex == entry.key) + ? AppColor.plainWhite + : AppColor.smokeGrayColor, + ), + ), + ); + }).toList(), + ); + }, + ), + ), + ), + Positioned( + top: 20, + left: 20, + child: Container( + padding: + const EdgeInsets.symmetric(horizontal: 15.0, vertical: 10.0), + decoration: BoxDecoration( + color: const Color(0xFFE4F5E9), + borderRadius: BorderRadius.circular(30.0), + ), + child: TextWidget().text12W700( + 'Asset Class', + clr: AppColor.selectedItemColor, + ), + ), + ), + Positioned( + top: 20, + right: 20, + child: Container( + padding: + const EdgeInsets.symmetric(horizontal: 15.0, vertical: 10.0), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(30.0), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Image.asset( + AppImages.portfolioClock, + height: 15.h, + ), + Gap( + 5.w, + ), + TextWidget().text12W500( + 'Jul 10 2025', + clr: AppColor.plainBlack, + ), + ], + ), + ), + ) + ], + ), + ); + } +} diff --git a/lib/features/MainScreens/MainScreen.dart b/lib/features/MainScreens/main_screen.dart similarity index 55% rename from lib/features/MainScreens/MainScreen.dart rename to lib/features/MainScreens/main_screen.dart index 50e94db..75432c9 100644 --- a/lib/features/MainScreens/MainScreen.dart +++ b/lib/features/MainScreens/main_screen.dart @@ -1,11 +1,14 @@ import 'package:flutter/material.dart'; -import 'package:tanami_app/features/MainScreens/Academy/presentation/pages/academyScreen.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:tanami_app/features/MainScreens/Academy/presentation/pages/academy_screen.dart'; import 'package:tanami_app/features/MainScreens/Invest/presentation/pages/investScreen.dart'; import 'package:tanami_app/features/MainScreens/Portfolio/presentation/pages/portfolio_screen.dart'; import 'package:tanami_app/features/MainScreens/Settings/presentation/pages/settingsScreen.dart'; import 'package:tanami_app/features/MainScreens/Wallet/presentation/pages/walletScreen.dart'; import 'package:tanami_app/shared/components/common_bottom_navigation.dart'; +import '../../shared/components/bloc/bottom_nav_bar/bottom_navigation_bloc.dart'; +import '../../shared/components/bloc/bottom_nav_bar/bottom_navigation_state.dart'; import '../../shared/components/exit_app_dialog.dart'; var currentTab = [ @@ -18,24 +21,25 @@ var currentTab = [ var selectedIndex = 1; -void updateTab(int index) { - selectedIndex = index; -} - class MainScreen extends StatelessWidget { const MainScreen({super.key}); @override Widget build(BuildContext context) { - return WillPopScope( - onWillPop: () async { - exitAppDialog(context); - return false; + return BlocBuilder( + builder: (context, state) { + int selectedIndex = (state as TabState).selectedIndex; + return WillPopScope( + onWillPop: () async { + exitAppDialog(context); + return false; + }, + child: Scaffold( + backgroundColor: Colors.white, + body: currentTab[selectedIndex], + bottomNavigationBar: bottomnavigationbar(context, selectedIndex), + ), + ); }, - child: Scaffold( - backgroundColor: Colors.white, - body: currentTab[selectedIndex], - bottomNavigationBar: bottomnavigationbar(selectedIndex), - ), ); } } diff --git a/lib/main.dart b/lib/main.dart index 4d4555d..71504dc 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -6,6 +6,7 @@ import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'core/routes/routes.dart'; import 'core/utils/connectivity/network_connectivity.dart'; import 'features/countrySelection/presentation/bloc/choose_country_bloc.dart'; +import 'shared/components/bloc/bottom_nav_bar/bottom_navigation_bloc.dart'; /* CREATED BY - JAYESH JAIN DATE - 24-05-2024 @@ -54,9 +55,9 @@ class _MyAppState extends State with WidgetsBindingObserver { BlocProvider( create: (context) => RadioBloc(), ), - // BlocProvider( - // create: (context) => PasswordVisibilityBloc(), - // ), + BlocProvider( + create: (_) => BottomNavigationBloc(), + ) ], child: ScreenUtilInit( builder: (BuildContext context, Widget? child) => MaterialApp.router( diff --git a/lib/shared/components/appbar_widget.dart b/lib/shared/components/appbar_widget.dart index 62eb1d7..b2a3669 100644 --- a/lib/shared/components/appbar_widget.dart +++ b/lib/shared/components/appbar_widget.dart @@ -9,16 +9,18 @@ import 'package:tanami_app/shared/components/text_widget.dart'; class AppBarWidget extends StatelessWidget implements PreferredSizeWidget { @override Size get preferredSize => Size.fromHeight(height!); - const AppBarWidget( - {super.key, - required this.titleTxt, - this.suffixIcon, - this.showLeading = true, - this.customBack, - this.backPageName = '', - this.customActionWidget, - this.onCustomActionPressed, - this.height = 105}); + const AppBarWidget({ + super.key, + required this.titleTxt, + this.suffixIcon, + this.showLeading = true, + this.customBack, + this.backPageName = '', + this.customActionWidget, + this.onCustomActionPressed, + this.height = 10, + this.centerTitle, + }); final String titleTxt; final String? suffixIcon; @@ -28,6 +30,7 @@ class AppBarWidget extends StatelessWidget implements PreferredSizeWidget { final Widget? customActionWidget; final VoidCallback? onCustomActionPressed; final double? height; + final bool? centerTitle; @override Widget build(BuildContext context) { return PreferredSize( @@ -35,11 +38,11 @@ class AppBarWidget extends StatelessWidget implements PreferredSizeWidget { child: AppBar( scrolledUnderElevation: 0.0, elevation: 0, - centerTitle: true, + centerTitle: centerTitle ?? true, title: TextWidget().text20W700(titleTxt, clr: AppColor.charcoalColor), leading: Padding( padding: EdgeInsets.only( - left: 16.w, + left: !showLeading! ? 0 : 16.w, ), child: !showLeading! ? null diff --git a/lib/shared/components/bloc/bottom_nav_bar/bottom_navigation_bloc.dart b/lib/shared/components/bloc/bottom_nav_bar/bottom_navigation_bloc.dart new file mode 100644 index 0000000..11c404f --- /dev/null +++ b/lib/shared/components/bloc/bottom_nav_bar/bottom_navigation_bloc.dart @@ -0,0 +1,15 @@ +import 'package:bloc/bloc.dart'; + +import 'bottom_navigation_event.dart'; +import 'bottom_navigation_state.dart'; + +// Bloc +class BottomNavigationBloc + extends Bloc { + BottomNavigationBloc() : super(TabState(0)) { + // Register the event handler + on((event, emit) { + emit(TabState(event.index)); + }); + } +} diff --git a/lib/shared/components/bloc/bottom_nav_bar/bottom_navigation_event.dart b/lib/shared/components/bloc/bottom_nav_bar/bottom_navigation_event.dart new file mode 100644 index 0000000..9bcce26 --- /dev/null +++ b/lib/shared/components/bloc/bottom_nav_bar/bottom_navigation_event.dart @@ -0,0 +1,7 @@ +abstract class BottomNavigationEvent {} + +class TabChanged extends BottomNavigationEvent { + final int index; + + TabChanged(this.index); +} diff --git a/lib/shared/components/bloc/bottom_nav_bar/bottom_navigation_state.dart b/lib/shared/components/bloc/bottom_nav_bar/bottom_navigation_state.dart new file mode 100644 index 0000000..6e8fb38 --- /dev/null +++ b/lib/shared/components/bloc/bottom_nav_bar/bottom_navigation_state.dart @@ -0,0 +1,7 @@ +abstract class BottomNavigationState {} + +class TabState extends BottomNavigationState { + final int selectedIndex; + + TabState(this.selectedIndex); +} diff --git a/lib/shared/components/common_bottom_navigation.dart b/lib/shared/components/common_bottom_navigation.dart index 2e6d7f0..6c0845a 100644 --- a/lib/shared/components/common_bottom_navigation.dart +++ b/lib/shared/components/common_bottom_navigation.dart @@ -1,28 +1,31 @@ import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; -import 'package:tanami_app/features/MainScreens/MainScreen.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:tanami_app/core/styles/app_color.dart'; -Widget bottomnavigationbar(selectedIndex) { +import 'bloc/bottom_nav_bar/bottom_navigation_bloc.dart'; +import 'bloc/bottom_nav_bar/bottom_navigation_event.dart'; + +Widget bottomnavigationbar(BuildContext context, selectedIndex) { return BottomNavigationBar( type: BottomNavigationBarType.fixed, showUnselectedLabels: true, - selectedItemColor: Color(0xFF0B8933), - unselectedItemColor: const Color(0xFF676767), - unselectedLabelStyle: TextStyle( + selectedItemColor: AppColor.selectedItemColor, + unselectedItemColor: AppColor.unselectedItemColor, + unselectedLabelStyle: GoogleFonts.dmSans( fontSize: 10.sp, - color: const Color(0xFF676767), + color: AppColor.unselectedItemColor, fontWeight: FontWeight.w400, - fontFamily: 'hiragino', ), - selectedLabelStyle: TextStyle( + selectedLabelStyle: GoogleFonts.dmSans( fontSize: 10.sp, - color: const Color(0xFF0B8933), + color: AppColor.selectedItemColor, fontWeight: FontWeight.w400, - fontFamily: 'hiragino', ), currentIndex: selectedIndex, onTap: (index) { - updateTab(index); + context.read().add(TabChanged(index)); }, items: [ BottomNavigationBarItem( @@ -62,8 +65,6 @@ Widget bottomnavigationbar(selectedIndex) { height: 28.h, width: 28.w, ), - - // SvgPicture.asset('assets/image/svg/active_shortTrade.svg'), label: 'Invest', ), BottomNavigationBarItem( diff --git a/lib/shared/components/text_widget.dart b/lib/shared/components/text_widget.dart index 80dbd91..d364cdf 100644 --- a/lib/shared/components/text_widget.dart +++ b/lib/shared/components/text_widget.dart @@ -12,6 +12,14 @@ class TextWidget { color: clr ?? AppColor.plainWhite)); } + Widget text11W500(String text, {Color? clr}) { + return Text(text, + style: GoogleFonts.dmSans( + fontSize: 11, + fontWeight: FontWeight.w500, + color: clr ?? AppColor.plainWhite)); + } + //Text Size 12 Widget text12W400(String text, {Color? clr}) { return Text(text, @@ -36,16 +44,29 @@ class TextWidget { fontWeight: FontWeight.w700, color: clr ?? AppColor.plainWhite)); } - //Text Size 14 +//Text Size 13 + Widget text13W500(String text, {Color? clr}) { + return Text(text, + style: GoogleFonts.dmSans( + fontSize: 13, + fontWeight: FontWeight.w500, + color: clr ?? AppColor.plainWhite)); + } + + //Text Size 14 Widget text14W400( String text, { Color? clr, TextDecoration? textDecoration, TextAlign? txtAlign, + int? maxLine, + TextOverflow? txtOverflow, }) { return Text(text, textAlign: txtAlign ?? TextAlign.center, + maxLines: maxLine ?? 20, + overflow: txtOverflow ?? TextOverflow.ellipsis, style: GoogleFonts.dmSans( fontSize: 14, fontWeight: FontWeight.w400, @@ -80,20 +101,6 @@ class TextWidget { } //Text Size 15 - Widget text15W500( - String text, { - Color? clr, - TextDecoration? textDecoration, - }) { - return Text(text, - textAlign: TextAlign.center, - style: GoogleFonts.dmSans( - fontSize: 15, - decorationColor: AppColor.hintTextColor, - decoration: textDecoration ?? TextDecoration.none, - fontWeight: FontWeight.w500, - color: clr ?? AppColor.plainWhite)); - } Widget text15W400( String text, { @@ -111,7 +118,53 @@ class TextWidget { color: clr ?? AppColor.plainWhite)); } + Widget text15W500( + String text, { + Color? clr, + TextDecoration? textDecoration, + }) { + return Text(text, + textAlign: TextAlign.center, + style: GoogleFonts.dmSans( + fontSize: 15, + decorationColor: AppColor.hintTextColor, + decoration: textDecoration ?? TextDecoration.none, + fontWeight: FontWeight.w500, + color: clr ?? AppColor.plainWhite)); + } + + Widget text15W700( + String text, { + Color? clr, + TextDecoration? textDecoration, + }) { + return Text(text, + textAlign: TextAlign.center, + style: GoogleFonts.dmSans( + fontSize: 15, + decorationColor: AppColor.hintTextColor, + decoration: textDecoration ?? TextDecoration.none, + fontWeight: FontWeight.w700, + color: clr ?? AppColor.plainWhite)); + } + //Text Size 17 + + Widget text17W600( + String text, { + Color? clr, + TextDecoration? textDecoration, + }) { + return Text(text, + textAlign: TextAlign.center, + style: GoogleFonts.dmSans( + fontSize: 17, + decorationColor: AppColor.hintTextColor, + decoration: textDecoration ?? TextDecoration.none, + fontWeight: FontWeight.w600, + color: clr ?? AppColor.plainWhite)); + } + Widget text17W700( String text, { Color? clr,