diff --git a/assets/icons/rasad_ban.svg b/assets/icons/rasad_ban.svg new file mode 100644 index 0000000..fd781ec --- /dev/null +++ b/assets/icons/rasad_ban.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/assets/icons/rasad_bar.svg b/assets/icons/rasad_bar.svg new file mode 100644 index 0000000..bc0a060 --- /dev/null +++ b/assets/icons/rasad_bar.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/assets/icons/rasad_bot.svg b/assets/icons/rasad_bot.svg new file mode 100644 index 0000000..19f27a2 --- /dev/null +++ b/assets/icons/rasad_bot.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/assets/icons/rasad_dam.svg b/assets/icons/rasad_dam.svg new file mode 100644 index 0000000..cf84209 --- /dev/null +++ b/assets/icons/rasad_dam.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/assets/icons/rasad_nan.svg b/assets/icons/rasad_nan.svg new file mode 100644 index 0000000..6fd8c7f --- /dev/null +++ b/assets/icons/rasad_nan.svg @@ -0,0 +1,507 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/icons/rasad_toyor.svg b/assets/icons/rasad_toyor.svg new file mode 100644 index 0000000..d98e848 --- /dev/null +++ b/assets/icons/rasad_toyor.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/assets/vec/rasad_ban.svg.vec b/assets/vec/rasad_ban.svg.vec new file mode 100644 index 0000000..53a4631 Binary files /dev/null and b/assets/vec/rasad_ban.svg.vec differ diff --git a/assets/vec/rasad_bar.svg.vec b/assets/vec/rasad_bar.svg.vec new file mode 100644 index 0000000..fea5942 Binary files /dev/null and b/assets/vec/rasad_bar.svg.vec differ diff --git a/assets/vec/rasad_bot.svg.vec b/assets/vec/rasad_bot.svg.vec new file mode 100644 index 0000000..87222b8 Binary files /dev/null and b/assets/vec/rasad_bot.svg.vec differ diff --git a/assets/vec/rasad_dam.svg.vec b/assets/vec/rasad_dam.svg.vec new file mode 100644 index 0000000..d298a1c Binary files /dev/null and b/assets/vec/rasad_dam.svg.vec differ diff --git a/assets/vec/rasad_nan.svg.vec b/assets/vec/rasad_nan.svg.vec new file mode 100644 index 0000000..0452acf Binary files /dev/null and b/assets/vec/rasad_nan.svg.vec differ diff --git a/assets/vec/rasad_toyor.svg.vec b/assets/vec/rasad_toyor.svg.vec new file mode 100644 index 0000000..9bf1f96 Binary files /dev/null and b/assets/vec/rasad_toyor.svg.vec differ diff --git a/lib/data/model/response/slider/slider_model.dart b/lib/data/model/response/slider/slider_model.dart new file mode 100644 index 0000000..ee7832a --- /dev/null +++ b/lib/data/model/response/slider/slider_model.dart @@ -0,0 +1,15 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'slider_model.freezed.dart'; +part 'slider_model.g.dart'; + +@freezed +abstract class SliderModel with _$SliderModel { + const factory SliderModel({ + List? up, + List? down, + }) = _SliderModel; + + factory SliderModel.fromJson(Map json) => + _$SliderModelFromJson(json); +} diff --git a/lib/data/model/response/slider/slider_model.freezed.dart b/lib/data/model/response/slider/slider_model.freezed.dart new file mode 100644 index 0000000..ff8f57a --- /dev/null +++ b/lib/data/model/response/slider/slider_model.freezed.dart @@ -0,0 +1,296 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'slider_model.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; + +/// @nodoc +mixin _$SliderModel { + + List? get up; List? get down; +/// Create a copy of SliderModel +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$SliderModelCopyWith get copyWith => _$SliderModelCopyWithImpl(this as SliderModel, _$identity); + + /// Serializes this SliderModel to a JSON map. + Map toJson(); + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is SliderModel&&const DeepCollectionEquality().equals(other.up, up)&&const DeepCollectionEquality().equals(other.down, down)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(up),const DeepCollectionEquality().hash(down)); + +@override +String toString() { + return 'SliderModel(up: $up, down: $down)'; +} + + +} + +/// @nodoc +abstract mixin class $SliderModelCopyWith<$Res> { + factory $SliderModelCopyWith(SliderModel value, $Res Function(SliderModel) _then) = _$SliderModelCopyWithImpl; +@useResult +$Res call({ + List? up, List? down +}); + + + + +} +/// @nodoc +class _$SliderModelCopyWithImpl<$Res> + implements $SliderModelCopyWith<$Res> { + _$SliderModelCopyWithImpl(this._self, this._then); + + final SliderModel _self; + final $Res Function(SliderModel) _then; + +/// Create a copy of SliderModel +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? up = freezed,Object? down = freezed,}) { + return _then(_self.copyWith( +up: freezed == up ? _self.up : up // ignore: cast_nullable_to_non_nullable +as List?,down: freezed == down ? _self.down : down // ignore: cast_nullable_to_non_nullable +as List?, + )); +} + +} + + +/// Adds pattern-matching-related methods to [SliderModel]. +extension SliderModelPatterns on SliderModel { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _SliderModel value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _SliderModel() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _SliderModel value) $default,){ +final _that = this; +switch (_that) { +case _SliderModel(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _SliderModel value)? $default,){ +final _that = this; +switch (_that) { +case _SliderModel() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( List? up, List? down)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _SliderModel() when $default != null: +return $default(_that.up,_that.down);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( List? up, List? down) $default,) {final _that = this; +switch (_that) { +case _SliderModel(): +return $default(_that.up,_that.down);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( List? up, List? down)? $default,) {final _that = this; +switch (_that) { +case _SliderModel() when $default != null: +return $default(_that.up,_that.down);case _: + return null; + +} +} + +} + +/// @nodoc +@JsonSerializable() + +class _SliderModel implements SliderModel { + const _SliderModel({final List? up, final List? down}): _up = up,_down = down; + factory _SliderModel.fromJson(Map json) => _$SliderModelFromJson(json); + + final List? _up; +@override List? get up { + final value = _up; + if (value == null) return null; + if (_up is EqualUnmodifiableListView) return _up; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(value); +} + + final List? _down; +@override List? get down { + final value = _down; + if (value == null) return null; + if (_down is EqualUnmodifiableListView) return _down; + // ignore: implicit_dynamic_type + return EqualUnmodifiableListView(value); +} + + +/// Create a copy of SliderModel +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$SliderModelCopyWith<_SliderModel> get copyWith => __$SliderModelCopyWithImpl<_SliderModel>(this, _$identity); + +@override +Map toJson() { + return _$SliderModelToJson(this, ); +} + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _SliderModel&&const DeepCollectionEquality().equals(other._up, _up)&&const DeepCollectionEquality().equals(other._down, _down)); +} + +@JsonKey(includeFromJson: false, includeToJson: false) +@override +int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(_up),const DeepCollectionEquality().hash(_down)); + +@override +String toString() { + return 'SliderModel(up: $up, down: $down)'; +} + + +} + +/// @nodoc +abstract mixin class _$SliderModelCopyWith<$Res> implements $SliderModelCopyWith<$Res> { + factory _$SliderModelCopyWith(_SliderModel value, $Res Function(_SliderModel) _then) = __$SliderModelCopyWithImpl; +@override @useResult +$Res call({ + List? up, List? down +}); + + + + +} +/// @nodoc +class __$SliderModelCopyWithImpl<$Res> + implements _$SliderModelCopyWith<$Res> { + __$SliderModelCopyWithImpl(this._self, this._then); + + final _SliderModel _self; + final $Res Function(_SliderModel) _then; + +/// Create a copy of SliderModel +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? up = freezed,Object? down = freezed,}) { + return _then(_SliderModel( +up: freezed == up ? _self._up : up // ignore: cast_nullable_to_non_nullable +as List?,down: freezed == down ? _self._down : down // ignore: cast_nullable_to_non_nullable +as List?, + )); +} + + +} + +// dart format on diff --git a/lib/data/model/response/slider/slider_model.g.dart b/lib/data/model/response/slider/slider_model.g.dart new file mode 100644 index 0000000..bd1d453 --- /dev/null +++ b/lib/data/model/response/slider/slider_model.g.dart @@ -0,0 +1,15 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'slider_model.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_SliderModel _$SliderModelFromJson(Map json) => _SliderModel( + up: (json['up'] as List?)?.map((e) => e as String).toList(), + down: (json['down'] as List?)?.map((e) => e as String).toList(), +); + +Map _$SliderModelToJson(_SliderModel instance) => + {'up': instance.up, 'down': instance.down}; diff --git a/lib/presentation/pages/modules/logic.dart b/lib/presentation/pages/modules/logic.dart index fb622c6..362a751 100644 --- a/lib/presentation/pages/modules/logic.dart +++ b/lib/presentation/pages/modules/logic.dart @@ -1,38 +1,90 @@ +import 'package:flutter/material.dart'; +import 'package:rasadyar_app/data/model/response/slider/slider_model.dart'; import 'package:rasadyar_app/presentation/routes/app_pages.dart'; import 'package:rasadyar_core/core.dart'; class ModulesLogic extends GetxController { TokenStorageService tokenService = Get.find(); + SliderLogic upSlider = Get.find(tag: "up"); + SliderLogic downSlider = Get.find(tag: "down"); RxBool isLoading = false.obs; List moduleList = [ - ModuleModel(title: 'بازرسی', icon: Assets.icons.inspection.path, module: Module.inspection), - ModuleModel(title: 'دام', icon: Assets.icons.liveStock.path, module: Module.liveStocks), - ModuleModel(title: 'مرغ', icon: Assets.icons.liveStock.path, module: Module.chicken), + ModuleModel( + title: 'رصدطیور', + icon: Assets.icons.rasadToyor.path, + module: Module.chicken, + borderColor: Color(0xFF4665AF), + backgroundColor: Color(0xFFECEEF2), + titleColor: Color(0xFF4665AF), + ), + ModuleModel( + title: 'رصدام', + icon: Assets.icons.rasadDam.path, + module: Module.liveStocks, + borderColor: Color(0xFFD7A972), + backgroundColor: Color(0xFFF4F1EF), + titleColor: Color(0xFF7F7F7F), + ), + ModuleModel( + title: 'رصدبان', + icon: Assets.icons.rasadBan.path, + module: Module.inspection, + borderColor: Color(0xFF014856), + backgroundColor: Color(0xFFE9EDED), + titleColor: Color(0xFF014856), + ), + ModuleModel( + title: 'رصدبار', + icon: Assets.icons.rasadBar.path, + borderColor: Color(0xFFF37021), + backgroundColor: Color(0xFFFFECE1), + titleColor: Color(0xFFF37021), + ), + ModuleModel( + title: 'رصدبات', + icon: Assets.icons.rasadBot.path, + borderColor: Color(0xFF4A148C), + backgroundColor: Color(0xFFEDEAF0), + titleColor: Color(0xFF4A148C), + ), + ModuleModel( + title: 'رصدنان', + icon: Assets.icons.rasadNan.path, + borderColor: Color(0xFFD7A972), + backgroundColor: Color(0xFFF4F2EA), + titleColor: Color(0xFF8E8E8E), + ), ]; RxnInt selectedIndex = RxnInt(null); @override - void onReady() { - super.onReady(); + void onInit() { + super.onInit(); + getSliders(); } - @override - void onClose() { - super.onClose(); - } void saveModule(Module module) { tokenService.saveModule(module); tokenService.appModule.value = module; } - void onTapCard(Module module, int index) async { - isLoading.value = !isLoading.value; + void onTapCard(Module? module, int index) async { + if (module == null) { + Get.snackbar("بزودی", "این ماژول به زودی اضافه می‌شود", snackPosition: SnackPosition.BOTTOM); + } else { + _goToModule(module, index); + } + } + + void _goToModule(Module module, int index) async { selectedIndex.value = index; - await Future.delayed(Duration(milliseconds: 200)); // Simulate loading delay - navigateToModule(module); + await Future.delayed(Duration(milliseconds: 300)); + selectedIndex.value = null; + saveModule(module); + await navigateToModule(module); } Future navigateToModule(Module module) async { @@ -44,4 +96,24 @@ class ModulesLogic extends GetxController { isLoading.value = !isLoading.value; Get.toNamed(target.key, arguments: module); } + + Future getSliders() async { + var dio = Dio(); + dio.interceptors.add( + PrettyDioLogger( + request: true, + enabled: true, + requestHeader: true, + responseHeader: true, + requestBody: true, + responseBody: true, + ), + ); + var res = await dio.get("https://miran.storage.c2.liara.space/app/urllapp.json"); + if (res.statusCode == 200) { + SliderModel sliderModel = SliderModel.fromJson(res.data); + upSlider.onSuccess(sliderModel.up ?? []); + downSlider.onSuccess(sliderModel.down ?? []); + } + } } diff --git a/lib/presentation/pages/modules/view.dart b/lib/presentation/pages/modules/view.dart index 6ff320a..bba39ed 100644 --- a/lib/presentation/pages/modules/view.dart +++ b/lib/presentation/pages/modules/view.dart @@ -11,7 +11,13 @@ class ModulesPage extends GetView { Widget build(BuildContext context) { return Scaffold( appBar: AppBar( - title: Text('انتخاب سامانه', style: AppFonts.yekan18.copyWith(color: Colors.white)), + title: Row( + spacing: 5.w, + children: [ + Text('سامانه جامع رصدیار', style: AppFonts.yekan18Bold.copyWith(color: Colors.white)), + Assets.logos.finalLogo.image(width: 40.w, height: 40.h), + ], + ), centerTitle: true, backgroundColor: AppColor.blueNormal, ), @@ -19,23 +25,40 @@ class ModulesPage extends GetView { fit: StackFit.expand, alignment: Alignment.center, children: [ - GridView.builder( - padding: EdgeInsets.symmetric(horizontal: 10, vertical: 20), - itemBuilder: (context, index) { - final module = controller.moduleList[index]; - return CardIcon( - title: module.title, - icon: module.icon, - onTap: () => controller.onTapCard(module.module, index), - ); - }, - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 3, - mainAxisSpacing: 10, - crossAxisSpacing: 10, + Positioned.fill( + child: Column( + children: [ + SizedBox(height: 24.h), + SliderWidget(widgetTag: "up"), + + Expanded( + child: GridView.builder( + padding: EdgeInsets.symmetric(horizontal: 25.w, vertical: 24.h), + itemBuilder: (context, index) { + final module = controller.moduleList[index]; + return CardIcon( + title: module.title, + icon: module.icon, + borderColor: module.borderColor, + backgroundColor: module.backgroundColor, + titleColor: module.titleColor, + onTap: () => controller.onTapCard(module.module, index), + ); + }, + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 3, + mainAxisSpacing: 24.h, + crossAxisSpacing: 16.w, + ), + physics: BouncingScrollPhysics(), + itemCount: controller.moduleList.length, + ), + ), + + SliderWidget(height: 160, widgetTag: "down"), + SizedBox(height: 30.h), + ], ), - physics: BouncingScrollPhysics(), - itemCount: controller.moduleList.length, ), ObxValue((loading) { if (!controller.isLoading.value) return SizedBox.shrink(); diff --git a/lib/presentation/routes/app_pages.dart b/lib/presentation/routes/app_pages.dart index 66ab559..4a11fb2 100644 --- a/lib/presentation/routes/app_pages.dart +++ b/lib/presentation/routes/app_pages.dart @@ -25,7 +25,12 @@ sealed class AppPages { GetPage( name: AppPaths.moduleList, page: () => ModulesPage(), - binding: BindingsBuilder.put(() => ModulesLogic()), + binding: BindingsBuilder(() { + + Get.lazyPut(() => SliderLogic(), tag: "up"); + Get.lazyPut(() => SliderLogic(), tag: "down"); + Get.put(ModulesLogic()); + }), ), GetPage( @@ -35,35 +40,33 @@ sealed class AppPages { ), ...InspectionPages.pages, - ...LiveStockPages.pages, ...ChickenPages.pages, ]; } - Map?> getTargetModule(Module? value) { switch (value) { case Module.inspection: - return {InspectionRoutes.init:setupInspectionDI()}; + return {InspectionRoutes.init: setupInspectionDI()}; case Module.liveStocks: return {LiveStockRoutes.init: setupLiveStockDI()}; case Module.chicken: - return {ChickenRoutes.init : setupChickenDI()}; + return {ChickenRoutes.init: setupChickenDI()}; default: - return {AppPaths.moduleList : null}; + return {AppPaths.moduleList: null}; } } Map?> getAuthTargetPage(Module? value) { switch (value) { case Module.inspection: - return {InspectionRoutes.auth:setupInspectionDI()}; + return {InspectionRoutes.auth: setupInspectionDI()}; case Module.liveStocks: return {LiveStockRoutes.auth: setupLiveStockDI()}; case Module.chicken: - return {ChickenRoutes.auth : setupChickenDI()}; + return {ChickenRoutes.auth: setupChickenDI()}; default: - return {AppPaths.moduleList : null}; + return {AppPaths.moduleList: null}; } } diff --git a/packages/core/lib/data/model/local/module/module_model.dart b/packages/core/lib/data/model/local/module/module_model.dart index 3ca5760..2d036cc 100644 --- a/packages/core/lib/data/model/local/module/module_model.dart +++ b/packages/core/lib/data/model/local/module/module_model.dart @@ -1,16 +1,18 @@ -import 'package:flutter/material.dart'; import 'package:rasadyar_core/core.dart'; -import 'package:rasadyar_core/data/model/local/user_local/user_local_model.dart'; +import 'package:flutter/material.dart'; part 'module_model.freezed.dart'; @freezed abstract class ModuleModel with _$ModuleModel{ - const factory ModuleModel({ + factory ModuleModel({ required String title, required String icon, - required Module module, + required Color borderColor, + required Color backgroundColor, + required Color titleColor, + Module? module, }) = _ModuleModel; } \ No newline at end of file diff --git a/packages/core/lib/data/model/local/module/module_model.freezed.dart b/packages/core/lib/data/model/local/module/module_model.freezed.dart index aedd18f..28a5bdd 100644 --- a/packages/core/lib/data/model/local/module/module_model.freezed.dart +++ b/packages/core/lib/data/model/local/module/module_model.freezed.dart @@ -14,7 +14,7 @@ T _$identity(T value) => value; /// @nodoc mixin _$ModuleModel { - String get title; String get icon; Module get module; + String get title; String get icon; Color get borderColor; Color get backgroundColor; Color get titleColor; Module? get module; /// Create a copy of ModuleModel /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @@ -25,16 +25,16 @@ $ModuleModelCopyWith get copyWith => _$ModuleModelCopyWithImpl Object.hash(runtimeType,title,icon,module); +int get hashCode => Object.hash(runtimeType,title,icon,borderColor,backgroundColor,titleColor,module); @override String toString() { - return 'ModuleModel(title: $title, icon: $icon, module: $module)'; + return 'ModuleModel(title: $title, icon: $icon, borderColor: $borderColor, backgroundColor: $backgroundColor, titleColor: $titleColor, module: $module)'; } @@ -45,7 +45,7 @@ abstract mixin class $ModuleModelCopyWith<$Res> { factory $ModuleModelCopyWith(ModuleModel value, $Res Function(ModuleModel) _then) = _$ModuleModelCopyWithImpl; @useResult $Res call({ - String title, String icon, Module module + String title, String icon, Color borderColor, Color backgroundColor, Color titleColor, Module? module }); @@ -62,12 +62,15 @@ class _$ModuleModelCopyWithImpl<$Res> /// Create a copy of ModuleModel /// with the given fields replaced by the non-null parameter values. -@pragma('vm:prefer-inline') @override $Res call({Object? title = null,Object? icon = null,Object? module = null,}) { +@pragma('vm:prefer-inline') @override $Res call({Object? title = null,Object? icon = null,Object? borderColor = null,Object? backgroundColor = null,Object? titleColor = null,Object? module = freezed,}) { return _then(_self.copyWith( title: null == title ? _self.title : title // ignore: cast_nullable_to_non_nullable as String,icon: null == icon ? _self.icon : icon // ignore: cast_nullable_to_non_nullable -as String,module: null == module ? _self.module : module // ignore: cast_nullable_to_non_nullable -as Module, +as String,borderColor: null == borderColor ? _self.borderColor : borderColor // ignore: cast_nullable_to_non_nullable +as Color,backgroundColor: null == backgroundColor ? _self.backgroundColor : backgroundColor // ignore: cast_nullable_to_non_nullable +as Color,titleColor: null == titleColor ? _self.titleColor : titleColor // ignore: cast_nullable_to_non_nullable +as Color,module: freezed == module ? _self.module : module // ignore: cast_nullable_to_non_nullable +as Module?, )); } @@ -152,10 +155,10 @@ return $default(_that);case _: /// } /// ``` -@optionalTypeArgs TResult maybeWhen(TResult Function( String title, String icon, Module module)? $default,{required TResult orElse(),}) {final _that = this; +@optionalTypeArgs TResult maybeWhen(TResult Function( String title, String icon, Color borderColor, Color backgroundColor, Color titleColor, Module? module)? $default,{required TResult orElse(),}) {final _that = this; switch (_that) { case _ModuleModel() when $default != null: -return $default(_that.title,_that.icon,_that.module);case _: +return $default(_that.title,_that.icon,_that.borderColor,_that.backgroundColor,_that.titleColor,_that.module);case _: return orElse(); } @@ -173,10 +176,10 @@ return $default(_that.title,_that.icon,_that.module);case _: /// } /// ``` -@optionalTypeArgs TResult when(TResult Function( String title, String icon, Module module) $default,) {final _that = this; +@optionalTypeArgs TResult when(TResult Function( String title, String icon, Color borderColor, Color backgroundColor, Color titleColor, Module? module) $default,) {final _that = this; switch (_that) { case _ModuleModel(): -return $default(_that.title,_that.icon,_that.module);case _: +return $default(_that.title,_that.icon,_that.borderColor,_that.backgroundColor,_that.titleColor,_that.module);case _: throw StateError('Unexpected subclass'); } @@ -193,10 +196,10 @@ return $default(_that.title,_that.icon,_that.module);case _: /// } /// ``` -@optionalTypeArgs TResult? whenOrNull(TResult? Function( String title, String icon, Module module)? $default,) {final _that = this; +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String title, String icon, Color borderColor, Color backgroundColor, Color titleColor, Module? module)? $default,) {final _that = this; switch (_that) { case _ModuleModel() when $default != null: -return $default(_that.title,_that.icon,_that.module);case _: +return $default(_that.title,_that.icon,_that.borderColor,_that.backgroundColor,_that.titleColor,_that.module);case _: return null; } @@ -208,12 +211,15 @@ return $default(_that.title,_that.icon,_that.module);case _: class _ModuleModel implements ModuleModel { - const _ModuleModel({required this.title, required this.icon, required this.module}); + _ModuleModel({required this.title, required this.icon, required this.borderColor, required this.backgroundColor, required this.titleColor, this.module}); @override final String title; @override final String icon; -@override final Module module; +@override final Color borderColor; +@override final Color backgroundColor; +@override final Color titleColor; +@override final Module? module; /// Create a copy of ModuleModel /// with the given fields replaced by the non-null parameter values. @@ -225,16 +231,16 @@ _$ModuleModelCopyWith<_ModuleModel> get copyWith => __$ModuleModelCopyWithImpl<_ @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is _ModuleModel&&(identical(other.title, title) || other.title == title)&&(identical(other.icon, icon) || other.icon == icon)&&(identical(other.module, module) || other.module == module)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is _ModuleModel&&(identical(other.title, title) || other.title == title)&&(identical(other.icon, icon) || other.icon == icon)&&(identical(other.borderColor, borderColor) || other.borderColor == borderColor)&&(identical(other.backgroundColor, backgroundColor) || other.backgroundColor == backgroundColor)&&(identical(other.titleColor, titleColor) || other.titleColor == titleColor)&&(identical(other.module, module) || other.module == module)); } @override -int get hashCode => Object.hash(runtimeType,title,icon,module); +int get hashCode => Object.hash(runtimeType,title,icon,borderColor,backgroundColor,titleColor,module); @override String toString() { - return 'ModuleModel(title: $title, icon: $icon, module: $module)'; + return 'ModuleModel(title: $title, icon: $icon, borderColor: $borderColor, backgroundColor: $backgroundColor, titleColor: $titleColor, module: $module)'; } @@ -245,7 +251,7 @@ abstract mixin class _$ModuleModelCopyWith<$Res> implements $ModuleModelCopyWith factory _$ModuleModelCopyWith(_ModuleModel value, $Res Function(_ModuleModel) _then) = __$ModuleModelCopyWithImpl; @override @useResult $Res call({ - String title, String icon, Module module + String title, String icon, Color borderColor, Color backgroundColor, Color titleColor, Module? module }); @@ -262,12 +268,15 @@ class __$ModuleModelCopyWithImpl<$Res> /// Create a copy of ModuleModel /// with the given fields replaced by the non-null parameter values. -@override @pragma('vm:prefer-inline') $Res call({Object? title = null,Object? icon = null,Object? module = null,}) { +@override @pragma('vm:prefer-inline') $Res call({Object? title = null,Object? icon = null,Object? borderColor = null,Object? backgroundColor = null,Object? titleColor = null,Object? module = freezed,}) { return _then(_ModuleModel( title: null == title ? _self.title : title // ignore: cast_nullable_to_non_nullable as String,icon: null == icon ? _self.icon : icon // ignore: cast_nullable_to_non_nullable -as String,module: null == module ? _self.module : module // ignore: cast_nullable_to_non_nullable -as Module, +as String,borderColor: null == borderColor ? _self.borderColor : borderColor // ignore: cast_nullable_to_non_nullable +as Color,backgroundColor: null == backgroundColor ? _self.backgroundColor : backgroundColor // ignore: cast_nullable_to_non_nullable +as Color,titleColor: null == titleColor ? _self.titleColor : titleColor // ignore: cast_nullable_to_non_nullable +as Color,module: freezed == module ? _self.module : module // ignore: cast_nullable_to_non_nullable +as Module?, )); } diff --git a/packages/core/lib/injection/di.dart b/packages/core/lib/injection/di.dart index 1e31ba5..c7bc829 100644 --- a/packages/core/lib/injection/di.dart +++ b/packages/core/lib/injection/di.dart @@ -11,9 +11,8 @@ Future setupAllCoreProvider() async { diCore.registerSingleton(NetworkStatus()..startListening()); //max 500MB Map Cashing - await diCore.registerSingleton( - FMTCObjectBoxBackend().initialise(maxDatabaseSize: 500 * 1024 * 1024), - ); + await FMTCObjectBoxBackend().initialise(); + diff --git a/packages/core/lib/presentation/common/app_fonts.dart b/packages/core/lib/presentation/common/app_fonts.dart index 72c1d45..cd31938 100644 --- a/packages/core/lib/presentation/common/app_fonts.dart +++ b/packages/core/lib/presentation/common/app_fonts.dart @@ -166,6 +166,15 @@ class AppFonts { height: _height, ); + + static TextStyle yekan18Bold = TextStyle( + fontFamily: yekan, + fontWeight: bold, // Use bold weight + fontSize: 18.sp, + height: _height, + ); + + static TextStyle yekan16Bold = TextStyle( // Base size bold fontFamily: yekan, diff --git a/packages/core/lib/presentation/common/assets.gen.dart b/packages/core/lib/presentation/common/assets.gen.dart index b349f7c..0ea224c 100644 --- a/packages/core/lib/presentation/common/assets.gen.dart +++ b/packages/core/lib/presentation/common/assets.gen.dart @@ -211,6 +211,24 @@ class $AssetsIconsGen { /// File path: assets/icons/profile_user.svg SvgGenImage get profileUser => const SvgGenImage('assets/icons/profile_user.svg'); + /// File path: assets/icons/rasad_ban.svg + SvgGenImage get rasadBan => const SvgGenImage('assets/icons/rasad_ban.svg'); + + /// File path: assets/icons/rasad_bar.svg + SvgGenImage get rasadBar => const SvgGenImage('assets/icons/rasad_bar.svg'); + + /// File path: assets/icons/rasad_bot.svg + SvgGenImage get rasadBot => const SvgGenImage('assets/icons/rasad_bot.svg'); + + /// File path: assets/icons/rasad_dam.svg + SvgGenImage get rasadDam => const SvgGenImage('assets/icons/rasad_dam.svg'); + + /// File path: assets/icons/rasad_nan.svg + SvgGenImage get rasadNan => const SvgGenImage('assets/icons/rasad_nan.svg'); + + /// File path: assets/icons/rasad_toyor.svg + SvgGenImage get rasadToyor => const SvgGenImage('assets/icons/rasad_toyor.svg'); + /// File path: assets/icons/receipt_discount.svg SvgGenImage get receiptDiscount => const SvgGenImage('assets/icons/receipt_discount.svg'); @@ -339,6 +357,12 @@ class $AssetsIconsGen { profile2Outline, profileCircle, profileUser, + rasadBan, + rasadBar, + rasadBot, + rasadDam, + rasadNan, + rasadToyor, receiptDiscount, sale, scan, @@ -576,6 +600,24 @@ class $AssetsVecGen { /// File path: assets/vec/profile_user.svg.vec SvgGenImage get profileUserSvg => const SvgGenImage.vec('assets/vec/profile_user.svg.vec'); + /// File path: assets/vec/rasad_ban.svg.vec + SvgGenImage get rasadBanSvg => const SvgGenImage.vec('assets/vec/rasad_ban.svg.vec'); + + /// File path: assets/vec/rasad_bar.svg.vec + SvgGenImage get rasadBarSvg => const SvgGenImage.vec('assets/vec/rasad_bar.svg.vec'); + + /// File path: assets/vec/rasad_bot.svg.vec + SvgGenImage get rasadBotSvg => const SvgGenImage.vec('assets/vec/rasad_bot.svg.vec'); + + /// File path: assets/vec/rasad_dam.svg.vec + SvgGenImage get rasadDamSvg => const SvgGenImage.vec('assets/vec/rasad_dam.svg.vec'); + + /// File path: assets/vec/rasad_nan.svg.vec + SvgGenImage get rasadNanSvg => const SvgGenImage.vec('assets/vec/rasad_nan.svg.vec'); + + /// File path: assets/vec/rasad_toyor.svg.vec + SvgGenImage get rasadToyorSvg => const SvgGenImage.vec('assets/vec/rasad_toyor.svg.vec'); + /// File path: assets/vec/receipt_discount.svg.vec SvgGenImage get receiptDiscountSvg => const SvgGenImage.vec('assets/vec/receipt_discount.svg.vec'); @@ -704,6 +746,12 @@ class $AssetsVecGen { profile2OutlineSvg, profileCircleSvg, profileUserSvg, + rasadBanSvg, + rasadBarSvg, + rasadBotSvg, + rasadDamSvg, + rasadNanSvg, + rasadToyorSvg, receiptDiscountSvg, saleSvg, scanSvg, diff --git a/packages/core/lib/presentation/widget/card/card_with_icon_with_border.dart b/packages/core/lib/presentation/widget/card/card_with_icon_with_border.dart index ca7d2b6..6986431 100644 --- a/packages/core/lib/presentation/widget/card/card_with_icon_with_border.dart +++ b/packages/core/lib/presentation/widget/card/card_with_icon_with_border.dart @@ -7,38 +7,53 @@ class CardIcon extends StatelessWidget { required this.title, required this.icon, this.onTap, + this.titleColor = AppColor.blueNormal, + this.titleStyle, + this.borderColor = AppColor.blueNormal, + this.backgroundColor = Colors.white, + this.borderRadius = 8, + this.width = 110, + this.height = 110, + this.borderWidth = 1, }); final String title; final String icon; final VoidCallback? onTap; + final Color titleColor; + final TextStyle? titleStyle; + + final Color borderColor; + final Color backgroundColor; + final double borderRadius; + final double borderWidth; + + final double width; + final double height; @override Widget build(BuildContext context) { - return InkWell( - onTap: onTap, - child: Card( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - side: const BorderSide(color: AppColor.blueNormal, width: 1), - ), - child: Container( - padding: const EdgeInsets.all(8), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(8), - color: Colors.white, - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - SvgGenImage(icon).svg(width: 50, height: 50), - const SizedBox(height: 8), - Text( - title, - style: AppFonts.yekan16.copyWith(color: AppColor.blueNormal), - ), - ], - ), + return Container( + clipBehavior: Clip.hardEdge, + padding: EdgeInsets.fromLTRB(17.w, 10.h, 17.w, 8.h), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(borderRadius.r), + color: backgroundColor, + border: Border.all(color: borderColor, width: borderWidth.w), + ), + child: InkWell( + onTap: onTap, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded(child: SvgGenImage(icon).svg(fit: BoxFit.fill)), + SizedBox(height: 10.h), + Text( + title, + textAlign: TextAlign.center, + style: titleStyle ?? AppFonts.yekan16Bold.copyWith(color: titleColor, height: 1.20), + ), + ], ), ), ); diff --git a/packages/core/lib/presentation/widget/slider/logic.dart b/packages/core/lib/presentation/widget/slider/logic.dart new file mode 100644 index 0000000..28ec188 --- /dev/null +++ b/packages/core/lib/presentation/widget/slider/logic.dart @@ -0,0 +1,45 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:rasadyar_core/core.dart'; + +class SliderLogic extends GetxController with StateMixin> { + final PageController pageController = PageController(initialPage: 0, viewportFraction: .93); + late Timer _timer; + late Duration duration; + + @override + void onInit() { + super.onInit(); + + duration = Duration(seconds: randomInt(8, 18)); + } + + void _startSliding(int itemCount) { + _timer = Timer.periodic(duration, (timer) { + if (pageController.hasClients) { + int nextPage = pageController.page!.round() + 1; + if (nextPage == itemCount) { + nextPage = 0; + } + pageController.animateToPage( + nextPage, + duration: Duration(milliseconds: 300), + curve: Curves.easeIn, + ); + } + }); + } + + @override + void onClose() { + _timer.cancel(); + pageController.dispose(); + super.onClose(); + } + + void onSuccess(List data) { + change(data, status: RxStatus.success()); + _startSliding(data.length); + } +} diff --git a/packages/core/lib/presentation/widget/slider/slider.dart b/packages/core/lib/presentation/widget/slider/slider.dart new file mode 100644 index 0000000..fe087c2 --- /dev/null +++ b/packages/core/lib/presentation/widget/slider/slider.dart @@ -0,0 +1,2 @@ +export 'logic.dart'; +export 'view.dart'; \ No newline at end of file diff --git a/packages/core/lib/presentation/widget/slider/view.dart b/packages/core/lib/presentation/widget/slider/view.dart new file mode 100644 index 0000000..ad438be --- /dev/null +++ b/packages/core/lib/presentation/widget/slider/view.dart @@ -0,0 +1,80 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:rasadyar_core/core.dart'; + +class SliderWidget extends GetView { + const SliderWidget({super.key, this.height = 210, this.widgetTag}); + + final int height; + final String? widgetTag; + + @override + String? get tag => widgetTag; + + @override + Widget build(BuildContext context) { + return SizedBox( + height: height.h, + child: controller.obx( + (state) => Stack( + alignment: AlignmentDirectional.bottomCenter, + fit: StackFit.expand, + children: [ + Positioned.fill( + child: PageView.builder( + controller: controller.pageController, + itemCount: state?.length ?? 0, + scrollDirection: Axis.horizontal, + itemBuilder: (context, index) { + String? image = state?[index]; + return Container( + height: height.h, + margin: EdgeInsets.symmetric(horizontal: 6.w), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(8.r), + image: DecorationImage(fit: BoxFit.fill, image: NetworkImage(image ?? '')), + ), + ); + }, + ), + ), + Visibility( + visible: (state?.length ?? 0) > 1, + child: Positioned( + bottom: 5, + child: Container( + height: 13.36, + padding: const EdgeInsets.symmetric(horizontal: 8), + margin: const EdgeInsets.symmetric(vertical: 12), + decoration: ShapeDecoration( + color: Colors.white38, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(9999)), + ), + child: SmoothPageIndicator( + controller: controller.pageController, // PageController + count: state?.length ?? 0, + effect: const WormEffect( + dotWidth: 6.0, + dotHeight: 6.0, + activeDotColor: Colors.white, + dotColor: Colors.white38, + ), // your preferred effect + onDotClicked: (index) { + controller.pageController.animateToPage( + index, + duration: const Duration(milliseconds: 500), + curve: Curves.easeIn, + ); + }, + ), + ), + ), + ), + ], + ), + onLoading: const Center(child: CupertinoActivityIndicator(color: AppColor.blueNormal)), + onError: (error) => Center(child: Text('خطا در بارگذاری اسلایدر: $error')), + ), + ); + } +} diff --git a/packages/core/lib/presentation/widget/widget.dart b/packages/core/lib/presentation/widget/widget.dart index 32b68cb..2564871 100644 --- a/packages/core/lib/presentation/widget/widget.dart +++ b/packages/core/lib/presentation/widget/widget.dart @@ -32,3 +32,4 @@ export 'tabs/new_tab.dart'; export 'tabs/r_segment.dart'; export 'tabs/tab.dart'; export 'vec_widget.dart'; +export 'slider/slider.dart'; \ No newline at end of file diff --git a/packages/core/lib/utils/number_utils.dart b/packages/core/lib/utils/number_utils.dart new file mode 100644 index 0000000..c44012f --- /dev/null +++ b/packages/core/lib/utils/number_utils.dart @@ -0,0 +1,13 @@ +import 'dart:math'; + +final _random = Random(); + + +int randomInt(int min, int max) { + return min + _random.nextInt(max - min + 1); +} + + +double randomDouble(double min, double max) { + return min + _random.nextDouble() * (max - min); +} \ No newline at end of file diff --git a/packages/core/lib/utils/utils.dart b/packages/core/lib/utils/utils.dart index 40b6ed5..cbb70e5 100644 --- a/packages/core/lib/utils/utils.dart +++ b/packages/core/lib/utils/utils.dart @@ -11,3 +11,4 @@ export 'network/network.dart'; export 'parser.dart'; export 'route_utils.dart'; export 'separator_input_formatter.dart'; +export 'number_utils.dart'; diff --git a/pubspec.lock b/pubspec.lock index 74f7cb2..c9af987 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1390,6 +1390,14 @@ packages: description: flutter source: sdk version: "0.0.0" + smooth_page_indicator: + dependency: transitive + description: + name: smooth_page_indicator + sha256: b21ebb8bc39cf72d11c7cfd809162a48c3800668ced1c9da3aade13a32cf6c1c + url: "https://pub.dev" + source: hosted + version: "1.2.1" source_gen: dependency: transitive description: