From 2b0f66527c4162dbe3cd5d08e2d0a45a822f75f8 Mon Sep 17 00:00:00 2001 From: sBubshait Date: Wed, 16 Jul 2025 14:17:24 +0300 Subject: [PATCH] feat: implement basic landing page --- assets/fonts/Blaka-Regular.ttf | Bin 0 -> 55828 bytes lib/main.dart | 717 ++++++++++++++++++++++++++++----- pubspec.yaml | 76 +--- 3 files changed, 630 insertions(+), 163 deletions(-) create mode 100644 assets/fonts/Blaka-Regular.ttf diff --git a/assets/fonts/Blaka-Regular.ttf b/assets/fonts/Blaka-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..4646e02e7eaa87cde606888de3fc941a9a61f0b4 GIT binary patch literal 55828 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 QDp|^B9bYE39dbqae<-`1d;kCd literal 0 HcmV?d00001 diff --git a/lib/main.dart b/lib/main.dart index 7b7f5b6..a053bd5 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,122 +1,653 @@ import 'package:flutter/material.dart'; +import 'screens/home_screen.dart'; void main() { - runApp(const MyApp()); + runApp(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', - 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), - ), - home: const MyHomePage(title: 'Flutter Demo Home Page'), + title: 'Connection App', + theme: ThemeData(primarySwatch: Colors.blue, fontFamily: 'Roboto'), + home: LandingPage(), + debugShowCheckedModeBanner: false, ); } } -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; - +class LandingPage extends StatefulWidget { @override - State createState() => _MyHomePageState(); + _LandingPageState createState() => _LandingPageState(); } -class _MyHomePageState extends State { - int _counter = 0; +class _LandingPageState extends State + with SingleTickerProviderStateMixin { + late AnimationController _animationController; + late Animation _slideAnimation; + bool _showBottomSheet = false; - void _incrementCounter() { + @override + void initState() { + super.initState(); + _animationController = AnimationController( + duration: Duration(milliseconds: 800), + vsync: this, + ); + _slideAnimation = Tween(begin: 1.0, end: 0.0).animate( + CurvedAnimation(parent: _animationController, curve: Curves.easeInOut), + ); + } + + @override + void dispose() { + _animationController.dispose(); + super.dispose(); + } + + void _showGetStartedBottomSheet() { 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++; + _showBottomSheet = true; }); + _animationController.forward(); + } + + void _hideBottomSheet() { + _animationController.reverse().then((_) { + setState(() { + _showBottomSheet = false; + }); + }); + } + + void _navigateToSignIn() { + Navigator.of( + context, + ).push(MaterialPageRoute(builder: (context) => SignInPage())); + } + + void _navigateToHome() { + Navigator.of( + context, + ).push(MaterialPageRoute(builder: (context) => HomeScreen())); } @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, + body: Stack( + children: [ + // Background gradient + Container( + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + Color(0xFF32B0A5), // Teal + Color(0xFF4600B9), // Purple + ], + stops: [0.0, 0.5], + ), ), - ], - ), + ), + + // Main content + SafeArea( + child: Column( + children: [ + Expanded( + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + // Logo + Container( + padding: EdgeInsets.all(40), + child: Text( + 'وصال', + style: TextStyle( + fontSize: 160, + fontWeight: FontWeight.w200, + fontFamily: 'Blaka', + color: Colors.white, + shadows: [ + Shadow( + offset: Offset(2, 2), + blurRadius: 4, + color: Colors.black.withOpacity(0.3), + ), + ], + ), + ), + ), + + SizedBox(height: 60), + + // Subtitle + Text( + 'Connections, Made\nEasier!', + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 32, + fontWeight: FontWeight.w600, + color: Colors.white, + height: 1.2, + ), + ), + + SizedBox(height: 80), + + // Get Started Button + Container( + width: 280, + height: 56, + child: ElevatedButton( + onPressed: _showGetStartedBottomSheet, + style: ElevatedButton.styleFrom( + backgroundColor: Color(0xFF6A4C93), + foregroundColor: Colors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(28), + ), + elevation: 8, + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'Get Started', + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w600, + ), + ), + SizedBox(width: 8), + Icon(Icons.arrow_forward, size: 20), + ], + ), + ), + ), + + SizedBox(height: 24), + + // Login link + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + GestureDetector( + onTap: _navigateToHome, + child: Text( + 'Skip to Home', + style: TextStyle( + color: Colors.white, + fontSize: 16, + fontWeight: FontWeight.w600, + decoration: TextDecoration.underline, + ), + ), + ), + ], + ), + ], + ), + ), + ), + ], + ), + ), + + // Bottom sheet overlay + if (_showBottomSheet) + AnimatedBuilder( + animation: _slideAnimation, + builder: (context, child) { + return Positioned( + bottom: 0, + left: 0, + right: 0, + child: Transform.translate( + offset: Offset(0, _slideAnimation.value * 400), + child: Container( + height: 400, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.only( + topLeft: Radius.circular(24), + topRight: Radius.circular(24), + ), + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.2), + blurRadius: 20, + offset: Offset(0, -5), + ), + ], + ), + child: Column( + children: [ + // Handle bar + Container( + margin: EdgeInsets.only(top: 12), + width: 40, + height: 4, + decoration: BoxDecoration( + color: Colors.grey[300], + borderRadius: BorderRadius.circular(2), + ), + ), + + // Close button + Align( + alignment: Alignment.topRight, + child: IconButton( + onPressed: _hideBottomSheet, + icon: Icon(Icons.close, color: Colors.grey[600]), + ), + ), + + Expanded( + child: Padding( + padding: EdgeInsets.symmetric(horizontal: 24), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + 'Get Started', + style: TextStyle( + fontSize: 28, + fontWeight: FontWeight.bold, + color: Colors.black87, + ), + ), + + SizedBox(height: 12), + + Text( + 'Create your account and start connecting with others', + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 16, + color: Colors.grey[600], + ), + ), + + SizedBox(height: 40), + + // Sign Up button + Container( + width: double.infinity, + height: 56, + child: ElevatedButton( + onPressed: () { + // Handle sign up + ScaffoldMessenger.of( + context, + ).showSnackBar( + SnackBar( + content: Text('Sign Up pressed'), + ), + ); + }, + style: ElevatedButton.styleFrom( + backgroundColor: Color(0xFF6A4C93), + foregroundColor: Colors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + 12, + ), + ), + elevation: 2, + ), + child: Text( + 'Sign Up Now', + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w600, + ), + ), + ), + ), + + SizedBox(height: 16), + + // Login button + Container( + width: double.infinity, + height: 56, + child: OutlinedButton( + onPressed: _navigateToSignIn, + style: OutlinedButton.styleFrom( + foregroundColor: Color(0xFF6A4C93), + side: BorderSide( + color: Color(0xFF6A4C93), + ), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + 12, + ), + ), + ), + child: Text( + 'Login', + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w600, + ), + ), + ), + ), + ], + ), + ), + ), + ], + ), + ), + ), + ); + }, + ), + ], + ), + ); + } +} + +class SignInPage extends StatefulWidget { + @override + _SignInPageState createState() => _SignInPageState(); +} + +class _SignInPageState extends State { + final _formKey = GlobalKey(); + final _emailController = TextEditingController(); + final _passwordController = TextEditingController(); + bool _isPasswordVisible = false; + bool _isLoading = false; + + @override + void dispose() { + _emailController.dispose(); + _passwordController.dispose(); + super.dispose(); + } + + void _handleSignIn() async { + if (_formKey.currentState!.validate()) { + setState(() { + _isLoading = true; + }); + + // Simulate API call + await Future.delayed(Duration(seconds: 2)); + + setState(() { + _isLoading = false; + }); + + ScaffoldMessenger.of( + context, + ).showSnackBar(SnackBar(content: Text('Sign in successful!'))); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Container( + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [Color(0xFF32B0A5), Color(0xFF4600B9)], + stops: [0.0, 0.5], + ), + ), + child: SafeArea( + child: Column( + children: [ + // App bar + Padding( + padding: EdgeInsets.all(16), + child: Row( + children: [ + IconButton( + onPressed: () => Navigator.of(context).pop(), + icon: Icon(Icons.arrow_back, color: Colors.white), + ), + Text( + 'Sign In', + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.w600, + color: Colors.white, + ), + ), + ], + ), + ), + + // Content + Expanded( + child: Container( + margin: EdgeInsets.all(16), + padding: EdgeInsets.all(24), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(16), + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.1), + blurRadius: 20, + offset: Offset(0, 5), + ), + ], + ), + child: Form( + key: _formKey, + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + SizedBox(height: 20), + + // Logo + Center( + child: Text( + 'وصال', + style: TextStyle( + fontSize: 48, + fontWeight: FontWeight.w200, + fontFamily: 'Blaka', + color: Color(0xFF6A4C93), + ), + ), + ), + + SizedBox(height: 40), + + // Welcome text + Text( + 'Welcome Back!', + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold, + color: Colors.black87, + ), + textAlign: TextAlign.center, + ), + + SizedBox(height: 8), + + Text( + 'Sign in to your account', + style: TextStyle( + fontSize: 16, + color: Colors.grey[600], + ), + textAlign: TextAlign.center, + ), + + SizedBox(height: 40), + + // Email field + TextFormField( + controller: _emailController, + keyboardType: TextInputType.emailAddress, + decoration: InputDecoration( + labelText: 'Email', + prefixIcon: Icon(Icons.email_outlined), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide(color: Color(0xFF6A4C93)), + ), + ), + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please enter your email'; + } + if (!value.contains('@')) { + return 'Please enter a valid email'; + } + return null; + }, + ), + + SizedBox(height: 20), + + // Password field + TextFormField( + controller: _passwordController, + obscureText: !_isPasswordVisible, + decoration: InputDecoration( + labelText: 'Password', + prefixIcon: Icon(Icons.lock_outline), + suffixIcon: IconButton( + icon: Icon( + _isPasswordVisible + ? Icons.visibility_off + : Icons.visibility, + ), + onPressed: () { + setState(() { + _isPasswordVisible = !_isPasswordVisible; + }); + }, + ), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide(color: Color(0xFF6A4C93)), + ), + ), + validator: (value) { + if (value == null || value.isEmpty) { + return 'Please enter your password'; + } + if (value.length < 6) { + return 'Password must be at least 6 characters'; + } + return null; + }, + ), + + SizedBox(height: 12), + + // Forgot password + Align( + alignment: Alignment.centerRight, + child: TextButton( + onPressed: () { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text('Forgot password pressed'), + ), + ); + }, + child: Text( + 'Forgot Password?', + style: TextStyle( + color: Color(0xFF6A4C93), + fontWeight: FontWeight.w600, + ), + ), + ), + ), + + SizedBox(height: 30), + + // Sign in button + Container( + height: 56, + child: ElevatedButton( + onPressed: _isLoading ? null : _handleSignIn, + style: ElevatedButton.styleFrom( + backgroundColor: Color(0xFF6A4C93), + foregroundColor: Colors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + ), + elevation: 2, + ), + child: _isLoading + ? CircularProgressIndicator( + valueColor: AlwaysStoppedAnimation( + Colors.white, + ), + ) + : Text( + 'Sign In', + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w600, + ), + ), + ), + ), + + SizedBox(height: 20), + + // Sign up link + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + "Don't have an account? ", + style: TextStyle(color: Colors.grey[600]), + ), + GestureDetector( + onTap: () { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text('Sign up pressed')), + ); + }, + child: Text( + 'Sign Up', + style: TextStyle( + color: Color(0xFF6A4C93), + fontWeight: FontWeight.w600, + ), + ), + ), + ], + ), + + Spacer(), + ], + ), + ), + ), + ), + ], + ), + ), ), - floatingActionButton: FloatingActionButton( - onPressed: _incrementCounter, - tooltip: 'Increment', - child: const Icon(Icons.add), - ), // This trailing comma makes auto-formatting nicer for build methods. ); } } diff --git a/pubspec.yaml b/pubspec.yaml index 78f349e..3b2b4e0 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,89 +1,25 @@ name: wesal_app description: "A new Flutter project." -# The following line prevents the package from being accidentally published to -# pub.dev using `flutter pub publish`. This is preferred for private packages. -publish_to: 'none' # Remove this line if you wish to publish to pub.dev - -# The following defines the version and build number for your application. -# A version number is three numbers separated by dots, like 1.2.43 -# followed by an optional build number separated by a +. -# Both the version and the builder number may be overridden in flutter -# build by specifying --build-name and --build-number, respectively. -# In Android, build-name is used as versionName while build-number used as versionCode. -# Read more about Android versioning at https://developer.android.com/studio/publish/versioning -# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion. -# Read more about iOS versioning at -# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -# In Windows, build-name is used as the major, minor, and patch parts -# of the product and file versions while build-number is used as the build suffix. +publish_to: 'none' version: 1.0.0+1 environment: sdk: ^3.8.1 -# Dependencies specify other packages that your package needs in order to work. -# To automatically upgrade your package dependencies to the latest versions -# consider running `flutter pub upgrade --major-versions`. Alternatively, -# dependencies can be manually updated by changing the version numbers below to -# the latest version available on pub.dev. To see which dependencies have newer -# versions available, run `flutter pub outdated`. dependencies: flutter: sdk: flutter - - # The following adds the Cupertino Icons font to your application. - # Use with the CupertinoIcons class for iOS style icons. cupertino_icons: ^1.0.8 dev_dependencies: flutter_test: sdk: flutter - - # The "flutter_lints" package below contains a set of recommended lints to - # encourage good coding practices. The lint set provided by the package is - # activated in the `analysis_options.yaml` file located at the root of your - # package. See that file for information about deactivating specific lint - # rules and activating additional ones. flutter_lints: ^5.0.0 -# For information on the generic Dart part of this file, see the -# following page: https://dart.dev/tools/pub/pubspec - -# The following section is specific to Flutter packages. flutter: - - # The following line ensures that the Material Icons font is - # included with your application, so that you can use the icons in - # the material Icons class. 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 - - # An image asset can refer to one or more resolution-specific "variants", see - # https://flutter.dev/to/resolution-aware-images - - # For details regarding adding assets from package dependencies, see - # https://flutter.dev/to/asset-from-package - - # To add custom fonts to your application, add a fonts section here, - # in this "flutter" section. Each entry in this list should have a - # "family" key with the font family name, and a "fonts" key with a - # list giving the asset and other descriptors for the font. For - # example: - # fonts: - # - family: Schyler - # fonts: - # - asset: fonts/Schyler-Regular.ttf - # - asset: fonts/Schyler-Italic.ttf - # style: italic - # - family: Trajan Pro - # fonts: - # - asset: fonts/TrajanPro.ttf - # - asset: fonts/TrajanPro_Bold.ttf - # weight: 700 - # - # For details regarding fonts from package dependencies, - # see https://flutter.dev/to/font-from-package + fonts: + - family: Blaka + fonts: + - asset: assets/fonts/Blaka-Regular.ttf + weight: 200 \ No newline at end of file