Skip to content

Commit

Permalink
Lulin/task/add reference link (#81)
Browse files Browse the repository at this point in the history
  • Loading branch information
Ida631 authored Dec 18, 2024
1 parent 16d6209 commit b7cae81
Show file tree
Hide file tree
Showing 8 changed files with 83 additions and 14 deletions.
4 changes: 2 additions & 2 deletions lib/presentation/settings/viewModels/settings_view_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -221,10 +221,10 @@ class SettingsViewModel extends ChangeNotifier {
}
}

Future<String> submitApplication(String reason) async {
Future<String> submitApplication(String reason, String link) async {
String result = '';
try {
submission = await userUserCase.submitApplication(reason);
submission = await userUserCase.submitApplication(reason, link);
if (submission == 'success') {
result = 'Application successfully submitted. Please wait for approval.';
return result;
Expand Down
50 changes: 46 additions & 4 deletions lib/presentation/settings/views/apply_expert_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,43 @@ class ApplyExpertPage extends StatefulWidget {

class _ApplyExpertPage extends State<ApplyExpertPage> {
final TextEditingController _reasonController = TextEditingController();
final TextEditingController _profileLinkController = TextEditingController();
bool _isLoading = false;

@override
@override
void dispose() {
_reasonController.dispose();
_profileLinkController.dispose();
super.dispose();
}


bool _isUrlValid(String url) {
final urlPattern =
r'^(https?:\/\/)?(www\.)?([a-zA-Z0-9-_]+\.)+[a-zA-Z]{2,}(:\d+)?(\/.*)?$';
return RegExp(urlPattern).hasMatch(url);
}


Future<void> _submitApplication() async {
final profileLink = _profileLinkController.text;

if (profileLink.isNotEmpty && !_isUrlValid(profileLink)) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("Please enter a valid URL.")),
);
return;
}

setState(() {
_isLoading = true;
});

try {
// Access the view model and submit the application
final viewModel = Provider.of<SettingsViewModel>(context, listen: false);
final result = await viewModel.submitApplication(_reasonController.text);
final result = await viewModel.submitApplication(_reasonController.text, profileLink);

if (result == 'Application successfully submitted. Please wait for approval.' ||
result == 'This user has already submitted an expert application. Please wait for approval.' ||
Expand All @@ -56,7 +76,7 @@ class _ApplyExpertPage extends State<ApplyExpertPage> {
await Future.delayed(Duration(milliseconds: 300)); // Optional delay
Navigator.pop(context, 'submit'); // Navigate back after dialog interaction
} catch (error) {
// Show error message if update fails
print("Submission error: $error"); // Log the error for debugging
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("Failed to submit: $error")),
);
Expand All @@ -70,14 +90,24 @@ class _ApplyExpertPage extends State<ApplyExpertPage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text("Expert Application")),
appBar: AppBar(title: const Text("Expert Applications")),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Reason (optional):",
"Filling these fields will increase your chances of approval and speed up the process.",
style: TextStyle(
fontSize: 16, // Slightly larger text
fontWeight: FontWeight.w500, // Medium weight for emphasis
color: Colors.blueAccent, // Use a subtle blue color for emphasis
),
textAlign: TextAlign.center, // Center the text horizontally
),
SizedBox(height: 25.0),
Text(
"Reason:",
style: TextStyle(fontSize: 16.0),
),
TextFormField(
Expand All @@ -87,6 +117,18 @@ class _ApplyExpertPage extends State<ApplyExpertPage> {
),
),
SizedBox(height: 20.0),
Text(
"LinkedIn or Other Professional Profile Link:",
style: TextStyle(fontSize: 16.0),
),
TextFormField(
controller: _profileLinkController,
decoration: InputDecoration(
hintText: "a link to showcase your professional work...",
),
keyboardType: TextInputType.url, // URL-specific keyboard
),
SizedBox(height: 20.0),
_isLoading
? Center(child: CircularProgressIndicator()) // Center the loading indicator
: Center(
Expand Down
30 changes: 26 additions & 4 deletions lib/presentation/settings/views/manage_composite_experts_page.dart
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@


import 'package:domain/entities/application.dart';
import 'package:domain/entities/user.dart';
import 'package:flutter/material.dart';

import 'package:provider/provider.dart';

import '../viewModels/manage_composite_experts_view_model.dart';
import 'package:url_launcher/url_launcher.dart';

class ManageCompositeExpertsPage extends StatefulWidget {
const ManageCompositeExpertsPage({Key? key}) : super(key: key);
Expand All @@ -28,6 +27,7 @@ class _ManageCompositeExpertsPageState extends State<ManageCompositeExpertsPage>
}



@override
Widget build(BuildContext context) {
return Scaffold(
Expand All @@ -52,8 +52,30 @@ class _ManageCompositeExpertsPageState extends State<ManageCompositeExpertsPage>
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("Reason: ${application?.reason}"),
Text("User ID: ${application?.userId}"),
Text("Reason: ${application?.reason?.isNotEmpty == true ? application?.reason : "Not available"}", ),
application?.link?.isNotEmpty == true
? GestureDetector(
onTap: () async {
final Uri uri = Uri.parse(application!.link!);
if (!await launchUrl(uri, mode: LaunchMode.externalApplication)) {
throw 'Could not launch ${application.link}';
}
},
child: RichText(
text: TextSpan(
text: "Profile Link: ", // The first part with black color
style: const TextStyle(color: Colors.black), // Style for "Profile Link:"
children: [
TextSpan(
text: application.link, // The link with blue color
style: const TextStyle(color: Colors.blue),
),
],
),
)
)
: const Text("Profile Link: Not available"),

FutureBuilder<User>(
future: userFuture, // Call your function
builder: (context, snapshot) {
Expand Down
3 changes: 2 additions & 1 deletion packages/data/lib/repositories/user_repository_impl.dart
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ class UserRepositoryImpl implements UserRepository {
}

@override
Future<String> submitApplication(String? reason) async {
Future<String> submitApplication(String? reason, String? link) async {
final baseURL = await apiEnvironment.getBaseUrl();
final url = Uri.parse('$baseURL/experts/register-expert');
final response = await authClient.post(
Expand All @@ -78,6 +78,7 @@ class UserRepositoryImpl implements UserRepository {
body: jsonEncode(
{
if (reason != null) 'reason': reason,
if (link != null) 'link': link,
},
),
);
Expand Down
3 changes: 3 additions & 0 deletions packages/domain/lib/entities/application.dart
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
class CompositeExpertRequest {
final int userId;
String? reason;
String? link;


CompositeExpertRequest({
required this.userId,
this.reason,
this.link
});

// Factory constructor to create a User instance from JSON
factory CompositeExpertRequest.fromJson(Map<String, dynamic> json) {
return CompositeExpertRequest(
userId: json['userId'],
reason: json['reason'] ?? '',
link: json['link'] ?? '',
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ abstract class UserRepository {
Future<User> fetchMe();
Future<void> updateMe(String newName);
Future<void> deleteAccount();
Future<String> submitApplication(String? reason);
Future<String> submitApplication(String? reason, String? link);
Future<User> getUserById(int userId);
Future<void> becomeExpert(int userId);
}
4 changes: 2 additions & 2 deletions packages/domain/lib/usecases/user_usercase.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ class UserUseCase {
await tokenProvider.deleteToken();
}

Future<String> submitApplication(String? reason) async{
String result = await repository.submitApplication(reason);
Future<String> submitApplication(String? reason, String? link) async{
String result = await repository.submitApplication(reason, link);
return result;
}

Expand Down
1 change: 1 addition & 0 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ dependencies:




dev_dependencies:
flutter_test:
sdk: flutter
Expand Down

0 comments on commit b7cae81

Please sign in to comment.