category fetch static

This commit is contained in:
meylis98 2023-02-28 20:01:39 +05:00
parent 5bb32c3296
commit 8bc1d2c4d7
17 changed files with 191 additions and 685 deletions

View File

@ -1,37 +0,0 @@
import 'package:adaptix/adaptix.dart';
import 'package:flutter/material.dart';
import 'package:sapaly_shop/services/app_constants.dart';
import 'package:sapaly_shop/themes/app_theme.dart';
Widget customButton({
void Function()? tap,
bool? status = false,
String? text = 'Save',
String? statusText,
bool? isValid = false,
BuildContext? context,
}) {
return Container(
height: 48.adaptedPx(),
width: AppConstants.deviceWidth(context!),
margin: EdgeInsets.symmetric(
vertical: 15.adaptedPx(), horizontal: 10.adaptedPx()),
alignment: Alignment.center,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(8.adaptedPx()),
color: status == false
? AppTheme.lightPrimaryColor
: AppTheme.blackColor.withOpacity(0.3),
),
child: TextButton(
onPressed: status == true ? null : tap,
child: Text(
status == false ? text! : statusText!,
style: Theme.of(context).primaryTextTheme.bodyMedium?.copyWith(
fontSize: 18.adaptedPx(),
color: AppTheme.whiteColor,
),
),
),
);
}

View File

@ -1,41 +0,0 @@
import 'package:adaptix/adaptix.dart';
import 'package:flutter/material.dart';
import 'package:sapaly_shop/themes/app_theme.dart';
// void successMessage({String? message, BuildContext? context}) {
// ScaffoldMessenger.of(context!).showSnackBar(
// SnackBar(
// content: Text(
// message!,
// style: Theme.of(context).primaryTextTheme.bodyMedium,
// ),
// backgroundColor: AppTheme.blackColor,
// ),
// );
// }
// void errorMessage({String? message, BuildContext? context}) {
// ScaffoldMessenger.of(context!).showSnackBar(
// SnackBar(
// content: Text(
// message!,
// style: Theme.of(context).primaryTextTheme.bodyMedium,
// ),
// backgroundColor: AppTheme.redColor,
// ),
// );
// }
void showMessage({String? message, BuildContext? context}) {
ScaffoldMessenger.of(context!).showSnackBar(
SnackBar(
content: Text(
message!,
style: Theme.of(context).primaryTextTheme.bodyMedium?.copyWith(
fontSize: 16.adaptedPx(),
color: AppTheme.blackColor,
),
),
),
);
}

View File

@ -1,43 +0,0 @@
import 'package:adaptix/adaptix.dart';
import 'package:flutter/material.dart';
import 'package:sapaly_shop/themes/app_theme.dart';
Widget customTextField({
String? title,
String? hint,
TextEditingController? controller,
int? maxLines = 1,
BuildContext? context,
}) {
return Column(
children: [
Container(
alignment: Alignment.centerLeft,
child: Text(
title!,
style: Theme.of(context!).primaryTextTheme.bodyMedium?.copyWith(
fontWeight: FontWeight.w600,
color: AppTheme.blackColor,
),
),
),
TextFormField(
controller: controller,
maxLines: maxLines,
cursorColor: AppTheme.lightPrimaryColor,
decoration: InputDecoration(
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(15.adaptedPx()),
borderSide: const BorderSide(
color: AppTheme.lightPrimaryColor,
),
),
focusColor: AppTheme.lightPrimaryColor,
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
),
),
),
],
);
}

View File

@ -1,9 +1,6 @@
import 'package:adaptix/adaptix.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:sapaly_shop/onboard.dart';
import 'package:sapaly_shop/providers/auth_provider/auth_provider.dart';
import 'package:sapaly_shop/screens/auth/login.dart';
import 'package:sapaly_shop/screens/category/category_screen.dart';
import 'package:sapaly_shop/screens/dashboard/dashboard.dart';
import 'package:sapaly_shop/screens/drawer/sapaly_drawer.dart';
@ -23,7 +20,6 @@ Future<void> main() async {
MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => SettingsModel(prefs)),
ChangeNotifierProvider(create: (_) => AuthenticatonProvider()),
],
child: const MyApp(),
),
@ -41,13 +37,11 @@ class MyApp extends StatelessWidget {
debugShowCheckedModeBanner: false,
theme: AppTheme.appLightTheme,
title: 'Sapaly Mahabat',
initialRoute: '/login',
initialRoute: '/home',
routes: <String, WidgetBuilder>{
'/': (context) => const Dashboard(),
'/drawer': (context) => SapalyDrawer(),
'/onboard': (context) => const Onboard(),
'/home': (context) => const HomeScreen(),
'/login': (context) => const LoginScreen(),
'/category': (context) => const CategoryScreen(),
},
localizationsDelegates: AppConstants.localizationsDelegate,

View File

@ -5,13 +5,11 @@ class CategoryModel {
required this.id,
required this.name,
required this.translations,
required this.icon,
});
final int id;
final String name;
final List<Translation> translations;
final Iconca icon;
factory CategoryModel.fromJson(
Map<String, dynamic> json, String currentLang) {
@ -30,31 +28,10 @@ class CategoryModel {
translations: (json['translations'] as List)
.map((e) => Translation.fromJson(e))
.toList(),
icon: Iconca.fromJson(json["icon"] ?? ''),
);
}
}
class Iconca {
Iconca({
required this.id,
required this.path,
});
final int id;
final String path;
factory Iconca.fromJson(Map<String, dynamic> json) => Iconca(
id: json["id"] ?? 0,
path: json["path"],
);
Map<String, dynamic> toJson() => {
"id": id,
"path": path,
};
}
class Translation {
Translation({
required this.locale,

View File

@ -19,7 +19,7 @@ class ProductModel {
final String name;
final String slug;
final int categoryId;
final PreviewImage previewImage;
final PreviewImage? previewImage;
final List<Translation> translations;
final List<Offer> offer;
@ -38,7 +38,9 @@ class ProductModel {
name: language,
slug: json["slug"] ?? '',
categoryId: json["category_id"] ?? '',
previewImage: PreviewImage.fromJson(json["preview_image"] ?? ''),
previewImage: (json["preview_image"] != null)
? PreviewImage.fromJson(json["preview_image"])
: null,
translations: List<Translation>.from(
json["translations"].map((x) => Translation.fromJson(x))),
offer: List<Offer>.from(json["offer"].map((x) => Offer.fromJson(x))),
@ -50,7 +52,7 @@ class ProductModel {
"name": name,
"slug": slug,
"category_id": categoryId,
"preview_image": previewImage.toJson(),
"preview_image": previewImage!.toJson(),
"translations": List<dynamic>.from(translations.map((x) => x.toJson())),
};
}

View File

@ -1,36 +0,0 @@
import 'package:flutter/material.dart';
import 'package:sapaly_shop/screens/auth/login.dart';
class Onboard extends StatefulWidget {
const Onboard({super.key});
@override
State<Onboard> createState() => _OnboardState();
}
class _OnboardState extends State<Onboard> {
void navigate(BuildContext context) {
Future.delayed(const Duration(seconds: 3), () {
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(
builder: (context) => const LoginScreen(),
),
(route) => false);
});
}
@override
void initState() {
navigate(context);
super.initState();
}
@override
Widget build(BuildContext context) {
return const Scaffold(
body: Center(
child: Text('On Board'),
),
);
}
}

View File

@ -1,107 +0,0 @@
import 'dart:convert';
import 'dart:io';
import 'package:http/http.dart' as http;
import 'package:flutter/widgets.dart';
import 'package:sapaly_shop/services/app_constants.dart';
class AuthenticatonProvider extends ChangeNotifier {
// Base URL
final requestBaseUrl = kBaseUrl;
bool _isLoading = false;
String _resMessage = '';
// Getter
bool get isLoading => _isLoading;
String get resMeessage => _resMessage;
// for sign_up
void register({
required String email,
required String phoneNumber,
required String password,
required String repeatPassword,
BuildContext? context,
}) async {
_isLoading = true;
notifyListeners();
String url = '$requestBaseUrl/api/jwt/register';
final body = {
'email': email,
'phone': phoneNumber,
'password': password,
'password_confirmation': repeatPassword,
};
debugPrint('This is SIGNUP BODY ${body.toString()}');
try {
final req = await http.post(Uri.parse(url), body: json.encode(body));
if (req.statusCode == 200 || req.statusCode == 201) {
debugPrint('SIGNUP success ${req.body}');
} else {
final res = json.decode(req.body);
debugPrint('SIGNUP error ${res.body}');
_isLoading = false;
notifyListeners();
}
} on SocketException catch (error) {
_isLoading = false;
_resMessage = 'Internet connection is not available';
notifyListeners();
} catch (err) {
_isLoading = false;
_resMessage = 'Please try again';
notifyListeners();
debugPrint('::::: ${err.toString()}');
}
}
// for sign_in
void login({
required String email,
required String password,
BuildContext? context,
}) async {
_isLoading = true;
notifyListeners();
String url = '$requestBaseUrl/api/jwt/login';
final body = {
'email': email,
'password': password,
};
debugPrint('This is SIGNUP BODY ${body.toString()}');
try {
final req = await http.post(Uri.parse(url), body: json.encode(body));
if (req.statusCode == 200 || req.statusCode == 201) {
debugPrint('LOGIN success ${req.body}');
} else {
final res = json.decode(req.body);
debugPrint('LOGIN error ${res.body}');
_isLoading = false;
notifyListeners();
}
} on SocketException catch (error) {
_isLoading = false;
_resMessage = 'Internet connection is not available';
notifyListeners();
} catch (err) {
_isLoading = false;
_resMessage = 'Please try again';
notifyListeners();
debugPrint('::::: ${err.toString()}');
}
}
}

View File

@ -1,131 +0,0 @@
import 'package:adaptix/adaptix.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:sapaly_shop/components/custom_button.dart';
import 'package:sapaly_shop/components/snack_message.dart';
import 'package:sapaly_shop/components/text_field.dart';
import 'package:sapaly_shop/providers/auth_provider/auth_provider.dart';
import 'package:sapaly_shop/screens/auth/register.dart';
import 'package:sapaly_shop/services/app_constants.dart';
import 'package:sapaly_shop/themes/app_theme.dart';
import '../../services/page_navigator.dart';
class LoginScreen extends StatefulWidget {
const LoginScreen({super.key});
@override
State<LoginScreen> createState() => _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreen> {
final TextEditingController _email = TextEditingController();
final TextEditingController _password = TextEditingController();
@override
void dispose() {
_email.clear();
_password.clear();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Container(
margin: EdgeInsets.symmetric(
horizontal: AppConstants.horizontalPadding(context),
),
padding: EdgeInsets.symmetric(
horizontal: AppConstants.horizontalPadding(context),
),
height: AppConstants.deviceHeight(context) / (1.4),
width: double.infinity,
decoration: BoxDecoration(
border: Border.all(
width: 2.adaptedPx(),
color: AppTheme.blackColor.withOpacity(0.1),
),
borderRadius: BorderRadius.circular(15.adaptedPx()),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset('assets/images/sapalyLogo.png'),
SizedBox(width: 20.adaptedPx()),
Text(
AppConstants.kAppName,
style:
Theme.of(context).primaryTextTheme.bodyMedium?.copyWith(
color: AppTheme.blackColor,
fontWeight: FontWeight.w600,
fontSize: 20.adaptedPx(),
),
),
],
),
SizedBox(height: 20.adaptedPx()),
customTextField(
title: 'Email',
context: context,
hint: 'Enter your valid email address',
controller: _email,
),
SizedBox(height: 20.adaptedPx()),
customTextField(
title: 'Password',
context: context,
hint: 'Enter your secured password',
controller: _password,
),
SizedBox(height: 45.adaptedPx()),
Consumer<AuthenticatonProvider>(builder: (context, auth, child) {
return customButton(
text: 'Login',
tap: () {
if (_email.text.isEmpty || _password.text.isEmpty) {
showMessage(
context: context,
message: 'All fields are required',
);
} else {
auth.login(
email: _email.text.trim(),
password: _password.text.trim());
}
},
context: context,
statusText: 'Loggin in...',
status: auth.isLoading,
);
}),
Text(
'Or',
textAlign: TextAlign.center,
style: Theme.of(context).primaryTextTheme.bodyMedium?.copyWith(
color: AppTheme.blackColor,
fontSize: 18.adaptedPx(),
),
),
customButton(
text: 'Register',
tap: () {
PageNavigator(ctx: context).nextPage(
page: const RegisterScreen(),
);
},
context: context,
isValid: false,
status: false,
),
],
),
),
),
);
}
}

View File

@ -1,121 +0,0 @@
import 'package:adaptix/adaptix.dart';
import 'package:flutter/material.dart';
import 'package:sapaly_shop/components/custom_button.dart';
import 'package:sapaly_shop/components/text_field.dart';
import 'package:sapaly_shop/screens/auth/login.dart';
import 'package:sapaly_shop/services/app_constants.dart';
import 'package:sapaly_shop/themes/app_theme.dart';
import '../../services/page_navigator.dart';
class RegisterScreen extends StatefulWidget {
const RegisterScreen({super.key});
@override
State<RegisterScreen> createState() => _RegisterScreenState();
}
class _RegisterScreenState extends State<RegisterScreen> {
final TextEditingController _email = TextEditingController();
final TextEditingController _password = TextEditingController();
final TextEditingController _passwordConfirm = TextEditingController();
final TextEditingController _phone = TextEditingController();
@override
void dispose() {
_email.clear();
_password.clear();
_passwordConfirm.clear();
_phone.clear();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Container(
margin: EdgeInsets.symmetric(
horizontal: AppConstants.horizontalPadding(context),
),
padding: EdgeInsets.symmetric(
horizontal: AppConstants.horizontalPadding(context),
),
height: AppConstants.deviceHeight(context) / (1.13),
width: double.infinity,
decoration: BoxDecoration(
border: Border.all(
width: 2.adaptedPx(),
color: AppTheme.blackColor.withOpacity(0.1),
),
borderRadius: BorderRadius.circular(15.adaptedPx()),
),
child: ListView(
physics: const NeverScrollableScrollPhysics(),
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset('assets/images/sapalyLogo.png'),
SizedBox(width: 20.adaptedPx()),
Text(
AppConstants.kAppName,
style:
Theme.of(context).primaryTextTheme.bodyMedium?.copyWith(
color: AppTheme.blackColor,
fontWeight: FontWeight.w600,
fontSize: 20.adaptedPx(),
),
),
],
),
SizedBox(height: 20.adaptedPx()),
customTextField(
title: 'Your email',
context: context,
controller: _email,
hint: '',
),
SizedBox(height: 15.adaptedPx()),
customTextField(title: 'Phone number', context: context),
SizedBox(height: 15.adaptedPx()),
customTextField(title: 'Password', context: context),
SizedBox(height: 15.adaptedPx()),
customTextField(title: 'Password confirmation', context: context),
SizedBox(height: 15.adaptedPx()),
customButton(
text: 'Register',
context: context,
status: false,
statusText: 'Registering...',
),
Padding(
padding: EdgeInsets.symmetric(vertical: 15.adaptedPx()),
child: Text(
'Or',
textAlign: TextAlign.center,
style:
Theme.of(context).primaryTextTheme.bodyMedium?.copyWith(
color: AppTheme.blackColor,
fontSize: 18.adaptedPx(),
),
),
),
customButton(
text: 'Login',
context: context,
tap: () {
PageNavigator(ctx: context).nextPageOnly(
page: const LoginScreen(),
);
},
statusText: 'Loggin in...',
status: true,
),
],
),
),
),
);
}
}

View File

@ -2,7 +2,6 @@ import 'package:adaptix/adaptix.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:provider/provider.dart';
import 'package:sapaly_shop/components/sapaly_app_bar.dart';
import 'package:sapaly_shop/models/category_model.dart';
import 'package:sapaly_shop/models/settings_model.dart';
@ -91,17 +90,17 @@ class _CategoryScreenState extends State<CategoryScreen> {
),
child: Column(
children: [
Expanded(
flex: 3,
child: CachedNetworkImage(
imageUrl: categories[index].icon.path,
width: MediaQuery.of(context).size.width / 7,
fit: BoxFit.contain,
progressIndicatorBuilder:
(context, url, progress) => const Center(
child: CircularProgressIndicator()),
),
),
// Expanded(
// flex: 3,
// child: CachedNetworkImage(
// imageUrl: categories[index].icon.path,
// width: MediaQuery.of(context).size.width / 7,
// fit: BoxFit.contain,
// progressIndicatorBuilder:
// (context, url, progress) => const Center(
// child: CircularProgressIndicator()),
// ),
// ),
Expanded(
flex: 1,
child: Text(

View File

@ -2,8 +2,6 @@ import 'package:adaptix/adaptix.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:sapaly_shop/screens/auth/login.dart';
import 'package:sapaly_shop/screens/auth/register.dart';
import 'package:sapaly_shop/screens/category/category_screen.dart';
import 'package:url_launcher/url_launcher_string.dart';
@ -33,8 +31,8 @@ class SapalyDrawer extends StatelessWidget {
List<Widget> routes = [
const CategoryScreen(),
const LoginScreen(),
const RegisterScreen(),
Container(),
Container(),
Container(),
Container(),
Container(),

View File

@ -5,16 +5,14 @@ import 'package:carousel_slider/carousel_slider.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:sapaly_shop/models/product_model.dart';
import 'package:sapaly_shop/models/settings_model.dart';
import 'package:sapaly_shop/models/sliders_model.dart';
import 'package:sapaly_shop/screens/drawer/sapaly_drawer.dart';
import 'package:sapaly_shop/screens/details/details.dart';
import 'package:sapaly_shop/screens/home/product.dart';
import 'package:sapaly_shop/screens/home/search.dart';
import 'package:sapaly_shop/services/app_constants.dart';
import 'package:sapaly_shop/services/requests.dart';
import '../../components/product_card.dart';
import '../../components/sapaly_app_bar.dart';
import '../../models/category_model.dart';
import '../../themes/app_theme.dart';
@ -31,8 +29,7 @@ class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
int currentPage = 0;
int categoryId = 0;
bool hasError = false;
late TabController tabController;
List<ProductModel> products = [];
TabController? tabController;
List<CategoryModel> categories = [];
List<SlidersModel> sliders = [];
@ -59,7 +56,6 @@ class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
hasError = false;
});
}
tabController = TabController(length: categories.length, vsync: this);
} catch (e) {
setState(() {
@ -69,24 +65,11 @@ class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
}
}
Future<void> getProductsByCategory(int id) async {
try {
var list = await API().getProductsByCategory(id);
if (mounted) {
setState(() {
products = list;
});
}
} catch (e) {
debugPrint(e.toString());
}
}
@override
void initState() {
getSliders();
getCategories();
getProductsByCategory(categoryId);
super.initState();
}
@ -248,39 +231,24 @@ class _HomeScreenState extends State<HomeScreen> with TickerProviderStateMixin {
),
),
SizedBox(height: 15.adaptedPx()),
products.isEmpty && categories.isEmpty
? SizedBox(
height: AppConstants.deviceHeight(context) / 1.190,
child: const Center(child: CircularProgressIndicator()),
)
: SizedBox(
height: AppConstants.deviceHeight(context),
width: double.infinity,
child: TabBarView(
SizedBox(
height: AppConstants.deviceHeight(context),
width: double.infinity,
child: tabController != null
? TabBarView(
controller: tabController,
children: [
for (ProductModel product in products)
ProductCard(
imageUrl: product.previewImage.path,
price: '${product.offer.first.price}.M',
discountPrice: '${product.offer.first.oldPrice}.M',
description: product.offer.first.name,
discountPriceValue:
product.offer.first.discountPriceValue,
onPressed: () => Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => Details(
id: product.id,
image: product.previewImage.path,
price: '${product.offer.first.price}.M',
description: product.offer.first.name,
children: categories.isNotEmpty
? categories
.map(
(category) => Products(
id: category.id,
),
),
),
)
],
),
),
)
.toList()
: [],
)
: Container(),
),
],
),
),

View File

@ -1,48 +1,28 @@
import 'package:flutter/material.dart';
import 'package:sapaly_shop/models/category_model.dart';
import 'package:sapaly_shop/models/product_model.dart';
import '../../components/product_card.dart';
import '../../services/app_constants.dart';
import '../../services/requests.dart';
import '../details/details.dart';
class Products extends StatefulWidget {
const Products({
super.key,
required this.id,
required this.length,
required this.controller,
});
final int id, length;
final TabController controller;
const Products({super.key, required this.id});
final int id;
@override
State<Products> createState() => _ProductsState();
}
class _ProductsState extends State<Products> {
List<ProductModel> products = [];
List<CategoryModel> categories = [];
Future<void> getCategories() async {
try {
var data = await API().getCategories();
setState(() {
categories = data;
});
} catch (e) {
debugPrint('Category error ${e.toString()}');
}
}
Future<void> getProductsByCategory(int id) async {
try {
var list = await API().getProductsByCategory(id);
setState(() {
products = list;
});
debugPrint("THIS IS PRODUCTS $products");
if (mounted) {
setState(() {
products = list;
});
}
} catch (e) {
debugPrint(e.toString());
}
@ -50,8 +30,8 @@ class _ProductsState extends State<Products> {
@override
void initState() {
getCategories();
getProductsByCategory(widget.id);
print('category id :${widget.id}');
super.initState();
}
@ -59,44 +39,33 @@ class _ProductsState extends State<Products> {
Widget build(BuildContext context) {
return products == null
? const Center(child: CircularProgressIndicator())
: SizedBox(
height: AppConstants.deviceHeight(context),
width: double.infinity,
child: TabBarView(
controller: widget.controller,
children: [
for (CategoryModel category in categories)
GridView.builder(
shrinkWrap: true,
gridDelegate:
const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
),
itemCount: products.length,
itemBuilder: (context, index) {
return ProductCard(
imageUrl: products[index].previewImage.path,
price: '${products[index].offer.first.price}.M',
discountPrice:
'${products[index].offer.first.oldPrice}.M',
description: products[index].offer.first.name,
discountPriceValue:
products[index].offer.first.discountPriceValue,
onPressed: () => Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => Details(
id: products[index].id,
image: products[index].previewImage.path,
price: '${products[index].offer.first.price}.M',
description: products[index].offer.first.name,
),
),
),
);
},
),
],
: GridView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
),
itemCount: products.length,
itemBuilder: (context, index) {
return ProductCard(
imageUrl: products[index].previewImage?.path ?? '',
price: '${products[index].offer.first.price}.M',
discountPrice: '${products[index].offer.first.oldPrice}.M',
description: products[index].offer.first.name,
discountPriceValue:
products[index].offer.first.discountPriceValue,
onPressed: () => Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => Details(
id: products[index].id,
image: products[index].previewImage?.path ?? '',
price: '${products[index].offer.first.price}.M',
description: products[index].offer.first.name,
),
),
),
);
},
);
}
}

View File

@ -36,9 +36,12 @@ class API {
String currentLang = prefs.getString('language') ?? 'ru';
try {
final products = await _getData('v1/products/category/$id');
return (products['data']['data'] as List)
.map((e) => ProductModel.fromJson(e, currentLang))
.toList();
return products.containsKey('data')
? (products['data']['data'] as List)
.map((e) => ProductModel.fromJson(e, currentLang))
.toList()
: [].cast<ProductModel>();
} catch (e) {
debugPrint('product by categ ' + e.toString());
rethrow;
@ -55,11 +58,26 @@ class API {
}
}
Future<List<CategoryModel>> getSubCategories(int id) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
String currentLanguage = prefs.getString('language') ?? 'ru';
try {
final categories = await _getData("v1/category/sub/$id");
return (categories["data"] as List)
.map((item) => CategoryModel.fromJson(item, currentLanguage))
.toList();
} catch (e) {
debugPrint('Category ' + e.toString());
rethrow;
}
}
Future<List<CategoryModel>> getCategories() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
String currentLanguage = prefs.getString('language') ?? 'ru';
try {
final categories = await _getData("v1/categories");
final categories = await _getData("v1/category/sub/19");
return (categories["data"] as List)
.map((item) => CategoryModel.fromJson(item, currentLanguage))
.toList();
@ -80,4 +98,27 @@ class API {
rethrow;
}
}
static Future<bool> register(String email, String phone, String password,
String password_confirmation) async {
Map<String, String> requestHeaders = {'Content-Type': 'application/json'};
var url = Uri.http(kBaseUrl, 'jwt/register');
var response = await http.post(
url,
headers: requestHeaders,
body: jsonEncode({
'email': email,
'password': password,
'password_confirmation': password_confirmation,
'phone': phone,
}),
);
if (response.statusCode == 200) {
return true;
} else {
return false;
}
}
}

View File

@ -146,6 +146,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.1.1"
cross_file:
dependency: transitive
description:
name: cross_file
sha256: "0b0036e8cccbfbe0555fd83c1d31a6f30b77a96b598b35a5d36dd41f718695e9"
url: "https://pub.dev"
source: hosted
version: "0.3.3+4"
crypto:
dependency: transitive
description:
@ -260,6 +268,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.2.16"
flutter_plugin_android_lifecycle:
dependency: transitive
description:
name: flutter_plugin_android_lifecycle
sha256: "4bef634684b2c7f3468c77c766c831229af829a0cd2d4ee6c1b99558bd14e5d2"
url: "https://pub.dev"
source: hosted
version: "2.0.8"
flutter_svg:
dependency: "direct main"
description:
@ -318,6 +334,46 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.3.0"
image_picker:
dependency: transitive
description:
name: image_picker
sha256: "22207768556b82d55ec70166824350fee32298732d5efa4d6e756f848f51f66a"
url: "https://pub.dev"
source: hosted
version: "0.8.6+3"
image_picker_android:
dependency: transitive
description:
name: image_picker_android
sha256: "68d067baf7f6e401b1124ee83dd6967e67847314250fd68012aab34a69beb344"
url: "https://pub.dev"
source: hosted
version: "0.8.5+7"
image_picker_for_web:
dependency: transitive
description:
name: image_picker_for_web
sha256: "66fc6e3877bbde82c33d122f3588777c3784ac5bd7d1cdd79213ef7aecb85b34"
url: "https://pub.dev"
source: hosted
version: "2.1.11"
image_picker_ios:
dependency: transitive
description:
name: image_picker_ios
sha256: "39aa70b5f1e5e7c94585b9738632d5fdb764a5655e40cd9e7b95fbd2fc50c519"
url: "https://pub.dev"
source: hosted
version: "0.8.6+9"
image_picker_platform_interface:
dependency: transitive
description:
name: image_picker_platform_interface
sha256: "1991219d9dbc42a99aff77e663af8ca51ced592cd6685c9485e3458302d3d4f8"
url: "https://pub.dev"
source: hosted
version: "2.6.3"
intl:
dependency: "direct main"
description:
@ -526,6 +582,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "4.2.4"
progress_hud:
dependency: "direct main"
description:
name: progress_hud
sha256: c7a79d70d278328cf3b0732c119a89ba96329825deb03b5dd64415c77dfb8ac4
url: "https://pub.dev"
source: hosted
version: "1.1.0"
provider:
dependency: "direct main"
description:
@ -611,6 +675,14 @@ packages:
description: flutter
source: sdk
version: "0.0.99"
snippet_coder_utils:
dependency: "direct main"
description:
name: snippet_coder_utils
sha256: fb60b8a6b4cab3dddc17ce903cc073d2f5d42ebed676146dde0faba040dc4158
url: "https://pub.dev"
source: hosted
version: "1.0.13"
source_span:
dependency: transitive
description:

View File

@ -52,6 +52,8 @@ dependencies:
url_launcher: ^6.1.9
shared_preferences: ^2.0.17
provider: ^6.0.5
snippet_coder_utils: ^1.0.13
progress_hud: ^1.1.0
dev_dependencies:
flutter_test: