feat:browse page ui done

This commit is contained in:
jahongireshonqulov
2025-10-25 15:29:38 +05:00
parent 33da49df6c
commit 57af573b6f
19 changed files with 513 additions and 19 deletions

View File

@@ -116,6 +116,31 @@
"addItemsStartBasket": "Add items to start a basket", "addItemsStartBasket": "Add items to start a basket",
"basketHint": "Once you add items from a restaurant or store, your basket will appear here.", "basketHint": "Once you add items from a restaurant or store, your basket will appear here.",
"startShopping": "Start Shopping", "startShopping": "Start Shopping",
"orders": "Orders" "orders": "Orders",
"recentSearches": "Recent searches",
"cafe": "Cafe",
"irish": "Irish",
"topCategories": "Top Categories",
"breakfastAndBrunch": "Breakfast and Brunch",
"coffeeAndTea": "Coffee and Tea",
"chinese": "Chinese",
"indian": "Indian",
"latestDeals": "Latest Deals",
"restaurantRewards": "Restaurant Rewards",
"bestOverall": "Best Overall",
"nationwideShipping": "Nationwide Shipping",
"mexican": "Mexican",
"fastFood": "Fast Food",
"healthy": "Healthy",
"pizza": "Pizza",
"sandwich": "Sandwich",
"asian": "Asian",
"bakery": "Bakery",
"allCategories": "All categories",
"categoriesShort": "Food, shopping, drinks, etc."
} }

View File

@@ -112,7 +112,30 @@
"addItemsStartBasket": "Добавьте товары, чтобы создать корзину", "addItemsStartBasket": "Добавьте товары, чтобы создать корзину",
"basketHint": "Когда вы добавите товары из ресторана или магазина, ваша корзина появится здесь.", "basketHint": "Когда вы добавите товары из ресторана или магазина, ваша корзина появится здесь.",
"startShopping": "Начать покупки", "startShopping": "Начать покупки",
"orders": "Заказы" "orders": "Заказы",
"recentSearches": "Недавние запросы",
"cafe": "Кафе",
"irish": "Ирландская кухня",
"topCategories": "Популярные категории",
"breakfastAndBrunch": "Завтрак и бранч",
"coffeeAndTea": "Кофе и чай",
"chinese": "Китайская кухня",
"indian": "Индийская кухня",
"latestDeals": "Новые предложения",
"restaurantRewards": "Ресторанные бонусы",
"bestOverall": "Лучшие варианты",
"nationwideShipping": "Доставка по всей стране",
"mexican": "Мексиканская кухня",
"fastFood": "Фастфуд",
"healthy": "Здоровая еда",
"pizza": "Пицца",
"sandwich": "Сэндвич",
"asian": "Азиатская кухня",
"bakery": "Пекарня",
"categoriesShort": "Еда, покупки, напитки и т.д.",
"allCategories": "Все категории"

View File

@@ -112,7 +112,30 @@
"addItemsStartBasket": "Savatni boshlash uchun mahsulot qoshing", "addItemsStartBasket": "Savatni boshlash uchun mahsulot qoshing",
"basketHint": "Restorandan yoki do'kondan mahsulot qoshsangiz, savatingiz shu yerda paydo boladi.", "basketHint": "Restorandan yoki do'kondan mahsulot qoshsangiz, savatingiz shu yerda paydo boladi.",
"startShopping": "Xaridni boshlash", "startShopping": "Xaridni boshlash",
"orders": "Buyurtmalar" "orders": "Buyurtmalar",
"recentSearches": "Yaqinda qidirilganlar",
"cafe": "Kafe",
"irish": "Irlandcha",
"topCategories": "Eng ommabop toifalar",
"breakfastAndBrunch": "Nonushta va bransh",
"coffeeAndTea": "Qahva va choy",
"chinese": "Xitoy taomlari",
"indian": "Hind taomlari",
"latestDeals": "Yangi chegirmalar",
"restaurantRewards": "Restoran mukofotlari",
"bestOverall": "Eng yaxshilari",
"nationwideShipping": "Butun mamlakat boylab yetkazib berish",
"mexican": "Meksika taomlari",
"fastFood": "Tezkor ovqatlar",
"healthy": "Soglom ovqatlar",
"pizza": "Pitsa",
"sandwich": "Sendvich",
"asian": "Osiyo taomlari",
"bakery": "Qandolatxona",
"categoriesShort": "Ovqat, xaridlar, ichimliklar va boshqalar.",
"allCategories": "Barcha toifalar"

View File

@@ -10,6 +10,9 @@ abstract class AppLocaleKeys {
static const String imageUrl = static const String imageUrl =
"https://xsznseejebbai1lj.public.blob.vercel-storage.com/homepage/hero/hero-1.webp"; "https://xsznseejebbai1lj.public.blob.vercel-storage.com/homepage/hero/hero-1.webp";
static const String foodImageUrl =
"https://www.precisionorthomd.com/wp-content/uploads/2023/10/percision-blog-header-junk-food-102323.jpg";
static const String lorem = '''Lorem Ipsum is simply dummy text of the static const String lorem = '''Lorem Ipsum is simply dummy text of the
printing and typesetting industry. Lorem Ipsum printing and typesetting industry. Lorem Ipsum
has been the industry's standard dummy text ever has been the industry's standard dummy text ever

View File

@@ -427,7 +427,7 @@ abstract class AppLocalizations {
/// No description provided for @bestOverall. /// No description provided for @bestOverall.
/// ///
/// In en, this message translates to: /// In en, this message translates to:
/// **'Best overall'** /// **'Best Overall'**
String get bestOverall; String get bestOverall;
/// No description provided for @priceRange. /// No description provided for @priceRange.
@@ -555,6 +555,102 @@ abstract class AppLocalizations {
/// In en, this message translates to: /// In en, this message translates to:
/// **'Orders'** /// **'Orders'**
String get orders; String get orders;
/// No description provided for @recentSearches.
///
/// In en, this message translates to:
/// **'Recent searches'**
String get recentSearches;
/// No description provided for @cafe.
///
/// In en, this message translates to:
/// **'Cafe'**
String get cafe;
/// No description provided for @irish.
///
/// In en, this message translates to:
/// **'Irish'**
String get irish;
/// No description provided for @topCategories.
///
/// In en, this message translates to:
/// **'Top Categories'**
String get topCategories;
/// No description provided for @breakfastAndBrunch.
///
/// In en, this message translates to:
/// **'Breakfast and Brunch'**
String get breakfastAndBrunch;
/// No description provided for @coffeeAndTea.
///
/// In en, this message translates to:
/// **'Coffee and Tea'**
String get coffeeAndTea;
/// No description provided for @latestDeals.
///
/// In en, this message translates to:
/// **'Latest Deals'**
String get latestDeals;
/// No description provided for @restaurantRewards.
///
/// In en, this message translates to:
/// **'Restaurant Rewards'**
String get restaurantRewards;
/// No description provided for @nationwideShipping.
///
/// In en, this message translates to:
/// **'Nationwide Shipping'**
String get nationwideShipping;
/// No description provided for @mexican.
///
/// In en, this message translates to:
/// **'Mexican'**
String get mexican;
/// No description provided for @fastFood.
///
/// In en, this message translates to:
/// **'Fast Food'**
String get fastFood;
/// No description provided for @healthy.
///
/// In en, this message translates to:
/// **'Healthy'**
String get healthy;
/// No description provided for @pizza.
///
/// In en, this message translates to:
/// **'Pizza'**
String get pizza;
/// No description provided for @sandwich.
///
/// In en, this message translates to:
/// **'Sandwich'**
String get sandwich;
/// No description provided for @bakery.
///
/// In en, this message translates to:
/// **'Bakery'**
String get bakery;
/// No description provided for @categoriesShort.
///
/// In en, this message translates to:
/// **'Food, shopping, drinks, etc.'**
String get categoriesShort;
} }
class _AppLocalizationsDelegate class _AppLocalizationsDelegate

View File

@@ -178,7 +178,7 @@ class AppLocalizationsEn extends AppLocalizations {
String get deals => 'Deals'; String get deals => 'Deals';
@override @override
String get bestOverall => 'Best overall'; String get bestOverall => 'Best Overall';
@override @override
String get priceRange => 'Price range'; String get priceRange => 'Price range';
@@ -247,4 +247,52 @@ class AppLocalizationsEn extends AppLocalizations {
@override @override
String get orders => 'Orders'; String get orders => 'Orders';
@override
String get recentSearches => 'Recent searches';
@override
String get cafe => 'Cafe';
@override
String get irish => 'Irish';
@override
String get topCategories => 'Top Categories';
@override
String get breakfastAndBrunch => 'Breakfast and Brunch';
@override
String get coffeeAndTea => 'Coffee and Tea';
@override
String get latestDeals => 'Latest Deals';
@override
String get restaurantRewards => 'Restaurant Rewards';
@override
String get nationwideShipping => 'Nationwide Shipping';
@override
String get mexican => 'Mexican';
@override
String get fastFood => 'Fast Food';
@override
String get healthy => 'Healthy';
@override
String get pizza => 'Pizza';
@override
String get sandwich => 'Sandwich';
@override
String get bakery => 'Bakery';
@override
String get categoriesShort => 'Food, shopping, drinks, etc.';
} }

View File

@@ -90,7 +90,7 @@ class AppLocalizationsRu extends AppLocalizations {
String get takeout => 'На вынос'; String get takeout => 'На вынос';
@override @override
String get asian => 'Азиатская'; String get asian => 'Азиатская кухня';
@override @override
String get iceCream => 'Мороженое'; String get iceCream => 'Мороженое';
@@ -105,7 +105,7 @@ class AppLocalizationsRu extends AppLocalizations {
String get caribbean => 'Карибская'; String get caribbean => 'Карибская';
@override @override
String get indian => 'Индийская'; String get indian => 'Индийская кухня';
@override @override
String get french => 'Французская'; String get french => 'Французская';
@@ -120,7 +120,7 @@ class AppLocalizationsRu extends AppLocalizations {
String get ride => 'Поездка'; String get ride => 'Поездка';
@override @override
String get chinese => 'Китайская'; String get chinese => 'Китайская кухня';
@override @override
String get dessert => 'Десерт'; String get dessert => 'Десерт';
@@ -179,7 +179,7 @@ class AppLocalizationsRu extends AppLocalizations {
String get deals => 'Скидки'; String get deals => 'Скидки';
@override @override
String get bestOverall => 'Лучший выбор'; String get bestOverall => 'Лучшие варианты';
@override @override
String get priceRange => 'Диапазон цен'; String get priceRange => 'Диапазон цен';
@@ -248,4 +248,52 @@ class AppLocalizationsRu extends AppLocalizations {
@override @override
String get orders => 'Заказы'; String get orders => 'Заказы';
@override
String get recentSearches => 'Недавние запросы';
@override
String get cafe => 'Кафе';
@override
String get irish => 'Ирландская кухня';
@override
String get topCategories => 'Популярные категории';
@override
String get breakfastAndBrunch => 'Завтрак и бранч';
@override
String get coffeeAndTea => 'Кофе и чай';
@override
String get latestDeals => 'Новые предложения';
@override
String get restaurantRewards => 'Ресторанные бонусы';
@override
String get nationwideShipping => 'Доставка по всей стране';
@override
String get mexican => 'Мексиканская кухня';
@override
String get fastFood => 'Фастфуд';
@override
String get healthy => 'Здоровая еда';
@override
String get pizza => 'Пицца';
@override
String get sandwich => 'Сэндвич';
@override
String get bakery => 'Пекарня';
@override
String get categoriesShort => 'Еда, покупки, напитки и т.д.';
} }

View File

@@ -90,7 +90,7 @@ class AppLocalizationsUz extends AppLocalizations {
String get takeout => 'Olib ketish'; String get takeout => 'Olib ketish';
@override @override
String get asian => 'Osiyo'; String get asian => 'Osiyo taomlari';
@override @override
String get iceCream => 'Muzqaymoq'; String get iceCream => 'Muzqaymoq';
@@ -105,7 +105,7 @@ class AppLocalizationsUz extends AppLocalizations {
String get caribbean => 'Karib'; String get caribbean => 'Karib';
@override @override
String get indian => 'Hind'; String get indian => 'Hind taomlari';
@override @override
String get french => 'Fransuz'; String get french => 'Fransuz';
@@ -120,7 +120,7 @@ class AppLocalizationsUz extends AppLocalizations {
String get ride => 'Yol'; String get ride => 'Yol';
@override @override
String get chinese => 'Xitoy'; String get chinese => 'Xitoy taomlari';
@override @override
String get dessert => 'Desert'; String get dessert => 'Desert';
@@ -179,7 +179,7 @@ class AppLocalizationsUz extends AppLocalizations {
String get deals => 'Aksiyalar'; String get deals => 'Aksiyalar';
@override @override
String get bestOverall => 'Eng yaxshisi'; String get bestOverall => 'Eng yaxshilari';
@override @override
String get priceRange => 'Narx oraligi'; String get priceRange => 'Narx oraligi';
@@ -248,4 +248,52 @@ class AppLocalizationsUz extends AppLocalizations {
@override @override
String get orders => 'Buyurtmalar'; String get orders => 'Buyurtmalar';
@override
String get recentSearches => 'Yaqinda qidirilganlar';
@override
String get cafe => 'Kafe';
@override
String get irish => 'Irlandcha';
@override
String get topCategories => 'Eng ommabop toifalar';
@override
String get breakfastAndBrunch => 'Nonushta va bransh';
@override
String get coffeeAndTea => 'Qahva va choy';
@override
String get latestDeals => 'Yangi chegirmalar';
@override
String get restaurantRewards => 'Restoran mukofotlari';
@override
String get nationwideShipping => 'Butun mamlakat boylab yetkazib berish';
@override
String get mexican => 'Meksika taomlari';
@override
String get fastFood => 'Tezkor ovqatlar';
@override
String get healthy => 'Soglom ovqatlar';
@override
String get pizza => 'Pitsa';
@override
String get sandwich => 'Sendvich';
@override
String get bakery => 'Qandolatxona';
@override
String get categoriesShort => 'Ovqat, xaridlar, ichimliklar va boshqalar.';
} }

View File

@@ -10,7 +10,6 @@ class AppRoutes {
final GoRouter router = GoRouter( final GoRouter router = GoRouter(
navigatorKey: navigatorKey, navigatorKey: navigatorKey,
initialLocation: Routes.splash, initialLocation: Routes.splash,
routes: [ routes: [
GoRoute(path: Routes.splash, builder: (context, state) => SplashPage()), GoRoute(path: Routes.splash, builder: (context, state) => SplashPage()),
GoRoute( GoRoute(
@@ -33,6 +32,10 @@ class AppRoutes {
child: RestaurantsByCategoryPage(categoryName: state.extra as String), child: RestaurantsByCategoryPage(categoryName: state.extra as String),
), ),
), ),
GoRoute(
path: Routes.browse,
pageBuilder: (context, state) => CupertinoPage(child: BrowsePage()),
),
], ],
); );
} }

View File

@@ -5,5 +5,6 @@ abstract class Routes {
static const String main = '/main'; static const String main = '/main';
static const String categories = '/categories'; static const String categories = '/categories';
static const String filters = '/filters'; static const String filters = '/filters';
static const String browse = '/browse';
static const String restaurantsByCategory = '/restaurants-by-category'; static const String restaurantsByCategory = '/restaurants-by-category';
} }

View File

@@ -22,4 +22,7 @@ abstract class AppColors {
static const Color c545454 = Color(0xFF545454); static const Color c545454 = Color(0xFF545454);
static const Color cEFF3FE = Color(0xFFEFF3FE); static const Color cEFF3FE = Color(0xFFEFF3FE);
static const Color c05A357 = Color(0xFF05A357); static const Color c05A357 = Color(0xFF05A357);
static const Color cE8E8E8 = Color(0xFFE8E8E8);
static const Color c660000 = Color(0x66000000);
} }

View File

@@ -77,6 +77,13 @@ abstract class AppTextStyles {
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
); );
static const TextStyle size24Medium = TextStyle(
color: _defaultColor,
fontSize: SizesCons.size_24,
fontFamily: _fontMedium,
fontWeight: FontWeight.w500,
);
static const TextStyle size16Bold= TextStyle( static const TextStyle size16Bold= TextStyle(
color: _defaultColor, color: _defaultColor,
fontSize: SizesCons.size_16, fontSize: SizesCons.size_16,

View File

@@ -38,6 +38,9 @@ abstract class AppUtils {
static const BorderRadius kBorderRadius14 = BorderRadius.all( static const BorderRadius kBorderRadius14 = BorderRadius.all(
Radius.circular(14), Radius.circular(14),
); );
static const BorderRadius kBorderRadius15 = BorderRadius.all(
Radius.circular(15),
);
static const BorderRadius kBorderRadius16 = BorderRadius.all( static const BorderRadius kBorderRadius16 = BorderRadius.all(
Radius.circular(16), Radius.circular(16),
); );
@@ -81,6 +84,10 @@ abstract class AppUtils {
static const BorderRadius kBorderRadius40 = BorderRadius.all( static const BorderRadius kBorderRadius40 = BorderRadius.all(
Radius.circular(40), Radius.circular(40),
); );
static const BorderRadius kBorderRadiusTop15 = BorderRadius.only(
topLeft: kRadius15,
topRight: kRadius15,
);
static const BorderRadius kBorderRadiusTop20 = BorderRadius.only( static const BorderRadius kBorderRadiusTop20 = BorderRadius.only(
topLeft: kRadius20, topLeft: kRadius20,
topRight: kRadius20, topRight: kRadius20,
@@ -93,4 +100,8 @@ abstract class AppUtils {
bottomRight: kRadius15, bottomRight: kRadius15,
topRight: kRadius15, topRight: kRadius15,
); );
static const BorderRadius kBorderRadiusBottom15 = BorderRadius.only(
bottomLeft: kRadius15,
bottomRight: kRadius15,
);
} }

View File

@@ -1,2 +1,3 @@
export 'presentation/pages/browse_page/browse_page.dart'; export 'presentation/pages/browse_page/browse_page.dart';
export 'package:food_delivery_client/feature/browse/presentation/pages/browse_page/widgets/w_browse_body.dart'; export 'package:food_delivery_client/feature/browse/presentation/pages/browse_page/widgets/w_browse_body.dart';
export 'package:food_delivery_client/feature/browse/presentation/pages/browse_page/widgets/w_browse_item.dart';

View File

@@ -0,0 +1,35 @@
import '../../../../../../food_delivery_client.dart';
class WAllCategories extends StatelessWidget {
const WAllCategories({super.key});
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
25.verticalSpace,
Text(
context.loc.allCategories,
style: AppTextStyles.size24Medium.copyWith(height: 36 / 24),
),
11.verticalSpace,
GridView.builder(
itemCount: 10,
shrinkWrap: true,
padding: EdgeInsets.zero,
physics: const NeverScrollableScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
mainAxisSpacing: 15,
crossAxisSpacing: 10,
mainAxisExtent: 140,
),
itemBuilder: (context, index) {
return WBrowseItem();
},
),
],
);
}
}

View File

@@ -1,3 +1,5 @@
import 'package:food_delivery_client/feature/browse/presentation/pages/browse_page/widgets/w_all_categories.dart';
import 'package:food_delivery_client/feature/browse/presentation/pages/browse_page/widgets/w_top_categories.dart';
import 'package:food_delivery_client/feature/common/presentation/widgets/app_text_form_field.dart'; import 'package:food_delivery_client/feature/common/presentation/widgets/app_text_form_field.dart';
import '../../../../../../food_delivery_client.dart'; import '../../../../../../food_delivery_client.dart';
@@ -8,12 +10,31 @@ class WBrowseBody extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
6.verticalSpace, DecoratedBox(
decoration: BoxDecoration(color: AppColors.cFFFFFF),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
10.verticalSpace,
AppTextFormField( AppTextFormField(
controller: TextEditingController(), controller: TextEditingController(),
prefixIcon: SvgPicture.asset( prefixIcon: SvgPicture.asset(AppIcons.icSearch),
AppIcons.icSearch, hintText: context.loc.categoriesShort,
hintTextStyle: AppTextStyles.size16Medium.copyWith(
color: AppColors.c660000
),
),
15.verticalSpace,
],
),
),
Expanded(
child: SingleChildScrollView(
child: Column(
children: [WTopCategories(), WAllCategories(), 40.verticalSpace],
),
), ),
), ),
], ],

View File

@@ -0,0 +1,52 @@
import '../../../../../../food_delivery_client.dart';
class WBrowseItem extends StatelessWidget {
const WBrowseItem({
super.key,
});
@override
Widget build(BuildContext context) {
return Bounceable(
onTap: () {},
child: Ink(
decoration: BoxDecoration(
color: AppColors.cFFFFFF,
borderRadius: AppUtils.kBorderRadius15,
),
child: Column(
children: [
ClipRRect(
borderRadius: AppUtils.kBorderRadiusTop15,
child: CachedNetworkImage(
imageUrl: AppLocaleKeys.foodImageUrl,
width: context.w,
height: 96,
fit: BoxFit.cover,
),
),
SizedBox(
width: context.w,
child: DecoratedBox(
decoration: BoxDecoration(
borderRadius: AppUtils.kBorderRadiusBottom15,
border: Border.all(
color: AppColors.cE8E8E8,
width: 1,
),
),
child: Text(
"Restaurant Rewards",
textAlign: TextAlign.center,
style: AppTextStyles.size16Regular.copyWith(
height: 20 / 16,
),
).paddingSymmetric(horizontal: 30),
),
),
],
),
),
);
}
}

View File

@@ -0,0 +1,36 @@
import '../../../../../../food_delivery_client.dart';
class WTopCategories extends StatelessWidget {
const WTopCategories({super.key});
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
context.loc.topCategories,
style: AppTextStyles.size24Medium.copyWith(height: 36 / 24),
),
11.verticalSpace,
GridView.builder(
itemCount:6,
shrinkWrap: true,
padding: EdgeInsets.zero,
physics: const NeverScrollableScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
mainAxisSpacing: 15,
crossAxisSpacing: 10,
mainAxisExtent: 140,
),
itemBuilder: (context, index) {
return WBrowseItem();
},
),
],
);
}
}

View File

@@ -0,0 +1,10 @@
import '../../../../../food_delivery_client.dart';
class SearchPage extends StatelessWidget {
const SearchPage({super.key});
@override
Widget build(BuildContext context) {
return WLayout(child: Scaffold());
}
}