import 'package:dart_jsonwebtoken/dart_jsonwebtoken.dart'; import 'package:fbla_ui/pages/signin_page.dart'; import 'package:fbla_ui/shared/global_vars.dart'; import 'package:fbla_ui/shared/utils.dart'; import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:url_launcher/url_launcher.dart'; // class BusinessDisplayPanel extends StatefulWidget { // final Map>? jobGroupedBusinesses; // final Map>? businessGroupedBusinesses; // final bool widescreen; // final Set? selectedBusinesses; // // const BusinessDisplayPanel( // {super.key, // this.jobGroupedBusinesses, // this.businessGroupedBusinesses, // required this.widescreen, // this.selectedBusinesses}); // // @override // State createState() => _BusinessDisplayPanelState(); // } // // class _BusinessDisplayPanelState extends State { // @override // Widget build(BuildContext context) { // if ((widget.businessGroupedBusinesses?.keys ?? []).isEmpty && // (widget.jobGroupedBusinesses?.keys ?? []).isEmpty) { // return const SliverToBoxAdapter( // child: Center( // child: Padding( // padding: EdgeInsets.all(16.0), // child: Text( // 'No results found!\nPlease change your search filters.', // textAlign: TextAlign.center, // style: TextStyle(fontSize: 18), // ), // ), // ), // ); // } // // List headers = []; // if (widget.jobGroupedBusinesses != null) { // for (JobType jobType in widget.jobGroupedBusinesses!.keys) { // headers.add(BusinessHeader( // jobType: jobType, // widescreen: widget.widescreen, // // selectable: widget.selectable, // selectedBusinesses: widget.selectedBusinesses, // // updateSelectedBusinessesCallback: // // widget.updateSelectedBusinessesCallback, // businesses: widget.jobGroupedBusinesses![jobType]!)); // } // headers.sort((a, b) => a.jobType!.index.compareTo(b.jobType!.index)); // return MultiSliver(children: headers); // } else if (widget.businessGroupedBusinesses != null) { // for (BusinessType businessType // in widget.businessGroupedBusinesses!.keys) { // headers.add(BusinessHeader( // businessType: businessType, // widescreen: widget.widescreen, // selectedBusinesses: widget.selectedBusinesses, // businesses: widget.businessGroupedBusinesses![businessType]!)); // } // headers.sort( // (a, b) => a.businessType!.index.compareTo(b.businessType!.index)); // return MultiSliver(children: headers); // } // return const Text('Error with input data!'); // } // } // // class BusinessHeader extends StatefulWidget { // final JobType? jobType; // final BusinessType? businessType; // final List businesses; // final Set? selectedBusinesses; // final bool widescreen; // final void Function()? updateSelectedBusinessesCallback; // // const BusinessHeader({ // super.key, // this.jobType, // this.businessType, // required this.businesses, // required this.widescreen, // this.updateSelectedBusinessesCallback, // this.selectedBusinesses, // }); // // @override // State createState() => _BusinessHeaderState(); // } // // class _BusinessHeaderState extends State { // refresh() { // setState(() {}); // } // // @override // Widget build(BuildContext context) { // return SliverStickyHeader( // header: Container( // height: 55.0, // color: Theme.of(context).colorScheme.primary, // padding: const EdgeInsets.symmetric(horizontal: 16.0), // alignment: Alignment.centerLeft, // child: _getHeaderRow(widget.selectedBusinesses), // ), // sliver: _getChildSliver( // widget.businesses, widget.widescreen, widget.selectedBusinesses), // ); // } // // Widget _getHeaderRow(Set? selectedBusinesses) { // if (selectedBusinesses != null) { // return Row( // mainAxisAlignment: MainAxisAlignment.spaceBetween, // children: [ // Row( // children: [ // Padding( // padding: const EdgeInsets.only(left: 4.0, right: 12.0), // child: Icon( // widget.jobType != null // ? getIconFromJobType(widget.jobType!) // : getIconFromBusinessType(widget.businessType!), // color: Theme.of(context).colorScheme.onPrimary, // )), // Text(widget.jobType != null // ? getNameFromJobType(widget.jobType!) // : getNameFromBusinessType(widget.businessType!)), // ], // ), // Padding( // padding: const EdgeInsets.only(right: 12.0), // child: Checkbox( // checkColor: Theme.of(context).colorScheme.primary, // activeColor: Theme.of(context).colorScheme.onPrimary, // value: widget.selectedBusinesses!.containsAll(widget.businesses), // onChanged: (value) { // if (value!) { // setState(() { // widget.selectedBusinesses!.addAll(widget.businesses); // }); // } else { // setState(() { // widget.selectedBusinesses!.removeAll(widget.businesses); // }); // } // }, // ), // ), // ], // ); // } else { // return Row( // children: [ // Padding( // padding: const EdgeInsets.only(left: 4.0, right: 12.0), // child: Icon( // widget.jobType != null // ? getIconFromJobType(widget.jobType!) // : getIconFromBusinessType(widget.businessType!), // color: Theme.of(context).colorScheme.onPrimary, // ), // ), // Text( // widget.jobType != null // ? getNameFromJobType(widget.jobType!) // : getNameFromBusinessType(widget.businessType!), // style: TextStyle(color: Theme.of(context).colorScheme.onPrimary), // ), // ], // ); // } // } // // Widget _getChildSliver(List businesses, bool widescreen, // Set? selectedBusinesses) { // if (widescreen) { // return SliverPadding( // padding: const EdgeInsets.all(4), // sliver: SliverGrid( // gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent( // mainAxisExtent: 250.0, // maxCrossAxisExtent: 400.0, // mainAxisSpacing: 4.0, // crossAxisSpacing: 4.0, // ), // delegate: SliverChildBuilderDelegate( // childCount: businesses.length, // (BuildContext context, int index) { // return BusinessCard( // business: businesses[index], // selectedBusinesses: selectedBusinesses, // widescreen: widescreen, // callback: refresh, // jobType: widget.jobType, // ); // }, // ), // ), // ); // } else { // return SliverList( // delegate: SliverChildBuilderDelegate( // childCount: businesses.length, // (BuildContext context, int index) { // return BusinessCard( // business: businesses[index], // selectedBusinesses: selectedBusinesses, // widescreen: widescreen, // callback: refresh, // jobType: widget.jobType, // ); // }, // ), // ); // } // } // } // // class BusinessCard extends StatefulWidget { // final Business business; // final bool widescreen; // final Set? selectedBusinesses; // final Function callback; // final JobType? jobType; // final BusinessType? businessType; // // const BusinessCard({ // super.key, // required this.business, // required this.widescreen, // required this.callback, // this.jobType, // this.businessType, // this.selectedBusinesses, // }); // // @override // State createState() => _BusinessCardState(); // } // // class _BusinessCardState extends State { // @override // Widget build(BuildContext context) { // if (widget.widescreen) { // return _businessTile(widget.business, widget.selectedBusinesses, // widget.jobType, widget.businessType); // } else { // return _businessListItem(widget.business, widget.selectedBusinesses, // widget.callback, widget.jobType, widget.businessType); // } // } // // Widget _businessTile(Business business, Set? selectedBusinesses, // JobType? jobType, BusinessType? businessType) { // return MouseRegion( // cursor: SystemMouseCursors.click, // child: GestureDetector( // onTap: () { // Navigator.of(context).push(MaterialPageRoute( // builder: (context) => BusinessDetail( // id: business.id, // name: business.name!, // ))); // }, // child: Card( // clipBehavior: Clip.antiAlias, // child: Column( // crossAxisAlignment: CrossAxisAlignment.center, // children: [ // _getTileRow(business, selectedBusinesses, widget.callback), // Padding( // padding: const EdgeInsets.all(8.0), // child: Text( // business.description!, // maxLines: selectedBusinesses != null ? 7 : 5, // overflow: TextOverflow.ellipsis, // ), // ), // const Spacer(), // Padding( // padding: const EdgeInsets.all(8.0), // child: selectedBusinesses == null // ? Row( // mainAxisAlignment: MainAxisAlignment.spaceEvenly, // children: [ // IconButton( // icon: const Icon(Icons.link), // onPressed: () { // launchUrl( // Uri.parse('https://${business.website}')); // }, // ), // if (business.locationName != '') // IconButton( // icon: const Icon(Icons.location_on), // onPressed: () { // launchUrl(Uri.parse(Uri.encodeFull( // 'https://www.google.com/maps/search/?api=1&query=${business.locationName}'))); // }, // ), // if ((business.contactPhone != null) && // (business.contactPhone != '')) // IconButton( // icon: const Icon(Icons.phone), // onPressed: () { // showDialog( // context: context, // builder: (BuildContext context) { // return AlertDialog( // backgroundColor: Theme.of(context) // .colorScheme // .surface, // title: Text((business.contactName == // null || // business.contactName == '') // ? 'Contact ${business.name}?' // : 'Contact ${business.contactName}'), // content: Text((business.contactName == // null || // business.contactName == '') // ? 'Would you like to call or text ${business.name}?' // : 'Would you like to call or text ${business.contactName}?'), // actions: [ // TextButton( // child: const Text('Text'), // onPressed: () { // launchUrl(Uri.parse( // 'sms:${business.contactPhone}')); // Navigator.of(context).pop(); // }), // TextButton( // child: const Text('Call'), // onPressed: () async { // launchUrl(Uri.parse( // 'tel:${business.contactPhone}')); // Navigator.of(context).pop(); // }), // ], // ); // }); // }, // ), // if (business.contactEmail != '') // IconButton( // icon: const Icon(Icons.email), // onPressed: () { // launchUrl(Uri.parse( // 'mailto:${business.contactEmail}')); // }, // ), // ], // ) // : null), // ], // ), // ), // ), // ); // } // // Widget _getTileRow( // Business business, Set? selectedBusinesses, Function callback) { // if (selectedBusinesses != null) { // return Row( // mainAxisAlignment: MainAxisAlignment.spaceBetween, // children: [ // Padding( // padding: const EdgeInsets.all(8.0), // child: ClipRRect( // borderRadius: BorderRadius.circular(6.0), // child: Image.network('$apiAddress/logos/${business.id}', // height: 48, width: 48, errorBuilder: (BuildContext context, // Object exception, StackTrace? stackTrace) { // return Icon( // getIconFromBusinessType(business.type!), // size: 48, // ); // }), // ), // ), // Flexible( // child: Padding( // padding: const EdgeInsets.all(8.0), // child: Text( // business.name!, // style: // const TextStyle(fontSize: 18, fontWeight: FontWeight.bold), // maxLines: 2, // overflow: TextOverflow.ellipsis, // ), // ), // ), // Padding( // padding: const EdgeInsets.only(right: 24.0), // child: _checkbox(callback, selectedBusinesses), // ) // ], // ); // } else { // return Row( // children: [ // Padding( // padding: const EdgeInsets.all(8.0), // child: ClipRRect( // borderRadius: BorderRadius.circular(6.0), // child: Image.network('$apiAddress/logos/${business.id}', // height: 48, width: 48, errorBuilder: (BuildContext context, // Object exception, StackTrace? stackTrace) { // return Icon(getIconFromBusinessType(business.type!), // size: 48); // }), // )), // Flexible( // child: Padding( // padding: const EdgeInsets.all(8.0), // child: Text( // business.name!, // style: // const TextStyle(fontSize: 18, fontWeight: FontWeight.bold), // maxLines: 2, // overflow: TextOverflow.ellipsis, // ), // ), // ), // ], // ); // } // } // // Widget _businessListItem(Business business, Set? selectedBusinesses, // Function callback, JobType? jobType, BusinessType? businessType) { // return Card( // child: ListTile( // leading: ClipRRect( // borderRadius: BorderRadius.circular(3.0), // child: Image.network('$apiAddress/logos/${business.id}', // height: 24, width: 24, errorBuilder: (BuildContext context, // Object exception, StackTrace? stackTrace) { // return Icon(getIconFromBusinessType(business.type!)); // })), // title: Text(business.name!), // subtitle: Text(business.description!, // maxLines: 1, overflow: TextOverflow.ellipsis), // trailing: _getCheckbox(selectedBusinesses, callback), // onTap: () { // Navigator.of(context).push(MaterialPageRoute( // builder: (context) => BusinessDetail( // id: business.id, // name: business.name!, // ))); // }, // ), // ); // } // // Widget _checkbox(Function callback, Set selectedBusinesses) { // return Checkbox( // value: selectedBusinesses.contains(widget.business), // onChanged: (value) { // if (value!) { // setState(() { // selectedBusinesses.add(widget.business); // }); // } else { // setState(() { // selectedBusinesses.remove(widget.business); // }); // } // callback(); // }, // ); // } // // Widget? _getCheckbox(Set? selectedBusinesses, Function callback) { // if (selectedBusinesses != null) { // return _checkbox(callback, selectedBusinesses); // } else { // return null; // } // } // } class BusinessSearchBar extends StatefulWidget { final String searchTextHint; final Widget filterIconButton; final void Function(String) setSearchCallback; const BusinessSearchBar( {super.key, required this.setSearchCallback, required this.searchTextHint, required this.filterIconButton}); @override State createState() => _BusinessSearchBarState(); } class _BusinessSearchBarState extends State { TextEditingController controller = TextEditingController(); @override Widget build(BuildContext context) { return SizedBox( width: 450, height: 50, child: SearchBar( hintText: widget.searchTextHint, controller: controller, backgroundColor: WidgetStateProperty.resolveWith((notNeeded) { return Theme.of(context).colorScheme.surfaceContainer; }), onChanged: (query) { widget.setSearchCallback(query); }, leading: const Padding( padding: EdgeInsets.only(left: 8.0), child: Icon(Icons.search), ), trailing: [ if (controller.text != '') IconButton( icon: const Icon(Icons.clear), onPressed: () { controller.text = ''; widget.setSearchCallback(''); }, ), widget.filterIconButton ]), ); } } class FilterChips extends StatefulWidget { final Set? selectedJobChips; final Set? selectedBusinessChips; const FilterChips( {super.key, this.selectedJobChips, this.selectedBusinessChips}); @override State createState() => _FilterChipsState(); } class _FilterChipsState extends State { List filterChips() { List chips = []; if (widget.selectedJobChips != null) { for (var type in JobType.values) { chips.add(Padding( padding: const EdgeInsets.only(left: 4.0, right: 4.0), child: FilterChip( showCheckmark: false, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(20)), label: Text(getNameFromJobType(type)), selected: widget.selectedJobChips!.contains(type), onSelected: (bool selected) { setState(() { if (selected) { widget.selectedJobChips!.add(type); } else { widget.selectedJobChips!.remove(type); } }); }), )); } } else if (widget.selectedBusinessChips != null) { for (var type in BusinessType.values) { chips.add(Padding( padding: const EdgeInsets.only(left: 4.0, right: 4.0), child: FilterChip( showCheckmark: false, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(20)), label: Text(getNameFromBusinessType(type)), selected: widget.selectedBusinessChips!.contains(type), onSelected: (bool selected) { setState(() { if (selected) { widget.selectedBusinessChips!.add(type); } else { widget.selectedBusinessChips!.remove(type); } }); }), )); } } return chips; } @override Widget build(BuildContext context) { return Wrap( children: filterChips(), ); } } class MainSliverAppBar extends StatefulWidget { final bool widescreen; final Widget filterIconButton; final void Function(String) setSearch; final void Function() themeCallback; final void Function() generatePDF; final void Function(bool) updateLoggedIn; final String searchHintText; const MainSliverAppBar({ super.key, required this.widescreen, required this.setSearch, required this.searchHintText, required this.themeCallback, required this.filterIconButton, required this.updateLoggedIn, required this.generatePDF, }); @override State createState() => _MainSliverAppBarState(); } class _MainSliverAppBarState extends State { @override Widget build(BuildContext context) { return SliverAppBar( title: widget.widescreen ? Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Flexible( child: BusinessSearchBar( setSearchCallback: widget.setSearch, searchTextHint: widget.searchHintText, filterIconButton: widget.filterIconButton, ), ) // const PreferredSize( // preferredSize: Size(144, 0), child: SizedBox()) ], ) : const Text('Job Link'), toolbarHeight: 70, stretch: false, backgroundColor: Theme.of(context).colorScheme.surface, pinned: true, // floating: true, scrolledUnderElevation: 0, centerTitle: !widget.widescreen, expandedHeight: widget.widescreen ? 70 : 120, bottom: _getBottom(widget.widescreen), leading: !widget.widescreen ? IconButton( icon: Icon(getIconFromThemeMode(themeMode)), onPressed: () { setState(() { widget.themeCallback(); }); }, ) : null, actions: [ IconButton( icon: const Icon(Icons.file_download_outlined), onPressed: widget.generatePDF, ), IconButton( icon: const Icon(Icons.help), onPressed: () { showDialog( context: context, builder: (BuildContext context) { return AlertDialog( title: const Text('About'), backgroundColor: Theme.of(context).colorScheme.surface, content: SizedBox( width: 500, child: IntrinsicHeight( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( 'Welcome to my FBLA 2024 Coding and Programming submission!\n\n' 'MarinoDev Job Link aims to provide comprehensive details of businesses and community partners' ' for Waukesha West High School\'s Career and Technical Education Department.\n\n'), MouseRegion( cursor: SystemMouseCursors.click, child: GestureDetector( child: const Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('Git Repo:'), Text( 'https://git.marinodev.com/MarinoDev/FBLA24\n', style: TextStyle(color: Colors.blue)), ], ), onTap: () { launchUrl(Uri.https('git.marinodev.com', '/MarinoDev/FBLA24')); }, ), ), MouseRegion( cursor: SystemMouseCursors.click, child: GestureDetector( child: const Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('Please direct any questions to'), Text('drake@marinodev.com', style: TextStyle(color: Colors.blue)), ], ), onTap: () { launchUrl( Uri.parse('mailto:drake@marinodev.com')); }, ), ) ], ), ), ), actions: [ TextButton( child: const Text('OK'), onPressed: () { Navigator.of(context).pop(); }), ], ); }); }, ), // IconButton( // icon: const Icon(Icons.picture_as_pdf), // onPressed: () async { // if (!_isPreviousData) { // ScaffoldMessenger.of(context).clearSnackBars(); // ScaffoldMessenger.of(context).showSnackBar( // const SnackBar( // width: 300, // behavior: SnackBarBehavior.floating, // content: Text('There is no data!'), // duration: Duration(seconds: 2), // ), // ); // } else { // selectedDataTypesBusiness = {}; // Navigator.push( // context, // MaterialPageRoute( // builder: (context) => ExportData( // groupedBusinesses: overviewBusinesses))); // } // }, // ), Padding( padding: const EdgeInsets.only(right: 8.0), child: IconButton( icon: loggedIn ? const Icon(Icons.account_circle) : const Icon(Icons.login), onPressed: () { if (loggedIn) { var payload = JWT.decode(jwt).payload; showDialog( context: context, builder: (BuildContext context) { return AlertDialog( backgroundColor: Theme.of(context).colorScheme.surface, title: Text('Hi, ${payload['username']}!'), content: Text( 'You are logged in as an admin with username ${payload['username']}.'), actions: [ TextButton( child: const Text('Cancel'), onPressed: () { Navigator.of(context).pop(); }), TextButton( child: const Text('Logout'), onPressed: () async { final prefs = await SharedPreferences.getInstance(); prefs.setBool('rememberMe', false); prefs.setString('username', ''); prefs.setString('password', ''); widget.updateLoggedIn(false); Navigator.of(context).pop(); }), ], ); }); } else { Navigator.push( context, MaterialPageRoute( builder: (context) => SignInPage(refreshAccount: widget.updateLoggedIn))); } }, ), ), ], ); } PreferredSizeWidget? _getBottom(bool widescreen) { if (!widescreen) { return PreferredSize( preferredSize: const Size.fromHeight(0), child: SizedBox( height: 70, child: Padding( padding: const EdgeInsets.all(10), child: BusinessSearchBar( filterIconButton: widget.filterIconButton, setSearchCallback: widget.setSearch, searchTextHint: widget.searchHintText, ), ), ), ); } return null; } }