diff --git a/assets/icons/AC.svg b/assets/icons/AC.svg
new file mode 100644
index 0000000..92f6fc5
--- /dev/null
+++ b/assets/icons/AC.svg
@@ -0,0 +1,14 @@
+
diff --git a/assets/icons/Curtain.svg b/assets/icons/Curtain.svg
new file mode 100644
index 0000000..a2e4f23
--- /dev/null
+++ b/assets/icons/Curtain.svg
@@ -0,0 +1,17 @@
+
diff --git a/assets/icons/Door Lock.svg b/assets/icons/Door Lock.svg
new file mode 100644
index 0000000..6f27673
--- /dev/null
+++ b/assets/icons/Door Lock.svg
@@ -0,0 +1,24 @@
+
diff --git a/assets/icons/Gateway.svg b/assets/icons/Gateway.svg
new file mode 100644
index 0000000..e293999
--- /dev/null
+++ b/assets/icons/Gateway.svg
@@ -0,0 +1,19 @@
+
diff --git a/assets/icons/Light.svg b/assets/icons/Light.svg
new file mode 100644
index 0000000..c8cfff5
--- /dev/null
+++ b/assets/icons/Light.svg
@@ -0,0 +1,15 @@
+
diff --git a/assets/icons/Screen.svg b/assets/icons/Screen.svg
new file mode 100644
index 0000000..cc0cd8f
--- /dev/null
+++ b/assets/icons/Screen.svg
@@ -0,0 +1,10 @@
+
diff --git a/lib/features/devices/bloc/devices_cubit.dart b/lib/features/devices/bloc/devices_cubit.dart
index 8062933..abc23cb 100644
--- a/lib/features/devices/bloc/devices_cubit.dart
+++ b/lib/features/devices/bloc/devices_cubit.dart
@@ -1,25 +1,99 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:syncrow_app/utils/resource_manager/assets_manager.dart';
-import '../model/device_model.dart';
+import '../model/device_category_model.dart';
part 'devices_state.dart';
class DevicesCubit extends Cubit {
DevicesCubit() : super(DevicesInitial()) {
- getDevices();
+ getCategories();
+ }
+
+ bool ACSwitchValue = false;
+ bool lightsSwitchValue = false;
+ bool doorSwitchValue = false;
+ bool curtainSwitchValue = false;
+ bool screensSwitchValue = false;
+ bool gatewaySwitchValue = false;
+
+ void changeSwitchValue(DeviceType device) {
+ switch (device) {
+ case DeviceType.AC:
+ ACSwitchValue = !ACSwitchValue;
+ break;
+ case DeviceType.Lights:
+ lightsSwitchValue = !lightsSwitchValue;
+ break;
+ case DeviceType.Door:
+ doorSwitchValue = !doorSwitchValue;
+ break;
+ case DeviceType.Curtain:
+ curtainSwitchValue = !curtainSwitchValue;
+ break;
+ case DeviceType.Screens:
+ screensSwitchValue = !screensSwitchValue;
+ break;
+ case DeviceType.Gateway:
+ gatewaySwitchValue = !gatewaySwitchValue;
+ break;
+ }
+ emit(DevicesSuccess());
}
- //TODO separate the navigation logic to another cubit
static DevicesCubit get(context) => BlocProvider.of(context);
- var devices = [];
+ var categories = [];
- Future> getDevices() async {
+ Future> getCategories() async {
emit(DevicesLoading());
await Future.delayed(const Duration(seconds: 2));
emit(DevicesSuccess());
- return devices = [];
+ return categories = [
+ DevicesCategoryModel(
+ devices: [],
+ icon: IconsManager.ac,
+ name: 'ACs',
+ switchValue: false,
+ type: DeviceType.AC,
+ ),
+ DevicesCategoryModel(
+ devices: [],
+ icon: IconsManager.light,
+ name: 'Lights',
+ switchValue: false,
+ type: DeviceType.Lights,
+ ),
+ DevicesCategoryModel(
+ devices: [],
+ icon: IconsManager.doorLock,
+ name: 'Doors',
+ switchValue: false,
+ type: DeviceType.Door,
+ ),
+ DevicesCategoryModel(
+ devices: [],
+ icon: IconsManager.curtain,
+ name: 'Curtains',
+ switchValue: false,
+ type: DeviceType.Curtain,
+ ),
+ DevicesCategoryModel(
+ devices: [],
+ icon: IconsManager.screen,
+ name: 'Screens',
+ switchValue: false,
+ type: DeviceType.Screens,
+ ),
+ DevicesCategoryModel(
+ devices: [],
+ icon: IconsManager.gateway,
+ name: 'Gateway',
+ switchValue: false,
+ type: DeviceType.Gateway,
+ ),
+ ];
}
}
diff --git a/lib/features/devices/model/device_category_model.dart b/lib/features/devices/model/device_category_model.dart
new file mode 100644
index 0000000..6197f26
--- /dev/null
+++ b/lib/features/devices/model/device_category_model.dart
@@ -0,0 +1,27 @@
+import 'device_model.dart';
+
+class DevicesCategoryModel {
+ final String name;
+ final String icon;
+
+ final bool switchValue;
+ final List devices;
+
+ final DeviceType type;
+
+ DevicesCategoryModel(
+ {required this.type,
+ required this.name,
+ required this.icon,
+ required this.switchValue,
+ required this.devices});
+}
+
+enum DeviceType {
+ AC,
+ Lights,
+ Door,
+ Curtain,
+ Screens,
+ Gateway,
+}
diff --git a/lib/features/devices/model/device_model.dart b/lib/features/devices/model/device_model.dart
index 75dba0d..37ee98e 100644
--- a/lib/features/devices/model/device_model.dart
+++ b/lib/features/devices/model/device_model.dart
@@ -1 +1,14 @@
-class DeviceModel {}
+class DeviceModel {
+ final String name;
+ final String imageUrl;
+ final String description;
+ final String category;
+ final String id;
+
+ DeviceModel(
+ {required this.name,
+ required this.imageUrl,
+ required this.description,
+ required this.category,
+ required this.id});
+}
diff --git a/lib/features/devices/view/devices_view.dart b/lib/features/devices/view/devices_view.dart
index e46862d..00f315d 100644
--- a/lib/features/devices/view/devices_view.dart
+++ b/lib/features/devices/view/devices_view.dart
@@ -3,8 +3,8 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart';
import 'package:syncrow_app/features/devices/view/widgets/devices_view_body.dart';
-class DevicesView extends StatelessWidget {
- const DevicesView({super.key});
+class CategoriesView extends StatelessWidget {
+ const CategoriesView({super.key});
@override
Widget build(BuildContext context) {
diff --git a/lib/features/devices/view/widgets/categories_view.dart b/lib/features/devices/view/widgets/categories_view.dart
new file mode 100644
index 0000000..4a21ee9
--- /dev/null
+++ b/lib/features/devices/view/widgets/categories_view.dart
@@ -0,0 +1,53 @@
+import 'package:flutter/material.dart';
+import 'package:syncrow_app/features/devices/view/widgets/devices_mode_tab.dart';
+import 'package:syncrow_app/features/devices/view/widgets/switches.dart';
+import 'package:syncrow_app/features/shared_widgets/text_widgets/title_medium.dart';
+import 'package:syncrow_app/utils/resource_manager/strings_manager.dart';
+
+class CategoriesView extends StatelessWidget {
+ const CategoriesView({
+ super.key,
+ });
+
+ @override
+ Widget build(BuildContext context) {
+ return const Padding(
+ padding: EdgeInsets.only(top: 60, right: 15, left: 15, bottom: 100),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Expanded(
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ TitleMedium(
+ text: StringsManager.devices,
+ style: TextStyle(
+ fontSize: 32,
+ fontWeight: FontWeight.bold,
+ ),
+ ),
+ DevicesModeTab(),
+ ],
+ ),
+ ),
+ Expanded(
+ flex: 3,
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ TitleMedium(
+ text: StringsManager.wizard,
+ style: TextStyle(
+ fontSize: 28,
+ ),
+ ),
+ Switches(),
+ ],
+ ),
+ )
+ ],
+ ),
+ );
+ }
+}
diff --git a/lib/features/devices/view/widgets/devices_mode_tab.dart b/lib/features/devices/view/widgets/devices_mode_tab.dart
new file mode 100644
index 0000000..77c1145
--- /dev/null
+++ b/lib/features/devices/view/widgets/devices_mode_tab.dart
@@ -0,0 +1,78 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_svg/flutter_svg.dart';
+import 'package:gap/gap.dart';
+import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
+import 'package:syncrow_app/utils/resource_manager/assets_manager.dart';
+import 'package:syncrow_app/utils/resource_manager/strings_manager.dart';
+
+class DevicesModeTab extends StatelessWidget {
+ const DevicesModeTab({
+ super.key,
+ });
+
+ @override
+ Widget build(BuildContext context) {
+ return Row(
+ mainAxisAlignment: MainAxisAlignment.start,
+ children: [
+ Container(
+ decoration: BoxDecoration(
+ color: Colors.white,
+ borderRadius: BorderRadius.circular(20),
+ ),
+ padding: const EdgeInsets.all(10),
+ margin: const EdgeInsets.only(right: 5),
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.start,
+ crossAxisAlignment: CrossAxisAlignment.center,
+ children: [
+ SizedBox(
+ height: 30,
+ width: 25,
+ child: SvgPicture.asset(
+ IconsManager.winter,
+ fit: BoxFit.contain,
+ ),
+ ),
+ const Gap(5),
+ const BodySmall(
+ text: StringsManager.winter,
+ fontWeight: FontWeight.bold,
+ fontColor: Colors.grey,
+ ),
+ ],
+ ),
+ ),
+ Container(
+ decoration: BoxDecoration(
+ color: Colors.white,
+ borderRadius: BorderRadius.circular(20),
+ ),
+ padding: const EdgeInsets.all(10),
+ margin: const EdgeInsets.only(right: 5),
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.start,
+ crossAxisAlignment: CrossAxisAlignment.center,
+ children: [
+ SizedBox(
+ height: 30,
+ width: 25,
+ child: SvgPicture.asset(
+ IconsManager.summer,
+ fit: BoxFit.contain,
+ ),
+ ),
+ const Gap(5),
+ const BodySmall(
+ text: StringsManager.summer,
+ fontWeight: FontWeight.bold,
+ fontColor: Colors.grey,
+ ),
+ ],
+ ),
+ ),
+ const Expanded(child: SizedBox.shrink())
+ ],
+ );
+ }
+}
diff --git a/lib/features/devices/view/widgets/devices_view_body.dart b/lib/features/devices/view/widgets/devices_view_body.dart
index 06fb86e..7f41859 100644
--- a/lib/features/devices/view/widgets/devices_view_body.dart
+++ b/lib/features/devices/view/widgets/devices_view_body.dart
@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:syncrow_app/features/devices/view/widgets/categories_view.dart';
import '../../bloc/devices_cubit.dart';
import 'no_devices_view.dart';
@@ -15,9 +16,13 @@ class DevicesViewBody extends StatelessWidget {
create: (context) => DevicesCubit(),
child: BlocBuilder(
builder: (context, state) {
- return DevicesCubit.get(context).devices.isEmpty
- ? const NoDevicesView()
- : const SizedBox();
+ return state is DevicesLoading
+ ? const Center(child: CircularProgressIndicator())
+ : state is DevicesSuccess
+ ? DevicesCubit.get(context).categories.isEmpty
+ ? const NoDevicesView()
+ : const CategoriesView()
+ : const Center(child: Text('Error'));
},
));
}
diff --git a/lib/features/devices/view/widgets/switches.dart b/lib/features/devices/view/widgets/switches.dart
new file mode 100644
index 0000000..08bb3df
--- /dev/null
+++ b/lib/features/devices/view/widgets/switches.dart
@@ -0,0 +1,65 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_svg/svg.dart';
+import 'package:syncrow_app/features/shared_widgets/custom_switch.dart';
+import 'package:syncrow_app/features/shared_widgets/default_container.dart';
+import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
+
+import '../../bloc/devices_cubit.dart';
+
+class Switches extends StatelessWidget {
+ const Switches({
+ super.key,
+ });
+
+ @override
+ Widget build(BuildContext context) {
+ return GridView.builder(
+ gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
+ crossAxisCount: 2,
+ crossAxisSpacing: 10,
+ mainAxisSpacing: 10,
+ childAspectRatio: 1.5,
+ ),
+ padding: const EdgeInsets.only(top: 10),
+ physics: const NeverScrollableScrollPhysics(),
+ shrinkWrap: true,
+ itemCount: DevicesCubit.get(context).categories.length,
+ itemBuilder: (context, index) {
+ return DefaultContainer(
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Row(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ SvgPicture.asset(
+ DevicesCubit.get(context).categories[index].icon,
+ fit: BoxFit.contain,
+ ),
+ SizedBox(
+ width: 30,
+ height: 20,
+ child: CustomSwitch(
+ value: DevicesCubit.get(context)
+ .categories[index]
+ .switchValue,
+ onChanged: (value) => DevicesCubit.get(context)
+ .changeSwitchValue(
+ DevicesCubit.get(context).categories[index].type),
+ ),
+ ),
+ ],
+ ),
+ BodyLarge(
+ text: DevicesCubit.get(context).categories[index].name,
+ fontWeight: FontWeight.bold,
+ )
+ ],
+ ),
+ );
+ },
+ );
+ }
+}
diff --git a/lib/features/shared_widgets/custom_switch.dart b/lib/features/shared_widgets/custom_switch.dart
new file mode 100644
index 0000000..d7bba55
--- /dev/null
+++ b/lib/features/shared_widgets/custom_switch.dart
@@ -0,0 +1,77 @@
+import 'package:flutter/material.dart';
+import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
+
+class CustomSwitch extends StatefulWidget {
+ final bool value;
+ final ValueChanged onChanged;
+
+ const CustomSwitch({super.key, required this.value, required this.onChanged});
+
+ @override
+ _CustomSwitchState createState() => _CustomSwitchState();
+}
+
+class _CustomSwitchState extends State
+ with SingleTickerProviderStateMixin {
+ Animation? _circleAnimation;
+ AnimationController? _animationController;
+
+ @override
+ void initState() {
+ super.initState();
+ _animationController = AnimationController(
+ vsync: this, duration: const Duration(milliseconds: 100));
+ _circleAnimation = AlignmentTween(
+ begin: widget.value ? Alignment.centerRight : Alignment.centerLeft,
+ end: widget.value ? Alignment.centerLeft : Alignment.centerRight)
+ .animate(CurvedAnimation(
+ parent: _animationController!, curve: Curves.linear));
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return AnimatedBuilder(
+ animation: _animationController!,
+ builder: (context, child) {
+ return GestureDetector(
+ onTap: () {
+ _animationController!.isCompleted
+ ? _animationController!.reverse()
+ : _animationController!.forward();
+ widget.value == false
+ ? widget.onChanged(true)
+ : widget.onChanged(false);
+ },
+ child: Container(
+ width: 45.0,
+ height: 28.0,
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.circular(24.0),
+ color: _circleAnimation!.value == Alignment.centerLeft
+ ? Colors.grey
+ : ColorsManager.primaryColor,
+ ),
+ child: Padding(
+ padding: const EdgeInsets.all(2.0),
+ child: Container(
+ alignment: widget.value
+ ? ((Directionality.of(context) == TextDirection.rtl)
+ ? Alignment.centerRight
+ : Alignment.centerLeft)
+ : ((Directionality.of(context) == TextDirection.rtl)
+ ? Alignment.centerLeft
+ : Alignment.centerRight),
+ child: Container(
+ width: 20.0,
+ height: 20.0,
+ decoration: const BoxDecoration(
+ shape: BoxShape.circle, color: Colors.white),
+ ),
+ ),
+ ),
+ ),
+ );
+ },
+ );
+ }
+}
diff --git a/lib/features/shared_widgets/default_container.dart b/lib/features/shared_widgets/default_container.dart
new file mode 100644
index 0000000..53b3ee0
--- /dev/null
+++ b/lib/features/shared_widgets/default_container.dart
@@ -0,0 +1,22 @@
+import 'package:flutter/material.dart';
+
+class DefaultContainer extends StatelessWidget {
+ const DefaultContainer({
+ super.key,
+ required this.child,
+ });
+
+ final Widget child;
+
+ @override
+ Widget build(BuildContext context) {
+ return Container(
+ decoration: BoxDecoration(
+ color: Colors.white,
+ borderRadius: BorderRadius.circular(20),
+ ),
+ padding: const EdgeInsets.all(10),
+ child: child,
+ );
+ }
+}
diff --git a/lib/features/shared_widgets/text_widgets/body_large.dart b/lib/features/shared_widgets/text_widgets/body_large.dart
index 471dbbb..18a1447 100644
--- a/lib/features/shared_widgets/text_widgets/body_large.dart
+++ b/lib/features/shared_widgets/text_widgets/body_large.dart
@@ -10,6 +10,7 @@ class BodyLarge extends StatelessWidget {
this.textAlign,
this.style,
this.height,
+ this.fontWeight,
});
final String text;
@@ -19,10 +20,13 @@ class BodyLarge extends StatelessWidget {
final double? height;
+ final FontWeight? fontWeight;
+
@override
Widget build(BuildContext context) => CustomText(
text,
style: style ?? context.bodyLarge.copyWith(height: height ?? 1.5),
textAlign: textAlign,
+ fontWeight: fontWeight,
);
}
diff --git a/lib/features/shared_widgets/text_widgets/body_small.dart b/lib/features/shared_widgets/text_widgets/body_small.dart
index 2cf842d..f784dc7 100644
--- a/lib/features/shared_widgets/text_widgets/body_small.dart
+++ b/lib/features/shared_widgets/text_widgets/body_small.dart
@@ -9,6 +9,7 @@ class BodySmall extends StatelessWidget {
this.style,
this.fontColor,
this.fontSize,
+ this.fontWeight,
});
final String text;
@@ -17,6 +18,7 @@ class BodySmall extends StatelessWidget {
final Color? fontColor;
final double? fontSize;
+ final FontWeight? fontWeight;
@override
Widget build(BuildContext context) => CustomText(
@@ -24,5 +26,6 @@ class BodySmall extends StatelessWidget {
style: style ?? context.bodySmall,
fontColor: fontColor,
fontSize: fontSize,
+ fontWeight: fontWeight,
);
}
diff --git a/lib/features/shared_widgets/text_widgets/custom_text_widget.dart b/lib/features/shared_widgets/text_widgets/custom_text_widget.dart
index 2d886f0..c0b7c5b 100644
--- a/lib/features/shared_widgets/text_widgets/custom_text_widget.dart
+++ b/lib/features/shared_widgets/text_widgets/custom_text_widget.dart
@@ -11,7 +11,8 @@ class CustomText extends StatelessWidget {
this.maxLines,
this.textDirection,
this.fontSize,
- this.fontColor});
+ this.fontColor,
+ this.fontWeight});
final String text;
final TextStyle? style;
@@ -24,14 +25,16 @@ class CustomText extends StatelessWidget {
final double? fontSize;
final Color? fontColor;
+ final FontWeight? fontWeight;
+
@override
Widget build(BuildContext context) {
return SelectableText(
text,
style: style!.copyWith(
- fontSize: fontSize,
- color: fontColor ?? ColorsManager.textPrimaryColor,
- ),
+ fontSize: fontSize,
+ color: fontColor ?? ColorsManager.textPrimaryColor,
+ fontWeight: fontWeight),
textAlign: textAlign,
onTap: onTap,
minLines: minLines,
diff --git a/lib/navigation/router.dart b/lib/navigation/router.dart
index 5a13864..0836b18 100644
--- a/lib/navigation/router.dart
+++ b/lib/navigation/router.dart
@@ -19,7 +19,7 @@ class Router {
case Routes.devicesRoute:
return MaterialPageRoute(
- builder: (_) => const DevicesView(), settings: settings);
+ builder: (_) => const CategoriesView(), settings: settings);
case Routes.profileRoute:
return MaterialPageRoute(
diff --git a/lib/utils/resource_manager/assets_manager.dart b/lib/utils/resource_manager/assets_manager.dart
index 0b469b4..217d4ed 100644
--- a/lib/utils/resource_manager/assets_manager.dart
+++ b/lib/utils/resource_manager/assets_manager.dart
@@ -30,12 +30,18 @@ abstract class IconsManager {
static const String layout = '$base/Layout.svg';
static const String layoutFill = '$base/Layout-fill.svg';
static const String frequency = '$base/frequency.svg';
- static const String winter = '$base/winter.svg';
+ static const String winter = '$base/Winter.svg';
static const String active = '$base/active.svg';
static const String voltMeter = '$base/volt-meter.svg';
static const String summer = '$base/Summer.svg';
static const String CO2 = '$base/CO2.svg';
static const String sustainability = '$base/sustainability.svg';
+ static const String ac = '$base/AC.svg';
+ static const String curtain = '$base/Curtain.svg';
+ static const String doorLock = '$base/Door Lock.svg';
+ static const String gateway = '$base/Gateway.svg';
+ static const String light = '$base/Light.svg';
+ static const String screen = '$base/Screen.svg';
}
abstract class VideosManager {
diff --git a/lib/utils/resource_manager/strings_manager.dart b/lib/utils/resource_manager/strings_manager.dart
index 31dd807..539a924 100644
--- a/lib/utils/resource_manager/strings_manager.dart
+++ b/lib/utils/resource_manager/strings_manager.dart
@@ -5,6 +5,8 @@ class StringsManager {
static const noInternetConnection = 'No internet connection';
static const dashboard = 'Dashboard';
+ static const devices = 'Devices';
+ static const wizard = 'Wizard';
static const active = 'Active';
static const current = 'Current';
static const frequency = 'Frequency';
@@ -14,4 +16,6 @@ class StringsManager {
static const units = 'Units';
static const emissions = 'Emissions';
static const reductions = 'Reductions';
+ static const winter = 'Winter';
+ static const summer = 'Summer';
}