create product page for mobile.

This commit is contained in:
OkaykOrhmn 2025-02-17 17:51:44 +03:30
parent a8c8fa88b9
commit 09d4553e73
10 changed files with 1518 additions and 148 deletions

View File

@ -1,5 +1,6 @@
#Mon Feb 17 08:57:28 IRST 2025
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-all.zip

View File

@ -4,75 +4,102 @@ import 'package:flutter_native_splash/flutter_native_splash.dart';
import 'package:go_router/go_router.dart';
import 'package:proxibuy/presentation/providers/cubit/user_info_cubit.dart';
import 'package:proxibuy/presentation/ui/screens/auth/auth_page.dart';
import 'package:proxibuy/presentation/ui/screens/home/explore_screen.dart';
import 'package:proxibuy/presentation/ui/screens/home/home_page.dart';
import 'package:proxibuy/presentation/ui/screens/home/home_screen.dart';
import 'package:proxibuy/presentation/ui/screens/home/setting_screen.dart';
import 'package:proxibuy/presentation/ui/screens/product/product_page.dart';
class AppRouter {
static final initial = '/';
static final home = '/home';
static final explore = '/explore';
static final setting = '/settings';
static final product = '/product';
static List<String> home = [initial, explore, setting];
static final GlobalKey<NavigatorState> navigatorKey =
GlobalKey<NavigatorState>();
GoRouter createRouter = GoRouter(
static GoRouter createRouter = GoRouter(
navigatorKey: navigatorKey,
initialLocation: home,
initialLocation: initial,
routes: [
GoRoute(
path: home,
builder: (BuildContext context, GoRouterState state) {
return BlocConsumer<UserInfoCubit, UserInfoState>(
listener: (context, state) {
if (state is UserInfoSuccess || state is UserInfoFail) {
FlutterNativeSplash.remove();
}
},
builder: (context, state) {
if (state is UserInfoSuccess) {
return const HomePage();
} else {
return const AuthPage();
}
},
);
},
routes: <RouteBase>[],
),
// StatefulShellRoute.indexedStack(
// builder: (context, state, navigationShell) =>
// BlocBuilder<UserInfoCubit, UserInfoState>(
// builder: (context, state) {
// if (state is UserInfoSuccess) {
// return CustomBottomNav(child: navigationShell);
// } else {
// return AuthPage();
// }
// },
// ),
// branches: [
// StatefulShellBranch(routes: [
// GoRoute(
// path: initial,
// builder: (context, state) {
// return HomeScreen();
// },
// ),
// ]),
// StatefulShellBranch(routes: [
// GoRoute(
// path: explore,
// builder: (context, state) => ExploreScreen(),
// ),
// ]),
// StatefulShellBranch(routes: [
// GoRoute(
// path: setting,
// builder: (context, state) => SettingScreen(),
// ),
// ]),
// GoRoute(
// path: initial,
// builder: (BuildContext context, GoRouterState state) {
// return BlocConsumer<UserInfoCubit, UserInfoState>(
// listener: (context, state) {
// if (state is UserInfoSuccess || state is UserInfoFail) {
// FlutterNativeSplash.remove();
// }
// },
// builder: (context, state) {
// if (state is UserInfoSuccess) {
// return const HomePage();
// } else {
// return const AuthPage();
// }
// },
// );
// },
// routes: <RouteBase>[
// GoRoute(
// path: product,
// builder: (BuildContext context, GoRouterState state) {
// return ProductPage();
// },
// routes: <RouteBase>[],
// ),
// ],
// ),
StatefulShellRoute.indexedStack(
builder: (context, state, navigationShell) =>
BlocBuilder<UserInfoCubit, UserInfoState>(
builder: (context, userState) {
if (userState is UserInfoSuccess) {
if (home.contains(state.fullPath)) {
return HomePage(child: navigationShell);
} else {
return navigationShell;
}
} else {
return AuthPage();
}
},
),
branches: [
StatefulShellBranch(routes: [
GoRoute(
path: initial,
builder: (context, state) {
return HomeScreen();
},
routes: [
GoRoute(
path: product,
builder: (BuildContext context, GoRouterState state) {
return ProductPage();
},
routes: <RouteBase>[],
),
]),
]),
StatefulShellBranch(routes: [
GoRoute(
path: explore,
builder: (context, state) => ExploreScreen(),
),
]),
StatefulShellBranch(routes: [
GoRoute(
path: setting,
builder: (context, state) => SettingScreen(),
),
]),
],
),
],
);
}

View File

@ -0,0 +1,11 @@
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
class MyCustomScrollBehavior extends MaterialScrollBehavior {
// Override behavior methods and getters like dragDevices
@override
Set<PointerDeviceKind> get dragDevices => {
PointerDeviceKind.touch,
PointerDeviceKind.mouse,
};
}

View File

@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_native_splash/flutter_native_splash.dart';
import 'package:proxibuy/core/routes/app_router.dart';
import 'package:proxibuy/core/utils/my_custom_scroll_behavior.dart';
import 'package:proxibuy/data/storage/shared_preferences_helper.dart';
import 'package:proxibuy/presentation/providers/cubit/them_mode_cubit.dart';
import 'package:proxibuy/presentation/providers/cubit/user_info_cubit.dart';
@ -43,11 +44,13 @@ class _MyAppState extends State<MyApp> {
return BlocBuilder<ThemModeCubit, ThemeMode>(
builder: (context, themeState) {
return MaterialApp.router(
routerConfig: AppRouter().createRouter,
routerConfig: AppRouter.createRouter,
restorationScopeId: 'app',
title: 'Proxibuy',
theme: appTheme,
darkTheme: darkTheme,
themeMode: themeState,
scrollBehavior: MyCustomScrollBehavior(),
debugShowCheckedModeBanner: false,
);
},

View File

@ -42,7 +42,10 @@ class _AuthPageState extends State<AuthPage> {
body: Responsive(context).builder(
mobile: onBoarding
? carousle(
withNavs: true, autoPlay: false, enableInfiniteScroll: false)
withNavs: true,
autoPlay: false,
enableInfiniteScroll: false,
)
: auth(context),
tablet: Row(
children: [
@ -50,10 +53,10 @@ class _AuthPageState extends State<AuthPage> {
child: Padding(
padding: const EdgeInsets.all(50.0),
child: carousle(
withNavs: false,
autoPlay: true,
enableInfiniteScroll: true,
height: MediaQuery.sizeOf(context).height * 0.8),
withNavs: false,
autoPlay: true,
enableInfiniteScroll: true,
),
),
),
Expanded(
@ -68,10 +71,10 @@ class _AuthPageState extends State<AuthPage> {
child: Padding(
padding: const EdgeInsets.all(80.0),
child: carousle(
withNavs: false,
autoPlay: true,
enableInfiniteScroll: true,
height: MediaQuery.sizeOf(context).height * 0.8),
withNavs: false,
autoPlay: true,
enableInfiniteScroll: true,
),
),
),
Expanded(
@ -182,13 +185,13 @@ class _AuthPageState extends State<AuthPage> {
);
}
CarouselSliderWidget<OnboardingBannerModel> carousle(
{required final bool withNavs,
required final bool autoPlay,
required final bool enableInfiniteScroll,
double? height}) {
CarouselSliderWidget<OnboardingBannerModel> carousle({
required final bool withNavs,
required final bool autoPlay,
required final bool enableInfiniteScroll,
}) {
return CarouselSliderWidget<OnboardingBannerModel>(
height: height ?? MediaQuery.sizeOf(context).height,
height: MediaQuery.sizeOf(context).height * 0.8,
items: [
OnboardingBannerModel(
image: Assets.image.onboarding.banner1,

View File

@ -1,7 +1,9 @@
import 'package:bottom_navy_bar/bottom_navy_bar.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:go_router/go_router.dart';
import 'package:proxibuy/core/gen/assets.gen.dart';
import 'package:proxibuy/core/routes/app_router.dart';
import 'package:proxibuy/core/utils/empty_space.dart';
import 'package:proxibuy/data/models/screen_model.dart';
import 'package:proxibuy/presentation/providers/cubit/them_mode_cubit.dart';
@ -12,7 +14,9 @@ import 'package:proxibuy/presentation/ui/theme/responsive.dart';
import 'package:proxibuy/presentation/ui/theme/theme.dart';
class HomePage extends StatefulWidget {
const HomePage({super.key});
final Widget child;
const HomePage({super.key, required this.child});
@override
State<HomePage> createState() => _HomePageState();
@ -25,6 +29,7 @@ class _HomePageState extends State<HomePage> {
ScreenModel(title: 'Explore', icon: Assets.icon.outline.map),
ScreenModel(title: 'Settings', icon: Assets.icon.outline.setting),
];
@override
Widget build(BuildContext context) {
return Responsive(context).builder(
@ -37,26 +42,6 @@ class _HomePageState extends State<HomePage> {
),
),
mobile: Scaffold(
appBar: AppBar(
title: Text(
"Proxibuy",
style: Theme.of(context).textTheme.headlineSmall,
),
actions: [
IconButton(
icon: Assets.icon.outline.notificationBing
.svg(color: Theme.of(context).colorScheme.onSurface),
onPressed: () {},
),
12.w,
IconButton(
icon: Icon(Icons.brightness_6),
onPressed: () {
context.read<ThemModeCubit>().changeTheme();
},
),
],
),
body: body(),
bottomNavigationBar: bottomNavigationBar(context),
),
@ -207,17 +192,24 @@ class _HomePageState extends State<HomePage> {
);
}
IndexedStack body() {
return IndexedStack(
sizing: StackFit.expand,
index: selectedIndex,
children: [HomeScreen(), ExploreScreen(), SettingScreen()],
);
Widget body() {
return widget.child;
}
void _onItemTapped(BuildContext context, int index) {
setState(() {
selectedIndex = index;
});
switch (index) {
case 0:
context.go(AppRouter.initial);
break;
case 1:
context.go(AppRouter.explore);
break;
case 2:
context.go(AppRouter.setting);
break;
}
}
}

View File

@ -1,6 +1,14 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:go_router/go_router.dart';
import 'package:proxibuy/core/gen/assets.gen.dart';
import 'package:proxibuy/core/routes/app_router.dart';
import 'package:proxibuy/core/utils/empty_space.dart';
import 'package:proxibuy/presentation/providers/cubit/them_mode_cubit.dart';
import 'package:proxibuy/presentation/ui/theme/colors.dart';
import 'package:proxibuy/presentation/ui/theme/responsive.dart';
import 'package:proxibuy/presentation/ui/widgets/carousel/carousel_slider_widget.dart';
class HomeScreen extends StatefulWidget {
const HomeScreen({super.key});
@ -17,58 +25,674 @@ class _HomeScreenState extends State<HomeScreen> {
@override
Widget build(BuildContext context) {
final defaultBorder = OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide:
BorderSide(color: Theme.of(context).colorScheme.surface, width: 2));
return Responsive(context).builder(
mobile: Scaffold(
body: Padding(
padding: const EdgeInsets.all(16.0),
return Responsive(context)
.builder(mobile: mobile(context), desktop: desktop(context));
}
Scaffold desktop(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
physics: BouncingScrollPhysics(),
child: Center(
child: ConstrainedBox(
constraints: BoxConstraints(maxWidth: 1600),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
// ElevatedButton(
// onPressed: () async {
// final notifPer = await requestNotificationPermission();
// if (notifPer) {
// if (kIsWeb) {
// NotificationServiceWeb.showNotification();
// } else {
// await NotificationSrviceAndroid.showCustomNotification();
// }
// }
// },
// child: Text('Show Notification')),
Flexible(
child: Container(
constraints: BoxConstraints(maxWidth: 800),
child: TextField(
textInputAction: TextInputAction.search,
onSubmitted: (value) {
print(value);
},
decoration: InputDecoration(
hintText: 'what are you looking for?',
suffixIcon: Padding(
padding: const EdgeInsets.all(12.0),
child: Assets.icon.outline.search.svg(
color: Theme.of(context).colorScheme.onSurface,
width: 16,
height: 16),
children: [
12.h,
titleDivider(context, title: 'what\'s on your mind?', top: 16),
SizedBox(
width: double.infinity,
height: 40,
child: ListView.builder(
itemCount: 20,
scrollDirection: Axis.horizontal,
shrinkWrap: true,
padding: EdgeInsets.symmetric(horizontal: 10),
physics: BouncingScrollPhysics(),
itemBuilder: (context, index) {
return Container(
width: 200,
height: 40,
margin: EdgeInsets.symmetric(horizontal: 6),
padding: EdgeInsets.all(8),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
color: Theme.of(context).colorScheme.surface,
),
enabledBorder: defaultBorder,
border: defaultBorder),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.car_crash),
8.w,
Text('Category')
],
),
);
},
),
)),
),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
titleDivider(context,
title: 'Top 10 Discount & Offers'),
CarouselSliderWidget<String>(
items: ['1', '2', '3', '4'],
height: 320,
viewportFraction: 0.9,
onPageBuilder: (context, item) {
return ClipRRect(
borderRadius: BorderRadius.circular(16),
child: Image.network(
'https://pixcap.com/cdn/library/templates/f1ee999f-4f9e-4b5d-83b5-51d04681a999/thumbnail/9158b87d-1079-4973-9514-ee4ada0adf54_transparent_1422_800.webp',
fit: BoxFit.cover,
width: double.infinity,
),
);
},
),
],
),
),
12.w,
Expanded(
child: flashSales(context),
)
],
),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(child: seasonalDiscounts(context)),
12.w,
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
titleDivider(context, title: 'special discount'),
CarouselSliderWidget<String>(
items: ['1', '2', '3', '4'],
height: 280,
viewportFraction: 0.9,
onPageBuilder: (context, item) {
return ClipRRect(
borderRadius: BorderRadius.circular(16),
child: Image.network(
'https://pixcap.com/cdn/library/templates/f1ee999f-4f9e-4b5d-83b5-51d04681a999/thumbnail/9158b87d-1079-4973-9514-ee4ada0adf54_transparent_1422_800.webp',
fit: BoxFit.cover,
width: double.infinity,
),
);
},
),
],
)),
],
),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
titleDivider(context, title: 'special discount'),
CarouselSliderWidget<String>(
items: ['1', '2', '3', '4'],
height: 280,
viewportFraction: 0.9,
onPageBuilder: (context, item) {
return ClipRRect(
borderRadius: BorderRadius.circular(16),
child: Image.network(
'https://pixcap.com/cdn/library/templates/f1ee999f-4f9e-4b5d-83b5-51d04681a999/thumbnail/9158b87d-1079-4973-9514-ee4ada0adf54_transparent_1422_800.webp',
fit: BoxFit.cover,
width: double.infinity,
),
);
},
),
],
)),
12.w,
Expanded(child: firstPurchaseDiscount(context)),
],
),
64.h
],
),
),
),
desktop: Scaffold(
body: SizedBox(),
));
),
);
}
Scaffold mobile(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Padding(
padding: const EdgeInsets.only(left: 2.0),
child: SelectableText(
"Proxibuy",
style: Theme.of(context).textTheme.headlineSmall,
),
),
actions: [
IconButton(
icon: Assets.icon.outline.notificationBing
.svg(color: Theme.of(context).colorScheme.onSurface),
onPressed: () {},
),
12.w,
IconButton(
icon: Icon(Icons.brightness_6),
onPressed: () {
context.read<ThemModeCubit>().changeTheme();
},
),
10.w
],
),
body: SingleChildScrollView(
physics: BouncingScrollPhysics(parent: AlwaysScrollableScrollPhysics()),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
searchBar(context),
categories(context),
titleDivider(context, title: 'Top 10 Discount & Offers'),
CarouselSliderWidget<String>(
items: ['1', '2', '3', '4'],
height: 180,
viewportFraction: 0.8,
onPageBuilder: (context, item) {
return ClipRRect(
borderRadius: BorderRadius.circular(16),
child: Image.network(
'https://pixcap.com/cdn/library/templates/f1ee999f-4f9e-4b5d-83b5-51d04681a999/thumbnail/9158b87d-1079-4973-9514-ee4ada0adf54_transparent_1422_800.webp',
fit: BoxFit.cover,
width: double.infinity,
),
);
},
),
flashSales(context, top: 12),
titleDivider(context, title: 'special discount'),
CarouselSliderWidget<String>(
items: ['1', '2', '3', '4'],
height: 180,
viewportFraction: 0.8,
onPageBuilder: (context, item) {
return ClipRRect(
borderRadius: BorderRadius.circular(16),
child: Image.network(
'https://pixcap.com/cdn/library/templates/f1ee999f-4f9e-4b5d-83b5-51d04681a999/thumbnail/9158b87d-1079-4973-9514-ee4ada0adf54_transparent_1422_800.webp',
fit: BoxFit.cover,
width: double.infinity,
),
);
},
),
seasonalDiscounts(context, top: 12),
titleDivider(context, title: 'Crafting something for you'),
CarouselSliderWidget<String>(
items: ['1', '2', '3', '4'],
height: 180,
viewportFraction: 0.8,
onPageBuilder: (context, item) {
return ClipRRect(
borderRadius: BorderRadius.circular(16),
child: Image.network(
'https://pixcap.com/cdn/library/templates/f1ee999f-4f9e-4b5d-83b5-51d04681a999/thumbnail/9158b87d-1079-4973-9514-ee4ada0adf54_transparent_1422_800.webp',
fit: BoxFit.cover,
width: double.infinity,
),
);
},
),
firstPurchaseDiscount(context),
12.h
],
),
),
);
}
Column firstPurchaseDiscount(BuildContext context) {
return Column(
children: [
titleDivider(context, title: 'First Purchase Discount'),
SizedBox(
width: double.infinity,
height: 280,
child: ListView.builder(
scrollDirection: Axis.horizontal,
shrinkWrap: true,
itemCount: 20,
padding: EdgeInsets.symmetric(horizontal: 16),
physics: BouncingScrollPhysics(),
itemBuilder: (context, index) {
return Container(
width: 180,
padding: EdgeInsets.all(8),
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surface,
borderRadius: BorderRadius.only(
topLeft: index == 0 ? Radius.circular(16) : Radius.zero,
bottomLeft:
index == 0 ? Radius.circular(16) : Radius.zero,
topRight:
index == 20 - 1 ? Radius.circular(16) : Radius.zero,
bottomRight: index == 20 - 1
? Radius.circular(16)
: Radius.zero)),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Center(
child: ClipRRect(
borderRadius: BorderRadius.circular(16),
child: Image.network(
'https://s3-alpha-sig.figma.com/img/6ec2/c17a/beca4d2eb02da53e80d47f73d5f6b56d?Expires=1740960000&Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ&Signature=VvgWny6Sfh-HI0Yp2stzKejafivtWKDI9I5FKuSAQ8VqNLgiT4c5zB5m-PX174NFrSDvkocDlUIZ33gM~hrAafD8UreEvYfs30sB0ZrIPR7kSPcms~d9ArYJRsXSQ7w8-cv~RHWruGfbw462CrOdvJadQ3ZReRkK9CJsPCg2EcU9mr~hlcyx84QxGx0rw~FdBvHt99pzX0gDMWpr0kC9Om-eM45Fylmcb91d5AGh2sxtf0NXyNwt83jjfKC-VOZHt5wbjbZq3NQNGmrwWTwzLOauhjtgOsC32EbsPim3O~8CrKJAQ-TVOSXN4B15ygiFxZ1WX2z6l-LnjFghzv9Z3w__',
width: double.infinity,
height: 120,
fit: BoxFit.cover,
),
),
),
12.h,
SelectableText(
'McDonald\'s',
style: Theme.of(context).textTheme.titleMedium?.copyWith(
overflow: TextOverflow.ellipsis,
),
maxLines: 1,
),
12.h,
SelectableText('Fast food',
maxLines: 1,
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
overflow: TextOverflow.ellipsis,
)),
8.h,
SelectableText('Up to 20% Off',
maxLines: 1,
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
overflow: TextOverflow.ellipsis,
)),
8.h,
Row(
children: [
Icon(
Icons.star_border_outlined,
color: semanticGreen,
),
4.w,
Text('4.5'),
],
)
],
),
);
},
),
),
],
);
}
Column seasonalDiscounts(BuildContext context, {final double top = 32}) {
return Column(
children: [
titleDivider(context, title: 'Seasonal Discount', top: top),
SizedBox(
width: double.infinity,
height: 100 * 2 + 12,
child: GridView.builder(
scrollDirection: Axis.horizontal,
shrinkWrap: true,
padding: EdgeInsets.symmetric(horizontal: 16),
physics: BouncingScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
mainAxisSpacing: 16,
crossAxisSpacing: 12,
childAspectRatio: 0.3,
crossAxisCount: 2),
itemBuilder: (context, index) {
return InkWell(
onTap: () {
context.go(AppRouter.product);
},
child: ClipRRect(
borderRadius: BorderRadius.circular(16),
child: Container(
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surface),
child: Row(
children: [
Image.network(
'https://s3-alpha-sig.figma.com/img/55dd/f119/e880815733401c0400dc01734b64e83a?Expires=1740960000&Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ&Signature=HtKhelOfFUI1gplOzBHtfDP4ljCPECuypXWNc88VVBfYaQ2knCk0qPFwd4mjcH7Trru2W8S4hpDUeo-ztViRi~83USuULrSE0558MtBC~3TjS5S~Jm7eaDQO3YtvnsRtPK2xDamOJU80Xnkq0YPPkB~EVb8jVKF-b8JF2jdjEwon6fcltZDb7jTFJU8L9pYQQAhFxRV1QC8dOwnTT1zknm9iDNRDVGSj~VKwPpQX7daYzAf7b6DuLF4sk7DmX2fDdgF54pcYZjc1UOoubraM-sf-RKnh2JD8Vl~XK9-drzg8~t9CT99dxxHYp6udCLlya~dHNhIYjd5R4anoDQQLPg__',
width: 100,
height: 100,
fit: BoxFit.cover,
),
8.w,
Expanded(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SelectableText(
'boots',
style: Theme.of(context)
.textTheme
.titleMedium
?.copyWith(overflow: TextOverflow.ellipsis),
maxLines: 1,
),
12.h,
Row(
children: [
Icon(
Icons.shopping_bag_outlined,
size: 16,
),
8.w,
Expanded(
child: SelectableText(
'Columbia Sportswear',
style: Theme.of(context)
.textTheme
.bodyMedium
?.copyWith(
overflow: TextOverflow.ellipsis,
),
maxLines: 1,
),
),
],
),
8.h,
Row(
children: [
Icon(
CupertinoIcons.ticket,
size: 16,
),
8.w,
Expanded(
child: SelectableText(
'22 - 35% off',
style: Theme.of(context)
.textTheme
.bodyMedium
?.copyWith(
color: semanticRed,
overflow: TextOverflow.ellipsis,
),
maxLines: 1,
),
),
],
)
],
),
))
],
),
),
),
);
},
),
),
],
);
}
Column flashSales(BuildContext context, {double top = 32}) {
return Column(
children: [
titleDivider(context, title: 'Flash Sale', top: top),
SizedBox(
width: double.infinity,
height: 348,
child: ListView.builder(
itemCount: 20,
scrollDirection: Axis.horizontal,
shrinkWrap: true,
padding: EdgeInsets.symmetric(horizontal: 10),
physics: BouncingScrollPhysics(),
itemBuilder: (context, index) {
return InkWell(
onTap: () {
context.go(AppRouter.product);
},
child: Container(
width: 200,
margin: EdgeInsets.symmetric(horizontal: 6),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
color: Theme.of(context).colorScheme.surface,
),
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Icon(
Icons.timer_outlined,
color: semanticRed,
size: 32,
),
12.w,
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SelectableText(
'Limited time deal',
style:
Theme.of(context).textTheme.titleMedium,
),
SelectableText('08: 35”:48',
style: Theme.of(context)
.textTheme
.titleSmall
?.copyWith(color: semanticRed))
],
)
],
),
),
AspectRatio(
aspectRatio: 16 / 9,
child: Image.network(
'https://s3-alpha-sig.figma.com/img/7919/da3d/6e638d21e4b8cec7cda36bd4fdec2012?Expires=1740960000&Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ&Signature=OiH30jVJjAo~EZTdnnGakp0gZzdPFWPHrthl4iSPv8X7d-pGh35sycz42ZvNekboa2Hyp22O4mx8YUOn~SUVHuIKsxmRblfb-vlGfCwqg9xZL16R8pQV6V~v8FpAvFIQL1id6EgfuL4VcnADASZ7m2XjJ6CDNd~c~-k5N4MwcKUxvFNBFt7OhLNdB9bXYuAT~sfiQAai3B~JDaikS0SD48irIGaXeBi4KNAtLlFGrrGDK3KLbyfetvXwRF5ml7G0RBzEbR26WvwkgdX39B7GjCxjQzBvExI6V-JM76oc2YZiSbQIE89Qpvu2ErP77Kc6dW4aOTPGQ5RJXxPzj2vWDA__',
width: double.infinity,
height: 100,
fit: BoxFit.cover,
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SelectableText(
'Amul Cheese Slices',
style: Theme.of(context)
.textTheme
.titleLarge
?.copyWith(
overflow: TextOverflow.ellipsis,
),
maxLines: 1,
),
12.h,
Row(
children: [
Icon(Icons.location_on_outlined),
8.w,
Expanded(
child: SelectableText(
'Fresno (750m away)',
style: Theme.of(context)
.textTheme
.bodyMedium
?.copyWith(
overflow: TextOverflow.ellipsis,
),
maxLines: 1,
))
],
),
8.h,
Row(
children: [
Icon(Icons.monetization_on_outlined),
8.w,
Expanded(
child: SelectableText(
'70 \$ - 53 \$ (13% off)',
style: Theme.of(context)
.textTheme
.bodyMedium
?.copyWith(
overflow: TextOverflow.ellipsis,
),
maxLines: 1,
))
],
),
8.h,
Center(
child: ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: semanticGreen,
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(16))),
onPressed: () {},
child: Text(
'Reservation',
)),
)
],
),
)
],
)),
);
},
),
),
],
);
}
Column categories(BuildContext context) {
return Column(
children: [
titleDivider(context, title: 'what\'s on your mind?', top: 16),
SizedBox(
width: double.infinity,
height: 64,
child: ListView.builder(
itemCount: 20,
scrollDirection: Axis.horizontal,
shrinkWrap: true,
padding: EdgeInsets.symmetric(horizontal: 10),
physics: BouncingScrollPhysics(),
itemBuilder: (context, index) {
return Container(
width: 64,
height: 64,
margin: EdgeInsets.symmetric(horizontal: 6),
padding: EdgeInsets.all(8),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8),
color: Theme.of(context).colorScheme.surface,
),
child: Center(
child: Icon(Icons.abc),
),
);
},
),
),
],
);
}
Widget searchBar(
BuildContext context,
) {
final defaultBorder = OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide:
BorderSide(color: Theme.of(context).colorScheme.surface, width: 2));
return Padding(
padding: const EdgeInsets.all(16.0),
child: Row(
children: [
Flexible(
child: Container(
constraints: BoxConstraints(maxWidth: 800),
child: TextField(
textInputAction: TextInputAction.search,
onSubmitted: (value) {
print(value);
},
decoration: InputDecoration(
hintText: 'what are you looking for?',
suffixIcon: Padding(
padding: const EdgeInsets.all(12.0),
child: Assets.icon.outline.search.svg(
color: Theme.of(context).colorScheme.onSurface,
width: 16,
height: 16),
),
enabledBorder: defaultBorder,
border: defaultBorder),
),
)),
],
),
);
}
Column titleDivider(BuildContext context,
{required final String title,
final double top = 32,
final double bottom = 16}) {
return Column(
children: [
top.h,
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Row(
children: [
SelectableText(
title,
style: Theme.of(context).textTheme.titleMedium,
),
12.w,
Expanded(
child: Divider(
color: Theme.of(context).colorScheme.onSurface,
)),
],
),
),
bottom.h,
],
);
}
}

View File

@ -0,0 +1,707 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:proxibuy/core/utils/empty_space.dart';
import 'package:proxibuy/presentation/ui/theme/colors.dart';
import 'package:proxibuy/presentation/ui/theme/responsive.dart';
class ProductPage extends StatelessWidget {
const ProductPage({super.key});
@override
Widget build(BuildContext context) {
return DefaultTabController(
length: 2,
child: Responsive(context).builder(
mobile: Scaffold(
body: SingleChildScrollView(
child: Column(
children: [
Stack(
children: [
Padding(
padding: const EdgeInsets.only(bottom: 46),
child: AspectRatio(
aspectRatio: 0.95,
child: Image.network(
'https://s3-alpha-sig.figma.com/img/4361/9bde/26f7810ea7f22d8aa59a907d378c16ff?Expires=1740960000&Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ&Signature=DIm2QGXae9cxWDNV2UoJd4JWpvvmL~qKmEefvrtVw9XwKTVHwcfgqR3-s-5s7jqsTiT0iWDsYY10MeuSf2d4xXx9uTra~QEj3LbO1x4cRv4DBDJ-wkLGxliV07HVWl~CMl1MhzXyfUvWkrR30QQ5x3IslvBpfulMj88AYU5l97XPaNMOcMT8YqErdCdpiqdXBM9L2vUpCUbZGH~SfKCQyl1QcNhuCBTPODPWcK6kGU1ell3qwXC0-4JcLiiR-Kdo9asKy495iVtQ584fyZAdeN1R4oJnVGnAlUyN2HRQh6j518FCrJIzr7O0JajvrmwZ7j48nXjWPtG0SGp8Lq4l6A__',
width: double.infinity,
fit: BoxFit.cover,
)),
),
Positioned(
left: 16,
right: 16,
top: 32,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
InkWell(
onTap: () {
context.pop();
},
child: Container(
decoration: BoxDecoration(
color: Theme.of(context)
.colorScheme
.surface
.withAlpha(180),
borderRadius: BorderRadius.circular(8)),
padding: EdgeInsets.all(8),
child: Icon(Icons.arrow_back_ios_new_rounded),
),
),
InkWell(
onTap: () {
context.pop();
},
child: Container(
decoration: BoxDecoration(
color: Theme.of(context)
.colorScheme
.surface
.withAlpha(180),
borderRadius: BorderRadius.circular(8)),
padding: EdgeInsets.all(8),
child: Icon(Icons.bookmark_add_rounded),
),
),
],
)),
Positioned(
right: 0,
left: 0,
bottom: 0,
child: SizedBox(
width: double.infinity,
height: 90,
child: ListView.builder(
itemCount: 20,
padding: EdgeInsets.symmetric(horizontal: 8),
scrollDirection: Axis.horizontal,
shrinkWrap: true,
physics: BouncingScrollPhysics(),
itemBuilder: (context, index) {
return Container(
margin: EdgeInsets.symmetric(horizontal: 8),
padding: EdgeInsets.all(4),
decoration: BoxDecoration(
color: Theme.of(context)
.colorScheme
.surface
.withAlpha(200),
borderRadius: BorderRadius.circular(8)),
child: Image.network(
'https://static.vecteezy.com/system/resources/previews/021/275/832/non_2x/running-shoes-illustration-with-fire-shape-yellow-and-red-isolated-on-transparan-background-free-png.png'),
);
},
),
))
],
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: TabBar(
tabs: [
Tab(text: 'Item'),
Tab(text: 'Shop'),
],
),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
child: SizedBox(
height: 1500,
child: TabBarView(
children: [itemTab(context), shopTab(context)],
),
),
),
],
),
),
),
desktop: Scaffold(),
),
);
}
Widget itemTab(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SelectableText(
'Philadelphia Honey Pecan Cream Cheese Spread, 7.5 oz Tub',
style: Theme.of(context).textTheme.headlineSmall,
),
4.h,
SelectableText(
'Brand: Philadelphia',
style: Theme.of(context).textTheme.titleSmall,
),
8.h,
Row(
children: [
Icon(Icons.star_rate_rounded),
Icon(Icons.star_rate_rounded),
Icon(Icons.star_rate_rounded),
Icon(Icons.star_rate_rounded),
Icon(Icons.star_half_rounded),
8.w,
Text(
'4.8',
style: Theme.of(context).textTheme.bodyMedium,
)
],
),
8.h,
SelectableText(
'Currently available. 23 remain',
style: Theme.of(context).textTheme.titleSmall,
),
12.h,
Row(
children: [
Icon(Icons.warning_amber_rounded),
8.w,
Text(
'Expire: 5 days',
style: Theme.of(context).textTheme.bodyMedium,
)
],
),
8.h,
Divider(
color: Theme.of(context).colorScheme.onSurface,
),
8.h,
SelectableText(
'Nutrition summary',
style: Theme.of(context).textTheme.titleLarge,
),
4.h,
SelectableText(
'7 servings per container | 2 Tbsp (33g)',
style: Theme.of(context).textTheme.bodyLarge,
),
16.h,
Container(
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surface,
borderRadius: BorderRadius.circular(16)),
padding: EdgeInsets.symmetric(vertical: 8, horizontal: 16),
child: Flex(
direction: Axis.horizontal,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Flexible(
flex: 1,
child: Column(
children: [
SelectableText(
'80',
style: Theme.of(context)
.textTheme
.labelLarge
?.copyWith(color: Theme.of(context).primaryColor),
),
SelectableText('Calories',
style: Theme.of(context).textTheme.labelLarge),
],
),
),
Flexible(
flex: 1,
child: Column(
children: [
SelectableText(
'100mg',
style: Theme.of(context)
.textTheme
.labelLarge
?.copyWith(color: Theme.of(context).primaryColor),
),
SelectableText('Sodium',
style: Theme.of(context).textTheme.labelLarge),
],
),
),
Flexible(
flex: 1,
child: Column(
children: [
SelectableText(
'0g',
style: Theme.of(context)
.textTheme
.labelLarge
?.copyWith(color: Theme.of(context).primaryColor),
),
SelectableText('Dietary Fiber',
style: Theme.of(context).textTheme.labelLarge),
],
),
),
Flexible(
flex: 1,
child: Column(
children: [
SelectableText(
'5g',
style: Theme.of(context)
.textTheme
.labelLarge
?.copyWith(color: Theme.of(context).primaryColor),
),
SelectableText('Sugars',
style: Theme.of(context).textTheme.labelLarge),
],
),
),
],
),
),
16.h,
Divider(
color: Theme.of(context).colorScheme.onSurface,
),
16.h,
Row(
children: [
Container(
decoration: BoxDecoration(
color: semanticRed, borderRadius: BorderRadius.circular(8)),
padding: EdgeInsets.all(8),
child: Text(
'HOT',
style: Theme.of(context)
.textTheme
.titleMedium
?.copyWith(color: Colors.white),
),
),
8.w,
SelectableText(
'(50%) 32.18 - 16.9 \$',
style: Theme.of(context)
.textTheme
.titleMedium
?.copyWith(color: semanticRed),
)
],
),
16.h,
Center(
child: Text(
'Top reviews from the United States',
style: Theme.of(context).textTheme.titleMedium,
)),
8.h,
ListView.builder(
shrinkWrap: true,
itemCount: 3,
physics: NeverScrollableScrollPhysics(),
itemBuilder: (context, index) {
return Column(
children: [
ListTile(
contentPadding: EdgeInsets.zero,
title: SelectableText(
'Kristin Watson',
style: Theme.of(context).textTheme.labelLarge,
),
subtitle: SelectableText(
'Verified Buyer',
style: Theme.of(context).textTheme.bodySmall,
),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.star_rate_rounded),
Icon(Icons.star_rate_rounded),
Icon(Icons.star_rate_rounded),
Icon(Icons.star_rate_rounded),
Icon(Icons.star_rate_rounded),
],
),
),
16.h,
SelectableText(
'This is 💯 one hundred percent the best !!! "Philadelphia cream cheese is absolutely amazing—so creamy and versatile, it elevates every recipe, from cheesecakes to simple bagels. A must-have in my kitchen!"😋😋😋',
style: Theme.of(context).textTheme.bodyLarge,
),
16.h,
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
Icon(Icons.thumb_up_alt_outlined),
8.w,
Text('Yes (2)'),
12.w,
Icon(Icons.thumb_down_alt_outlined),
8.w,
Text('No (0)'),
],
),
Text(
'Nov 09, 2024',
style: Theme.of(context).textTheme.bodySmall,
)
],
),
if (index != 3 - 1)
Divider(
color: Theme.of(context).colorScheme.onSurface,
)
],
);
},
),
12.h,
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'See all reviws',
style: Theme.of(context)
.textTheme
.titleMedium
?.copyWith(color: semanticRed),
),
4.w,
Icon(
Icons.arrow_forward,
color: semanticRed,
)
],
)
],
),
);
}
Widget shopTab(BuildContext context) {
return Column(
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SelectableText(
'Heinen\'s Grocery',
style: Theme.of(context).textTheme.headlineSmall,
),
8.h,
Row(
children: [
Icon(Icons.star_rate_rounded),
Icon(Icons.star_rate_rounded),
Icon(Icons.star_rate_rounded),
Icon(Icons.star_rate_rounded),
Icon(Icons.star_half_rounded),
8.w,
Text(
'4.8',
style: Theme.of(context).textTheme.bodyMedium,
)
],
),
8.h,
Row(
children: [
Icon(Icons.location_on_outlined),
8.w,
Text(
'Shop 1, Cleveland, Ohio, United States',
style: Theme.of(context).textTheme.bodyMedium,
)
],
),
4.h,
Row(
children: [
Icon(Icons.access_time_rounded),
8.w,
Text(
'Open now | 10:00 AM - 12:00 PM',
style: Theme.of(context).textTheme.bodyMedium,
)
],
),
16.h,
Row(
children: [
SelectableText(
'Facilities',
style: Theme.of(context).textTheme.titleMedium,
),
8.w,
Expanded(
child: Divider(
color: Theme.of(context).colorScheme.onSurface,
),
),
],
),
8.h,
Row(
children: [
Icon(Icons.check_box_outlined),
8.w,
Text(
'Home Delivery',
style: Theme.of(context).textTheme.bodyMedium,
)
],
),
16.h,
SizedBox(
height: 46,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Theme.of(context).colorScheme.surface),
onPressed: () {},
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.navigation_rounded),
4.w,
Text('Direction')
],
)),
),
16.h,
Container(
width: double.infinity,
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surface,
borderRadius: BorderRadius.circular(16)),
padding: EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
'23 min (8.7 km)',
style: Theme.of(context).textTheme.titleLarge,
),
12.h,
SizedBox(
height: 46,
width: double.infinity,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: semanticGreen),
onPressed: () {},
child: Text('Reservation')),
),
],
),
),
],
),
),
16.h,
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Row(
children: [
SelectableText(
'List of offers',
style: Theme.of(context).textTheme.titleLarge,
),
],
),
),
16.h,
SizedBox(
width: double.infinity,
height: 150,
child: ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
padding: EdgeInsets.symmetric(horizontal: 8),
physics: BouncingScrollPhysics(),
itemBuilder: (context, index) {
return Container(
width: 300,
padding: EdgeInsets.all(12),
margin: EdgeInsets.symmetric(horizontal: 8),
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surface,
borderRadius: BorderRadius.circular(16)),
child: Column(
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ClipRRect(
borderRadius: BorderRadius.circular(8),
child: Image.network(
'https://s3-alpha-sig.figma.com/img/f773/0650/56608740ed0260647aa12c36f8b46534?Expires=1740960000&Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ&Signature=UxdqWfGI5Ix~S2728Qsiw0MHGST~we6M25cWRZ8YetaIGlC-ITXjDaX8LDssimYJt5XWmfyWqE0D4vRq1lP9Nmy3CfI~bLXaaBBSmQqAwdXDz1aVXFh7Q8ri5klxYoCjIF0HTp3nr4Scpf5d9PHU7L32s8JF0pz4dt8tyaCo-goeEOsjn8Q-LOBKNHVE6B8uRnW74GH12V7GNygxv1EV59dDD1vcXNcD7kS~2Ox7RejK159Ys7La1F-Evbt5sU7XFOMJuFbPVUgWA05wgrF1U1zdaz5b10Mu9~4PnErR~FjJTZPYcznatVYwuxWRWRAtpwjhjew2TL0DoOvlCKHbYw__',
width: 74,
height: 74,
fit: BoxFit.cover,
),
),
12.w,
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SelectableText(
'Kellogg\'s Corn Flakes',
style: Theme.of(context)
.textTheme
.titleMedium
?.copyWith(overflow: TextOverflow.ellipsis),
maxLines: 1,
),
8.h,
SelectableText(
'Classic cereal with a crispy texture an a mildly sweet flavor',
style: Theme.of(context)
.textTheme
.bodyMedium
?.copyWith(overflow: TextOverflow.ellipsis),
maxLines: 2,
),
],
),
)
],
),
12.h,
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
Container(
decoration: BoxDecoration(
color: semanticRed,
borderRadius: BorderRadius.circular(8)),
padding: EdgeInsets.all(8),
child: Text(
'HOT',
style: Theme.of(context)
.textTheme
.titleSmall
?.copyWith(color: Colors.white),
),
),
8.w,
Text(
'(50%) / 16 - 8\$',
style: Theme.of(context).textTheme.titleSmall,
)
],
),
Container(
decoration: BoxDecoration(
color: semanticGreen,
borderRadius: BorderRadius.circular(8)),
padding: EdgeInsets.all(8),
child: Text(
'Reservation',
style: Theme.of(context)
.textTheme
.titleSmall
?.copyWith(color: Colors.white),
),
),
],
)
],
),
);
},
),
),
16.h,
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Row(
children: [
SelectableText(
'Similar Business',
style: Theme.of(context).textTheme.titleLarge,
),
],
),
),
16.h,
SizedBox(
width: double.infinity,
height: 270,
child: ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
padding: EdgeInsets.symmetric(horizontal: 8),
physics: BouncingScrollPhysics(),
itemBuilder: (context, index) {
return Container(
width: 240,
padding: EdgeInsets.all(12),
margin: EdgeInsets.symmetric(horizontal: 8),
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surface,
borderRadius: BorderRadius.circular(16)),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ClipRRect(
borderRadius: BorderRadius.circular(8),
child: AspectRatio(
aspectRatio: 16 / 9,
child: Image.network(
'https://s3-alpha-sig.figma.com/img/c720/df1c/d8288c0392372fb3dd15824b84b9d563?Expires=1740960000&Key-Pair-Id=APKAQ4GOSFWCW27IBOMQ&Signature=CMct6yvsv~g0YEUDRp-D3prnQve4nZc5mB~oJ4jbRsH63ltvM4yoCKbTYJLCm~ONwb9e7TNoFO1Q1pO8sPz3TBB-gAFIX9j53fz40ypp0VsRXSOK91G7LBj82V974E1Yqxol2fhAZ8icTAaOZVJgJH-47EG3wQqujGieHbcOYCCBZoCPP0a~jKG~LsE-EtLmP0RdXOuqE9-o2gMzEBH2TMXLtWJXYtA6dS~XHPBIeUXn4Sa7Hy4ca3pGb6wXN4owNt4SeanQuxeR-CEgDYJTI~tU6LkW1N2TSPOt6iGn5Jbb4XdkFjKA7dkwijG9mEU9F3wy16aMj7a1Z1yEwAvlwg__',
height: 100,
fit: BoxFit.cover,
),
),
),
8.h,
SelectableText(
'Milam\'s Markets',
style: Theme.of(context)
.textTheme
.titleMedium
?.copyWith(overflow: TextOverflow.ellipsis),
maxLines: 1,
),
8.h,
Row(
children: [
Icon(Icons.location_on_outlined),
8.w,
SelectableText(
'Miami Springs, Florida',
style: Theme.of(context)
.textTheme
.bodyMedium
?.copyWith(overflow: TextOverflow.ellipsis),
maxLines: 1,
)
],
),
8.h,
SizedBox(
child: ElevatedButton(
onPressed: () {}, child: Text('See more about')),
),
],
),
);
},
),
)
],
);
}
}

View File

@ -90,7 +90,7 @@ final ThemeData darkTheme = ThemeData(
CustomColors(
primarySwatch: darkPrimarySwatch,
secondrySwatch: darkSecondarySwatch,
primaryLightSurface: darkPrimarySwatch[900]!,
primaryLightSurface: darkPrimarySwatch[600]!,
),
],

View File

@ -10,6 +10,7 @@ class CarouselSliderWidget<T> extends StatefulWidget {
) onPageBuilder;
final bool withNavs;
final double height;
final double viewportFraction;
final bool autoPlay;
final bool enableInfiniteScroll;
final Function()? onLastClick;
@ -23,6 +24,7 @@ class CarouselSliderWidget<T> extends StatefulWidget {
this.autoPlay = true,
this.enableInfiniteScroll = true,
this.height = 200,
this.viewportFraction = 0.9,
});
@override
@ -46,11 +48,11 @@ class _CarouselSliderWidgetState<T> extends State<CarouselSliderWidget<T>> {
return widget.onPageBuilder(context, widget.items[index]);
},
options: CarouselOptions(
height: widget.height * 0.75,
height: widget.height,
autoPlay: widget.autoPlay,
enableInfiniteScroll: widget.enableInfiniteScroll,
enlargeCenterPage: true,
viewportFraction: 0.9,
viewportFraction: widget.viewportFraction,
onPageChanged: (index, reason) =>
setState(() => activeIndex = index),
),