tourist partly done

This commit is contained in:
LilleBRG 2024-09-13 09:59:21 +02:00
parent 8b3da8ff6e
commit 4100a51194
17 changed files with 176 additions and 20 deletions

1
.gitignore vendored
View File

@ -3,3 +3,4 @@ API/bin
API/obj API/obj
.idea .idea
/rust-backend/.env.example

3
Mobile/.gitignore vendored
View File

@ -43,4 +43,5 @@ app.*.map.json
/android/app/release /android/app/release
environment.json environment.json
node_modules node_modules
.env

View File

@ -1,5 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:mobile/api.dart' as api; import 'package:mobile/services/api.dart' as api;
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
import 'variables.dart'; import 'variables.dart';
@ -96,7 +96,7 @@ class _SideMenuState extends State<SideMenu> {
Navigator.pushReplacementNamed(context, '/favorites'); Navigator.pushReplacementNamed(context, '/favorites');
}, },
), ),
ListTile( ListTile(
title: const Text('Profile'), title: const Text('Profile'),
leading: const Icon(Icons.person), leading: const Icon(Icons.person),
selected: _selectedIndex == 2, selected: _selectedIndex == 2,
@ -104,6 +104,14 @@ class _SideMenuState extends State<SideMenu> {
Navigator.pushReplacementNamed(context, '/profile'); Navigator.pushReplacementNamed(context, '/profile');
}, },
), ),
ListTile(
title: const Text('GuideBook'),
leading: const Icon(Icons.person),
selected: _selectedIndex == 5,
onTap: () {
Navigator.pushReplacementNamed(context, '/tourist-guide-book');
},
),
const Divider( const Divider(
color: Colors.grey, color: Colors.grey,
thickness: 2, thickness: 2,

View File

@ -4,7 +4,7 @@ import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart'; import 'package:image_picker/image_picker.dart';
import 'package:mobile/base/sidemenu.dart'; import 'package:mobile/base/sidemenu.dart';
import 'models.dart' as models; import 'models.dart' as models;
import 'api.dart' as api; import 'services/api.dart' as api;
import 'package:path/path.dart' as path; import 'package:path/path.dart' as path;
class CreateReviewPage extends StatefulWidget { class CreateReviewPage extends StatefulWidget {

View File

@ -4,7 +4,7 @@ import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart'; import 'package:image_picker/image_picker.dart';
import 'package:mobile/models.dart' as models; import 'package:mobile/models.dart' as models;
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import 'api.dart' as api; import 'services/api.dart' as api;
import 'base/variables.dart'; import 'base/variables.dart';
class EditProfilePage extends StatefulWidget { class EditProfilePage extends StatefulWidget {

View File

@ -1,5 +1,5 @@
import 'dart:convert'; import 'dart:convert';
import 'api.dart' as api; import 'services/api.dart' as api;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'base/sidemenu.dart'; // Import the base layout widget import 'base/sidemenu.dart'; // Import the base layout widget
import 'models.dart'; import 'models.dart';

View File

@ -4,7 +4,7 @@ import 'package:mobile/models.dart' as models;
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
import 'dart:convert'; import 'dart:convert';
import 'api.dart' as api; import 'services/api.dart' as api;
import 'base/variables.dart'; import 'base/variables.dart';
class LoginPage extends StatefulWidget { class LoginPage extends StatefulWidget {

View File

@ -8,13 +8,14 @@ import 'package:mobile/createreview.dart';
import 'package:mobile/favorites.dart'; import 'package:mobile/favorites.dart';
import 'package:mobile/register.dart'; import 'package:mobile/register.dart';
import 'package:mobile/reviewlist.dart'; import 'package:mobile/reviewlist.dart';
import 'package:mobile/touristguidebook.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import 'login.dart'; import 'login.dart';
import 'base/sidemenu.dart'; import 'base/sidemenu.dart';
import 'profile.dart'; import 'profile.dart';
import 'models.dart'; import 'models.dart';
import 'package:geolocator/geolocator.dart'; import 'package:geolocator/geolocator.dart';
import 'api.dart' as api; import 'services/api.dart' as api;
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
void main() async { void main() async {
@ -48,6 +49,7 @@ class MyApp extends StatelessWidget {
'/register': (context) => const RegisterPage(), '/register': (context) => const RegisterPage(),
'/reviews': (context) => const ReviewListPage(), '/reviews': (context) => const ReviewListPage(),
'/create-review': (context) => const CreateReviewPage(), '/create-review': (context) => const CreateReviewPage(),
'/tourist-guide-book': (context) => const TouristGuideBookPage(),
}, },
); );
} }

View File

@ -4,7 +4,7 @@ import 'package:mobile/base/variables.dart';
import 'package:mobile/models.dart' as models; import 'package:mobile/models.dart' as models;
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import 'base/sidemenu.dart'; import 'base/sidemenu.dart';
import 'api.dart' as api; import 'services/api.dart' as api;
import 'editprofile.dart'; import 'editprofile.dart';
class ProfilePage extends StatefulWidget { class ProfilePage extends StatefulWidget {

View File

@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
import 'package:mobile/base/sidemenu.dart'; import 'package:mobile/base/sidemenu.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
import 'package:mobile/base/variables.dart'; import 'package:mobile/base/variables.dart';
import 'api.dart' as api; import 'services/api.dart' as api;
class RegisterPage extends StatefulWidget { class RegisterPage extends StatefulWidget {
const RegisterPage({super.key}); const RegisterPage({super.key});

View File

@ -2,7 +2,7 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:mobile/base/sidemenu.dart'; import 'package:mobile/base/sidemenu.dart';
import 'models.dart' as models; import 'models.dart' as models;
import 'api.dart' as api; import 'services/api.dart' as api;
class ReviewListPage extends StatefulWidget { class ReviewListPage extends StatefulWidget {
const ReviewListPage({super.key}); const ReviewListPage({super.key});

View File

@ -193,5 +193,3 @@ void logout() async {
prefs.remove('refresh-token'); prefs.remove('refresh-token');
prefs.remove('id'); prefs.remove('id');
} }
//------------------------------OPENAI API------------------------------//

View File

@ -0,0 +1,49 @@
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:flutter_dotenv/flutter_dotenv.dart';
class OpenAIService {
static Future<Map<String, dynamic>> getGuideBook(String country) async {
final apiKey = dotenv.env['OPENAI_API_KEY'];
final uri = Uri.parse('https://api.openai.com/v1/chat/completions');
final requestBody = jsonEncode({
"model": "gpt-4o-mini",
"messages": [
{
"role": "system",
"content": "You are a Tourist-guide book that makes a guidebook over a given country and further instructions in the message."
},
{
"role": "user",
"content": "Make a tourist guide book over $country. The topics should be: A little introduction to how the people of the country is like and what to expect from the environment, famous tourist attractions in the country(amusement park always included), Basic words that would be nice to learn in the country's language(should always be from English to the country's language) and transportation. These topics should be in a Json-Object format."
}
],
});
final response = await http.post(
uri,
headers: {
'Authorization': 'Bearer $apiKey',
'Content-Type': 'application/json',
},
body: requestBody,
);
if (response.statusCode == 200) {
try {
return jsonDecode(response.body);
} catch (e) {
return {
'navn': 'Fejl',
'art': 'Ukendt',
'type': 'Fejl',
'description': 'Fejl ved JSON parsing: $e'
};
}
} else {
throw Exception('Fejl ved hentning af data: ${response.statusCode}');
}
}
}

View File

@ -0,0 +1,86 @@
import 'package:dropdown_search/dropdown_search.dart';
import 'package:flutter/material.dart';
import 'package:mobile/base/sidemenu.dart';
import 'package:mobile/models.dart' as models;
import 'package:shared_preferences/shared_preferences.dart';
import 'package:google_fonts/google_fonts.dart';
import 'dart:convert';
import 'services/openaiservice.dart' as api;
import 'base/variables.dart';
class TouristGuideBookPage extends StatefulWidget {
const TouristGuideBookPage({super.key});
@override
State<TouristGuideBookPage> createState() => _TouristGuideBookPageState();
}
class _TouristGuideBookPageState extends State<TouristGuideBookPage> {
String? _selectedCountry;
final List<String> countries = [
"Afghanistan", "Albania", "Algeria", "Andorra", "Angola", "Argentina",
// Add more countries
];
Future<void> getBook() async {
if (_selectedCountry != null) {
final response = await api.OpenAIService.getGuideBook(_selectedCountry!);
print(response); // For debugging to check the response
} else {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Choose a country')),
);
}
}
@override
Widget build(BuildContext context) {
return SideMenu(
selectedIndex: 5,
body: Scaffold(
appBar: AppBar(
title: Text('Select Country'),
),
body: Center(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
DropdownSearch<String>(
items: countries,
popupProps: const PopupProps.menu(
showSearchBox: true,
searchFieldProps: TextFieldProps(
decoration: InputDecoration(
labelText: "Search a country",
border: OutlineInputBorder(),
),
),
),
dropdownDecoratorProps: const DropDownDecoratorProps(
dropdownSearchDecoration: InputDecoration(
labelText: "Select a country",
hintText: "Search a country",
border: OutlineInputBorder(),
),
),
onChanged: (String? country) {
setState(() {
_selectedCountry = country;
});
},
selectedItem: "Select a country you want a touristbook for",
),
ElevatedButton(
onPressed: getBook,
child: Text('Get Guidebook'),
),
],
),
),
),
),
);
}
}

View File

@ -73,6 +73,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.1.0" version: "1.1.0"
dropdown_search:
dependency: "direct main"
description:
name: dropdown_search
sha256: "55106e8290acaa97ed15bea1fdad82c3cf0c248dd410e651f5a8ac6870f783ab"
url: "https://pub.dev"
source: hosted
version: "5.0.6"
fake_async: fake_async:
dependency: transitive dependency: transitive
description: description:
@ -142,6 +150,14 @@ packages:
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.0" version: "0.0.0"
flutter_dotenv:
dependency: "direct main"
description:
name: flutter_dotenv
sha256: "9357883bdd153ab78cbf9ffa07656e336b8bbb2b5a3ca596b0b27e119f7c7d77"
url: "https://pub.dev"
source: hosted
version: "5.1.0"
flutter_image_compress: flutter_image_compress:
dependency: "direct main" dependency: "direct main"
description: description:

View File

@ -43,6 +43,8 @@ dependencies:
geolocator: ^13.0.1 geolocator: ^13.0.1
image_picker: ^1.1.2 image_picker: ^1.1.2
flutter_image_compress: ^2.3.0 flutter_image_compress: ^2.3.0
flutter_dotenv: ^5.1.0
dropdown_search: ^5.0.6
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:

View File

@ -1,7 +0,0 @@
JWT_SECRET=DenHerMåAldrigVæreOffentligKunIDetteDemoProjekt
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_ENDPOINT_URL=
AWS_REGION=
R2_BUCKET_NAME=
R2_BUCKET_URL=