initialized Splash UI

initialized Login UI
initialized Home(no Devices) UI
Added Colors (from syncrow website)
Added Logo
This commit is contained in:
Mohammad Salameh
2024-02-15 00:10:33 +03:00
parent 3385ed1297
commit 16f47f744c
24 changed files with 316 additions and 92 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

BIN
assets/images/box-empty.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View 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: '',
);
}

View 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),
],
),
),
),
);
}
}

View 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,
};
}
}

View File

@ -1,3 +0,0 @@
import 'package:flutter/material.dart';
class AuthProvider extends ChangeNotifier {}

View File

@ -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();
}
}

View File

@ -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];

View File

@ -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(),
);
},

View File

@ -0,0 +1 @@
class DeviceModel {}

View File

@ -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: () {},
),
],

View File

@ -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();
},
),
);
}
}

View 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);
}
}

View 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),
),
);
}
}

View File

@ -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)),
),
);
}

View 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(),
),
],
);
}
}

View File

@ -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,

View File

@ -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(

View File

@ -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';
}

View File

@ -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';
}

View File

@ -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);
}

View File

@ -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:

View File

@ -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