diff --git a/lib/api/products.dart b/lib/api/api.dart similarity index 56% rename from lib/api/products.dart rename to lib/api/api.dart index c9989d1..df3e0c0 100644 --- a/lib/api/products.dart +++ b/lib/api/api.dart @@ -5,4 +5,10 @@ Future getProducts() async { var req = await Dio().get(host + '/getproducts'); var res = req.data; return res; +} + +Future getProduct(id) async { + var req = await Dio().get(host + '/getproduct', queryParameters: {'id': id}); + var res = req.data; + return res; } \ No newline at end of file diff --git a/lib/components/product_box.dart b/lib/components/product_box.dart index b5d10a6..c92f97a 100644 --- a/lib/components/product_box.dart +++ b/lib/components/product_box.dart @@ -2,11 +2,12 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; class ProductBox extends StatefulWidget { - const ProductBox({Key? key, required this.imageUrl, required this.title}) + const ProductBox({Key? key, required this.imageUrl, required this.title, required this.callback}) : super(key: key); final String imageUrl; final String title; + final Function() callback; @override State createState() => _ProductBoxState(); @@ -23,7 +24,7 @@ class _ProductBoxState extends State { borderRadius: BorderRadius.circular(10), ), child: InkWell( - onTap: () {}, + onTap: () => widget.callback(), borderRadius: BorderRadius.circular(10), splashColor: const Color(0xff8B0000), highlightColor: const Color(0xff8B0000), diff --git a/lib/components/product_detail.dart b/lib/components/product_detail.dart new file mode 100644 index 0000000..4b90e8c --- /dev/null +++ b/lib/components/product_detail.dart @@ -0,0 +1,88 @@ +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/material.dart'; + +import 'package:nekoya_flutter/api/api.dart'; + +Widget makeDismissible({required context, required Widget child}) => GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () => Navigator.of(context).pop(), + child: GestureDetector( + onTap: () {}, + child: child, + ) +); + +Widget productDetail(context, id) { + return makeDismissible( + context: context, + child: DraggableScrollableSheet( + initialChildSize: 0.7, + minChildSize: 0.5, + maxChildSize: 1, + builder: (_, controller) => FutureBuilder ( + future: getProduct(id), + builder: (context, snapshot) { + if (snapshot.hasData) { + var data = snapshot.data; + return Container( + decoration: const BoxDecoration( + color: Color(0xff1b1c1e), + borderRadius: BorderRadius.vertical(top: Radius.circular(20)) + ), + padding: const EdgeInsets.all(16), + child: ListView( + controller: controller, + children: [ + CachedNetworkImage( + imageUrl: 'https://nekoya.moe.team/img/' + data[0]['IMAGE'], + placeholder: (context, url) => + const CircularProgressIndicator( + color: Color(0xff8B0000), + ), + errorWidget: (context, url, error) => Image.asset('assets/image-error.webp'), + fadeOutDuration: const Duration(milliseconds: 5), + imageBuilder: (context, imageProvider) => Container( + margin: const EdgeInsets.all(5.0), + width: 300, + height: 300, + decoration: BoxDecoration( + image: DecorationImage( + image: imageProvider, fit: BoxFit.cover)), + ), + ), + Text(data[0]['TITLE'], style: const TextStyle(color: Colors.white, fontSize: 30.0, fontWeight: FontWeight.w700),), + const SizedBox(height: 15.0), + Text(data[0]['DESCRIPTION'], style: const TextStyle(color: Colors.white, fontSize: 18.0),), + const SizedBox(height: 15.0), + Text('Price : ' + data[0]['PRICE'].toString(), style: const TextStyle(color: Colors.white, fontSize: 18.0, fontWeight: FontWeight.w500),), + Text('Stock : ' + data[0]['STOCK'].toString(), style: const TextStyle(color: Colors.white, fontSize: 18.0, fontWeight: FontWeight.w500),), + Text('Size : ' + data[0]['SIZE'], style: const TextStyle(color: Colors.white, fontSize: 18.0, fontWeight: FontWeight.w500),), + const SizedBox(height: 30.0), + ElevatedButton.icon( + onPressed: (){}, + icon: const Icon(Icons.add_shopping_cart), + label: const Text('Add to Cart', style: TextStyle(color: Colors.white, fontSize: 18.0),), + style: ButtonStyle( + backgroundColor: MaterialStateProperty.all(const Color(0xff8B0000)), + shape: MaterialStateProperty.all( + RoundedRectangleBorder( + borderRadius: BorderRadius.circular(18.0) + ) + ) + ) + ) + ], + ) + ); + } + + return const Center( + child: CircularProgressIndicator( + color: Color(0xff8B0000), + ), + ); + } + ) + ) + ); +} \ No newline at end of file diff --git a/lib/screens/products.dart b/lib/screens/products.dart index 50659f4..94f2ca7 100644 --- a/lib/screens/products.dart +++ b/lib/screens/products.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; -import 'package:nekoya_flutter/api/products.dart'; +import 'package:nekoya_flutter/api/api.dart'; import 'package:nekoya_flutter/components/product_box.dart'; +import 'package:nekoya_flutter/components/product_detail.dart'; class Products extends StatefulWidget { const Products({Key? key}) : super(key: key); @@ -30,7 +31,15 @@ class _ProductsState extends State { return ProductBox( imageUrl: 'https://nekoya.moe.team/img/' + data[index]['IMAGE'], - title: data[index]['TITLE'] + title: data[index]['TITLE'], + callback: () { + showModalBottomSheet( + isScrollControlled: true, + backgroundColor: Colors.transparent, + context: context, + builder: (context) => productDetail(context, data[index]['ID']), + ); + }, ); }), );