Skip to content

Commit 2a84e94

Browse files
committed
Add username display and answers under questions #17
1 parent caa87f3 commit 2a84e94

3 files changed

Lines changed: 268 additions & 225 deletions

File tree

app/api_service.dart

Lines changed: 73 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -2,59 +2,60 @@ import 'package:http/http.dart' as http;
22
import 'dart:convert';
33

44
class ApiService {
5-
//main server URL on Fly.io
6-
final String baseUrl = 'https://unstuck.fly.dev/api';
5+
//main server URL on Fly.io
6+
final String baseUrl = 'https://unstuck.fly.dev/api';
77

8-
//Check if server is running
9-
Future<bool> checkServer() async {
10-
try {
11-
final response = await http.get(Uri.parse('$baseUrl/'));
12-
return response.statusCode == 200;
13-
} catch (e) {
14-
return false;
15-
}
16-
}
17-
18-
// == Login ==
19-
20-
Future<bool> registerUser(String username, String password) async {
21-
try {
22-
final response = await http.post(
23-
Uri.parse('$baseUrl/register'),
24-
headers: {'Content-Type': 'application/json'},
25-
body: jsonEncode({
26-
'username': username,
27-
'password': password,
28-
}),
29-
);
30-
return response.statusCode == 201;
31-
} catch (e) {
32-
print('Registration error: $e');
33-
return false;
34-
}
35-
}
36-
37-
Future<bool> loginUser(String username, String password) async {
38-
try {
39-
final response = await http.post(
40-
Uri.parse('$baseUrl/login'),
41-
42-
headers: {'Content-Type': 'application/json'},
43-
body: jsonEncode({
44-
'username': username,
45-
'password': password,
46-
}),
47-
);
48-
return response.statusCode == 200;
49-
} catch (e) {
50-
print('Login error: $e');
51-
return false; // Return false if the request fails
52-
}
53-
}
54-
55-
// == Query and Answer ==
8+
//Check if server is running
9+
Future<bool> checkServer() async {
10+
try {
11+
final response = await http.get(Uri.parse('https://unstuck.fly.dev/'));
12+
return response.statusCode == 200;
13+
} catch (e) {
14+
return false;
15+
}
16+
}
5617

57-
// - Read from the DB -
18+
// == Login ==
19+
20+
Future<bool> registerUser(String username, String password) async {
21+
try {
22+
final response = await http.post(
23+
Uri.parse('$baseUrl/register'),
24+
headers: {'Content-Type': 'application/json'},
25+
body: jsonEncode({
26+
'username': username,
27+
'password': password,
28+
}),
29+
);
30+
return response.statusCode == 201;
31+
} catch (e) {
32+
print('Registration error: $e');
33+
return false;
34+
}
35+
}
36+
37+
Future<String?> loginUser(String username, String password) async {
38+
try {
39+
final response = await http.post(
40+
Uri.parse('$baseUrl/login'),
41+
headers: {'Content-Type': 'application/json'},
42+
body: jsonEncode({
43+
'username': username,
44+
'password': password,
45+
}),
46+
);
47+
if (response.statusCode == 200) {
48+
final data = jsonDecode(response.body);
49+
return data['user']['username'];
50+
}
51+
return null;
52+
} catch (e) {
53+
print('Login error: $e');
54+
return null;
55+
}
56+
}
57+
58+
// == Read from the DB ==
5859

5960
//Get all inquiries from database
6061
Future<List> getInquiries() async {
@@ -83,32 +84,31 @@ class ApiService {
8384
return [];
8485
}
8586
}
86-
87-
//- New entry to DB -
87+
88+
//== New entry to DB ==
8889

8990
//POST - Add an inquiry to the database
9091
Future<bool> addInquiry(String title, String body) async {
91-
try {
92-
final response = await http.post(
93-
Uri.parse('$baseUrl/create-entry'),
94-
headers: {'Content-Type': 'application/json'},
95-
body: jsonEncode({
96-
'resource': 'inquiries',
97-
'data': {
98-
'body': body,
99-
'title': title,
100-
'chosen_answer_id': null,
101-
'is_solved': false,
102-
},
103-
}),
104-
);
105-
106-
return response.statusCode == 200;
107-
} catch (e) {
108-
print('Error: $e');
109-
return false;
92+
try {
93+
final response = await http.post(
94+
Uri.parse('$baseUrl/create-entry'),
95+
headers: {'Content-Type': 'application/json'},
96+
body: jsonEncode({
97+
'resource': 'inquiries',
98+
'data': {
99+
'body': body,
100+
'title': title,
101+
'chosen_answer_id': null,
102+
'is_solved': false,
103+
},
104+
}),
105+
);
106+
return response.statusCode == 200;
107+
} catch (e) {
108+
print('Error: $e');
109+
return false;
110+
}
110111
}
111-
}
112112

113113
//POST - Add an answer to the db
114114
Future<bool> addAnswer(int inquiryId, String answerText) async {
@@ -124,12 +124,10 @@ class ApiService {
124124
},
125125
}),
126126
);
127-
128127
return response.statusCode == 200;
129128
} catch (e) {
130129
print('Error sending answer: $e');
131130
return false;
132131
}
133132
}
134-
135133
}

app/pages/home_page.dart

Lines changed: 59 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import 'package:flutter/material.dart';
22
import '../api_service.dart';
33
import 'ask_page.dart';
4+
import 'login_page.dart';
45

56
class HomePage extends StatefulWidget {
6-
const HomePage({super.key});
7+
final String username;
8+
const HomePage({super.key, required this.username});
79

810
@override
911
State<HomePage> createState() => _HomePageState();
@@ -12,6 +14,7 @@ class HomePage extends StatefulWidget {
1214
class _HomePageState extends State<HomePage> {
1315
final ApiService api = ApiService();
1416
List inquiries = [];
17+
List answers = [];
1518

1619
@override
1720
void initState() {
@@ -20,12 +23,18 @@ class _HomePageState extends State<HomePage> {
2023
}
2124

2225
Future<void> loadData() async {
23-
List data = await api.getInquiries();
26+
List inqData = await api.getInquiries();
27+
List ansData = await api.getAnswers();
2428
setState(() {
25-
inquiries = data;
29+
inquiries = inqData;
30+
answers = ansData;
2631
});
2732
}
2833

34+
List getAnswersForInquiry(int inquiryId) {
35+
return answers.where((a) => a['inquiry_id'] == inquiryId).toList();
36+
}
37+
2938
@override
3039
Widget build(BuildContext context) {
3140
return Scaffold(
@@ -36,18 +45,21 @@ class _HomePageState extends State<HomePage> {
3645
child: ListView(
3746
padding: EdgeInsets.zero,
3847
children: [
39-
const DrawerHeader(
40-
decoration: BoxDecoration(color: Colors.deepPurple),
48+
DrawerHeader(
49+
decoration: const BoxDecoration(color: Colors.deepPurple),
4150
child: Column(
4251
crossAxisAlignment: CrossAxisAlignment.start,
4352
mainAxisAlignment: MainAxisAlignment.end,
4453
children: [
45-
CircleAvatar(
54+
const CircleAvatar(
4655
radius: 30,
4756
child: Icon(Icons.person, size: 30),
4857
),
49-
SizedBox(height: 8),
50-
Text('User Name', style: TextStyle(color: Colors.white, fontSize: 16)),
58+
const SizedBox(height: 8),
59+
Text(
60+
widget.username,
61+
style: const TextStyle(color: Colors.white, fontSize: 16),
62+
),
5163
],
5264
),
5365
),
@@ -71,7 +83,11 @@ class _HomePageState extends State<HomePage> {
7183
leading: const Icon(Icons.logout),
7284
title: const Text('Sign out'),
7385
onTap: () {
74-
Navigator.popUntil(context, (route) => route.isFirst);
86+
Navigator.pushAndRemoveUntil(
87+
context,
88+
MaterialPageRoute(builder: (context) => const LoginPage()),
89+
(route) => false,
90+
);
7591
},
7692
),
7793
],
@@ -81,10 +97,40 @@ class _HomePageState extends State<HomePage> {
8197
itemCount: inquiries.length,
8298
itemBuilder: (context, index) {
8399
final item = inquiries[index];
84-
return ListTile(
85-
leading: const CircleAvatar(child: Icon(Icons.person)),
86-
title: Text(item['title'] ?? 'No title'),
87-
subtitle: Text(item['body'] ?? ''),
100+
final inquiryAnswers = getAnswersForInquiry(item['inquiry_id']);
101+
return Card(
102+
margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
103+
child: Padding(
104+
padding: const EdgeInsets.all(8.0),
105+
child: Column(
106+
crossAxisAlignment: CrossAxisAlignment.start,
107+
children: [
108+
Row(
109+
children: [
110+
const CircleAvatar(
111+
radius: 16,
112+
child: Icon(Icons.person, size: 16),
113+
),
114+
const SizedBox(width: 8),
115+
Text(
116+
item['title'] ?? 'No title',
117+
style: const TextStyle(fontWeight: FontWeight.bold),
118+
),
119+
],
120+
),
121+
const SizedBox(height: 4),
122+
Text(item['body'] ?? ''),
123+
if (inquiryAnswers.isNotEmpty) ...[
124+
const Divider(),
125+
const Text('Answers:', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 12)),
126+
...inquiryAnswers.map((answer) => Padding(
127+
padding: const EdgeInsets.only(top: 4, left: 8),
128+
child: Text('• ${answer['body']}'),
129+
)),
130+
],
131+
],
132+
),
133+
),
88134
);
89135
},
90136
),

0 commit comments

Comments
 (0)