diff --git a/assets/images/drops.png b/assets/images/drops.png new file mode 100644 index 0000000..67ea18d Binary files /dev/null and b/assets/images/drops.png differ diff --git a/assets/images/inhalers.jpg b/assets/images/inhalers.jpg new file mode 100644 index 0000000..8595ae2 Binary files /dev/null and b/assets/images/inhalers.jpg differ diff --git a/assets/images/injection.jpg b/assets/images/injection.jpg new file mode 100644 index 0000000..ab8a684 Binary files /dev/null and b/assets/images/injection.jpg differ diff --git a/assets/images/liquid.png b/assets/images/liquid.png new file mode 100644 index 0000000..5bbac6b Binary files /dev/null and b/assets/images/liquid.png differ diff --git a/assets/images/pills2.png b/assets/images/pills2.png new file mode 100644 index 0000000..203eb72 Binary files /dev/null and b/assets/images/pills2.png differ diff --git a/assets/images/profile.png b/assets/images/profile.png new file mode 100644 index 0000000..2c6d6a8 Binary files /dev/null and b/assets/images/profile.png differ diff --git a/assets/images/tropical.png b/assets/images/tropical.png new file mode 100644 index 0000000..3fd5542 Binary files /dev/null and b/assets/images/tropical.png differ diff --git a/lib/components/nav_bar.dart b/lib/components/nav_bar.dart new file mode 100644 index 0000000..8449ee5 --- /dev/null +++ b/lib/components/nav_bar.dart @@ -0,0 +1,46 @@ +import 'package:brianpharmacy/constraints.dart'; +import 'package:flutter/material.dart'; + +class MyNavBar extends StatelessWidget { + const MyNavBar({ + super.key, + }); + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.only( + left: kDefaultPadding * 2, + right: kDefaultPadding * 2, + bottom: kDefaultPadding, + ), + height: 80, + decoration: BoxDecoration( + color: Colors.white, + boxShadow: [ + BoxShadow( + blurRadius: 35, + offset: const Offset(0, -10), + color: kPrimaryColor.withOpacity(0.38)), + ], + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + IconButton( + onPressed: () {}, + icon: const Icon(Icons.home), + ), + IconButton( + onPressed: () {}, + icon: const Icon(Icons.notifications), + ), + IconButton( + onPressed: () {}, + icon: const Icon(Icons.settings), + ), + ], + ), + ); + } +} diff --git a/lib/constraints.dart b/lib/constraints.dart new file mode 100644 index 0000000..354effe --- /dev/null +++ b/lib/constraints.dart @@ -0,0 +1,8 @@ +import 'package:flutter/material.dart'; + +//Colors for the app +const kPrimaryColor = Color.fromARGB(255, 18, 56, 180); +const kTextColor = Color.fromARGB(255, 0, 0, 0); +const kBackgroundColor = Color(0xFFF9F8FD); + +const double kDefaultPadding = 20.0; diff --git a/lib/main.dart b/lib/main.dart index aac10b5..b9ec233 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,120 +1,27 @@ +import 'package:brianpharmacy/constraints.dart'; +import 'package:brianpharmacy/screens/dashboard/home.dart'; import 'package:brianpharmacy/screens/onboarding/onboarding.dart'; import 'package:flutter/material.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', + title: 'Brian Pharamcy', + debugShowCheckedModeBanner: false, theme: ThemeData( - // This is the theme of your application. - // - // Try running your application with "flutter run". You'll see the - // application has a blue toolbar. Then, without quitting the app, try - // changing the primarySwatch below to Colors.green and then invoke - // "hot reload" (press "r" in the console where you ran "flutter run", - // or simply save your changes to "hot reload" in a Flutter IDE). - // Notice that the counter didn't reset back to zero; the application - // is not restarted. - primarySwatch: Colors.blue, - ), - home: const OnboardingScreen(), + scaffoldBackgroundColor: kBackgroundColor, + primaryColor: kPrimaryColor, + textTheme: Theme.of(context).textTheme.apply(bodyColor: kTextColor), + visualDensity: VisualDensity.adaptivePlatformDensity), + home: const HomePage(), ); } } - - -// 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( -// // 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. -// // -// // Invoke "debug painting" (press "p" in the console, choose the -// // "Toggle Debug Paint" action from the Flutter Inspector in Android -// // Studio, or the "Toggle Debug Paint" command in Visual Studio Code) -// // to see the wireframe for each widget. -// // -// // 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). -// 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. -// ); -// } -// } diff --git a/lib/screens/dashboard/components/body.dart b/lib/screens/dashboard/components/body.dart new file mode 100644 index 0000000..5427c36 --- /dev/null +++ b/lib/screens/dashboard/components/body.dart @@ -0,0 +1,37 @@ +import 'package:brianpharmacy/constraints.dart'; +import 'package:brianpharmacy/screens/dashboard/components/doctors_list.dart'; +import 'package:brianpharmacy/screens/dashboard/components/header_with_search_bar.dart'; +import 'package:brianpharmacy/screens/dashboard/components/recomended_categories.dart'; +import 'package:brianpharmacy/screens/dashboard/components/title_with_more_btn.dart'; +import 'package:flutter/material.dart'; + +class Body extends StatelessWidget { + const Body({super.key}); + + @override + Widget build(BuildContext context) { + // This will provide us the total height and width of our screen + Size size = MediaQuery.of(context).size; + // this enables scrolling + return SingleChildScrollView( + child: Column( + children: [ + HeaderWithSearchBox(size: size), + TitleWithBtn( + title: "Categories", + press: () {}, + ), + const RecomendedCategories(), + TitleWithBtn( + title: "Doctors", + press: () {}, + ), + const DoctorsList(), + const SizedBox( + height: kDefaultPadding, + ) + ], + ), + ); + } +} \ No newline at end of file diff --git a/lib/screens/dashboard/components/doctors_list.dart b/lib/screens/dashboard/components/doctors_list.dart new file mode 100644 index 0000000..9eb982c --- /dev/null +++ b/lib/screens/dashboard/components/doctors_list.dart @@ -0,0 +1,94 @@ +import 'package:brianpharmacy/constraints.dart'; +import 'package:flutter/material.dart'; + +class DoctorsList extends StatelessWidget { + const DoctorsList({ + super.key, + }); + + @override + Widget build(BuildContext context) { + return SingleChildScrollView( + child: Column( + children: [ + DoctorsTile( + image: "assets/images/profile.png", + title: "Marcus James", + subtitle: "Orthodontist", + press: () {}, + ), + DoctorsTile( + image: "assets/images/profile.png", + title: "Juliet Akoth", + subtitle: "Psychiatrists", + press: () {}, + ), + DoctorsTile( + image: "assets/images/profile.png", + title: "Joe Doe", + subtitle: "Neurologists", + press: () {}, + ), + ], + ), + ); + } +} + +class DoctorsTile extends StatelessWidget { + const DoctorsTile({ + super.key, + required this.image, + required this.title, + required this.subtitle, + required this.press, + }); + final String image, title, subtitle; + final VoidCallback press; + + @override + Widget build(BuildContext context) { + Size size = MediaQuery.of(context).size; + return Container( + margin: const EdgeInsets.only( + left: kDefaultPadding, + top: kDefaultPadding / 2, + bottom: kDefaultPadding / 10, + ), + width: size.width * 1, + height: 100, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + ), + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Container( + color: Colors.transparent, + child: GestureDetector( + onTap: press, + child: ListTile( + leading: CircleAvatar( + radius: 30, // Image radius + backgroundImage: AssetImage(image), + ), + title: Text( + title, + textScaleFactor: 1.5, + ), + trailing: IconButton( + onPressed: () {}, + icon: const Icon(Icons.bookmark_add_outlined)), + subtitle: Text(subtitle), + selected: true, + onTap: () {}, + ), + ), + ), + ), + ], + ), + ); + } +} diff --git a/lib/screens/dashboard/components/header_with_search_bar.dart b/lib/screens/dashboard/components/header_with_search_bar.dart new file mode 100644 index 0000000..0e95085 --- /dev/null +++ b/lib/screens/dashboard/components/header_with_search_bar.dart @@ -0,0 +1,93 @@ +import 'package:brianpharmacy/constraints.dart'; +import 'package:flutter/material.dart'; + +class HeaderWithSearchBox extends StatelessWidget { + const HeaderWithSearchBox({ + super.key, + required this.size, + }); + + final Size size; + + @override + Widget build(BuildContext context) { + return Container( + margin: const EdgeInsets.only(bottom: kDefaultPadding * 2.5), + // this will cover 20% of our total height + height: size.height * 0.2, + child: Stack( + children: [ + Container( + padding: const EdgeInsets.only( + left: kDefaultPadding, + right: kDefaultPadding, + bottom: 36 + kDefaultPadding), + height: size.height * 0.2 - 27, + decoration: const BoxDecoration( + color: kPrimaryColor, + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular(36), + bottomRight: Radius.circular(36), + ), + ), + child: Row( + children: [ + Text( + "Welcome Brian K!", + style: Theme.of(context).textTheme.headlineSmall?.copyWith( + color: Colors.white, fontWeight: FontWeight.bold), + ), + const Spacer(), + const CircleAvatar( + radius: 30, // Image radius + backgroundImage: AssetImage("assets/images/profile.png"), + ) + ], + )), + Positioned( + bottom: 0, + left: 0, + right: 0, + child: Container( + alignment: Alignment.center, + margin: const EdgeInsets.symmetric(horizontal: kDefaultPadding), + height: 54, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(20), + boxShadow: [ + BoxShadow( + offset: const Offset(0, 10), + blurRadius: 50, + color: kPrimaryColor.withOpacity(0.23), + ), + ], + ), + child: Row( + children: [ + Expanded( + child: Padding( + padding: const EdgeInsets.only(left: 20), + child: TextField( + onChanged: (value) {}, + decoration: InputDecoration( + hintText: "Search", + hintStyle: TextStyle( + color: kPrimaryColor.withOpacity(0.5), + ), + enabledBorder: InputBorder.none, + focusedBorder: InputBorder.none, + suffixIcon: const Icon(Icons.search_rounded), + ), + ), + ), + ), + ], + ), + ), + ), + ], + ), + ); + } +} diff --git a/lib/screens/dashboard/components/recomended_categories.dart b/lib/screens/dashboard/components/recomended_categories.dart new file mode 100644 index 0000000..e4e9de0 --- /dev/null +++ b/lib/screens/dashboard/components/recomended_categories.dart @@ -0,0 +1,108 @@ +import 'package:brianpharmacy/constraints.dart'; +import 'package:flutter/material.dart'; + +class RecomendedCategories extends StatelessWidget { + const RecomendedCategories({ + super.key, + }); + + @override + Widget build(BuildContext context) { + return SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Row( + children: [ + RecomendedDrugs( + image: "assets/images/pills2.png", + title: "Pills", + press: () {}, + ), + RecomendedDrugs( + image: "assets/images/drops.png", + title: "Drops", + press: () {}, + ), + RecomendedDrugs( + image: "assets/images/inhalers.jpg", + title: "Inhalers", + press: () {}, + ), + RecomendedDrugs( + image: "assets/images/liquid.png", + title: "Liquid", + press: () {}, + ), + RecomendedDrugs( + image: "assets/images/injection.jpg", + title: "Injection", + press: () {}, + ), + RecomendedDrugs( + image: "assets/images/tropical.png", + title: "Tropical", + press: () {}, + ), + ], + ), + ); + } +} + +class RecomendedDrugs extends StatelessWidget { + const RecomendedDrugs({ + super.key, + required this.image, + required this.title, + required this.press, + }); + + final String image, title; + final VoidCallback press; + + @override + Widget build(BuildContext context) { + Size size = MediaQuery.of(context).size; + return Container( + margin: const EdgeInsets.only( + left: kDefaultPadding, + top: kDefaultPadding / 5, + bottom: kDefaultPadding / 4, + ), + width: size.width * 0.7, + child: Column( + children: [ + ClipRRect( + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(10.0), + topRight: Radius.circular(10.0)), + child: Image.asset(image), + ), + GestureDetector( + onTap: press, + child: Container( + padding: const EdgeInsets.all(kDefaultPadding / 1), + decoration: BoxDecoration( + borderRadius: const BorderRadius.only( + bottomLeft: Radius.circular(10.0), + bottomRight: Radius.circular(10.0)), + color: Colors.white, + boxShadow: [ + BoxShadow( + offset: const Offset(0, 10), + blurRadius: 50, + color: kPrimaryColor.withOpacity(0.23)), + ], + ), + child: Row(children: [ + Text( + title.toUpperCase(), + style: Theme.of(context).textTheme.bodySmall, + ) + ]), + ), + ) + ], + ), + ); + } +} diff --git a/lib/screens/dashboard/components/title_with_more_btn.dart b/lib/screens/dashboard/components/title_with_more_btn.dart new file mode 100644 index 0000000..da190da --- /dev/null +++ b/lib/screens/dashboard/components/title_with_more_btn.dart @@ -0,0 +1,64 @@ +import 'package:brianpharmacy/constraints.dart'; +import 'package:flutter/material.dart'; + +class TitleWithBtn extends StatelessWidget { + const TitleWithBtn({ + super.key, + required this.title, + required this.press, + }); + final String title; + final VoidCallback press; + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: kDefaultPadding), + child: Row( + children: [ + Title(text: title), + const Spacer(), + ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: kPrimaryColor, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20), + ), + ), + onPressed: press, + child: const Text("More", style: TextStyle(color: Colors.white)), + ), + ], + ), + ); + } +} + +class Title extends StatelessWidget { + const Title({ + super.key, + required this.text, + }); + final String text; + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.all(0.0), + height: 24, + child: Stack( + children: [ + Padding( + padding: const EdgeInsets.only(left: kDefaultPadding / 4), + child: Text( + text, + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.bold, + color: Colors.blue[900]), + ), + ), + ], + ), + ); + } +} diff --git a/lib/screens/dashboard/home.dart b/lib/screens/dashboard/home.dart index dc394f9..c7560bb 100644 --- a/lib/screens/dashboard/home.dart +++ b/lib/screens/dashboard/home.dart @@ -1,28 +1,30 @@ +import 'package:brianpharmacy/components/nav_bar.dart'; +import 'package:brianpharmacy/constraints.dart'; +import 'package:brianpharmacy/screens/dashboard/components/body.dart'; import 'package:flutter/material.dart'; -class HomePage extends StatefulWidget { +class HomePage extends StatelessWidget { const HomePage({super.key}); - @override - State createState() => _HomePageState(); -} - -class _HomePageState extends State { @override Widget build(BuildContext context) { - return SafeArea( - child: Scaffold( - appBar: AppBar( - leading: IconButton( - onPressed: () {}, - icon: const Icon( - Icons.arrow_back_rounded, - ), - ), - title: const Text("Dashboard"), + return Scaffold( + appBar: buildAppBar(), + body: const Body(), + bottomNavigationBar: const MyNavBar(), + ); + } + + AppBar buildAppBar() { + return AppBar( + backgroundColor: kPrimaryColor, + elevation: 0, + leading: IconButton( + onPressed: () {}, + icon: const Icon( + Icons.more_vert_rounded, ), - body: const Center(child: Text("This is the home screen")), ), ); } -} +} \ No newline at end of file diff --git a/lib/screens/onboarding/onboarding.dart b/lib/screens/onboarding/onboarding.dart index 4921666..8671c3d 100644 --- a/lib/screens/onboarding/onboarding.dart +++ b/lib/screens/onboarding/onboarding.dart @@ -69,7 +69,7 @@ class _OnboardingScreenState extends State { ), bottomSheet: isLastPage ? Container( - color: Color.fromARGB(0, 255, 255, 255), + color: const Color.fromARGB(0, 255, 255, 255), padding: const EdgeInsets.only( bottom: 2, right: 4, @@ -80,20 +80,20 @@ class _OnboardingScreenState extends State { elevation: 2, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(50)), - backgroundColor: (Color.fromARGB(255, 151, 26, 22)), + backgroundColor: (const Color.fromARGB(255, 151, 26, 22)), minimumSize: const Size.fromHeight(50)), child: const Text( 'Get Started', style: TextStyle(fontSize: 24), ), onPressed: () async { - //navigate directly to auth screen + // navigate directly to auth screen final prefs = await SharedPreferences.getInstance(); prefs.setBool('testpage', true); Navigator.of(context).pushReplacement( MaterialPageRoute( - builder: (context) => HomePage(), + builder: (context) => const HomePage(), ), ); }, diff --git a/pubspec.lock b/pubspec.lock index d121283..c93de0a 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -25,6 +25,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.1" + charcode: + dependency: transitive + description: + name: charcode + sha256: fb98c0f6d12c920a02ee2d998da788bca066ca5f148492b7085ee23372b12306 + url: "https://pub.dev" + source: hosted + version: "1.3.1" clock: dependency: transitive description: @@ -41,6 +49,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.17.0" + convert: + dependency: transitive + description: + name: convert + sha256: "3fa83bc417e26f1d55814443a603747d48e3cdf55b2f4fea27dea8e9224dcefd" + url: "https://pub.dev" + source: hosted + version: "2.1.1" cupertino_icons: dependency: "direct main" description: @@ -86,6 +102,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.1" + flutter_svg: + dependency: "direct main" + description: + name: flutter_svg + sha256: "565738e46beb692622c0fad7419aabcc54d15693845049085948c76406da386f" + url: "https://pub.dev" + source: hosted + version: "0.17.4" flutter_test: dependency: "direct dev" description: flutter @@ -144,6 +168,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.8.2" + path_drawing: + dependency: transitive + description: + name: path_drawing + sha256: b3dd74e2210b2b71be3d3098b956dbab853ee43a86918b4bc20c9b9bd49f03f3 + url: "https://pub.dev" + source: hosted + version: "0.4.1+1" + path_parsing: + dependency: transitive + description: + name: path_parsing + sha256: "4e613c811d25f1533c0d05eb2755e21410247b8a13ac7f6cd23c0cecb2ff683d" + url: "https://pub.dev" + source: hosted + version: "0.1.4" path_provider_linux: dependency: transitive description: @@ -168,6 +208,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + petitparser: + dependency: transitive + description: + name: petitparser + sha256: fe07f9345bf03ff0c881d1f5494e20cc40206780ca5dea86aab8037cb49af5f2 + url: "https://pub.dev" + source: hosted + version: "3.1.0" platform: dependency: transitive description: @@ -309,6 +357,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.4.16" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: "26f87ade979c47a150c9eaab93ccd2bebe70a27dc0b4b29517f2904f04eb11a5" + url: "https://pub.dev" + source: hosted + version: "1.3.1" vector_math: dependency: transitive description: @@ -333,6 +389,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.0" + xml: + dependency: transitive + description: + name: xml + sha256: a11fbb305f75dd200c96d3fd13f9fdb4bc8d8dcdb5331f6ba15c57acb950ef09 + url: "https://pub.dev" + source: hosted + version: "3.7.0" sdks: dart: ">=2.19.1 <3.0.0" flutter: ">=3.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index 4ca341b..a0db883 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -37,6 +37,7 @@ dependencies: cupertino_icons: ^1.0.2 smooth_page_indicator: ^1.0.1 shared_preferences: ^2.0.18 + flutter_svg: ^0.17.4 dev_dependencies: flutter_test: @@ -62,6 +63,7 @@ flutter: # To add assets to your application, add an assets section, like this: assets: + - assets/icons/ - assets/images/ # - images/a_dot_ham.jpeg