├── .gitignore ├── .idea ├── codeStyles │ └── Project.xml ├── libraries │ ├── Dart_Packages.xml │ └── Dart_SDK.xml ├── modules.xml ├── portfolio_demo.iml └── vcs.xml ├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── analysis_options.yaml ├── android ├── app │ └── src │ │ └── main │ │ └── java │ │ └── io │ │ └── flutter │ │ └── plugins │ │ └── GeneratedPluginRegistrant.java └── local.properties ├── ios ├── Flutter │ └── Generated.xcconfig └── Runner │ ├── GeneratedPluginRegistrant.h │ └── GeneratedPluginRegistrant.m ├── lib ├── constants │ ├── assets.dart │ ├── fonts.dart │ ├── strings.dart │ └── text_styles.dart ├── main.dart ├── models │ └── education.dart ├── ui │ └── home.dart ├── utils │ └── screen │ │ └── screen_utils.dart └── widgets │ └── responsive_widget.dart ├── pubspec.yaml ├── screenshots └── portfolio.png └── web ├── assets ├── FontManifest.json ├── fonts │ ├── MaterialIcons-Regular.ttf │ ├── Nexa-Bold.otf │ ├── Nexa-Light.otf │ ├── Product-Sans-Regular.ttf │ └── Quicksand-Regular.otf ├── icons │ ├── ic_dribbble.png │ ├── ic_evernote.png │ ├── ic_google.png │ ├── ic_linkedIn.png │ └── ic_twitter.png └── images │ └── programmer-3.gif ├── favicon.ico ├── index.html └── main.dart /.gitignore: -------------------------------------------------------------------------------- 1 | # Files and directories created by pub 2 | .dart_tool/ 3 | .packages 4 | # Remove the following pattern if you wish to check in your lock file 5 | pubspec.lock 6 | 7 | # Conventional directory for build outputs 8 | build/ 9 | 10 | # Directory created by dartdoc 11 | doc/api/ 12 | -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 15 | 16 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /.idea/libraries/Dart_Packages.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | -------------------------------------------------------------------------------- /.idea/libraries/Dart_SDK.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/portfolio_demo.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 1.0.0 2 | 3 | - Initial version, created by Stagehand 4 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Zubair Rehman 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Portfolio 2 | 3 | A portfolio build by using flutter for web. 4 | 5 | ## Demo 6 | 7 |

8 | 9 |

10 | 11 | ## How to Create and Deploy 12 | Follow the links below to learn more about how to create and deploy web applications in flutter. 13 | 14 | * Flutter For Web: [A Complete Guide to Create & Run a Web Application](https://medium.com/@zubairehman.work/flutter-for-web-c75011a41956) 15 | 16 | * Flutter For Web: [A Complete Guide to Deploy a Web Application](https://medium.com/@zubairehman.work/flutter-for-web-a-complete-guide-to-deploy-a-web-application-3fa9463377a8) 17 | 18 | ## How to Use 19 | 20 | **Step 1:** 21 | 22 | Download or clone this repo by using the link below: 23 | 24 | ``` 25 | https://github.com/zubairehman/Portfolio-Demo.git 26 | ``` 27 | 28 | **Step 2:** 29 | 30 | Go to project root and execute the following command in console to get the required dependencies: 31 | 32 | ``` 33 | flutter pub get 34 | ``` 35 | 36 | **Step 3:** 37 | 38 | To use the Flutter SDK with the flutter_web preview make sure you have upgraded Flutter to at least v1.5.4 by running flutter upgrade from your machine. Follow the link to learn more about how to configure flutter for web: https://medium.com/@zubairehman.work/flutter-for-web-c75011a41956 39 | 40 | **Step 4:** 41 | 42 | To run this application simply type in the following command: 43 | 44 | ``` 45 | flutter packages pub global run webdev serve 46 | ``` 47 | 48 | ## Folder Structure 49 | Here is the core folder structure which flutter provides. 50 | 51 | ``` 52 | flutter-app/ 53 | |- android 54 | |- build 55 | |- ios 56 | |- lib 57 | |- test 58 | ``` 59 | 60 | Here is the folder structure we have been using in this project 61 | 62 | ``` 63 | lib/ 64 | |- constants/ 65 | |- ui/ 66 | |- utils/ 67 | |- widgets/ 68 | |- main.dart 69 | ``` 70 | 71 | Now, lets dive into the lib folder which has the main code for the application. 72 | 73 | ``` 74 | 1- constants - All the application level constants are defined in this directory with-in their respective files. This directory contains the constants for `theme`, `dimentions`, `api endpoints`, `preferences` and `strings`. 75 | 2- ui — Contains all the ui of your project, contains sub directory for each screen. 76 | 3- util — Contains the utilities/common functions of your application. 77 | 4- widgets — Contains the common widgets for your applications. For example, Button, TextField etc. 78 | 5- main.dart - This is the starting point of the application. All the application level configurations are defined in this file i.e, theme, routes, title, orientation etc. 79 | ``` 80 | 81 | ### Constants 82 | 83 | This directory contains all the application level constants. A separate file is created for each type as shown in example below: 84 | 85 | ``` 86 | constants/ 87 | |- assets.dart 88 | |- fonts.dart 89 | |- strings.dart 90 | |- text_styles.dart 91 | ``` 92 | 93 | ### UI 94 | 95 | This directory contains all the ui of your application. Each screen is located in a separate folder making it easy to combine group of files related to that particular screen. All the screen specific widgets will be placed in `widgets` directory as shown in the example below: 96 | 97 | ``` 98 | ui/ 99 | |- login 100 | |- login_screen.dart 101 | |- widgets 102 | |- login_form.dart 103 | |- login_button.dart 104 | ``` 105 | 106 | ### Utils 107 | 108 | Contains the common file(s) and utilities used in a project. The folder structure is as follows: 109 | 110 | ``` 111 | utils/ 112 | |- encryption 113 | |- xxtea.dart 114 | |- date 115 | |- date_time.dart 116 | ``` 117 | 118 | ### Widgets 119 | 120 | Contains the common widgets that are shared across multiple screens. For example, Button, TextField etc. 121 | 122 | ``` 123 | widgets/ 124 | |- app_icon_widget.dart 125 | |- empty_app_bar.dart 126 | |- progress_indicator.dart 127 | ``` 128 | 129 | ### Main 130 | 131 | This is the starting point of the application. All the application level configurations are defined in this file i.e, theme, routes, title, orientation etc. 132 | 133 | ``` 134 | import 'package:flutter_web/material.dart'; 135 | import 'package:portfolio/ui/home.dart'; 136 | 137 | import 'package:portfolio/utils/screen/screen_utils.dart'; 138 | 139 | void main() { 140 | runApp(MyApp()); 141 | } 142 | 143 | class MyApp extends StatelessWidget { 144 | 145 | @override 146 | Widget build(BuildContext context) { 147 | 148 | return MaterialApp( 149 | debugShowCheckedModeBanner: false, 150 | theme: ThemeData( 151 | brightness: Brightness.light, 152 | primaryColorBrightness: Brightness.light, 153 | accentColorBrightness: Brightness.light 154 | ), 155 | home: MyAppChild(), 156 | ); 157 | } 158 | } 159 | 160 | class MyAppChild extends StatefulWidget { 161 | 162 | @override 163 | _MyAppChildState createState() => _MyAppChildState(); 164 | } 165 | 166 | class _MyAppChildState extends State { 167 | @override 168 | Widget build(BuildContext context) { 169 | // instantiating ScreenUtil singleton instance, as this will be used throughout 170 | // the app to get screen size and other stuff 171 | ScreenUtil.instance = ScreenUtil.getInstance()..init(context); 172 | return HomePage(); 173 | } 174 | } 175 | ``` 176 | 177 | If you liked my work, don’t forget to ⭐ star the repo to show your support. 178 | -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | # Defines a default set of lint rules enforced for 2 | # projects at Google. For details and rationale, 3 | # see https://github.com/dart-lang/pedantic#enabled-lints. 4 | include: package:pedantic/analysis_options.yaml 5 | 6 | # For lint rules and documentation, see http://dart-lang.github.io/linter/lints. 7 | # Uncomment to specify additional rules. 8 | # linter: 9 | # rules: 10 | # - camel_case_types 11 | 12 | analyzer: 13 | # exclude: 14 | # - path/to/excluded/files/** 15 | -------------------------------------------------------------------------------- /android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java: -------------------------------------------------------------------------------- 1 | package io.flutter.plugins; 2 | 3 | import io.flutter.plugin.common.PluginRegistry; 4 | 5 | /** 6 | * Generated file. Do not edit. 7 | */ 8 | public final class GeneratedPluginRegistrant { 9 | public static void registerWith(PluginRegistry registry) { 10 | if (alreadyRegisteredWith(registry)) { 11 | return; 12 | } 13 | } 14 | 15 | private static boolean alreadyRegisteredWith(PluginRegistry registry) { 16 | final String key = GeneratedPluginRegistrant.class.getCanonicalName(); 17 | if (registry.hasPlugin(key)) { 18 | return true; 19 | } 20 | registry.registrarFor(key); 21 | return false; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /android/local.properties: -------------------------------------------------------------------------------- 1 | sdk.dir=/Users/macbookpro/Library/Android/sdk 2 | flutter.sdk=/Users/macbookpro/Documents/flutter -------------------------------------------------------------------------------- /ios/Flutter/Generated.xcconfig: -------------------------------------------------------------------------------- 1 | // This is a generated file; do not edit or check into version control. 2 | FLUTTER_ROOT=/Users/zubairehman/Desktop/flutter 3 | FLUTTER_APPLICATION_PATH=/Users/zubairehman/Desktop/Zubair/Practice Projects/outdoor_furniture 4 | FLUTTER_TARGET=lib/main.dart 5 | FLUTTER_BUILD_DIR=build 6 | SYMROOT=${SOURCE_ROOT}/../build/ios 7 | FLUTTER_FRAMEWORK_DIR=/Users/zubairehman/Desktop/flutter/bin/cache/artifacts/engine/ios 8 | -------------------------------------------------------------------------------- /ios/Runner/GeneratedPluginRegistrant.h: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | #ifndef GeneratedPluginRegistrant_h 6 | #define GeneratedPluginRegistrant_h 7 | 8 | #import 9 | 10 | @interface GeneratedPluginRegistrant : NSObject 11 | + (void)registerWithRegistry:(NSObject*)registry; 12 | @end 13 | 14 | #endif /* GeneratedPluginRegistrant_h */ 15 | -------------------------------------------------------------------------------- /ios/Runner/GeneratedPluginRegistrant.m: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | #import "GeneratedPluginRegistrant.h" 6 | 7 | @implementation GeneratedPluginRegistrant 8 | 9 | + (void)registerWithRegistry:(NSObject*)registry { 10 | } 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /lib/constants/assets.dart: -------------------------------------------------------------------------------- 1 | class Assets { 2 | Assets._(); 3 | 4 | static const String programmer3 = 'assets/images/programmer-3.gif'; 5 | 6 | // social icons 7 | static const String dribble = 'assets/icons/ic_dribbble.png'; 8 | static const String evernote = 'assets/icons/ic_evernote.png'; 9 | static const String google = 'assets/icons/ic_google.png'; 10 | static const String twitter = 'assets/icons/ic_twitter.png'; 11 | static const String linkedin = 'assets/icons/ic_linkedIn.png'; 12 | } -------------------------------------------------------------------------------- /lib/constants/fonts.dart: -------------------------------------------------------------------------------- 1 | class Fonts { 2 | Fonts._(); 3 | 4 | static const String product = 'ProductSans'; 5 | static const String nexa_light = 'NexaLight'; 6 | static const String nexa_bold = 'NexaBold'; 7 | 8 | } -------------------------------------------------------------------------------- /lib/constants/strings.dart: -------------------------------------------------------------------------------- 1 | class Strings { 2 | Strings._(); 3 | 4 | static const String about_me = 'About Me'; 5 | static const String about = 'About'; 6 | static const String me = ' Me'; 7 | static const String portfoli = 'Portfoli'; 8 | static const String o = 'o'; 9 | static const String headline = 'I\'am Zubair Rehman, Mobile App Developer from Islamabad, Pakistan'; 10 | static const String summary = 'Focused professional having excellent technical and communication skills, and offering 6 years of experience in Computer industry. Proficient at designing and formulating test automation frameworks, writing code in various languages, feature development and implementation. Specialize in thinking outside the box to find unique solutions to difficult engineering problems.'; 11 | static const String experience = 'Experience'; 12 | static const String skills_i_have = 'What Skill I Have'; 13 | static const String rights_reserved = '© 2019 IOTECK SOLUTIONS. ALL RIGHTS RESERVED.'; 14 | 15 | // menu items 16 | static const String menu_home = 'Home'; 17 | static const String menu_about = 'About'; 18 | static const String menu_contact = 'Contact'; 19 | 20 | } -------------------------------------------------------------------------------- /lib/constants/text_styles.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_web/material.dart'; 2 | import 'package:portfolio/constants/fonts.dart'; 3 | 4 | class TextStyles { 5 | TextStyles._(); 6 | 7 | static TextStyle get logo => TextStyle( 8 | fontFamily: Fonts.product, 9 | color: Color(0xFF45405B), 10 | fontSize: 22.0, //22.0 11 | fontWeight: FontWeight.bold, 12 | letterSpacing: 1.0, 13 | ); 14 | 15 | static TextStyle get menu_item => TextStyle( 16 | fontFamily: Fonts.product, 17 | fontSize: 12.0, //12,.0 18 | letterSpacing: 1.0, 19 | color: Color(0xFF45405B), 20 | ); 21 | 22 | static TextStyle get heading => TextStyle( 23 | fontFamily: Fonts.nexa_bold, 24 | color: Color(0xFF45405B), 25 | fontSize: 45.0, //45.0 26 | fontWeight: FontWeight.bold, 27 | letterSpacing: 1.0, 28 | ); 29 | 30 | static TextStyle get sub_heading => TextStyle( 31 | color: Color(0xFF45405B), 32 | fontFamily: Fonts.product, 33 | fontSize: 17.0, //17.0 34 | letterSpacing: 1.2, 35 | ); 36 | 37 | static TextStyle get company => TextStyle( 38 | fontFamily: Fonts.product, 39 | color: Color(0xFF45405B), 40 | height: 1.5, 41 | fontSize: 15.0, //15.0 42 | letterSpacing: 1.0, 43 | ); 44 | 45 | static TextStyle get body => TextStyle( 46 | fontFamily: Fonts.product, 47 | color: Color(0xFF85819C), 48 | height: 1.5, 49 | fontSize: 12.0, //12.0 50 | letterSpacing: 1.0, 51 | ); 52 | 53 | static TextStyle get body1 => TextStyle( 54 | fontFamily: Fonts.product, 55 | color: Color(0xFF85819C), 56 | height: 1.5, 57 | fontSize: 10.0, //10.0 58 | letterSpacing: 1.0, 59 | ); 60 | 61 | static TextStyle get chip => TextStyle( 62 | fontFamily: Fonts.product, 63 | color: Color(0xFF85819C), 64 | height: 1.5, 65 | fontSize: 12.0, //12.0 66 | letterSpacing: 1.0, 67 | ); 68 | } 69 | -------------------------------------------------------------------------------- /lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_web/material.dart'; 2 | import 'package:portfolio/ui/home.dart'; 3 | 4 | import 'package:portfolio/utils/screen/screen_utils.dart'; 5 | 6 | void main() { 7 | runApp(MyApp()); 8 | } 9 | 10 | class MyApp extends StatelessWidget { 11 | 12 | @override 13 | Widget build(BuildContext context) { 14 | 15 | return MaterialApp( 16 | debugShowCheckedModeBanner: false, 17 | theme: ThemeData( 18 | brightness: Brightness.light, 19 | primaryColorBrightness: Brightness.light, 20 | accentColorBrightness: Brightness.light 21 | ), 22 | home: MyAppChild(), 23 | ); 24 | } 25 | } 26 | 27 | class MyAppChild extends StatefulWidget { 28 | 29 | @override 30 | _MyAppChildState createState() => _MyAppChildState(); 31 | } 32 | 33 | class _MyAppChildState extends State { 34 | @override 35 | Widget build(BuildContext context) { 36 | // instantiating ScreenUtil singleton instance, as this will be used throughout 37 | // the app to get screen size and other stuff 38 | ScreenUtil.instance = ScreenUtil.getInstance()..init(context); 39 | return HomePage(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /lib/models/education.dart: -------------------------------------------------------------------------------- 1 | class Education { 2 | String from; 3 | String to; 4 | String organization; 5 | String post; 6 | 7 | Education(this.from, this.to, this.organization, this.post); 8 | } 9 | -------------------------------------------------------------------------------- /lib/ui/home.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_web/material.dart'; 2 | import 'package:portfolio/constants/assets.dart'; 3 | import 'package:portfolio/constants/fonts.dart'; 4 | import 'package:portfolio/constants/strings.dart'; 5 | import 'package:portfolio/constants/text_styles.dart'; 6 | import 'package:portfolio/models/education.dart'; 7 | import 'package:portfolio/utils/screen/screen_utils.dart'; 8 | import 'package:portfolio/widgets/responsive_widget.dart'; 9 | import 'dart:html' as html; 10 | 11 | class HomePage extends StatelessWidget { 12 | @override 13 | Widget build(BuildContext context) { 14 | return Material( 15 | color: Color(0xFFF7F8FA), 16 | child: Padding( 17 | padding: EdgeInsets.symmetric( 18 | horizontal: (ScreenUtil.getInstance().setWidth(108))), //144 19 | child: Scaffold( 20 | backgroundColor: Colors.transparent, 21 | appBar: _buildAppBar(context), 22 | drawer: _buildDrawer(context), 23 | body: LayoutBuilder(builder: (context, constraints) { 24 | return _buildBody(context, constraints); 25 | }), 26 | ), 27 | ), 28 | ); 29 | } 30 | 31 | //AppBar Methods:------------------------------------------------------------- 32 | Widget _buildAppBar(BuildContext context) { 33 | return AppBar( 34 | titleSpacing: 0.0, 35 | title: _buildTitle(), 36 | backgroundColor: Colors.transparent, 37 | elevation: 0.0, 38 | actions: 39 | !ResponsiveWidget.isSmallScreen(context) ? _buildActions() : null, 40 | ); 41 | } 42 | 43 | Widget _buildTitle() { 44 | return RichText( 45 | text: TextSpan( 46 | // Note: Styles for TextSpans must be explicitly defined. 47 | // Child text spans will inherit styles from parent 48 | style: TextStyle( 49 | fontSize: 14.0, 50 | color: Colors.black, 51 | ), 52 | children: [ 53 | TextSpan( 54 | text: Strings.portfoli, 55 | style: TextStyles.logo, 56 | ), 57 | TextSpan( 58 | text: Strings.o, 59 | style: TextStyles.logo.copyWith( 60 | color: Color(0xFF50AFC0), 61 | ), 62 | ), 63 | ], 64 | ), 65 | ); 66 | } 67 | 68 | List _buildActions() { 69 | return [ 70 | MaterialButton( 71 | child: Text( 72 | Strings.menu_home, 73 | style: TextStyles.menu_item.copyWith( 74 | color: Color(0xFF50AFC0), 75 | ), 76 | ), 77 | onPressed: () {}, 78 | ), 79 | MaterialButton( 80 | child: Text( 81 | Strings.menu_about, 82 | style: TextStyles.menu_item, 83 | ), 84 | onPressed: () {}, 85 | ), 86 | MaterialButton( 87 | child: Text( 88 | Strings.menu_contact, 89 | style: TextStyles.menu_item, 90 | ), 91 | onPressed: () {}, 92 | ), 93 | ]; 94 | } 95 | 96 | Widget _buildDrawer(BuildContext context) { 97 | return ResponsiveWidget.isSmallScreen(context) 98 | ? Drawer( 99 | child: ListView( 100 | padding: const EdgeInsets.all(20), 101 | children: _buildActions(), 102 | ), 103 | ) 104 | : null; 105 | } 106 | 107 | //Screen Methods:------------------------------------------------------------- 108 | Widget _buildBody(BuildContext context, BoxConstraints constraints) { 109 | return SingleChildScrollView( 110 | child: ConstrainedBox( 111 | constraints: BoxConstraints( 112 | minWidth: constraints.maxWidth, minHeight: constraints.maxHeight), 113 | child: ResponsiveWidget( 114 | largeScreen: _buildLargeScreen(context), 115 | mediumScreen: _buildMediumScreen(context), 116 | smallScreen: _buildSmallScreen(context), 117 | ), 118 | ), 119 | ); 120 | } 121 | 122 | Widget _buildLargeScreen(BuildContext context) { 123 | return IntrinsicHeight( 124 | child: Column( 125 | mainAxisSize: MainAxisSize.min, 126 | mainAxisAlignment: MainAxisAlignment.start, 127 | children: [ 128 | Expanded( 129 | child: Row( 130 | mainAxisSize: MainAxisSize.max, 131 | children: [ 132 | Expanded(flex: 1, child: _buildContent(context)), 133 | _buildIllustration(), 134 | ], 135 | ), 136 | ), 137 | _buildFooter(context) 138 | ], 139 | ), 140 | ); 141 | } 142 | 143 | Widget _buildMediumScreen(BuildContext context) { 144 | return IntrinsicHeight( 145 | child: Column( 146 | mainAxisSize: MainAxisSize.min, 147 | mainAxisAlignment: MainAxisAlignment.start, 148 | children: [ 149 | Expanded( 150 | child: Row( 151 | mainAxisSize: MainAxisSize.max, 152 | children: [ 153 | Expanded(flex: 1, child: _buildContent(context)), 154 | ], 155 | ), 156 | ), 157 | _buildFooter(context) 158 | ], 159 | ), 160 | ); 161 | } 162 | 163 | Widget _buildSmallScreen(BuildContext context) { 164 | return IntrinsicHeight( 165 | child: Column( 166 | mainAxisSize: MainAxisSize.min, 167 | children: [ 168 | Expanded(flex: 1, child: _buildContent(context)), 169 | Divider(), 170 | _buildCopyRightText(context), 171 | SizedBox( 172 | height: ResponsiveWidget.isSmallScreen(context) ? 12.0 : 0.0), 173 | _buildSocialIcons(), 174 | SizedBox( 175 | height: ResponsiveWidget.isSmallScreen(context) ? 12.0 : 0.0), 176 | ], 177 | ), 178 | ); 179 | } 180 | 181 | // Body Methods:-------------------------------------------------------------- 182 | Widget _buildIllustration() { 183 | return Image.network( 184 | Assets.programmer3, 185 | height: ScreenUtil.getInstance().setWidth(345), //480.0 186 | ); 187 | } 188 | 189 | Widget _buildContent(BuildContext context) { 190 | return Column( 191 | mainAxisSize: MainAxisSize.min, 192 | mainAxisAlignment: MainAxisAlignment.center, 193 | crossAxisAlignment: CrossAxisAlignment.start, 194 | children: [ 195 | SizedBox(height: ResponsiveWidget.isSmallScreen(context) ? 24.0 : 0.0), 196 | _buildAboutMe(context), 197 | SizedBox(height: 4.0), 198 | _buildHeadline(context), 199 | SizedBox(height: ResponsiveWidget.isSmallScreen(context) ? 12.0 : 24.0), 200 | _buildSummary(), 201 | SizedBox(height: ResponsiveWidget.isSmallScreen(context) ? 24.0 : 48.0), 202 | ResponsiveWidget.isSmallScreen(context) 203 | ? Column( 204 | mainAxisSize: MainAxisSize.min, 205 | crossAxisAlignment: CrossAxisAlignment.start, 206 | children: [ 207 | _buildEducation(), 208 | SizedBox(height: 24.0), 209 | _buildSkills(context), 210 | ], 211 | ) 212 | : _buildSkillsAndEducation(context) 213 | ], 214 | ); 215 | } 216 | 217 | Widget _buildAboutMe(BuildContext context) { 218 | return RichText( 219 | text: TextSpan( 220 | // Note: Styles for TextSpans must be explicitly defined. 221 | // Child text spans will inherit styles from parent 222 | style: TextStyle( 223 | fontSize: 14.0, 224 | color: Colors.black, 225 | ), 226 | children: [ 227 | TextSpan( 228 | text: Strings.about, 229 | style: TextStyles.heading.copyWith( 230 | fontFamily: Fonts.nexa_light, 231 | fontSize: ResponsiveWidget.isSmallScreen(context) ? 36 : 45.0, 232 | ), 233 | ), 234 | TextSpan( 235 | text: Strings.me, 236 | style: TextStyles.heading.copyWith( 237 | color: Color(0xFF50AFC0), 238 | fontSize: ResponsiveWidget.isSmallScreen(context) ? 36 : 45.0, 239 | ), 240 | ), 241 | ], 242 | ), 243 | ); 244 | } 245 | 246 | Widget _buildHeadline(BuildContext context) { 247 | return Text( 248 | ResponsiveWidget.isSmallScreen(context) 249 | ? Strings.headline 250 | : Strings.headline.replaceFirst(RegExp(r' f'), '\nf'), 251 | style: TextStyles.sub_heading, 252 | ); 253 | } 254 | 255 | Widget _buildSummary() { 256 | return Padding( 257 | padding: EdgeInsets.only(right: 80.0), 258 | child: Text( 259 | Strings.summary, 260 | style: TextStyles.body, 261 | ), 262 | ); 263 | } 264 | 265 | Widget _buildSkillsAndEducation(BuildContext context) { 266 | return Row( 267 | crossAxisAlignment: CrossAxisAlignment.start, 268 | children: [ 269 | Expanded( 270 | flex: 1, 271 | child: _buildEducation(), 272 | ), 273 | SizedBox(width: 40.0), 274 | Expanded( 275 | flex: 1, 276 | child: _buildSkills(context), 277 | ), 278 | ], 279 | ); 280 | } 281 | 282 | // Skills Methods:------------------------------------------------------------ 283 | final skills = [ 284 | 'Java', 285 | 'Kotlin', 286 | 'Dart', 287 | 'Flutter', 288 | 'Android', 289 | 'iOS', 290 | 'Xamarin', 291 | 'Reactive Programming', 292 | 'Jenkins', 293 | 'Photoshop', 294 | 'JFrog Atrtifactory', 295 | 'Code Magic', 296 | ]; 297 | 298 | Widget _buildSkills(BuildContext context) { 299 | final List widgets = skills 300 | .map((skill) => Padding( 301 | padding: EdgeInsets.only(right: 8.0), 302 | child: _buildSkillChip(context, skill), 303 | )) 304 | .toList(); 305 | 306 | return Column( 307 | mainAxisSize: MainAxisSize.max, 308 | crossAxisAlignment: CrossAxisAlignment.start, 309 | children: [ 310 | _buildSkillsContainerHeading(), 311 | Wrap(children: widgets), 312 | // _buildNavigationArrows(), 313 | ], 314 | ); 315 | } 316 | 317 | Widget _buildSkillsContainerHeading() { 318 | return Text( 319 | Strings.skills_i_have, 320 | style: TextStyles.sub_heading, 321 | ); 322 | } 323 | 324 | Widget _buildSkillChip(BuildContext context, String label) { 325 | return Chip( 326 | label: Text( 327 | label, 328 | style: TextStyles.chip.copyWith( 329 | fontSize: ResponsiveWidget.isSmallScreen(context) ? 10.0 : 11.0, 330 | ), 331 | ), 332 | ); 333 | } 334 | 335 | // Education Methods:--------------------------------------------------------- 336 | final educationList = [ 337 | Education( 338 | 'Apr 2018', 339 | 'Present', 340 | 'Embrace-it Pakistan', 341 | 'Sr. Software Engineer', 342 | ), 343 | Education( 344 | 'Apr 2016', 345 | 'Apr 2018', 346 | 'TEO International', 347 | 'Sr. Software Engineer', 348 | ), 349 | Education( 350 | 'July 2014', 351 | 'March 2016', 352 | 'Citrusbits', 353 | 'Software Engineer', 354 | ), 355 | ]; 356 | 357 | Widget _buildEducation() { 358 | return Column( 359 | crossAxisAlignment: CrossAxisAlignment.start, 360 | children: [ 361 | _buildEducationContainerHeading(), 362 | _buildEducationSummary(), 363 | SizedBox(height: 8.0), 364 | _buildEducationTimeline(), 365 | ], 366 | ); 367 | } 368 | 369 | Widget _buildEducationContainerHeading() { 370 | return Text( 371 | Strings.experience, 372 | style: TextStyles.sub_heading, 373 | ); 374 | } 375 | 376 | Widget _buildEducationSummary() { 377 | return Text( 378 | 'Lorem Ipsum is simply dummy text of the printing and typesetting industry.', 379 | style: TextStyles.body, 380 | ); 381 | } 382 | 383 | Widget _buildEducationTimeline() { 384 | final List widgets = educationList 385 | .map((education) => _buildEducationTile(education)) 386 | .toList(); 387 | return Column(children: widgets); 388 | } 389 | 390 | Widget _buildEducationTile(Education education) { 391 | return Padding( 392 | padding: EdgeInsets.symmetric(vertical: 8.0), 393 | child: Column( 394 | crossAxisAlignment: CrossAxisAlignment.stretch, 395 | children: [ 396 | Text( 397 | '${education.post}', 398 | style: TextStyles.company, 399 | ), 400 | Text( 401 | '${education.organization}', 402 | style: TextStyles.body.copyWith( 403 | color: Color(0xFF45405B), 404 | ), 405 | ), 406 | Text( 407 | '${education.from}-${education.to}', 408 | style: TextStyles.body, 409 | ), 410 | ], 411 | ), 412 | ); 413 | } 414 | 415 | // Footer Methods:------------------------------------------------------------ 416 | Widget _buildFooter(BuildContext context) { 417 | return Column( 418 | children: [ 419 | Divider(), 420 | Padding( 421 | padding: EdgeInsets.all(12.0), 422 | child: Row( 423 | mainAxisSize: MainAxisSize.max, 424 | mainAxisAlignment: MainAxisAlignment.spaceBetween, 425 | children: [ 426 | Align( 427 | child: _buildCopyRightText(context), 428 | alignment: Alignment.centerLeft, 429 | ), 430 | Align( 431 | child: _buildSocialIcons(), 432 | alignment: Alignment.centerRight, 433 | ), 434 | ], 435 | ), 436 | ), 437 | ], 438 | ); 439 | } 440 | 441 | Widget _buildCopyRightText(BuildContext context) { 442 | return Text( 443 | Strings.rights_reserved, 444 | style: TextStyles.body1.copyWith( 445 | fontSize: ResponsiveWidget.isSmallScreen(context) ? 8 : 10.0, 446 | ), 447 | ); 448 | } 449 | 450 | Widget _buildSocialIcons() { 451 | return Row( 452 | mainAxisSize: MainAxisSize.max, 453 | mainAxisAlignment: MainAxisAlignment.center, 454 | children: [ 455 | GestureDetector( 456 | onTap: () { 457 | html.window 458 | .open("https://www.linkedin.com/in/zubairehman/", "LinkedIn"); 459 | }, 460 | child: Image.network( 461 | Assets.linkedin, 462 | color: Color(0xFF45405B), 463 | height: 20.0, 464 | width: 20.0, 465 | ), 466 | ), 467 | SizedBox(width: 16.0), 468 | GestureDetector( 469 | onTap: () { 470 | html.window.open("https://medium.com/@zubairehman.work", "Medium"); 471 | }, 472 | child: Image.network( 473 | Assets.evernote, 474 | color: Color(0xFF45405B), 475 | height: 20.0, 476 | width: 20.0, 477 | ), 478 | ), 479 | SizedBox(width: 16.0), 480 | GestureDetector( 481 | onTap: () { 482 | html.window.open("https://github.com/zubairehman", "Github"); 483 | }, 484 | child: Image.network( 485 | Assets.google, 486 | color: Color(0xFF45405B), 487 | height: 20.0, 488 | width: 20.0, 489 | ), 490 | ), 491 | SizedBox(width: 16.0), 492 | GestureDetector( 493 | onTap: () { 494 | html.window.open("https://twitter.com/zubair340", "Twitter"); 495 | }, 496 | child: Image.network( 497 | Assets.twitter, 498 | color: Color(0xFF45405B), 499 | height: 20.0, 500 | width: 20.0, 501 | ), 502 | ), 503 | ], 504 | ); 505 | } 506 | } 507 | -------------------------------------------------------------------------------- /lib/utils/screen/screen_utils.dart: -------------------------------------------------------------------------------- 1 | /* 2 | * Created by 李卓原 on 2018/9/29. 3 | * email: zhuoyuan93@gmail.com 4 | */ 5 | 6 | import 'package:flutter_web/material.dart'; 7 | 8 | class ScreenUtil { 9 | static ScreenUtil instance = new ScreenUtil(); 10 | 11 | //设计稿的设备尺寸修改 12 | double width; 13 | double height; 14 | bool allowFontScaling; 15 | 16 | static MediaQueryData _mediaQueryData; 17 | static double _screenWidth; 18 | static double _screenHeight; 19 | static double _pixelRatio; 20 | static double _statusBarHeight; 21 | 22 | static double _bottomBarHeight; 23 | 24 | static double _textScaleFactor; 25 | 26 | ScreenUtil({ 27 | this.width = 1080, 28 | this.height = 1920, 29 | this.allowFontScaling = false, 30 | }); 31 | 32 | static ScreenUtil getInstance() { 33 | return instance; 34 | } 35 | 36 | void init(BuildContext context) { 37 | MediaQueryData mediaQuery = MediaQuery.of(context); 38 | _mediaQueryData = mediaQuery; 39 | _pixelRatio = mediaQuery.devicePixelRatio; 40 | _screenWidth = mediaQuery.size.width; 41 | _screenHeight = mediaQuery.size.height; 42 | _statusBarHeight = mediaQuery.padding.top; 43 | _bottomBarHeight = _mediaQueryData.padding.bottom; 44 | _textScaleFactor = mediaQuery.textScaleFactor; 45 | } 46 | 47 | static MediaQueryData get mediaQueryData => _mediaQueryData; 48 | 49 | ///每个逻辑像素的字体像素数,字体的缩放比例 50 | static double get textScaleFactory => _textScaleFactor; 51 | 52 | ///设备的像素密度 53 | static double get pixelRatio => _pixelRatio; 54 | 55 | ///当前设备宽度 dp 56 | static double get screenWidthDp => _screenWidth; 57 | 58 | ///当前设备高度 dp 59 | static double get screenHeightDp => _screenHeight; 60 | 61 | ///当前设备宽度 px 62 | static double get screenWidth => _screenWidth * _pixelRatio; 63 | 64 | ///当前设备高度 px 65 | static double get screenHeight => _screenHeight * _pixelRatio; 66 | 67 | ///状态栏高度 dp 刘海屏会更高 68 | static double get statusBarHeight => _statusBarHeight; 69 | 70 | ///底部安全区距离 dp 71 | static double get bottomBarHeight => _bottomBarHeight; 72 | 73 | ///实际的dp与设计稿px的比例 74 | get scaleWidth => _screenWidth / instance.width; 75 | 76 | get scaleHeight => _screenHeight / instance.height; 77 | 78 | ///根据设计稿的设备宽度适配 79 | ///高度也根据这个来做适配可以保证不变形 80 | setWidth(double width) => width * scaleWidth; 81 | 82 | /// 根据设计稿的设备高度适配 83 | /// 当发现设计稿中的一屏显示的与当前样式效果不符合时, 84 | /// 或者形状有差异时,高度适配建议使用此方法 85 | /// 高度适配主要针对想根据设计稿的一屏展示一样的效果 86 | setHeight(double height) => height * scaleHeight; 87 | 88 | ///字体大小适配方法 89 | ///@param fontSize 传入设计稿上字体的px , 90 | ///@param allowFontScaling 控制字体是否要根据系统的“字体大小”辅助选项来进行缩放。默认值为false。 91 | ///@param allowFontScaling Specifies whether fonts should scale to respect Text Size accessibility settings. The default is false. 92 | setSp(double fontSize) => allowFontScaling 93 | ? setWidth(fontSize) 94 | : setWidth(fontSize) / _textScaleFactor; 95 | } -------------------------------------------------------------------------------- /lib/widgets/responsive_widget.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_web/material.dart'; 2 | 3 | class ResponsiveWidget extends StatelessWidget { 4 | final Widget largeScreen; 5 | final Widget mediumScreen; 6 | final Widget smallScreen; 7 | 8 | const ResponsiveWidget( 9 | {Key key, 10 | @required this.largeScreen, 11 | this.mediumScreen, 12 | this.smallScreen}) 13 | : super(key: key); 14 | 15 | static bool isSmallScreen(BuildContext context) { 16 | return MediaQuery.of(context).size.width < 768; 17 | } 18 | 19 | static bool isLargeScreen(BuildContext context) { 20 | return MediaQuery.of(context).size.width > 768; 21 | } 22 | 23 | static bool isMediumScreen(BuildContext context) { 24 | return MediaQuery.of(context).size.width > 768 && 25 | MediaQuery.of(context).size.width < 1200; 26 | } 27 | 28 | @override 29 | Widget build(BuildContext context) { 30 | return LayoutBuilder( 31 | builder: (context, constraints) { 32 | if (constraints.maxWidth > 768) { 33 | return largeScreen; 34 | } else if (constraints.maxWidth < 1200 && constraints.maxWidth > 425) { 35 | return mediumScreen ?? largeScreen; 36 | } else { 37 | return smallScreen ?? largeScreen; 38 | } 39 | }, 40 | ); 41 | } 42 | } -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: portfolio 2 | description: A portfolio build by using flutter for web. 3 | # version: 1.0.0 4 | #homepage: http://zubair-portfolio.surge.sh/#/ 5 | #author: zubairehman 6 | 7 | environment: 8 | sdk: '>=2.2.0 <3.0.0' 9 | 10 | dependencies: 11 | flutter_web: any 12 | flutter_web_ui: any 13 | 14 | dev_dependencies: 15 | # Enables the `pub run build_runner` command 16 | build_runner: ^1.6.5 17 | 18 | # Includes the JavaScript compilers 19 | build_web_compilers: ^2.1.5 20 | 21 | # The Font Awesome Icon pack available as Flutter Icons. 22 | font_awesome: any 23 | 24 | # font_awesome_flutter: ^8.5.0 25 | 26 | # flutter_web packages are not published to pub.dartlang.org 27 | # These overrides tell the package tools to get them from GitHub 28 | dependency_overrides: 29 | flutter_web: 30 | git: 31 | url: https://github.com/flutter/flutter_web 32 | path: packages/flutter_web 33 | flutter_web_ui: 34 | git: 35 | url: https://github.com/flutter/flutter_web 36 | path: packages/flutter_web_ui 37 | 38 | flutter: 39 | uses-material-design: true 40 | -------------------------------------------------------------------------------- /screenshots/portfolio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ezin-rev/portfolio-flutter/9fb3d9728e65745c99d48e94ec2e844ca7a05f5e/screenshots/portfolio.png -------------------------------------------------------------------------------- /web/assets/FontManifest.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "fonts": [ 4 | { 5 | "asset": "fonts/MaterialIcons-Regular.ttf" 6 | } 7 | ], 8 | "family": "MaterialIcons" 9 | }, 10 | { 11 | "fonts": [ 12 | { 13 | "asset": "fonts/Quicksand-Regular.otf" 14 | } 15 | ], 16 | "family": "Quicksand" 17 | }, 18 | { 19 | "fonts": [ 20 | { 21 | "asset": "fonts/Product-Sans-Regular.ttf" 22 | } 23 | ], 24 | "family": "ProductSans" 25 | }, 26 | { 27 | "fonts": [ 28 | { 29 | "asset": "fonts/Nexa-Bold.otf" 30 | } 31 | ], 32 | "family": "NexaBold" 33 | }, 34 | { 35 | "fonts": [ 36 | { 37 | "asset": "fonts/Nexa-Light.otf" 38 | } 39 | ], 40 | "family": "NexaLight" 41 | } 42 | ] -------------------------------------------------------------------------------- /web/assets/fonts/MaterialIcons-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ezin-rev/portfolio-flutter/9fb3d9728e65745c99d48e94ec2e844ca7a05f5e/web/assets/fonts/MaterialIcons-Regular.ttf -------------------------------------------------------------------------------- /web/assets/fonts/Nexa-Bold.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ezin-rev/portfolio-flutter/9fb3d9728e65745c99d48e94ec2e844ca7a05f5e/web/assets/fonts/Nexa-Bold.otf -------------------------------------------------------------------------------- /web/assets/fonts/Nexa-Light.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ezin-rev/portfolio-flutter/9fb3d9728e65745c99d48e94ec2e844ca7a05f5e/web/assets/fonts/Nexa-Light.otf -------------------------------------------------------------------------------- /web/assets/fonts/Product-Sans-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ezin-rev/portfolio-flutter/9fb3d9728e65745c99d48e94ec2e844ca7a05f5e/web/assets/fonts/Product-Sans-Regular.ttf -------------------------------------------------------------------------------- /web/assets/fonts/Quicksand-Regular.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ezin-rev/portfolio-flutter/9fb3d9728e65745c99d48e94ec2e844ca7a05f5e/web/assets/fonts/Quicksand-Regular.otf -------------------------------------------------------------------------------- /web/assets/icons/ic_dribbble.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ezin-rev/portfolio-flutter/9fb3d9728e65745c99d48e94ec2e844ca7a05f5e/web/assets/icons/ic_dribbble.png -------------------------------------------------------------------------------- /web/assets/icons/ic_evernote.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ezin-rev/portfolio-flutter/9fb3d9728e65745c99d48e94ec2e844ca7a05f5e/web/assets/icons/ic_evernote.png -------------------------------------------------------------------------------- /web/assets/icons/ic_google.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ezin-rev/portfolio-flutter/9fb3d9728e65745c99d48e94ec2e844ca7a05f5e/web/assets/icons/ic_google.png -------------------------------------------------------------------------------- /web/assets/icons/ic_linkedIn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ezin-rev/portfolio-flutter/9fb3d9728e65745c99d48e94ec2e844ca7a05f5e/web/assets/icons/ic_linkedIn.png -------------------------------------------------------------------------------- /web/assets/icons/ic_twitter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ezin-rev/portfolio-flutter/9fb3d9728e65745c99d48e94ec2e844ca7a05f5e/web/assets/icons/ic_twitter.png -------------------------------------------------------------------------------- /web/assets/images/programmer-3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ezin-rev/portfolio-flutter/9fb3d9728e65745c99d48e94ec2e844ca7a05f5e/web/assets/images/programmer-3.gif -------------------------------------------------------------------------------- /web/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ezin-rev/portfolio-flutter/9fb3d9728e65745c99d48e94ec2e844ca7a05f5e/web/favicon.ico -------------------------------------------------------------------------------- /web/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Portfolio 6 | 22 | 66 | 67 | 68 | 69 |
70 |
71 |
72 |
73 | 74 | 75 | -------------------------------------------------------------------------------- /web/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:portfolio/main.dart' as app; 2 | import 'package:flutter_web_ui/ui.dart' as ui; 3 | 4 | main() async { 5 | await ui.webOnlyInitializePlatform(); 6 | app.main(); 7 | } 8 | --------------------------------------------------------------------------------