wip: info page and GET app login / settings
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_remix/flutter_remix.dart';
|
||||
import 'package:furman_now/src/layouts/app_page.dart';
|
||||
import 'package:furman_now/src/utils/date_range.dart';
|
||||
import 'package:furman_now/src/utils/theme.dart';
|
||||
import 'package:furman_now/src/widgets/header.dart';
|
||||
@@ -11,98 +13,56 @@ class EventsScreen extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: Container(
|
||||
color: Colors.grey[100],
|
||||
child: SafeArea(
|
||||
child: Stack(
|
||||
fit: StackFit.loose,
|
||||
children: [
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
height: double.infinity,
|
||||
child: Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 30),
|
||||
width: double.infinity,
|
||||
height: 100,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Wrap(
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
children: [
|
||||
Icon(Icons.calendar_month_outlined, size: 35, color: Colors.grey[700]),
|
||||
const SizedBox(width: 12),
|
||||
Text("Events", style: furmanTextStyle(TextStyle(color: Colors.grey[900], fontSize: 28, fontWeight: FontWeight.w700))),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
return AppPageLayout(
|
||||
title: "Events",
|
||||
icon: FlutterRemix.calendar_line,
|
||||
content: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 20),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const HeaderWidget(title: "Today"),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||
child: EventsList()
|
||||
),
|
||||
const HeaderWidget(title: "Tomorrow"),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||
child: EventsList(dateRange: constructDateRange(
|
||||
DateTime.now().add(const Duration(days: 1)),
|
||||
DateTime.now().add(const Duration(days: 1)),
|
||||
)),
|
||||
),
|
||||
...[for(var i=2; i<7; i+=1) i].map((i) {
|
||||
var date = DateTime.now().add(Duration(days: i));
|
||||
var dayName = DateFormat('EEEE').format(date);
|
||||
return Wrap(
|
||||
children: [
|
||||
HeaderWidget(title: dayName),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||
child: EventsList(dateRange: constructDateRange(
|
||||
date,
|
||||
date,
|
||||
)),
|
||||
),
|
||||
),
|
||||
),
|
||||
ScrollViewWithHeight(
|
||||
child: Container(
|
||||
decoration: const BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.vertical(top: Radius.circular(30)),
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(vertical: 20),
|
||||
margin: const EdgeInsets.only(top: 100),
|
||||
width: double.infinity,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const HeaderWidget(title: "Today"),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||
child: EventsList()
|
||||
),
|
||||
const HeaderWidget(title: "Tomorrow"),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||
child: EventsList(dateRange: constructDateRange(
|
||||
DateTime.now().add(const Duration(days: 1)),
|
||||
DateTime.now().add(const Duration(days: 1)),
|
||||
)),
|
||||
),
|
||||
...[for(var i=2; i<7; i+=1) i].map((i) {
|
||||
var date = DateTime.now().add(Duration(days: i));
|
||||
var dayName = DateFormat('EEEE').format(date);
|
||||
return Wrap(
|
||||
children: [
|
||||
HeaderWidget(title: dayName),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||
child: EventsList(dateRange: constructDateRange(
|
||||
date,
|
||||
date,
|
||||
)),
|
||||
),
|
||||
],
|
||||
);
|
||||
}),
|
||||
Center(child:
|
||||
Wrap(
|
||||
direction: Axis.vertical,
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
children: const [
|
||||
Text("Need more events?"),
|
||||
Text("Syncdin"),
|
||||
Text("Athletics"),
|
||||
Text("CLPs"),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
}),
|
||||
Center(child:
|
||||
Wrap(
|
||||
direction: Axis.vertical,
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
children: const [
|
||||
Text("Need more events?"),
|
||||
Text("Syncdin"),
|
||||
Text("Athletics"),
|
||||
Text("CLPs"),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
|
63
lib/src/screens/info/contacts.dart
Normal file
63
lib/src/screens/info/contacts.dart
Normal file
@@ -0,0 +1,63 @@
|
||||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_remix/flutter_remix.dart';
|
||||
import 'package:furman_now/src/layouts/app_page.dart';
|
||||
import 'package:furman_now/src/services/info/contacts_service.dart';
|
||||
import 'package:furman_now/src/widgets/info/info_card.dart';
|
||||
|
||||
class ContactsScreen extends StatelessWidget {
|
||||
const ContactsScreen({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AppPageLayout(
|
||||
title: "Contacts",
|
||||
icon: FlutterRemix.arrow_left_line,
|
||||
backgroundColor: Colors.deepPurple.shade50,
|
||||
iconTapAction: () => context.router.pop(),
|
||||
content: Padding(
|
||||
padding: const EdgeInsets.all(20),
|
||||
child: FutureBuilder<Iterable<ContactInfo>>(
|
||||
future: ContactsService.fetchContactInfo(),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.hasData) {
|
||||
var items = snapshot.data!;
|
||||
return Column(
|
||||
children: items.map((item) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 15),
|
||||
child: InfoCard(
|
||||
title: item.name,
|
||||
icon: item.buildingId != 0
|
||||
? FlutterRemix.building_line
|
||||
: FlutterRemix.contacts_line,
|
||||
items: [
|
||||
InfoCardItem(
|
||||
name: item.phone,
|
||||
icon: FlutterRemix.phone_line
|
||||
),
|
||||
],
|
||||
onClick: () => item.launch(),
|
||||
),
|
||||
);
|
||||
}).toList());
|
||||
}
|
||||
else if (snapshot.hasError) {
|
||||
return Text(
|
||||
'${snapshot.error}',
|
||||
style: const TextStyle(color: Colors.red)
|
||||
);
|
||||
}
|
||||
// By default, show a loading spinner.
|
||||
return const Center(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 25),
|
||||
child: CircularProgressIndicator()
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
82
lib/src/screens/info/health_safety.dart
Normal file
82
lib/src/screens/info/health_safety.dart
Normal file
@@ -0,0 +1,82 @@
|
||||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_remix/flutter_remix.dart';
|
||||
import 'package:furman_now/src/layouts/app_page.dart';
|
||||
import 'package:furman_now/src/services/info/health_safety_service.dart';
|
||||
import 'package:furman_now/src/widgets/info/info_card.dart';
|
||||
|
||||
class HealthSafetyScreen extends StatelessWidget {
|
||||
const HealthSafetyScreen({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AppPageLayout(
|
||||
title: "Health and Safety",
|
||||
icon: FlutterRemix.arrow_left_line,
|
||||
backgroundColor: Colors.red.shade50,
|
||||
iconTapAction: () => context.router.pop(),
|
||||
content: Padding(
|
||||
padding: const EdgeInsets.all(20),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(top: 15, bottom: 35),
|
||||
child: Text(
|
||||
"If you are in an emergency, dial 911",
|
||||
style: Theme.of(context).textTheme.titleMedium?.copyWith(
|
||||
color: Colors.red.shade800,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
FutureBuilder<Iterable<HealthSafetyInfo>>(
|
||||
future: HealthSafetyService.fetchHealthSafetyInfo(),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.hasData) {
|
||||
var items = snapshot.data!.where((item) =>
|
||||
item.type != HealthSafetyInfoType.removed
|
||||
);
|
||||
var iconMap = {
|
||||
HealthSafetyInfoType.phone: FlutterRemix.phone_line,
|
||||
HealthSafetyInfoType.link: FlutterRemix.external_link_line,
|
||||
HealthSafetyInfoType.app: FlutterRemix.apps_line,
|
||||
};
|
||||
return Column(
|
||||
children: items.map((item) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 15),
|
||||
child: InfoCard(
|
||||
title: item.name,
|
||||
icon: item.icon,
|
||||
items: [
|
||||
InfoCardItem(
|
||||
name: item.linkText,
|
||||
icon: iconMap[item.type] ?? FlutterRemix.link
|
||||
),
|
||||
],
|
||||
onClick: () => item.launch(),
|
||||
),
|
||||
);
|
||||
}).toList());
|
||||
}
|
||||
else if (snapshot.hasError) {
|
||||
return Text(
|
||||
'${snapshot.error}', style: const TextStyle(color: Colors.red),);
|
||||
}
|
||||
// By default, show a loading spinner.
|
||||
return const Center(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 25),
|
||||
child: CircularProgressIndicator()
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
72
lib/src/screens/info/hours.dart
Normal file
72
lib/src/screens/info/hours.dart
Normal file
@@ -0,0 +1,72 @@
|
||||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_remix/flutter_remix.dart';
|
||||
import 'package:furman_now/src/layouts/app_page.dart';
|
||||
import 'package:furman_now/src/services/buildings/buildings_service.dart';
|
||||
import 'package:furman_now/src/store/index.dart';
|
||||
import 'package:furman_now/src/widgets/info/info_card.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class HoursScreen extends StatelessWidget {
|
||||
const HoursScreen({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AppPageLayout(
|
||||
title: "Hours",
|
||||
icon: FlutterRemix.arrow_left_line,
|
||||
backgroundColor: Colors.blue.shade50,
|
||||
iconTapAction: () => context.router.pop(),
|
||||
content: Padding(
|
||||
padding: const EdgeInsets.all(20),
|
||||
child: Consumer<AppState>(
|
||||
builder: (context, state, _) {
|
||||
return FutureBuilder<Iterable<Building>>(
|
||||
future: state.buildings,
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.hasData) {
|
||||
var items = snapshot.data!.where(
|
||||
(building) => building.hoursList.isNotEmpty
|
||||
);
|
||||
return Column(
|
||||
children: items.map((item) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 15),
|
||||
child: InfoCard(
|
||||
title: item.name,
|
||||
icon: FlutterRemix.building_line,
|
||||
items: item.hoursList.map((hours) =>
|
||||
InfoCardItem(
|
||||
name: ""
|
||||
"${hours.daysOfWeek} from "
|
||||
"${hours.startTime.format(context)} - "
|
||||
"${hours.endTime.format(context)}",
|
||||
icon: FlutterRemix.time_line,
|
||||
),
|
||||
).toList(),
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
);
|
||||
}
|
||||
else if (snapshot.hasError) {
|
||||
return Text(
|
||||
'${snapshot.error}',
|
||||
style: const TextStyle(color: Colors.red),
|
||||
);
|
||||
}
|
||||
// By default, show a loading spinner.
|
||||
return const Center(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 25),
|
||||
child: CircularProgressIndicator()
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@@ -1,84 +1,64 @@
|
||||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:furman_now/src/utils/theme.dart';
|
||||
import 'package:furman_now/src/widgets/info/info_card.dart';
|
||||
import 'package:furman_now/src/widgets/scroll_view_height.dart';
|
||||
import 'package:flutter_remix/flutter_remix.dart';
|
||||
import 'package:furman_now/src/layouts/app_page.dart';
|
||||
import 'package:furman_now/src/routes/index.gr.dart';
|
||||
import 'package:furman_now/src/widgets/info/info_category_card.dart';
|
||||
|
||||
class InfoScreen extends StatelessWidget {
|
||||
const InfoScreen({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: Container(
|
||||
color: Colors.grey[100],
|
||||
child: SafeArea(
|
||||
child: Stack(
|
||||
fit: StackFit.loose,
|
||||
children: [
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
height: double.infinity,
|
||||
child: Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 30),
|
||||
width: double.infinity,
|
||||
height: 100,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Wrap(
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
children: [
|
||||
Icon(Icons.info_outline, size: 35, color: Colors.grey[700]),
|
||||
const SizedBox(width: 12),
|
||||
Text("Info", style: furmanTextStyle(TextStyle(color: Colors.grey[900], fontSize: 28, fontWeight: FontWeight.w700))),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
return AppPageLayout(
|
||||
title: "Info",
|
||||
icon: FlutterRemix.information_line,
|
||||
content: Padding(
|
||||
padding: const EdgeInsets.all(20),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () => context.router.push(const HealthSafetyRoute()),
|
||||
child: InfoCategoryCard(
|
||||
color: Colors.red.shade50,
|
||||
icon: Icons.local_hospital,
|
||||
title: "Health and Safety",
|
||||
description: "Important contact information and links regarding student health and safety.",
|
||||
),
|
||||
ScrollViewWithHeight(
|
||||
child: Container(
|
||||
decoration: const BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.vertical(top: Radius.circular(30)),
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 20),
|
||||
margin: const EdgeInsets.only(top: 100),
|
||||
width: double.infinity,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
InfoCard(
|
||||
color: Colors.red.shade50,
|
||||
icon: Icons.local_hospital,
|
||||
title: "Health and Safety",
|
||||
description: "Important contact information and links regarding student health and safety.",
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
InfoCard(
|
||||
color: Colors.deepPurple.shade50,
|
||||
icon: Icons.phone,
|
||||
title: "Contacts",
|
||||
description: "Important contact information and links regarding student health and safety.",
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
InfoCard(
|
||||
color: Colors.blue.shade50,
|
||||
icon: Icons.access_time,
|
||||
title: "Hours",
|
||||
description: "Important contact information and links regarding student health and safety.",
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
GestureDetector(
|
||||
onTap: () => context.router.push(const ContactsRoute()),
|
||||
child: InfoCategoryCard(
|
||||
color: Colors.deepPurple.shade50,
|
||||
icon: Icons.phone,
|
||||
title: "Contacts",
|
||||
description: "Contact information for offices and resources on Furman's campus.",
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
GestureDetector(
|
||||
onTap: () => context.router.push(const HoursRoute()),
|
||||
child: InfoCategoryCard(
|
||||
color: Colors.blue.shade50,
|
||||
icon: Icons.access_time,
|
||||
title: "Hours",
|
||||
description: "Check the hours for buildings and services on Furman's campus.",
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
const Spacer(),
|
||||
GestureDetector(
|
||||
onTap: () => context.router.push(const SettingsRoute()),
|
||||
child: InfoCategoryCard(
|
||||
color: Colors.grey.shade100,
|
||||
icon: Icons.settings,
|
||||
title: "Settings",
|
||||
description: "Account settings, GET login, dark mode",
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
|
42
lib/src/screens/settings/settings.dart
Normal file
42
lib/src/screens/settings/settings.dart
Normal file
@@ -0,0 +1,42 @@
|
||||
import 'package:auto_route/auto_route.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_remix/flutter_remix.dart';
|
||||
import 'package:furman_now/src/layouts/app_page.dart';
|
||||
import 'package:furman_now/src/services/get_app/user/user_service.dart';
|
||||
|
||||
class SettingsScreen extends StatefulWidget {
|
||||
const SettingsScreen({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<SettingsScreen> createState() => _SettingsScreenState();
|
||||
}
|
||||
|
||||
class _SettingsScreenState extends State<SettingsScreen> {
|
||||
final UserService _service = UserService();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AppPageLayout(
|
||||
title: "Settings",
|
||||
icon: FlutterRemix.arrow_left_line,
|
||||
backgroundColor: Colors.grey.shade100,
|
||||
iconTapAction: () => context.router.pop(),
|
||||
content: Padding(
|
||||
padding: const EdgeInsets.all(20),
|
||||
child: Column(
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
_service.login();
|
||||
},
|
||||
child: Container(
|
||||
padding: EdgeInsets.all(20),
|
||||
child: Text("Log in with GET app."),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user