diff --git a/fbla_ui/lib/pages/business_detail.dart b/fbla_ui/lib/pages/business_detail.dart index 84c74ee..a0f8461 100644 --- a/fbla_ui/lib/pages/business_detail.dart +++ b/fbla_ui/lib/pages/business_detail.dart @@ -4,12 +4,12 @@ import 'package:fbla_ui/pages/create_edit_listing.dart'; import 'package:fbla_ui/pages/listing_detail.dart'; import 'package:fbla_ui/shared/api_logic.dart'; import 'package:fbla_ui/shared/global_vars.dart'; +import 'package:fbla_ui/shared/utils.dart'; +import 'package:fbla_ui/shared/widgets.dart'; import 'package:flutter/material.dart'; import 'package:rive/rive.dart'; import 'package:url_launcher/url_launcher.dart'; -import '../shared/utils.dart'; - class BusinessDetail extends StatefulWidget { final int id; final String name; @@ -212,71 +212,7 @@ class _CreateBusinessDetailState extends State { ]), ), // Contact info - Card( - clipBehavior: Clip.antiAlias, - child: Column( - children: [ - Row( - children: [ - Padding( - padding: - const EdgeInsets.only(left: 16.0, top: 8.0), - child: Text( - business.contactName!, - textAlign: TextAlign.left, - style: const TextStyle( - fontSize: 20, fontWeight: FontWeight.bold), - ), - ), - ], - ), - if (business.contactPhone != null) - ListTile( - leading: const Icon(Icons.phone), - title: Text(business.contactPhone!), - onTap: () { - showDialog( - context: context, - builder: (BuildContext context) { - return AlertDialog( - backgroundColor: - Theme.of(context).colorScheme.surface, - title: - Text('Contact ${business.contactName}'), - content: Text( - '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 != null) - ListTile( - leading: const Icon(Icons.email), - title: Text(business.contactEmail!), - onTap: () { - launchUrl( - Uri.parse('mailto:${business.contactEmail}')); - }, - ), - ], - ), - ), + ContactInformationCard(business: business), // Location Card( clipBehavior: Clip.antiAlias, diff --git a/fbla_ui/lib/pages/create_edit_business.dart b/fbla_ui/lib/pages/create_edit_business.dart index 9847f35..0c01846 100644 --- a/fbla_ui/lib/pages/create_edit_business.dart +++ b/fbla_ui/lib/pages/create_edit_business.dart @@ -1,11 +1,10 @@ import 'package:fbla_ui/main.dart'; import 'package:fbla_ui/shared/api_logic.dart'; +import 'package:fbla_ui/shared/global_vars.dart'; import 'package:fbla_ui/shared/utils.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import '../shared/global_vars.dart'; - class CreateEditBusiness extends StatefulWidget { final Business? inputBusiness; diff --git a/fbla_ui/lib/pages/listing_detail.dart b/fbla_ui/lib/pages/listing_detail.dart index c2e8a4c..1384396 100644 --- a/fbla_ui/lib/pages/listing_detail.dart +++ b/fbla_ui/lib/pages/listing_detail.dart @@ -4,9 +4,11 @@ import 'package:fbla_ui/pages/create_edit_listing.dart'; import 'package:fbla_ui/shared/api_logic.dart'; import 'package:fbla_ui/shared/global_vars.dart'; import 'package:fbla_ui/shared/utils.dart'; +import 'package:fbla_ui/shared/widgets.dart'; import 'package:flutter/material.dart'; import 'package:url_launcher/url_launcher.dart'; +/// A page to view all specific details about a single job listing (with it's businesses contact info) class JobListingDetail extends StatefulWidget { final JobListing listing; final Business fromBusiness; @@ -33,104 +35,16 @@ class _CreateBusinessDetailState extends State { Widget _detailBody(JobListing listing) { return ListView( children: [ - // Title, logo, desc, website Center( child: SizedBox( width: 800, child: Column( children: [ + // Top summary card Padding( - padding: const EdgeInsets.only(top: 4.0), - child: Card( - clipBehavior: Clip.antiAlias, - child: Column( - children: [ - Padding( - padding: const EdgeInsets.only(right: 8.0), - child: ListTile( - minVerticalPadding: 0, - titleAlignment: ListTileTitleAlignment.titleHeight, - title: Padding( - padding: const EdgeInsets.only(top: 8.0), - child: Text( - '${listing.name} (${getNameFromOfferType(listing.offerType!)})', - style: const TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold)), - ), - subtitle: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - MouseRegion( - cursor: SystemMouseCursors.click, - child: GestureDetector( - onTap: () { - Navigator.push(context, - MaterialPageRoute(builder: (context) { - return BusinessDetail( - id: widget.fromBusiness.id, - name: widget.fromBusiness.name!); - })); - }, - child: Text( - widget.fromBusiness.name!, - style: const TextStyle(fontSize: 18), - ), - ), - ), - Text( - listing.description, - ), - ], - ), - contentPadding: - const EdgeInsets.only(bottom: 8, left: 16), - leading: Badge( - label: Text( - getLetterFromOfferType(listing.offerType!), - style: const TextStyle(fontSize: 16), - ), - largeSize: 24, - offset: const Offset(12, -3), - textColor: Colors.white, - backgroundColor: - getColorFromOfferType(listing.offerType!), - child: ClipRRect( - borderRadius: BorderRadius.circular(6.0), - child: Image.network( - '$apiAddress/logos/${widget.fromBusiness.id}', - width: 48, - height: 48, errorBuilder: - (BuildContext context, Object exception, - StackTrace? stackTrace) { - return Icon( - getIconFromJobType( - listing.type ?? JobType.other), - size: 48); - }), - ), - ), - ), - ), - if (listing.link != null && listing.link != '') - ListTile( - leading: const Icon(Icons.link), - title: const Text('More Information'), - subtitle: Text( - listing.link! - .replaceAll('https://', '') - .replaceAll('http://', '') - .replaceAll('www.', ''), - style: const TextStyle(color: Colors.blue)), - onTap: () { - launchUrl(Uri.parse(listing.link!)); - }, - ), - ], - ), - ), - ), - // Wage + padding: const EdgeInsets.only(top: 4.0), + child: _summaryCard(listing)), + // Wage card if (listing.wage != null && listing.wage != '') Card( child: ListTile( @@ -139,72 +53,8 @@ class _CreateBusinessDetailState extends State { title: const Text('Wage Information'), ), ), - Card( - clipBehavior: Clip.antiAlias, - child: Column( - children: [ - Row( - children: [ - Padding( - padding: - const EdgeInsets.only(left: 16.0, top: 8.0), - child: Text( - widget.fromBusiness.contactName!, - textAlign: TextAlign.left, - style: const TextStyle( - fontSize: 20, fontWeight: FontWeight.bold), - ), - ), - ], - ), - if (widget.fromBusiness.contactPhone != null) - ListTile( - leading: const Icon(Icons.phone), - title: Text(widget.fromBusiness.contactPhone!), - // maybe replace ! with ?? ''. same is true for below - onTap: () { - showDialog( - context: context, - builder: (BuildContext context) { - return AlertDialog( - backgroundColor: - Theme.of(context).colorScheme.surface, - title: Text( - 'Contact ${widget.fromBusiness.contactName}'), - content: Text( - 'Would you like to call or text ${widget.fromBusiness.contactName}?'), - actions: [ - TextButton( - child: const Text('Text'), - onPressed: () { - launchUrl(Uri.parse( - 'sms:${widget.fromBusiness.contactPhone}')); - Navigator.of(context).pop(); - }), - TextButton( - child: const Text('Call'), - onPressed: () async { - launchUrl(Uri.parse( - 'tel:${widget.fromBusiness.contactPhone}')); - Navigator.of(context).pop(); - }), - ], - ); - }); - }, - ), - if (widget.fromBusiness.contactEmail != null) - ListTile( - leading: const Icon(Icons.email), - title: Text(widget.fromBusiness.contactEmail!), - onTap: () { - launchUrl(Uri.parse( - 'mailto:${widget.fromBusiness.contactEmail}')); - }, - ), - ], - ), - ), + // Contact information for the business contact + ContactInformationCard(business: widget.fromBusiness) ], ), ), @@ -213,6 +63,90 @@ class _CreateBusinessDetailState extends State { ); } + Widget _summaryCard(JobListing listing) { + return Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.only(right: 8.0), + child: ListTile( + minVerticalPadding: 0, + titleAlignment: ListTileTitleAlignment.titleHeight, + title: Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Text( + '${listing.name} (${getNameFromOfferType(listing.offerType!)})', + style: const TextStyle( + fontSize: 24, fontWeight: FontWeight.bold)), + ), + subtitle: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + MouseRegion( + cursor: SystemMouseCursors.click, + child: GestureDetector( + onTap: () { + Navigator.push(context, + MaterialPageRoute(builder: (context) { + return BusinessDetail( + id: widget.fromBusiness.id, + name: widget.fromBusiness.name!); + })); + }, + child: Text( + widget.fromBusiness.name!, + style: const TextStyle(fontSize: 18), + ), + ), + ), + Text(listing.description), + ], + ), + contentPadding: const EdgeInsets.only(bottom: 8, left: 16), + leading: Badge( + label: Text( + getLetterFromOfferType(listing.offerType!), + style: const TextStyle(fontSize: 16), + ), + largeSize: 24, + offset: const Offset(12, -3), + textColor: Colors.white, + backgroundColor: getColorFromOfferType(listing.offerType!), + child: ClipRRect( + borderRadius: BorderRadius.circular(6.0), + child: Image.network( + '$apiAddress/logos/${widget.fromBusiness.id}', + width: 48, + height: 48, errorBuilder: (BuildContext context, + Object exception, StackTrace? stackTrace) { + return Icon( + getIconFromJobType(listing.type ?? JobType.other), + size: 48); + }), + ), + ), + ), + ), + if (listing.link != null && listing.link != '') + ListTile( + leading: const Icon(Icons.link), + title: const Text('More Information'), + subtitle: Text( + listing.link! + .replaceAll('https://', '') + .replaceAll('http://', '') + .replaceAll('www.', ''), + style: const TextStyle(color: Colors.blue)), + onTap: () { + launchUrl(Uri.parse(listing.link!)); + }, + ), + ], + ), + ); + } + List? _getActions(JobListing listing, Business fromBusiness) { if (loggedIn) { return [ diff --git a/fbla_ui/lib/shared/widgets.dart b/fbla_ui/lib/shared/widgets.dart index 3eb499b..12a0500 100644 --- a/fbla_ui/lib/shared/widgets.dart +++ b/fbla_ui/lib/shared/widgets.dart @@ -6,488 +6,6 @@ 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; @@ -745,29 +263,6 @@ class _MainSliverAppBarState extends State { }); }, ), -// 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( @@ -841,3 +336,74 @@ class _MainSliverAppBarState extends State { return null; } } + +class ContactInformationCard extends StatelessWidget { + final Business business; + + ContactInformationCard({super.key, required this.business}); + + @override + Widget build(BuildContext context) { + return Card( + clipBehavior: Clip.antiAlias, + child: Column( + children: [ + Row( + children: [ + Padding( + padding: const EdgeInsets.only(left: 16.0, top: 8.0), + child: Text( + business.contactName!, + textAlign: TextAlign.left, + style: const TextStyle( + fontSize: 20, fontWeight: FontWeight.bold), + ), + ), + ], + ), + if (business.contactPhone != null) + ListTile( + leading: const Icon(Icons.phone), + title: Text(business.contactPhone!), + onTap: () { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + backgroundColor: Theme.of(context).colorScheme.surface, + title: Text('Contact ${business.contactName}'), + content: Text( + '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 != null) + ListTile( + leading: const Icon(Icons.email), + title: Text(business.contactEmail!), + onTap: () { + launchUrl(Uri.parse('mailto:${business.contactEmail}')); + }, + ), + ], + ), + ); + } +}