Skip to content
This repository has been archived by the owner on May 28, 2024. It is now read-only.

Commit

Permalink
Beta 14 (#150)
Browse files Browse the repository at this point in the history
  • Loading branch information
dillonfagan authored Mar 8, 2024
1 parent 90f963b commit cf28051
Show file tree
Hide file tree
Showing 19 changed files with 433 additions and 84 deletions.
2 changes: 1 addition & 1 deletion lib/constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ const String supabasePublicKey = String.fromEnvironment('SUPABASE_PUBLIC_KEY');
const String apiHost = String.fromEnvironment('API_HOST',
defaultValue: 'http://localhost:8088/lending');

const String apiKey = String.fromEnvironment('API_KEY', defaultValue: '');
const String apiKey = String.fromEnvironment('API_KEY');

const String appUrl = String.fromEnvironment('APP_URL');
6 changes: 6 additions & 0 deletions lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart' as riverpod;
import 'package:librarian_app/constants.dart';
import 'package:librarian_app/src/core/library.dart';
import 'package:librarian_app/src/features/splash/pages/splash_page.dart';
import 'package:librarian_app/src/services/image_service.dart';
import 'package:librarian_app/src/theme/indigo_theme.dart';
import 'package:supabase_flutter/supabase_flutter.dart' as supabase;

Expand All @@ -13,6 +15,10 @@ Future<void> main() async {
anonKey: supabasePublicKey,
);

if (supabaseUrl.isNotEmpty) {
Library.logoUrl = ImageService().getPublicUrl('library', 'settings/logo');
}

runApp(const riverpod.ProviderScope(
child: LibrarianApp(),
));
Expand Down
3 changes: 3 additions & 0 deletions lib/src/core/library.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
class Library {
static String? logoUrl;
}
74 changes: 55 additions & 19 deletions lib/src/features/authentication/pages/signin_page.dart
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import 'dart:math';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:librarian_app/src/core/library.dart';
import 'package:librarian_app/src/features/authentication/providers/signin_error_provider.dart';
import 'package:librarian_app/src/features/authentication/widgets/discord_button.dart';
import 'package:librarian_app/src/features/authentication/providers/auth_service_provider.dart';
import 'package:librarian_app/src/features/dashboard/pages/dashboard_page.dart';
import 'package:librarian_app/src/widgets/fade_page_route.dart';
import 'package:supabase_flutter/supabase_flutter.dart';

class SignInPage extends ConsumerWidget {
Expand All @@ -14,7 +18,7 @@ class SignInPage extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
void onSignedIn() {
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(builder: (_) => const DashboardPage()),
createFadePageRoute(child: const DashboardPage()),
(route) => false,
);
}
Expand All @@ -36,37 +40,69 @@ class SignInPage extends ConsumerWidget {
}
}

return Scaffold(
body: Padding(
final screenSize = MediaQuery.of(context).size;
final cardHeight = min<double>(240, screenSize.height);
final cardWidth = min<double>(cardHeight, screenSize.width);

final card = Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Center(
child: SizedBox(
height: cardHeight,
width: cardWidth,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
Image.asset(
"pvd_things.png",
isAntiAlias: true,
width: 160,
),
const SizedBox(height: 32),
const Spacer(),
_LogoImage(),
const Spacer(),
DiscordSigninButton(onPressed: signIn),
if (ref.watch(signinErrorProvider) != null) ...[
const SizedBox(height: 16),
Text(ref.read(signinErrorProvider)!)
],
const SizedBox(height: 32),
const Card(
child: Padding(
padding: EdgeInsets.all(16),
child: Text(
'Only authorized users can sign in.\nPlease ask the PVD Things Digital Team for volunteer access.'),
),
),
const Spacer(),
],
),
),
),
);

return Scaffold(
body: Padding(
padding: const EdgeInsets.all(16),
child: Center(child: card),
),
);
}
}

class _LogoImage extends StatelessWidget {
@override
Widget build(BuildContext context) {
if (Library.logoUrl != null) {
return Image.network(
Library.logoUrl!,
loadingBuilder: (context, child, progress) {
return Center(child: child);
},
isAntiAlias: true,
height: 120,
);
}

if (kDebugMode) {
return Image.asset(
'pvd_things.png',
isAntiAlias: true,
height: 120,
);
}

return const Icon(
Icons.local_library_outlined,
size: 120,
);
}
}
5 changes: 3 additions & 2 deletions lib/src/features/authentication/widgets/discord_button.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ class DiscordSigninButton extends StatelessWidget {
Widget build(BuildContext context) {
return ElevatedButton.icon(
icon: const Icon(Icons.discord_rounded),
label: const Text('Sign in with Discord'),
label: const Text('Sign in'),
onPressed: onPressed,
style: ElevatedButton.styleFrom(
textStyle: const TextStyle(fontSize: 20),
backgroundColor: Theme.of(context).primaryColor,
padding: const EdgeInsets.all(16),
textStyle: const TextStyle(fontSize: 20),
),
);
}
Expand Down
40 changes: 39 additions & 1 deletion lib/src/features/dashboard/pages/dashboard_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import 'package:librarian_app/src/features/loans/pages/checkout_page.dart';
import 'package:librarian_app/src/features/loans/pages/loan_details_page.dart';
import 'package:librarian_app/src/features/loans/widgets/loans_list/searchable_loans_list.dart';
import 'package:librarian_app/src/features/loans/widgets/layouts/loans_desktop_layout.dart';
import 'package:librarian_app/src/features/updates/widgets/update_dialog_controller.dart';
import 'package:librarian_app/src/features/updates/notifiers/update_notifier.dart';
import 'package:librarian_app/src/utils/media_query.dart';
import 'package:librarian_app/src/features/actions/widgets/actions.dart'
as librarian_actions;
Expand All @@ -32,6 +34,16 @@ class DashboardPage extends ConsumerStatefulWidget {

class _DashboardPageState extends ConsumerState<DashboardPage> {
final _createButtonKey = GlobalKey<State>();
final _updateNotifier = UpdateNotifier.instance;

@override
void initState() {
super.initState();
_updateNotifier.addListener(() {
UpdateDialogController(context)
.showUpdateDialog(_updateNotifier.newerVersion!);
});
}

int _moduleIndex = 0;

Expand Down Expand Up @@ -165,8 +177,10 @@ class _DashboardPageState extends ConsumerState<DashboardPage> {
centerTitle: mobile,
actions: [
if (!mobile) ...[
_UpdateButton(),
const SizedBox(width: 32),
const UserTray(),
const SizedBox(width: 16),
const SizedBox(width: 32),
],
IconButton(
onPressed: () {
Expand Down Expand Up @@ -237,3 +251,27 @@ class DashboardModule {
final Widget desktopLayout;
final Widget? mobileLayout;
}

class _UpdateButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ListenableBuilder(
listenable: UpdateNotifier.instance,
builder: (context, _) {
final newVersion = UpdateNotifier.instance.newerVersion;

if (newVersion == null) {
return const SizedBox.shrink();
}

return IconButton(
onPressed: () {
UpdateDialogController(context).showUpdateDialog(newVersion);
},
tooltip: 'Update Available',
icon: const Icon(Icons.update, color: Colors.amber),
);
},
);
}
}
73 changes: 53 additions & 20 deletions lib/src/features/loans/widgets/checkout/checkout_stepper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -113,26 +113,12 @@ class _CheckoutStepperState extends ConsumerState<CheckoutStepper> {
subtitle: _borrower != null ? Text(_borrower!.name) : null,
content: Column(
children: [
TextField(
controller: TextEditingController(text: _borrower?.name),
canRequestFocus: false,
decoration: const InputDecoration(
labelText: 'Borrower',
prefixIcon: Icon(Icons.person_rounded),
),
onTap: () {
ref.invalidate(borrowersRepositoryProvider);
ref.read(borrowersRepositoryProvider).then((borrowers) async {
return await showSearch(
context: context,
delegate: BorrowerSearchDelegate(borrowers),
useRootNavigator: true,
);
}).then((borrower) {
if (borrower != null) {
setState(() => _borrower = borrower);
}
});
_SelectBorrowerTextField(
text: _borrower?.name,
onSelected: (borrower) {
if (borrower != null) {
setState(() => _borrower = borrower);
}
},
),
if (_borrower != null && !_borrower!.active) ...[
Expand Down Expand Up @@ -229,3 +215,50 @@ class _CheckoutStepperState extends ConsumerState<CheckoutStepper> {
);
}
}

class _SelectBorrowerTextField extends ConsumerStatefulWidget {
const _SelectBorrowerTextField({
required this.text,
required this.onSelected,
});

final String? text;
final void Function(BorrowerModel? borrower) onSelected;

@override
ConsumerState<_SelectBorrowerTextField> createState() =>
_SelectBorrowerTextFieldState();
}

class _SelectBorrowerTextFieldState
extends ConsumerState<_SelectBorrowerTextField> {
bool _isLoading = false;

@override
Widget build(BuildContext context) {
return TextField(
controller: TextEditingController(text: widget.text),
canRequestFocus: false,
decoration: InputDecoration(
labelText: _isLoading ? 'Loading...' : 'Borrower',
prefixIcon: const Icon(Icons.person_rounded),
),
enabled: !_isLoading,
onTap: () {
setState(() => _isLoading = true);

ref.invalidate(borrowersRepositoryProvider);
ref.read(borrowersRepositoryProvider).then((borrowers) async {
return await showSearch(
context: context,
delegate: BorrowerSearchDelegate(borrowers),
useRootNavigator: true,
);
}).then((borrower) {
widget.onSelected(borrower);
setState(() => _isLoading = false);
});
},
);
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:librarian_app/src/features/inventory/data/inventory_repository.dart';
import 'package:librarian_app/src/features/inventory/models/item_model.dart';

Expand Down Expand Up @@ -29,15 +30,17 @@ class ConnectedThingSearchField extends StatelessWidget {
controller: _textController,
onSubmitted: (_) => _submit(),
decoration: InputDecoration(
hintText: 'Enter Thing #',
prefixText: '#',
prefixIcon: const Icon(Icons.build_rounded),
suffix: IconButton(
hintText: 'Enter Thing Number',
prefixIcon: const Icon(Icons.numbers),
suffixIcon: IconButton(
tooltip: 'Add Thing',
onPressed: () => _submit(),
icon: const Icon(Icons.add_rounded),
),
),
inputFormatters: [
FilteringTextInputFormatter.digitsOnly,
],
);
}
}
Expand Down
5 changes: 3 additions & 2 deletions lib/src/features/splash/pages/splash_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:librarian_app/src/features/authentication/pages/signin_page.dart';
import 'package:librarian_app/src/features/authentication/providers/auth_service_provider.dart';
import 'package:librarian_app/src/features/dashboard/pages/dashboard_page.dart';
import 'package:librarian_app/src/widgets/fade_page_route.dart';

class SplashPage extends ConsumerStatefulWidget {
const SplashPage({super.key});
Expand All @@ -22,12 +23,12 @@ class _SplashPageState extends ConsumerState<SplashPage> {

if (!service.hasValidSession) {
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(builder: (_) => const SignInPage()),
createFadePageRoute(child: const SignInPage()),
(route) => false,
);
} else {
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(builder: (_) => const DashboardPage()),
createFadePageRoute(child: const DashboardPage()),
(route) => false,
);
}
Expand Down
Loading

0 comments on commit cf28051

Please sign in to comment.