Skip to content

Commit ec045c3

Browse files
authored
Merge pull request #270 from mdgspace/casper/hostel_change
feat: Adds Hostel Change UI and API
2 parents e57147a + 83bbc57 commit ec045c3

File tree

16 files changed

+690
-30
lines changed

16 files changed

+690
-30
lines changed

lib/data/constants/api_endpoints.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,5 @@ class ApiEndpoints {
4040
static const String oAuthRedirect = '/api/user/oauth/omniport/redirect/';
4141
static const String oAuthComplete = '/api/user/oauth/complete/';
4242
static const String notifications = '/api/user/message/list/';
43+
static const String hostelChange = '/api/user/hostel-change/';
4344
}

lib/data/core/router/registry/paths.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ class AppPathsRegistry {
1616
static const String weekMenu = 'weekMenu';
1717
static const String leavesAndRebate = 'leavesAndRebate';
1818
static const String feedback = 'feedback';
19+
static const String hostelChange = 'hostelChange';
1920
static const String resetPassword = 'resetPassword';
2021

2122
static const String noInternetWrapper = '/noInternetWrapper';

lib/data/core/router/registry/routes.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ class AppRoutesRegistry {
5959
path: AppPathsRegistry.resetPassword,
6060
page: ResetPasswordRoute.page,
6161
),
62+
CustomRoute(
63+
path: AppPathsRegistry.hostelChange,
64+
page: HostelChangeRoute.page,
65+
),
6266
],
6367
),
6468
CustomRoute(

lib/data/services/remote/api_service.dart

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import 'package:appetizer/domain/models/appetizer_version.dart';
33
import 'package:appetizer/domain/models/coupon/coupon.dart';
44
import 'package:appetizer/domain/models/feedback/appetizer_feedback.dart';
55
import 'package:appetizer/domain/models/feedback/feedback_response.dart';
6+
import 'package:appetizer/domain/models/hostel_change_request/hostel_change_request.dart';
67
import 'package:appetizer/domain/models/leaves/paginated_leaves.dart';
78
import 'package:appetizer/domain/models/menu/week_menu_tmp.dart';
89
import 'package:appetizer/domain/models/transaction/faq.dart';
@@ -181,4 +182,15 @@ abstract class ApiService {
181182

182183
@GET(ApiEndpoints.notifications)
183184
Future getNotifications();
185+
186+
@POST(ApiEndpoints.hostelChange)
187+
Future<void> postChangeHostel(
188+
@Body() Map<String, dynamic> map,
189+
);
190+
191+
@GET(ApiEndpoints.hostelChange)
192+
Future<HostelChangeRequest> getHostelChangeStatus();
193+
194+
@DELETE(ApiEndpoints.hostelChange)
195+
Future deleteChangeHostel();
184196
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import 'package:freezed_annotation/freezed_annotation.dart';
2+
3+
part 'hostel_change_request.freezed.dart';
4+
part 'hostel_change_request.g.dart';
5+
6+
@freezed
7+
class HostelChangeRequest with _$HostelChangeRequest {
8+
@JsonSerializable(fieldRename: FieldRename.snake)
9+
const factory HostelChangeRequest(
10+
{required int user,
11+
required int id,
12+
required String hostelCode,
13+
required String newRoomNo,
14+
bool? isApprovedByAdmin,
15+
required String timestamp,
16+
required int newHostel}) = _HostelChangeRequest;
17+
18+
factory HostelChangeRequest.fromJson(Map<String, dynamic> json) =>
19+
_$HostelChangeRequestFromJson(json);
20+
}

lib/domain/repositories/user/user_repository.dart

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,4 +154,35 @@ class UserRepository {
154154
throw Failure(AppConstants.GENERIC_FAILURE);
155155
}
156156
}
157+
158+
Future<void> postChangeHostel(String hostelCode, String roomNo) async {
159+
Map<String, dynamic> map = {
160+
'new_hostel_code': hostelCode,
161+
'new_room_no': roomNo
162+
};
163+
try {
164+
return await _apiService.postChangeHostel(map);
165+
} catch (e) {
166+
debugPrint(e.toString());
167+
throw Failure(AppConstants.GENERIC_FAILURE);
168+
}
169+
}
170+
171+
Future<dynamic> getHostelChangeStatus() async {
172+
try {
173+
return await _apiService.getHostelChangeStatus();
174+
} catch (e) {
175+
debugPrint(e.toString());
176+
throw Failure(AppConstants.GENERIC_FAILURE);
177+
}
178+
}
179+
180+
Future<dynamic> deleteChangeHostel() async {
181+
try {
182+
return await _apiService.deleteChangeHostel();
183+
} catch (e) {
184+
debugPrint(e.toString());
185+
throw Failure(AppConstants.GENERIC_FAILURE);
186+
}
187+
}
157188
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import 'dart:async';
2+
3+
import 'package:appetizer/data/constants/constants.dart';
4+
import 'package:appetizer/domain/repositories/user/user_repository.dart';
5+
import 'package:bloc/bloc.dart';
6+
import 'package:equatable/equatable.dart';
7+
8+
part 'hostel_change_event.dart';
9+
part 'hostel_change_state.dart';
10+
11+
class HostelChangeBloc extends Bloc<HostelChangeEvent, HostelChangeState> {
12+
final UserRepository repo;
13+
HostelChangeBloc({required this.repo}) : super(const HostelChangeInitial()) {
14+
on<HostelChangePressed>(_onHostelChangePressed);
15+
on<HostelSearchQueryChanged>(_onHostelSearchQueryChanged);
16+
}
17+
18+
FutureOr<void> _onHostelChangePressed(
19+
HostelChangePressed event, Emitter<HostelChangeState> emit) async {
20+
emit(Loading());
21+
String hostel = event.hostel;
22+
String roomNo = event.roomNo;
23+
if (hostel == "") {
24+
emit(const HostelChangeInitial(error: "Please select a hostel"));
25+
return;
26+
}
27+
if (roomNo == "") {
28+
emit(const HostelChangeInitial(error: "Please enter a room number"));
29+
if (hostel != "") emit(HostelQueryChanged(query: hostel));
30+
return;
31+
}
32+
try {
33+
await repo.postChangeHostel(hostel, roomNo);
34+
emit(HostelChangeSuccess());
35+
} catch (e) {
36+
emit(const HostelChangeInitial(error: AppConstants.GENERIC_FAILURE));
37+
}
38+
}
39+
40+
FutureOr<void> _onHostelSearchQueryChanged(
41+
HostelSearchQueryChanged event, Emitter<HostelChangeState> emit) async {
42+
if (event.query == "") {
43+
emit(const HostelChangeInitial());
44+
} else {
45+
emit(Loading());
46+
emit(HostelQueryChanged(query: event.query));
47+
}
48+
// emit(const HostelChangeInitial());
49+
}
50+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
part of 'hostel_change_bloc.dart';
2+
3+
abstract class HostelChangeEvent {}
4+
5+
class HostelChangePressed extends HostelChangeEvent {
6+
final String hostel;
7+
final String roomNo;
8+
HostelChangePressed({
9+
required this.hostel,
10+
required this.roomNo,
11+
});
12+
}
13+
14+
class HostelSearchQueryChanged extends HostelChangeEvent {
15+
final String query;
16+
HostelSearchQueryChanged({
17+
required this.query,
18+
});
19+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
part of 'hostel_change_bloc.dart';
2+
3+
abstract class HostelChangeState extends Equatable {
4+
const HostelChangeState();
5+
6+
@override
7+
List<Object?> get props => [];
8+
}
9+
10+
class HostelChangeInitial extends HostelChangeState {
11+
final String? error;
12+
const HostelChangeInitial({this.error});
13+
}
14+
15+
class Loading extends HostelChangeState {}
16+
17+
class HostelChangeSuccess extends HostelChangeState {}
18+
19+
class HostelQueryChanged extends HostelChangeState {
20+
final String query;
21+
const HostelQueryChanged({required this.query});
22+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import 'package:appetizer/app_theme.dart';
2+
import 'package:appetizer/data/core/theme/dimensional/dimensional.dart';
3+
import 'package:appetizer/presentation/components/app_banner.dart';
4+
import 'package:auto_route/auto_route.dart';
5+
import 'package:flutter/material.dart';
6+
7+
class HostelChangeBanner extends StatelessWidget {
8+
const HostelChangeBanner({super.key});
9+
10+
@override
11+
Widget build(BuildContext context) {
12+
return AppBanner(
13+
height: 140.toAutoScaledHeight,
14+
child: Row(
15+
children: [
16+
IconButton(
17+
onPressed: () => context.router.pop(),
18+
icon: const Icon(
19+
Icons.arrow_back,
20+
color: Colors.white,
21+
),
22+
),
23+
Text(
24+
"Hostel Change",
25+
style: AppTheme.headline1,
26+
),
27+
],
28+
),
29+
);
30+
}
31+
}

0 commit comments

Comments
 (0)