From 80f4ab4ac14438087e7e2c07b897d42d7e19d642 Mon Sep 17 00:00:00 2001 From: Erfan Rahmati Date: Sat, 13 Aug 2022 04:39:54 +0430 Subject: [PATCH] Add profile section --- assets/images/no_picture.png | Bin 0 -> 2468 bytes lib/constants/types.dart | 2 + lib/main.dart | 3 + lib/models/hive/convertor.dart | 4 + .../fields/show_preview_fields.dart | 25 +- lib/models/hive/models/show_preview.dart | 2 + lib/models/hive/models/show_preview.g.dart | 51 +++-- lib/models/show_models/full_show_model.dart | 4 +- .../show_models/show_preview_model.dart | 3 + .../preferences/preferences_shareholder.dart | 3 + lib/pages/main/profile/profile.dart | 5 +- .../main/profile/profile_controller.dart | 101 +++++++++ .../list_page/sections/stats_page/stats.dart | 2 +- .../user_profile/edit_user_profile.dart | 58 +++++ .../sections/user_profile/user_profile.dart | 213 ++++++++++++++++++ lib/pages/splash/get_Initial_data.dart | 3 +- lib/pages/splash/get_user_data.dart | 203 +++++++++++++++++ lib/pages/splash/splash_screen.dart | 2 + lib/widgets/buttons/glassmorphism_button.dart | 57 ++--- lib/widgets/textfield_widget.dart | 68 ++++++ pubspec.yaml | 2 +- 21 files changed, 742 insertions(+), 69 deletions(-) create mode 100644 assets/images/no_picture.png create mode 100644 lib/pages/main/profile/profile_controller.dart create mode 100644 lib/pages/main/profile/sections/user_profile/edit_user_profile.dart create mode 100644 lib/pages/main/profile/sections/user_profile/user_profile.dart create mode 100644 lib/pages/splash/get_user_data.dart create mode 100644 lib/widgets/textfield_widget.dart diff --git a/assets/images/no_picture.png b/assets/images/no_picture.png new file mode 100644 index 0000000000000000000000000000000000000000..8880a921c158a32a0f01ff8c0ba7ebf3a82731e3 GIT binary patch literal 2468 zcmb7`1zQse14cI#*pL`-sR>93BH_rGoF%INC|!O@76 zu#J=!VRU@npYT1;d*1UG4(7hGE(0Bu4gdf!=<8{j{x$hOKz|Q#eJbGt001`9*V06W z&TQrQ`p)XG^xhZ}cTBAp5W!qg{LSX^MD`b3`_82tBdy(nM#9Tn2y2?e^E7R}-l0FX zeH^&|G9P0)`R(w)#p1TtzF019)Qr{({1~5BEA;C9q@uZjWEz-Qs0ywe8^5E3DCewql;qZ$$N=KBc?i<7WB-Ult^c4 zaqi_VcK2-X114 zd!XCOO~Mw_eQCrPJ8)ayvv}pQUgUIyn$-Gr+x=XGCa#0$@?wy!pdhQ<52J0DMNKl zjDD=hDkj8x-QbtnEDB1s*XRN(p@?Ur0VqO?Tw8K2YUM|hlF%?7;jU1hOj7eZe;BFgVl*F>RDEAC39Ol2-xoDvhrcYyWt@Z3B77jj#iQ zt)6h-0idhh{WZ?!i}jYkv5ZcCJBsj!W z0UJI6SsAOwjBp{PO|D#g;6=~|R&oIe4yx#@`=UwrkMemDfY%d-j_+-~(ZdfgL2YR| z$B-6WCcM*v*mTRnC}Ol`hd@uMEb}0;vOK~r#LUi+j#FMPrup@sx~sGA zu2(dj{xK`nM?Wov1u`$&{H)3uda7PFG~KsmP)$(^pPeTLQy|MuQ;p|GfQ7u)M~hL4 zqvblO;GE-T-w6PP+jdvELq@#zLGRNEW0i^QlL}- zs&QG{=Hd{zws#gcYXmaMdgUFXYw2T#iejyGN5O?QRBei+lkmAC&z{_8}|g!z}+u5%NkMTn&(3IH6<+KcCr*L;jY+< zuisoN^QO}PdCU$P@wrTSmg3}blkQXL&2Q7u@59szb-7uxl?@bE?J;fv00oXtrZZl2 z;?J+LXNi#=s7V^t8w_)&zpa9S_Vjr^6}q3*Led^4n*ldp{z^JtG}A@_>;^pg3bi_g z&4E;-xX9r1dg|L54{1StM1yBkB36m)9OhIj;yVO^G%=lN%lqYiO6ADAAwJEI5bvE3 zCApuiGfc#g-ijt1B`5F_Swq&CGLP=ErE(=?p~ivcd2ySKR`>do4EOJNG~<3e@(v#W zwF*v6E_TD*?9T4-i4K2I*e_x$&}#qviQ-Zeo1cPaRPUNNE`3ZuJ12G=AN}Yk6*-r2 zoKyWl+tW-mG^k$c6HBK1=-FluDCac2zeoujV0bNY=9-7X-1m_mmv9!?HQ`p6mfrN6 z2TlE}C^T+PZwno1?hCn-S+jK)un z0ZTo`<6?zmBS8SL%GVHt&tF|&m&u^sH4T|Xd8~Yi#X~7=q{NI*QWal8hm$dt1b(#m*0CRXKV8_7zK@w&maH>nNG{yF2>? bIt04=`T(TRmYX~O<(Iy;vDQa~{fqwr(&4KU literal 0 HcmV?d00001 diff --git a/lib/constants/types.dart b/lib/constants/types.dart index 5f84d04..9f1e501 100644 --- a/lib/constants/types.dart +++ b/lib/constants/types.dart @@ -20,3 +20,5 @@ enum ListName { FAVORITE_TRAILERS, PERSONAL_LIST } + +enum ItemType { MOVIE, TV, ARTIST, OTHER, UNKNOWN } diff --git a/lib/main.dart b/lib/main.dart index 1e8aebb..43f99fd 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -3,6 +3,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:get/get.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:hive_flutter/adapters.dart'; +import 'package:movielab/pages/main/profile/profile_controller.dart'; import 'constants/colors.dart'; import 'constants/routes.dart'; import 'models/hive/hive_helper/register_adapters.dart'; @@ -29,6 +30,7 @@ void main() async { Get.put(MainController()); Get.put(HomeDataController()); Get.put(SearchBarController()); + Get.put(ProfileController()); Get.put(CacheData()); runApp(const ProviderScope(child: App())); @@ -43,6 +45,7 @@ class App extends StatelessWidget { title: 'MovieLab', debugShowCheckedModeBanner: false, theme: ThemeData( + backgroundColor: kBackgroundColor, primaryColor: kPrimaryColor, textTheme: GoogleFonts.ubuntuTextTheme( Theme.of(context).textTheme, diff --git a/lib/models/hive/convertor.dart b/lib/models/hive/convertor.dart index cbb3586..b4d13bc 100644 --- a/lib/models/hive/convertor.dart +++ b/lib/models/hive/convertor.dart @@ -8,6 +8,7 @@ ShowPreview convertHiveToShowPreview(HiveShowPreview hive) { id: hive.id, rank: hive.rank, title: hive.title, + type: hive.type, crew: hive.crew, image: hive.image, year: hive.year, @@ -46,6 +47,7 @@ HiveShowPreview convertShowPreviewToHive( ..id = showPreview.id ..rank = showPreview.rank ..title = showPreview.title + ..type = showPreview.type ..crew = showPreview.crew ..image = showPreview.image ..year = showPreview.year @@ -84,6 +86,7 @@ Future convertFullShowToHive( ..id = fullShow.id ..rank = rank ..title = fullShow.title + ..type = fullShow.type ..crew = crew ..image = fullShow.image ..year = fullShow.year @@ -118,6 +121,7 @@ Future convertFullShowToShowPreview( return ShowPreview( id: fullShow.id, title: fullShow.title, + type: fullShow.type, crew: crew, image: fullShow.image, year: fullShow.year, diff --git a/lib/models/hive/hive_helper/fields/show_preview_fields.dart b/lib/models/hive/hive_helper/fields/show_preview_fields.dart index da22dac..114385d 100644 --- a/lib/models/hive/hive_helper/fields/show_preview_fields.dart +++ b/lib/models/hive/hive_helper/fields/show_preview_fields.dart @@ -2,16 +2,17 @@ class ShowPreviewFields { static const int id = 0; static const int rank = 1; static const int title = 2; - static const int crew = 3; - static const int image = 4; - static const int year = 5; - static const int imDbRating = 6; - static const int genres = 7; - static const int countries = 8; - static const int languages = 9; - static const int companies = 10; - static const int contentRating = 11; - static const int similars = 12; - static const int watchDate = 13; - static const int watchTime = 14; + static const int type = 3; + static const int crew = 4; + static const int image = 5; + static const int year = 6; + static const int imDbRating = 7; + static const int genres = 8; + static const int countries = 9; + static const int languages = 10; + static const int companies = 11; + static const int contentRating = 12; + static const int similars = 13; + static const int watchDate = 14; + static const int watchTime = 15; } diff --git a/lib/models/hive/models/show_preview.dart b/lib/models/hive/models/show_preview.dart index cd740b9..14d8a18 100644 --- a/lib/models/hive/models/show_preview.dart +++ b/lib/models/hive/models/show_preview.dart @@ -14,6 +14,8 @@ class HiveShowPreview extends HiveObject { late String rank; @HiveField(ShowPreviewFields.title) late String title; + @HiveField(ShowPreviewFields.type) + late String type; @HiveField(ShowPreviewFields.crew) late String crew; @HiveField(ShowPreviewFields.image) diff --git a/lib/models/hive/models/show_preview.g.dart b/lib/models/hive/models/show_preview.g.dart index c66aab6..57057f8 100644 --- a/lib/models/hive/models/show_preview.g.dart +++ b/lib/models/hive/models/show_preview.g.dart @@ -20,24 +20,25 @@ class HiveShowPreviewAdapter extends TypeAdapter { ..id = fields[0] as String ..rank = fields[1] as String ..title = fields[2] as String - ..crew = fields[3] as String - ..image = fields[4] as String - ..year = fields[5] as String - ..imDbRating = fields[6] as String - ..genres = fields[7] as String - ..countries = fields[8] as String - ..languages = fields[9] as String - ..companies = fields[10] as String - ..contentRating = fields[11] as String - ..similars = (fields[12] as List).cast() - ..watchDate = fields[13] as DateTime? - ..watchTime = fields[14] as TimeOfDay?; + ..type = fields[3] as String + ..crew = fields[4] as String + ..image = fields[5] as String + ..year = fields[6] as String + ..imDbRating = fields[7] as String + ..genres = fields[8] as String + ..countries = fields[9] as String + ..languages = fields[10] as String + ..companies = fields[11] as String + ..contentRating = fields[12] as String + ..similars = (fields[13] as List).cast() + ..watchDate = fields[14] as DateTime? + ..watchTime = fields[15] as TimeOfDay?; } @override void write(BinaryWriter writer, HiveShowPreview obj) { writer - ..writeByte(15) + ..writeByte(16) ..writeByte(0) ..write(obj.id) ..writeByte(1) @@ -45,28 +46,30 @@ class HiveShowPreviewAdapter extends TypeAdapter { ..writeByte(2) ..write(obj.title) ..writeByte(3) - ..write(obj.crew) + ..write(obj.type) ..writeByte(4) - ..write(obj.image) + ..write(obj.crew) ..writeByte(5) - ..write(obj.year) + ..write(obj.image) ..writeByte(6) - ..write(obj.imDbRating) + ..write(obj.year) ..writeByte(7) - ..write(obj.genres) + ..write(obj.imDbRating) ..writeByte(8) - ..write(obj.countries) + ..write(obj.genres) ..writeByte(9) - ..write(obj.languages) + ..write(obj.countries) ..writeByte(10) - ..write(obj.companies) + ..write(obj.languages) ..writeByte(11) - ..write(obj.contentRating) + ..write(obj.companies) ..writeByte(12) - ..write(obj.similars) + ..write(obj.contentRating) ..writeByte(13) - ..write(obj.watchDate) + ..write(obj.similars) ..writeByte(14) + ..write(obj.watchDate) + ..writeByte(15) ..write(obj.watchTime); } diff --git a/lib/models/show_models/full_show_model.dart b/lib/models/show_models/full_show_model.dart index 9d613a2..ef508fe 100644 --- a/lib/models/show_models/full_show_model.dart +++ b/lib/models/show_models/full_show_model.dart @@ -1,4 +1,4 @@ -import '../actor_models/actor_preview_model.dart'; +import 'package:movielab/models/actor_models/actor_preview_model.dart'; import 'show_preview_model.dart'; // Movie or TV show all detail model class @@ -91,7 +91,7 @@ class FullShow { return FullShow( id: json['id'], title: json['title'] ?? "", - type: json['type'] ?? "", + type: json['type'] ?? json['role'] ?? "", image: json['image'].toString().replaceAll( "._V1_UX128_CR0,3,128,176_AL_.jpg", "._V1_Ratio0.6716_AL_.jpg"), images: ImageData.getImages(json['images']) ?? [], diff --git a/lib/models/show_models/show_preview_model.dart b/lib/models/show_models/show_preview_model.dart index 3e25fcf..e004ae2 100644 --- a/lib/models/show_models/show_preview_model.dart +++ b/lib/models/show_models/show_preview_model.dart @@ -6,6 +6,7 @@ class ShowPreview { final String id; final String rank; final String title; + final String type; final String crew; final String image; final String year; @@ -31,6 +32,7 @@ class ShowPreview { required this.id, required this.rank, required this.title, + required this.type, required this.crew, required this.image, required this.year, @@ -58,6 +60,7 @@ class ShowPreview { id: json['id'], rank: json['rank'] ?? "", title: json['title'], + type: json['type'] ?? json['role'] ?? "", crew: json['crew'] ?? json['stars'] ?? "", image: json['image'].toString().replaceAll( "._V1_UX128_CR0,3,128,176_AL_.jpg", "._V1_Ratio0.6716_AL_.jpg"), diff --git a/lib/modules/preferences/preferences_shareholder.dart b/lib/modules/preferences/preferences_shareholder.dart index 9b30762..5033415 100644 --- a/lib/modules/preferences/preferences_shareholder.dart +++ b/lib/modules/preferences/preferences_shareholder.dart @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; import 'package:hive_flutter/adapters.dart'; import 'package:movielab/models/show_models/show_preview_model.dart'; import 'package:movielab/modules/Recommender/Recommender.dart'; +import 'package:movielab/pages/splash/get_user_data.dart'; import '../../models/hive/convertor.dart'; import '../../models/hive/models/show_preview.dart'; @@ -45,6 +46,7 @@ class PreferencesShareholder { print("The item added to $listName"); } recommender(); + updateUserStats(); return true; } @@ -62,6 +64,7 @@ class PreferencesShareholder { } } recommender(); + updateUserStats(); return false; } diff --git a/lib/pages/main/profile/profile.dart b/lib/pages/main/profile/profile.dart index 7c0af0f..a8274c6 100644 --- a/lib/pages/main/profile/profile.dart +++ b/lib/pages/main/profile/profile.dart @@ -1,10 +1,11 @@ import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:movielab/constants/colors.dart'; -import 'package:movielab/pages/main/profile/sections/lists.dart'; +import 'sections/lists.dart'; import 'sections/settings.dart'; import 'sections/socials.dart'; +import 'sections/user_profile/user_profile.dart'; class ProfilePage extends StatelessWidget { const ProfilePage({Key? key}) : super(key: key); @@ -28,6 +29,8 @@ class ProfilePage extends StatelessWidget { child: ListView( physics: const BouncingScrollPhysics(), children: const [ + SizedBox(height: 40), + ProfilePageUserProfile(), SizedBox(height: 40), ProfilePageLists(), SizedBox(height: 40), diff --git a/lib/pages/main/profile/profile_controller.dart b/lib/pages/main/profile/profile_controller.dart new file mode 100644 index 0000000..561251c --- /dev/null +++ b/lib/pages/main/profile/profile_controller.dart @@ -0,0 +1,101 @@ +import 'package:get/get.dart'; + +class ProfileController extends GetxController { + int watchedMoviesCount = 0; + int watchedSeriesCount = 0; + updateWatchedMoviesCount(int count) { + watchedMoviesCount = count; + update(); + } + + updateWatchedSeriesCount(int count) { + watchedSeriesCount = count; + update(); + } + + double imdbRatingAverage = 0; + updateImdbRatingAverage(double value) { + imdbRatingAverage = value; + update(); + } + + Map genres = {}; + List sortedGenres = []; + int genresLength = 0; + int genresOthers = 0; + updateGenres( + {required Map genres, + required List sortedGenres, + required int genresLength, + required int genresOthers}) { + this.genres = genres; + this.sortedGenres = sortedGenres; + this.genresLength = genresLength; + this.genresOthers = genresOthers; + update(); + } + + Map countries = {}; + List sortedCountries = []; + int countriesLength = 0; + int countriesOthers = 0; + updateCountries( + {required Map countries, + required List sortedCountries, + required int countriesLength, + required int countriesOthers}) { + this.countries = countries; + this.sortedCountries = sortedCountries; + this.countriesLength = countriesLength; + this.countriesOthers = countriesOthers; + update(); + } + + Map languages = {}; + List sortedLanguages = []; + int languagesLength = 0; + int languagesOthers = 0; + updateLanguages( + {required Map languages, + required List sortedLanguages, + required int languagesLength, + required int languagesOthers}) { + this.languages = languages; + this.sortedLanguages = sortedLanguages; + this.languagesLength = languagesLength; + this.languagesOthers = languagesOthers; + update(); + } + + Map companies = {}; + List sortedCompanies = []; + int companiesLength = 0; + int companiesOthers = 0; + updateCompanies( + {required Map companies, + required List sortedCompanies, + required int companiesLength, + required int companiesOthers}) { + this.companies = companies; + this.sortedCompanies = sortedCompanies; + this.companiesLength = companiesLength; + this.companiesOthers = companiesOthers; + update(); + } + + Map contentRatings = {}; + List sortedContentRatings = []; + int contentRatingsLength = 0; + int contentRatingsOthers = 0; + updateContentRatings( + {required Map contentRatings, + required List sortedContentRatings, + required int contentRatingsLength, + required int contentRatingsOthers}) { + this.contentRatings = contentRatings; + this.sortedContentRatings = sortedContentRatings; + this.contentRatingsLength = contentRatingsLength; + this.contentRatingsOthers = contentRatingsOthers; + update(); + } +} diff --git a/lib/pages/main/profile/sections/list_page/sections/stats_page/stats.dart b/lib/pages/main/profile/sections/list_page/sections/stats_page/stats.dart index 27b40d6..6b188da 100644 --- a/lib/pages/main/profile/sections/list_page/sections/stats_page/stats.dart +++ b/lib/pages/main/profile/sections/list_page/sections/stats_page/stats.dart @@ -123,7 +123,7 @@ class _ListStatsPageState extends State { const SizedBox( height: 7.5, ), - Text("Avarage IMDB rating", + Text("Avarage IMDb rating", style: TextStyle( color: Colors.white.withOpacity(0.75), fontSize: 15, diff --git a/lib/pages/main/profile/sections/user_profile/edit_user_profile.dart b/lib/pages/main/profile/sections/user_profile/edit_user_profile.dart new file mode 100644 index 0000000..76df52c --- /dev/null +++ b/lib/pages/main/profile/sections/user_profile/edit_user_profile.dart @@ -0,0 +1,58 @@ +import 'package:flutter/material.dart'; +import 'package:movielab/constants/colors.dart'; +import 'package:movielab/widgets/buttons/glassmorphism_button.dart'; +import 'package:movielab/widgets/textfield_widget.dart'; + +import 'user_profile.dart'; + +class ProfilePageEditUserProfile extends StatelessWidget { + const ProfilePageEditUserProfile({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: kBackgroundColor, + appBar: AppBar( + leading: const BackButton(), + backgroundColor: Colors.transparent, + elevation: 0, + ), + body: ListView( + padding: const EdgeInsets.symmetric(horizontal: 32), + physics: const BouncingScrollPhysics(), + children: [ + userProfileImage(context, icon: Icons.add_a_photo, onTap: () {}), + const SizedBox(height: 24), + TextFieldWidget( + label: 'Full Name', + text: "user.name", + onChanged: (name) {}, + ), + const SizedBox(height: 24), + TextFieldWidget( + label: 'Email', + text: "user.email", + onChanged: (email) {}, + ), + const SizedBox(height: 24), + TextFieldWidget( + label: 'About', + text: "user.about", + maxLines: 5, + onChanged: (about) {}, + ), + const SizedBox(height: 40), + GmButton( + text: "Save", + onTap: () { + Navigator.pop(context); + }, + padding: EdgeInsets.symmetric( + horizontal: MediaQuery.of(context).size.width / 5), + backgroundColor: Colors.blue, + color: Colors.white) + ], + ), + ); + } +} diff --git a/lib/pages/main/profile/sections/user_profile/user_profile.dart b/lib/pages/main/profile/sections/user_profile/user_profile.dart new file mode 100644 index 0000000..b253d4d --- /dev/null +++ b/lib/pages/main/profile/sections/user_profile/user_profile.dart @@ -0,0 +1,213 @@ +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_rating_bar/flutter_rating_bar.dart'; +import 'package:get/get.dart'; +import 'package:movielab/constants/colors.dart'; +import 'package:movielab/modules/tools/navigate.dart'; +import 'package:movielab/pages/main/profile/profile_controller.dart'; + +import 'edit_user_profile.dart'; + +class ProfilePageUserProfile extends StatelessWidget { + const ProfilePageUserProfile({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return GetBuilder(builder: (_) { + return Center( + child: Stack( + children: [ + AnimatedContainer( + height: 350, + margin: const EdgeInsets.only(top: 64), + padding: const EdgeInsets.only(top: 70), + width: MediaQuery.of(context).size.width, + decoration: BoxDecoration( + color: kSecondaryColor, + borderRadius: BorderRadius.circular(15)), + duration: const Duration(milliseconds: 150), + child: Column( + children: [ + const Text( + "Erfan Rahmati", + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: 24), + ), + const SizedBox(height: 4), + Text( + "@ErfanRht", + style: TextStyle( + color: Colors.white.withOpacity(0.5), + fontWeight: FontWeight.w600, + ), + ), + Stack( + children: [ + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 25, vertical: 5), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + buildButton( + context, + _.watchedMoviesCount.toString(), + "Watched\nMovies", + ), + buildButton( + context, + _.watchedSeriesCount.toString(), + "Watched\nSeries", + ), + ], + ), + ), + Padding( + padding: const EdgeInsets.symmetric(vertical: 20), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + RatingBarIndicator( + rating: (_.imdbRatingAverage / 10) - 0.15, + itemBuilder: (context, index) => const Icon( + Icons.star, + color: kImdbColor, + ), + unratedColor: kGreyColor, + itemCount: 1, + itemSize: 50, + ), + Text(_.imdbRatingAverage.toString(), + style: const TextStyle( + color: kImdbColor, + fontSize: 25, + fontWeight: FontWeight.w700, + )), + const SizedBox(height: 3), + Text( + "Avarage IMDb rating", + textAlign: TextAlign.center, + style: TextStyle( + color: Colors.white.withOpacity(0.75), + fontSize: 12.5, + fontWeight: FontWeight.w600), + ), + ], + ), + ], + ), + ) + ], + ), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 40, vertical: 7.5), + child: Divider( + color: Colors.white.withOpacity(0.75), + thickness: 2.5, + ), + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: const [ + //buildButton(context, "Drama", "Favorite Genre"), + ], + ) + ], + ), + ), + userProfileImage(context, icon: Icons.edit, onTap: () { + Navigate.pushHeroicTo( + context, const ProfilePageEditUserProfile()); + }), + ], + ), + ); + }); + } +} + +Widget buildButton(BuildContext context, String value, String text) => + MaterialButton( + padding: const EdgeInsets.symmetric(vertical: 4), + onPressed: () {}, + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + value, + style: const TextStyle( + color: Colors.white, fontWeight: FontWeight.bold, fontSize: 24), + ), + const SizedBox(height: 2), + Text( + text, + textAlign: TextAlign.center, + style: TextStyle( + color: Colors.white.withOpacity(0.75), + fontWeight: FontWeight.w600), + ), + ], + ), + ); + +Widget userProfileImage(BuildContext context, + {required IconData icon, void Function()? onTap}) => + Center( + child: Stack( + children: [ + ClipOval( + child: Material( + color: Colors.transparent, + child: Ink.image( + image: const AssetImage("assets/images/no_picture.png"), + fit: BoxFit.cover, + width: 128, + height: 128, + child: InkWell(onTap: () {}), + ), + ), + ), + Positioned( + bottom: 0, + right: 4, + child: InkWell( + onTap: onTap, + child: buildCircle( + color: kSecondaryColor, + all: 3, + child: buildCircle( + color: Colors.blue, + all: 8, + child: Icon( + icon, + color: Colors.white, + size: 20, + ), + ), + ), + ), + ), + ], + ), + ); + +Widget buildCircle({ + required Widget child, + required double all, + required Color color, +}) => + ClipOval( + child: Container( + padding: EdgeInsets.all(all), + color: color, + child: child, + ), + ); diff --git a/lib/pages/splash/get_Initial_data.dart b/lib/pages/splash/get_Initial_data.dart index bf34264..dbdd5cc 100644 --- a/lib/pages/splash/get_Initial_data.dart +++ b/lib/pages/splash/get_Initial_data.dart @@ -1,7 +1,7 @@ import 'package:get/get.dart'; import 'package:movielab/constants/types.dart'; +import 'package:movielab/modules/api/api_requester.dart'; import 'package:movielab/pages/main/home/home_data_controller.dart'; -import '../../modules/api/api_requester.dart'; Future getInitialData() async { final apiRequester = APIRequester(); @@ -13,7 +13,6 @@ Future getInitialData() async { await Future.delayed(const Duration(seconds: 1)); return RequestResult.FAILURE_USER_PROBLEM; } - if (Get.find().trendingMovies.isNotEmpty || Get.find().trendingShows.isNotEmpty || Get.find().inTheaters.isNotEmpty) { diff --git a/lib/pages/splash/get_user_data.dart b/lib/pages/splash/get_user_data.dart new file mode 100644 index 0000000..4b7cff0 --- /dev/null +++ b/lib/pages/splash/get_user_data.dart @@ -0,0 +1,203 @@ +import 'package:get/get.dart'; +import 'package:movielab/models/show_models/show_preview_model.dart'; +import 'package:movielab/modules/preferences/preferences_shareholder.dart'; +import 'package:movielab/pages/main/profile/profile_controller.dart'; + +Future getUserData() async { + await updateUserStats(); +} + +Future updateUserStats() async { + PreferencesShareholder preferencesShareholder = PreferencesShareholder(); + List> allLists = await preferencesShareholder.getAllLists(); + List items = await getAllItems(allLists: allLists); + + ProfileController controller = Get.find(); + + if (allLists[0].isNotEmpty || + allLists[1].isNotEmpty || + allLists[2].isNotEmpty) { + int watchedMovieCount = 0; + int watchedShowCount = 0; + for (ShowPreview item in allLists[2]) { + if (item.type == "Movie") { + watchedMovieCount++; + } else if (item.type == "TVSeries") { + watchedShowCount++; + } + } + controller.updateWatchedMoviesCount(watchedMovieCount); + controller.updateWatchedSeriesCount(watchedShowCount); + + List itemsImdbRatings = []; + for (ShowPreview item in items) { + try { + itemsImdbRatings.add(double.parse(item.imDbRating)); + // ignore: empty_catches + } catch (e) {} + } + final double itemsImdbRatingAverage = double.parse( + ((itemsImdbRatings.reduce((a, b) => a + b) / itemsImdbRatings.length)) + .toStringAsFixed(2)); + controller.updateImdbRatingAverage(itemsImdbRatingAverage); + + Map itemsGenres = {}; + int genresLength = 0; + int genresOthers = 0; + int i = 0; + for (ShowPreview item in items) { + for (String genre in item.genres!.split(", ")) { + genresLength++; + if (i > 6) { + genresOthers++; + } + i++; + if (itemsGenres.containsKey(genre)) { + itemsGenres[genre] = itemsGenres[genre]! + 1; + } else { + itemsGenres[genre] = 1; + } + } + } + final List sortedGenres = itemsGenres.keys.toList(); + sortedGenres.sort((a, b) => itemsGenres[b]!.compareTo(itemsGenres[a]!)); + if (sortedGenres.length > 7) { + for (int i = 0; i < sortedGenres.length; i++) {} + } + controller.updateGenres( + genres: itemsGenres, + sortedGenres: sortedGenres, + genresLength: genresLength, + genresOthers: genresOthers); + + Map itemCountries = {}; + int countriesLength = 0; + int countriesOthers = 0; + i = 0; + for (ShowPreview item in items) { + for (String country in item.countries!.split(", ")) { + countriesLength++; + if (i > 6) { + countriesOthers++; + } + i++; + if (itemCountries.containsKey(country)) { + itemCountries[country] = itemCountries[country]! + 1; + } else { + itemCountries[country] = 1; + } + } + } + final List sortedCountries = itemCountries.keys.toList(); + sortedCountries + .sort((a, b) => itemCountries[b]!.compareTo(itemCountries[a]!)); + if (sortedCountries.length > 7) { + for (int i = 0; i < sortedCountries.length; i++) {} + } + controller.updateCountries( + countries: itemCountries, + sortedCountries: sortedCountries, + countriesLength: countriesLength, + countriesOthers: countriesOthers); + + Map languages = {}; + int languagesLength = 0; + int languagesOthers = 0; + i = 0; + for (ShowPreview item in items) { + for (String language in item.languages!.split(", ")) { + languagesLength++; + if (i > 6) { + languagesOthers++; + } + i++; + if (languages.containsKey(language)) { + languages[language] = languages[language]! + 1; + } else { + languages[language] = 1; + } + } + } + final List sortedLanguages = languages.keys.toList(); + sortedLanguages.sort((a, b) => languages[b]!.compareTo(languages[a]!)); + if (sortedLanguages.length > 7) { + for (int i = 0; i < sortedLanguages.length; i++) {} + } + controller.updateLanguages( + languages: languages, + sortedLanguages: sortedLanguages, + languagesLength: languagesLength, + languagesOthers: languagesOthers); + + Map companies = {}; + int companiesLength = 0; + int companiesOthers = 0; + i = 0; + for (ShowPreview item in items) { + for (String company in item.companies!.split(", ")) { + companiesLength++; + if (i > 6) { + companiesOthers++; + } + i++; + if (companies.containsKey(company)) { + companies[company] = companies[company]! + 1; + } else { + companies[company] = 1; + } + } + } + final List sortedCompanies = companies.keys.toList(); + sortedCompanies.sort((a, b) => companies[b]!.compareTo(companies[a]!)); + if (sortedCompanies.length > 7) { + for (int i = 0; i < sortedCompanies.length; i++) {} + } + controller.updateCompanies( + companies: companies, + sortedCompanies: sortedCompanies, + companiesLength: companiesLength, + companiesOthers: companiesOthers); + + Map contentRatings = {}; + int contentRatingsLength = 0; + int contentRatingsOthers = 0; + i = 0; + for (ShowPreview item in items) { + for (String contentRating in item.contentRating!.split(", ")) { + contentRatingsLength++; + if (i > 6) { + contentRatingsOthers++; + } + i++; + if (contentRatings.containsKey(contentRating)) { + contentRatings[contentRating] = contentRatings[contentRating]! + 1; + } else { + contentRatings[contentRating] = 1; + } + } + } + final List sortedContentRatings = contentRatings.keys.toList(); + sortedContentRatings + .sort((a, b) => contentRatings[b]!.compareTo(contentRatings[a]!)); + if (sortedContentRatings.length > 7) { + for (int i = 0; i < sortedContentRatings.length; i++) {} + } + controller.updateContentRatings( + contentRatings: contentRatings, + sortedContentRatings: sortedContentRatings, + contentRatingsLength: contentRatingsLength, + contentRatingsOthers: contentRatingsOthers); + print("User stats updated"); + return true; + } + return false; +} + +Future> getAllItems( + {required List> allLists}) async { + List items = []; + for (List list in allLists) { + items.addAll(list); + } + return items; +} diff --git a/lib/pages/splash/splash_screen.dart b/lib/pages/splash/splash_screen.dart index 3e2b3ba..bc7fe63 100644 --- a/lib/pages/splash/splash_screen.dart +++ b/lib/pages/splash/splash_screen.dart @@ -8,6 +8,7 @@ import '../../constants/colors.dart'; import '../../constants/types.dart'; import '../../modules/tools/system_ui_overlay_style.dart'; import 'get_initial_data.dart'; +import 'get_user_data.dart'; class SplashScreen extends StatefulWidget { const SplashScreen({Key? key}) : super(key: key); @@ -85,6 +86,7 @@ class _SplashScreenState extends State { getInitialData().then((result) { if (result == RequestResult.SUCCESS) { recommender(); + getUserData(); Navigate.replaceTo(context, const MainPage()); } else { setState(() { diff --git a/lib/widgets/buttons/glassmorphism_button.dart b/lib/widgets/buttons/glassmorphism_button.dart index 5096720..b746f17 100644 --- a/lib/widgets/buttons/glassmorphism_button.dart +++ b/lib/widgets/buttons/glassmorphism_button.dart @@ -11,7 +11,8 @@ class GmButton extends StatelessWidget { required this.color, this.backgroundColor, this.height = 35, - this.width = 100}) + this.width = 100, + this.padding = EdgeInsets.zero}) : super(key: key); final String text; @@ -22,34 +23,38 @@ class GmButton extends StatelessWidget { final Color? backgroundColor; final double height; final double width; + final EdgeInsets padding; @override Widget build(BuildContext context) { - return InkWell( - onTap: onTap, - borderRadius: BorderRadius.circular(radius), - child: Container( - width: width, - height: height, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(radius), - color: backgroundColor ?? color.withOpacity(0.25), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - icon != null - ? Icon(icon, color: color, size: 15) - : const SizedBox.shrink(), - icon != null - ? const SizedBox( - width: 7.5, - ) - : const SizedBox.shrink(), - Text(text, - style: GoogleFonts.ubuntu( - color: color, fontSize: 15, fontWeight: FontWeight.w500)), - ], + return Padding( + padding: padding, + child: InkWell( + onTap: onTap, + borderRadius: BorderRadius.circular(radius), + child: Container( + width: width, + height: height, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(radius), + color: backgroundColor ?? color.withOpacity(0.25), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + icon != null + ? Icon(icon, color: color, size: 15) + : const SizedBox.shrink(), + icon != null + ? const SizedBox( + width: 7.5, + ) + : const SizedBox.shrink(), + Text(text, + style: GoogleFonts.ubuntu( + color: color, fontSize: 15, fontWeight: FontWeight.w500)), + ], + ), ), ), ); diff --git a/lib/widgets/textfield_widget.dart b/lib/widgets/textfield_widget.dart new file mode 100644 index 0000000..1094ed9 --- /dev/null +++ b/lib/widgets/textfield_widget.dart @@ -0,0 +1,68 @@ +import 'package:flutter/material.dart'; + +class TextFieldWidget extends StatefulWidget { + final int maxLines; + final String label; + final String text; + final ValueChanged onChanged; + + const TextFieldWidget({ + Key? key, + this.maxLines = 1, + required this.label, + required this.text, + required this.onChanged, + }) : super(key: key); + + @override + TextFieldWidgetState createState() => TextFieldWidgetState(); +} + +class TextFieldWidgetState extends State { + late final TextEditingController controller; + + @override + void initState() { + super.initState(); + + controller = TextEditingController(text: widget.text); + } + + @override + void dispose() { + controller.dispose(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) => Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + widget.label, + style: const TextStyle( + color: Colors.white, fontWeight: FontWeight.bold, fontSize: 16), + ), + const SizedBox(height: 8), + TextField( + controller: controller, + style: TextStyle(color: Colors.white.withOpacity(0.8)), + decoration: InputDecoration( + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + ), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Colors.white.withOpacity(0.25), width: 2.0), + borderRadius: BorderRadius.circular(12), + ), + focusedBorder: OutlineInputBorder( + borderSide: + const BorderSide(color: Colors.blue, width: 2.5), + borderRadius: BorderRadius.circular(12))), + maxLines: widget.maxLines, + ), + ], + ); +} diff --git a/pubspec.yaml b/pubspec.yaml index 0abc1aa..26fe569 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -57,4 +57,4 @@ flutter: assets: - assets/images/logos/ - - assets/images/erfan_rahmati_profile.jpg \ No newline at end of file + - assets/images/ \ No newline at end of file