diff --git a/assets/images/click_logo.png b/assets/images/click_logo.png new file mode 100644 index 0000000..1709cdb Binary files /dev/null and b/assets/images/click_logo.png differ diff --git a/assets/images/cosmetics_img.png b/assets/images/cosmetics_img.png new file mode 100644 index 0000000..b4e7a00 Binary files /dev/null and b/assets/images/cosmetics_img.png differ diff --git a/assets/images/delivery_img.png b/assets/images/delivery_img.png new file mode 100644 index 0000000..cedb056 Binary files /dev/null and b/assets/images/delivery_img.png differ diff --git a/assets/images/fondex_logo.png b/assets/images/fondex_logo.png new file mode 100644 index 0000000..50fc8f2 Binary files /dev/null and b/assets/images/fondex_logo.png differ diff --git a/assets/images/fondex_logo_main.png b/assets/images/fondex_logo_main.png new file mode 100644 index 0000000..5d701dd Binary files /dev/null and b/assets/images/fondex_logo_main.png differ diff --git a/assets/images/food_img.png b/assets/images/food_img.png new file mode 100644 index 0000000..b7e9b5c Binary files /dev/null and b/assets/images/food_img.png differ diff --git a/assets/images/garderob_img.png b/assets/images/garderob_img.png new file mode 100644 index 0000000..ef351e1 Binary files /dev/null and b/assets/images/garderob_img.png differ diff --git a/assets/images/ic_pick_drop_location.png b/assets/images/ic_pick_drop_location.png new file mode 100644 index 0000000..f384623 Binary files /dev/null and b/assets/images/ic_pick_drop_location.png differ diff --git a/assets/images/keys_img.png b/assets/images/keys_img.png new file mode 100644 index 0000000..9a7c835 Binary files /dev/null and b/assets/images/keys_img.png differ diff --git a/assets/images/location_indicatorl b/assets/images/location_indicatorl new file mode 100644 index 0000000..a48f948 Binary files /dev/null and b/assets/images/location_indicatorl differ diff --git a/assets/images/money_logo.png b/assets/images/money_logo.png new file mode 100644 index 0000000..b8b8421 Binary files /dev/null and b/assets/images/money_logo.png differ diff --git a/assets/images/outer_city_taxi_option.png b/assets/images/outer_city_taxi_option.png new file mode 100644 index 0000000..0af0c0d Binary files /dev/null and b/assets/images/outer_city_taxi_option.png differ diff --git a/assets/images/payme_logo.png b/assets/images/payme_logo.png new file mode 100644 index 0000000..5e33868 Binary files /dev/null and b/assets/images/payme_logo.png differ diff --git a/assets/images/products_img.png b/assets/images/products_img.png new file mode 100644 index 0000000..85e4a3b Binary files /dev/null and b/assets/images/products_img.png differ diff --git a/assets/images/taxi_img.png b/assets/images/taxi_img.png new file mode 100644 index 0000000..58bfadf Binary files /dev/null and b/assets/images/taxi_img.png differ diff --git a/assets/images/taxi_option.png b/assets/images/taxi_option.png new file mode 100644 index 0000000..340f726 Binary files /dev/null and b/assets/images/taxi_option.png differ diff --git a/lib/main.dart b/lib/main.dart index 8e1f5ea..d607b39 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -6,6 +6,7 @@ import 'package:customer/utils/preferences.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/material.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; import 'controllers/global_setting_controller.dart'; import 'controllers/theme_controller.dart'; @@ -13,7 +14,10 @@ import 'firebase_options.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); - await Firebase.initializeApp(name: 'default', options: DefaultFirebaseOptions.currentPlatform); + await Firebase.initializeApp( + name: 'default', + options: DefaultFirebaseOptions.currentPlatform, + ); await Preferences.initPref(); @@ -32,54 +36,79 @@ class MyApp extends StatelessWidget { Widget build(BuildContext context) { Get.put(ThemeController()); return Obx( - () => GetMaterialApp( - debugShowCheckedModeBanner: false, - builder: (context, child) { - return SafeArea(bottom: true, top: false, child: EasyLoading.init()(context, child)); - }, - translations: LocalizationService(), - locale: LocalizationService.locale, - fallbackLocale: LocalizationService.locale, - themeMode: themeController.themeMode, - theme: ThemeData( - scaffoldBackgroundColor: AppThemeData.surface, - textTheme: TextTheme(bodyLarge: TextStyle(color: AppThemeData.grey900)), - appBarTheme: AppBarTheme( - backgroundColor: AppThemeData.surface, - foregroundColor: AppThemeData.grey900, - iconTheme: IconThemeData(color: AppThemeData.grey900), - ), - bottomNavigationBarTheme: BottomNavigationBarThemeData( - backgroundColor: AppThemeData.surface, - selectedItemColor: AppThemeData.primary300, - unselectedItemColor: AppThemeData.grey600, - selectedLabelStyle: TextStyle(fontFamily: AppThemeData.bold, fontSize: 12), - unselectedLabelStyle: TextStyle(fontFamily: AppThemeData.bold, fontSize: 12), - type: BottomNavigationBarType.fixed, - ), - ), - darkTheme: ThemeData( - scaffoldBackgroundColor: AppThemeData.surfaceDark, - textTheme: TextTheme(bodyLarge: TextStyle(color: AppThemeData.greyDark900)), - appBarTheme: AppBarTheme( - backgroundColor: AppThemeData.surfaceDark, - foregroundColor: AppThemeData.greyDark900, - iconTheme: IconThemeData(color: AppThemeData.greyDark900), - ), - bottomNavigationBarTheme: BottomNavigationBarThemeData( - backgroundColor: AppThemeData.grey900, - selectedItemColor: AppThemeData.primary300, - unselectedItemColor: AppThemeData.grey300, - selectedLabelStyle: TextStyle(fontFamily: AppThemeData.bold, fontSize: 12), - unselectedLabelStyle: TextStyle(fontFamily: AppThemeData.bold, fontSize: 12), - type: BottomNavigationBarType.fixed, - ), - ), - home: GetBuilder( - init: GlobalSettingController(), - builder: (context) { - return const SplashScreen(); + () => ScreenUtilInit( + designSize: Size(375, 812), + minTextAdapt: true, + splitScreenMode: true, + child: GetMaterialApp( + debugShowCheckedModeBanner: false, + builder: (context, child) { + return SafeArea( + bottom: true, + top: false, + child: EasyLoading.init()(context, child), + ); }, + translations: LocalizationService(), + locale: LocalizationService.locale, + fallbackLocale: LocalizationService.locale, + themeMode: themeController.themeMode, + theme: ThemeData( + scaffoldBackgroundColor: AppThemeData.surface, + textTheme: TextTheme( + bodyLarge: TextStyle(color: AppThemeData.grey900), + ), + appBarTheme: AppBarTheme( + backgroundColor: AppThemeData.surface, + foregroundColor: AppThemeData.grey900, + iconTheme: IconThemeData(color: AppThemeData.grey900), + ), + bottomNavigationBarTheme: BottomNavigationBarThemeData( + backgroundColor: AppThemeData.surface, + selectedItemColor: AppThemeData.primary300, + unselectedItemColor: AppThemeData.grey600, + selectedLabelStyle: TextStyle( + fontFamily: AppThemeData.bold, + fontSize: 12, + ), + unselectedLabelStyle: TextStyle( + fontFamily: AppThemeData.bold, + fontSize: 12, + ), + type: BottomNavigationBarType.fixed, + ), + ), + darkTheme: ThemeData( + scaffoldBackgroundColor: AppThemeData.surfaceDark, + textTheme: TextTheme( + bodyLarge: TextStyle(color: AppThemeData.greyDark900), + ), + appBarTheme: AppBarTheme( + backgroundColor: AppThemeData.surfaceDark, + foregroundColor: AppThemeData.greyDark900, + iconTheme: IconThemeData(color: AppThemeData.greyDark900), + ), + bottomNavigationBarTheme: BottomNavigationBarThemeData( + backgroundColor: AppThemeData.grey900, + selectedItemColor: AppThemeData.primary300, + unselectedItemColor: AppThemeData.grey300, + selectedLabelStyle: TextStyle( + fontFamily: AppThemeData.bold, + fontSize: 12, + ), + unselectedLabelStyle: TextStyle( + fontFamily: AppThemeData.bold, + fontSize: 12, + ), + type: BottomNavigationBarType.fixed, + ), + ), + home: GetBuilder( + init: GlobalSettingController(), + builder: (context) { + return const SplashScreen(); + }, + ), ), ), ); diff --git a/lib/screen_ui/service_home_screen/service_list_screen.dart b/lib/screen_ui/service_home_screen/service_list_screen.dart index b6a5aaf..03584cf 100644 --- a/lib/screen_ui/service_home_screen/service_list_screen.dart +++ b/lib/screen_ui/service_home_screen/service_list_screen.dart @@ -1,5 +1,8 @@ +import 'dart:developer'; + import 'package:customer/constant/constant.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; import '../../controllers/service_list_controller.dart'; import '../../controllers/theme_controller.dart'; @@ -25,8 +28,8 @@ class ServiceListScreen extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text("eMart".tr, style: AppThemeData.semiBoldTextStyle(fontSize: 22, color: themeController.isDark.value ? AppThemeData.grey50 : AppThemeData.grey900)), - Text("All Your Needs in One App!".tr, style: AppThemeData.regularTextStyle(fontSize: 14, color: themeController.isDark.value ? AppThemeData.grey100 : AppThemeData.grey700)), + Image.asset("assets/images/fondex_logo.png", + height: 32.r, width: 124.r, fit: BoxFit.contain), ], ), ), @@ -37,45 +40,140 @@ class ServiceListScreen extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ + controller.serviceListBanner.isEmpty + ? SizedBox() + : Padding( + padding: EdgeInsets.symmetric(horizontal: 16.r), + child: BannerView( + bannerList: controller.serviceListBanner, + ), + ), + // Main Cards Section + _mainCardsSection(), + + SizedBox(height: 15.h), + + // Other Services Section Title + Padding( + padding: EdgeInsets.symmetric(horizontal: 16.r), + child: Text( + "Другие услуги", + style: TextStyle( + fontFamily: AppThemeData.bold, + fontWeight: FontWeight.w700, + fontSize: 20.sp, + color: AppThemeData.darkGrey, + ), + ), + ), + + SizedBox(height: 10.h), + + _otherServicesCardMaker( + image: "assets/images/delivery_img.png", + title: "Курьерская доставка", + subtitle: "Доставляем безопасно", + ), + _otherServicesCardMaker( + image: "assets/images/keys_img.png", + title: "Аренда", + subtitle: "Огромный выбор объявлений!", + ), + _otherServicesCardMaker( + image: "assets/images/cosmetics_img.png", + title: "Косметика", + subtitle: "Более 1000 товаров", + ), + _otherServicesCardMaker( + image: "assets/images/products_img.png", + title: "Продукты питания", + subtitle: "Более 1000 товаров", + ), + + SizedBox(height: 45.h), const SizedBox(height: 12), - controller.serviceListBanner.isEmpty ? SizedBox() : BannerView(bannerList: controller.serviceListBanner), + controller.serviceListBanner.isEmpty + ? SizedBox() + : BannerView( + bannerList: controller.serviceListBanner, + ), const SizedBox(height: 12), Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text("Explore Our Services".tr, style: AppThemeData.semiBoldTextStyle(fontSize: 20, color: themeController.isDark.value ? AppThemeData.grey50 : AppThemeData.grey900)), + Text( + "Explore Our Services".tr, + style: AppThemeData.semiBoldTextStyle( + fontSize: 20, + color: + themeController.isDark.value + ? AppThemeData.grey50 + : AppThemeData.grey900, + ), + ), const SizedBox(height: 12), GridView.builder( itemCount: controller.sectionList.length, physics: const NeverScrollableScrollPhysics(), shrinkWrap: true, - gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3, mainAxisSpacing: 12, crossAxisSpacing: 12, mainAxisExtent: 130), + gridDelegate: + const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 3, + mainAxisSpacing: 12, + crossAxisSpacing: 12, + mainAxisExtent: 130, + ), itemBuilder: (context, index) { final section = controller.sectionList[index]; return GestureDetector( - onTap: () => controller.onServiceTap(context, section), + onTap: + () => controller.onServiceTap( + context, + section, + ), child: Container( decoration: BoxDecoration( - gradient: LinearGradient(colors: Constant.sectionColor[index % Constant.sectionColor.length], begin: Alignment.topCenter, end: Alignment.bottomCenter), + gradient: LinearGradient( + colors: + Constant.sectionColor[index % + Constant.sectionColor.length], + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + ), borderRadius: BorderRadius.circular(12), ), child: Column( - crossAxisAlignment: CrossAxisAlignment.center, + crossAxisAlignment: + CrossAxisAlignment.center, children: [ Padding( - padding: const EdgeInsets.only(top: 10, left: 5, right: 5), + padding: const EdgeInsets.only( + top: 10, + left: 5, + right: 5, + ), child: Text( section.name ?? '', textAlign: TextAlign.center, maxLines: 2, overflow: TextOverflow.ellipsis, - style: AppThemeData.semiBoldTextStyle(fontSize: 14, color: AppThemeData.grey900), + style: + AppThemeData.semiBoldTextStyle( + fontSize: 14, + color: AppThemeData.grey900, + ), ), ), const Spacer(), - NetworkImageWidget(imageUrl: section.sectionImage ?? '', width: 80, height: 60, fit: BoxFit.contain), + NetworkImageWidget( + imageUrl: + section.sectionImage ?? '', + width: 80, + height: 60, + fit: BoxFit.contain, + ), ], ), ), @@ -92,6 +190,238 @@ class ServiceListScreen extends StatelessWidget { }, ); } + + Widget _otherServicesCardMaker({ + required String image, + required String title, + required String subtitle, + }) { + return InkWell( + onTap: () { + log("Other Service Card Tapped: $title"); + }, + child: Container( + width: double.infinity, + margin: EdgeInsets.symmetric(horizontal: 16.r).copyWith(bottom: 10.r), + padding: EdgeInsets.only(left: 6.r, right: 12.r, top: 6.r, bottom: 6.r), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(16.r), + color: AppThemeData.grey50, + ), + child: Row( + spacing: 15.r, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Row( + spacing: 10.r, + children: [ + Container( + height: 52.r, + width: 52.r, + decoration: BoxDecoration( + color: AppThemeData.cardColor, + borderRadius: BorderRadius.circular(14.r), + ), + child: Image.asset( + image, + height: 62.r, + width: 62.r, + fit: BoxFit.contain, + ), + ), + Expanded( + child: Column( + spacing: 2.r, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + title, + style: TextStyle( + overflow: TextOverflow.ellipsis, + fontFamily: AppThemeData.semiBold, + fontSize: 16.sp, + fontWeight: FontWeight.w700, + color: AppThemeData.darkGrey, + ), + ), + Text( + subtitle, + style: TextStyle( + overflow: TextOverflow.ellipsis, + fontFamily: AppThemeData.semiBold, + fontSize: 13.sp, + fontWeight: FontWeight.w400, + color: AppThemeData.darkGrey, + ), + ), + ], + ), + ), + ], + ), + ), + Icon( + Icons.arrow_forward_ios, + size: 18.r, + color: AppThemeData.darkGrey, + ), + ], + ), + ), + ); + } + + Widget _mainCardsSection() { + return Container( + padding: EdgeInsets.symmetric(vertical: 16.r, horizontal: 16.r), + decoration: BoxDecoration( + color: AppThemeData.grey50, + borderRadius: BorderRadius.circular(16.r), + ), + child: Row( + spacing: 12.r, + children: [ + // Food & Garderobe Cards + Column( + spacing: 12.r, + children: [ + _mainCardsMaker( + title: "Еда и доставка", + image: "assets/images/food_img.png", + // onTap: () { + // log("Main Card Tapped"); + onTap: () async {}, + // }, + ), + _mainCardsMaker( + title: "Обновить гардероб", + image: "assets/images/garderob_img.png", + onTap: () { + log("Main Card Tapped"); + }, + ), + ], + ), + // Taxi Card + InkWell( + onTap: () { + log("Taxi Card Tapped"); + // push(context, DashBoardCabService(user: null)); + }, + child: Container( + height: 192.h, + width: 166.w, + padding: EdgeInsets.only(top: 12.r, right: 12.r), + decoration: BoxDecoration( + color: AppThemeData.yellow, + borderRadius: BorderRadius.circular(16.r), + ), + child: Column( + children: [ + Expanded( + child: Padding( + padding: EdgeInsets.only(left: 12.r), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: Text( + maxLines: 2, + "Позвать такси", + style: TextStyle( + overflow: TextOverflow.ellipsis, + fontFamily: AppThemeData.bold, + fontSize: 18.sp, + fontWeight: FontWeight.w700, + color: AppThemeData.grey50, + ), + ), + ), + Container( + height: 36.r, + width: 36.r, + decoration: BoxDecoration( + color: AppThemeData.grey50.withValues(alpha: 0.3), + borderRadius: BorderRadius.circular(8.r), + ), + child: Icon( + Icons.arrow_outward_rounded, + size: 20.r, + color: AppThemeData.grey50, + ), + ), + ], + ), + ), + ), + Image.asset( + "assets/images/taxi_img.png", + height: 119.r, + width: 156.r, + fit: BoxFit.contain, + ), + ], + ), + ), + ), + ], + ), + ); + } + + Widget _mainCardsMaker({ + required String title, + required String image, + required VoidCallback onTap, + }) { + return InkWell( + onTap: onTap, + child: Container( + height: 93.h, + width: 165.w, + padding: EdgeInsets.only(left: 12.r), + decoration: BoxDecoration( + color: AppThemeData.cardColor, + borderRadius: BorderRadius.circular(16.r), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Expanded( + child: Padding( + padding: EdgeInsets.only(bottom: 12.r, top: 12.r), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + maxLines: 2, + title, + style: TextStyle( + overflow: TextOverflow.ellipsis, + fontFamily: AppThemeData.bold, + fontSize: 14.sp, + fontWeight: FontWeight.w700, + color: AppThemeData.darkGrey, + ), + ), + Icon( + Icons.arrow_outward_rounded, + size: 24.r, + color: AppThemeData.darkGrey, + ), + ], + ), + ), + ), + Image.asset(image, height: 71.r, width: 71.r, fit: BoxFit.contain), + ], + ), + ), + ); + } } class BannerView extends StatelessWidget { @@ -132,7 +462,13 @@ class BannerView extends StatelessWidget { itemBuilder: (context, index) { return ClipRRect( borderRadius: BorderRadius.circular(12), - child: SizedBox(width: MediaQuery.of(context).size.width * 0.8, child: NetworkImageWidget(imageUrl: bannerList[index].toString(), fit: BoxFit.fill)), + child: SizedBox( + width: MediaQuery.of(context).size.width * 0.8, + child: NetworkImageWidget( + imageUrl: bannerList[index].toString(), + fit: BoxFit.fill, + ), + ), ); }, ), @@ -142,7 +478,18 @@ class BannerView extends StatelessWidget { return Row( children: List.generate(bannerList.length, (index) { final isSelected = currentPage.value == index; - return Expanded(child: Container(height: 4, decoration: BoxDecoration(color: isSelected ? AppThemeData.grey300 : AppThemeData.grey100, borderRadius: BorderRadius.circular(5)))); + return Expanded( + child: Container( + height: 4, + decoration: BoxDecoration( + color: + isSelected + ? AppThemeData.grey300 + : AppThemeData.grey100, + borderRadius: BorderRadius.circular(5), + ), + ), + ); }), ); }), diff --git a/lib/themes/app_them_data.dart b/lib/themes/app_them_data.dart index 47dcaa8..d9485f1 100644 --- a/lib/themes/app_them_data.dart +++ b/lib/themes/app_them_data.dart @@ -199,6 +199,12 @@ class AppThemeData { static const Color warningDark500 = Color(0xFFFFE9AB); static const Color warningDark600 = Color(0xFFFFF8E5); + static const Color yellow = Color(0xFFE5AE3E); + static const Color cardColor = Color(0xFFEEEFF2); + static const Color darkGrey = Color(0xFF1F2937); + static const Color mainColor = Color(0xFFFF6839); + static const lightGrey = Color(0xFF8E8E93); + static const Color primary50 = Color(0xFFFFEBE5); static const Color primary100 = Color(0xFFFFC0AB); static const Color primary200 = Color(0xFFFF9472); diff --git a/pubspec.lock b/pubspec.lock index 8d3bc1b..ad977d0 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -678,6 +678,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.1" + flutter_screenutil: + dependency: "direct main" + description: + name: flutter_screenutil + sha256: "8239210dd68bee6b0577aa4a090890342d04a136ce1c81f98ee513fc0ce891de" + url: "https://pub.dev" + source: hosted + version: "5.9.3" flutter_spinkit: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index a196789..3e74692 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -86,6 +86,7 @@ dependencies: intl: ^0.20.2 uuid: ^4.5.2 flutter_google_places_hoc081098: ^2.0.0 + flutter_screenutil: ^5.9.3 dependency_overrides: webview_flutter: ^4.9.0