html element with children.
+ yield div(classes: 'main', [
+ const Home(),
+ ]);
+ }
+
+ // Defines the css styles for elements of this component.
+ //
+ // By using the @css annotation, these will be rendered automatically to css inside the of your page.
+ // Must be a variable or getter of type [List
].
+ @css
+ static final styles = [
+ css('.main', [
+ css('p').text(color: Colors.white),
+ css('a').text(color: Colors.white),
+ css('h1').text(color: Colors.white),
+ css('h2').text(color: Colors.white),
+ css('span').text(color: Colors.white),
+ ]),
+ ];
+}
diff --git a/lib/components/app_button.dart b/lib/components/app_button.dart
new file mode 100644
index 0000000..7e44824
--- /dev/null
+++ b/lib/components/app_button.dart
@@ -0,0 +1,66 @@
+import 'package:devfolio/constants/theme.dart';
+import 'package:jaspr/jaspr.dart';
+
+@client
+class AppButton extends StatelessComponent {
+ final String label;
+ final String href;
+
+ final Unit? width;
+ final Unit? height;
+
+ const AppButton({
+ super.key,
+ required this.label,
+ required this.href,
+ this.width,
+ this.height,
+ });
+
+ @override
+ Iterable build(BuildContext context) sync* {
+ yield a(
+ classes: 'app-button',
+ target: Target.blank,
+ styles: Styles.box(width: width, height: height),
+ href: href,
+ [
+ span(classes: 'label', [text(label)])
+ ],
+ );
+ }
+
+ @css
+ static final List styles = [
+ css('.app-button')
+ .box(
+ width: 100.px,
+ padding: EdgeInsets.all(10.px),
+ radius: BorderRadius.circular(6.px),
+ border: Border.all(BorderSide(
+ color: themePrimaryColor,
+ width: 1.px,
+ )),
+ )
+ .flexbox(
+ direction: FlexDirection.row,
+ alignItems: AlignItems.center,
+ justifyContent: JustifyContent.center,
+ )
+ .text(
+ decoration: TextDecoration.none,
+ )
+ .background(
+ color: Colors.transparent,
+ ),
+ css('.app-button:hover')
+ .background(
+ color: themePrimaryColor,
+ )
+ .box(
+ transition: Transition('background-color', duration: 500),
+ cursor: Cursor.pointer,
+ ),
+ css('.label').text(fontSize: 12.px),
+ ];
+}
diff --git a/lib/components/contact.dart b/lib/components/contact.dart
new file mode 100644
index 0000000..e84f471
--- /dev/null
+++ b/lib/components/contact.dart
@@ -0,0 +1,75 @@
+import 'package:devfolio/constants/theme.dart';
+import 'package:jaspr/jaspr.dart';
+
+@client
+class ContactCard extends StatelessComponent {
+ final String icon;
+ final String title;
+ final String description;
+ final String action;
+ const ContactCard({
+ required this.icon,
+ required this.title,
+ required this.description,
+ required this.action,
+ });
+
+ @override
+ Iterable build(BuildContext context) sync* {
+ yield a(href: action, target: Target.blank, classes: 'contact-card', [
+ i(classes: '$icon c-icon', []),
+ span(classes: 'c-title', [
+ text(title),
+ ]),
+ span(classes: 'c-description', [
+ text(description),
+ ]),
+ ]);
+ }
+
+ @css
+ static final List styles = [
+ css('.contact-card')
+ .text(decoration: TextDecoration.none)
+ .flexbox(
+ direction: FlexDirection.column,
+ alignItems: AlignItems.center,
+ justifyContent: JustifyContent.center,
+ )
+ .box(
+ width: 300.px,
+ height: 150.px,
+ padding: EdgeInsets.all(15.px),
+ radius: BorderRadius.circular(12.px),
+ margin: EdgeInsets.only(top: 25.px, left: 15.px, right: 15.px),
+ )
+ .background(
+ color: themeDarkGreyColor,
+ ),
+ css('.contact-card:hover').box(
+ shadow: BoxShadow(
+ color: themePrimaryColor,
+ offsetX: 0.px,
+ offsetY: 0.px,
+ blur: 8.px,
+ spread: 2.px,
+ ),
+ transition: Transition('box-shadow', duration: 500),
+ ),
+ css('.c-icon').text(
+ fontSize: 50.px,
+ color: themePrimaryColor,
+ ),
+ css('.c-title')
+ .text(
+ fontSize: 15.px,
+ color: themePrimaryColor,
+ )
+ .box(
+ margin: EdgeInsets.symmetric(vertical: 15.px),
+ ),
+ css('.c-description').text(
+ fontSize: 12.px,
+ ),
+ ];
+}
diff --git a/lib/components/footer.dart b/lib/components/footer.dart
new file mode 100644
index 0000000..8067068
--- /dev/null
+++ b/lib/components/footer.dart
@@ -0,0 +1,39 @@
+import 'package:jaspr/jaspr.dart';
+
+@client
+class Footer extends StatelessComponent {
+ const Footer({super.key});
+
+ @override
+ Iterable build(BuildContext context) sync* {
+ yield footer(classes: 'foot', [
+ span([text('Developed in 💙 with')]),
+ a(
+ href: 'https://docs.page/schultek/jaspr',
+ classes: 'tech-name',
+ target: Target.blank,
+ styles: Styles.text(color: Color.hex('#1977d1')),
+ [text('Jaspr')]),
+ ]);
+ }
+
+ @css
+ static final List styles = [
+ css('.foot')
+ .flexbox(
+ direction: FlexDirection.row,
+ alignItems: AlignItems.center,
+ justifyContent: JustifyContent.center,
+ )
+ .box(
+ padding: EdgeInsets.symmetric(vertical: 2.vh),
+ )
+ .text(fontSize: 12.px),
+ css('.tech-name')
+ .text(
+ fontSize: 12.px,
+ decoration: TextDecoration.none,
+ )
+ .box(margin: EdgeInsets.only(left: 5.px)),
+ ];
+}
diff --git a/lib/components/nav_bar.dart b/lib/components/nav_bar.dart
new file mode 100644
index 0000000..0f49358
--- /dev/null
+++ b/lib/components/nav_bar.dart
@@ -0,0 +1,103 @@
+import 'package:devfolio/components/app_button.dart';
+import 'package:devfolio/constants/theme.dart';
+import 'package:jaspr/jaspr.dart';
+
+@client
+class NavBar extends StatelessComponent {
+ const NavBar({super.key});
+
+ @override
+ Iterable build(BuildContext context) sync* {
+ yield section(classes: 'navbar', [
+ div([
+ span([text('< ')]),
+ span(classes: 'brand', [text('Hamza')]),
+ span([text(' />')]),
+ ]),
+ div(classes: 'labels', [
+ a(
+ classes: 'navbar-label',
+ href: '#',
+ [
+ text('HOME'),
+ ],
+ ),
+ a(
+ href: '#about',
+ classes: 'navbar-label',
+ [
+ text('ABOUT'),
+ ],
+ ),
+ a(
+ href: '#services',
+ classes: 'navbar-label',
+ [
+ text('SERVICES'),
+ ],
+ ),
+ a(
+ href: '#projects',
+ classes: 'navbar-label',
+ [
+ text('PROJECTS'),
+ ],
+ ),
+ a(
+ href: '#contact',
+ classes: 'navbar-label',
+ [
+ text('CONTACT'),
+ ],
+ ),
+ AppButton(
+ label: 'RESUME',
+ href:
+ "https://drive.google.com/drive/u/0/folders/1E6NxJlmnW2lTYTszcbODdpXiPFYe_kBM",
+ ),
+ ]),
+ ]);
+ }
+
+ @css
+ static final List styles = [
+ css('.navbar')
+ .box(padding: EdgeInsets.all(25.px))
+ .flexbox(
+ direction: FlexDirection.row,
+ justifyContent: JustifyContent.spaceBetween,
+ alignItems: AlignItems.center,
+ )
+ .background(
+ color: Colors.black,
+ ),
+ css('.navbar-label')
+ .box(
+ padding: EdgeInsets.only(right: 35.px),
+ )
+ .text(
+ fontSize: 12.px,
+ decoration: TextDecoration.none,
+ )
+ .flexbox(
+ direction: FlexDirection.row,
+ justifyContent: JustifyContent.spaceBetween,
+ alignItems: AlignItems.center,
+ ),
+ css('.navbar-label:hover')
+ .text(
+ color: themePrimaryColor,
+ )
+ .box(
+ transition: Transition('color', duration: 500),
+ ),
+ css('.labels').flexbox(
+ direction: FlexDirection.row,
+ justifyContent: JustifyContent.end,
+ ),
+ css('.brand').text(
+ fontFamily: FontFamily('Agustina'),
+ fontSize: 24.px,
+ ),
+ ];
+}
diff --git a/lib/components/project_card.dart b/lib/components/project_card.dart
new file mode 100644
index 0000000..a308ed7
--- /dev/null
+++ b/lib/components/project_card.dart
@@ -0,0 +1,96 @@
+import 'package:devfolio/constants/theme.dart';
+import 'package:jaspr/jaspr.dart';
+
+@client
+class ProjectCard extends StatelessComponent {
+ final String title;
+ final String description;
+ final String icon;
+ final String banner;
+ final String url;
+ const ProjectCard({
+ super.key,
+ required this.title,
+ required this.description,
+ required this.icon,
+ required this.banner,
+ required this.url,
+ });
+
+ @override
+ Iterable build(BuildContext context) sync* {
+ yield a(href: url, target: Target.blank, classes: 'banner-card', [
+ div(
+ classes: 'banner-image',
+ styles: Styles.combine([
+ Styles.background(
+ image: ImageStyle.url(banner),
+ size: BackgroundSize.cover,
+ ),
+ ]),
+ []),
+ img(src: icon, height: 40),
+ span(classes: 'service-title', [
+ text(title),
+ ]),
+ span(classes: 'service-description', [
+ text(description),
+ ]),
+ ]);
+ }
+
+ @css
+ static final List styles = [
+ css('.banner-card')
+ .flexbox(
+ direction: FlexDirection.column,
+ alignItems: AlignItems.center,
+ justifyContent: JustifyContent.center,
+ )
+ .box(
+ height: 200.px,
+ width: 350.px,
+ radius: BorderRadius.circular(12.px),
+ margin: EdgeInsets.only(top: 25.px, left: 15.px, right: 15.px),
+ )
+ .background(
+ color: themeDarkGreyColor,
+ )
+ .text(
+ decoration: TextDecoration.none,
+ ),
+ css('.banner-card:hover').box(
+ shadow: BoxShadow(
+ color: themePrimaryColor,
+ offsetX: 0.px,
+ offsetY: 0.px,
+ blur: 8.px,
+ spread: 2.px,
+ ),
+ transition: Transition('box-shadow', duration: 500),
+ cursor: Cursor.pointer,
+ ),
+ css('.banner-image').box(
+ height: 200.px,
+ width: 350.px,
+ ),
+ css('.service-description')
+ .text(
+ fontSize: 12.px,
+ align: TextAlign.center,
+ )
+ .box(
+ padding: EdgeInsets.symmetric(horizontal: 10.px),
+ margin: EdgeInsets.only(top: 10.px),
+ ),
+ css('.banner-image').box(
+ opacity: 1.0,
+ radius: BorderRadius.circular(12.px),
+ position: Position.absolute(),
+ ),
+ css('.banner-image:hover').box(
+ opacity: 0,
+ transition: Transition('opacity', duration: 500),
+ ),
+ ];
+}
diff --git a/lib/components/service_card.dart b/lib/components/service_card.dart
new file mode 100644
index 0000000..9522007
--- /dev/null
+++ b/lib/components/service_card.dart
@@ -0,0 +1,60 @@
+import 'package:devfolio/constants/theme.dart';
+import 'package:jaspr/jaspr.dart';
+
+@client
+class ServiceCard extends StatelessComponent {
+ final String icon;
+ final String label;
+ const ServiceCard({
+ super.key,
+ required this.icon,
+ required this.label,
+ });
+
+ @override
+ Iterable build(BuildContext context) sync* {
+ yield div(classes: 'service-card', [
+ img(src: icon, height: 80),
+ span(classes: 'service-title', [
+ text(label),
+ ]),
+ ]);
+ }
+
+ @css
+ static final List styles = [
+ css('.service-card')
+ .flexbox(
+ direction: FlexDirection.column,
+ alignItems: AlignItems.center,
+ justifyContent: JustifyContent.center,
+ )
+ .box(
+ padding: EdgeInsets.all(15.px),
+ height: 200.px,
+ width: 250.px,
+ radius: BorderRadius.circular(12.px),
+ margin: EdgeInsets.only(top: 25.px, left: 15.px, right: 15.px),
+ )
+ .background(
+ color: themeDarkGreyColor,
+ ),
+ css('.service-title')
+ .text(
+ fontSize: 14.px,
+ )
+ .box(
+ margin: EdgeInsets.only(top: 10.px),
+ ),
+ css('.service-card:hover').box(
+ shadow: BoxShadow(
+ color: themePrimaryColor,
+ offsetX: 0.px,
+ offsetY: 0.px,
+ blur: 8.px,
+ spread: 2.px,
+ ),
+ transition: Transition('box-shadow', duration: 500),
+ ),
+ ];
+}
diff --git a/lib/configs/app.dart b/lib/configs/app.dart
deleted file mode 100644
index bcd4143..0000000
--- a/lib/configs/app.dart
+++ /dev/null
@@ -1,17 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:folio/configs/configs.dart';
-
-class App {
- static bool? isLtr;
- static bool showAds = false;
-
- static init(BuildContext context) {
- UI.init(context);
- AppDimensions.init();
- AppTheme.init(context);
- UIProps.init();
- Space.init();
- AppText.init();
- isLtr = Directionality.of(context) == TextDirection.ltr;
- }
-}
diff --git a/lib/configs/app_core_theme.dart b/lib/configs/app_core_theme.dart
deleted file mode 100644
index d1f01e2..0000000
--- a/lib/configs/app_core_theme.dart
+++ /dev/null
@@ -1,80 +0,0 @@
-import 'package:flutter/material.dart';
-
-class AppCoreTheme {
- Color? primary;
- Color? primaryLight;
- Color? primaryDark;
-
- Color? accent;
- Color? accentLight;
- Color? accentDark;
-
- Color? background;
- Color? backgroundSub;
- Color? scaffold;
- Color? scaffoldDark;
-
- Color? text;
- Color? textSub;
- Color? textSub2;
-
- Color? shadow; // Normal shadowOnBackground
- Color? shadowSub; // Shadow light
-
- AppCoreTheme({
- this.primary,
- this.primaryLight,
- this.primaryDark,
- this.accent,
- this.accentLight,
- this.accentDark,
- this.background,
- this.backgroundSub,
- this.scaffold,
- this.scaffoldDark,
- this.text,
- this.textSub,
- this.textSub2,
- this.shadow,
- this.shadowSub,
- });
-
- AppCoreTheme copyWith({
- Color? primary,
- Color? primaryLight,
- Color? primaryDark,
- Color? accent,
- Color? accentLight,
- Color? accentDark,
- Color? background,
- Color? backgroundSub,
- Color? scaffold,
- Color? scaffoldDark,
- Color? text,
- Color? textSub,
- Color? textSub2,
- Color? shadow,
- Color? shadowSub,
- Color? upsellCard,
- Color? hotelChipRefundable,
- Color? hotelChipAirportTransfer,
- }) {
- return AppCoreTheme(
- primary: primary ?? this.primary,
- primaryLight: primaryLight ?? this.primaryLight,
- primaryDark: primaryDark ?? this.primaryDark,
- accent: accent ?? this.accent,
- accentLight: accentLight ?? this.accentLight,
- accentDark: accentDark ?? this.accentDark,
- background: background ?? this.background,
- backgroundSub: backgroundSub ?? this.backgroundSub,
- scaffold: scaffold ?? this.scaffold,
- scaffoldDark: scaffoldDark ?? this.scaffoldDark,
- text: text ?? this.text,
- textSub: textSub ?? this.textSub,
- textSub2: textSub2 ?? this.textSub2,
- shadow: shadow ?? this.shadow,
- shadowSub: shadowSub ?? this.shadowSub,
- );
- }
-}
diff --git a/lib/configs/app_dimensions.dart b/lib/configs/app_dimensions.dart
deleted file mode 100644
index e73792d..0000000
--- a/lib/configs/app_dimensions.dart
+++ /dev/null
@@ -1,62 +0,0 @@
-import 'package:flutter/material.dart';
-import 'ui.dart';
-
-class AppDimensions {
- static double? maxContainerWidth;
- static double? miniContainerWidth;
-
- static bool? isLandscape;
- static double? padding;
- static double ratio = 0;
-
- static Size? size;
-
- static init() {
- ratio = UI.width! / UI.height!;
- double pixelDensity = UI.mediaQuery().devicePixelRatio;
- ratio = (ratio) + ((pixelDensity + ratio) / 2);
-
- if (UI.width! <= 380 && pixelDensity >= 3) {
- ratio *= 0.85;
- }
-
- _initLargeScreens();
- _initSmallScreensHighDensity();
-
- padding = ratio * 3;
- }
-
- static _initLargeScreens() {
- const safe = 2.4;
-
- ratio *= 1.5;
-
- if (ratio > safe) {
- ratio = safe;
- }
- }
-
- static _initSmallScreensHighDensity() {
- if (!UI.sm! && ratio > 2.0) {
- ratio = 2.0;
- }
- if (!UI.xs! && ratio > 1.6) {
- ratio = 1.6;
- }
- if (!UI.xxs! && ratio > 1.4) {
- ratio = 1.4;
- }
- }
-
- static double space([double multiplier = 1.0]) {
- return AppDimensions.padding! * 3 * multiplier;
- }
-
- static double normalize(double unit) {
- return (AppDimensions.ratio * unit * 0.77) + unit;
- }
-
- static double font(double unit) {
- return (AppDimensions.ratio * unit * 0.125) + unit * 1.90;
- }
-}
diff --git a/lib/configs/app_theme.dart b/lib/configs/app_theme.dart
deleted file mode 100644
index f6abb5c..0000000
--- a/lib/configs/app_theme.dart
+++ /dev/null
@@ -1,40 +0,0 @@
-import 'package:flutter/material.dart';
-
-import 'app_core_theme.dart';
-
-class AppTheme {
- static final _core = AppCoreTheme(
- shadowSub: const Color(0xffC0392B).withAlpha(100),
- primary: const Color(0xffC0392B),
- primaryLight: const Color(0xffC0392B).withAlpha(100),
- textSub: const Color(0xff141414),
- textSub2: const Color(0xff696969),
- );
-
- static AppCoreTheme light = _core.copyWith(
- background: Colors.white,
- backgroundSub: const Color(0xffF0F0F0),
- scaffold: const Color(0xfffefefe),
- scaffoldDark: const Color(0xfffcfcfc),
- text: const Color(0xff484848),
- textSub2: Colors.black.withOpacity(0.25),
- );
-
- static AppCoreTheme dark = _core.copyWith(
- background: Colors.grey[900],
- backgroundSub: const Color(0xff1c1c1e),
- scaffold: const Color(0xff0e0e0e),
- text: Colors.white,
- textSub2: Colors.white.withOpacity(0.25),
- );
-
- static AppCoreTheme? c;
-
- // Init
- static init(BuildContext context) {
- c = isDark(context) ? dark : light;
- }
-
- static bool isDark(BuildContext context) =>
- Theme.of(context).brightness == Brightness.dark;
-}
diff --git a/lib/configs/app_typography.dart b/lib/configs/app_typography.dart
deleted file mode 100644
index bc1f46a..0000000
--- a/lib/configs/app_typography.dart
+++ /dev/null
@@ -1,52 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:folio/configs/configs.dart';
-
-class AppText {
- static TextStyle? btn;
-
- // Headings
- static TextStyle? h1;
- static TextStyle? h1b;
- static TextStyle? h2;
- static TextStyle? h2b;
- static TextStyle? h3;
- static TextStyle? h3b;
-
- // Body
- static TextStyle? b1;
- static TextStyle? b1b;
- static TextStyle? b2;
- static TextStyle? b2b;
-
- // Label
- static TextStyle? l1;
- static TextStyle? l1b;
- static TextStyle? l2;
- static TextStyle? l2b;
-
- static init() {
- const b = FontWeight.bold;
- const baseStyle = TextStyle(fontFamily: fontFamily);
-
- h1 = baseStyle.copyWith(fontSize: AppDimensions.font(22));
- h1b = h1!.copyWith(fontWeight: b);
-
- h2 = baseStyle.copyWith(fontSize: AppDimensions.font(18));
- h2b = h2!.copyWith(fontWeight: b);
-
- h3 = baseStyle.copyWith(fontSize: AppDimensions.font(15));
- h3b = h3!.copyWith(fontWeight: b);
-
- b1 = baseStyle.copyWith(fontSize: AppDimensions.font(10));
- b1b = b1!.copyWith(fontWeight: b);
-
- b2 = baseStyle.copyWith(fontSize: AppDimensions.font(8));
- b2b = b2!.copyWith(fontWeight: b);
-
- l1 = baseStyle.copyWith(fontSize: AppDimensions.font(6));
- l1b = l1!.copyWith(fontWeight: b);
-
- l2 = baseStyle.copyWith(fontSize: AppDimensions.font(4));
- l2b = l2!.copyWith(fontWeight: b);
- }
-}
diff --git a/lib/configs/app_typography_ext.dart b/lib/configs/app_typography_ext.dart
deleted file mode 100644
index 7de8081..0000000
--- a/lib/configs/app_typography_ext.dart
+++ /dev/null
@@ -1,41 +0,0 @@
-import 'package:flutter/material.dart';
-
-extension SuperTextStyles on TextStyle {
- TextStyle cl(Color color) {
- return copyWith(
- color: color,
- );
- }
-
- TextStyle s([double? size]) {
- return copyWith(
- fontSize: size ?? fontSize,
- );
- }
-
- TextStyle tsc([double multiplier = 1.0]) {
- return copyWith(
- fontSize: fontSize! * multiplier,
- );
- }
-
- TextStyle w(int i) {
- FontWeight w = FontWeight.w400;
-
- if (i == 3) {
- w = FontWeight.w300;
- }
- if (i == 5) {
- w = FontWeight.w500;
- }
- if (i == 6) {
- w = FontWeight.w600;
- }
- if (i == 7) {
- w = FontWeight.w700;
- }
- return copyWith(
- fontWeight: w,
- );
- }
-}
diff --git a/lib/configs/configs.dart b/lib/configs/configs.dart
deleted file mode 100644
index d70a0e1..0000000
--- a/lib/configs/configs.dart
+++ /dev/null
@@ -1,11 +0,0 @@
-export 'app_dimensions.dart';
-export 'app_typography.dart';
-export 'app_typography_ext.dart';
-export 'app_theme.dart';
-export 'ui_props.dart';
-export 'space.dart';
-export 'space_ext.dart';
-export 'ui.dart';
-
-export 'core_theme.dart' show fontFamily;
-export 'date_ext.dart';
diff --git a/lib/configs/core_theme.dart b/lib/configs/core_theme.dart
deleted file mode 100644
index 8e65c2a..0000000
--- a/lib/configs/core_theme.dart
+++ /dev/null
@@ -1,42 +0,0 @@
-import 'package:flutter/material.dart';
-
-const fontFamily = 'Poppins';
-
-final themeLight = ThemeData(
- primaryColorLight: const Color(0xffC0392B),
- brightness: Brightness.light,
- primaryColor: const Color(0xffC0392B),
- highlightColor: Colors.black,
- canvasColor: Colors.white,
- fontFamily: fontFamily,
- splashColor: Colors.transparent,
- scaffoldBackgroundColor: Colors.white,
- colorScheme: ColorScheme.fromSwatch(
- primarySwatch: Colors.red,
- )
- .copyWith(
- secondary: Colors.black,
- brightness: Brightness.light,
- surface: Colors.white,
- )
- .copyWith(
- surface: Colors.white,
- ),
-);
-
-final themeDark = ThemeData(
- brightness: Brightness.dark,
- primaryColorDark: const Color(0xffC0392B),
- primaryColor: const Color(0xffC0392B),
- highlightColor: const Color(0xffC0392B),
- canvasColor: Colors.white,
- fontFamily: fontFamily,
- splashColor: Colors.transparent,
- scaffoldBackgroundColor: Colors.black,
- colorScheme: ColorScheme.fromSwatch(
- primarySwatch: Colors.red,
- brightness: Brightness.dark,
- ).copyWith(
- surface: Colors.grey[800],
- ),
-);
diff --git a/lib/configs/date_ext.dart b/lib/configs/date_ext.dart
deleted file mode 100644
index c449e15..0000000
--- a/lib/configs/date_ext.dart
+++ /dev/null
@@ -1,3 +0,0 @@
-extension SuperDate on DateTime {
- DateTime get today => DateTime(year, month, day);
-}
diff --git a/lib/configs/space.dart b/lib/configs/space.dart
deleted file mode 100644
index 9d02ac4..0000000
--- a/lib/configs/space.dart
+++ /dev/null
@@ -1,68 +0,0 @@
-import 'package:flutter/material.dart';
-import 'ui.dart';
-import 'app_dimensions.dart';
-
-class Space {
- static Widget? x;
- static Widget? y;
- static Widget? x1;
- static Widget? y1;
- static Widget? x2;
- static Widget? y2;
- static Widget? xm;
- static Widget? ym;
-
- static EdgeInsets? z;
- static EdgeInsets? h;
- static EdgeInsets? v;
- static EdgeInsets? h1;
- static EdgeInsets? v1;
- static EdgeInsets? h2;
- static EdgeInsets? v2;
-
- static Widget? top;
- static Widget? bottom;
-
- static void init() {
- x = SizedBox(width: AppDimensions.space(0.5));
- y = SizedBox(height: AppDimensions.space(0.5));
-
- x1 = SizedBox(width: AppDimensions.space());
- y1 = SizedBox(height: AppDimensions.space());
-
- x2 = SizedBox(width: AppDimensions.space(2));
- y2 = SizedBox(height: AppDimensions.space(2));
-
- xm = const Expanded(child: SizedBox(width: double.infinity));
- ym = const Expanded(child: SizedBox(height: double.infinity));
-
- z = EdgeInsets.zero;
- h = EdgeInsets.symmetric(horizontal: AppDimensions.space(0.5));
- v = EdgeInsets.symmetric(vertical: AppDimensions.space(0.5));
-
- h1 = EdgeInsets.symmetric(horizontal: AppDimensions.space());
- v1 = EdgeInsets.symmetric(vertical: AppDimensions.space());
-
- h2 = EdgeInsets.symmetric(horizontal: AppDimensions.space(2));
- v2 = EdgeInsets.symmetric(vertical: AppDimensions.space(2));
-
- top = SizedBox(height: UI.padding!.top);
- bottom = SizedBox(height: UI.padding!.bottom);
- }
-
- static Widget xf([double no = 1]) => SizedBox(width: AppDimensions.space(no));
- static Widget yf([double no = 1]) =>
- SizedBox(height: AppDimensions.space(no));
-
- static EdgeInsets hf([double no = 1]) => EdgeInsets.symmetric(
- horizontal: AppDimensions.space(no),
- );
- static EdgeInsets vf([double no = 1]) => EdgeInsets.symmetric(
- vertical: AppDimensions.space(no),
- );
-
- static EdgeInsets all([double h = 0.5, double? v]) => EdgeInsets.symmetric(
- vertical: AppDimensions.space(v ?? h),
- horizontal: AppDimensions.space(h),
- );
-}
diff --git a/lib/configs/space_ext.dart b/lib/configs/space_ext.dart
deleted file mode 100644
index 00826f3..0000000
--- a/lib/configs/space_ext.dart
+++ /dev/null
@@ -1,36 +0,0 @@
-import 'package:flutter/material.dart';
-import 'app_dimensions.dart';
-import 'ui.dart';
-
-extension SuperEdgeInsets on EdgeInsets {
- EdgeInsets sv() {
- return copyWith(
- top: top + UI.padding!.top,
- bottom: bottom + UI.padding!.bottom,
- );
- }
-
- EdgeInsets st() {
- return copyWith(top: top + UI.padding!.top);
- }
-
- EdgeInsets sb() {
- return copyWith(bottom: bottom + UI.padding!.bottom);
- }
-
- EdgeInsets b(double no) {
- return copyWith(bottom: AppDimensions.space(no));
- }
-
- EdgeInsets t(double no) {
- return copyWith(top: AppDimensions.space(no));
- }
-
- EdgeInsets l(double no) {
- return copyWith(left: AppDimensions.space(no));
- }
-
- EdgeInsets r(double no) {
- return copyWith(right: AppDimensions.space(no));
- }
-}
diff --git a/lib/configs/ui.dart b/lib/configs/ui.dart
deleted file mode 100644
index 1a2630f..0000000
--- a/lib/configs/ui.dart
+++ /dev/null
@@ -1,66 +0,0 @@
-import 'dart:math';
-import 'package:flutter/widgets.dart';
-
-class UI {
- static MediaQueryData? _mediaQueryData;
- static double? width;
- static double? height;
- static double? horizontal;
- static double? vertical;
- static EdgeInsets? padding;
- static EdgeInsets? vi;
-
- static double? _safeAreaHorizontal;
- static double? _safeAreaVertical;
- static double? safeWidth;
- static double? safeHeight;
-
- static double? diagonal;
-
- static bool? xxs;
- static bool? xs;
- static bool? sm;
- static bool? md;
- static bool? xmd;
- static bool? lg;
- static bool? xl;
- static bool? xlg;
- static bool? xxlg;
-
- static void init(BuildContext context) {
- _mediaQueryData = MediaQuery.of(context);
- initChecks(_mediaQueryData!);
-
- padding = _mediaQueryData!.padding;
- vi = _mediaQueryData!.viewInsets;
- width = _mediaQueryData!.size.width;
- height = _mediaQueryData!.size.height;
- horizontal = width! / 100;
- vertical = height! / 100;
-
- _safeAreaHorizontal =
- _mediaQueryData!.padding.left + _mediaQueryData!.padding.right;
- _safeAreaVertical =
- _mediaQueryData!.padding.top + _mediaQueryData!.padding.bottom;
- safeWidth = (width! - _safeAreaHorizontal!);
- safeHeight = (height! - _safeAreaVertical!);
- }
-
- static initChecks(MediaQueryData query) {
- var size = query.size;
- diagonal = sqrt((size.width * size.width) + (size.height * size.height));
- xxs = size.width > 300;
- xs = size.width > 360;
- sm = size.width > 480;
- md = size.width > 600;
- xmd = size.width > 720;
- lg = size.width > 980;
- xl = size.width > 1160;
- xlg = size.width > 1400;
- xxlg = size.width > 1700;
- }
-
- static MediaQueryData mediaQuery() => _mediaQueryData!;
-
- static Size getSize() => _mediaQueryData!.size;
-}
diff --git a/lib/configs/ui_props.dart b/lib/configs/ui_props.dart
deleted file mode 100644
index c3a8d80..0000000
--- a/lib/configs/ui_props.dart
+++ /dev/null
@@ -1,75 +0,0 @@
-import 'package:flutter/material.dart';
-
-import 'app_dimensions.dart';
-import 'app_theme.dart';
-
-abstract class UIProps {
- // Animations
- static Duration duration = const Duration(milliseconds: 280);
- static Duration duration2 = const Duration(milliseconds: 400);
-
- // Paddings
- static EdgeInsets? btnPadMed;
- static EdgeInsets? btnPadSm;
-
- // Radius
- static double radius = 6.0;
- static BorderRadius? tabRadius;
- static BorderRadius? buttonRadius;
- static BorderRadius? cardRadius;
- static BoxDecoration? borderButton;
-
- // Shadows
- static List? cardShadow;
-
- // BoxDecoration
- static BoxDecoration? boxCard;
-
- static init() {
- initRadius();
- initButtons();
- initShadows();
- initBoxDecorations();
- }
-
- static initRadius() {
- tabRadius = BorderRadius.circular(radius * 2);
- buttonRadius = BorderRadius.circular(radius);
- cardRadius = BorderRadius.circular(radius * 2);
- }
-
- static initButtons() {
- borderButton = BoxDecoration(
- borderRadius: UIProps.buttonRadius,
- border: Border.all(
- width: 1.4,
- color: AppTheme.c!.primary!,
- ),
- );
- btnPadSm = EdgeInsets.symmetric(
- horizontal: AppDimensions.padding! * 2,
- vertical: AppDimensions.padding! * 1.0,
- );
- btnPadMed = EdgeInsets.symmetric(
- horizontal: AppDimensions.padding! * 3,
- vertical: AppDimensions.padding! * 1.5,
- );
- }
-
- static initShadows() {
- cardShadow = [
- BoxShadow(
- color: AppTheme.c!.shadowSub!,
- blurRadius: 6,
- ),
- ];
- }
-
- static initBoxDecorations() {
- boxCard = BoxDecoration(
- borderRadius: cardRadius,
- boxShadow: cardShadow,
- color: AppTheme.c!.background,
- );
- }
-}
diff --git a/lib/constants.dart b/lib/constants.dart
deleted file mode 100644
index e248c0d..0000000
--- a/lib/constants.dart
+++ /dev/null
@@ -1,15 +0,0 @@
-import 'package:url_launcher/url_launcher.dart';
-
-// URL Launcher
-void openURL(String url) => launchUrl(
- Uri.parse(url),
- );
-
-// Tools & Tech
-final kTools = [
- "Flutter",
- "Dart",
- "Python",
- "Java",
- "C++",
-];
diff --git a/lib/constants/theme.dart b/lib/constants/theme.dart
new file mode 100644
index 0000000..5329dcf
--- /dev/null
+++ b/lib/constants/theme.dart
@@ -0,0 +1,6 @@
+import 'package:jaspr/jaspr.dart';
+
+// As your css styles are defined using just Dart, you can simply
+// use global variables or methods for common things like colors.
+const themePrimaryColor = Color.hex('#C0392B');
+const themeDarkGreyColor = Color.hex('#212121');
diff --git a/lib/jaspr_options.dart b/lib/jaspr_options.dart
new file mode 100644
index 0000000..343ac69
--- /dev/null
+++ b/lib/jaspr_options.dart
@@ -0,0 +1,69 @@
+// GENERATED FILE, DO NOT MODIFY
+// Generated with jaspr_builder
+
+import 'package:jaspr/jaspr.dart';
+import 'package:devfolio/components/app_button.dart' as prefix0;
+import 'package:devfolio/components/contact.dart' as prefix1;
+import 'package:devfolio/components/footer.dart' as prefix2;
+import 'package:devfolio/components/nav_bar.dart' as prefix3;
+import 'package:devfolio/components/project_card.dart' as prefix4;
+import 'package:devfolio/components/service_card.dart' as prefix5;
+import 'package:devfolio/pages/home.dart' as prefix6;
+import 'package:devfolio/sections/about_me.dart' as prefix7;
+import 'package:devfolio/sections/basic_info.dart' as prefix8;
+import 'package:devfolio/sections/contact.dart' as prefix9;
+import 'package:devfolio/sections/projects.dart' as prefix10;
+import 'package:devfolio/sections/services.dart' as prefix11;
+import 'package:devfolio/app.dart' as prefix12;
+
+/// Default [JasprOptions] for use with your jaspr project.
+///
+/// Use this to initialize jaspr **before** calling [runApp].
+///
+/// Example:
+/// ```dart
+/// import 'jaspr_options.dart';
+///
+/// void main() {
+/// Jaspr.initializeApp(
+/// options: defaultJasprOptions,
+/// );
+///
+/// runApp(...);
+/// }
+/// ```
+final defaultJasprOptions = JasprOptions(
+ clients: {
+ prefix12.App: ClientTarget('app'),
+ prefix0.AppButton: ClientTarget('components/app_button', params: _prefix0AppButton),
+ prefix1.ContactCard: ClientTarget('components/contact', params: _prefix1ContactCard),
+ prefix2.Footer: ClientTarget('components/footer'),
+ prefix3.NavBar: ClientTarget('components/nav_bar'),
+ prefix4.ProjectCard: ClientTarget('components/project_card', params: _prefix4ProjectCard),
+ prefix5.ServiceCard: ClientTarget('components/service_card', params: _prefix5ServiceCard),
+ prefix7.AboutMeSection: ClientTarget('sections/about_me'),
+ },
+ styles: () => [
+ ...prefix0.AppButton.styles,
+ ...prefix1.ContactCard.styles,
+ ...prefix2.Footer.styles,
+ ...prefix3.NavBar.styles,
+ ...prefix4.ProjectCard.styles,
+ ...prefix5.ServiceCard.styles,
+ ...prefix6.Home.styles,
+ ...prefix7.AboutMeSection.styles,
+ ...prefix8.BasicInfoSection.styles,
+ ...prefix9.ContactSection.styles,
+ ...prefix10.ProjectsSections.styles,
+ ...prefix11.ServicesSection.styles,
+ ...prefix12.AppState.styles,
+ ],
+);
+
+Map _prefix0AppButton(prefix0.AppButton c) =>
+ {'label': c.label, 'href': c.href, 'width': c.width, 'height': c.height};
+Map _prefix1ContactCard(prefix1.ContactCard c) =>
+ {'icon': c.icon, 'title': c.title, 'description': c.description, 'action': c.action};
+Map _prefix4ProjectCard(prefix4.ProjectCard c) =>
+ {'title': c.title, 'description': c.description, 'icon': c.icon, 'banner': c.banner, 'url': c.url};
+Map _prefix5ServiceCard(prefix5.ServiceCard c) => {'icon': c.icon, 'label': c.label};
diff --git a/lib/main.dart b/lib/main.dart
index d71b77c..364dfca 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -1,75 +1,53 @@
-import 'package:flutter/material.dart';
-import 'package:folio/provider/app_provider.dart';
-import 'package:folio/provider/drawer_provider.dart';
-import 'package:folio/provider/scroll_provider.dart';
-import 'package:folio/sections/main/main_section.dart';
-import 'package:provider/provider.dart';
-import 'package:url_strategy/url_strategy.dart';
-import 'package:folio/configs/core_theme.dart' as theme;
+// The entrypoint for the **server** environment.
+//
+// The [main] method will only be executed on the server during pre-rendering.
+// To run code on the client, use the @client annotation.
-void main() {
- WidgetsFlutterBinding.ensureInitialized();
- setPathUrlStrategy();
- runApp(const MyApp());
-}
+// Server-specific jaspr import.
+import 'package:jaspr/server.dart';
-class MyApp extends StatefulWidget {
- const MyApp({super.key});
+// Imports the [App] component.
+import 'app.dart';
- @override
- MyAppState createState() => MyAppState();
-}
+// This file is generated automatically by Jaspr, do not remove or edit.
+import 'jaspr_options.dart';
-class MyAppState extends State {
- @override
- Widget build(BuildContext context) {
- return MultiProvider(
- providers: [
- ChangeNotifierProvider(create: (_) => AppProvider()),
- ChangeNotifierProvider(create: (_) => DrawerProvider()),
- ChangeNotifierProvider(create: (_) => ScrollProvider()),
- ],
- child: Consumer(
- builder: (context, value, _) => MaterialChild(
- provider: value,
- ),
+void main() {
+ // Initializes the server environment with the generated default options.
+ Jaspr.initializeApp(
+ options: defaultJasprOptions,
+ );
+
+ // Starts the app.
+ //
+ // [Document] renders the root document structure (, and )
+ // with the provided parameters and components.
+ runApp(Document(
+ title: 'Hamza',
+ head: [
+ link(
+ href:
+ 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.6.0/css/all.min.css',
+ rel: 'stylesheet',
),
- );
- }
-}
-
-class MaterialChild extends StatefulWidget {
- final AppProvider provider;
- const MaterialChild({super.key, required this.provider});
-
- @override
- State createState() => _MaterialChildState();
-}
-
-class _MaterialChildState extends State {
- void initAppTheme() {
- final appProviders = AppProvider.state(context);
- appProviders.init();
- }
-
- @override
- void initState() {
- initAppTheme();
- super.initState();
- }
-
- @override
- Widget build(BuildContext context) {
- return MaterialApp(
- debugShowCheckedModeBanner: false,
- title: 'Hamza',
- theme: theme.themeLight,
- darkTheme: theme.themeDark,
- themeMode: widget.provider.themeMode,
- initialRoute: "/",
- routes: {
- "/": (context) => const MainPage(),
- },
- );
- }
+ ],
+ styles: [
+ // Special import rule to include to another css file.
+ css.import('https://fonts.googleapis.com/css?family=Montserrat'),
+ // Each style rule takes a valid css selector and a set of styles.
+ // Styles are defined using type-safe css bindings and can be freely chained and nested.
+ css('html, body')
+ .text(
+ fontFamily: const FontFamily.list(
+ [FontFamily('Montserrat'), FontFamilies.sansSerif]))
+ .box(width: 100.percent, minHeight: 100.vh)
+ .box(margin: EdgeInsets.zero, padding: EdgeInsets.zero),
+ css('h1').text(fontSize: 4.rem).box(margin: EdgeInsets.unset),
+ css.fontFace(
+ family: 'Agustina',
+ url: '/fonts/agustina/agustina.otf',
+ ),
+ ],
+ body: App(),
+ ));
}
diff --git a/lib/pages/home.dart b/lib/pages/home.dart
new file mode 100644
index 0000000..22f9e9d
--- /dev/null
+++ b/lib/pages/home.dart
@@ -0,0 +1,36 @@
+import 'package:devfolio/components/footer.dart';
+import 'package:devfolio/components/nav_bar.dart';
+import 'package:devfolio/sections/about_me.dart';
+import 'package:devfolio/sections/basic_info.dart';
+import 'package:devfolio/sections/contact.dart';
+import 'package:devfolio/sections/projects.dart';
+import 'package:devfolio/sections/services.dart';
+import 'package:jaspr/jaspr.dart';
+
+class Home extends StatelessComponent {
+ const Home({super.key});
+
+ @override
+ Iterable build(BuildContext context) sync* {
+ yield div(classes: 'home-body', [
+ NavBar(),
+ BasicInfoSection(),
+ AboutMeSection(),
+ ServicesSection(),
+ ProjectsSections(),
+ ContactSection(),
+ Footer(),
+ ]);
+ }
+
+ @css
+ static final List styles = [
+ css('.home-body')
+ .box(
+ width: 100.vw,
+ )
+ .background(
+ color: Colors.black,
+ ),
+ ];
+}
diff --git a/lib/provider/app_provider.dart b/lib/provider/app_provider.dart
deleted file mode 100644
index 55c379c..0000000
--- a/lib/provider/app_provider.dart
+++ /dev/null
@@ -1,51 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
-import 'package:shared_preferences/shared_preferences.dart';
-
-final themeMap = {
- "dark": ThemeMode.dark,
- "light": ThemeMode.light,
-};
-
-class AppProvider extends ChangeNotifier {
- static AppProvider state(BuildContext context, [bool listen = false]) =>
- Provider.of(context, listen: listen);
-
- ThemeMode _themeMode = ThemeMode.light;
- ThemeMode get themeMode => _themeMode;
-
- bool get isDark => _themeMode == ThemeMode.dark;
-
- void init() async {
- final prefs = await SharedPreferences.getInstance();
-
- String? stringTheme = prefs.getString('theme');
-
- ThemeMode? theme =
- stringTheme == null ? ThemeMode.light : themeMap[stringTheme];
-
- if (theme == null) {
- await prefs.setString(
- 'theme', ThemeMode.light.toString().split(".").last);
-
- _themeMode = ThemeMode.light;
- }
- _themeMode = theme!;
-
- notifyListeners();
- }
-
- void setTheme(ThemeMode newTheme) async {
- SharedPreferences prefs = await SharedPreferences.getInstance();
- if (_themeMode == newTheme) {
- return;
- }
- _themeMode = newTheme;
-
- await prefs.setString(
- 'theme',
- newTheme.toString().split('.').last,
- );
- notifyListeners();
- }
-}
diff --git a/lib/provider/drawer_provider.dart b/lib/provider/drawer_provider.dart
deleted file mode 100644
index 13e1701..0000000
--- a/lib/provider/drawer_provider.dart
+++ /dev/null
@@ -1,7 +0,0 @@
-import 'package:flutter/material.dart';
-
-class DrawerProvider extends ChangeNotifier {
- final scafoldKey = GlobalKey();
-
- GlobalKey get key => scafoldKey;
-}
diff --git a/lib/provider/scroll_provider.dart b/lib/provider/scroll_provider.dart
deleted file mode 100644
index e0521a6..0000000
--- a/lib/provider/scroll_provider.dart
+++ /dev/null
@@ -1,42 +0,0 @@
-import 'package:flutter/cupertino.dart';
-import 'package:folio/configs/app_dimensions.dart';
-
-class ScrollProvider extends ChangeNotifier {
- final scrollController = ScrollController();
-
- ScrollController get controller => scrollController;
-
- scroll(int index) {
- double offset = index == 1
- ? 270
- : index == 2
- ? 255
- : index == 3
- ? 250
- : 245;
- controller.animateTo(
- AppDimensions.normalize(
- offset * index.toDouble(),
- ),
- duration: const Duration(seconds: 1),
- curve: Curves.easeInOut,
- );
- }
-
- scrollMobile(int index) {
- double offset = index == 1
- ? 290
- : index == 2
- ? 360
- : index == 3
- ? 300
- : 310;
- controller.animateTo(
- AppDimensions.normalize(
- offset * index.toDouble(),
- ),
- duration: const Duration(seconds: 1),
- curve: Curves.easeInOut,
- );
- }
-}
diff --git a/lib/responsive/responsive.dart b/lib/responsive/responsive.dart
deleted file mode 100644
index 845566c..0000000
--- a/lib/responsive/responsive.dart
+++ /dev/null
@@ -1,39 +0,0 @@
-import 'package:flutter/material.dart';
-
-class Responsive extends StatelessWidget {
- final Widget mobile;
- final Widget tablet;
- final Widget desktop;
- const Responsive({
- super.key,
- required this.mobile,
- required this.tablet,
- required this.desktop,
- });
-
- // screen sizes
- static bool isMobile(BuildContext context) =>
- MediaQuery.of(context).size.width < 600;
-
- static bool isTablet(BuildContext context) =>
- MediaQuery.of(context).size.width < 1000 &&
- MediaQuery.of(context).size.width >= 600;
-
- static bool isDesktop(BuildContext context) =>
- MediaQuery.of(context).size.width >= 1000;
-
- @override
- Widget build(BuildContext context) {
- return LayoutBuilder(
- builder: (context, constraints) {
- if (constraints.maxWidth >= 1000) {
- return desktop;
- } else if (constraints.maxWidth >= 600) {
- return tablet;
- } else {
- return mobile;
- }
- },
- );
- }
-}
diff --git a/lib/sections/about/about.dart b/lib/sections/about/about.dart
deleted file mode 100644
index 7e53ca4..0000000
--- a/lib/sections/about/about.dart
+++ /dev/null
@@ -1,18 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:folio/responsive/responsive.dart';
-import 'package:folio/sections/about/about_desktop.dart';
-import 'package:folio/sections/about/about_mobile.dart';
-import 'package:folio/sections/about/about_tablet.dart';
-
-class About extends StatelessWidget {
- const About({super.key});
-
- @override
- Widget build(BuildContext context) {
- return const Responsive(
- tablet: AboutTab(),
- mobile: AboutMobile(),
- desktop: AboutDesktop(),
- );
- }
-}
diff --git a/lib/sections/about/about_desktop.dart b/lib/sections/about/about_desktop.dart
deleted file mode 100644
index cc22915..0000000
--- a/lib/sections/about/about_desktop.dart
+++ /dev/null
@@ -1,174 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:folio/configs/configs.dart';
-import 'package:folio/constants.dart';
-import 'package:folio/utils/about_utils.dart';
-
-import 'package:folio/utils/utils.dart';
-import 'package:folio/utils/work_utils.dart';
-import 'package:folio/widget/about_me_data.dart';
-import 'package:folio/widget/community_button.dart';
-import 'package:folio/widget/custom_text_heading.dart';
-import 'package:folio/widget/tech_widget.dart';
-
-import 'package:universal_html/html.dart' as html;
-
-class AboutDesktop extends StatelessWidget {
- const AboutDesktop({super.key});
-
- @override
- Widget build(BuildContext context) {
- double height = MediaQuery.of(context).size.height;
- double width = MediaQuery.of(context).size.width;
-
- return Container(
- padding: Space.h,
- child: Column(
- children: [
- const CustomSectionHeading(
- text: '\nAbout Me',
- ),
- const CustomSectionSubHeading(
- text: 'Get to know me :)',
- ),
- Space.y1!,
- Row(
- children: [
- Expanded(
- child: Image.asset(
- StaticUtils.coloredPhoto,
- height: height * 0.7,
- ),
- ),
- Expanded(
- flex: width < 1230 ? 2 : 1,
- child: Container(
- padding: EdgeInsets.only(left: width < 1230 ? 25.0 : 0),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Text(
- 'Who am I?',
- style: AppText.b1!.copyWith(
- color: AppTheme.c!.primary,
- ),
- ),
- Space.y1!,
- Text(
- AboutUtils.aboutMeHeadline,
- style: AppText.b1b!.copyWith(
- fontFamily: 'Montserrat',
- ),
- ),
- Space.y!,
- Text(
- AboutUtils.aboutMeDetail,
- style: AppText.b2!.copyWith(
- height: 2,
- letterSpacing: 1.1,
- fontFamily: 'Montserrat',
- fontSize: AppDimensions.normalize(5),
- ),
- textAlign: TextAlign.justify,
- ),
- Space.y!,
- Divider(
- color: Colors.grey[800],
- thickness: AppDimensions.normalize(0.5),
- ),
- Space.y!,
- Text(
- 'Technologies I have worked with:',
- style: AppText.l1!.copyWith(
- color: AppTheme.c!.primary,
- ),
- ),
- Space.y!,
- Row(
- children: kTools
- .map((e) => ToolTechWidget(
- techName: e,
- ))
- .toList(),
- ),
- Space.y!,
- Divider(
- color: Colors.grey[800],
- thickness: AppDimensions.normalize(0.5),
- ),
- const Row(
- children: [
- Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- AboutMeData(
- data: "Name",
- information: "Muhammad Hamza",
- ),
- AboutMeData(
- data: "Age",
- information: "24",
- ),
- ],
- ),
- Spacer(),
- Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- AboutMeData(
- data: "Email",
- information: "hamza.6.shakeel@gmail.com",
- ),
- AboutMeData(
- data: "From",
- information: "Attock, PK",
- ),
- ],
- ),
- ],
- ),
- Space.y1!,
- Row(
- children: [
- SizedBox(
- height: AppDimensions.normalize(13),
- width: AppDimensions.normalize(40),
- child: OutlinedButton(
- onPressed: () =>
- html.window.open(StaticUtils.resume, 'pdf'),
- child: const Text(
- "Resume",
- ),
- ),
- ),
- Space.x1!,
- Container(
- color: Colors.grey[900]!,
- width: AppDimensions.normalize(30),
- height: AppDimensions.normalize(0.5),
- ),
- ...WorkUtils.logos.asMap().entries.map(
- (e) => Expanded(
- child: CommunityIconBtn(
- icon: e.value,
- link: WorkUtils.communityLinks[e.key],
- height:
- WorkUtils.communityLogoHeight[e.key],
- ),
- ),
- )
- ],
- ),
- ],
- ),
- ),
- ),
- Container(
- width: width < 1230 ? width * 0.05 : width * 0.1,
- ),
- ],
- )
- ],
- ),
- );
- }
-}
diff --git a/lib/sections/about/about_mobile.dart b/lib/sections/about/about_mobile.dart
deleted file mode 100644
index a8af81d..0000000
--- a/lib/sections/about/about_mobile.dart
+++ /dev/null
@@ -1,132 +0,0 @@
-import 'package:flutter/foundation.dart';
-import 'package:folio/configs/configs.dart';
-import 'package:folio/utils/about_utils.dart';
-import 'package:folio/utils/utils.dart';
-import 'package:folio/utils/work_utils.dart';
-
-import 'package:folio/widget/custom_text_heading.dart';
-import 'package:universal_html/html.dart' as html;
-
-import 'package:flutter/material.dart';
-import 'package:folio/constants.dart';
-import 'package:folio/widget/about_me_data.dart';
-import 'package:folio/widget/community_button.dart';
-import 'package:folio/widget/tech_widget.dart';
-
-class AboutMobile extends StatelessWidget {
- const AboutMobile({super.key});
-
- @override
- Widget build(BuildContext context) {
- double height = MediaQuery.of(context).size.height;
-
- return Container(
- padding: Space.h,
- child: Column(
- children: [
- const CustomSectionHeading(
- text: '\nAbout Me',
- ),
- const CustomSectionSubHeading(
- text: 'Get to know me :)',
- ),
- Space.y1!,
- Image.asset(
- StaticUtils.mobilePhoto,
- height: height * 0.27,
- ),
- SizedBox(
- height: height * 0.03,
- ),
- Align(
- alignment: Alignment.centerLeft,
- child: Text(
- "Who am I?",
- style: AppText.b2!.copyWith(
- color: AppTheme.c!.primary,
- ),
- ),
- ),
- Space.y1!,
- Text(
- AboutUtils.aboutMeHeadline,
- style: AppText.b2b!.copyWith(
- fontFamily: 'Montserrat',
- ),
- ),
- SizedBox(
- height: height * 0.02,
- ),
- Text(
- AboutUtils.aboutMeDetail,
- style: AppText.l1!.copyWith(
- height: 2,
- letterSpacing: 1.1,
- fontFamily: 'Montserrat',
- ),
- ),
- Space.y!,
- Divider(
- color: Colors.grey[800],
- thickness: AppDimensions.normalize(0.5),
- ),
- Space.y!,
- Text(
- 'Technologies I have worked with:',
- style: AppText.l1!.copyWith(
- color: AppTheme.c!.primary,
- ),
- ),
- Space.y!,
- Row(
- mainAxisAlignment: MainAxisAlignment.center,
- children: kTools
- .map(
- (e) => ToolTechWidget(techName: e),
- )
- .toList(),
- ),
- Space.y!,
- Divider(
- color: Colors.grey[800],
- thickness: AppDimensions.normalize(0.5),
- ),
- SizedBox(
- height: height * 0.02,
- ),
- const AboutMeData(
- data: "Name",
- information: "Muhammad Hamza",
- ),
- const AboutMeData(
- data: "Email",
- information: "hamza.6.shakeel@gmail.com",
- ),
- Space.y!,
- OutlinedButton(
- child: const Text("Resume"),
- onPressed: () {
- kIsWeb
- ? html.window.open(StaticUtils.resume, "pdf")
- : openURL(StaticUtils.resume);
- }),
- Space.y!,
- Wrap(
- alignment: WrapAlignment.center,
- crossAxisAlignment: WrapCrossAlignment.center,
- children: WorkUtils.logos
- .asMap()
- .entries
- .map(
- (e) => CommunityIconBtn(
- icon: e.value,
- link: WorkUtils.communityLinks[e.key],
- height: WorkUtils.communityLogoHeight[e.key],
- ),
- )
- .toList()),
- ],
- ),
- );
- }
-}
diff --git a/lib/sections/about/about_tablet.dart b/lib/sections/about/about_tablet.dart
deleted file mode 100644
index df659fb..0000000
--- a/lib/sections/about/about_tablet.dart
+++ /dev/null
@@ -1,173 +0,0 @@
-import 'package:folio/configs/configs.dart';
-import 'package:folio/utils/about_utils.dart';
-import 'package:folio/utils/utils.dart';
-import 'package:folio/utils/work_utils.dart';
-
-import 'package:folio/widget/custom_text_heading.dart';
-import 'package:universal_html/html.dart' as html;
-import 'package:flutter/material.dart';
-import 'package:folio/constants.dart';
-import 'package:folio/widget/about_me_data.dart';
-import 'package:folio/widget/community_button.dart';
-import 'package:folio/widget/tech_widget.dart';
-
-class AboutTab extends StatelessWidget {
- const AboutTab({super.key});
-
- @override
- Widget build(BuildContext context) {
- double height = MediaQuery.of(context).size.height;
- double width = MediaQuery.of(context).size.width;
-
- return Container(
- padding: Space.h,
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.stretch,
- children: [
- const Center(
- child: CustomSectionHeading(
- text: '\nAbout Me',
- ),
- ),
- const Center(
- child: CustomSectionSubHeading(
- text: 'Get to know me :)',
- ),
- ),
- Space.y1!,
- Image.asset(
- StaticUtils.mobilePhoto,
- height: height * 0.27,
- ),
- SizedBox(
- height: height * 0.03,
- ),
- Text(
- "Who am I?",
- style: AppText.b2!.copyWith(
- color: AppTheme.c!.primary,
- ),
- ),
- Space.y1!,
- Text(
- AboutUtils.aboutMeHeadline,
- style: AppText.b2b!.copyWith(
- fontFamily: 'Montserrat',
- ),
- ),
- SizedBox(
- height: height * 0.02,
- ),
- Text(
- AboutUtils.aboutMeDetail,
- style: AppText.l1!.copyWith(
- height: 2,
- letterSpacing: 1.1,
- fontFamily: 'Montserrat',
- ),
- ),
- Space.y!,
- Divider(
- color: Colors.grey[800],
- thickness: AppDimensions.normalize(0.5),
- ),
- Space.y!,
- Text(
- 'Technologies I have worked with:',
- style: AppText.l1!.copyWith(
- color: AppTheme.c!.primary,
- ),
- ),
- Row(
- children: kTools
- .map(
- (e) => ToolTechWidget(techName: e),
- )
- .toList(),
- ),
- Space.y!,
- Divider(
- color: Colors.grey[800],
- thickness: AppDimensions.normalize(0.5),
- ),
- Space.y!,
- Row(
- children: [
- const Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- AboutMeData(
- data: "Name",
- information: "Muhammad Hamza",
- ),
- AboutMeData(
- data: "Age",
- information: "24",
- ),
- ],
- ),
- SizedBox(
- width: width > 710 ? width * 0.2 : width * 0.05,
- ),
- const Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- AboutMeData(
- data: "Email",
- information: "hamza.6.shakeel@gmail.com",
- ),
- AboutMeData(
- data: "From",
- information: "Attock, PK",
- ),
- ],
- ),
- ],
- ),
- Space.y1!,
- Row(
- children: [
- SizedBox(
- height: AppDimensions.normalize(13),
- width: AppDimensions.normalize(40),
- child: OutlinedButton(
- onPressed: () => html.window.open(StaticUtils.resume, 'pdf'),
- child: const Text(
- "Resume",
- ),
- ),
- ),
- Space.x!,
- Container(
- width: width * 0.05,
- decoration: BoxDecoration(
- border: Border(
- bottom: BorderSide(
- color: Colors.grey[900]!,
- width: 2.0,
- ),
- ),
- ),
- ),
- SingleChildScrollView(
- scrollDirection: Axis.horizontal,
- child: Row(
- children: WorkUtils.logos
- .asMap()
- .entries
- .map(
- (e) => CommunityIconBtn(
- icon: e.value,
- link: WorkUtils.communityLinks[e.key],
- height: WorkUtils.communityLogoHeight[e.key],
- ),
- )
- .toList()),
- ),
- ],
- )
- ],
- ),
- );
- }
-}
diff --git a/lib/sections/about_me.dart b/lib/sections/about_me.dart
new file mode 100644
index 0000000..1779ef7
--- /dev/null
+++ b/lib/sections/about_me.dart
@@ -0,0 +1,294 @@
+import 'package:devfolio/components/app_button.dart';
+import 'package:devfolio/constants/theme.dart';
+import 'package:devfolio/utils/assets.dart';
+import 'package:jaspr/jaspr.dart';
+
+@client
+class AboutMeSection extends StatelessComponent {
+ const AboutMeSection({super.key});
+
+ @override
+ Iterable build(BuildContext context) sync* {
+ final tech = [
+ 'Flutter',
+ 'Dart',
+ 'Firebase',
+ 'Python',
+ 'dart_frog',
+ 'jaspr',
+ 'nodejs',
+ 'express',
+ ];
+
+ final works = [
+ {
+ 'image': StaticAssets.cui,
+ 'url': 'https://www.comsats.edu.pk/',
+ 'height': 50,
+ },
+ {
+ 'image': StaticAssets.dsc,
+ 'url': 'https://developers.google.com/community/dsc',
+ 'height': 30,
+ },
+ {
+ 'image': StaticAssets.flutterisl,
+ 'url': 'https://meetup.com/flutter-islamabad',
+ 'height': 60,
+ },
+ {
+ 'image': StaticAssets.st,
+ 'url': 'https://www.sastaticket.pk/',
+ 'height': 60,
+ },
+ ];
+
+ yield section(classes: 'about-me-section', [
+ span(classes: 'title', id: 'about', [
+ text('About Me'),
+ ]),
+ span(classes: 'subtitle', [
+ text('Get to know me :)'),
+ ]),
+ div(classes: 'section-body', [
+ div(classes: 'profile-picture', []),
+ div(classes: 'about-details', [
+ span(
+ classes: 'intro-label',
+ styles: Styles.text(color: themePrimaryColor),
+ [
+ text('Who am I?'),
+ ]),
+ span(classes: 'intro-heading', [
+ text(
+ "I'm Muhammad Hamza, a Flutter Developer, Technical blog writer and UI/UX Designer."),
+ ]),
+ span(
+ classes: 'intro-details',
+ styles: Styles.text(
+ color: Colors.lightGrey,
+ ),
+ [
+ text(
+ "I'm a fresh graduate with Computer Science as Majors from COMSATS University Islamabad. I have been working with Flutter for the past 2 years and have developed multiple applications for both Android and iOS platforms. I have a keen interest in UI/UX designing and have been working on it for the past 3 years. I have also been writing technical blogs for the past 2 years and have been a part of multiple technical writing communities."),
+ ]),
+ div(classes: 'divider', []),
+ span(
+ classes: 'tech-label',
+ styles: Styles.text(color: themePrimaryColor),
+ [
+ text('Technologies I have worked with:'),
+ ]),
+ div(classes: 'tech-stack', [
+ for (final t in tech)
+ span([
+ i(classes: 'fa-solid fa-play play-icon', []),
+ span(classes: 'tech-item', [
+ text(t),
+ ]),
+ ]),
+ ]),
+ div(classes: 'divider', []),
+ div(classes: 'personal-row', [
+ div([
+ span(classes: 'personal-label', [
+ text('Name: '),
+ ]),
+ span(classes: 'personal-value', [
+ text(' Muhammad Hamza'),
+ ]),
+ ]),
+ div([
+ span(classes: 'personal-label', [
+ text('Email: '),
+ ]),
+ span(classes: 'personal-value', [
+ text(' hamza.6.shakeel@gmail.com'),
+ ]),
+ ])
+ ]),
+ div(styles: Styles.box(height: 15.px), []),
+ div(classes: 'personal-row', [
+ div([
+ span(classes: 'personal-label', [
+ text('Age: '),
+ ]),
+ span(classes: 'personal-value', [
+ text(' 25'),
+ ]),
+ ]),
+ div([
+ span(classes: 'personal-label', [
+ text('From: '),
+ ]),
+ span(classes: 'personal-value', [
+ text(' Islamabad, PK'),
+ ]),
+ ])
+ ]),
+ div(styles: Styles.box(height: 25.px), []),
+ div(classes: 'work-row', [
+ AppButton(
+ label: 'RESUME',
+ href:
+ "https://drive.google.com/drive/u/0/folders/1E6NxJlmnW2lTYTszcbODdpXiPFYe_kBM",
+ ),
+ div(classes: 'divider', styles: Styles.box(width: 80.px), []),
+ for (final work in works)
+ a(
+ classes: 'work-item',
+ href: (work['url'] as String),
+ target: Target.blank,
+ [
+ img(
+ src: (work['image'] as String),
+ height: (work['height'] as int)),
+ ]),
+ ])
+ ]),
+ ])
+ ]);
+ }
+
+ @css
+ static final List styles = [
+ css('.about-me-section')
+ .flexbox(
+ direction: FlexDirection.column,
+ alignItems: AlignItems.center,
+ justifyContent: JustifyContent.start,
+ )
+ .box(
+ padding: EdgeInsets.only(top: 5.vh),
+ width: 100.percent,
+ ),
+ css('.play-icon').text(color: themePrimaryColor),
+ css('.title').text(
+ fontFamily: FontFamily('Montserrat'),
+ fontWeight: FontWeight.w100,
+ fontSize: 40.px,
+ ),
+ css('.section-body')
+ .flexbox(
+ direction: FlexDirection.row,
+ // alignItems: AlignItems.center,
+ // justifyContent: JustifyContent.center,
+ )
+ .box(
+ margin: EdgeInsets.only(top: 50.px),
+ // width: 100.percent,
+ ),
+ css('.profile-picture')
+ .background(
+ image: ImageStyle.url(
+ StaticAssets.coloredImage,
+ ),
+ size: BackgroundSize.cover,
+ )
+ .box(
+ height: 700.px,
+ width: 450.px,
+ margin: EdgeInsets.only(right: 100.px),
+ ),
+ css('.about-details')
+ .flexbox(
+ direction: FlexDirection.column,
+ alignItems: AlignItems.start,
+ justifyContent: JustifyContent.center,
+ )
+ .box(
+ width: 750.px,
+ ),
+ css('.intro-label').text(fontSize: 18.px),
+ css('.intro-heading')
+ .box(
+ margin: EdgeInsets.symmetric(vertical: 15.px),
+ )
+ .text(fontSize: 20.px),
+ css('.intro-details').text(
+ lineHeight: 3.vh,
+ wordSpacing: 1.5.px,
+ color: Colors.lightGrey,
+ ),
+ css('.divider')
+ .box(
+ height: 1.px,
+ width: 100.percent,
+ margin: EdgeInsets.symmetric(vertical: 2.vh),
+ )
+ .background(color: Colors.lightGrey),
+ css('.tech-label').text(fontSize: 12.px),
+ css('.tech-stack')
+ .flexbox(
+ direction: FlexDirection.row,
+ alignItems: AlignItems.center,
+ justifyContent: JustifyContent.start,
+ wrap: FlexWrap.wrap,
+ )
+ .box(
+ margin: EdgeInsets.only(top: 15.px),
+ ),
+ css('.tech-item')
+ .box(margin: EdgeInsets.only(right: 12.px, left: 5.px))
+ .text(fontSize: 14.px),
+ css('.personal-label').text(
+ fontWeight: FontWeight.bold,
+ fontSize: 12.px,
+ ),
+ css('.personal-value').text(
+ fontSize: 12.px,
+ ),
+ css('.personal-row').box(width: 100.percent).flexbox(
+ direction: FlexDirection.row,
+ justifyContent: JustifyContent.spaceBetween,
+ ),
+ css('.work-row').box(width: 100.percent).flexbox(
+ direction: FlexDirection.row,
+ alignItems: AlignItems.center,
+ justifyContent: JustifyContent.spaceBetween,
+ ),
+
+ /// MEDIA QUERIES
+ /// For smaller screens
+ css.media(MediaQuery.screen(maxWidth: 1350.px), [
+ css('.profile-picture').box(
+ maxHeight: 100.percent,
+ margin: EdgeInsets.symmetric(horizontal: 50.px),
+ ),
+ css('.about-details').box(width: 45.vw),
+ ]),
+
+ css.media(MediaQuery.screen(maxWidth: 1100.px), [
+ css('.profile-picture').box(
+ maxHeight: 80.percent,
+ width: 400.px,
+ margin: EdgeInsets.symmetric(horizontal: 30.px),
+ ),
+ css('.about-details').box(width: 45.vw),
+ ]),
+
+ css.media(MediaQuery.screen(maxWidth: 900.px), [
+ css('.about-me-section').box(
+ padding: EdgeInsets.only(top: 3.vh, right: 0.vw),
+ ),
+ css('.section-body').flexbox(
+ direction: FlexDirection.column,
+ alignItems: AlignItems.center,
+ justifyContent: JustifyContent.start,
+ ),
+ css('.profile-picture')
+ .background(
+ image: ImageStyle.url(
+ StaticAssets.mobileImage,
+ ),
+ size: BackgroundSize.cover,
+ )
+ .box(
+ width: 250.px,
+ height: 250.px,
+ ),
+ css('.about-details')
+ .box(width: 80.percent, margin: EdgeInsets.only(top: 40.px)),
+ ]),
+ ];
+}
diff --git a/lib/sections/basic_info.dart b/lib/sections/basic_info.dart
new file mode 100644
index 0000000..58a2d77
--- /dev/null
+++ b/lib/sections/basic_info.dart
@@ -0,0 +1,162 @@
+import 'package:devfolio/constants/theme.dart';
+import 'package:devfolio/utils/assets.dart';
+import 'package:jaspr/jaspr.dart';
+
+class BasicInfoSection extends StatelessComponent {
+ const BasicInfoSection({super.key});
+
+ @override
+ Iterable build(BuildContext context) sync* {
+ final List