API Rewrite with UI
This commit is contained in:
@@ -4,229 +4,311 @@ import 'package:fbla_ui/pages/create_edit_business.dart';
|
||||
import 'package:fbla_ui/pages/signin_page.dart';
|
||||
import 'package:fbla_ui/shared.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rive/rive.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
class BusinessDetail extends StatefulWidget {
|
||||
final Business inputBusiness;
|
||||
final int id;
|
||||
final String name;
|
||||
final JobType clickFromType;
|
||||
|
||||
const BusinessDetail({super.key, required this.inputBusiness});
|
||||
const BusinessDetail(
|
||||
{super.key,
|
||||
required this.id,
|
||||
required this.name,
|
||||
required this.clickFromType});
|
||||
|
||||
@override
|
||||
State<BusinessDetail> createState() => _CreateBusinessDetailState();
|
||||
}
|
||||
|
||||
class _CreateBusinessDetailState extends State<BusinessDetail> {
|
||||
late Future loadBusiness;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
loadBusiness = fetchBusiness(widget.id);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Business business = Business.copy(widget.inputBusiness);
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(business.name),
|
||||
actions: _getActions(business),
|
||||
),
|
||||
body: ListView(
|
||||
children: [
|
||||
// Title, logo, desc, website
|
||||
Card(
|
||||
return FutureBuilder(
|
||||
future: loadBusiness,
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.connectionState == ConnectionState.done) {
|
||||
if (snapshot.hasData) {
|
||||
if (snapshot.data.runtimeType != String) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(snapshot.data.name),
|
||||
actions: _getActions(snapshot.data, widget.clickFromType),
|
||||
),
|
||||
body: _detailBody(snapshot.data),
|
||||
);
|
||||
} else {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(widget.name),
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(children: [
|
||||
Center(
|
||||
child:
|
||||
Text(snapshot.data, textAlign: TextAlign.center)),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: FilledButton(
|
||||
child: const Text('Retry'),
|
||||
onPressed: () {
|
||||
var refreshedData = fetchBusiness(widget.id);
|
||||
setState(() {
|
||||
loadBusiness = refreshedData;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
]),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
} else if (snapshot.connectionState == ConnectionState.waiting) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(widget.name),
|
||||
),
|
||||
body: Container(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
alignment: Alignment.center,
|
||||
child: const SizedBox(
|
||||
width: 75,
|
||||
height: 75,
|
||||
child:
|
||||
RiveAnimation.asset('assets/mdev_triangle_loading.riv'),
|
||||
)),
|
||||
);
|
||||
}
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(widget.name),
|
||||
),
|
||||
body: Text(
|
||||
'\nError: ${snapshot.error}',
|
||||
style: const TextStyle(fontSize: 18),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
ListView _detailBody(Business business) {
|
||||
return ListView(
|
||||
children: [
|
||||
// Title, logo, desc, website
|
||||
Card(
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: Column(
|
||||
children: [
|
||||
ListTile(
|
||||
title: Text(business.name,
|
||||
textAlign: TextAlign.left,
|
||||
style: const TextStyle(
|
||||
fontSize: 24, fontWeight: FontWeight.bold)),
|
||||
subtitle: Text(
|
||||
business.description,
|
||||
textAlign: TextAlign.left,
|
||||
),
|
||||
leading: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(6.0),
|
||||
child: Image.network('$apiAddress/logos/${business.id}',
|
||||
width: 48,
|
||||
height: 48, errorBuilder: (BuildContext context,
|
||||
Object exception, StackTrace? stackTrace) {
|
||||
return getIconFromJobType(widget.clickFromType, 48,
|
||||
Theme.of(context).colorScheme.onSurface);
|
||||
}),
|
||||
),
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.link),
|
||||
title: const Text('Website'),
|
||||
subtitle: Text(business.website!,
|
||||
style: const TextStyle(color: Colors.blue)),
|
||||
onTap: () {
|
||||
launchUrl(Uri.parse('https://${business.website}'));
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
// Available positions
|
||||
Card(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 16.0, top: 8.0),
|
||||
child:
|
||||
Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||
const Text(
|
||||
'Available Postitions',
|
||||
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
|
||||
),
|
||||
// Container(
|
||||
// height: 400,
|
||||
// width: 300,
|
||||
ListView(
|
||||
scrollDirection: Axis.vertical,
|
||||
shrinkWrap: true,
|
||||
children: [
|
||||
ListTile(
|
||||
title: Text('Postition 1'),
|
||||
leading: Icon(Icons.work),
|
||||
onTap: () {
|
||||
// launchUrl(Uri.parse(''));
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
title: Text('Postition 2'),
|
||||
leading: Icon(Icons.work),
|
||||
onTap: () {
|
||||
// launchUrl(Uri.parse(''));
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
title: Text('Postition 3'),
|
||||
leading: Icon(Icons.work),
|
||||
onTap: () {
|
||||
// launchUrl(Uri.parse(''));
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
]),
|
||||
),
|
||||
),
|
||||
// Contact info
|
||||
Visibility(
|
||||
visible:
|
||||
(business.contactEmail != null || business.contactPhone != null),
|
||||
child: Card(
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: Column(
|
||||
children: [
|
||||
ListTile(
|
||||
title: Text(business.name,
|
||||
textAlign: TextAlign.left,
|
||||
style: const TextStyle(
|
||||
fontSize: 24, fontWeight: FontWeight.bold)),
|
||||
subtitle: Text(
|
||||
business.description,
|
||||
textAlign: TextAlign.left,
|
||||
),
|
||||
leading: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(6.0),
|
||||
child: Image.network('$apiAddress/logos/${business.id}',
|
||||
width: 48,
|
||||
height: 48, errorBuilder: (BuildContext context,
|
||||
Object exception, StackTrace? stackTrace) {
|
||||
return getIconFromType(business.type, 48,
|
||||
Theme.of(context).colorScheme.onSurface);
|
||||
}),
|
||||
Row(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 16.0, top: 8.0),
|
||||
child: Text(
|
||||
business.contactName ?? 'Contact ${business.name}',
|
||||
textAlign: TextAlign.left,
|
||||
style: const TextStyle(
|
||||
fontSize: 20, fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Visibility(
|
||||
visible: business.contactPhone != null,
|
||||
child: ListTile(
|
||||
leading: Icon(Icons.phone),
|
||||
title: Text(business.contactPhone!),
|
||||
// maybe replace ! with ?? ''. same is true for below
|
||||
onTap: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
backgroundColor:
|
||||
Theme.of(context).colorScheme.background,
|
||||
title: Text(business.contactName!.isEmpty
|
||||
? 'Contact ${business.name}?'
|
||||
: 'Contact ${business.contactName}'),
|
||||
content: Text(business.contactName!.isEmpty
|
||||
? '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();
|
||||
}),
|
||||
],
|
||||
);
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.link),
|
||||
title: const Text('Website'),
|
||||
subtitle: Text(business.website,
|
||||
style: const TextStyle(color: Colors.blue)),
|
||||
onTap: () {
|
||||
launchUrl(Uri.parse('https://${business.website}'));
|
||||
},
|
||||
Visibility(
|
||||
visible: business.contactEmail != null,
|
||||
child: ListTile(
|
||||
leading: const Icon(Icons.email),
|
||||
title: Text(business.contactEmail!),
|
||||
onTap: () {
|
||||
launchUrl(Uri.parse('mailto:${business.contactEmail}'));
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
// Available positions
|
||||
Card(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 16.0, top: 8.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'Available Postitions',
|
||||
style: const TextStyle(
|
||||
fontSize: 20, fontWeight: FontWeight.bold),
|
||||
),
|
||||
// Container(
|
||||
// height: 400,
|
||||
// width: 300,
|
||||
ListView(
|
||||
scrollDirection: Axis.vertical,
|
||||
shrinkWrap: true,
|
||||
children: [
|
||||
ListTile(
|
||||
title: Text('Postition 1'),
|
||||
leading: Icon(Icons.work),
|
||||
onTap: () {
|
||||
// launchUrl(Uri.parse(''));
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
title: Text('Postition 2'),
|
||||
leading: Icon(Icons.work),
|
||||
onTap: () {
|
||||
// launchUrl(Uri.parse(''));
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
title: Text('Postition 3'),
|
||||
leading: Icon(Icons.work),
|
||||
onTap: () {
|
||||
// launchUrl(Uri.parse(''));
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
]),
|
||||
),
|
||||
// Location
|
||||
Visibility(
|
||||
child: Card(
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: ListTile(
|
||||
leading: const Icon(Icons.location_on),
|
||||
title: Text(business.locationName!),
|
||||
subtitle: Text(business.locationAddress!),
|
||||
onTap: () {
|
||||
launchUrl(Uri.parse(Uri.encodeFull(
|
||||
'https://www.google.com/maps/search/?api=1&query=${business.locationName}')));
|
||||
},
|
||||
),
|
||||
),
|
||||
// Contact info
|
||||
Visibility(
|
||||
visible: (business.contactEmail.isNotEmpty ||
|
||||
business.contactPhone.isNotEmpty),
|
||||
child: Card(
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 16.0, top: 8.0),
|
||||
child: Text(
|
||||
business.contactName.isEmpty
|
||||
? 'Contact ${business.name}'
|
||||
: business.contactName,
|
||||
textAlign: TextAlign.left,
|
||||
style: const TextStyle(
|
||||
fontSize: 20, fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Visibility(
|
||||
visible: business.contactPhone.isNotEmpty,
|
||||
child: ListTile(
|
||||
leading: Icon(Icons.phone),
|
||||
title: Text(business.contactPhone),
|
||||
onTap: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
backgroundColor:
|
||||
Theme.of(context).colorScheme.background,
|
||||
title: Text(business.contactName.isEmpty
|
||||
? 'Contact ${business.name}?'
|
||||
: 'Contact ${business.contactName}'),
|
||||
content: Text(business.contactName.isEmpty
|
||||
? '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();
|
||||
}),
|
||||
],
|
||||
);
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
Visibility(
|
||||
visible: business.contactEmail.isNotEmpty,
|
||||
child: ListTile(
|
||||
leading: const Icon(Icons.email),
|
||||
title: Text(business.contactEmail),
|
||||
onTap: () {
|
||||
launchUrl(Uri.parse('mailto:${business.contactEmail}'));
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
// Notes
|
||||
Visibility(
|
||||
visible: business.notes != null,
|
||||
child: Card(
|
||||
child: ListTile(
|
||||
leading: const Icon(Icons.notes),
|
||||
title: const Text(
|
||||
'Additional Notes:',
|
||||
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
|
||||
),
|
||||
subtitle: Text(business.notes!),
|
||||
),
|
||||
),
|
||||
// Location
|
||||
Visibility(
|
||||
child: Card(
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: ListTile(
|
||||
leading: const Icon(Icons.location_on),
|
||||
title: Text(business.locationName),
|
||||
subtitle: Text(business.locationAddress),
|
||||
onTap: () {
|
||||
launchUrl(Uri.parse(Uri.encodeFull(
|
||||
'https://www.google.com/maps/search/?api=1&query=${business.locationName}')));
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
// Notes
|
||||
Visibility(
|
||||
visible: business.notes.isNotEmpty,
|
||||
child: Card(
|
||||
child: ListTile(
|
||||
leading: const Icon(Icons.notes),
|
||||
title: const Text(
|
||||
'Additional Notes:',
|
||||
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
|
||||
),
|
||||
subtitle: Text(business.notes),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
List<Widget>? _getActions(Business business) {
|
||||
List<Widget>? _getActions(Business business, JobType clickFromType) {
|
||||
if (loggedIn) {
|
||||
return [
|
||||
IconButton(
|
||||
icon: const Icon(Icons.edit),
|
||||
onPressed: () {
|
||||
Navigator.of(context).push(MaterialPageRoute(
|
||||
builder: (context) =>
|
||||
CreateEditBusiness(inputBusiness: business)));
|
||||
builder: (context) => CreateEditBusiness(
|
||||
inputBusiness: business,
|
||||
clickFromType: clickFromType,
|
||||
)));
|
||||
},
|
||||
),
|
||||
IconButton(
|
||||
@@ -250,7 +332,7 @@ class _CreateBusinessDetailState extends State<BusinessDetail> {
|
||||
child: const Text('Yes'),
|
||||
onPressed: () async {
|
||||
String? deleteResult =
|
||||
await deleteBusiness(business, jwt);
|
||||
await deleteBusiness(business.id, jwt);
|
||||
if (deleteResult != null) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
|
||||
@@ -6,8 +6,9 @@ import 'package:flutter/services.dart';
|
||||
|
||||
class CreateEditBusiness extends StatefulWidget {
|
||||
final Business? inputBusiness;
|
||||
final JobType? clickFromType;
|
||||
|
||||
const CreateEditBusiness({super.key, this.inputBusiness});
|
||||
const CreateEditBusiness({super.key, this.inputBusiness, this.clickFromType});
|
||||
|
||||
@override
|
||||
State<CreateEditBusiness> createState() => _CreateEditBusinessState();
|
||||
@@ -27,7 +28,6 @@ class _CreateEditBusinessState extends State<CreateEditBusiness> {
|
||||
id: 0,
|
||||
name: 'Business',
|
||||
description: 'Add details about the business below.',
|
||||
type: BusinessType.other,
|
||||
website: '',
|
||||
contactName: '',
|
||||
contactEmail: '',
|
||||
@@ -155,7 +155,9 @@ class _CreateEditBusinessState extends State<CreateEditBusiness> {
|
||||
'https://logo.clearbit.com/${business.website}',
|
||||
errorBuilder: (BuildContext context,
|
||||
Object exception, StackTrace? stackTrace) {
|
||||
return getIconFromType(business.type, 48,
|
||||
return getIconFromJobType(
|
||||
widget.clickFromType ?? JobType.other,
|
||||
48,
|
||||
Theme.of(context).colorScheme.onBackground);
|
||||
}),
|
||||
),
|
||||
@@ -239,7 +241,8 @@ class _CreateEditBusinessState extends State<CreateEditBusiness> {
|
||||
FocusScope.of(context).unfocus();
|
||||
},
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Business Description (required)',
|
||||
labelText:
|
||||
'Business Description (required)',
|
||||
),
|
||||
validator: (value) {
|
||||
if (value != null && value.isEmpty) {
|
||||
@@ -357,46 +360,49 @@ class _CreateEditBusinessState extends State<CreateEditBusiness> {
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
left: 8.0, right: 8.0, bottom: 8.0),
|
||||
child: Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Text('Type of Business',
|
||||
style: TextStyle(fontSize: 16)),
|
||||
DropdownMenu<BusinessType>(
|
||||
initialSelection: business.type,
|
||||
controller: businessTypeController,
|
||||
label: const Text('Business Type'),
|
||||
dropdownMenuEntries: const [
|
||||
DropdownMenuEntry(
|
||||
value: BusinessType.food,
|
||||
label: 'Food Related'),
|
||||
DropdownMenuEntry(
|
||||
value: BusinessType.shop,
|
||||
label: 'Shop'),
|
||||
DropdownMenuEntry(
|
||||
value: BusinessType.outdoors,
|
||||
label: 'Outdoors'),
|
||||
DropdownMenuEntry(
|
||||
value: BusinessType.manufacturing,
|
||||
label: 'Manufacturing'),
|
||||
DropdownMenuEntry(
|
||||
value: BusinessType.entertainment,
|
||||
label: 'Entertainment'),
|
||||
DropdownMenuEntry(
|
||||
value: BusinessType.other,
|
||||
label: 'Other'),
|
||||
],
|
||||
onSelected: (inputType) {
|
||||
business.type = inputType!;
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
// Business Type Dropdown
|
||||
|
||||
// Padding(
|
||||
// padding: const EdgeInsets.only(
|
||||
// left: 8.0, right: 8.0, bottom: 8.0),
|
||||
// child: Row(
|
||||
// mainAxisAlignment:
|
||||
// MainAxisAlignment.spaceBetween,
|
||||
// children: [
|
||||
// const Text('Type of Business',
|
||||
// style: TextStyle(fontSize: 16)),
|
||||
// DropdownMenu<BusinessType>(
|
||||
// initialSelection: business.type,
|
||||
// controller: businessTypeController,
|
||||
// label: const Text('Business Type'),
|
||||
// dropdownMenuEntries: const [
|
||||
// DropdownMenuEntry(
|
||||
// value: BusinessType.food,
|
||||
// label: 'Food Related'),
|
||||
// DropdownMenuEntry(
|
||||
// value: BusinessType.shop,
|
||||
// label: 'Shop'),
|
||||
// DropdownMenuEntry(
|
||||
// value: BusinessType.outdoors,
|
||||
// label: 'Outdoors'),
|
||||
// DropdownMenuEntry(
|
||||
// value: BusinessType.manufacturing,
|
||||
// label: 'Manufacturing'),
|
||||
// DropdownMenuEntry(
|
||||
// value: BusinessType.entertainment,
|
||||
// label: 'Entertainment'),
|
||||
// DropdownMenuEntry(
|
||||
// value: BusinessType.other,
|
||||
// label: 'Other'),
|
||||
// ],
|
||||
// onSelected: (inputType) {
|
||||
// business.type = inputType!;
|
||||
// },
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
left: 8.0, right: 8.0, bottom: 8.0),
|
||||
@@ -409,8 +415,7 @@ class _CreateEditBusinessState extends State<CreateEditBusiness> {
|
||||
FocusScope.of(context).unfocus();
|
||||
},
|
||||
decoration: const InputDecoration(
|
||||
labelText:
|
||||
'Contact Information Name',
|
||||
labelText: 'Contact Information Name',
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -16,9 +16,9 @@ bool isBusinessesFiltered = true;
|
||||
bool _isLoading = false;
|
||||
|
||||
class ExportData extends StatefulWidget {
|
||||
final List<Business> businesses;
|
||||
final Map<JobType, List<Business>> groupedBusinesses;
|
||||
|
||||
const ExportData({super.key, required this.businesses});
|
||||
const ExportData({super.key, required this.groupedBusinesses});
|
||||
|
||||
@override
|
||||
State<ExportData> createState() => _ExportDataState();
|
||||
@@ -31,7 +31,7 @@ class _ExportDataState extends State<ExportData> {
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
refreshBusinessDataFuture = fetchBusinessData();
|
||||
refreshBusinessDataFuture = fetchBusinessDataOverview();
|
||||
_isLoading = false;
|
||||
selectedBusinesses = <Business>{};
|
||||
}
|
||||
@@ -39,7 +39,7 @@ class _ExportDataState extends State<ExportData> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
floatingActionButton: _FAB(businesses: widget.businesses),
|
||||
floatingActionButton: _FAB(groupedBusinesses: widget.groupedBusinesses),
|
||||
body: CustomScrollView(
|
||||
slivers: [
|
||||
SliverAppBar(
|
||||
@@ -196,7 +196,7 @@ class _ExportDataState extends State<ExportData> {
|
||||
),
|
||||
),
|
||||
BusinessDisplayPanel(
|
||||
businesses: widget.businesses,
|
||||
groupedBusinesses: widget.groupedBusinesses,
|
||||
widescreen: MediaQuery.sizeOf(context).width >= 1000,
|
||||
selectable: true),
|
||||
const SliverToBoxAdapter(
|
||||
@@ -211,15 +211,26 @@ class _ExportDataState extends State<ExportData> {
|
||||
}
|
||||
|
||||
class _FAB extends StatefulWidget {
|
||||
final List<Business> businesses;
|
||||
final Map<JobType, List<Business>> groupedBusinesses;
|
||||
|
||||
const _FAB({required this.businesses});
|
||||
const _FAB({required this.groupedBusinesses});
|
||||
|
||||
@override
|
||||
State<_FAB> createState() => _FABState();
|
||||
}
|
||||
|
||||
class _FABState extends State<_FAB> {
|
||||
List<Business> allBusinesses = [];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
for (JobType type in widget.groupedBusinesses.keys) {
|
||||
allBusinesses.addAll(widget.groupedBusinesses[type]!);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return FloatingActionButton(
|
||||
@@ -273,7 +284,7 @@ class _FABState extends State<_FAB> {
|
||||
|
||||
List<pw.TableRow> rows = [];
|
||||
if (selectedBusinesses.isEmpty) {
|
||||
selectedBusinesses.addAll(widget.businesses);
|
||||
selectedBusinesses.addAll(allBusinesses);
|
||||
isBusinessesFiltered = false;
|
||||
} else {
|
||||
isBusinessesFiltered = true;
|
||||
@@ -284,9 +295,9 @@ class _FABState extends State<_FAB> {
|
||||
if (dataTypeFilters.contains(DataType.logo)) {
|
||||
remainingSpace -= 32;
|
||||
}
|
||||
if (dataTypeFilters.contains(DataType.type)) {
|
||||
remainingSpace -= 56;
|
||||
}
|
||||
// if (dataTypeFilters.contains(DataType.type)) {
|
||||
// remainingSpace -= 56;
|
||||
// }
|
||||
if (dataTypeFilters.contains(DataType.contactName)) {
|
||||
remainingSpace -= 72;
|
||||
}
|
||||
@@ -331,9 +342,9 @@ class _FABState extends State<_FAB> {
|
||||
} else if (dataType == DataType.description) {
|
||||
width = pw.FixedColumnWidth(descriptionWidth);
|
||||
columnNum++;
|
||||
} else if (dataType == DataType.type) {
|
||||
width = const pw.FixedColumnWidth(56);
|
||||
columnNum++;
|
||||
// } else if (dataType == DataType.type) {
|
||||
// width = const pw.FixedColumnWidth(56);
|
||||
// columnNum++;
|
||||
} else if (dataType == DataType.website) {
|
||||
width = pw.FixedColumnWidth(websiteWidth);
|
||||
columnNum++;
|
||||
@@ -394,18 +405,18 @@ class _FABState extends State<_FAB> {
|
||||
),
|
||||
padding: const pw.EdgeInsets.all(4.0)));
|
||||
}
|
||||
if (dataTypeFilters.contains(DataType.type)) {
|
||||
data.add(pw.Padding(
|
||||
child: pw.Text(
|
||||
business.type.name,
|
||||
// style: const pw.TextStyle(fontSize: 10)
|
||||
),
|
||||
padding: const pw.EdgeInsets.all(4.0)));
|
||||
}
|
||||
// if (dataTypeFilters.contains(DataType.type)) {
|
||||
// data.add(pw.Padding(
|
||||
// child: pw.Text(
|
||||
// business.type.name,
|
||||
// // style: const pw.TextStyle(fontSize: 10)
|
||||
// ),
|
||||
// padding: const pw.EdgeInsets.all(4.0)));
|
||||
// }
|
||||
if (dataTypeFilters.contains(DataType.website)) {
|
||||
data.add(pw.Padding(
|
||||
child: pw.Text(
|
||||
business.website,
|
||||
business.website ?? '',
|
||||
// style: const pw.TextStyle(fontSize: 10)
|
||||
),
|
||||
padding: const pw.EdgeInsets.all(4.0)));
|
||||
@@ -413,7 +424,7 @@ class _FABState extends State<_FAB> {
|
||||
if (dataTypeFilters.contains(DataType.contactName)) {
|
||||
data.add(pw.Padding(
|
||||
child: pw.Text(
|
||||
business.contactName,
|
||||
business.contactName ?? '',
|
||||
// style: const pw.TextStyle(fontSize: 10)
|
||||
),
|
||||
padding: const pw.EdgeInsets.all(4.0)));
|
||||
@@ -421,7 +432,7 @@ class _FABState extends State<_FAB> {
|
||||
if (dataTypeFilters.contains(DataType.contactEmail)) {
|
||||
data.add(pw.Padding(
|
||||
child: pw.Text(
|
||||
business.contactEmail,
|
||||
business.contactEmail ?? '',
|
||||
// style: const pw.TextStyle(fontSize: 10)
|
||||
),
|
||||
padding: const pw.EdgeInsets.all(4.0)));
|
||||
@@ -429,7 +440,7 @@ class _FABState extends State<_FAB> {
|
||||
if (dataTypeFilters.contains(DataType.contactPhone)) {
|
||||
data.add(pw.Padding(
|
||||
child: pw.Text(
|
||||
business.contactPhone,
|
||||
business.contactPhone ?? '',
|
||||
// style: const pw.TextStyle(fontSize: 10)
|
||||
),
|
||||
padding: const pw.EdgeInsets.all(4.0)));
|
||||
@@ -440,7 +451,7 @@ class _FABState extends State<_FAB> {
|
||||
style = const pw.TextStyle(fontSize: 8);
|
||||
}
|
||||
data.add(pw.Padding(
|
||||
child: pw.Text(business.notes, style: style),
|
||||
child: pw.Text(business.notes ?? '', style: style),
|
||||
padding: const pw.EdgeInsets.all(4.0)));
|
||||
}
|
||||
|
||||
@@ -461,10 +472,10 @@ class _FABState extends State<_FAB> {
|
||||
} else {
|
||||
rows.add(pw.TableRow(
|
||||
children: [
|
||||
pw.Padding(
|
||||
child: getPwIconFromType(
|
||||
business.type, 24, PdfColors.black),
|
||||
padding: const pw.EdgeInsets.all(4.0)),
|
||||
// pw.Padding(
|
||||
// child: getPwIconFromType(
|
||||
// business.type, 24, PdfColors.black),
|
||||
// padding: const pw.EdgeInsets.all(4.0)),
|
||||
...data
|
||||
],
|
||||
));
|
||||
|
||||
Reference in New Issue
Block a user