mirror of
https://github.com/SyncrowIOT/syncrow-app.git
synced 2025-07-15 17:47:28 +00:00
initialized Splash UI
initialized Login UI initialized Home(no Devices) UI Added Colors (from syncrow website) Added Logo
This commit is contained in:
BIN
assets/images/black-logo.png
Normal file
BIN
assets/images/black-logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.5 KiB |
BIN
assets/images/box-empty.jpg
Normal file
BIN
assets/images/box-empty.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 208 KiB |
BIN
assets/images/white-logo.png
Normal file
BIN
assets/images/white-logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.1 KiB |
16
lib/features/auth/auth_provider.dart
Normal file
16
lib/features/auth/auth_provider.dart
Normal file
@ -0,0 +1,16 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:syncrow_app/features/auth/models/user_model.dart';
|
||||
|
||||
class AuthProvider extends ChangeNotifier {
|
||||
// todo remove temp user
|
||||
UserModel user = UserModel(
|
||||
id: '1',
|
||||
name: 'John Doe',
|
||||
email: '',
|
||||
photoUrl: '',
|
||||
isAgreementAccepted: false,
|
||||
isAnonymous: false,
|
||||
isEmailVerified: false,
|
||||
phoneNumber: '',
|
||||
);
|
||||
}
|
58
lib/features/auth/auth_view.dart
Normal file
58
lib/features/auth/auth_view.dart
Normal file
@ -0,0 +1,58 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:syncrow_app/features/home/widgets/syncrow_logo.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_text_button.dart';
|
||||
import 'package:syncrow_app/navigation/route_manager.dart';
|
||||
|
||||
import '../../navigation/routing_constants.dart';
|
||||
import 'auth_provider.dart';
|
||||
|
||||
class AuthPage extends StatelessWidget {
|
||||
const AuthPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ChangeNotifierProvider(
|
||||
create: (BuildContext context) => AuthProvider(),
|
||||
builder: (context, child) => Scaffold(
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 40.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
const Expanded(child: SizedBox()),
|
||||
const SyncrowLogo(),
|
||||
const Expanded(flex: 2, child: SizedBox()),
|
||||
DefaultTextButton(
|
||||
text: 'Login',
|
||||
onPressed: () {
|
||||
RouteManager().routerManagerPopAndPushNamed(
|
||||
routeName: Routes.homeRoute,
|
||||
context: context,
|
||||
);
|
||||
},
|
||||
isPrimary: true,
|
||||
),
|
||||
const Gap(15),
|
||||
const DefaultTextButton(text: 'Sign Up'),
|
||||
const Gap(20),
|
||||
Center(
|
||||
child: InkWell(
|
||||
onTap: () {},
|
||||
child: const Text(
|
||||
'Try as a Guest',
|
||||
style: TextStyle(
|
||||
color: Colors.grey,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const Gap(30),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
51
lib/features/auth/models/user_model.dart
Normal file
51
lib/features/auth/models/user_model.dart
Normal file
@ -0,0 +1,51 @@
|
||||
class UserModel {
|
||||
final String? id;
|
||||
final String? email;
|
||||
final String? name;
|
||||
final String? photoUrl;
|
||||
|
||||
final String? phoneNumber;
|
||||
|
||||
final bool? isAnonymous;
|
||||
|
||||
final bool? isEmailVerified;
|
||||
|
||||
final bool? isAgreementAccepted;
|
||||
|
||||
UserModel({
|
||||
required this.id,
|
||||
required this.email,
|
||||
required this.name,
|
||||
required this.photoUrl,
|
||||
required this.phoneNumber,
|
||||
required this.isAnonymous,
|
||||
required this.isEmailVerified,
|
||||
required this.isAgreementAccepted,
|
||||
});
|
||||
|
||||
factory UserModel.fromJson(Map<String, dynamic> json) {
|
||||
return UserModel(
|
||||
id: json['id'],
|
||||
email: json['email'],
|
||||
name: json['name'],
|
||||
photoUrl: json['photoUrl'],
|
||||
phoneNumber: json['phoneNumber'],
|
||||
isAnonymous: json['isAnonymous'],
|
||||
isEmailVerified: json['isEmailVerified'],
|
||||
isAgreementAccepted: json['isAgreementAccepted'],
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'id': id,
|
||||
'email': email,
|
||||
'name': name,
|
||||
'photoUrl': photoUrl,
|
||||
'phoneNumber': phoneNumber,
|
||||
'isAnonymous': isAnonymous,
|
||||
'isEmailVerified': isEmailVerified,
|
||||
'isAgreementAccepted': isAgreementAccepted,
|
||||
};
|
||||
}
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class AuthProvider extends ChangeNotifier {}
|
@ -1,22 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../provider/auth_provider.dart';
|
||||
|
||||
class AuthView extends StatelessWidget {
|
||||
const AuthView({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ChangeNotifierProvider(
|
||||
create: (BuildContext context) => AuthProvider(),
|
||||
builder: (context, child) => _buildPage(context),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildPage(BuildContext context) {
|
||||
final provider = context.read<AuthProvider>();
|
||||
|
||||
return Container();
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:syncrow_app/features/home/model/device_model.dart';
|
||||
import 'package:syncrow_app/features/profile/profile_view.dart';
|
||||
import 'package:syncrow_app/features/scene/scene_view.dart';
|
||||
import 'package:syncrow_app/features/smart/smart_view.dart';
|
||||
@ -16,12 +17,14 @@ class HomeProvider extends ChangeNotifier {
|
||||
|
||||
static int pageIndex = 0;
|
||||
|
||||
Future<List<String>> getDevices() async {
|
||||
var devices = <DeviceModel>[];
|
||||
|
||||
Future<List<DeviceModel>> getDevices() async {
|
||||
state.setLoading();
|
||||
await Future.delayed(const Duration(seconds: 2));
|
||||
state.setSuccess();
|
||||
notifyListeners();
|
||||
return <String>[];
|
||||
return devices = [];
|
||||
}
|
||||
|
||||
Map<String, List<Widget>> appBarActions = {
|
||||
@ -66,7 +69,7 @@ class HomeProvider extends ChangeNotifier {
|
||||
const ProfilePage(),
|
||||
];
|
||||
|
||||
Widget currentPage() {
|
||||
Widget getCurrentPage() {
|
||||
notifyListeners();
|
||||
|
||||
return pages[pageIndex];
|
||||
|
@ -18,7 +18,7 @@ class HomePage extends StatelessWidget {
|
||||
appBar: const DefaultAppBar(),
|
||||
body: provider.state.loading
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: provider.currentPage(),
|
||||
: provider.getCurrentPage(),
|
||||
bottomNavigationBar: const DefaultNavBar(),
|
||||
);
|
||||
},
|
||||
|
1
lib/features/home/model/device_model.dart
Normal file
1
lib/features/home/model/device_model.dart
Normal file
@ -0,0 +1 @@
|
||||
class DeviceModel {}
|
@ -1,5 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:syncrow_app/features/home/widgets/syncrow_logo.dart';
|
||||
import 'package:syncrow_app/resource_manager/color_manager.dart';
|
||||
|
||||
import '../home_provider.dart';
|
||||
|
||||
@ -11,14 +13,15 @@ class DefaultAppBar extends StatelessWidget implements PreferredSizeWidget {
|
||||
return Consumer<HomeProvider>(
|
||||
builder: (context, provider, child) {
|
||||
return AppBar(
|
||||
title: const Text('Syncrow'),
|
||||
title: const SyncrowLogo(),
|
||||
actions: <Widget>[
|
||||
IconButton(
|
||||
icon: const Icon(Icons.mic),
|
||||
onPressed: () {},
|
||||
),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.add_circle),
|
||||
icon: const Icon(Icons.add_circle,
|
||||
color: ColorsManager.primaryColor),
|
||||
onPressed: () {},
|
||||
),
|
||||
],
|
||||
|
@ -1,4 +1,9 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:syncrow_app/features/home/home_provider.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_text_button.dart';
|
||||
import 'package:syncrow_app/resource_manager/assets_manager.dart';
|
||||
|
||||
class HomeViewBody extends StatelessWidget {
|
||||
const HomeViewBody({
|
||||
@ -7,8 +12,40 @@ class HomeViewBody extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return const Center(
|
||||
child: Text('Home'),
|
||||
return ChangeNotifierProvider(
|
||||
create: (BuildContext context) => HomeProvider(),
|
||||
child: Consumer<HomeProvider>(
|
||||
builder: (context, provider, child) {
|
||||
return provider.devices.isEmpty
|
||||
? Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Image.asset(
|
||||
ImageManager.boxEmpty,
|
||||
opacity: const AlwaysStoppedAnimation(0.5),
|
||||
scale: 1,
|
||||
width: 140,
|
||||
),
|
||||
const Gap(15),
|
||||
const Text(
|
||||
'No Devices',
|
||||
style: TextStyle(
|
||||
color: Colors.grey,
|
||||
fontSize: 18,
|
||||
),
|
||||
),
|
||||
const Gap(15),
|
||||
const DefaultTextButton(
|
||||
text: 'Add Device',
|
||||
isPrimary: true,
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
: const SizedBox();
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
20
lib/features/home/widgets/syncrow_logo.dart
Normal file
20
lib/features/home/widgets/syncrow_logo.dart
Normal file
@ -0,0 +1,20 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:syncrow_app/resource_manager/assets_manager.dart';
|
||||
|
||||
class SyncrowLogo extends StatelessWidget {
|
||||
const SyncrowLogo({
|
||||
super.key,
|
||||
this.isDark = true,
|
||||
this.width = 150,
|
||||
});
|
||||
|
||||
final bool isDark;
|
||||
|
||||
final double width;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Image.asset(isDark ? ImageManager.blackLogo : ImageManager.whiteLogo,
|
||||
scale: 1, width: width);
|
||||
}
|
||||
}
|
38
lib/features/shared_widgets/default_text_button.dart
Normal file
38
lib/features/shared_widgets/default_text_button.dart
Normal file
@ -0,0 +1,38 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:syncrow_app/resource_manager/color_manager.dart';
|
||||
|
||||
class DefaultTextButton extends StatelessWidget {
|
||||
const DefaultTextButton({
|
||||
super.key,
|
||||
this.onPressed,
|
||||
required this.text,
|
||||
this.isPrimary = false,
|
||||
});
|
||||
|
||||
final void Function()? onPressed;
|
||||
final String text;
|
||||
|
||||
final bool isPrimary;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return TextButton(
|
||||
onPressed: onPressed,
|
||||
style: isPrimary
|
||||
? ButtonStyle(
|
||||
backgroundColor:
|
||||
MaterialStateProperty.all(ColorsManager.primaryColor),
|
||||
shape: MaterialStateProperty.all(
|
||||
RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
),
|
||||
)
|
||||
: null,
|
||||
child: Text(
|
||||
text,
|
||||
style: TextStyle(color: isPrimary ? Colors.white : Colors.black),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,12 +1,21 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:syncrow_app/features/splash/user_agreement_dialog.dart';
|
||||
import 'package:syncrow_app/navigation/route_manager.dart';
|
||||
import 'package:syncrow_app/navigation/routing_constants.dart';
|
||||
import 'package:syncrow_app/resource_manager/assets_manager.dart';
|
||||
|
||||
class SplashView extends StatelessWidget {
|
||||
const SplashView({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
//TODO Remove delay
|
||||
// Future.delayed(const Duration(seconds: 5), () {
|
||||
// RouteManager().routerManagerPushUntil(
|
||||
// context,
|
||||
// routeName: Routes.homeRoute,
|
||||
// );
|
||||
// });
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
actions: [
|
||||
@ -14,15 +23,23 @@ class SplashView extends StatelessWidget {
|
||||
icon: const Icon(Icons.arrow_forward),
|
||||
onPressed: () {
|
||||
RouteManager().routerManagerPopAndPushNamed(
|
||||
routeName: Routes.homeRoute,
|
||||
routeName: Routes.authRoute,
|
||||
context: context,
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
body: const Center(
|
||||
child: Text('Splash Screen'),
|
||||
body: Center(
|
||||
child: InkWell(
|
||||
//TODO check if user agreement is accepted
|
||||
onTap: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => const UserAgreementDialog(),
|
||||
);
|
||||
},
|
||||
child: Image.asset(ImageManager.blackLogo)),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
31
lib/features/splash/user_agreement_dialog.dart
Normal file
31
lib/features/splash/user_agreement_dialog.dart
Normal file
@ -0,0 +1,31 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:syncrow_app/features/shared_widgets/default_text_button.dart';
|
||||
|
||||
class UserAgreementDialog extends StatelessWidget {
|
||||
const UserAgreementDialog({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AlertDialog(
|
||||
elevation: 40,
|
||||
title: const Text('User Agreement'),
|
||||
content:
|
||||
const Text('By using this app you agree to the terms and conditions'),
|
||||
actions: [
|
||||
DefaultTextButton(
|
||||
text: 'I Agree',
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
isPrimary: true,
|
||||
),
|
||||
DefaultTextButton(
|
||||
text: 'I Disagree',
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
@ -1,8 +1,9 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:syncrow_app/resource_manager/color_manager.dart';
|
||||
|
||||
import 'features/auth/provider/auth_provider.dart';
|
||||
import 'features/auth/auth_provider.dart';
|
||||
import 'navigation/router.dart' as router;
|
||||
import 'navigation/routing_constants.dart';
|
||||
import 'services/navigation_service.dart';
|
||||
@ -33,7 +34,7 @@ class _MyAppState extends State<MyApp> {
|
||||
debugShowCheckedModeBanner: false,
|
||||
navigatorKey: NavigationService.navigatorKey,
|
||||
scaffoldMessengerKey: NavigationService.snackbarKey,
|
||||
color: Colors.white,
|
||||
color: ColorsManager.primaryColor,
|
||||
title: 'Syncrow App',
|
||||
onGenerateRoute: router.Router.generateRoute,
|
||||
initialRoute: Routes.splash,
|
||||
|
@ -1,4 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:syncrow_app/features/auth/auth_view.dart';
|
||||
import 'package:syncrow_app/features/home/home_view.dart';
|
||||
import 'package:syncrow_app/features/profile/profile_view.dart';
|
||||
import 'package:syncrow_app/features/scene/scene_view.dart';
|
||||
@ -30,6 +31,10 @@ class Router {
|
||||
return MaterialPageRoute(
|
||||
builder: (_) => const SmartPage(), settings: settings);
|
||||
|
||||
case Routes.authRoute:
|
||||
return MaterialPageRoute(
|
||||
builder: (_) => const AuthPage(), settings: settings);
|
||||
|
||||
default:
|
||||
return MaterialPageRoute(
|
||||
builder: (_) => Scaffold(
|
||||
|
@ -4,4 +4,5 @@ class Routes {
|
||||
static const String sceneRoute = '/scene';
|
||||
static const String smartRoute = '/smart';
|
||||
static const String profileRoute = '/profile';
|
||||
static const String authRoute = '/auth';
|
||||
}
|
||||
|
@ -1,13 +1,15 @@
|
||||
class ImagesAssets {
|
||||
// static const String base = 'assets/images/';
|
||||
class ImageManager {
|
||||
static const String base = 'assets/images';
|
||||
|
||||
// static const String bigLightLogo = '$base/image.png';
|
||||
static const String whiteLogo = '$base/white-logo.png';
|
||||
static const String blackLogo = '$base/black-logo.png';
|
||||
static const String boxEmpty = '$base/box-empty.jpg';
|
||||
}
|
||||
|
||||
class IconsAssets {
|
||||
class IconsManager {
|
||||
// static const String facebookIcon = 'assets/icons/icon.png';
|
||||
}
|
||||
|
||||
class VideosAssets {
|
||||
class VideosManager {
|
||||
// static const String registrationVideo = 'assets/videos/video.mp4';
|
||||
}
|
||||
|
@ -1,53 +1,9 @@
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class ColorsManager {
|
||||
// static const Color primaryLightColor = Color(0xFF3a96db);
|
||||
// static const Color onPrimaryLightColor = Color(0xFFFFFFFF);
|
||||
static const Color primaryColor = Color(0xFF023dfe);
|
||||
static const Color secondaryColor = Colors.white;
|
||||
static const Color primaryTextColor = Colors.black;
|
||||
|
||||
// static const Color primaryDarkColor = Color(0xFF24588d);
|
||||
// static const Color onPrimaryDarkColor = Color(0xFFFFFFFF);
|
||||
|
||||
// static const Color secondaryLightColor = Color(0xFFFFFFFF);
|
||||
// static const Color onSecondaryLightColor = Color(0xFF4D4E56);
|
||||
|
||||
// static const Color secondaryDarkColor = Color(0xFF4D4E56);
|
||||
// static const Color onSecondaryDarkColor = Color(0xFFFFFFFF);
|
||||
|
||||
// static const Color thirdDarkColor = Color(0xFFE0E6ED);
|
||||
// static const Color onThirdDarkColor = Color(0xFF4D4E56);
|
||||
|
||||
// static const Color errorColor = Color(0xFFff4c4c);
|
||||
// static const Color onErrorColor = Color(0xFFFFFFFF);
|
||||
|
||||
// static const Color textColor = Colors.black;
|
||||
// static const Color textColorGrey = Colors.grey;
|
||||
// static const Color textColorLight = Colors.white;
|
||||
|
||||
// static const lightColorScheme = ColorScheme(
|
||||
// brightness: Brightness.light,
|
||||
// primary: ColorsManager.primaryLightColor,
|
||||
// onPrimary: ColorsManager.onPrimaryLightColor,
|
||||
// secondary: ColorsManager.secondaryLightColor,
|
||||
// onSecondary: ColorsManager.onSecondaryLightColor,
|
||||
// error: ColorsManager.errorColor,
|
||||
// onError: ColorsManager.onErrorColor,
|
||||
// background: Colors.white,
|
||||
// onBackground: Colors.black,
|
||||
// surface: Colors.white,
|
||||
// onSurface: Colors.black,
|
||||
// );
|
||||
|
||||
// static const darkColorScheme = ColorScheme(
|
||||
// brightness: Brightness.dark,
|
||||
// primary: ColorsManager.primaryDarkColor,
|
||||
// onPrimary: ColorsManager.onPrimaryDarkColor,
|
||||
// secondary: ColorsManager.secondaryDarkColor,
|
||||
// onSecondary: ColorsManager.onSecondaryDarkColor,
|
||||
// error: ColorsManager.errorColor,
|
||||
// onError: ColorsManager.onErrorColor,
|
||||
// background: secondaryDarkColor,
|
||||
// onBackground: onSecondaryDarkColor,
|
||||
// surface: secondaryDarkColor,
|
||||
// onSurface: onSecondaryDarkColor,
|
||||
// );
|
||||
static const Color greyColor = Color(0xFFd9d9d9);
|
||||
}
|
||||
|
@ -301,6 +301,14 @@ packages:
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
gap:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: gap
|
||||
sha256: f19387d4e32f849394758b91377f9153a1b41d79513ef7668c088c77dbc6955d
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.1"
|
||||
get_it:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -17,6 +17,7 @@ dependencies:
|
||||
cupertino_icons: ^1.0.6
|
||||
shared_preferences: ^2.2.2
|
||||
flutter_animated_dialog: ^2.0.1
|
||||
gap: ^3.0.1
|
||||
|
||||
# Utility Packages
|
||||
flutter_secure_storage: ^9.0.0
|
||||
|
Reference in New Issue
Block a user