diff --git a/assets/images/Background.png b/assets/images/Background.png new file mode 100644 index 00000000..02529ba3 Binary files /dev/null and b/assets/images/Background.png differ diff --git a/assets/images/Logo.svg b/assets/images/Logo.svg new file mode 100644 index 00000000..0a592c03 --- /dev/null +++ b/assets/images/Logo.svg @@ -0,0 +1,38 @@ + + + diff --git a/assets/images/Vector.png b/assets/images/Vector.png new file mode 100644 index 00000000..c105e7e3 Binary files /dev/null and b/assets/images/Vector.png differ diff --git a/assets/images/black-logo.png b/assets/images/black-logo.png new file mode 100644 index 00000000..0d42805c Binary files /dev/null and b/assets/images/black-logo.png differ diff --git a/assets/images/login_logo.svg b/assets/images/login_logo.svg new file mode 100644 index 00000000..0e5f7681 --- /dev/null +++ b/assets/images/login_logo.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/assets/images/logo_horizontal.png b/assets/images/logo_horizontal.png new file mode 100644 index 00000000..2d29681a Binary files /dev/null and b/assets/images/logo_horizontal.png differ diff --git a/assets/images/web_Background.svg b/assets/images/web_Background.svg new file mode 100644 index 00000000..11c967e0 --- /dev/null +++ b/assets/images/web_Background.svg @@ -0,0 +1,323 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/white-logo.png b/assets/images/white-logo.png new file mode 100644 index 00000000..2e73e35b Binary files /dev/null and b/assets/images/white-logo.png differ diff --git a/lib/main.dart b/lib/main.dart index ace34de6..22b0ee28 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,126 +1,29 @@ +import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; -import 'package:syncrow_web/pages/auth/view/login_page.dart'; +import 'package:syncrow_web/pages/home/view/home_page.dart'; void main() { runApp(const MyApp()); } - class MyApp extends StatelessWidget { const MyApp({super.key}); - - // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( - title: 'Flutter Demo', + debugShowCheckedModeBanner: false, + scrollBehavior: const MaterialScrollBehavior().copyWith( + dragDevices: { + PointerDeviceKind.mouse, + PointerDeviceKind.touch, + PointerDeviceKind.stylus, + PointerDeviceKind.unknown + }, + ), theme: ThemeData( - // This is the theme of your application. - // - // TRY THIS: Try running your application with "flutter run". You'll see - // the application has a purple toolbar. Then, without quitting the app, - // try changing the seedColor in the colorScheme below to Colors.green - // and then invoke "hot reload" (save your changes or press the "hot - // reload" button in a Flutter-supported IDE, or press "r" if you used - // the command line to start the app). - // - // Notice that the counter didn't reset back to zero; the application - // state is not lost during the reload. To reset the state, use hot - // restart instead. - // - // This works for code too, not just values: Most code changes can be - // tested with just a hot reload. colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), useMaterial3: true, ), - home: LoginPage(), - ); - } -} - -class MyHomePage extends StatefulWidget { - const MyHomePage({super.key, required this.title}); - - // This widget is the home page of your application. It is stateful, meaning - // that it has a State object (defined below) that contains fields that affect - // how it looks. - - // This class is the configuration for the state. It holds the values (in this - // case the title) provided by the parent (in this case the App widget) and - // used by the build method of the State. Fields in a Widget subclass are - // always marked "final". - - final String title; - - @override - State createState() => _MyHomePageState(); -} - -class _MyHomePageState extends State { - int _counter = 0; - - void _incrementCounter() { - setState(() { - // This call to setState tells the Flutter framework that something has - // changed in this State, which causes it to rerun the build method below - // so that the display can reflect the updated values. If we changed - // _counter without calling setState(), then the build method would not be - // called again, and so nothing would appear to happen. - _counter++; - }); - } - - @override - Widget build(BuildContext context) { - // This method is rerun every time setState is called, for instance as done - // by the _incrementCounter method above. - // - // The Flutter framework has been optimized to make rerunning build methods - // fast, so that you can just rebuild anything that needs updating rather - // than having to individually change instances of widgets. - return Scaffold( - appBar: AppBar( - // TRY THIS: Try changing the color here to a specific color (to - // Colors.amber, perhaps?) and trigger a hot reload to see the AppBar - // change color while the other colors stay the same. - backgroundColor: Theme.of(context).colorScheme.inversePrimary, - // Here we take the value from the MyHomePage object that was created by - // the App.build method, and use it to set our appbar title. - title: Text(widget.title), - ), - body: Center( - // Center is a layout widget. It takes a single child and positions it - // in the middle of the parent. - child: Column( - // Column is also a layout widget. It takes a list of children and - // arranges them vertically. By default, it sizes itself to fit its - // children horizontally, and tries to be as tall as its parent. - // - // Column has various properties to control how it sizes itself and - // how it positions its children. Here we use mainAxisAlignment to - // center the children vertically; the main axis here is the vertical - // axis because Columns are vertical (the cross axis would be - // horizontal). - // - // TRY THIS: Invoke "debug painting" (choose the "Toggle Debug Paint" - // action in the IDE, or press "p" in the console), to see the - // wireframe for each widget. - mainAxisAlignment: MainAxisAlignment.center, - children: [ - const Text( - 'You have pushed the button this many times:', - ), - Text( - '$_counter', - style: Theme.of(context).textTheme.headlineMedium, - ), - ], - ), - ), - floatingActionButton: FloatingActionButton( - onPressed: _incrementCounter, - tooltip: 'Increment', - child: const Icon(Icons.add), - ), // This trailing comma makes auto-formatting nicer for build methods. + home: const HomePage(), ); } } diff --git a/lib/pages/auth/view/login_mobile_page.dart b/lib/pages/auth/view/login_mobile_page.dart new file mode 100644 index 00000000..9dc81efe --- /dev/null +++ b/lib/pages/auth/view/login_mobile_page.dart @@ -0,0 +1,220 @@ +import 'dart:ui'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:syncrow_web/utils/assets.dart'; +import 'package:syncrow_web/pages/auth/bloc/login_bloc.dart'; +import 'package:syncrow_web/pages/auth/bloc/login_event.dart'; +import 'package:syncrow_web/pages/auth/bloc/login_state.dart'; +import 'package:syncrow_web/pages/home/view/home_page.dart'; + +class LoginMobilePage extends StatelessWidget { + const LoginMobilePage({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: BlocProvider( + create: (context) => LoginBloc(), + child: BlocConsumer( + listener: (context, state) { + if (state is LoginSuccess) { + // Navigate to home screen after successful login + Navigator.pushReplacement( + context, + MaterialPageRoute(builder: (context) => const HomePage()), + ); + } else if (state is LoginFailure) { + // Show error message + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text(state.error), + ), + ); + } + }, + builder: (context, state) { + if (state is LoginLoading) { + return const Center(child: CircularProgressIndicator()); + } else { + return _buildLoginForm(context); + } + }, + ), + ), + + ); + } + + Widget _buildLoginForm(BuildContext context) { + final loginBloc = BlocProvider.of(context); + final TextEditingController _usernameController = TextEditingController(); + final TextEditingController _passwordController = TextEditingController(); + return Center( + child: Stack( + children: [ + Container( + width: MediaQuery.sizeOf(context).width, + height: MediaQuery.sizeOf(context).height, + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage( + Assets.background, + ), + fit: BoxFit.cover, + ), + ), + ), + Container( + width: MediaQuery.sizeOf(context).width, + height: MediaQuery.sizeOf(context).height, + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage(Assets.vector), + fit: BoxFit.cover, + opacity: 0.9, + ), + ), + ), + SingleChildScrollView( + child: Container( + margin: const EdgeInsets.all(50), + decoration: BoxDecoration( + color: Colors.black.withOpacity(0.3), + borderRadius: const BorderRadius.all(Radius.circular(20))), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsets.all(15.0), + child: SvgPicture.asset( + Assets.loginLogo, + ), + ), + Container( + margin: const EdgeInsets.all(15), + decoration: BoxDecoration( + color: Colors.white.withOpacity(0.3), + borderRadius: const BorderRadius.all(Radius.circular(30))), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 50, vertical: 20), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 15), + const Text( + 'Login', + style: TextStyle( + color: Colors.white, + fontSize: 24, + fontWeight: FontWeight.bold), + ), + const SizedBox(height: 15), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + const Text( + "Email", + style: TextStyle( + color: Colors.white, + fontSize: 13, + fontWeight: FontWeight.bold), + ), + SizedBox( + child: TextFormField( + decoration: InputDecoration( + labelText: 'Email', + labelStyle: TextStyle(color: Colors.white), + hintText: 'username@gmail.com', + hintStyle: TextStyle(color: Colors.grey), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8.0), + borderSide: BorderSide(color: Colors.white), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8.0), + borderSide: BorderSide(color: Colors.white), + ), + filled: true, + fillColor: Colors.white, + contentPadding: EdgeInsets.symmetric( + vertical: 16.0, horizontal: 12.0), + ), + style: TextStyle(color: Colors.black), + )), + ], + ), + const SizedBox(height: 15.0), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + const Text( + "Password", + style: TextStyle( + color: Colors.white, + fontSize: 13, + fontWeight: FontWeight.bold), + ), + SizedBox( + child: TextFormField( + decoration: InputDecoration( + labelText: 'Password', + labelStyle: TextStyle(color: Colors.white), + hintText: 'Password', + hintStyle: TextStyle(color: Colors.grey), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8.0), + borderSide: BorderSide(color: Colors.white), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8.0), + borderSide: BorderSide(color: Colors.white), + ), + filled: true, + fillColor: Colors.white, + contentPadding: EdgeInsets.symmetric( + vertical: 16.0, horizontal: 12.0), + ), + style: TextStyle(color: Colors.black), + )), + const SizedBox(height: 20.0), + const Text( + "Forgot Password?", + style: TextStyle( + color: Colors.white, + fontSize: 13, + fontWeight: FontWeight.bold), + ), + ], + ), + const SizedBox(height: 20.0), + ElevatedButton( + onPressed: () async { + // Trigger login event + loginBloc.add( + LoginButtonPressed( + username: _usernameController.text, + password: _passwordController.text, + ), + ); + }, + child: const Text('Login'), + ), + ], + ), + ), + ), + ], + ), + ), + ), + ], + ), + ); + } +} diff --git a/lib/pages/auth/view/login_page.dart b/lib/pages/auth/view/login_page.dart index de451e50..d5644b5e 100644 --- a/lib/pages/auth/view/login_page.dart +++ b/lib/pages/auth/view/login_page.dart @@ -1,100 +1,18 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:syncrow_web/pages/auth/bloc/login_bloc.dart'; -import 'package:syncrow_web/pages/auth/bloc/login_event.dart'; -import 'package:syncrow_web/pages/auth/bloc/login_state.dart'; -import 'package:syncrow_web/pages/home/view/home_page.dart'; +import 'package:syncrow_web/pages/auth/view/login_mobile_page.dart'; +import 'package:syncrow_web/pages/auth/view/login_web_page.dart'; +import 'package:syncrow_web/utils/responsive_layout.dart'; class LoginPage extends StatelessWidget { const LoginPage({super.key}); @override Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: const Text('Login'), - ), - body: BlocProvider( - create: (context) => LoginBloc(), - child: BlocConsumer( - listener: (context, state) { - if (state is LoginSuccess) { - // Navigate to home screen after successful login - Navigator.pushReplacement( - context, - MaterialPageRoute(builder: (context) => const HomePage()), - ); - } else if (state is LoginFailure) { - // Show error message - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(state.error), - ), - ); - } - }, - builder: (context, state) { - if (state is LoginLoading) { - return const Center(child: CircularProgressIndicator()); - } else { - return _buildLoginForm(context); - } - }, - ), - ), - ); - } - - Widget _buildLoginForm(BuildContext context) { - final loginBloc = BlocProvider.of(context); - final TextEditingController _usernameController = TextEditingController(); - final TextEditingController _passwordController = TextEditingController(); - - return Center( - child: Padding( - padding: const EdgeInsets.all(20.0), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - SizedBox( - width: MediaQuery.sizeOf(context).width * 0.4, - child: TextField( - controller: _usernameController, - decoration: const InputDecoration( - labelText: 'Username', - ), - ), - ), - const SizedBox(height: 20.0), - SizedBox( - width: MediaQuery.sizeOf(context).width * 0.4, - child: TextField( - controller: _passwordController, - obscureText: true, - decoration: const InputDecoration( - labelText: 'Password', - ), - ), - ), - const SizedBox(height: 20.0), - ElevatedButton( - onPressed: () async { - // Trigger login event - loginBloc.add( - LoginButtonPressed( - username: _usernameController.text, - password: _passwordController.text, - ), - ); - }, - child: const Text('Login'), - ), - ], - ), - ), + return const ResponsiveLayout( + desktopBody: LoginWebPage(), + mobileBody:LoginMobilePage() ); } } diff --git a/lib/pages/auth/view/login_web_page.dart b/lib/pages/auth/view/login_web_page.dart new file mode 100644 index 00000000..e367f96a --- /dev/null +++ b/lib/pages/auth/view/login_web_page.dart @@ -0,0 +1,230 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:syncrow_web/utils/assets.dart'; +import 'package:syncrow_web/pages/auth/bloc/login_bloc.dart'; +import 'package:syncrow_web/pages/auth/bloc/login_event.dart'; +import 'package:syncrow_web/pages/auth/bloc/login_state.dart'; +import 'package:syncrow_web/pages/home/view/home_page.dart'; + +class LoginWebPage extends StatelessWidget { + const LoginWebPage({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + // appBar: AppBar( + // title: const Text('Login'), + // ), + body: BlocProvider( + create: (context) => LoginBloc(), + child: BlocConsumer( + listener: (context, state) { + if (state is LoginSuccess) { + // Navigate to home screen after successful login + Navigator.pushReplacement( + context, + MaterialPageRoute(builder: (context) => const HomePage()), + ); + } else if (state is LoginFailure) { + // Show error message + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text(state.error), + ), + ); + } + }, + builder: (context, state) { + if (state is LoginLoading) { + return const Center(child: CircularProgressIndicator()); + } else { + return _buildLoginForm(context); + } + }, + ), + ), + ); + } + + Widget _buildLoginForm(BuildContext context) { + final loginBloc = BlocProvider.of(context); + final TextEditingController _usernameController = TextEditingController(); + final TextEditingController _passwordController = TextEditingController(); + return Center( + child: Stack( + children: [ + Container( + width: MediaQuery.sizeOf(context).width, + height: MediaQuery.sizeOf(context).height, + child: SvgPicture.asset( + Assets.webBackground, + fit: BoxFit.cover, + ), + ), + Container( + width: MediaQuery.sizeOf(context).width, + height: MediaQuery.sizeOf(context).height, + decoration: const BoxDecoration( + image: DecorationImage( + image: AssetImage(Assets.vector), + fit: BoxFit.cover, + opacity: 0.9, + ), + ), + ), + Container( + margin: const EdgeInsets.all(50), + decoration: BoxDecoration( + color: Colors.black.withOpacity(0.3), + borderRadius: const BorderRadius.all(Radius.circular(20)), + ), + child:Center( + child: ListView( + shrinkWrap: true, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Spacer(), + Expanded( + flex: 2, + child: SvgPicture.asset( + Assets.loginLogo, + ), + ), + const Spacer(), + Container( + decoration: BoxDecoration( + color: Colors.white.withOpacity(0.3), + borderRadius: const BorderRadius.all(Radius.circular(30)), + ), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 50, vertical: 20), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 15), + const Text( + 'Login', + style: TextStyle( + color: Colors.white, + fontSize: 24, + fontWeight: FontWeight.bold), + ), + const SizedBox(height: 30), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + const Text( + "Email", + style: TextStyle( + color: Colors.white, + fontSize: 13, + fontWeight: FontWeight.bold), + ), + SizedBox( + width: MediaQuery.sizeOf(context).width * 0.2, + child: TextFormField( + controller: _usernameController, + decoration: InputDecoration( + labelText: 'Email', + labelStyle: const TextStyle(color: Colors.white), + hintText: 'username@gmail.com', + hintStyle: const TextStyle(color: Colors.grey), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8.0), + borderSide: const BorderSide(color: Colors.white), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8.0), + borderSide: const BorderSide(color: Colors.white), + ), + filled: true, + fillColor: Colors.white, + contentPadding: const EdgeInsets.symmetric( + vertical: 16.0, horizontal: 12.0), + ), + style: const TextStyle(color: Colors.black), + ), + ), + ], + ), + const SizedBox(height: 20.0), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + const Text( + "Password", + style: TextStyle( + color: Colors.white, + fontSize: 13, + fontWeight: FontWeight.bold), + ), + SizedBox( + width: MediaQuery.sizeOf(context).width * 0.2, + child: TextFormField( + controller: _passwordController, + decoration: InputDecoration( + labelText: 'Password', + labelStyle: const TextStyle(color: Colors.white), + hintText: 'Password', + hintStyle: const TextStyle(color: Colors.grey), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8.0), + borderSide: const BorderSide(color: Colors.white), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8.0), + borderSide: const BorderSide(color: Colors.white), + ), + filled: true, + fillColor: Colors.white, + contentPadding: const EdgeInsets.symmetric( + vertical: 16.0, horizontal: 12.0), + ), + style: const TextStyle(color: Colors.black), + ), + ), + const SizedBox(height: 20.0), + const Text( + "Forgot Password?", + style: TextStyle( + color: Colors.white, + fontSize: 13, + fontWeight: FontWeight.bold), + ), + ], + ), + const SizedBox(height: 20.0), + ElevatedButton( + onPressed: () async { + // Trigger login event + loginBloc.add( + LoginButtonPressed( + username: _usernameController.text, + password: _passwordController.text, + ), + ); + }, + child: const Text('Login'), + ), + ], + ), + ), + ), + const Spacer(), + ], + ), + ], + )), + ), + ], + ), + ); + } +} diff --git a/lib/pages/home/view/home_page.dart b/lib/pages/home/view/home_page.dart index a28a4d0e..de8f0821 100644 --- a/lib/pages/home/view/home_page.dart +++ b/lib/pages/home/view/home_page.dart @@ -2,16 +2,29 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncrow_web/pages/home/bloc/home_bloc.dart'; import 'package:syncrow_web/pages/home/view/tree_page.dart'; +import 'package:syncrow_web/utils/style.dart'; +import 'package:syncrow_web/web_layout/web_scaffold.dart'; class HomePage extends StatelessWidget { const HomePage({super.key}); - @override Widget build(BuildContext context) { - return Scaffold( - body: BlocProvider( - create: (context) => HomeBloc(), - child: const TreeWidget(), - )); + return WebScaffold( + appBarTitle: 'Space Management', + appBarBody:[ + Text( + 'Community structure', + style: appBarTextStyle, + ), + Text( + 'Community ', + style: appBarTextStyle + ), + ], + scaffoldBody: BlocProvider( + create: (context) => HomeBloc(), + child: const TreeWidget(), + ), + ); } } diff --git a/lib/pages/home/view/tree_page.dart b/lib/pages/home/view/tree_page.dart index 21033607..a213c84e 100644 --- a/lib/pages/home/view/tree_page.dart +++ b/lib/pages/home/view/tree_page.dart @@ -29,11 +29,11 @@ class TreeWidget extends StatelessWidget { if (state is HomeInitial) { return Wrap( children: [ - Container( + SizedBox( width: 100, child: TextFormField( decoration: - InputDecoration(labelText: "Subtree separation"), + const InputDecoration(labelText: "Subtree separation"), onChanged: (text) { firstNodeName = text; }, @@ -55,7 +55,6 @@ class TreeWidget extends StatelessWidget { onPressed: () { final node1 = Node.Id(firstNodeName); final node2 = Node.Id(secondNodeName); - context.read().add(CreateNewNode( sourceNode: node1, destinationNode: node2)); }, @@ -99,7 +98,6 @@ class TreeWidget extends StatelessWidget { Widget rectangleWidget(String text, Node node, BuildContext blocContext) { String nodeName = ''; - return InkWell( onTap: () { showDialog( @@ -145,6 +143,7 @@ Widget rectangleWidget(String text, Node node, BuildContext blocContext) { BoxShadow(color: Colors.blue[100]!, spreadRadius: 1), ], ), - child: Text(text)), + child: Text(text) + ), ); } diff --git a/lib/utils/assets.dart b/lib/utils/assets.dart new file mode 100644 index 00000000..1e5e0d00 --- /dev/null +++ b/lib/utils/assets.dart @@ -0,0 +1,12 @@ +class Assets { + Assets._(); + static const String background = "assets/images/Background.png"; + static const String webBackground = "assets/images/web_Background.svg"; + static const String blackLogo = "assets/images/black-logo.png"; + static const String logo = "assets/images/Logo.svg"; + static const String logoHorizontal = "assets/images/logo_horizontal.png"; + static const String vector = "assets/images/Vector.png"; + static const String loginLogo = "assets/images/login_logo.svg"; + static const String whiteLogo = "assets/images/white-logo.png"; + static const String window = "assets/images/Window.png"; +} diff --git a/lib/utils/color_manager.dart b/lib/utils/color_manager.dart new file mode 100644 index 00000000..36e5b0fc --- /dev/null +++ b/lib/utils/color_manager.dart @@ -0,0 +1,30 @@ +import 'package:flutter/material.dart'; + +abstract class ColorsManager { + static const Color textPrimaryColor = Color(0xFF5D5D5D); + static const Color switchOffColor = Color(0x7F8D99AE); + static const Color primaryColor = Color(0xFF0030CB);//023DFE + static const Color secondaryTextColor = Color(0xFF848484); + static Color primaryColorWithOpacity = const Color(0xFF023DFE).withOpacity(0.6); + static const Color whiteColors = Colors.white; + static const Color secondaryColor = Color(0xFF023DFE); + static const Color onSecondaryColor = Color(0xFF023DFE); + + static const Color primaryTextColor = Colors.black; + + static const Color greyColor = Color(0xFFd5d5d5); + + static const Color backgroundColor = Color(0xFFececec); + static const Color dozeColor = Color(0xFFFEC258); + static const Color relaxColor = Color(0xFFFBD288); + static const Color readingColor = Color(0xFFF7D69C); + static const Color energizingColor = Color(0xFFEDEDED); + static const Color dividerColor = Color(0xFFEBEBEB); + static const Color slidingBlueColor = Color(0x99023DFE); + static const Color blackColor = Color(0xFF000000); + static const Color lightGreen = Color(0xFF00FF0A); + static const Color grayColor = Color(0xFF999999); + static const Color red = Colors.red; + static const Color graysColor = Color(0xffEBEBEB); + static const Color textGray = Color(0xffD5D5D5); +} diff --git a/lib/utils/responsive_layout.dart b/lib/utils/responsive_layout.dart new file mode 100644 index 00000000..13b584ea --- /dev/null +++ b/lib/utils/responsive_layout.dart @@ -0,0 +1,21 @@ + + +import 'package:flutter/material.dart'; + + +class ResponsiveLayout extends StatelessWidget { + final Widget desktopBody; + final Widget mobileBody; + const ResponsiveLayout({super.key,required this.desktopBody,required this.mobileBody}); + @override + Widget build(BuildContext context) { + return LayoutBuilder(builder: (context, constraints) { + if(constraints.maxWidth<600){ + return mobileBody; + }else{ + return desktopBody; + } + }, + ); + } +} diff --git a/lib/utils/style.dart b/lib/utils/style.dart new file mode 100644 index 00000000..677aac50 --- /dev/null +++ b/lib/utils/style.dart @@ -0,0 +1,27 @@ +import 'package:flutter/material.dart'; + +import 'color_manager.dart'; + +InputDecoration? textBoxDecoration = InputDecoration( + focusColor: ColorsManager.grayColor, + suffixIcon: const Icon(Icons.search), + hintText: 'Search', + filled: true, // Enable background filling + fillColor: Colors.grey.shade200, // Set the background color + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(15), // Add border radius + borderSide: BorderSide.none, // Remove the underline + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(15), // Add border radius + borderSide: BorderSide.none, // Remove the underline + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(15), // Add border radius + borderSide: BorderSide.none, // Remove the underline + ), +); + + +TextStyle appBarTextStyle = + const TextStyle(fontSize: 20, color: ColorsManager.whiteColors); diff --git a/lib/web_layout/menu_sidebar.dart b/lib/web_layout/menu_sidebar.dart new file mode 100644 index 00000000..f5af64d7 --- /dev/null +++ b/lib/web_layout/menu_sidebar.dart @@ -0,0 +1,56 @@ + + +import 'package:flutter/material.dart'; +import 'package:syncrow_web/utils/color_manager.dart'; +import 'package:syncrow_web/utils/style.dart'; + +class MenuSidebar extends StatelessWidget { + const MenuSidebar({super.key}); + + @override + Widget build(BuildContext context) { + return Expanded( + child: Container( + decoration: const BoxDecoration( + shape: BoxShape.rectangle, + boxShadow: [ + BoxShadow( + color: Colors.black26, + offset: Offset(4, 0), + blurRadius: 10, + ) + ], + color: ColorsManager.whiteColors, + ), + width: 200, + child: Padding( + padding: const EdgeInsets.all(15.0), + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Text('Community',style: TextStyle(fontSize: 20),), + CircleAvatar( + backgroundColor: Colors.grey.shade200, + child: IconButton( + color: ColorsManager.onSecondaryColor, + onPressed: () {}, + icon: const Icon(Icons.add) + ), + ) + ], + ), + const SizedBox(height: 20,), + TextFormField( + controller: TextEditingController(), + decoration:textBoxDecoration + ), + Container(height: 100,) + ], + ), + ), + ), + ); + } +} diff --git a/lib/web_layout/web_app_bar.dart b/lib/web_layout/web_app_bar.dart new file mode 100644 index 00000000..94773d73 --- /dev/null +++ b/lib/web_layout/web_app_bar.dart @@ -0,0 +1,63 @@ +import 'package:flutter/material.dart'; +import 'package:syncrow_web/utils/color_manager.dart'; + +class WebAppBar extends StatelessWidget { + final String? title; + final List? body; + const WebAppBar({super.key,this.title,this.body}); + + @override + Widget build(BuildContext context) { + return Container( + height: 120, + decoration: const BoxDecoration(color:ColorsManager.secondaryColor ), + padding: const EdgeInsets.all(10), + child: Expanded( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Text( + title!,style: const TextStyle( + fontSize: 30, + color: Colors.white),) + ), + if (body != null) + Expanded( + flex: 2, + child: Wrap( + spacing: 15, // Adjust the spacing as needed + children: body!, + ), + ), + Row( + children: [ + IconButton(onPressed: () {}, + icon: const Icon(Icons.apps_sharp,color: Colors.white,)), + const SizedBox(width: 10,), + const SizedBox.square( + dimension: 40, + child: CircleAvatar( + backgroundColor: Colors.white, + child: SizedBox.square( + dimension: 35, + child: CircleAvatar( + backgroundColor: Colors.grey, + child: FlutterLogo(), + ), + ), + ), + ), + const SizedBox(width: 10,), + const Text('mohamamd alnemer ',style: TextStyle(fontSize: 16,color: Colors.white),), + ], + ) + ], + ), + ) , + ); + } + + // @override + // Size get preferredSize => Size.fromHeight(50.0); +} \ No newline at end of file diff --git a/lib/web_layout/web_scaffold.dart b/lib/web_layout/web_scaffold.dart new file mode 100644 index 00000000..8ea9f506 --- /dev/null +++ b/lib/web_layout/web_scaffold.dart @@ -0,0 +1,54 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:syncrow_web/utils/assets.dart'; +import 'package:syncrow_web/web_layout/web_app_bar.dart'; +import 'menu_sidebar.dart'; + +class WebScaffold extends StatelessWidget { + final bool enableMenuSideba; + final String? appBarTitle; + final List? appBarBody; + final Widget? scaffoldBody; + const WebScaffold({super.key,this.appBarTitle,this.appBarBody,this.scaffoldBody,this.enableMenuSideba=true}); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Stack( + children: [ + SizedBox( + width: MediaQuery.sizeOf(context).width, + height: MediaQuery.sizeOf(context).height, + child: SvgPicture.asset( + Assets.webBackground, + fit: BoxFit.cover, + ), + ), + Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Opacity( + opacity: 0.6, + child: WebAppBar( + title: appBarTitle, + body: appBarBody, + ) + ), + Expanded( + child: Row( + children: [ + if(enableMenuSideba) + const MenuSidebar(), + Expanded( + flex: 5, + child: scaffoldBody! + ) + ], + ), + ) + ], + ), + ], + )); + } +} diff --git a/pubspec.lock b/pubspec.lock index 21eb45a3..863a9197 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,6 +1,14 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + args: + dependency: transitive + description: + name: args + sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a" + url: "https://pub.dev" + source: hosted + version: "2.5.0" async: dependency: transitive description: @@ -94,6 +102,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.2" + flutter_svg: + dependency: "direct main" + description: + name: flutter_svg + sha256: "7b4ca6cf3304575fe9c8ec64813c8d02ee41d2afe60bcfe0678bcb5375d596a2" + url: "https://pub.dev" + source: hosted + version: "2.0.10+1" flutter_test: dependency: "direct dev" description: flutter @@ -107,30 +123,46 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.0" + http: + dependency: transitive + description: + name: http + sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010 + url: "https://pub.dev" + source: hosted + version: "1.2.2" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + url: "https://pub.dev" + source: hosted + version: "4.0.2" leak_tracker: dependency: transitive description: name: leak_tracker - sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa" + sha256: "7f0df31977cb2c0b88585095d168e689669a2cc9b97c309665e3386f3e9d341a" url: "https://pub.dev" source: hosted - version: "10.0.0" + version: "10.0.4" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0 + sha256: "06e98f569d004c1315b991ded39924b21af84cf14cc94791b8aea337d25b57f8" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "3.0.3" leak_tracker_testing: dependency: transitive description: name: leak_tracker_testing - sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47 + sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "3.0.1" lints: dependency: transitive description: @@ -159,10 +191,10 @@ packages: dependency: transitive description: name: meta - sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 + sha256: "7687075e408b093f36e6bbf6c91878cc0d4cd10f409506f7bc996f68220b9136" url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.12.0" nested: dependency: transitive description: @@ -179,6 +211,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.9.0" + path_parsing: + dependency: transitive + description: + name: path_parsing + sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf + url: "https://pub.dev" + source: hosted + version: "1.0.1" + petitparser: + dependency: transitive + description: + name: petitparser + sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27 + url: "https://pub.dev" + source: hosted + version: "6.0.2" provider: dependency: transitive description: @@ -236,10 +284,42 @@ packages: dependency: transitive description: name: test_api - sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" + sha256: "9955ae474176f7ac8ee4e989dadfb411a58c30415bcfb648fa04b2b8a03afa7f" url: "https://pub.dev" source: hosted - version: "0.6.1" + version: "0.7.0" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c + url: "https://pub.dev" + source: hosted + version: "1.3.2" + vector_graphics: + dependency: transitive + description: + name: vector_graphics + sha256: "32c3c684e02f9bc0afb0ae0aa653337a2fe022e8ab064bcd7ffda27a74e288e3" + url: "https://pub.dev" + source: hosted + version: "1.1.11+1" + vector_graphics_codec: + dependency: transitive + description: + name: vector_graphics_codec + sha256: c86987475f162fadff579e7320c7ddda04cd2fdeffbe1129227a85d9ac9e03da + url: "https://pub.dev" + source: hosted + version: "1.1.11+1" + vector_graphics_compiler: + dependency: transitive + description: + name: vector_graphics_compiler + sha256: "12faff3f73b1741a36ca7e31b292ddeb629af819ca9efe9953b70bd63fc8cd81" + url: "https://pub.dev" + source: hosted + version: "1.1.11+1" vector_math: dependency: transitive description: @@ -252,10 +332,26 @@ packages: dependency: transitive description: name: vm_service - sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957 + sha256: "3923c89304b715fb1eb6423f017651664a03bf5f4b29983627c4da791f74a4ec" url: "https://pub.dev" source: hosted - version: "13.0.0" + version: "14.2.1" + web: + dependency: transitive + description: + name: web + sha256: d43c1d6b787bf0afad444700ae7f4db8827f701bc61c255ac8d328c6f4d52062 + url: "https://pub.dev" + source: hosted + version: "1.0.0" + xml: + dependency: transitive + description: + name: xml + sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226 + url: "https://pub.dev" + source: hosted + version: "6.5.0" sdks: - dart: ">=3.3.1 <4.0.0" - flutter: ">=1.17.0" + dart: ">=3.4.0 <4.0.0" + flutter: ">=3.18.0-18.0.pre.54" diff --git a/pubspec.yaml b/pubspec.yaml index 2dc3fdbc..5b17566f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -38,7 +38,8 @@ dependencies: flutter_bloc: ^8.1.5 equatable: ^2.0.5 graphview: ^1.2.0 - + flutter_svg: ^2.0.10+1 + dev_dependencies: flutter_test: @@ -63,9 +64,9 @@ flutter: uses-material-design: true # To add assets to your application, add an assets section, like this: - # assets: - # - images/a_dot_burr.jpeg - # - images/a_dot_ham.jpeg + assets: + - assets/images/ + # An image asset can refer to one or more resolution-specific "variants", see # https://flutter.dev/assets-and-images/#resolution-aware