Error provider

This commit is contained in:
2024-05-17 16:11:05 +03:00
parent c54176212a
commit 986a9d9bd5
7 changed files with 238 additions and 204 deletions

View File

@@ -1,8 +1,10 @@
import 'package:flutter/material.dart';
import 'package:gymlink_module_web/providers/main.dart';
import 'package:gymlink_module_web/states/web.dart';
import 'package:provider/provider.dart';
void main() {
runApp(const MyApp());
runApp(const MyAppWithProvider());
}
class MyApp extends StatefulWidget {
@@ -11,3 +13,13 @@ class MyApp extends StatefulWidget {
@override
State<MyApp> createState() => MyAppStateWeb();
}
class MyAppWithProvider extends StatelessWidget {
const MyAppWithProvider({super.key});
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (_) => GymLinkProvider(), child: const MyApp());
}
}

View File

@@ -4,6 +4,7 @@ import 'package:gymlink_module_web/components/basket_item_card.dart';
import 'package:gymlink_module_web/components/heading.dart';
import 'package:gymlink_module_web/pages/order_confirmation.dart';
import 'package:gymlink_module_web/providers/cart.dart';
import 'package:gymlink_module_web/providers/main.dart';
import 'package:gymlink_module_web/tools/prefs.dart';
import 'package:gymlink_module_web/tools/routes.dart';
import 'package:lazy_load_scrollview/lazy_load_scrollview.dart';
@@ -77,6 +78,7 @@ class _BasketPageState extends State<BasketPage> {
void _updateCart() {
Provider.of<CartProvider>(context, listen: false).updateCartLength();
Provider.of<GymLinkProvider>(context, listen: false).onTokenReceived('123');
}
void removeItem(String id) async {

View File

@@ -7,6 +7,7 @@ import 'package:gymlink_module_web/pages/basket.dart';
import 'package:gymlink_module_web/pages/detail.dart';
import 'package:gymlink_module_web/pages/order_history.dart';
import 'package:gymlink_module_web/providers/cart.dart';
import 'package:gymlink_module_web/providers/main.dart';
import 'package:gymlink_module_web/tools/prefs.dart';
import 'package:gymlink_module_web/tools/relative.dart';
import 'package:gymlink_module_web/tools/routes.dart';
@@ -54,11 +55,8 @@ const List<Map<String, String>> testData = [
];
class MainPage extends StatefulWidget {
final bool isLoading;
const MainPage({
super.key,
required this.isLoading,
});
@override
@@ -108,177 +106,170 @@ class _MainPageState extends State<MainPage> {
@override
Widget build(BuildContext context) {
final cartL = context.watch<CartProvider>().cartLength;
final onError = context.read<GymLinkProvider>().onError;
return Scaffold(
appBar: widget.isLoading ? null : const GymLinkAppBar(),
body: widget.isLoading
? const Center(child: CircularProgressIndicator())
: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Padding(
padding: const EdgeInsets.symmetric(horizontal: 5),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Expanded(
child: TextField(
onChanged: (value) => setState(() {
searchText = value;
}),
decoration: InputDecoration(
hintText: 'Поиск',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
),
suffixIcon: Padding(
padding: const EdgeInsets.only(right: 8),
child: ElevatedButton(
onPressed: _onSearch,
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(
vertical: 8,
horizontal: 0,
),
minimumSize:
const Size(50, kMinInteractiveDimension),
backgroundColor:
Theme.of(context).primaryColor,
shape: const CircleBorder(),
),
child: const Icon(
Icons.search,
color: Colors.white,
size: 24,
),
),
),
),
),
),
getSpacer(context: context, flex: 2),
const SizedBox(
width: 8,
),
ElevatedButton(
onPressed: () {
Navigator.of(context).push(CustomPageRoute(
builder: (context) => const HistoryPage(),
));
},
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.all(0),
minimumSize: const Size(50, kMinInteractiveDimension),
backgroundColor: Theme.of(context).primaryColor,
shape: const CircleBorder(
side: BorderSide(
color: Colors.black,
width: 1,
),
),
),
child: const Icon(
Icons.history,
color: Colors.white,
size: 24,
),
),
const SizedBox(
width: 10,
)
],
),
),
appBar: const GymLinkAppBar(),
body: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Padding(
padding: const EdgeInsets.symmetric(horizontal: 5),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Expanded(
child: LazyLoadScrollView(
onEndOfPage: _onLoad,
child: Stack(
children: [
GridView.builder(
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: min(
(MediaQuery.sizeOf(context).width ~/ 200)
.toInt(),
8),
child: TextField(
onChanged: (value) => setState(() {
searchText = value;
}),
decoration: InputDecoration(
hintText: 'Поиск',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
),
suffixIcon: Padding(
padding: const EdgeInsets.only(right: 8),
child: ElevatedButton(
onPressed: _onSearch,
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(
vertical: 8,
horizontal: 0,
),
minimumSize:
const Size(50, kMinInteractiveDimension),
backgroundColor: Theme.of(context).primaryColor,
shape: const CircleBorder(),
),
child: const Icon(
Icons.search,
color: Colors.white,
size: 24,
),
itemCount: filteredData.length,
itemBuilder: (context, index) {
final product = filteredData[index];
return ProductCard(
imagePath: Image(
image: Image.network(
'https://rus-sport.net/upload/iblock/311/topb85ez18pq0aavohpa5zipk2sbfxll.jpg')
.image,
width: 50,
),
name: product['name']!,
price: product['price']!,
onTap: () => Navigator.of(context).push(
CustomPageRoute(
builder: (context) => DetailPage(
name: product['name']!,
description: product['details']!,
price: product['price']!,
id: product['id']!,
image: Image(
image: AssetImage(
'assets/${product['image']!}'),
width: 300),
),
),
),
);
},
),
],
),
),
),
),
getSpacer(context: context, flex: 2),
const SizedBox(
width: 8,
),
ElevatedButton(
onPressed: () {
onError();
Navigator.of(context).push(CustomPageRoute(
builder: (context) => const HistoryPage(),
));
},
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.all(0),
minimumSize: const Size(50, kMinInteractiveDimension),
backgroundColor: Theme.of(context).primaryColor,
shape: const CircleBorder(
side: BorderSide(
color: Colors.black,
width: 1,
),
),
),
child: const Icon(
Icons.history,
color: Colors.white,
size: 24,
),
),
const SizedBox(
width: 10,
)
],
),
floatingActionButton: !widget.isLoading
? SizedBox(
height: 80,
width: 80,
child: FittedBox(
child: Stack(
children: [
FloatingActionButton(
onPressed: () =>
Navigator.of(context).push(CustomPageRoute(
builder: (context) => const BasketPage(),
)),
backgroundColor: Colors.transparent,
elevation: 0,
child: CircleAvatar(
radius: 25,
backgroundColor: Theme.of(context).primaryColor,
foregroundColor: Colors.white,
child: const Icon(Icons.shopping_cart_outlined)),
),
Expanded(
child: LazyLoadScrollView(
onEndOfPage: _onLoad,
child: Stack(
children: [
GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: min(
(MediaQuery.sizeOf(context).width ~/ 200).toInt(), 8),
),
cartL > 0
? Positioned(
right: -3,
bottom: 0,
child: Card(
color: Colors.red,
child: SizedBox(
width: 20,
child: Center(
child: Text(
cartL.toString(),
style: const TextStyle(color: Colors.white),
),
),
),
itemCount: filteredData.length,
itemBuilder: (context, index) {
final product = filteredData[index];
return ProductCard(
imagePath: Image(
image: Image.network(
'https://rus-sport.net/upload/iblock/311/topb85ez18pq0aavohpa5zipk2sbfxll.jpg')
.image,
width: 50,
),
name: product['name']!,
price: product['price']!,
onTap: () => Navigator.of(context).push(
CustomPageRoute(
builder: (context) => DetailPage(
name: product['name']!,
description: product['details']!,
price: product['price']!,
id: product['id']!,
image: Image(
image:
AssetImage('assets/${product['image']!}'),
width: 300),
),
)
: const SizedBox.shrink(),
],
),
),
),
);
},
),
],
),
)
: null,
),
),
],
),
floatingActionButton: SizedBox(
height: 80,
width: 80,
child: FittedBox(
child: Stack(
children: [
FloatingActionButton(
onPressed: () => Navigator.of(context).push(CustomPageRoute(
builder: (context) => const BasketPage(),
)),
backgroundColor: Colors.transparent,
elevation: 0,
child: CircleAvatar(
radius: 25,
backgroundColor: Theme.of(context).primaryColor,
foregroundColor: Colors.white,
child: const Icon(Icons.shopping_cart_outlined)),
),
cartL > 0
? Positioned(
right: -3,
bottom: 0,
child: Card(
color: Colors.red,
child: SizedBox(
width: 20,
child: Center(
child: Text(
cartL.toString(),
style: const TextStyle(color: Colors.white),
),
),
),
),
)
: const SizedBox.shrink(),
],
),
),
),
floatingActionButtonLocation: FloatingActionButtonLocation.startFloat,
);
}

View File

@@ -8,10 +8,17 @@ class GymLinkProvider with ChangeNotifier {
bool get blackTheme => _blackTheme;
ThemeData _theme = myTheme;
ThemeData get theme => _theme;
void Function() _onError = () => {};
void Function() get onError => _onError;
void onTokenReceived(String token) {
if (token == 'token123') {
_isLoading = false;
notifyListeners();
} else {
_isLoading = true;
notifyListeners();
}
}
@@ -25,4 +32,8 @@ class GymLinkProvider with ChangeNotifier {
_theme = theme;
notifyListeners();
}
void setOnError(void Function() onError) {
_onError = onError;
}
}

View File

@@ -14,12 +14,14 @@ class MyAppStateMobile extends State<MyApp> {
final isLoading = provider.isLoading;
return ChangeNotifierProvider(
create: (_) => CartProvider(),
builder: (context, __) => MaterialApp(
title: 'GymLink Module',
theme: theme,
debugShowCheckedModeBanner: false,
home: MainPage(isLoading: isLoading),
),
builder: (context, __) => isLoading
? const Center(child: CircularProgressIndicator())
: MaterialApp(
title: 'GymLink Module',
theme: theme,
debugShowCheckedModeBanner: false,
home: const MainPage(),
),
);
},
);

View File

@@ -6,13 +6,13 @@ import 'package:flutter/material.dart';
import 'package:gymlink_module_web/main.dart';
import 'package:gymlink_module_web/pages/main.dart';
import 'package:gymlink_module_web/providers/cart.dart';
import 'package:gymlink_module_web/providers/main.dart';
import 'package:gymlink_module_web/theme.dart';
import 'package:provider/provider.dart';
@js.JSExport()
class MyAppStateWeb extends State<MyApp> {
final _streamController = StreamController<void>.broadcast();
bool _isLoading = true;
ThemeData theme = myTheme;
bool black_theme = false;
@@ -32,31 +32,33 @@ class MyAppStateWeb extends State<MyApp> {
@override
Widget build(BuildContext context) {
final theme = context.watch<GymLinkProvider>().theme;
final isLoading = context.watch<GymLinkProvider>().isLoading;
return ChangeNotifierProvider(
create: (_) => CartProvider(),
child: MaterialApp(
title: 'GymLink Module',
theme: theme,
debugShowCheckedModeBanner: false,
home: MainPage(isLoading: _isLoading),
),
child: isLoading
? const Center(child: CircularProgressIndicator())
: MaterialApp(
title: 'GymLink Module',
theme: theme,
debugShowCheckedModeBanner: false,
home: const MainPage(),
),
);
}
@js.JSExport()
void onTokenReceived(String token) {
if (token == 'token123') {
setState(() {
_isLoading = false;
});
}
context.read<GymLinkProvider>().onTokenReceived(token);
}
@js.JSExport()
void changeColor(int color) {
setState(() {
black_theme = !black_theme; //FIXME: TEMPORARY
theme = getThemeData(Color(color), black_theme);
});
context.read<GymLinkProvider>().changeTheme(color);
}
@js.JSExport()
void setOnError(void Function() onError) {
context.read<GymLinkProvider>().setOnError(onError);
}
}

View File

@@ -1,31 +1,45 @@
(function(){
"use strict";
(function () {
'use strict';
window._stateSet = function () {
window._stateSet = function() {
console.log("Call _stateSet only once");
window._stateSet = function () {
console.log('Call _stateSet only once');
};
let appState = window._appState;
let btn = document.getElementById('token');
btn.addEventListener('click', function() {
btn.addEventListener('click', function () {
appState.onTokenReceived('token123');
})
});
let colorChangeBtnRed = document.getElementById('colorChangeBtnRed');
colorChangeBtnRed.addEventListener('click', function() {
var hexColor = '#FF0000'.replace(/^#?([a-f\d])([a-f\d])([a-f\d])$/i
, (m, r, g, b) => '#ff' + r + r + g + g + b + b).substring(1);
colorChangeBtnRed.addEventListener('click', function () {
var hexColor = '#FF0000'
.replace(
/^#?([a-f\d])([a-f\d])([a-f\d])$/i,
(m, r, g, b) => '#ff' + r + r + g + g + b + b
)
.substring(1);
var numColor = parseInt(hexColor, 16);
appState.changeColor(numColor)
})
appState.changeColor(numColor);
});
let colorChangeBtnBlue = document.getElementById('colorChangeBtnBlue');
colorChangeBtnBlue.addEventListener('click', function() {
var hexColor = '#0000FF'.replace(/^#?([a-f\d])([a-f\d])([a-f\d])$/i
, (m, r, g, b) => '#ff' + r + r + g + g + b + b).substring(1);
colorChangeBtnBlue.addEventListener('click', function () {
var hexColor = '#0000FF'
.replace(
/^#?([a-f\d])([a-f\d])([a-f\d])$/i,
(m, r, g, b) => '#ff' + r + r + g + g + b + b
)
.substring(1);
var numColor = parseInt(hexColor, 16);
appState.changeColor(numColor)
})
}
}());
appState.changeColor(numColor);
});
function onError() {
console.error('aboba');
}
appState.setOnError(onError);
};
})();