initialized Devices Page

This commit is contained in:
Mohammad Salameh
2024-02-20 16:01:50 +03:00
parent d27063f149
commit cdfb778884
22 changed files with 551 additions and 18 deletions
+80 -6
View File
@@ -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<DevicesState> {
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 = <DeviceModel>[];
var categories = <DevicesCategoryModel>[];
Future<List<DeviceModel>> getDevices() async {
Future<List<DevicesCategoryModel>> 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,
),
];
}
}
@@ -0,0 +1,27 @@
import 'device_model.dart';
class DevicesCategoryModel {
final String name;
final String icon;
final bool switchValue;
final List<DeviceModel> 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,
}
+14 -1
View File
@@ -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});
}
+2 -2
View File
@@ -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) {
@@ -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(),
],
),
)
],
),
);
}
}
@@ -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())
],
);
}
}
@@ -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<DevicesCubit, DevicesState>(
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'));
},
));
}
@@ -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,
)
],
),
);
},
);
}
}
@@ -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<bool> onChanged;
const CustomSwitch({super.key, required this.value, required this.onChanged});
@override
_CustomSwitchState createState() => _CustomSwitchState();
}
class _CustomSwitchState extends State<CustomSwitch>
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),
),
),
),
),
);
},
);
}
}
@@ -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,
);
}
}
@@ -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,
);
}
@@ -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,
);
}
@@ -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,
+1 -1
View File
@@ -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(
@@ -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 {
@@ -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';
}