API Listing half-rewrite

This commit is contained in:
Drake Marino 2024-06-12 14:28:13 -05:00
parent 68edb2c3a1
commit 0a1250dfd2
2 changed files with 175 additions and 29 deletions

View File

@ -22,32 +22,33 @@ enum BusinessType {
other, other,
} }
enum JobType { cashier, server, mechanic }
class Business { class Business {
int id; int id;
String name; String name;
String description; String description;
BusinessType type; BusinessType? type;
String website; String? website;
String contactName; String? contactName;
String contactEmail; String? contactEmail;
String contactPhone; String? contactPhone;
String notes; String? notes;
String locationName; String? locationName;
String locationAddress; String? locationAddress;
Business({ Business(
required this.id, {required this.id,
required this.name, required this.name,
required this.description, required this.description,
required this.type, this.type,
required this.website, this.website,
required this.contactName, this.contactName,
required this.contactEmail, this.contactEmail,
required this.contactPhone, this.contactPhone,
required this.notes, this.notes,
required this.locationName, this.locationName,
required this.locationAddress, this.locationAddress});
});
factory Business.fromJson(Map<String, dynamic> json) { factory Business.fromJson(Map<String, dynamic> json) {
bool typeValid = true; bool typeValid = true;
@ -56,6 +57,7 @@ class Business {
} catch (e) { } catch (e) {
typeValid = false; typeValid = false;
} }
return Business( return Business(
id: json['id'], id: json['id'],
name: json['name'], name: json['name'],
@ -74,6 +76,22 @@ class Business {
} }
} }
class JobListing {
String name;
String description;
JobType type;
String wage;
String link;
JobListing({
required this.name,
required this.description,
required this.type,
required this.wage,
required this.link,
});
}
Future<String> fetchBusinessData() async { Future<String> fetchBusinessData() async {
final result = await postgres.query(''' final result = await postgres.query('''
SELECT json_agg( SELECT json_agg(
@ -93,9 +111,7 @@ Future<String> fetchBusinessData() async {
) FROM businesses ) FROM businesses
'''); ''');
var encoded = json.encode(result); var encoded = json.encode(result[0][0]);
var decoded = json.decode(encoded);
encoded = json.encode(decoded[0][0]);
return encoded; return encoded;
} }
@ -125,12 +141,92 @@ void main() async {
headers: {'Access-Control-Allow-Origin': '*'}, headers: {'Access-Control-Allow-Origin': '*'},
); );
}); });
app.get('/fbla-api/businessdata/overview', (Request request) async {
print('business overview request received');
var filters = request.url.queryParameters['filters']?.split(',') ??
JobType.values.asNameMap().keys;
// List<Map<String, List<Map<String, dynamic>>>> this is the real type lol
List<dynamic> output = [];
for (int i = 0; i < filters.length; i++) {
var postgresResult = (await postgres.query('''
SELECT json_agg(
json_build_object(
'id', id,
'name', name,
'description', description
)
) FROM public.businesses WHERE id IN (SELECT id FROM public.listings WHERE type='${filters.elementAt(i)}')
'''))[0][0];
if (postgresResult != null) {
output.add({filters.elementAt(i): postgresResult});
}
}
return Response.ok(
json.encode(output),
headers: {
'Access-Control-Allow-Origin': '*',
'Content-Type': 'text/plain'
},
);
});
app.get('/fbla-api/businessdata/business/<business>',
(Request request, String business) async {
print('idividual business data request received');
var result = (await postgres.query('''
SELECT
json_build_object(
'id', b.id,
'name', b.name,
'description', b.description,
'type', b.type,
'website', b.website,
'contactName', b."contactName",
'contactEmail', b."contactEmail",
'contactPhone', b."contactPhone",
'notes', b.notes,
'locationName', b."locationName",
'locationAddress', b."locationAddress",
'listings',
json_agg(
json_build_object(
'id', l.id,
'name', l.name,
'description', l.description,
'type', l.type,
'wage', l.wage,
'link', l.link
)
)
)
FROM businesses b
LEFT JOIN listings l ON b.id = l.business_id
WHERE b.id = $business
GROUP BY b.id;
'''))[0][0];
return Response.ok(
json.encode(result),
headers: {
'Access-Control-Allow-Origin': '*',
'Content-Type': 'text/plain'
},
);
});
app.get('/fbla-api/businessdata', (Request request) async { app.get('/fbla-api/businessdata', (Request request) async {
print('business data request received'); print('business data request received');
final output = await fetchBusinessData(); final output = await fetchBusinessData();
return Response.ok( return Response.ok(
output.toString(), output.toString(),
headers: {'Access-Control-Allow-Origin': '*'}, headers: {
'Access-Control-Allow-Origin': '*',
'Content-Type': 'text/plain'
},
); );
}); });
app.get('/fbla-api/logos/<logo>', (Request request, String logoId) { app.get('/fbla-api/logos/<logo>', (Request request, String logoId) {
@ -159,7 +255,7 @@ void main() async {
await postgres.query(''' await postgres.query('''
INSERT INTO businesses (name, description, type, website, "contactName", "contactPhone", "contactEmail", notes, "locationName", "locationAddress") INSERT INTO businesses (name, description, type, website, "contactName", "contactPhone", "contactEmail", notes, "locationName", "locationAddress")
VALUES ('${business.name.replaceAll("'", "''")}', '${business.description.replaceAll("'", "''")}', '${business.type.name}', '${business.website}', '${business.contactName.replaceAll("'", "''")}', '${business.contactPhone}', '${business.contactEmail}', '${business.notes.replaceAll("'", "''")}', '${business.locationName.replaceAll("'", "''")}', '${business.locationAddress.replaceAll("'", "''")}') VALUES ('${business.name.replaceAll("'", "''")}', '${business.description.replaceAll("'", "''")}', '${business.type!.name}', '${business.website!}', '${business.contactName!.replaceAll("'", "''")}', '${business.contactPhone!}', '${business.contactEmail!}', '${business.notes!.replaceAll("'", "''")}', '${business.locationName!.replaceAll("'", "''")}', '${business.locationAddress!.replaceAll("'", "''")}')
'''); ''');
final dbBusiness = await postgres.query('''SELECT * FROM public.businesses final dbBusiness = await postgres.query('''SELECT * FROM public.businesses
@ -237,7 +333,7 @@ void main() async {
await postgres.query(''' await postgres.query('''
UPDATE businesses SET UPDATE businesses SET
name = '${business.name.replaceAll("'", "''").replaceAll("\"", "\"\"")}'::text, description = '${business.description.replaceAll("'", "''").replaceAll("\"", "\"\"")}'::text, website = '${business.website}'::text, type = '${business.type.name}'::text, "contactName" = '${business.contactName.replaceAll("'", "''").replaceAll("\"", "\"\"")}'::text, "contactPhone" = '${business.contactPhone}'::text, "contactEmail" = '${business.contactEmail}'::text, notes = '${business.notes.replaceAll("'", "''").replaceAll("\"", "\"\"")}'::text, "locationName" = '${business.locationName.replaceAll("'", "''").replaceAll("\"", "\"\"")}'::text, "locationAddress" = '${business.locationAddress.replaceAll("'", "''").replaceAll("\"", "\"\"")}'::text WHERE name = '${business.name.replaceAll("'", "''").replaceAll("\"", "\"\"")}'::text, description = '${business.description.replaceAll("'", "''").replaceAll("\"", "\"\"")}'::text, website = '${business.website!}'::text, type = '${business.type!.name}'::text, "contactName" = '${business.contactName!.replaceAll("'", "''").replaceAll("\"", "\"\"")}'::text, "contactPhone" = '${business.contactPhone!}'::text, "contactEmail" = '${business.contactEmail!}'::text, notes = '${business.notes!.replaceAll("'", "''").replaceAll("\"", "\"\"")}'::text, "locationName" = '${business.locationName!.replaceAll("'", "''").replaceAll("\"", "\"\"")}'::text, "locationAddress" = '${business.locationAddress!.replaceAll("'", "''").replaceAll("\"", "\"\"")}'::text WHERE
id = ${business.id}; id = ${business.id};
'''); ''');
@ -445,4 +541,6 @@ void main() async {
final server = await io.serve(app, _hostname, _port); final server = await io.serve(app, _hostname, _port);
print('Serving at http://${server.address.host}:${server.port}'); print('Serving at http://${server.address.host}:${server.port}');
// print((await postgres.query('select testdouble from public.test')));
} }

View File

@ -26,6 +26,7 @@ class _CreateBusinessDetailState extends State<BusinessDetail> {
), ),
body: ListView( body: ListView(
children: [ children: [
// Title, logo, desc, website
Card( Card(
clipBehavior: Clip.antiAlias, clipBehavior: Clip.antiAlias,
child: Column( child: Column(
@ -41,8 +42,7 @@ class _CreateBusinessDetailState extends State<BusinessDetail> {
), ),
leading: ClipRRect( leading: ClipRRect(
borderRadius: BorderRadius.circular(6.0), borderRadius: BorderRadius.circular(6.0),
child: Image.network( child: Image.network('$apiAddress/logos/${business.id}',
'$apiAddress/logos/${business.id}',
width: 48, width: 48,
height: 48, errorBuilder: (BuildContext context, height: 48, errorBuilder: (BuildContext context,
Object exception, StackTrace? stackTrace) { Object exception, StackTrace? stackTrace) {
@ -63,6 +63,52 @@ class _CreateBusinessDetailState extends State<BusinessDetail> {
], ],
), ),
), ),
// 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(''));
},
),
],
),
]),
),
),
// Contact info
Visibility( Visibility(
visible: (business.contactEmail.isNotEmpty || visible: (business.contactEmail.isNotEmpty ||
business.contactPhone.isNotEmpty), business.contactPhone.isNotEmpty),
@ -138,6 +184,7 @@ class _CreateBusinessDetailState extends State<BusinessDetail> {
), ),
), ),
), ),
// Location
Visibility( Visibility(
child: Card( child: Card(
clipBehavior: Clip.antiAlias, clipBehavior: Clip.antiAlias,
@ -152,6 +199,7 @@ class _CreateBusinessDetailState extends State<BusinessDetail> {
), ),
), ),
), ),
// Notes
Visibility( Visibility(
visible: business.notes.isNotEmpty, visible: business.notes.isNotEmpty,
child: Card( child: Card(