From 092d3dd21906b561a17629bc0877f621e0a8649b Mon Sep 17 00:00:00 2001 From: Fransolet Thomas Date: Thu, 8 Sep 2022 17:33:12 +0200 Subject: [PATCH] Visit page (wip) + language select --- .flutter-plugins-dependencies | 2 +- lib/Components/LanguageSelection.dart | 31 +++- lib/Components/SearchBox.dart | 39 +++++ lib/Models/visitContext.dart | 4 +- lib/Screens/Home/home.dart | 18 ++- lib/Screens/Visit/components/body.dart | 99 ++++++++++++ .../Visit/components/section_card.dart | 153 ++++++++++++++++++ .../Visit/details/components/body.dart | 81 ++++++++++ .../components/chat_and_add_to_cart.dart | 51 ++++++ .../Visit/details/components/color_dots.dart | 38 +++++ .../details/components/list_of_colors.dart | 32 ++++ .../details/components/product_image.dart | 42 +++++ lib/Screens/Visit/details/details_screen.dart | 47 ++++++ lib/Screens/Visit/product.dart | 35 ++++ lib/Screens/Visit/visit.dart | 24 +-- lib/constants.dart | 10 ++ 16 files changed, 677 insertions(+), 29 deletions(-) create mode 100644 lib/Components/SearchBox.dart create mode 100644 lib/Screens/Visit/components/body.dart create mode 100644 lib/Screens/Visit/components/section_card.dart create mode 100644 lib/Screens/Visit/details/components/body.dart create mode 100644 lib/Screens/Visit/details/components/chat_and_add_to_cart.dart create mode 100644 lib/Screens/Visit/details/components/color_dots.dart create mode 100644 lib/Screens/Visit/details/components/list_of_colors.dart create mode 100644 lib/Screens/Visit/details/components/product_image.dart create mode 100644 lib/Screens/Visit/details/details_screen.dart create mode 100644 lib/Screens/Visit/product.dart diff --git a/.flutter-plugins-dependencies b/.flutter-plugins-dependencies index 5cfbe18..a25e17c 100644 --- a/.flutter-plugins-dependencies +++ b/.flutter-plugins-dependencies @@ -1 +1 @@ -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"qr_code_scanner","path":"C:\\\\Users\\\\thoma\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dartlang.org\\\\qr_code_scanner-1.0.0\\\\","native_build":true,"dependencies":[]},{"name":"sqflite","path":"C:\\\\Users\\\\thoma\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-2.0.3+1\\\\","native_build":true,"dependencies":[]}],"android":[{"name":"qr_code_scanner","path":"C:\\\\Users\\\\thoma\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dartlang.org\\\\qr_code_scanner-1.0.0\\\\","native_build":true,"dependencies":[]},{"name":"sqflite","path":"C:\\\\Users\\\\thoma\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-2.0.3+1\\\\","native_build":true,"dependencies":[]}],"macos":[{"name":"sqflite","path":"C:\\\\Users\\\\thoma\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-2.0.3+1\\\\","native_build":true,"dependencies":[]}],"linux":[],"windows":[],"web":[]},"dependencyGraph":[{"name":"qr_code_scanner","dependencies":[]},{"name":"sqflite","dependencies":[]}],"date_created":"2022-09-03 17:27:02.945881","version":"3.0.3"} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"qr_code_scanner","path":"C:\\\\Users\\\\thoma\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dartlang.org\\\\qr_code_scanner-1.0.0\\\\","native_build":true,"dependencies":[]},{"name":"sqflite","path":"C:\\\\Users\\\\thoma\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-2.0.3+1\\\\","native_build":true,"dependencies":[]}],"android":[{"name":"qr_code_scanner","path":"C:\\\\Users\\\\thoma\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dartlang.org\\\\qr_code_scanner-1.0.0\\\\","native_build":true,"dependencies":[]},{"name":"sqflite","path":"C:\\\\Users\\\\thoma\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-2.0.3+1\\\\","native_build":true,"dependencies":[]}],"macos":[{"name":"sqflite","path":"C:\\\\Users\\\\thoma\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dartlang.org\\\\sqflite-2.0.3+1\\\\","native_build":true,"dependencies":[]}],"linux":[],"windows":[],"web":[]},"dependencyGraph":[{"name":"qr_code_scanner","dependencies":[]},{"name":"sqflite","dependencies":[]}],"date_created":"2022-09-08 17:31:19.765627","version":"3.0.3"} \ No newline at end of file diff --git a/lib/Components/LanguageSelection.dart b/lib/Components/LanguageSelection.dart index 3c78983..a711fde 100644 --- a/lib/Components/LanguageSelection.dart +++ b/lib/Components/LanguageSelection.dart @@ -4,6 +4,8 @@ import 'package:mymuseum_visitapp/app_context.dart'; import 'package:mymuseum_visitapp/constants.dart'; import 'package:provider/provider.dart'; +import '../Helpers/DatabaseHelper.dart'; + class LanguageSelection extends StatefulWidget { const LanguageSelection(); @@ -22,12 +24,16 @@ class _LanguageSelection extends State with TickerProviderSta Widget build(BuildContext context) { final appContext = Provider.of(context); Size size = MediaQuery.of(context).size; - print("YOLOO"); + var configurationLanguages = (appContext.getContext() as VisitAppContext).configuration?.languages; + print(configurationLanguages); + languagesEnable = configurationLanguages ?? languages; selectedLanguage = (appContext.getContext() as VisitAppContext).language; + + if(!languagesEnable!.any((lg) => lg == selectedLanguage)) { + print("selectedLanguage not supported"); + selectedLanguage = defaultLanguage; + } print(selectedLanguage); - languagesEnable = ["FR", "EN", "NL", "DE"]; // TODO - //languagesEnable = (appContext.getContext() as VisitAppContext).configuration!.languages; // Todo filter language possible - print(languagesEnable); return PopupMenuButton( icon: Container( @@ -53,15 +59,24 @@ class _LanguageSelection extends State with TickerProviderSta } return menuItems; }, - onSelected:(value){ - // TODO update App context + update local DB - if(value == 0){ + onSelected:(value) async { + // Update App context + update local DB + VisitAppContext visitAppContext = appContext.getContext(); + visitAppContext.language = languagesEnable![int.parse(value.toString())]; + appContext.setContext(visitAppContext); + + print(visitAppContext); + print("onSelectedonSelectedonSelected"); + + // Update local DB + await DatabaseHelper.instance.insert(DatabaseTableType.main, visitAppContext.toMap()); + /*if(value == 0){ print("My account menu is selected."); }else if(value == 1){ print("Settings menu is selected."); }else if(value == 2){ print("Logout menu is selected."); - } + }*/ } ); } diff --git a/lib/Components/SearchBox.dart b/lib/Components/SearchBox.dart new file mode 100644 index 0000000..8632ddd --- /dev/null +++ b/lib/Components/SearchBox.dart @@ -0,0 +1,39 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; + +import '../constants.dart'; + +class SearchBox extends StatelessWidget { + const SearchBox({ + Key? key, + this.onChanged, + }) : super(key: key); + + final ValueChanged? onChanged; + + @override + Widget build(BuildContext context) { + return Container( + margin: EdgeInsets.all(kDefaultPadding), + padding: EdgeInsets.symmetric( + horizontal: kDefaultPadding, + vertical: kDefaultPadding / 4, // 5 top and bottom + ), + decoration: BoxDecoration( + color: Colors.white.withOpacity(0.4), + borderRadius: BorderRadius.circular(12), + ), + child: TextField( + onChanged: onChanged, + style: TextStyle(color: Colors.white), + decoration: InputDecoration( + enabledBorder: InputBorder.none, + focusedBorder: InputBorder.none, + icon: const Icon(Icons.search, color: Colors.white), + hintText: 'Search', + hintStyle: TextStyle(color: Colors.white), + ), + ), + ); + } +} \ No newline at end of file diff --git a/lib/Models/visitContext.dart b/lib/Models/visitContext.dart index e63b475..d89adba 100644 --- a/lib/Models/visitContext.dart +++ b/lib/Models/visitContext.dart @@ -18,7 +18,7 @@ class VisitAppContext with ChangeNotifier{ 'id': id, //'host': host, 'language': language, - 'configuration': configuration == null ? null : jsonEncode(configuration?.toJson()), + //'configuration': configuration == null ? null : jsonEncode(configuration?.toJson()), }; } @@ -27,7 +27,7 @@ class VisitAppContext with ChangeNotifier{ id: json['id'] as String, /*host: json['host'] as String,*/ language: json['language'] as String, - configuration: json['configuration'] == null ? null : ConfigurationDTO.fromJson(json['configuration']), + configuration: json['configuration'] == null ? null : ConfigurationDTO.fromJson(json['configuration']), ); } diff --git a/lib/Screens/Home/home.dart b/lib/Screens/Home/home.dart index 3934543..f61cd80 100644 --- a/lib/Screens/Home/home.dart +++ b/lib/Screens/Home/home.dart @@ -11,6 +11,7 @@ import 'package:mymuseum_visitapp/Components/ScannerBouton.dart'; import 'package:mymuseum_visitapp/Helpers/DatabaseHelper.dart'; import 'package:mymuseum_visitapp/Helpers/networkCheck.dart'; import 'package:mymuseum_visitapp/Models/resourceModel.dart'; +import 'package:mymuseum_visitapp/Models/visitContext.dart'; import 'package:mymuseum_visitapp/Screens/Visit/visit.dart'; import 'package:mymuseum_visitapp/app_context.dart'; import 'package:mymuseum_visitapp/client.dart'; @@ -25,8 +26,8 @@ class HomePage extends StatefulWidget { } class _HomePageState extends State { - //List configurations = [ConfigurationDTO(label: "Test 0", isOffline: false), ConfigurationDTO(label: "Test 1", isOffline: true), ConfigurationDTO(label: "Test 2", isOffline: true)]; List configurations = []; + List alreadyDownloaded = []; @override Widget build(BuildContext context) { @@ -60,6 +61,10 @@ class _HomePageState extends State { onTap: () { setState(() { print(configurations[index].label); + // Update context + VisitAppContext visitAppContext = appContext.getContext(); + visitAppContext.configuration = configurations[index]; + appContext.setContext(visitAppContext); Navigator.of(context).pushReplacement(MaterialPageRoute( builder: (context) => VisitPage(configurationId: configurations[index].id!), @@ -83,7 +88,7 @@ class _HomePageState extends State { ), ), ), - if(configurations[index].isOffline!) // TODO check if already downloaded + if(configurations[index].isOffline! && !alreadyDownloaded.any((c) => c == configurations[index].id)) Positioned( bottom: 0, right: 0, @@ -140,15 +145,14 @@ class _HomePageState extends State { try { List? configurations; bool isOnline = await hasNetwork(); + configurations = List.from(await DatabaseHelper.instance.getData(DatabaseTableType.configurations)); + alreadyDownloaded = configurations.map((c) => c.id).toList(); + if(isOnline) { //var client = new Client("http://192.168.31.140:8089"); // TODO REMOVE configurations = await client.configurationApi!.configurationGet(); - return configurations ?? []; } else { - print("Search in local DB as we don't have internet connection"); - configurations = List.from(await DatabaseHelper.instance.getData(DatabaseTableType.configurations)); - print("RESULT AAH"); return configurations ?? []; // TODO return local list.. } } catch (e) { @@ -220,8 +224,6 @@ class _HomePageState extends State { // Update local DB - Configuration await DatabaseHelper.instance.insert(DatabaseTableType.configurations, configuration.toJson()); - //var teeest = await DatabaseHelper.instance.getData(DatabaseTableType.configurations); - List? sections = await getAllSections(appContext.clientAPI, configuration.id!); if(sections!.isNotEmpty) { diff --git a/lib/Screens/Visit/components/body.dart b/lib/Screens/Visit/components/body.dart new file mode 100644 index 0000000..05c1e01 --- /dev/null +++ b/lib/Screens/Visit/components/body.dart @@ -0,0 +1,99 @@ +import 'package:flutter/material.dart'; +import 'package:manager_api/api.dart'; +import 'package:mymuseum_visitapp/Components/Loading.dart'; +import 'package:mymuseum_visitapp/Components/SearchBox.dart'; +import 'package:mymuseum_visitapp/Helpers/DatabaseHelper.dart'; +import 'package:mymuseum_visitapp/Models/visitContext.dart'; +import 'package:mymuseum_visitapp/Screens/Visit/details/details_screen.dart'; +import 'package:mymuseum_visitapp/Screens/Visit/product.dart'; +import 'package:mymuseum_visitapp/app_context.dart'; +import 'package:mymuseum_visitapp/constants.dart'; +import 'package:provider/provider.dart'; + +import 'section_card.dart'; + +class Body extends StatefulWidget { + const Body({Key? key, required this.configurationId}) : super(key: key); + + final String? configurationId; + + @override + State createState() => _BodyState(); +} + +class _BodyState extends State { + List sections = []; + + @override + Widget build(BuildContext context) { + final appContext = Provider.of(context); + Size size = MediaQuery.of(context).size; + + return SafeArea( + bottom: false, + child: Column( + children: [ + SearchBox(onChanged: (value) {}), + const SizedBox(height: kDefaultPadding / 2), + Expanded( + child: Stack( + children: [ + // Our background + Container( + margin: const EdgeInsets.only(top: 70), + decoration: const BoxDecoration( + color: kBackgroundColor, + borderRadius: BorderRadius.only( + topLeft: Radius.circular(40), + topRight: Radius.circular(40), + ), + ), + ), + FutureBuilder( + future: getSections(), + builder: (context, AsyncSnapshot snapshot) { + if (snapshot.connectionState == ConnectionState.done) { + return ListView.builder( + itemCount: sections.length, + itemBuilder: (context, index) => SectionCard( + itemIndex: index, + sectionDTO: sections[index], + press: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => DetailsScreen( + product: products[index], + ), + ), + ); + }, + ), + ); + } else if (snapshot.connectionState == ConnectionState.none) { + return Text("No data"); + } else { + return Center( + child: Container( + height: size.height * 0.15, + child: Loading() + ) + ); + } + } + ) + ], + ), + ), + ], + ), + ); + } + + getSections() async { + sections = List.from(await DatabaseHelper.instance.getData(DatabaseTableType.sections)); + sections = sections.where((s) => s.configurationId == widget.configurationId).toList(); + sections.sort((a,b) => a.order!.compareTo(b.order!)); + print(sections); + } +} diff --git a/lib/Screens/Visit/components/section_card.dart b/lib/Screens/Visit/components/section_card.dart new file mode 100644 index 0000000..a8add2d --- /dev/null +++ b/lib/Screens/Visit/components/section_card.dart @@ -0,0 +1,153 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:manager_api/api.dart'; +import 'package:mymuseum_visitapp/Components/Loading.dart'; +import 'package:mymuseum_visitapp/Helpers/DatabaseHelper.dart'; +import 'package:mymuseum_visitapp/Helpers/translationHelper.dart'; +import 'package:mymuseum_visitapp/Models/resourceModel.dart'; +import 'package:mymuseum_visitapp/app_context.dart'; +import 'package:mymuseum_visitapp/constants.dart'; +import 'package:provider/provider.dart'; + +class SectionCard extends StatelessWidget { + const SectionCard({ + Key? key, + required this.itemIndex, + required this.sectionDTO, + required this.press, + }) : super(key: key); + + final int itemIndex; + final SectionDTO sectionDTO; + final void Function()? press; + + @override + Widget build(BuildContext context) { + // It will provide us total height and width of our screen + Size size = MediaQuery.of(context).size; + final appContext = Provider.of(context); + ResourceModel? resourceModel; + + getResource(String? imageId) async { + await DatabaseHelper.instance.queryWithId(DatabaseTableType.resources, sectionDTO!.imageId!).then((value) { + resourceModel = DatabaseHelper.instance.getResourceFromDB(value.first); + }); + } + + return Container( + margin: const EdgeInsets.symmetric( + horizontal: kDefaultPadding, + vertical: kDefaultPadding / 2, + ), + // color: Colors.blueAccent, + height: 160, + child: InkWell( + onTap: press, + child: Stack( + alignment: Alignment.bottomCenter, + children: [ + // Those are our background + Container( + height: 136, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(22), + color: itemIndex.isEven ? kTestSecondColor : kSecondRed, + boxShadow: [kDefaultShadow], + ), + child: Container( + margin: EdgeInsets.only(right: 10), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(22), + ), + ), + ), + // our product image + Positioned( + top: 0, + right: 0, + child: Hero( + tag: '${sectionDTO.id}', + child: Container( + padding: EdgeInsets.symmetric(horizontal: kDefaultPadding), + height: 160, + // image is square but we add extra 20 + 20 padding thats why width is 200 + width: 200, + child: FutureBuilder( + future: getResource(sectionDTO.imageId), + builder: (context, AsyncSnapshot snapshot) { + if (snapshot.connectionState == ConnectionState.done) { + return resourceModel != null ? Image.memory( + base64Decode(resourceModel!.data!), + fit: BoxFit.cover + ) : Text(""); + } else if (snapshot.connectionState == ConnectionState.none) { + return Text("No data"); + } else { + return Center( + child: Container( + height: size.height * 0.15, + child: Loading() + ) + ); + } + } + )/*Image.asset( + section.image, + fit: BoxFit.cover, + ),*/ + ), + ), + ), + // Product title and price + Positioned( + bottom: 0, + left: 0, + child: SizedBox( + height: 136, + // our image take 200 width, thats why we set out total width - 200 + width: size.width - 200, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Spacer(), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: kDefaultPadding), + child: Text( + sectionDTO != null ? TranslationHelper.get(sectionDTO!.title, appContext) : "", + style: Theme.of(context).textTheme.button, + ), + ), + // it use the available space + Spacer(), + Container( + padding: EdgeInsets.symmetric( + horizontal: kDefaultPadding * 1.5, // 30 padding + vertical: kDefaultPadding / 4, // 5 top and bottom + ), + decoration: BoxDecoration( + color: kSecondRed, + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular(22), + topRight: Radius.circular(22), + ), + ), + child: Text( + "${sectionDTO.order!+1}", + style: Theme.of(context).textTheme.button, + ), + ), + ], + ), + ), + ), + ], + ), + ), + ); + } + + +} diff --git a/lib/Screens/Visit/details/components/body.dart b/lib/Screens/Visit/details/components/body.dart new file mode 100644 index 0000000..d7c2547 --- /dev/null +++ b/lib/Screens/Visit/details/components/body.dart @@ -0,0 +1,81 @@ +import 'package:flutter/material.dart'; +import 'package:mymuseum_visitapp/Screens/Visit/product.dart'; +import 'package:mymuseum_visitapp/constants.dart'; + +import 'chat_and_add_to_cart.dart'; +import 'list_of_colors.dart'; +import 'product_image.dart'; + +class Body extends StatelessWidget { + final Product product; + + const Body({Key? key, required this.product}) : super(key: key); + @override + Widget build(BuildContext context) { + // it provide us total height and width + Size size = MediaQuery.of(context).size; + // it enable scrolling on small devices + return SafeArea( + bottom: false, + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + width: double.infinity, + padding: EdgeInsets.symmetric(horizontal: kDefaultPadding), + decoration: BoxDecoration( + color: kBackgroundColor, + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular(50), + bottomRight: Radius.circular(50), + ), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Center( + child: Hero( + tag: '${product.id}', + child: ProductPoster( + size: size, + image: product.image!, + ), + ), + ), + ListOfColors(), + Padding( + padding: const EdgeInsets.symmetric( + vertical: kDefaultPadding / 2), + child: Text( + product.title!, + style: Theme.of(context).textTheme.headline6, + ), + ), + Text( + '\$${product.price}', + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.w600, + color: kSecondRed, + ), + ), + Padding( + padding: + EdgeInsets.symmetric(vertical: kDefaultPadding / 2), + child: Text( + product.description!, + style: TextStyle(color: kTextRed), + ), + ), + SizedBox(height: kDefaultPadding), + ], + ), + ), + ChatAndAddToCart(), + ], + ), + ), + ); + } +} diff --git a/lib/Screens/Visit/details/components/chat_and_add_to_cart.dart b/lib/Screens/Visit/details/components/chat_and_add_to_cart.dart new file mode 100644 index 0000000..ff75a8f --- /dev/null +++ b/lib/Screens/Visit/details/components/chat_and_add_to_cart.dart @@ -0,0 +1,51 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:mymuseum_visitapp/constants.dart'; + + +class ChatAndAddToCart extends StatelessWidget { + const ChatAndAddToCart({ + Key? key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + margin: EdgeInsets.all(kDefaultPadding), + padding: EdgeInsets.symmetric( + horizontal: kDefaultPadding, + vertical: kDefaultPadding / 2, + ), + decoration: BoxDecoration( + color: Color(0xFFFCBF1E), + borderRadius: BorderRadius.circular(30), + ), + child: Row( + children: [ + SvgPicture.asset( + "assets/icons/chat.svg", + height: 18, + ), + SizedBox(width: kDefaultPadding / 2), + Text( + "Chat", + style: TextStyle(color: Colors.white), + ), + // it will cover all available spaces + Spacer(), + FlatButton.icon( + onPressed: () {}, + icon: SvgPicture.asset( + "assets/icons/shopping-bag.svg", + height: 18, + ), + label: Text( + "Add to Cart", + style: TextStyle(color: Colors.white), + ), + ), + ], + ), + ); + } +} diff --git a/lib/Screens/Visit/details/components/color_dots.dart b/lib/Screens/Visit/details/components/color_dots.dart new file mode 100644 index 0000000..314170e --- /dev/null +++ b/lib/Screens/Visit/details/components/color_dots.dart @@ -0,0 +1,38 @@ +import 'package:flutter/material.dart'; +import 'package:mymuseum_visitapp/constants.dart'; + + +class ColorDot extends StatelessWidget { + const ColorDot({ + Key? key, + required this.fillColor, + // by default we set it false + this.isSelected = false, + }) : super(key: key); + final Color fillColor; + final bool isSelected; + + @override + Widget build(BuildContext context) { + return Container( + margin: + // left and right padding 8 + EdgeInsets.symmetric(horizontal: kDefaultPadding / 2.5), + padding: EdgeInsets.all(3), + height: 24, + width: 24, + decoration: BoxDecoration( + shape: BoxShape.circle, + border: Border.all( + color: isSelected ? Color(0xFF707070) : Colors.transparent, + ), + ), + child: Container( + decoration: BoxDecoration( + shape: BoxShape.circle, + color: fillColor, + ), + ), + ); + } +} diff --git a/lib/Screens/Visit/details/components/list_of_colors.dart b/lib/Screens/Visit/details/components/list_of_colors.dart new file mode 100644 index 0000000..cdaee58 --- /dev/null +++ b/lib/Screens/Visit/details/components/list_of_colors.dart @@ -0,0 +1,32 @@ +import 'package:flutter/material.dart'; +import 'package:mymuseum_visitapp/constants.dart'; + +import 'color_dots.dart'; + +class ListOfColors extends StatelessWidget { + const ListOfColors({ + Key? key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: kDefaultPadding), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + ColorDot( + fillColor: Color(0xFF80989A), + isSelected: true, + ), + ColorDot( + fillColor: Color(0xFFFF5200), + ), + ColorDot( + fillColor: kTestSecondColor, + ), + ], + ), + ); + } +} diff --git a/lib/Screens/Visit/details/components/product_image.dart b/lib/Screens/Visit/details/components/product_image.dart new file mode 100644 index 0000000..12b7fdb --- /dev/null +++ b/lib/Screens/Visit/details/components/product_image.dart @@ -0,0 +1,42 @@ +import 'package:flutter/material.dart'; +import 'package:mymuseum_visitapp/constants.dart'; + +class ProductPoster extends StatelessWidget { + const ProductPoster({ + Key? key, + required this.size, + required this.image, + }) : super(key: key); + + final Size size; + final String image; + + @override + Widget build(BuildContext context) { + return Container( + margin: EdgeInsets.symmetric(vertical: kDefaultPadding), + // the height of this container is 80% of our width + height: size.width * 0.8, + + child: Stack( + alignment: Alignment.bottomCenter, + children: [ + Container( + height: size.width * 0.7, + width: size.width * 0.7, + decoration: BoxDecoration( + color: Colors.white, + shape: BoxShape.circle, + ), + ), + Image.asset( + image, + height: size.width * 0.75, + width: size.width * 0.75, + fit: BoxFit.cover, + ), + ], + ), + ); + } +} diff --git a/lib/Screens/Visit/details/details_screen.dart b/lib/Screens/Visit/details/details_screen.dart new file mode 100644 index 0000000..5726c41 --- /dev/null +++ b/lib/Screens/Visit/details/details_screen.dart @@ -0,0 +1,47 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:mymuseum_visitapp/Screens/Visit/product.dart'; +import 'package:mymuseum_visitapp/constants.dart'; + +import 'components/body.dart'; + +class DetailsScreen extends StatelessWidget { + final Product product; + + const DetailsScreen({Key? key, required this.product}) : super(key: key); + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: kTestSecondColor, + appBar: buildAppBar(context), + body: Body( + product: product, + ), + ); + } + + AppBar buildAppBar(BuildContext context) { + return AppBar( + backgroundColor: kBackgroundColor, + elevation: 0, + leading: IconButton( + padding: EdgeInsets.only(left: kDefaultPadding), + icon: SvgPicture.asset("assets/icons/back.svg"), + onPressed: () { + Navigator.pop(context); + }, + ), + centerTitle: false, + title: Text( + 'Back'.toUpperCase(), + style: Theme.of(context).textTheme.bodyText2, + ), + actions: [ + IconButton( + icon: SvgPicture.asset('assets/icons/cart_with_item.svg'), + onPressed: () {}, + ), + ], + ); + } +} diff --git a/lib/Screens/Visit/product.dart b/lib/Screens/Visit/product.dart new file mode 100644 index 0000000..01a4590 --- /dev/null +++ b/lib/Screens/Visit/product.dart @@ -0,0 +1,35 @@ +class Product { + final int? id, price; + final String? title, description, image; + + Product({this.id, this.price, this.title, this.description, this.image}); +} + +// list of products +// for our demo +List products = [ + Product( + id: 1, + price: 56, + title: "Classic Leather Arm Chair", + image: "assets/images/Item_1.png", + description: + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim", + ), + Product( + id: 4, + price: 68, + title: "Poppy Plastic Tub Chair", + image: "assets/images/Item_2.png", + description: + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim", + ), + Product( + id: 9, + price: 39, + title: "Bar Stool Chair", + image: "assets/images/Item_3.png", + description: + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim", + ), +]; \ No newline at end of file diff --git a/lib/Screens/Visit/visit.dart b/lib/Screens/Visit/visit.dart index e86962d..80d2c39 100644 --- a/lib/Screens/Visit/visit.dart +++ b/lib/Screens/Visit/visit.dart @@ -1,12 +1,13 @@ - -import 'package:auto_size_text/auto_size_text.dart'; import 'package:flutter/material.dart'; import 'package:manager_api/api.dart'; import 'package:mymuseum_visitapp/Components/CustomAppBar.dart'; import 'package:mymuseum_visitapp/Components/ScannerBouton.dart'; -import 'package:mymuseum_visitapp/Screens/Scanner/scanner_old.dart'; -import 'package:mymuseum_visitapp/client.dart'; +import 'package:mymuseum_visitapp/Models/visitContext.dart'; +import 'package:mymuseum_visitapp/app_context.dart'; import 'package:mymuseum_visitapp/constants.dart'; +import 'package:provider/provider.dart'; + +import 'components/body.dart'; class VisitPage extends StatefulWidget { const VisitPage({Key? key, required this.configurationId}) : super(key: key); @@ -18,18 +19,21 @@ class VisitPage extends StatefulWidget { } class _VisitPageState extends State { + ConfigurationDTO? configuration; @override Widget build(BuildContext context) { - Size size = MediaQuery.of(context).size; + final appContext = Provider.of(context); + VisitAppContext visitAppContext = appContext.getContext(); + configuration = visitAppContext.configuration; + return Scaffold( - appBar: CustomAppBar( - title: "Visit page", + appBar:CustomAppBar( + title: configuration?.label ?? "", isHomeButton: true, ), - body: Text( - "TODO description du parcours puis bouton scanner, ou visite virtuelle ?" - ), + backgroundColor: kMainGrey, + body: Body(configurationId: configuration!.id), // TODO handle error.. floatingActionButton: const ScannerBouton(isReplacement: false), ); } diff --git a/lib/constants.dart b/lib/constants.dart index 32ec41b..6a4fd2a 100644 --- a/lib/constants.dart +++ b/lib/constants.dart @@ -11,6 +11,7 @@ const kArticleDescriptionSize = 12.5; const kArticleContentSize = 16.0; const List languages = ["FR", "NL", "EN", "DE"]; // hmmmm depends on config.. +const String defaultLanguage = "EN"; // Text Style const kHeadingTextStyle = TextStyle( @@ -19,6 +20,8 @@ const kHeadingTextStyle = TextStyle( color: Color(0xFFFFFFFF) ); +const kDefaultPadding = 20.0; + const kMainGrey = Color(0xFF424242); const kSecondGrey = Color(0xFF555457); const kTestSecondColor = Color(0xFF2F4858); @@ -40,6 +43,13 @@ const kMenuDescriptionDetailSize = 18.0; const kNoneInfoOrIncorrect = 35.0; +// our default Shadow +const kDefaultShadow = BoxShadow( + offset: Offset(0, 15), + blurRadius: 27, + color: Colors.black12, // Black color with 12% opacity +); + /* const kTextStyle = TextStyle( fontSize: 23,