migration commit
This commit is contained in:
17
lib/classes/activity_action.dart
Normal file
17
lib/classes/activity_action.dart
Normal file
@ -0,0 +1,17 @@
|
||||
class ActivityAction {
|
||||
ActivityAction(
|
||||
{required this.id,
|
||||
required this.title,
|
||||
required this.description,
|
||||
this.repetitions,
|
||||
this.time,
|
||||
this.weight});
|
||||
|
||||
final int id;
|
||||
final String title;
|
||||
final String description;
|
||||
final int? repetitions;
|
||||
final int? weight;
|
||||
// in milliseconds
|
||||
final int? time;
|
||||
}
|
16
lib/classes/media.dart
Normal file
16
lib/classes/media.dart
Normal file
@ -0,0 +1,16 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class Media {
|
||||
Media(
|
||||
{required this.id,
|
||||
required this.reference,
|
||||
required this.type,
|
||||
this.description,
|
||||
this.comments});
|
||||
|
||||
final int id;
|
||||
final String reference;
|
||||
final String type;
|
||||
final String? description;
|
||||
final List<String>? comments;
|
||||
}
|
92
lib/main.dart
Normal file
92
lib/main.dart
Normal file
@ -0,0 +1,92 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:sendtrain/screens/activities_screen.dart';
|
||||
import 'package:sendtrain/screens/sessions_screen.dart';
|
||||
|
||||
class SendTrain extends StatelessWidget {
|
||||
const SendTrain({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
title: "Sendtrain",
|
||||
theme: ThemeData.dark(useMaterial3: true),
|
||||
home: const App());
|
||||
}
|
||||
}
|
||||
|
||||
class App extends StatefulWidget {
|
||||
const App({super.key});
|
||||
|
||||
@override
|
||||
State<App> createState() => _AppState();
|
||||
}
|
||||
|
||||
class _AppState extends State<App> {
|
||||
int currentPageIndex = 0;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
// appBar: AppBar(
|
||||
// toolbarOpacity: 0,
|
||||
// centerTitle: true,
|
||||
// title: const Text('SENDTRAIN'),
|
||||
// scrolledUnderElevation: 0,
|
||||
// actions: <Widget>[
|
||||
// IconButton(
|
||||
// // highlightColor: Colors.deepPurple,
|
||||
// icon: const Icon(Icons.settings),
|
||||
// tooltip: 'Application Settings',
|
||||
// onPressed: () {})
|
||||
// ]),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(0, 50, 0, 0),
|
||||
child: <Widget>[
|
||||
const SessionsScreen(),
|
||||
const ActivitiesScreen(),
|
||||
Container(
|
||||
alignment: Alignment.center,
|
||||
child: const Text('In Progress...'),
|
||||
),
|
||||
Container(
|
||||
alignment: Alignment.center,
|
||||
child: const Text('In Progress...'),
|
||||
),
|
||||
Container(
|
||||
alignment: Alignment.center,
|
||||
child: const Text('In Progress...'),
|
||||
),
|
||||
][currentPageIndex]),
|
||||
bottomNavigationBar: NavigationBar(
|
||||
onDestinationSelected: (int index) {
|
||||
setState(() {
|
||||
currentPageIndex = index;
|
||||
});
|
||||
},
|
||||
selectedIndex: currentPageIndex,
|
||||
destinations: const <Widget>[
|
||||
NavigationDestination(
|
||||
icon: Icon(Icons.sports), label: "Sessions"),
|
||||
NavigationDestination(
|
||||
icon: Icon(Icons.landscape), label: "Activities"),
|
||||
NavigationDestination(
|
||||
icon: Icon(Icons.calendar_month_rounded), label: "Plan"),
|
||||
NavigationDestination(
|
||||
icon: Icon(Icons.group), label: "Team Send"),
|
||||
NavigationDestination(
|
||||
icon: Icon(Icons.analytics), label: "Progress")
|
||||
]),
|
||||
floatingActionButton: FloatingActionButton.extended(
|
||||
onPressed: () {
|
||||
// Add your onPressed code here!
|
||||
},
|
||||
label: const Text('New Session'),
|
||||
icon: const Icon(Icons.add_chart),
|
||||
backgroundColor: Colors.deepPurple,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
runApp(const SendTrain());
|
||||
}
|
20
lib/models/activity_model.dart
Normal file
20
lib/models/activity_model.dart
Normal file
@ -0,0 +1,20 @@
|
||||
import '../classes/activity_action.dart';
|
||||
|
||||
class ActivityModel {
|
||||
ActivityModel(
|
||||
{required this.id,
|
||||
required this.title,
|
||||
required this.type,
|
||||
required this.categories,
|
||||
required this.description,
|
||||
required this.actions,
|
||||
this.resources});
|
||||
|
||||
final int id;
|
||||
final String title;
|
||||
final String type;
|
||||
final List<String> categories;
|
||||
final String description;
|
||||
final List<ActivityAction> actions;
|
||||
final List<String>? resources;
|
||||
}
|
21
lib/models/session_model.dart
Normal file
21
lib/models/session_model.dart
Normal file
@ -0,0 +1,21 @@
|
||||
import 'package:sendtrain/classes/media.dart';
|
||||
import 'package:sendtrain/models/activity_model.dart';
|
||||
|
||||
class SessionModel {
|
||||
SessionModel(
|
||||
{required this.id,
|
||||
required this.title,
|
||||
required this.content,
|
||||
required this.date,
|
||||
this.activities,
|
||||
this.achievements,
|
||||
this.media});
|
||||
|
||||
final int id;
|
||||
final String title;
|
||||
final String content;
|
||||
final DateTime date;
|
||||
final List<ActivityModel>? activities;
|
||||
final List<String>? achievements;
|
||||
final List<Media>? media;
|
||||
}
|
35
lib/screens/activities_screen.dart
Normal file
35
lib/screens/activities_screen.dart
Normal file
@ -0,0 +1,35 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../widgets/activities_header.dart';
|
||||
import '../widgets/activity_card.dart';
|
||||
|
||||
class ActivitiesScreen extends StatefulWidget {
|
||||
const ActivitiesScreen({super.key});
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _ActivitiesScreenState();
|
||||
}
|
||||
|
||||
class _ActivitiesScreenState extends State<ActivitiesScreen> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
List<Widget> activities = List.generate(10, (i) => ActivityCard());
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.fromLTRB(10, 15, 10, 0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
const ActivitiesHeader(),
|
||||
Expanded(
|
||||
child: GridView.count(
|
||||
primary: false,
|
||||
padding: const EdgeInsets.fromLTRB(0, 0, 0, 0),
|
||||
crossAxisSpacing: 10,
|
||||
mainAxisSpacing: 10,
|
||||
crossAxisCount: 2,
|
||||
children: activities,
|
||||
))
|
||||
]));
|
||||
}
|
||||
}
|
52
lib/screens/sessions_screen.dart
Normal file
52
lib/screens/sessions_screen.dart
Normal file
@ -0,0 +1,52 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../widgets/session_card.dart';
|
||||
|
||||
class SessionsScreen extends StatelessWidget {
|
||||
const SessionsScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
List<Widget> previousSessions =
|
||||
List.generate(10, (i) => const SessionCard(state: 1, type: 1));
|
||||
Widget upcomingSession = const SessionCard(state: 2);
|
||||
Widget currentSession = const SessionCard();
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
const Padding(
|
||||
padding: EdgeInsets.fromLTRB(15, 5, 0, 0),
|
||||
child: Text(
|
||||
style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold),
|
||||
'Current:')),
|
||||
currentSession,
|
||||
const Padding(
|
||||
padding: EdgeInsets.fromLTRB(15, 30, 0, 0),
|
||||
child: Text(
|
||||
style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold),
|
||||
'Upcoming:')),
|
||||
upcomingSession,
|
||||
const Padding(
|
||||
padding: EdgeInsets.fromLTRB(15, 30, 0, 0),
|
||||
child: Text(
|
||||
style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold),
|
||||
'Previous:')),
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
height: 160,
|
||||
child: GridView.count(
|
||||
padding: const EdgeInsets.fromLTRB(15, 10, 0, 0),
|
||||
scrollDirection: Axis.horizontal,
|
||||
crossAxisSpacing: 5,
|
||||
mainAxisSpacing: 5,
|
||||
crossAxisCount: 1,
|
||||
children: previousSessions))
|
||||
// Flexible(
|
||||
// child: ListView(
|
||||
// scrollDirection: Axis.vertical,
|
||||
// children: previousSessions,
|
||||
// )),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
41
lib/widgets/activities_header.dart
Normal file
41
lib/widgets/activities_header.dart
Normal file
@ -0,0 +1,41 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../widgets/activity_type_filter.dart';
|
||||
|
||||
class ActivitiesHeader extends StatefulWidget {
|
||||
const ActivitiesHeader({super.key});
|
||||
|
||||
@override
|
||||
_ActivitiesHeaderState createState() => _ActivitiesHeaderState();
|
||||
}
|
||||
|
||||
class _ActivitiesHeaderState extends State<ActivitiesHeader> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 10),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: const <Widget>[
|
||||
Padding(
|
||||
padding: EdgeInsets.fromLTRB(10, 0, 10, 0),
|
||||
child: Text(
|
||||
style:
|
||||
TextStyle(fontSize: 25, fontWeight: FontWeight.bold),
|
||||
'Filters:')),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(right: 5),
|
||||
child: ActivityTypeFilter()),
|
||||
]));
|
||||
}
|
||||
}
|
35
lib/widgets/activity_card.dart
Normal file
35
lib/widgets/activity_card.dart
Normal file
@ -0,0 +1,35 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:sendtrain/classes/activity_action.dart';
|
||||
import 'package:sendtrain/models/activity_model.dart';
|
||||
|
||||
class ActivityCard extends StatelessWidget {
|
||||
ActivityCard({super.key});
|
||||
|
||||
final data = ActivityModel(
|
||||
id: 1,
|
||||
categories: ['power'],
|
||||
description: 'description',
|
||||
title: 'activity',
|
||||
type: 'fundamentals',
|
||||
actions: List.generate(
|
||||
10,
|
||||
(i) => ActivityAction(
|
||||
id: 1,
|
||||
title: 'exercise',
|
||||
description: 'description',
|
||||
repetitions: 5,
|
||||
time: 5200)));
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Card(
|
||||
clipBehavior: Clip.hardEdge,
|
||||
child: Align(
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
data.title,
|
||||
style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
32
lib/widgets/activity_type_filter.dart
Normal file
32
lib/widgets/activity_type_filter.dart
Normal file
@ -0,0 +1,32 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class ActivityTypeFilter extends StatefulWidget {
|
||||
const ActivityTypeFilter({super.key});
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _ActivityTypeFilterState();
|
||||
}
|
||||
|
||||
class _ActivityTypeFilterState extends State<ActivityTypeFilter> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return const DropdownMenu(
|
||||
hintText: 'Filter by type of activity',
|
||||
initialSelection: "fundamentals",
|
||||
// controller: colorController,
|
||||
label: Text('Type'),
|
||||
dropdownMenuEntries: [
|
||||
DropdownMenuEntry(value: 'fundamentals', label: 'Fundamentals'),
|
||||
DropdownMenuEntry(value: 'conditioning', label: 'Conditioning'),
|
||||
DropdownMenuEntry(value: 'advanced', label: 'Advanced'),
|
||||
DropdownMenuEntry(value: 'custom', label: 'Custom'),
|
||||
DropdownMenuEntry(value: 'pro', label: 'Pro')
|
||||
],
|
||||
// onSelected: (ColorLabel? color) {
|
||||
// setState(() {
|
||||
// selectedColor = color;
|
||||
// });
|
||||
// },
|
||||
);
|
||||
}
|
||||
}
|
93
lib/widgets/media_card.dart
Normal file
93
lib/widgets/media_card.dart
Normal file
@ -0,0 +1,93 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:sendtrain/classes/media.dart';
|
||||
import 'package:youtube_player_flutter/youtube_player_flutter.dart';
|
||||
|
||||
class MediaCard extends StatelessWidget {
|
||||
const MediaCard({super.key, required this.media});
|
||||
|
||||
final Media media;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
YoutubePlayerController _controller = YoutubePlayerController(
|
||||
initialVideoId: media.reference,
|
||||
flags: const YoutubePlayerFlags(
|
||||
autoPlay: false, mute: true, showLiveFullscreenButton: false));
|
||||
|
||||
DecorationImage mediaImage(Media media) {
|
||||
String image = '';
|
||||
|
||||
if (media.type == "image") {
|
||||
image = media.reference;
|
||||
} else if (media.type == "youtube") {
|
||||
image = 'https://img.youtube.com/vi/${media.reference}/0.jpg';
|
||||
}
|
||||
|
||||
return DecorationImage(image: NetworkImage(image), fit: BoxFit.cover);
|
||||
}
|
||||
|
||||
Widget mediaItem(Media media) {
|
||||
if (media.type == "image") {
|
||||
return Image(image: NetworkImage(media.reference));
|
||||
} else if (media.type == "youtube") {
|
||||
return YoutubePlayer(
|
||||
controller: _controller,
|
||||
aspectRatio: 16 / 9,
|
||||
);
|
||||
}
|
||||
|
||||
return const Image(image: AssetImage('assets/images/placeholder.jpg'));
|
||||
}
|
||||
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
image: mediaImage(media),
|
||||
),
|
||||
child: Card(
|
||||
color: Colors.transparent,
|
||||
shape:
|
||||
RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
|
||||
shadowColor: const Color.fromARGB(0, 255, 255, 255),
|
||||
child: TextButton(
|
||||
onPressed: () => showDialog<String>(
|
||||
context: context,
|
||||
builder: (BuildContext context) => Dialog.fullscreen(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
mediaItem(media),
|
||||
const SizedBox(height: 15),
|
||||
Text(
|
||||
'${media.description}',
|
||||
style: const TextStyle(fontSize: 20),
|
||||
),
|
||||
const Divider(
|
||||
indent: 20,
|
||||
endIndent: 20,
|
||||
color: Colors.deepPurple,
|
||||
),
|
||||
// const Text(
|
||||
// 'Comments',
|
||||
// style: TextStyle(fontSize: 20),
|
||||
// ),
|
||||
const SizedBox(height: 15),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: const Text('Close'),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
child: const ListTile(
|
||||
title: Text(''),
|
||||
))));
|
||||
}
|
||||
}
|
264
lib/widgets/session_card.dart
Normal file
264
lib/widgets/session_card.dart
Normal file
@ -0,0 +1,264 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:intl/date_symbol_data_local.dart';
|
||||
import 'package:sendtrain/classes/activity_action.dart';
|
||||
import 'package:sendtrain/classes/media.dart';
|
||||
import 'package:sendtrain/models/activity_model.dart';
|
||||
import 'package:sendtrain/models/session_model.dart';
|
||||
import 'package:sendtrain/widgets/session_view.dart';
|
||||
|
||||
class SessionCard extends StatelessWidget {
|
||||
final int state;
|
||||
final int type;
|
||||
const SessionCard({super.key, this.state = 0, this.type = 0});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
initializeDateFormatting('en');
|
||||
final DateFormat dateFormat = DateFormat('yyyy-MM-dd');
|
||||
|
||||
Color color = (state == 0)
|
||||
? const Color(0xff3A5FB6)
|
||||
: ThemeData.dark(useMaterial3: true).colorScheme.background;
|
||||
|
||||
// place holder until we can retrieve real data
|
||||
final data = SessionModel(
|
||||
id: 1,
|
||||
title: "Projecting @ Climbers Rock",
|
||||
content:
|
||||
"Beta pully beta beta pinch one arm crimpy. Futuristic pinch, dyno dynamic drop knee climb. Climbing ondra slopey onsight beta ondra power endurance.",
|
||||
date: DateTime.now(),
|
||||
activities: [
|
||||
ActivityModel(
|
||||
id: 1,
|
||||
title: 'Campus Board',
|
||||
type: 'fundamental',
|
||||
categories: ['strength', 'power'],
|
||||
description:
|
||||
"Campus board session, focussing on explosiveness and contact strength.",
|
||||
actions: [
|
||||
ActivityAction(
|
||||
id: 1,
|
||||
title: '1, 3, 5 - left hand start',
|
||||
description:
|
||||
'move from rungs 1, 3, and 5, alternating arms on each movement',
|
||||
repetitions: 1),
|
||||
ActivityAction(
|
||||
id: 2,
|
||||
title: 'Rest',
|
||||
description: 'rest for alotted time',
|
||||
time: 15000),
|
||||
ActivityAction(
|
||||
id: 3,
|
||||
title: '1, 3, 5 - right hand start',
|
||||
description:
|
||||
'move from rungs 1, 3, and 5, alternating arms on each movement',
|
||||
repetitions: 1),
|
||||
ActivityAction(
|
||||
id: 4,
|
||||
title: 'Rest',
|
||||
description: 'rest for alotted time',
|
||||
time: 300000),
|
||||
ActivityAction(
|
||||
id: 5,
|
||||
title: 'Repeat',
|
||||
description: 'repeat cycle',
|
||||
repetitions: 5)
|
||||
],
|
||||
resources: ['https://www.youtube.com/watch?v=bLz0xp1PEm4']),
|
||||
ActivityModel(
|
||||
id: 1,
|
||||
title: 'Projecting',
|
||||
type: 'fundamental',
|
||||
categories: ['technique', 'conditioning'],
|
||||
description:
|
||||
"Session focussed on attempting a climb at or beyond your perceived limit.",
|
||||
actions: [
|
||||
ActivityAction(
|
||||
id: 1,
|
||||
title: 'attempt boulder',
|
||||
description: 'attempt boulder project',
|
||||
repetitions: 1),
|
||||
ActivityAction(
|
||||
id: 2,
|
||||
title: 'Rest',
|
||||
description: 'rest for alotted time',
|
||||
time: 300000),
|
||||
ActivityAction(
|
||||
id: 5,
|
||||
title: 'Repeat',
|
||||
description: 'repeat cycle',
|
||||
repetitions: 5)
|
||||
],
|
||||
resources: ['https://www.youtube.com/watch?v=dyAvbUvY_PU']),
|
||||
ActivityModel(
|
||||
id: 1,
|
||||
title: 'Weighted Pull Ups',
|
||||
type: 'fundamental',
|
||||
categories: ['Strength', 'Power'],
|
||||
description:
|
||||
"Weight pullups to increase strength and maximal pulling force.",
|
||||
actions: [
|
||||
ActivityAction(
|
||||
id: 1,
|
||||
title: 'pull ups',
|
||||
description: 'pull ups',
|
||||
repetitions: 5,
|
||||
weight: 100),
|
||||
ActivityAction(
|
||||
id: 2,
|
||||
title: 'Rest',
|
||||
description: 'rest for alotted time',
|
||||
time: 300000),
|
||||
ActivityAction(
|
||||
id: 5,
|
||||
title: 'Repeat',
|
||||
description: 'repeat cycle',
|
||||
repetitions: 5)
|
||||
],
|
||||
resources: ['https://www.youtube.com/watch?v=dyAvbUvY_PU']),
|
||||
],
|
||||
achievements: [
|
||||
'got 1 3 5 first time!',
|
||||
'no pain in elbow',
|
||||
'life is pain',
|
||||
'new PR for pullups'
|
||||
],
|
||||
media: [
|
||||
Media(
|
||||
id: 1,
|
||||
reference: 'TwS8ycTY5cc',
|
||||
type: 'youtube',
|
||||
description: 'Attempting crux move'),
|
||||
Media(
|
||||
id: 1,
|
||||
reference:
|
||||
'https://static.wixstatic.com/media/c83481_1dd473ad49524ae5a95d993ba10e0a50~mv2.jpg/v1/fill/w_640,h_426,al_c,q_80,usm_0.66_1.00_0.01,enc_auto/c83481_1dd473ad49524ae5a95d993ba10e0a50~mv2.jpg',
|
||||
type: 'image',
|
||||
description: 'Struggling on deadpoints'),
|
||||
Media(
|
||||
id: 1,
|
||||
reference: 'TwS8ycTY5cc',
|
||||
type: 'youtube',
|
||||
description: 'Attempting crux move')
|
||||
]);
|
||||
|
||||
if (type == 0) {
|
||||
return Card(
|
||||
color: color,
|
||||
margin: const EdgeInsets.fromLTRB(15, 15, 15, 0),
|
||||
clipBehavior: Clip.hardEdge,
|
||||
child: InkWell(
|
||||
// splashColor: Colors.deepPurple,
|
||||
onTap: () => showGeneralDialog(
|
||||
barrierColor: Colors.black.withOpacity(0.5),
|
||||
transitionDuration: const Duration(milliseconds: 220),
|
||||
transitionBuilder: (BuildContext context,
|
||||
Animation<double> animation,
|
||||
Animation<double> secondaryAnimation,
|
||||
Widget child) {
|
||||
Animation<Offset> custom = Tween<Offset>(
|
||||
begin: const Offset(0.0, 1.0),
|
||||
end: const Offset(0.0, 0.0))
|
||||
.animate(animation);
|
||||
return SlideTransition(
|
||||
position: custom,
|
||||
child: Dialog.fullscreen(child: SessionView(data: data)));
|
||||
},
|
||||
barrierDismissible: true,
|
||||
barrierLabel: '',
|
||||
context: context,
|
||||
pageBuilder: (context, animation1, animation2) {
|
||||
return Container();
|
||||
}),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
ListTile(
|
||||
leading: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(0, 8, 0, 0),
|
||||
child: Container(
|
||||
width: 60,
|
||||
decoration: const BoxDecoration(
|
||||
image: DecorationImage(
|
||||
fit: BoxFit.cover,
|
||||
image:
|
||||
AssetImage('assets/images/placeholder.jpg')),
|
||||
// color: Colors.blue,
|
||||
borderRadius:
|
||||
BorderRadius.all(Radius.elliptical(10, 10)),
|
||||
),
|
||||
)),
|
||||
title: Text(maxLines: 1, data.title),
|
||||
subtitle: Text(maxLines: 1, dateFormat.format(data.date)),
|
||||
),
|
||||
ListTile(
|
||||
contentPadding: const EdgeInsets.fromLTRB(15, 0, 15, 15),
|
||||
title: Text(
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: const TextStyle(fontWeight: FontWeight.w300),
|
||||
data.content),
|
||||
),
|
||||
],
|
||||
)),
|
||||
);
|
||||
} else {
|
||||
return Card(
|
||||
color: const Color.fromARGB(125, 0, 0, 0),
|
||||
child: InkWell(
|
||||
// overlayColor: MaterialStateColor(Colors.deepPurple as int),
|
||||
// splashColor: Colors.deepPurple,
|
||||
borderRadius: const BorderRadius.all(Radius.elliptical(10, 10)),
|
||||
onTap: () => showGeneralDialog(
|
||||
// barrierColor: Colors.black.withOpacity(0.5),
|
||||
transitionDuration: const Duration(milliseconds: 220),
|
||||
transitionBuilder: (BuildContext context,
|
||||
Animation<double> animation,
|
||||
Animation<double> secondaryAnimation,
|
||||
Widget child) {
|
||||
Animation<Offset> custom = Tween<Offset>(
|
||||
begin: const Offset(0.0, 1.0),
|
||||
end: const Offset(0.0, 0.0))
|
||||
.animate(animation);
|
||||
return SlideTransition(
|
||||
position: custom,
|
||||
child:
|
||||
Dialog.fullscreen(child: SessionView(data: data)));
|
||||
},
|
||||
barrierDismissible: true,
|
||||
barrierLabel: '',
|
||||
context: context,
|
||||
pageBuilder: (context, animation1, animation2) {
|
||||
return Container();
|
||||
}),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
// color: const Color.fromARGB(47, 0, 0, 0),
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
image: const DecorationImage(
|
||||
colorFilter: ColorFilter.mode(
|
||||
Color.fromARGB(220, 41, 39, 39),
|
||||
BlendMode.hardLight),
|
||||
image: AssetImage('assets/images/placeholder.jpg'),
|
||||
fit: BoxFit.cover),
|
||||
),
|
||||
child: Align(
|
||||
alignment: Alignment.center,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
ListTile(
|
||||
title: Text(
|
||||
maxLines: 3,
|
||||
data.title,
|
||||
textAlign: TextAlign.center),
|
||||
subtitle: Text(
|
||||
maxLines: 1,
|
||||
dateFormat.format(data.date),
|
||||
textAlign: TextAlign.center),
|
||||
),
|
||||
])))));
|
||||
}
|
||||
}
|
||||
}
|
221
lib/widgets/session_view.dart
Normal file
221
lib/widgets/session_view.dart
Normal file
@ -0,0 +1,221 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:intl/date_symbol_data_local.dart';
|
||||
|
||||
import 'package:sendtrain/classes/media.dart';
|
||||
import 'package:sendtrain/models/activity_model.dart';
|
||||
import 'package:sendtrain/models/session_model.dart';
|
||||
import 'package:sendtrain/widgets/media_card.dart';
|
||||
|
||||
class SessionView extends StatelessWidget {
|
||||
const SessionView({super.key, required this.data});
|
||||
|
||||
final SessionModel data;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
initializeDateFormatting('en');
|
||||
final DateFormat dateFormat = DateFormat('yyyy-MM-dd');
|
||||
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
AppBar(
|
||||
centerTitle: true,
|
||||
title: Text('Session @ ${dateFormat.format(data.date)}',
|
||||
style: const TextStyle(fontSize: 15)),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 20, right: 20, bottom: 10),
|
||||
child: Text(
|
||||
maxLines: 1,
|
||||
style:
|
||||
const TextStyle(fontSize: 25, fontWeight: FontWeight.bold),
|
||||
data.title)),
|
||||
SessionViewAchievements(achievements: data.achievements),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 15, right: 15),
|
||||
child: Text(textAlign: TextAlign.center, data.content)),
|
||||
SessionViewMedia(media: data.media),
|
||||
const Padding(
|
||||
padding: EdgeInsets.only(top: 25, bottom: 10),
|
||||
child: Text(
|
||||
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
|
||||
'Activities:')),
|
||||
SessionViewActivities(activities: data.activities),
|
||||
// TextButton(
|
||||
// onPressed: () {
|
||||
// Navigator.pop(context);
|
||||
// },
|
||||
// child: const Text('Close'),
|
||||
// ),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class SessionViewActivities extends StatelessWidget {
|
||||
const SessionViewActivities({super.key, this.activities});
|
||||
|
||||
final List<ActivityModel>? activities;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Expanded(
|
||||
child: ListView.builder(
|
||||
shrinkWrap: true,
|
||||
padding: const EdgeInsets.fromLTRB(10, 0, 10, 0),
|
||||
itemCount: activities?.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
return Card(
|
||||
color: const Color(0xff3A5FB6),
|
||||
child: ListTile(
|
||||
// dense: true,
|
||||
focusColor: const Color(0xff3A5FB6),
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.elliptical(10, 10))),
|
||||
onTap: () => showGeneralDialog(
|
||||
barrierColor: Colors.black.withOpacity(0.5),
|
||||
transitionDuration: const Duration(milliseconds: 220),
|
||||
transitionBuilder: (BuildContext context,
|
||||
Animation<double> animation,
|
||||
Animation<double> secondaryAnimation,
|
||||
Widget child) {
|
||||
Animation<Offset> custom = Tween<Offset>(
|
||||
begin: const Offset(0.0, 1.0),
|
||||
end: const Offset(0.0, 0.0))
|
||||
.animate(animation);
|
||||
return SlideTransition(
|
||||
position: custom,
|
||||
child: Dialog(
|
||||
child: Flex(
|
||||
direction: Axis.vertical,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text('${activities?[index].title}'),
|
||||
Text('${activities?[index].categories}'),
|
||||
Text('${activities?[index].description}'),
|
||||
Text('${activities?[index].resources}'),
|
||||
Text('${activities?[index].actions[0].title}'),
|
||||
Text(
|
||||
'${activities?[index].actions[0].description}'),
|
||||
])));
|
||||
},
|
||||
barrierDismissible: true,
|
||||
barrierLabel: '',
|
||||
context: context,
|
||||
pageBuilder: (context, animation1, animation2) {
|
||||
return Container();
|
||||
}),
|
||||
enableFeedback: true,
|
||||
title: Text(maxLines: 1, '${activities?[index].title}'),
|
||||
subtitle: Padding(
|
||||
padding: const EdgeInsets.only(bottom: 3),
|
||||
child:
|
||||
Text(maxLines: 2, '${activities?[index].description}')),
|
||||
));
|
||||
},
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
class SessionViewAchievements extends StatelessWidget {
|
||||
const SessionViewAchievements({super.key, this.achievements});
|
||||
|
||||
final List<String>? achievements;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 10),
|
||||
child: SizedBox(
|
||||
height: 40,
|
||||
child: ListView.builder(
|
||||
scrollDirection: Axis.horizontal,
|
||||
padding: const EdgeInsets.fromLTRB(10, 0, 10, 0),
|
||||
itemCount: achievements?.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(right: 5),
|
||||
child: ActionChip(
|
||||
visualDensity: VisualDensity.compact,
|
||||
avatar: const Icon(Icons.check_circle_outline),
|
||||
label: Text(maxLines: 1, '${achievements?[index]}'),
|
||||
onPressed: () {
|
||||
// setState(() {
|
||||
// favorite = !favorite;
|
||||
// });
|
||||
},
|
||||
));
|
||||
// return Card(
|
||||
// child: ListTile(
|
||||
// // dense: true,
|
||||
// focusColor: Colors.deepPurple,
|
||||
// shape: const RoundedRectangleBorder(
|
||||
// borderRadius: BorderRadius.all(Radius.circular(10))),
|
||||
// onTap: () {},
|
||||
// enableFeedback: true,
|
||||
// title: Text(maxLines: 1, '${achievements?[index]}'),
|
||||
// ));
|
||||
},
|
||||
))),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class SessionViewMedia extends StatelessWidget {
|
||||
const SessionViewMedia({super.key, this.media});
|
||||
|
||||
final List<Media>? media;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
List<Widget> mediaCards = List.generate((media != null) ? media!.length : 0,
|
||||
(i) => MediaCard(media: media![i]));
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
const Padding(
|
||||
padding: EdgeInsets.only(top: 25),
|
||||
child: Text(
|
||||
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
|
||||
'Media:')),
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
height: 100,
|
||||
child: GridView.count(
|
||||
padding: const EdgeInsets.fromLTRB(15, 10, 0, 0),
|
||||
scrollDirection: Axis.horizontal,
|
||||
crossAxisSpacing: 5,
|
||||
mainAxisSpacing: 5,
|
||||
crossAxisCount: 1,
|
||||
children: mediaCards))
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// SizedBox(
|
||||
// height: 100,
|
||||
// width: double.infinity,
|
||||
// child: ListView.builder(
|
||||
// // scrollDirection: Axis.horizontal,
|
||||
// padding: const EdgeInsets.fromLTRB(10, 0, 10, 0),
|
||||
// itemCount: media?.length,
|
||||
// itemBuilder: (BuildContext context, int index) {
|
||||
// return Card(
|
||||
// child: ListTile(
|
||||
// dense: true,
|
||||
// focusColor: Colors.deepPurple,
|
||||
// shape: const RoundedRectangleBorder(
|
||||
// borderRadius: BorderRadius.all(Radius.circular(10))),
|
||||
// onTap: () {},
|
||||
// enableFeedback: true,
|
||||
// title: const Text(maxLines: 1, 'test'),
|
||||
// ));
|
||||
// }))
|
||||
|
Reference in New Issue
Block a user