FBLA24/fbla_ui/lib/pages/listing_detail.dart
2024-06-23 17:02:19 -05:00

256 lines
11 KiB
Dart

import 'package:fbla_ui/main.dart';
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:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
class JobListingDetail extends StatefulWidget {
final JobListing listing;
final Business fromBusiness;
const JobListingDetail(
{super.key, required this.listing, required this.fromBusiness});
@override
State<JobListingDetail> createState() => _CreateBusinessDetailState();
}
class _CreateBusinessDetailState extends State<JobListingDetail> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.listing.name),
actions: _getActions(widget.listing, widget.fromBusiness),
),
body: _detailBody(widget.listing),
);
}
Widget _detailBody(JobListing listing) {
return ListView(
children: [
// Title, logo, desc, website
Center(
child: SizedBox(
width: 800,
child: Column(
children: [
Padding(
padding: const EdgeInsets.only(top: 4.0),
child: Card(
clipBehavior: Clip.antiAlias,
child: Column(
children: [
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: [
Text(
getNameFromJobType(listing.type!),
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: 26,
offset: const Offset(15, -5),
textColor: Colors.white,
backgroundColor:
getColorFromOfferType(listing.offerType!),
child: ClipRRect(
borderRadius: BorderRadius.circular(6.0),
child: Image.network(
'$apiAddress/logos/${listing.businessId}',
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('https://${listing.link!}'));
},
),
],
),
),
),
// Wage
if (listing.wage != null && listing.wage != '')
Card(
child: ListTile(
leading: const Icon(Icons.attach_money),
subtitle: Text(listing.wage!),
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}'));
},
),
],
),
),
],
),
),
),
],
);
}
List<Widget>? _getActions(JobListing listing, Business fromBusiness) {
if (loggedIn) {
return [
IconButton(
icon: const Icon(Icons.edit),
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => CreateEditJobListing(
inputJobListing: listing,
inputBusiness: fromBusiness,
)));
},
),
IconButton(
icon: const Icon(Icons.delete),
onPressed: () {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
backgroundColor: Theme.of(context).colorScheme.surface,
title: const Text('Are You Sure?'),
content:
Text('This will permanently delete ${listing.name}.'),
actions: [
TextButton(
child: const Text('Cancel'),
onPressed: () {
Navigator.of(context).pop();
}),
TextButton(
child: const Text('Yes'),
onPressed: () async {
String? deleteResult =
await deleteListing(listing.id!);
if (deleteResult != null) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
width: 300,
behavior: SnackBarBehavior.floating,
content: Text(deleteResult)));
} else {
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => const MainApp()));
}
}),
],
);
});
},
),
];
}
return null;
}
}