Skip to content

Commit

Permalink
Merge pull request #47 from arafaysaleem/release
Browse files Browse the repository at this point in the history
Release 16/06/2021
  • Loading branch information
arafaysaleem authored Jun 16, 2021
2 parents ba5f591 + f068d31 commit acd1015
Show file tree
Hide file tree
Showing 31 changed files with 1,084 additions and 147 deletions.
2 changes: 1 addition & 1 deletion .github/labeler.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ repositories:
- any: ['lib/services/repositories/**/*']

interceptors:
- any: ['lib/services/interceptors/**/*']
- any: ['lib/services/networking/interceptors/**/*']

api:
- any: ['lib/services/networking/**/*api*']
Expand Down
3 changes: 3 additions & 0 deletions lib/helper/utils/constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ class Constants {
/// The color value for dark grey [CustomDialog] in the app.
static const Color barrierColor = Colors.black87;

/// The color value for light grey [CustomDialog] in the app.
static const Color barrierColorLight = Color(0xBF000000);

/// The TextStyle for Lato font in the app.
static TextStyle latoFont = GoogleFonts.lato().copyWith(color: Colors.black);

Expand Down
1 change: 1 addition & 0 deletions lib/helper/utils/custom_theme.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class CustomTheme {
/// * textButtonTheme: [TextButtonTheme] without the default padding,
static late final mainTheme = ThemeData(
primaryColor: Constants.primaryColor,
accentColor: Constants.primaryColor,
scaffoldBackgroundColor: Constants.scaffoldColor,
fontFamily: Constants.poppinsFont.fontFamily,
textTheme: TextTheme(
Expand Down
2 changes: 1 addition & 1 deletion lib/models/booking_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class BookingModel with _$BookingModel {
const factory BookingModel({
@JsonKey(toJson: Constants.toNull, includeIfNull: false) required int? bookingId,
@JsonKey(includeIfNull: false) required int? userId,
required int showId,
@JsonKey(includeIfNull: false) required int? showId,
@JsonKey(toJson: Constants.toNull, includeIfNull: false) String? seatRow,
@JsonKey(toJson: Constants.toNull, includeIfNull: false) int? seatNumber,
required double price,
Expand Down
3 changes: 2 additions & 1 deletion lib/models/user_booking_model.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'package:freezed_annotation/freezed_annotation.dart';

import 'booking_model.dart';
import 'user_booking_show_model.dart';

part 'user_booking_model.freezed.dart';
part 'user_booking_model.g.dart';
Expand All @@ -9,9 +10,9 @@ part 'user_booking_model.g.dart';
class UserBookingModel with _$UserBookingModel {
@JsonSerializable()
const factory UserBookingModel({
required int showId,
required String title,
required String posterUrl,
required UserBookingShowModel show,
required List<BookingModel> bookings,
}) = _UserBookingModel;

Expand Down
17 changes: 17 additions & 0 deletions lib/models/user_booking_show_model.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import 'package:freezed_annotation/freezed_annotation.dart';
import '../enums/show_type_enum.dart';

part 'user_booking_show_model.freezed.dart';
part 'user_booking_show_model.g.dart';

@freezed
class UserBookingShowModel with _$UserBookingShowModel {
@JsonSerializable(fieldRename: FieldRename.snake)
const factory UserBookingShowModel({
required int showId,
required ShowType showType,
required DateTime showDatetime,
}) = _UserBookingShowModel;

factory UserBookingShowModel.fromJson(Map<String, dynamic> json) => _$UserBookingShowModelFromJson(json);
}
6 changes: 6 additions & 0 deletions lib/providers/bookings_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ import '../services/repositories/bookings_repository.dart';
import 'all_providers.dart';
import 'shows_provider.dart';

final userBookingsProvider = FutureProvider.autoDispose((ref) async {
final _userId = ref.watch(authProvider.notifier).currentUserId;
final _bookingsProvider = ref.watch(bookingsProvider);
return await _bookingsProvider.getUserBookings(userId: _userId);
});

class BookingsProvider {
final BookingsRepository _bookingsRepository;
final Reader _reader;
Expand Down
30 changes: 13 additions & 17 deletions lib/providers/shows_provider.dart
Original file line number Diff line number Diff line change
@@ -1,38 +1,38 @@
import 'package:hooks_riverpod/hooks_riverpod.dart';

//Services
import '../services/repositories/shows_repository.dart';

//Enums
import '../enums/show_status_enum.dart';
import '../enums/show_type_enum.dart';
import '../models/show_model.dart';

//Models
import '../models/show_time_model.dart';
import '../models/show_model.dart';

//Services
import '../services/repositories/shows_repository.dart';

//Providers
import 'all_providers.dart';
import 'movies_provider.dart';

final showsFutureProvider = FutureProvider<List<ShowModel>>(
(ref) async {
final showsFutureProvider = FutureProvider.autoDispose<List<ShowModel>>(
(ref) async {
final _movieId = ref.watch(selectedMovieProvider).state.movieId;
final _showsProvider = ref.watch(showsProvider);
final _showDates = await _showsProvider.getAllShows(movieId: _movieId!);
return _showDates;
},
);

final selectedShowProvider = StateProvider<ShowModel>((ref) {
final selectedShowProvider = StateProvider.autoDispose<ShowModel>((ref) {
return ref.watch(showsFutureProvider).maybeWhen(
data: (shows) => shows[0],
orElse: () => ShowModel.initial(),
);
data: (shows) => shows[0],
orElse: () => ShowModel.initial(),
);
});

final selectedShowTimeProvider = StateProvider<ShowTimeModel>(
(ref) {
final selectedShowTimeProvider = StateProvider.autoDispose<ShowTimeModel>(
(ref) {
final _selectedShow = ref.watch(selectedShowProvider).state;
if (_selectedShow.showTimes.isEmpty) return ShowTimeModel.initial();
return _selectedShow.showTimes[0];
Expand Down Expand Up @@ -88,11 +88,7 @@ class ShowsProvider {
theaterId: theaterId,
);

final show = ShowModel(
date: date,
movieId: movieId,
showTimes: [showTime]
);
final show = ShowModel(date: date, movieId: movieId, showTimes: [showTime]);
return show;
}

Expand Down
15 changes: 9 additions & 6 deletions lib/providers/theaters_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,23 @@ import 'shows_provider.dart';

final selectedTheaterNameProvider = StateProvider<String>((_) => "");

final showSeatingFuture = FutureProvider<ShowSeatingModel>((ref) async {
/// Does not use `ref.maintainState = true` bcz we wanted to load theater seats
/// everytime because it can receive frequent updates.
final showSeatingFuture = FutureProvider.autoDispose<ShowSeatingModel>((ref) async {
final _selectedShowTime = ref.watch(selectedShowTimeProvider).state;

final _theatersProvider = ref.read(theatersProvider);
final _theaterId = _selectedShowTime.theaterId;
final _showId = _selectedShowTime.showId;

/// For any provider that can notify listeners, watch it's notifier instead
/// of state to prevent rebuilds upon listener's notifications.
final _theatersProvider = ref.watch(theatersProvider.notifier);
final theater = await _theatersProvider.getTheaterById(theaterId: _theaterId);

final _bookingsProvider = ref.watch(bookingsProvider);
final _showId = _selectedShowTime.showId;
final bookedSeats =
await _bookingsProvider.getShowBookedSeats(showId: _showId);

ref.read(selectedTheaterNameProvider).state = theater.theaterName;
ref.watch(selectedTheaterNameProvider.notifier).state = theater.theaterName;

return ShowSeatingModel(
showTime: _selectedShowTime,
Expand Down Expand Up @@ -60,7 +64,6 @@ class TheatersProvider extends ChangeNotifier {
} else {
_selectedSeats.remove(seat);
}
print(_selectedSeats);
notifyListeners();
}

Expand Down
2 changes: 2 additions & 0 deletions lib/routes/app_router.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import '../views/screens/theater_screen.dart';
import '../views/screens/ticket_summary_screen.dart';
import '../views/screens/payment_screen.dart';
import '../views/screens/confirmation_screen.dart';
import '../views/screens/user_bookings_screen.dart';

@MaterialAutoRouter(
routes: <AutoRoute>[
Expand All @@ -25,6 +26,7 @@ import '../views/screens/confirmation_screen.dart';
AutoRoute(page: TicketSummaryScreen),
AutoRoute(page: PaymentScreen),
AutoRoute(page: ConfirmationScreen),
AutoRoute(page: UserBookingsScreen),
],
)
class $AppRouter{}
2 changes: 1 addition & 1 deletion lib/services/local_storage/prefs_base.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import 'package:shared_preferences/shared_preferences.dart';

///Internal class for shared preferences methods
///Base class for shared preferences methods
///This class provides low level preferences methods
class PrefsBase{
///Instance of shared preferences
Expand Down
34 changes: 22 additions & 12 deletions lib/services/local_storage/prefs_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,57 +9,67 @@ import '../../models/user_model.dart';
//states
import '../../providers/states/auth_state.dart';

/// A service class for providing methods to store and retrieve data from
/// shared preferences.
class PrefsService {
final authTokenKey = "authToken";
final authStateKey = "authStateKey";
final authPasswordKey = "authPasswordKey";
final authUserKey = "authUserKey";

/// The name of auth token key
static const _authTokenKey = "authToken";

/// The name of auth state key
static const _authStateKey = "authStateKey";

/// The name of user password key
static const _authPasswordKey = "authPasswordKey";

/// The name of user model key
static const _authUserKey = "authUserKey";

///Instance of prefs class
final _prefs = PrefsBase.instance;

///Returns logged in user password
String getAuthPassword() {
return _prefs.get<String>(authPasswordKey) ?? '';
return _prefs.get<String>(_authPasswordKey) ?? '';
}

///Returns last authentication status
bool getAuthState() {
return _prefs.get<bool>(authStateKey) ?? false;
return _prefs.get<bool>(_authStateKey) ?? false;
}

///Returns last authenticated user
UserModel? getAuthUser() {
final user = _prefs.get<String>(authUserKey);
final user = _prefs.get<String>(_authUserKey);
if(user == null) return null;
return UserModel.fromJson(jsonDecode(user));
}

///Returns last authentication token
String getAuthToken() {
return _prefs.get<String>(authTokenKey) ?? '';
return _prefs.get<String>(_authTokenKey) ?? '';
}

///Sets the authentication password to this value
void setAuthPassword(String password) {
_prefs.set<String>(authPasswordKey, password);
_prefs.set<String>(_authPasswordKey, password);
}

///Sets the authentication status to this value
void setAuthState(AuthState authState) {
if(authState is AUTHENTICATED) {
_prefs.set<bool>(authStateKey, true);
_prefs.set<bool>(_authStateKey, true);
}
}

///Sets the authenticated user to this value
void setAuthUser(UserModel user) {
_prefs.set<String>(authUserKey, jsonEncode(user.toJson()));
_prefs.set<String>(_authUserKey, jsonEncode(user.toJson()));
}

///Sets the authentication token to this value
void setAuthToken(String token) {
_prefs.set<String>(authTokenKey, token);
_prefs.set<String>(_authTokenKey, token);
}

///Resets the authentication
Expand Down
47 changes: 47 additions & 0 deletions lib/services/networking/interceptors/api_interceptor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,29 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';

import '../../../providers/all_providers.dart';

/// A class that holds intercepting logic for API related requests. This is
/// the first interceptor in case of both request and response.
///
/// Since this interceptor isn't responsible for error handling, if an exception
/// occurs it is passed on the next [Interceptor] or to [Dio].
class ApiInterceptor extends Interceptor {

/// This method intercepts an out-going request before it reaches the
/// destination.
///
/// [options] contains http request information and configuration.
/// [handler] is used to forward, resolve, or reject requests.
///
/// This method is used to inject any token/API keys in the request.
///
/// The [RequestInterceptorHandler] in each method controls the what will
/// happen to the intercepted request. It has 3 possible options:
///
/// - [handler.next]/[super.onRequest], if you want to forward the request.
/// - [handler.resolve]/[super.onResponse], if you want to resolve the
/// request with your custom [Response]. All ** request ** interceptors are ignored.
/// - [handler.reject]/[super.onError], if you want to fail the request
/// with your custom [DioError].
@override
void onRequest(
RequestOptions options,
Expand All @@ -20,6 +42,31 @@ class ApiInterceptor extends Interceptor {
return handler.next(options);
}

/// This method intercepts an incoming response before it reaches Dio.
///
/// [response] contains http [Response] info.
/// [handler] is used to forward, resolve, or reject responses.
///
/// This method is used to check the success of the response by verifying
/// its headers.
///
/// If response is successful, it is simply passed on. It may again be
/// intercepted if there are any after it. If none, it is passed to [Dio].
///
/// Else if response indicates failure, a [DioError] is thrown with the
/// response and original request's options.
///
/// ** The success criteria is dependant on the API and may not always be
/// the same. It might need changing according to your own API. **
///
/// The [RequestInterceptorHandler] in each method controls the what will
/// happen to the intercepted response. It has 3 possible options:
///
/// - [handler.next]/[super.onRequest], if you want to forward the [Response].
/// - [handler.resolve]/[super.onResponse], if you want to resolve the
/// [Response] with your custom data. All ** response ** interceptors are ignored.
/// - [handler.reject]/[super.onError], if you want to fail the response
/// with your custom [DioError].
@override
void onResponse(
Response response,
Expand Down
Loading

0 comments on commit acd1015

Please sign in to comment.