initial commit to gitea
This commit is contained in:
411
lib/widgets/mobile/create_online_store_1.dart
Normal file
411
lib/widgets/mobile/create_online_store_1.dart
Normal file
@@ -0,0 +1,411 @@
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '/models/group.dart';
|
||||
import '/pages/buy_service.dart';
|
||||
import '../../constants.dart';
|
||||
import '../../generated/l10n.dart';
|
||||
import '../../routes.dart';
|
||||
import '../../utils/http_util.dart';
|
||||
import '../../utils/utils.dart';
|
||||
|
||||
class CreateOnlineStore1 extends StatefulWidget {
|
||||
final int businessId;
|
||||
|
||||
const CreateOnlineStore1(this.businessId, {Key key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() {
|
||||
return CreateOnlineStore1State();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class CreateOnlineStore1State extends State<CreateOnlineStore1> {
|
||||
|
||||
TextEditingController groupNumberController = TextEditingController();
|
||||
|
||||
TextEditingController domainController = TextEditingController();
|
||||
|
||||
bool canSubmit = false;
|
||||
|
||||
List<dynamic> stores = [];
|
||||
Map<String, dynamic> service;
|
||||
dynamic selectedStore;
|
||||
|
||||
Group group;
|
||||
|
||||
String selectedDomain;
|
||||
List<dynamic> domainResult = [];
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Column col = Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [],
|
||||
);
|
||||
|
||||
col.children.add(
|
||||
Container(
|
||||
padding: EdgeInsets.only(top: 20, left: 16, right: 16, bottom: 10,),
|
||||
child: Text(
|
||||
S.of(context).open_online_store,
|
||||
style: TextStyle(
|
||||
fontSize: 28,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
col.children.add(
|
||||
Container(
|
||||
padding: EdgeInsets.only(top: 4, bottom: 4, left: 16.0, right: 16.0),
|
||||
child: Text(
|
||||
S.of(context)
|
||||
.select_a_store,
|
||||
style: TextStyle(
|
||||
color: Colors.black45,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
col.children.add(
|
||||
Container(
|
||||
padding: EdgeInsets.only(top: 4, bottom: 4, left: 16.0, right: 16.0),
|
||||
child: DropdownButton<dynamic>(
|
||||
items: stores.map((e) => DropdownMenuItem<dynamic>(
|
||||
value: e,
|
||||
child: Text(e['name']),
|
||||
)).toList(),
|
||||
isExpanded: false,
|
||||
hint: Text(S.of(context).select_a_store),
|
||||
onChanged: (newValue) {
|
||||
print('newValue $newValue');
|
||||
setState(() {
|
||||
selectedStore = newValue;
|
||||
});
|
||||
},
|
||||
value: selectedStore,
|
||||
),
|
||||
),
|
||||
);
|
||||
col.children.add(
|
||||
Container(
|
||||
padding: EdgeInsets.only(
|
||||
left: 16.0, right: 16.0, top: 20, bottom: 20),
|
||||
child: Visibility(
|
||||
child: getSearchDomainWidget(),
|
||||
visible: selectedStore != null,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
leading: IconButton(
|
||||
icon: Icon(Icons.arrow_back_ios),
|
||||
onPressed: (){
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
title: Text(S.of(context).open_online_store),
|
||||
backgroundColor: Theme.of(context).primaryColor,
|
||||
),
|
||||
body: SingleChildScrollView(
|
||||
child: col,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget getSearchDomainWidget() {
|
||||
if (selectedStore == null) {
|
||||
return SizedBox.shrink();
|
||||
}
|
||||
Column col = Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [],
|
||||
);
|
||||
col.children.add(
|
||||
Container(
|
||||
padding: EdgeInsets.only(bottom: 4,),
|
||||
child: Text(selectedStore == null ? '' : selectedStore['name'],
|
||||
style: TextStyle(
|
||||
fontSize: 28,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
Map<String, dynamic> existing_web_svc;
|
||||
if (selectedStore != null && (selectedStore['services'] as List).length > 0) {
|
||||
for (Map<String, dynamic>svc in (selectedStore['services'] as List)) {
|
||||
if (svc['code'] == Constants.WEB_MINISTORE_SERVICE) {
|
||||
existing_web_svc = svc;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (existing_web_svc != null) {
|
||||
col.children.add(
|
||||
Container(
|
||||
padding: EdgeInsets.only(top: 8.0),
|
||||
child: Text(
|
||||
'${existing_web_svc['description']}',
|
||||
),
|
||||
),
|
||||
);
|
||||
col.children.add(
|
||||
Container(
|
||||
padding: EdgeInsets.only(top: 4.0),
|
||||
child: Text(
|
||||
S.of(context).expiration_date + ": "
|
||||
+ Utils.utcDatetimeStringToLocalDatetimeString(context, existing_web_svc['expiration_date']),
|
||||
),
|
||||
),
|
||||
);
|
||||
col.children.add(
|
||||
Container(
|
||||
padding: EdgeInsets.only(top: 4.0),
|
||||
child: Text(
|
||||
S.of(context).store + ": " + '${existing_web_svc['store']['name']}'
|
||||
),
|
||||
),
|
||||
);
|
||||
col.children.add(
|
||||
Container(
|
||||
padding: EdgeInsets.only(top: 4.0),
|
||||
child: Text(
|
||||
S.of(context).domain_name + ": " + '${existing_web_svc['domain']}'
|
||||
),
|
||||
),
|
||||
);
|
||||
col.children.add(
|
||||
Container(
|
||||
padding: EdgeInsets.only(top: 10.0),
|
||||
child: ElevatedButton(
|
||||
child: Text(S.of(context).renew_service_now),
|
||||
onPressed: () {
|
||||
Navigator.pushReplacement(context, MaterialPageRoute(
|
||||
builder: (BuildContext context) =>
|
||||
BuyService(group.id, Constants.WEB_MINISTORE_SERVICE,
|
||||
domain: existing_web_svc['domain'],
|
||||
sid: existing_web_svc['store']['id'],
|
||||
),
|
||||
));
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
col.children.add(
|
||||
Container(
|
||||
padding: EdgeInsets.only(top: 8.0),
|
||||
child: Text(S.of(context).enter_desired_domain),
|
||||
),
|
||||
);
|
||||
col.children.add(
|
||||
Container(
|
||||
padding: EdgeInsets.only(top: 0,),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextFormField(
|
||||
controller: domainController,
|
||||
decoration: new InputDecoration(
|
||||
enabledBorder: UnderlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Colors.black12,
|
||||
),
|
||||
),
|
||||
focusedBorder: UnderlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Colors.blue,
|
||||
),
|
||||
),
|
||||
labelText: S.of(context).domains_separated_comma,
|
||||
),
|
||||
style: TextStyle(
|
||||
fontSize: 18.0
|
||||
),
|
||||
autofocus: true,
|
||||
validator: (String value) {
|
||||
if (value.trim().isEmpty) {
|
||||
return S.of(context).domains_separated_comma;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
onChanged: (string) {
|
||||
if (string.isNotEmpty) {
|
||||
canSubmit = true;
|
||||
} else {
|
||||
canSubmit = false;
|
||||
}
|
||||
setState(() {});
|
||||
},
|
||||
),
|
||||
),
|
||||
Container(
|
||||
padding: EdgeInsets.only(left: 8.0),
|
||||
child: ElevatedButton(
|
||||
child: Text(
|
||||
S.of(context).check_domain_name,
|
||||
),
|
||||
onPressed: domainController.text.length > 0 ? checkDomainAvailability : null,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
);
|
||||
if (domainResult.length > 0) {
|
||||
for (dynamic dr in domainResult) {
|
||||
col.children.add(_getDomain(dr));
|
||||
}
|
||||
}
|
||||
if (selectedDomain != null && service != null) {
|
||||
col.children.add(
|
||||
Container(
|
||||
padding: EdgeInsets.only(top: 8.0),
|
||||
child: Text(
|
||||
service['description'],
|
||||
),
|
||||
),
|
||||
);
|
||||
col.children.add(
|
||||
Container(
|
||||
padding: EdgeInsets.only(top: 8.0),
|
||||
child: Text(
|
||||
service['options'][0]['name'],
|
||||
),
|
||||
),
|
||||
);
|
||||
col.children.add(
|
||||
Container(
|
||||
padding: EdgeInsets.only(top: 8.0),
|
||||
child: Text(
|
||||
'\$${service['options'][0]['price']}',
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.orange,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
col.children.add(
|
||||
Container(
|
||||
padding: EdgeInsets.only(top: 10.0),
|
||||
child: ElevatedButton(
|
||||
child: Text(
|
||||
S.of(context).place_order_now,
|
||||
),
|
||||
onPressed: () {
|
||||
Navigator.pushReplacement(context, MaterialPageRoute(
|
||||
builder: (BuildContext context) =>
|
||||
BuyService(group.id, Constants.WEB_MINISTORE_SERVICE,
|
||||
domain: selectedDomain,
|
||||
sid: selectedStore['id'],
|
||||
),
|
||||
));
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
return Container(
|
||||
padding: EdgeInsets.only(bottom: 4,),
|
||||
child: col,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
HttpUtil.httpGet(
|
||||
'v1/get-contact-stores',
|
||||
queryParameters: {
|
||||
'service': Constants.WEB_MINISTORE_SERVICE
|
||||
}
|
||||
).then((value) {
|
||||
setState(() {
|
||||
stores = value['stores'];
|
||||
service = value['service'];
|
||||
group = Group.fromJson(value['group']);
|
||||
print('stores: ${value}');
|
||||
});
|
||||
}).onError((error, stackTrace) {
|
||||
Utils.showMessageDialog(context, error, onOk: () {
|
||||
Routes.router.navigateTo(context, '/');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> checkDomainAvailability() async {
|
||||
Utils.showLoadingDialog(context);
|
||||
selectedDomain = null;
|
||||
domainResult = [];
|
||||
setState(() {});
|
||||
HttpUtil.httpGet(
|
||||
'v1/check-domain-availability',
|
||||
queryParameters: {
|
||||
'domain': domainController.text,
|
||||
},
|
||||
).then((value) {
|
||||
Routes.router.pop(context);
|
||||
print('value: $value');
|
||||
if (value['status'] == 'OK') {
|
||||
domainResult = (value['domain_check_result'] as List);
|
||||
setState(() {});
|
||||
} else if (value['status'] == 'ERROR') {
|
||||
String errors = '';
|
||||
for (int i = 0; i < (value['errors'] as List).length; i++) {
|
||||
errors += value['errors'][i] + '\n';
|
||||
}
|
||||
Utils.showMessageDialog(context, errors);
|
||||
}
|
||||
}).onError((error, stackTrace) {
|
||||
Routes.router.pop(context);
|
||||
Utils.showMessageDialog(context, error);
|
||||
});
|
||||
}
|
||||
|
||||
Widget _getDomain(dynamic d) {
|
||||
if ((d['available'] as bool)) {
|
||||
return Container(
|
||||
child: ListTile(
|
||||
title: Text(
|
||||
d['domain'],
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
leading: Radio(
|
||||
value: d['domain'],
|
||||
groupValue: selectedDomain,
|
||||
onChanged: (val) {
|
||||
setState(() {
|
||||
selectedDomain = val;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return Container(
|
||||
padding: EdgeInsets.only(top: 1.0),
|
||||
child: ListTile(
|
||||
title: Text(
|
||||
d['domain'],
|
||||
style: TextStyle(
|
||||
color: Colors.black45,
|
||||
),
|
||||
),
|
||||
leading: Icon(Icons.clear, color: Colors.red,),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -52,6 +52,18 @@ class MobileBuyServiceState extends State<MobileBuyService> {
|
||||
Utils.buildLine(S.of(context).your_group, widget.data['group']['name'], valueSize: 16),
|
||||
);
|
||||
|
||||
if (widget.data['store']['id'] != null) {
|
||||
col1.children.add(
|
||||
Utils.buildLine(S.of(context).store, widget.data['store']['name'], valueSize: 16),
|
||||
);
|
||||
}
|
||||
|
||||
if (widget.data['domain'] != null) {
|
||||
col1.children.add(
|
||||
Utils.buildLine(S.of(context).domain_name, widget.data['domain'], valueSize: 16),
|
||||
);
|
||||
}
|
||||
|
||||
if (widget.data['exists_service'] == null) {
|
||||
col1.children.add(
|
||||
Utils.buildLine(S.of(context).current_plan, 'N/A', valueSize: 16),
|
||||
|
||||
@@ -335,6 +335,7 @@ class MobileCheckoutState extends State<MobileCheckout> with SingleTickerProvide
|
||||
check();
|
||||
},
|
||||
initialLabelIndex: deliveryMethodIndex,
|
||||
totalSwitches: shippingMethodLabels.length,
|
||||
);
|
||||
switch (position) {
|
||||
case 0:
|
||||
|
||||
@@ -189,6 +189,7 @@ class MobileNavigationDrawerState extends State<MobileNavigationDrawer> {
|
||||
TextLink(S.of(context).contact_us, '/contact-us', paddingVertical: 5.0, paddingHorizontal: 10.0, closeDrawer: true,),
|
||||
TextLink(S.of(context).about_us, '/about-us', paddingVertical: 5.0, paddingHorizontal: 10.0, closeDrawer: true,),
|
||||
TextLink(S.of(context).renew_license, '/renew-license', paddingVertical: 5.0, paddingHorizontal: 10.0, closeDrawer: true,),
|
||||
TextLink(S.of(context).create_a_online_store, '/contact-stores', paddingVertical: 5.0, paddingHorizontal: 10.0,),
|
||||
Container(
|
||||
margin: EdgeInsets.only(top: 20.0, bottom: 10.0),
|
||||
child: Text(
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
|
||||
import '../../constants.dart';
|
||||
import '../../utils/iframe_web.dart' if (dart.library.io) '../../utils/fake_iframe_web.dart';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||
|
||||
class MobileTutorials extends StatefulWidget {
|
||||
const MobileTutorials({Key key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() {
|
||||
return MobileTutorialsState();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class MobileTutorialsState extends State<MobileTutorials> {
|
||||
InAppWebViewController webView;
|
||||
String url = "";
|
||||
double progress = 0;
|
||||
bool isLoadStop = false;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (kIsWeb) {
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Expanded(
|
||||
child: IFrameWeb(
|
||||
width: double.maxFinite.toString(),
|
||||
height: double.maxFinite.toString(),
|
||||
src: Constants.TUTORIAL_URL,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
} else {
|
||||
print('progress: $progress');
|
||||
return Stack(
|
||||
children: [
|
||||
InAppWebView(
|
||||
initialUrlRequest: URLRequest(url: Uri.parse(Constants.TUTORIAL_URL)),
|
||||
initialOptions: InAppWebViewGroupOptions(
|
||||
crossPlatform: InAppWebViewOptions(
|
||||
|
||||
),
|
||||
),
|
||||
onWebViewCreated: (InAppWebViewController controller) {
|
||||
webView = controller;
|
||||
},
|
||||
onLoadStart: (controller, url) {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
this.url = url.toString();
|
||||
this.isLoadStop = false;
|
||||
});
|
||||
}
|
||||
},
|
||||
onLoadStop: (controller, url) async {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
this.url = url.toString();
|
||||
this.isLoadStop = true;
|
||||
});
|
||||
}
|
||||
},
|
||||
onProgressChanged: (InAppWebViewController controller, int progress) {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
if (this.progress < 1.0) {
|
||||
this.isLoadStop = false;
|
||||
} else {
|
||||
this.isLoadStop = true;
|
||||
}
|
||||
this.progress = progress / 100;
|
||||
});
|
||||
}
|
||||
},
|
||||
),
|
||||
isLoadStop ? Container() :
|
||||
Center(
|
||||
child: CircularProgressIndicator(),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -13,6 +13,8 @@ import '../../store/store.dart';
|
||||
import '../../utils/http_util.dart';
|
||||
import '../../utils/utils.dart';
|
||||
|
||||
import '../../utils/util_io.dart' if (dart.library.html) '../../utils/util_web.dart';
|
||||
|
||||
class MobileViewBlog extends StatefulWidget {
|
||||
final Key key;
|
||||
final int bid;
|
||||
@@ -126,11 +128,7 @@ class MobileViewBlogState extends State<MobileViewBlog> {
|
||||
Container(
|
||||
width: min(MediaQuery.of(context).size.width, MediaQuery.of(context).size.height) - 100.0,
|
||||
height: min(MediaQuery.of(context).size.width, MediaQuery.of(context).size.height) - 100.0,
|
||||
child: PhotoView(
|
||||
imageProvider: NetworkImage(
|
||||
'https:${blog.imageUrl}',
|
||||
),
|
||||
),
|
||||
child: Util.showImage('https:${blog.imageUrl}'),
|
||||
) : SizedBox.shrink(),
|
||||
decoration: BoxDecoration(
|
||||
border: Border(
|
||||
|
||||
261
lib/widgets/mobile/product_item.dart
Normal file
261
lib/widgets/mobile/product_item.dart
Normal file
@@ -0,0 +1,261 @@
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../constants.dart';
|
||||
import '../../events/eventbus.dart';
|
||||
import '../../events/events.dart';
|
||||
import '../../generated/l10n.dart';
|
||||
import '../../models/business.dart';
|
||||
import '../../models/product.dart';
|
||||
import '../../pages/product_detail_page.dart';
|
||||
import '../../utils/util_io.dart' if (dart.library.html) '../../utils/util_web.dart';
|
||||
import '../../widgets/general/add_remove_button.dart';
|
||||
import '../../widgets/general/show_price.dart';
|
||||
|
||||
class ProductItem extends StatefulWidget {
|
||||
final Business business;
|
||||
final Product product;
|
||||
final bool horizontal;
|
||||
final double imageWidth;
|
||||
|
||||
const ProductItem(this.product, this.business, {
|
||||
Key key,
|
||||
this.horizontal = false,
|
||||
this.imageWidth = 110,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => ProductItemState();
|
||||
|
||||
}
|
||||
|
||||
class ProductItemState extends State<ProductItem> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
// width: 160.0,
|
||||
height: widget.horizontal ? Constants.PRODUCT_ITEM_HEIGHT_H : Constants.PRODUCT_ITEM_HEIGHT_V,
|
||||
padding: new EdgeInsets.symmetric(horizontal: 10.0, vertical: 15.0).copyWith(bottom: 5.0),
|
||||
decoration: new BoxDecoration(
|
||||
color: Colors.white,
|
||||
border: new Border(
|
||||
bottom: new BorderSide(
|
||||
color: new Color(0xFFEBEBEB),
|
||||
),
|
||||
),
|
||||
),
|
||||
child: new SizedBox.expand(
|
||||
child: Container(
|
||||
padding: EdgeInsets.only(left: 10.0, right: 10.0, top: 10.0, bottom: 10.0),
|
||||
child: widget.horizontal ? getHorizontal(true) : getVertial(true),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget getHorizontal(bool onHover) {
|
||||
Row row1 = Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
margin: new EdgeInsets.all(10.0),
|
||||
width: widget.imageWidth,
|
||||
height: widget.imageWidth,
|
||||
child: GestureDetector(
|
||||
child: onHover && widget.product.secondImagePath.isNotEmpty ?
|
||||
Util.showImage('${widget.product.secondImagePath}',
|
||||
fit: BoxFit.fill,
|
||||
) :
|
||||
Util.showImage('${widget.product.imagePath}',
|
||||
fit: BoxFit.fill,
|
||||
),
|
||||
onTap: (){
|
||||
_showProductDetail();
|
||||
},
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Container(
|
||||
child: GestureDetector(
|
||||
child: Text(
|
||||
'${widget.product.name}',
|
||||
// overflow: kIsWeb ? null : TextOverflow.ellipsis,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
maxLines: 2,
|
||||
softWrap: true,
|
||||
style: new TextStyle(
|
||||
fontSize: 15.0,
|
||||
),
|
||||
),
|
||||
onTap: (){
|
||||
_showProductDetail();
|
||||
},
|
||||
),
|
||||
),
|
||||
Text(
|
||||
widget.product.description,
|
||||
// overflow: kIsWeb ? null : TextOverflow.ellipsis,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
maxLines: 2,
|
||||
style: new TextStyle(
|
||||
fontSize: 12.0,
|
||||
color: new Color(0xFF999999),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
row1,
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: <Widget>[
|
||||
new Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
new Container(
|
||||
child: widget.business.showMonthlySold ?
|
||||
Text(
|
||||
S.of(context).sold_per_month_token(widget.product.monthSales.toStringAsFixed(0)),
|
||||
style: new TextStyle(
|
||||
fontSize: 9.0
|
||||
),
|
||||
) : SizedBox.shrink(),
|
||||
),
|
||||
ShowPrice(
|
||||
widget.product.price,
|
||||
regularPrice: widget.product.regularPrice,
|
||||
currencySign: '\$',
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
],
|
||||
),
|
||||
AddRemoveButton(product: widget.product, business: widget.business, addOnly: false, onHovor: onHover,),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget getVertial(bool onHover) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
new Container(
|
||||
margin: new EdgeInsets.all(10.0),
|
||||
width: widget.imageWidth,
|
||||
height: widget.imageWidth,
|
||||
child: GestureDetector(
|
||||
child: onHover && widget.product.secondImagePath.isNotEmpty ?
|
||||
Util.showImage('${widget.product.secondImagePath}',
|
||||
fit: BoxFit.fill,
|
||||
) :
|
||||
Util.showImage('${widget.product.imagePath}',
|
||||
fit: BoxFit.fill,
|
||||
),
|
||||
onTap: (){
|
||||
_showProductDetail();
|
||||
},
|
||||
),
|
||||
),
|
||||
new Expanded(
|
||||
child: new Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Container(
|
||||
child: GestureDetector(
|
||||
child: Text(
|
||||
'${widget.product.name}',
|
||||
// overflow: kIsWeb ? null : TextOverflow.ellipsis,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
maxLines: 2,
|
||||
softWrap: true,
|
||||
style: new TextStyle(
|
||||
fontSize: 15.0,
|
||||
),
|
||||
),
|
||||
onTap: (){
|
||||
_showProductDetail();
|
||||
},
|
||||
),
|
||||
),
|
||||
Container(
|
||||
child: Text(
|
||||
widget.product.description,
|
||||
// overflow: kIsWeb ? null : TextOverflow.ellipsis,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
maxLines: 2,
|
||||
style: new TextStyle(
|
||||
fontSize: 12.0,
|
||||
color: new Color(0xFF999999),
|
||||
),
|
||||
),
|
||||
),
|
||||
new Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: <Widget>[
|
||||
new Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
new Container(
|
||||
child: widget.business.showMonthlySold ?
|
||||
Text(
|
||||
S.of(context).sold_per_month_token(widget.product.monthSales.toStringAsFixed(0)),
|
||||
style: new TextStyle(
|
||||
fontSize: 9.0
|
||||
),
|
||||
) : SizedBox.shrink(),
|
||||
),
|
||||
ShowPrice(
|
||||
widget.product.price,
|
||||
regularPrice: widget.product.regularPrice,
|
||||
currencySign: '\$',
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
],
|
||||
),
|
||||
AddRemoveButton(product: widget.product, business: widget.business, addOnly: false, onHovor: onHover,),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
void _showProductDetail() {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => ProductDetailPage(
|
||||
product: widget.product,
|
||||
business: widget.business,
|
||||
)),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
eventBus.on<OnCartInfoUpdated>().listen((event) {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
152
lib/widgets/mobile/product_search.dart
Normal file
152
lib/widgets/mobile/product_search.dart
Normal file
@@ -0,0 +1,152 @@
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flappy_search_bar/flappy_search_bar.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../events/eventbus.dart';
|
||||
import '../../events/events.dart';
|
||||
import '../../generated/l10n.dart';
|
||||
import '../../models/business.dart';
|
||||
import '../../models/product.dart';
|
||||
import '../../pages/product_detail_page.dart';
|
||||
import '../../utils/http_util.dart';
|
||||
import '../../utils/utils.dart';
|
||||
import '../../widgets/general/breadcrumbs.dart';
|
||||
import '../../widgets/general/navigationbar.dart';
|
||||
import 'product_item.dart';
|
||||
|
||||
class ProductSearch extends StatefulWidget {
|
||||
final Business business;
|
||||
|
||||
const ProductSearch(this.business, {Key key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => ProductSearchState();
|
||||
}
|
||||
|
||||
class ProductSearchState extends State<ProductSearch> {
|
||||
|
||||
int page = 1;
|
||||
int numPerPage = 10;
|
||||
int lastResultSize = 0;
|
||||
double lastBottomPosition = 0;
|
||||
String lastKeyword = '';
|
||||
|
||||
SearchBarController _controller = SearchBarController<Product>();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
||||
return Scaffold(
|
||||
appBar: MiniNavigationBar(
|
||||
title: S.of(context).search_product,
|
||||
back: true,
|
||||
breadCrumbs: [
|
||||
BreadCrumb(S.of(context).search_product, null),
|
||||
],
|
||||
),
|
||||
drawer: null,
|
||||
body: SafeArea(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||
child: NotificationListener<ScrollNotification>(
|
||||
child: SearchBar(
|
||||
searchBarController: _controller,
|
||||
minimumChars: 2,
|
||||
hintText: S.of(context).enter_keyword,
|
||||
cancellationWidget: Text(
|
||||
S.of(context).cancel,
|
||||
),
|
||||
onSearch: search,
|
||||
onItemFound: (Product searchProduct, int index) {
|
||||
return ProductItem(
|
||||
searchProduct,
|
||||
widget.business,
|
||||
horizontal: true,
|
||||
imageWidth: 80.0,
|
||||
);
|
||||
},
|
||||
onError: (error) {
|
||||
return Center(
|
||||
child: Text("$error"),
|
||||
);
|
||||
},
|
||||
emptyWidget: Center(
|
||||
child: Text(
|
||||
S.of(context).empty_result_change_keyword,
|
||||
),
|
||||
),
|
||||
),
|
||||
onNotification: (notification) {
|
||||
if (notification.metrics.atEdge) {
|
||||
print('fff: $page, $lastBottomPosition, ${notification.metrics.pixels}');
|
||||
if (page != 0 && lastResultSize >= numPerPage && notification.metrics.pixels != 0) {
|
||||
if (notification.metrics.pixels > lastBottomPosition) {
|
||||
lastBottomPosition = notification.metrics.pixels;
|
||||
page += 1;
|
||||
_controller.replayLastSearch();
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
bottomNavigationBar: null,
|
||||
);
|
||||
}
|
||||
|
||||
Future<List<Product>> search(String keyword) async {
|
||||
if (lastKeyword != keyword) {
|
||||
page = 1;
|
||||
}
|
||||
lastKeyword = keyword;
|
||||
var result = await HttpUtil.httpGet('v1/search-store-product2',
|
||||
queryParameters: {
|
||||
'store_id': widget.business.id,
|
||||
'keyword': keyword,
|
||||
'page': page,
|
||||
'num_per_page': numPerPage,
|
||||
},
|
||||
returnError: true,
|
||||
);
|
||||
if (result is DioError) {
|
||||
if (result.response != null) {
|
||||
throw RuntimeError(result.response.data);
|
||||
} else {
|
||||
throw RuntimeError(result.message);
|
||||
}
|
||||
} else if (result != null && result is List) {
|
||||
lastBottomPosition = 0;
|
||||
var r = result.map((e) => Product.fromJson(e)).toList();
|
||||
lastResultSize = r.length;
|
||||
if (lastResultSize < numPerPage) {
|
||||
page = 1;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
eventBus.on<OnCartInfoUpdated>().listen((event) {
|
||||
if (mounted) {
|
||||
setState(() {});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void _showProductDetail(Product p) {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => ProductDetailPage(
|
||||
product: p,
|
||||
business: widget.business,
|
||||
)),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,63 +1,59 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:badges/badges.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_spinkit/flutter_spinkit.dart';
|
||||
import 'package:flutter_wisetronic/events/eventbus.dart';
|
||||
import 'package:flutter_wisetronic/events/events.dart';
|
||||
import 'package:flutter_wisetronic/generated/l10n.dart';
|
||||
import 'package:flutter_wisetronic/models/business.dart';
|
||||
import 'package:flutter_wisetronic/models/cart_info.dart';
|
||||
import 'package:flutter_wisetronic/models/cart_line_item.dart';
|
||||
import 'package:flutter_wisetronic/models/category_products.dart';
|
||||
import 'package:flutter_wisetronic/models/comment.dart';
|
||||
import 'package:flutter_wisetronic/models/product.dart';
|
||||
import 'package:flutter_wisetronic/models/product_image.dart';
|
||||
import 'package:flutter_wisetronic/pages/product_detail_page.dart';
|
||||
import 'package:flutter_wisetronic/store/store.dart';
|
||||
import 'package:flutter_wisetronic/utils/http_util.dart';
|
||||
import 'package:flutter_wisetronic/utils/shop_scroll_controller.dart';
|
||||
import 'package:flutter_wisetronic/utils/shop_scroll_coordinator.dart';
|
||||
import 'package:flutter_wisetronic/utils/utils.dart';
|
||||
import 'package:flutter_wisetronic/widgets/general/add_remove_button.dart';
|
||||
import 'package:flutter_wisetronic/widgets/general/animation_point_manager.dart';
|
||||
import 'package:flutter_wisetronic/widgets/general/carousel.dart';
|
||||
import 'package:flutter_wisetronic/widgets/general/read_more_text.dart';
|
||||
import 'package:flutter_wisetronic/widgets/general/show_price.dart';
|
||||
import 'package:fluttertoast/fluttertoast.dart';
|
||||
import 'package:flutter_wisetronic/widgets/general/sliding_up_panel.dart';
|
||||
import 'package:pull_to_refresh/pull_to_refresh.dart';
|
||||
import 'package:smooth_star_rating/smooth_star_rating.dart';
|
||||
|
||||
import '../../constants.dart';
|
||||
import '../../events/eventbus.dart';
|
||||
import '../../events/events.dart';
|
||||
import '../../generated/l10n.dart';
|
||||
import '../../models/business.dart';
|
||||
import '../../models/cart_info.dart';
|
||||
import '../../models/cart_line_item.dart';
|
||||
import '../../models/category_products.dart';
|
||||
import '../../models/comment.dart';
|
||||
import '../../models/product.dart';
|
||||
import '../../models/product_image.dart';
|
||||
import '../../pages/product_detail_page.dart';
|
||||
import '../../pages/store_product_search.dart';
|
||||
import '../../routes.dart';
|
||||
import '../../store/actions.dart';
|
||||
import '../../store/store.dart';
|
||||
import '../../utils/http_util.dart';
|
||||
import '../../utils/shop_scroll_controller.dart';
|
||||
import '../../utils/shop_scroll_coordinator.dart';
|
||||
import '../../utils/util_web.dart'
|
||||
if (dart.library.io) '../../utils/util_io.dart';
|
||||
import '../../utils/utils.dart';
|
||||
import '../../widgets/general/add_remove_button.dart';
|
||||
import '../../widgets/general/animation_point_manager.dart';
|
||||
import '../../widgets/general/carousel.dart';
|
||||
import '../../widgets/general/product_item.dart';
|
||||
import '../../widgets/general/read_more_text.dart';
|
||||
import '../../widgets/general/sliding_up_panel.dart';
|
||||
import '../../widgets/general/style.dart';
|
||||
|
||||
import '../../utils/util_io.dart' if (dart.library.html) '../../utils/util_web.dart';
|
||||
import 'product_item.dart';
|
||||
import 'product_search.dart';
|
||||
import 'shopping_cart_bar.dart';
|
||||
|
||||
class MobileShop extends StatefulWidget {
|
||||
final int businessId;
|
||||
|
||||
const MobileShop({Key key, this.businessId}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => MobileShopState();
|
||||
}
|
||||
|
||||
MediaQueryData mediaQuery;
|
||||
double statusBarHeight;
|
||||
double screenWidth;
|
||||
double screenHeight;
|
||||
|
||||
class MobileShopState extends State<MobileShop>
|
||||
class Shop extends StatefulWidget {
|
||||
final int businessId;
|
||||
|
||||
const Shop({Key key, this.businessId}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => ShopState();
|
||||
}
|
||||
|
||||
class ShopState extends State<Shop>
|
||||
with TickerProviderStateMixin, AutomaticKeepAliveClientMixin {
|
||||
|
||||
GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
|
||||
|
||||
Business _business;
|
||||
@@ -75,7 +71,7 @@ class MobileShopState extends State<MobileShop>
|
||||
|
||||
static const num _categoryHeight = 50.0;
|
||||
static const num _categoryDescHeight = 50.0;
|
||||
static const num _productHeight = 115.0;
|
||||
static const num _productHeight = Constants.PRODUCT_ITEM_HEIGHT_H;
|
||||
|
||||
int _categoryIndex = 0;
|
||||
bool _categoryIndexChange = false;
|
||||
@@ -103,7 +99,7 @@ class MobileShopState extends State<MobileShop>
|
||||
int _commentPageCount = 1;
|
||||
bool _commentLoadingFinish = false;
|
||||
RefreshController _commentRefreshController =
|
||||
RefreshController(initialRefresh: true);
|
||||
RefreshController(initialRefresh: true);
|
||||
|
||||
PanelController panelController = PanelController();
|
||||
SlidingUpPanel _slidUpShoppingCart;
|
||||
@@ -256,9 +252,33 @@ class MobileShopState extends State<MobileShop>
|
||||
padding: EdgeInsets.only(
|
||||
left: 10.0,
|
||||
top: 10.0,
|
||||
right: 10.0,
|
||||
bottom: 10.0,
|
||||
),
|
||||
width: 150.0,
|
||||
margin: EdgeInsets.symmetric(horizontal: 5.0, vertical: 5.0),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.all(Radius.circular(5.0)),
|
||||
color: Colors.white,
|
||||
border: Border(
|
||||
top: BorderSide(
|
||||
width: 1.0,
|
||||
color: Colors.black12,
|
||||
),
|
||||
bottom: BorderSide(
|
||||
width: 1.0,
|
||||
color: Colors.black12,
|
||||
),
|
||||
left: BorderSide(
|
||||
width: 1.0,
|
||||
color: Colors.black12,
|
||||
),
|
||||
right: BorderSide(
|
||||
width: 1.0,
|
||||
color: Colors.black12,
|
||||
),
|
||||
),
|
||||
),
|
||||
width: 160.0,
|
||||
height: 220.0,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
@@ -267,6 +287,7 @@ class MobileShopState extends State<MobileShop>
|
||||
child: Container(
|
||||
child: Util.showImage(
|
||||
_business.promoProducts[i].imagePath,
|
||||
width: 110.0,
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
@@ -308,7 +329,7 @@ class MobileShopState extends State<MobileShop>
|
||||
pinned: false,
|
||||
floating: true,
|
||||
delegate: _SliverAppBarDelegate2(
|
||||
minHeight: 250.0,
|
||||
minHeight: 256.0,
|
||||
maxHeight: 260.0,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
@@ -359,7 +380,7 @@ class MobileShopState extends State<MobileShop>
|
||||
icon: Icon(Icons.arrow_back_ios),
|
||||
onPressed: () {
|
||||
if (_animationFinish) {
|
||||
Routes.router.pop(context);
|
||||
Navigator.of(context).maybePop();
|
||||
}
|
||||
}),
|
||||
titleSpacing: 0.0,
|
||||
@@ -371,8 +392,8 @@ class MobileShopState extends State<MobileShop>
|
||||
onTap: () {
|
||||
Navigator.push(context,
|
||||
MaterialPageRoute(builder: (BuildContext context) {
|
||||
return StoreProductSearch(_business);
|
||||
}));
|
||||
return ProductSearch(_business);
|
||||
}));
|
||||
},
|
||||
),
|
||||
),
|
||||
@@ -540,7 +561,7 @@ class MobileShopState extends State<MobileShop>
|
||||
cancelButton: CupertinoActionSheetAction(
|
||||
child: Text(S.of(context).close),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
Navigator.of(context).maybePop();
|
||||
},
|
||||
),
|
||||
);
|
||||
@@ -786,8 +807,8 @@ class MobileShopState extends State<MobileShop>
|
||||
));
|
||||
var duration = Duration(
|
||||
seconds: (_business.distanceInfo.duration != null
|
||||
? _business.distanceInfo.duration.value
|
||||
: 30) +
|
||||
? _business.distanceInfo.duration.value
|
||||
: 30) +
|
||||
_business.shippingTime * 60);
|
||||
var hours = duration.inHours.remainder(60);
|
||||
var minutes = duration.inMinutes.remainder(60);
|
||||
@@ -922,28 +943,28 @@ class MobileShopState extends State<MobileShop>
|
||||
children: <Widget>[
|
||||
_business.bulletin.isNotEmpty ? Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Container(
|
||||
children: <Widget>[
|
||||
Container(
|
||||
padding:
|
||||
EdgeInsets.only(left: 10.0, right: 5.0, bottom: 10.0),
|
||||
EdgeInsets.only(left: 10.0, right: 5.0, bottom: 10.0),
|
||||
child: Icon(
|
||||
Icons.announcement,
|
||||
size: 14.0,
|
||||
color: Colors.white,
|
||||
)),
|
||||
Container(
|
||||
width: mediaQuery.size.width - 30.0,
|
||||
padding: EdgeInsets.only(right: 10.0, bottom: 10.0),
|
||||
child: new Text(
|
||||
_business.bulletin.isEmpty ? '' : _business.bulletin,
|
||||
softWrap: true,
|
||||
style: new TextStyle(
|
||||
fontSize: 12.0, color: const Color(0xFFDDDDDD)),
|
||||
Container(
|
||||
width: mediaQuery.size.width - 30.0,
|
||||
padding: EdgeInsets.only(right: 10.0, bottom: 10.0),
|
||||
child: new Text(
|
||||
_business.bulletin.isEmpty ? '' : _business.bulletin,
|
||||
softWrap: true,
|
||||
style: new TextStyle(
|
||||
fontSize: 12.0, color: const Color(0xFFDDDDDD)),
|
||||
// overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
],
|
||||
) : SizedBox.shrink(),
|
||||
),
|
||||
],
|
||||
) : SizedBox.shrink(),
|
||||
_business.description.isNotEmpty ? Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@@ -1092,13 +1113,13 @@ class MobileShopState extends State<MobileShop>
|
||||
}
|
||||
|
||||
Widget _buildMainContent() {
|
||||
return new Row(
|
||||
return Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: <Widget>[
|
||||
_buildCategories(),
|
||||
Expanded(
|
||||
child: _buildProducts(),
|
||||
)
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
@@ -1116,7 +1137,7 @@ class MobileShopState extends State<MobileShop>
|
||||
CategoryProducts cp = _categoryProducts[i];
|
||||
int qtyInCategory = 0;
|
||||
CartInfo cartInfo =
|
||||
Utils.getCartInfoByBusiness(store.state.cartInfos, _business);
|
||||
Utils.getCartInfoByBusiness(store.state.cartInfos, _business);
|
||||
if (cartInfo != null &&
|
||||
cartInfo.businessInfo.id == _business.id &&
|
||||
cartInfo.productList != null) {
|
||||
@@ -1141,14 +1162,14 @@ class MobileShopState extends State<MobileShop>
|
||||
style: TextStyle(
|
||||
fontSize: 13.0,
|
||||
fontWeight: (cp.id == Constants.FEATURED_PRODUCT_ID ||
|
||||
cp.id == Constants.HOT_SALE_ID)
|
||||
cp.id == Constants.HOT_SALE_ID)
|
||||
? FontWeight.bold
|
||||
: FontWeight.normal,
|
||||
color: (cp.id == Constants.HOT_SALE_ID)
|
||||
? Colors.redAccent
|
||||
: ((cp.id == Constants.FEATURED_PRODUCT_ID)
|
||||
? Colors.lightGreen
|
||||
: Colors.black87)),
|
||||
? Colors.lightGreen
|
||||
: Colors.black87)),
|
||||
// overflow: kIsWeb ? null : TextOverflow.ellipsis,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
softWrap: true,
|
||||
@@ -1178,10 +1199,10 @@ class MobileShopState extends State<MobileShop>
|
||||
height: 70.0,
|
||||
padding: new EdgeInsets.symmetric(horizontal: 10.0),
|
||||
decoration: new BoxDecoration(
|
||||
color: _categoryIndex == i ? Style.backgroundColor : null,
|
||||
color: _categoryIndex == i ? Colors.white : null,
|
||||
border: new Border(
|
||||
bottom:
|
||||
new BorderSide(color: new Color(0xFFEBEBEB)))),
|
||||
new BorderSide(color: new Color(0xFFEBEBEB)))),
|
||||
child: categoryRow,
|
||||
),
|
||||
onTap: () => _selectCategory(i),
|
||||
@@ -1208,10 +1229,10 @@ class MobileShopState extends State<MobileShop>
|
||||
_categoryIndexChange = true;
|
||||
_listScrollController1
|
||||
.animateTo(height,
|
||||
duration: new Duration(
|
||||
microseconds: 200,
|
||||
),
|
||||
curve: Curves.linear)
|
||||
duration: new Duration(
|
||||
microseconds: 200,
|
||||
),
|
||||
curve: Curves.linear)
|
||||
.then((value) {
|
||||
_categoryIndexChange = false;
|
||||
});
|
||||
@@ -1316,7 +1337,7 @@ class MobileShopState extends State<MobileShop>
|
||||
controller: _listScrollController1,
|
||||
// itemCount: displayProductByCategoryClick ? 1 : (_categoryProducts == null ? 0 : _categoryProducts.length),
|
||||
itemCount:
|
||||
_categoryProducts == null ? 0 : numCategoriesHasProducts(),
|
||||
_categoryProducts == null ? 0 : numCategoriesHasProducts(),
|
||||
itemBuilder: (BuildContext context, int i) {
|
||||
CategoryProducts cp;
|
||||
cp = _categoryProducts[i];
|
||||
@@ -1357,42 +1378,42 @@ class MobileShopState extends State<MobileShop>
|
||||
children: <Widget>[
|
||||
new Expanded(
|
||||
child: new Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
textBaseline: TextBaseline.alphabetic,
|
||||
children: <Widget>[
|
||||
new Padding(
|
||||
padding: new EdgeInsets.only(right: 5.0),
|
||||
child: new Text(
|
||||
cp.name,
|
||||
style: new TextStyle(
|
||||
fontSize: 16.0,
|
||||
fontWeight:
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
textBaseline: TextBaseline.alphabetic,
|
||||
children: <Widget>[
|
||||
new Padding(
|
||||
padding: new EdgeInsets.only(right: 5.0),
|
||||
child: new Text(
|
||||
cp.name,
|
||||
style: new TextStyle(
|
||||
fontSize: 16.0,
|
||||
fontWeight:
|
||||
(cp.id == Constants.FEATURED_PRODUCT_ID ||
|
||||
cp.id == Constants.HOT_SALE_ID)
|
||||
cp.id == Constants.HOT_SALE_ID)
|
||||
? FontWeight.bold
|
||||
: FontWeight.normal,
|
||||
color: (cp.id == Constants.HOT_SALE_ID)
|
||||
? Colors.redAccent
|
||||
: ((cp.id ==
|
||||
Constants.FEATURED_PRODUCT_ID)
|
||||
color: (cp.id == Constants.HOT_SALE_ID)
|
||||
? Colors.redAccent
|
||||
: ((cp.id ==
|
||||
Constants.FEATURED_PRODUCT_ID)
|
||||
? Colors.lightGreen
|
||||
: Colors.black87)),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
new Visibility(
|
||||
visible: cp.description.isNotEmpty,
|
||||
child: new Text(
|
||||
cp.description,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: new TextStyle(
|
||||
fontSize: 10.0,
|
||||
color: new Color(0xFF999999)),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
replacement: const SizedBox.shrink()),
|
||||
],
|
||||
))
|
||||
new Visibility(
|
||||
visible: cp.description.isNotEmpty,
|
||||
child: new Text(
|
||||
cp.description,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: new TextStyle(
|
||||
fontSize: 10.0,
|
||||
color: new Color(0xFF999999)),
|
||||
),
|
||||
replacement: const SizedBox.shrink()),
|
||||
],
|
||||
))
|
||||
],
|
||||
)));
|
||||
for (var p in cp.products) {
|
||||
@@ -1400,9 +1421,13 @@ class MobileShopState extends State<MobileShop>
|
||||
children: <Widget>[],
|
||||
);
|
||||
|
||||
pStack.children.add(new ProductItem(
|
||||
product: p,
|
||||
business: _business,
|
||||
pStack.children.add(Container(
|
||||
// width: MediaQuery.of(context).size.width - 100.0,
|
||||
child: ProductItem(
|
||||
p, _business,
|
||||
horizontal: true,
|
||||
imageWidth: 80.0,
|
||||
),
|
||||
));
|
||||
|
||||
col.children.add(pStack);
|
||||
@@ -1494,129 +1519,6 @@ class MobileShopState extends State<MobileShop>
|
||||
}
|
||||
});
|
||||
|
||||
// onProductWillAddToCartSubscription =
|
||||
// eventBus.on<OnProductWillAddToCart>().listen((event) {
|
||||
// if (mounted) {
|
||||
// itemAddToCart(event.buttonKey);
|
||||
//
|
||||
// CartInfo cartInfo =
|
||||
// Utils.getCartInfoByBusiness(store.state.cartInfos, event.business);
|
||||
//
|
||||
// if (cartInfo == null || cartInfo.productList.length == 0) {
|
||||
// cartInfo = CartInfo();
|
||||
// cartInfo.id = 0;
|
||||
// cartInfo.amountPaid = 0.0;
|
||||
// cartInfo.businessInfo = event.business;
|
||||
// cartInfo.extraFeeList = [];
|
||||
// cartInfo.discountList = [];
|
||||
// CartLineItem lineItem = _newCartLineItem(
|
||||
// id: 0,
|
||||
// price: event.price,
|
||||
// product: event.product,
|
||||
// name: event.product.name,
|
||||
// description: event.description,
|
||||
// quantity: 1.0);
|
||||
// cartInfo.productList = [lineItem];
|
||||
// store.dispatch(new UpdateCartInfo(Utils.addCartInfoToCartInfoList(
|
||||
// store.state.cartInfos, cartInfo)));
|
||||
// eventBus.fire(new OnCartInfoUpdated());
|
||||
// } else {
|
||||
// if (event.product.productAttributes.length > 0) {
|
||||
// CartLineItem lineItem = _newCartLineItem(
|
||||
// id: 0,
|
||||
// price: event.price,
|
||||
// product: event.product,
|
||||
// name: event.product.name,
|
||||
// description: event.description,
|
||||
// quantity: 1.0);
|
||||
// cartInfo.productList.add(lineItem);
|
||||
// store.dispatch(new UpdateCartInfo(Utils.addCartInfoToCartInfoList(
|
||||
// store.state.cartInfos, cartInfo)));
|
||||
// eventBus.fire(new OnCartInfoUpdated());
|
||||
// } else {
|
||||
// int found = -1;
|
||||
// for (var i = 0; i < cartInfo.productList.length; i++) {
|
||||
// if (event.product.id == cartInfo.productList[i].product.id) {
|
||||
// found = i;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// if (found == -1) {
|
||||
// CartLineItem lineItem = _newCartLineItem(
|
||||
// id: 0,
|
||||
// price: event.price,
|
||||
// product: event.product,
|
||||
// name: event.product.name,
|
||||
// description: event.description,
|
||||
// quantity: 1.0);
|
||||
// cartInfo.productList.add(lineItem);
|
||||
// store.dispatch(new UpdateCartInfo(Utils.addCartInfoToCartInfoList(
|
||||
// store.state.cartInfos, cartInfo)));
|
||||
// eventBus.fire(new OnCartInfoUpdated());
|
||||
// } else {
|
||||
// if (cartInfo.productList[found].quantity + 1.0 >
|
||||
// event.product.leftNum) {
|
||||
// Fluttertoast.showToast(
|
||||
// msg: S.of(context).product_insufficient,
|
||||
// toastLength: Toast.LENGTH_SHORT,
|
||||
// gravity: ToastGravity.CENTER,
|
||||
// backgroundColor: Colors.red,
|
||||
// textColor: Colors.white);
|
||||
// } else {
|
||||
// cartInfo.productList[found].quantity += 1;
|
||||
// store.dispatch(new UpdateCartInfo(
|
||||
// Utils.addCartInfoToCartInfoList(
|
||||
// store.state.cartInfos, cartInfo)));
|
||||
// eventBus.fire(new OnCartInfoUpdated());
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// onProductWillRemoveFromCartSubscription =
|
||||
// eventBus.on<OnProductWillRemoveFromCart>().listen((event) {
|
||||
// if (mounted) {
|
||||
// CartInfo cartInfo =
|
||||
// Utils.getCartInfoByBusiness(store.state.cartInfos, event.business);
|
||||
// if (cartInfo != null) {
|
||||
// if (cartInfo.productList.length > 0) {
|
||||
// if (event.productListIndex != -1) {
|
||||
// if (cartInfo.productList[event.productListIndex].quantity <= 1) {
|
||||
// cartInfo.productList.removeAt(event.productListIndex);
|
||||
// } else {
|
||||
// cartInfo.productList[event.productListIndex].quantity -= 1;
|
||||
// }
|
||||
// } else {
|
||||
// int productListIndex = -1;
|
||||
// for (var i = 0; i < cartInfo.productList.length; i++) {
|
||||
// if (cartInfo.productList[i].product.id == event.product.id) {
|
||||
// productListIndex = i;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// if (productListIndex != -1) {
|
||||
// if (cartInfo.productList[productListIndex].quantity <= 1) {
|
||||
// cartInfo.productList.removeAt(productListIndex);
|
||||
// } else {
|
||||
// cartInfo.productList[productListIndex].quantity -= 1;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (cartInfo.productList.length <= 0) {
|
||||
// store.dispatch(UpdateCartInfo(Utils.removeCartInfoFromCartInfoList(
|
||||
// store.state.cartInfos, cartInfo)));
|
||||
// } else {
|
||||
// store.dispatch(UpdateCartInfo(Utils.addCartInfoToCartInfoList(
|
||||
// store.state.cartInfos, cartInfo)));
|
||||
// }
|
||||
// eventBus.fire(new OnCartInfoUpdated());
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
|
||||
loadProducts();
|
||||
}
|
||||
|
||||
@@ -1630,67 +1532,71 @@ class MobileShopState extends State<MobileShop>
|
||||
}
|
||||
_productCurrentPage = 1;
|
||||
Utils.loadProducts(
|
||||
widget.businessId, categoryId, _productCurrentPage, false,
|
||||
(value) {
|
||||
if (_isLoading) {
|
||||
_isLoading = false;
|
||||
Navigator.of(context).pop();
|
||||
widget.businessId, categoryId, _productCurrentPage, false,
|
||||
(value) {
|
||||
if (_isLoading) {
|
||||
_isLoading = false;
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
|
||||
displayProductByCategoryClick =
|
||||
value['display_product_by_category_click'];
|
||||
displayProductByCategoryClickIndicator = '';
|
||||
_business = Business.fromJson(value['business']);
|
||||
|
||||
_categoryProducts = (value['category_products'] as List)
|
||||
.map((i) => CategoryProducts.fromJson(i))
|
||||
.toList();
|
||||
// _featuredProducts = (value['featured_products'] as List)
|
||||
// .map((i) => Product.fromJson(i))
|
||||
// .toList();
|
||||
_featuredProducts = [];
|
||||
// _hotSaleProducts = (value['hot_sale_products'] as List)
|
||||
// .map((i) => Product.fromJson(i))
|
||||
// .toList();
|
||||
_hotSaleProducts = [];
|
||||
_prompts = value['prompt'] as List;
|
||||
|
||||
if (_hotSaleProducts.length > 0) {
|
||||
CategoryProducts hs = CategoryProducts(
|
||||
Constants.HOT_SALE_ID,
|
||||
widget.businessId,
|
||||
S.of(context).hot_sale,
|
||||
'',
|
||||
'',
|
||||
_hotSaleProducts);
|
||||
_categoryProducts.insert(0, hs);
|
||||
}
|
||||
|
||||
if (_featuredProducts.length > 0) {
|
||||
CategoryProducts fe = CategoryProducts(
|
||||
Constants.FEATURED_PRODUCT_ID,
|
||||
widget.businessId,
|
||||
S.of(context).featured_product,
|
||||
'',
|
||||
'',
|
||||
_featuredProducts);
|
||||
_categoryProducts.insert(0, fe);
|
||||
}
|
||||
|
||||
checkActionAndClose(context);
|
||||
|
||||
if (displayProductByCategoryClick) {
|
||||
_resetProductListScroll();
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
(error) {
|
||||
print('error: $error');
|
||||
if (_isLoading) {
|
||||
_isLoading = false;
|
||||
Navigator.of(context).maybePop();
|
||||
}
|
||||
Utils.showMessageDialog(context, error);
|
||||
}
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
displayProductByCategoryClick =
|
||||
value['display_product_by_category_click'];
|
||||
displayProductByCategoryClickIndicator = '';
|
||||
_business = Business.fromJson(value['business']);
|
||||
_categoryProducts = (value['category_products'] as List)
|
||||
.map((i) => CategoryProducts.fromJson(i))
|
||||
.toList();
|
||||
_featuredProducts = (value['featured_products'] as List)
|
||||
.map((i) => Product.fromJson(i))
|
||||
.toList();
|
||||
_hotSaleProducts = (value['hot_sale_products'] as List)
|
||||
.map((i) => Product.fromJson(i))
|
||||
.toList();
|
||||
_prompts = value['prompt'] as List;
|
||||
|
||||
if (_hotSaleProducts.length > 0) {
|
||||
CategoryProducts hs = CategoryProducts(
|
||||
Constants.HOT_SALE_ID,
|
||||
widget.businessId,
|
||||
S.of(context).hot_sale,
|
||||
'',
|
||||
'',
|
||||
_hotSaleProducts);
|
||||
_categoryProducts.insert(0, hs);
|
||||
}
|
||||
|
||||
if (_featuredProducts.length > 0) {
|
||||
CategoryProducts fe = CategoryProducts(
|
||||
Constants.FEATURED_PRODUCT_ID,
|
||||
widget.businessId,
|
||||
S.of(context).featured_product,
|
||||
'',
|
||||
'',
|
||||
_featuredProducts);
|
||||
_categoryProducts.insert(0, fe);
|
||||
}
|
||||
|
||||
checkActionAndClose(context);
|
||||
|
||||
if (displayProductByCategoryClick) {
|
||||
_resetProductListScroll();
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
(error) {
|
||||
print('error: $error');
|
||||
if (_isLoading) {
|
||||
_isLoading = false;
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
Utils.showMessageDialog(context, error);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1700,59 +1606,59 @@ class MobileShopState extends State<MobileShop>
|
||||
}
|
||||
_productCurrentPage += 1;
|
||||
Utils.loadProducts(widget.businessId, categoryId, _productCurrentPage, true,
|
||||
(value) {
|
||||
if (_isLoading) {
|
||||
_isLoading = false;
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
List<CategoryProducts> moreCategoryProducts =
|
||||
(value as List).map((i) => CategoryProducts.fromJson(i)).toList();
|
||||
if (moreCategoryProducts.isEmpty) {
|
||||
_productCurrentPage = 0;
|
||||
displayProductByCategoryClickIndicator =
|
||||
S.of(context).end_of_the_list;
|
||||
} else {
|
||||
if (moreCategoryProducts[0].products.length < Constants.ORDERS_PER_PAGE) {
|
||||
(value) {
|
||||
if (_isLoading) {
|
||||
_isLoading = false;
|
||||
Navigator.of(context).maybePop();
|
||||
}
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
List<CategoryProducts> moreCategoryProducts =
|
||||
(value as List).map((i) => CategoryProducts.fromJson(i)).toList();
|
||||
if (moreCategoryProducts.isEmpty) {
|
||||
_productCurrentPage = 0;
|
||||
displayProductByCategoryClickIndicator =
|
||||
S.of(context).end_of_the_list;
|
||||
} else {
|
||||
displayProductByCategoryClickIndicator =
|
||||
S.of(context).pull_up_to_load_more;
|
||||
if (moreCategoryProducts[0].products.length < Constants.ORDERS_PER_PAGE) {
|
||||
_productCurrentPage = 0;
|
||||
displayProductByCategoryClickIndicator =
|
||||
S.of(context).end_of_the_list;
|
||||
} else {
|
||||
displayProductByCategoryClickIndicator =
|
||||
S.of(context).pull_up_to_load_more;
|
||||
}
|
||||
CategoryProducts currentCp =
|
||||
getCategoryProductByCategoryId(categoryId);
|
||||
if (currentCp != null) {
|
||||
currentCp.products.addAll(moreCategoryProducts[0].products);
|
||||
} else {
|
||||
_productCurrentPage = 0;
|
||||
displayProductByCategoryClickIndicator =
|
||||
S.of(context).end_of_the_list;
|
||||
}
|
||||
}
|
||||
CategoryProducts currentCp =
|
||||
getCategoryProductByCategoryId(categoryId);
|
||||
if (currentCp != null) {
|
||||
currentCp.products.addAll(moreCategoryProducts[0].products);
|
||||
} else {
|
||||
_productCurrentPage = 0;
|
||||
displayProductByCategoryClickIndicator =
|
||||
S.of(context).end_of_the_list;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
(error) {
|
||||
print('error: $error');
|
||||
if (_isLoading) {
|
||||
_isLoading = false;
|
||||
Navigator.of(context).maybePop();
|
||||
}
|
||||
Utils.showMessageDialog(context, error);
|
||||
}
|
||||
},
|
||||
(error) {
|
||||
print('error: $error');
|
||||
if (_isLoading) {
|
||||
_isLoading = false;
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
Utils.showMessageDialog(context, error);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
CartLineItem _newCartLineItem(
|
||||
{int id,
|
||||
double price,
|
||||
Product product,
|
||||
String name,
|
||||
String description,
|
||||
double quantity}) {
|
||||
double price,
|
||||
Product product,
|
||||
String name,
|
||||
String description,
|
||||
double quantity}) {
|
||||
CartLineItem lineItem = CartLineItem();
|
||||
lineItem.unitPrice = price;
|
||||
lineItem.product = product;
|
||||
@@ -1787,9 +1693,9 @@ class MobileShopState extends State<MobileShop>
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => ProductDetailPage(
|
||||
product: p,
|
||||
business: _business,
|
||||
)),
|
||||
product: p,
|
||||
business: _business,
|
||||
)),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1925,10 +1831,10 @@ class MobileShopState extends State<MobileShop>
|
||||
S.of(context).store_closed,
|
||||
),
|
||||
actions: <Widget>[
|
||||
FlatButton(
|
||||
TextButton(
|
||||
child: Text(S.of(context).ok),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
Navigator.of(context).maybePop();
|
||||
showPrompt(0);
|
||||
},
|
||||
)
|
||||
@@ -1981,10 +1887,10 @@ class MobileShopState extends State<MobileShop>
|
||||
),
|
||||
),
|
||||
actions: <Widget>[
|
||||
FlatButton(
|
||||
TextButton(
|
||||
child: Text(S.of(context).ok),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
Navigator.of(context).maybePop();
|
||||
showPrompt(0);
|
||||
},
|
||||
)
|
||||
@@ -2007,10 +1913,10 @@ class MobileShopState extends State<MobileShop>
|
||||
title: Text(_prompt['title']),
|
||||
content: Text(_prompt['message']),
|
||||
actions: [
|
||||
FlatButton(
|
||||
TextButton(
|
||||
child: Text(S.of(context).ok),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
Navigator.of(context).maybePop();
|
||||
showPrompt(idx + 1);
|
||||
},
|
||||
),
|
||||
@@ -2053,4 +1959,4 @@ class _SliverAppBarDelegate2 extends SliverPersistentHeaderDelegate {
|
||||
minHeight != oldDelegate.minHeight ||
|
||||
child != oldDelegate.child;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user