Created
January 3, 2023 10:59
-
-
Save tushar4303/a6ff0979f7c8ffe15baedcf196e53d11 to your computer and use it in GitHub Desktop.
main.dart file for the example app
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'dart:async'; | |
import 'dart:io'; | |
import 'package:flutter/material.dart'; | |
import 'dart:convert'; | |
import 'package:http/http.dart' as http; | |
import 'package:retry/retry.dart'; | |
import 'package:intl/intl.dart'; | |
import 'package:navbar_router/navbar_router.dart'; | |
import 'dart:convert'; | |
import 'package:collection/collection.dart'; | |
import 'package:timeago/timeago.dart' as timeago; | |
import 'package:cached_network_image/cached_network_image.dart'; | |
void main() { | |
runApp(MyApp()); | |
} | |
class MyApp extends StatelessWidget { | |
MyApp({Key? key}) : super(key: key); | |
final List<Color> colors = [mediumPurple, Colors.orange, Colors.teal]; | |
@override | |
Widget build(BuildContext context) { | |
return MaterialApp( | |
title: 'BottomNavbar Demo', | |
theme: ThemeData( | |
primarySwatch: Colors.indigo, | |
), | |
home: HomePage()); | |
// home: const NavbarSample(title: 'BottomNavbar Demo')); | |
} | |
} | |
class HomePage extends StatelessWidget { | |
HomePage({Key? key}) : super(key: key); | |
List<NavbarItem> items = [ | |
NavbarItem( | |
Icons.home, | |
'Home', | |
), | |
NavbarItem( | |
Icons.notifications, | |
'Notifications', | |
), | |
NavbarItem(Icons.explore, 'Explore'), | |
NavbarItem(Icons.person, 'Profile'), | |
]; | |
final Map<int, Map<String, Widget>> _routes = const { | |
0: { | |
'/': HomeScreen(), | |
}, | |
1: { | |
'/': NotificationPage(), | |
}, | |
2: { | |
'/': MyEvents(), | |
}, | |
3: { | |
'/': HomeScreen(), | |
}, | |
}; | |
@override | |
Widget build(BuildContext context) { | |
return NavbarRouter( | |
errorBuilder: (context) { | |
return const Center(child: Text('Error 404')); | |
}, | |
onBackButtonPressed: (isExiting) { | |
return isExiting; | |
}, | |
destinationAnimationCurve: Curves.fastOutSlowIn, | |
destinationAnimationDuration: 600, | |
decoration: NavbarDecoration( | |
backgroundColor: Colors.white, | |
selectedIconTheme: const IconThemeData(color: Colors.black), | |
navbarType: BottomNavigationBarType.fixed, | |
elevation: 18, | |
selectedLabelTextStyle: const TextStyle(color: Colors.black), | |
enableFeedback: true), | |
destinations: [ | |
for (int i = 0; i < items.length; i++) | |
DestinationRouter( | |
navbarItem: items[i], | |
destinations: [ | |
for (int j = 0; j < _routes[i]!.keys.length; j++) | |
Destination( | |
route: _routes[i]!.keys.elementAt(j), | |
widget: _routes[i]!.values.elementAt(j), | |
), | |
], | |
initialRoute: _routes[i]!.keys.first, | |
), | |
], | |
); | |
} | |
} | |
class HomeScreen extends StatelessWidget { | |
static var route; | |
const HomeScreen({super.key}); | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
appBar: AppBar( | |
backgroundColor: Colors.transparent, | |
automaticallyImplyLeading: false, | |
toolbarHeight: MediaQuery.of(context).size.height * 0.096, | |
elevation: 0.3, | |
title: Transform( | |
transform: Matrix4.translationValues(8.0, -5.6, 0), | |
child: const Text( | |
"Home", | |
textAlign: TextAlign.left, | |
textScaleFactor: 1.3, | |
style: TextStyle(color: Color.fromARGB(255, 30, 29, 29)), | |
), | |
)), | |
); | |
} | |
} | |
class NotificationPage extends StatefulWidget { | |
const NotificationPage({super.key}); | |
@override | |
State<NotificationPage> createState() => _NotificationPageState(); | |
} | |
class _NotificationPageState extends State<NotificationPage> { | |
bool showFrom = false; | |
//set variable for Connectivity subscription listiner | |
final url = | |
"https://gist.githubusercontent.com/tushar4303/0ababbdad3073acd8ab2580b5deb084b/raw/e56d65b028681c9beb3074657e9d81f0d33f5391/notifications.json"; | |
final _filters = []; | |
final _senders = []; | |
final List<Item> _filteredNotifications = []; | |
late Future<List<Item>?> myfuture; | |
@override | |
void initState() { | |
// using this listiner, you can get the medium of connection as well. | |
super.initState(); | |
myfuture = loadNotifications(); | |
} | |
@override | |
void dispose() { | |
super.dispose(); | |
} | |
Future<List<Item>?> loadNotifications() async { | |
final r = RetryOptions(maxAttempts: 3); | |
final response = await r.retry( | |
// Make a GET request | |
() => http.get(Uri.parse(url)).timeout(Duration(seconds: 2)), | |
// Retry on SocketException or TimeoutException | |
retryIf: (e) => e is SocketException || e is TimeoutException, | |
); | |
try { | |
if (response.statusCode == 200) { | |
final NotificationsJson = response.body; | |
final decodedData = jsonDecode(NotificationsJson); | |
var notificationsData = decodedData["notifications"]; | |
var labelsData = decodedData["labels"]; | |
var senderRolesData = decodedData["senderRoles"]; | |
NotificationModel.labels = List.from(labelsData); | |
NotificationModel.senderRoles = List.from(senderRolesData); | |
NotificationModel.items = List.from(notificationsData) | |
.map<Item>((item) => Item.fromMap(item)) | |
.toList(); | |
setState(() { | |
_filters.clear(); | |
_senders.clear(); | |
showFrom = false; | |
_filteredNotifications.clear(); | |
_filteredNotifications.addAll(NotificationModel.items!); | |
}); | |
return NotificationModel.items; | |
} | |
} catch (e) { | |
throw Exception(e.toString()); | |
} | |
} | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
backgroundColor: Color.fromARGB(255, 255, 255, 255), | |
appBar: AppBar( | |
backgroundColor: Colors.transparent, | |
automaticallyImplyLeading: false, | |
toolbarHeight: MediaQuery.of(context).size.height * 0.125, | |
elevation: 0.3, | |
// title: Text("Notifications"), | |
title: Transform( | |
transform: Matrix4.translationValues(8.0, 16.0, 0), | |
child: Column( | |
// mainAxisAlignment: MainAxisAlignment.end, | |
crossAxisAlignment: CrossAxisAlignment.start, | |
children: [ | |
Text( | |
"Notifications", | |
textAlign: TextAlign.left, | |
textScaleFactor: 1.3, | |
style: TextStyle(color: Color.fromARGB(255, 30, 29, 29)), | |
), | |
SizedBox( | |
height: 4, | |
), | |
(NotificationModel.labels != null && | |
NotificationModel.labels!.isNotEmpty) | |
? SingleChildScrollView( | |
scrollDirection: Axis.horizontal, | |
child: Container( | |
margin: EdgeInsets.only(bottom: 16), | |
child: Row( | |
children: [ | |
Transform( | |
transform: Matrix4.translationValues(0, -4, 0), | |
child: Visibility( | |
visible: showFrom, | |
child: Padding( | |
padding: const EdgeInsets.only(right: 16), | |
child: ActionChip( | |
onPressed: () { | |
//if filtertype == Academics then call show modalbottomsheet | |
showModalBottomSheet( | |
enableDrag: true, | |
useRootNavigator: true, | |
isScrollControlled: true, | |
shape: const RoundedRectangleBorder( | |
borderRadius: BorderRadius.vertical( | |
top: Radius.circular(25.0), | |
), | |
), | |
context: context, | |
builder: (builder) { | |
return SingleChildScrollView( | |
child: SizedBox( | |
child: Container( | |
decoration: BoxDecoration( | |
color: Colors.white, | |
borderRadius: BorderRadius.only( | |
topLeft: const Radius | |
.circular(20.0), | |
topRight: const Radius | |
.circular(20.0))), | |
//content starts | |
child: Container( | |
margin: EdgeInsets.only( | |
right: 5.0, | |
left: 5.0, | |
top: 10.0), | |
child: Column( | |
mainAxisAlignment: | |
MainAxisAlignment | |
.spaceBetween, | |
children: <Widget>[ | |
// rounded rectangle grey handle | |
Container( | |
width: 40.0, | |
height: 5.0, | |
decoration: | |
BoxDecoration( | |
borderRadius: | |
BorderRadius | |
.circular( | |
10.0), | |
color: Colors.grey, | |
), | |
), | |
SingleChildScrollView( | |
child: Column( | |
crossAxisAlignment: | |
CrossAxisAlignment | |
.start, | |
mainAxisAlignment: | |
MainAxisAlignment | |
.start, | |
children: (NotificationModel | |
.senderRoles! | |
.map( | |
(sender) { | |
return Column( | |
children: [ | |
ListTile( | |
title: Text( | |
sender), | |
trailing: | |
Visibility( | |
visible: | |
_senders.contains(sender), | |
child: | |
Icon( | |
Icons | |
.done, | |
color: | |
Colors.blueAccent, | |
), | |
), | |
onTap: | |
() { | |
setState( | |
() { | |
if (_senders | |
.contains(sender)) { | |
_senders.remove(sender); | |
} else { | |
_senders.add(sender); | |
} | |
}); | |
}, | |
), | |
Divider(), | |
], | |
); | |
}).toList())), | |
), | |
], | |
), | |
), | |
), | |
), | |
); | |
}); | |
}, | |
label: Text("From"), | |
avatar: Icon( | |
Icons.account_circle, | |
color: Colors.black, | |
), | |
visualDensity: | |
VisualDensity(vertical: -1.5), | |
side: BorderSide( | |
width: 1, | |
color: Color.fromARGB(66, 75, 74, 74)), | |
// surfaceTintColor: Colors.black, | |
shape: RoundedRectangleBorder( | |
borderRadius: BorderRadius.circular(20.0), | |
), | |
), | |
), | |
), | |
), | |
Row( | |
mainAxisAlignment: MainAxisAlignment.start, | |
children: | |
(NotificationModel.labels!.map((filterType) { | |
return Transform( | |
transform: Matrix4.identity()..scale(0.85), | |
child: FilterChip( | |
checkmarkColor: Colors.black, | |
label: Text( | |
filterType, | |
textScaleFactor: 1.1, | |
), | |
// labelPadding: EdgeInsets.symmetric( | |
// horizontal: 4, vertical: 0), | |
selected: _filters.contains(filterType), | |
side: BorderSide( | |
width: 1, | |
color: | |
Color.fromARGB(66, 75, 74, 74)), | |
// surfaceTintColor: Colors.black, | |
shape: RoundedRectangleBorder( | |
borderRadius: | |
BorderRadius.circular(20.0), | |
), | |
selectedColor: | |
Color.fromARGB(180, 224, 220, 220), | |
onSelected: ((value) { | |
setState(() { | |
if (value) { | |
_filters.add(filterType); | |
} else { | |
_filters.removeWhere((name) { | |
return name == filterType; | |
}); | |
} | |
_filteredNotifications.clear(); | |
if (_filters | |
.contains("Academics")) { | |
setState(() { | |
showFrom = true; | |
}); | |
} else { | |
setState(() { | |
showFrom = false; | |
}); | |
} | |
if (_filters.isEmpty) { | |
_filteredNotifications.addAll( | |
NotificationModel.items!); | |
} else { | |
_filteredNotifications.addAll( | |
NotificationModel.items!.where( | |
(notification) => _filters | |
.contains(notification | |
.messageLabel))); | |
} | |
}); | |
}))); | |
}).toList()), | |
), | |
], | |
), | |
), | |
) | |
: Center( | |
child: CircularProgressIndicator( | |
color: Colors.white, | |
)), | |
], | |
), | |
), | |
), | |
body: Column( | |
children: [ | |
Expanded( | |
child: Padding( | |
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 8), | |
child: FutureBuilder( | |
future: myfuture, | |
builder: ((context, snapshot) { | |
if (snapshot.connectionState == ConnectionState.done) { | |
if (snapshot.hasData) { | |
return RefreshIndicator( | |
onRefresh: () async { | |
loadNotifications(); | |
}, | |
child: Padding( | |
padding: const EdgeInsets.only(bottom: 54), | |
child: ListView.builder( | |
itemCount: _filteredNotifications.length, | |
itemBuilder: (context, index) { | |
return NotificationWidget( | |
item: _filteredNotifications[index], | |
); | |
}), | |
), | |
); | |
} else if (snapshot.hasError) { | |
return Text("Some error has occured"); | |
} | |
} | |
return Center( | |
child: CircularProgressIndicator( | |
color: Colors.black, | |
), | |
); | |
}))), | |
), | |
], | |
), | |
// ignore: prefer_const_literals_to_create_immutables | |
); | |
} | |
} | |
class MyEvents extends StatefulWidget { | |
const MyEvents({super.key}); | |
@override | |
State<MyEvents> createState() => _MyEventsState(); | |
} | |
class _MyEventsState extends State<MyEvents> { | |
bool showFrom = false; | |
//set variable for Connectivity subscription listiner | |
final url = | |
"https://gist.githubusercontent.com/tushar4303/675432e0e112e258c971986dbca37156/raw/d805186a9b7fb95b8606fe2b2257fcadadb2a47c/events.json"; | |
final _filters = []; | |
final _senders = []; | |
final List<Item> _filteredEvents = []; | |
late Future<List<Item>?> myfuture; | |
@override | |
void initState() { | |
// using this listiner, you can get the medium of connection as well. | |
super.initState(); | |
myfuture = loadEvents(); | |
} | |
@override | |
void dispose() { | |
super.dispose(); | |
} | |
Future<List<Item>?> loadEvents() async { | |
final r = RetryOptions(maxAttempts: 3); | |
final response = await r.retry( | |
// Make a GET request | |
() => http.get(Uri.parse(url)).timeout(Duration(seconds: 2)), | |
// Retry on SocketException or TimeoutException | |
retryIf: (e) => e is SocketException || e is TimeoutException, | |
); | |
try { | |
if (response.statusCode == 200) { | |
final EventsJson = response.body; | |
final decodedData = jsonDecode(EventsJson); | |
var eventsData = decodedData["events"]; | |
var labelsData = decodedData["labels"]; | |
var senderRolesData = decodedData["senderRoles"]; | |
NotificationModel.labels = List.from(labelsData); | |
NotificationModel.senderRoles = List.from(senderRolesData); | |
NotificationModel.items = List.from(eventsData) | |
.map<Item>((item) => Item.fromMap(item)) | |
.toList(); | |
setState(() { | |
_filters.clear(); | |
_senders.clear(); | |
showFrom = false; | |
_filteredEvents.clear(); | |
_filteredEvents.addAll(NotificationModel.items!); | |
}); | |
return NotificationModel.items; | |
} | |
} catch (e) { | |
throw Exception(e.toString()); | |
} | |
} | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
backgroundColor: Color.fromARGB(255, 255, 255, 255), | |
appBar: AppBar( | |
backgroundColor: Colors.transparent, | |
automaticallyImplyLeading: false, | |
toolbarHeight: MediaQuery.of(context).size.height * 0.125, | |
elevation: 0.3, | |
// title: Text("Notifications"), | |
title: Transform( | |
transform: Matrix4.translationValues(8.0, 16.0, 0), | |
child: Column( | |
// mainAxisAlignment: MainAxisAlignment.end, | |
crossAxisAlignment: CrossAxisAlignment.start, | |
children: [ | |
Text( | |
"Events", | |
textAlign: TextAlign.left, | |
textScaleFactor: 1.3, | |
style: TextStyle(color: Color.fromARGB(255, 30, 29, 29)), | |
), | |
SizedBox( | |
height: 4, | |
), | |
(NotificationModel.labels != null && | |
NotificationModel.labels!.isNotEmpty) | |
? SingleChildScrollView( | |
scrollDirection: Axis.horizontal, | |
child: Container( | |
margin: EdgeInsets.only(bottom: 16), | |
child: Row( | |
children: [ | |
Transform( | |
transform: Matrix4.translationValues(0, -4, 0), | |
child: Visibility( | |
visible: showFrom, | |
child: Padding( | |
padding: const EdgeInsets.only(right: 16), | |
child: ActionChip( | |
onPressed: () { | |
//if filtertype == Academics then call show modalbottomsheet | |
showModalBottomSheet( | |
enableDrag: true, | |
useRootNavigator: true, | |
isScrollControlled: true, | |
shape: const RoundedRectangleBorder( | |
borderRadius: BorderRadius.vertical( | |
top: Radius.circular(25.0), | |
), | |
), | |
context: context, | |
builder: (builder) { | |
return SingleChildScrollView( | |
child: SizedBox( | |
child: Container( | |
decoration: BoxDecoration( | |
color: Colors.white, | |
borderRadius: BorderRadius.only( | |
topLeft: const Radius | |
.circular(20.0), | |
topRight: const Radius | |
.circular(20.0))), | |
//content starts | |
child: Container( | |
margin: EdgeInsets.only( | |
right: 5.0, | |
left: 5.0, | |
top: 10.0), | |
child: Column( | |
mainAxisAlignment: | |
MainAxisAlignment | |
.spaceBetween, | |
children: <Widget>[ | |
// rounded rectangle grey handle | |
Container( | |
width: 40.0, | |
height: 5.0, | |
decoration: | |
BoxDecoration( | |
borderRadius: | |
BorderRadius | |
.circular( | |
10.0), | |
color: Colors.grey, | |
), | |
), | |
SingleChildScrollView( | |
child: Column( | |
crossAxisAlignment: | |
CrossAxisAlignment | |
.start, | |
mainAxisAlignment: | |
MainAxisAlignment | |
.start, | |
children: (NotificationModel | |
.senderRoles! | |
.map( | |
(sender) { | |
return Column( | |
children: [ | |
ListTile( | |
title: Text( | |
sender), | |
trailing: | |
Visibility( | |
visible: | |
_senders.contains(sender), | |
child: | |
Icon( | |
Icons | |
.done, | |
color: | |
Colors.blueAccent, | |
), | |
), | |
onTap: | |
() { | |
setState( | |
() { | |
if (_senders | |
.contains(sender)) { | |
_senders.remove(sender); | |
} else { | |
_senders.add(sender); | |
} | |
}); | |
}, | |
), | |
Divider(), | |
], | |
); | |
}).toList())), | |
), | |
], | |
), | |
), | |
), | |
), | |
); | |
}); | |
}, | |
label: Text("From"), | |
avatar: Icon( | |
Icons.auto_awesome, | |
color: Colors.black, | |
), | |
visualDensity: | |
VisualDensity(vertical: -1.5), | |
side: BorderSide( | |
width: 1, | |
color: Color.fromARGB(66, 75, 74, 74)), | |
// surfaceTintColor: Colors.black, | |
shape: RoundedRectangleBorder( | |
borderRadius: BorderRadius.circular(20.0), | |
), | |
), | |
), | |
), | |
), | |
Row( | |
mainAxisAlignment: MainAxisAlignment.start, | |
children: | |
(NotificationModel.labels!.map((filterType) { | |
return Transform( | |
transform: Matrix4.identity()..scale(0.85), | |
child: FilterChip( | |
checkmarkColor: Colors.black, | |
label: Text( | |
filterType, | |
textScaleFactor: 1.1, | |
), | |
// labelPadding: EdgeInsets.symmetric( | |
// horizontal: 4, vertical: 0), | |
selected: _filters.contains(filterType), | |
side: BorderSide( | |
width: 1, | |
color: | |
Color.fromARGB(66, 75, 74, 74)), | |
// surfaceTintColor: Colors.black, | |
shape: RoundedRectangleBorder( | |
borderRadius: | |
BorderRadius.circular(20.0), | |
), | |
selectedColor: | |
Color.fromARGB(180, 224, 220, 220), | |
onSelected: ((value) { | |
setState(() { | |
if (value) { | |
_filters.add(filterType); | |
} else { | |
_filters.removeWhere((name) { | |
return name == filterType; | |
}); | |
} | |
_filteredEvents.clear(); | |
if (_filters | |
.contains("Technical")) { | |
setState(() { | |
showFrom = true; | |
}); | |
} else { | |
setState(() { | |
showFrom = false; | |
}); | |
} | |
if (_filters.isEmpty) { | |
_filteredEvents.addAll( | |
NotificationModel.items!); | |
} else { | |
_filteredEvents.addAll( | |
NotificationModel.items!.where( | |
(notification) => _filters | |
.contains(notification | |
.messageLabel))); | |
} | |
}); | |
}))); | |
}).toList()), | |
), | |
], | |
), | |
), | |
) | |
: Center( | |
child: CircularProgressIndicator( | |
color: Colors.white, | |
)), | |
], | |
), | |
), | |
), | |
body: Column( | |
children: [ | |
Expanded( | |
child: Padding( | |
padding: | |
const EdgeInsets.symmetric(horizontal: 16, vertical: 8), | |
child: FutureBuilder( | |
future: myfuture, | |
builder: ((context, snapshot) { | |
if (snapshot.connectionState == ConnectionState.done) { | |
if (snapshot.hasData) { | |
return RefreshIndicator( | |
onRefresh: () async { | |
loadEvents(); | |
}, | |
child: Padding( | |
padding: | |
const EdgeInsets.only(bottom: 54, top: 4), | |
child: GridView.builder( | |
itemCount: _filteredEvents.length, | |
itemBuilder: (context, index) { | |
return EventsWidget( | |
item: _filteredEvents[index]); | |
}, | |
gridDelegate: | |
SliverGridDelegateWithFixedCrossAxisCount( | |
crossAxisCount: 2, | |
crossAxisSpacing: 16.0, | |
mainAxisSpacing: 12.0, | |
mainAxisExtent: 310.0), | |
), | |
), | |
); | |
} else if (snapshot.hasError) { | |
return Text("Some error has occured"); | |
} | |
} | |
return Center( | |
child: CircularProgressIndicator( | |
color: Colors.black, | |
), | |
); | |
}))), | |
), | |
], | |
), | |
// ignore: prefer_const_literals_to_create_immutables | |
); | |
} | |
} | |
class EventsWidget extends StatelessWidget { | |
const EventsWidget({super.key, required this.item}); | |
final Item item; | |
@override | |
Widget build(BuildContext context) { | |
return Hero( | |
tag: Key(item.messageId.toString()), | |
child: InkWell( | |
onTap: () { | |
Navigator.push( | |
context, | |
MaterialPageRoute( | |
builder: (context) => NotificationDetailsPage(item: item))); | |
}, | |
child: Column( | |
children: [ | |
ClipRRect( | |
borderRadius: const BorderRadius.all(Radius.circular(12)), | |
child: Stack( | |
children: <Widget>[ | |
Container( | |
height: 260, | |
decoration: BoxDecoration( | |
borderRadius: BorderRadius.circular(12.0)), | |
child: CachedNetworkImage( | |
fit: BoxFit.cover, | |
imageUrl: item.imageUrl, | |
placeholder: (context, url) { | |
return Image.asset( | |
"assets/images/placeholder.png", | |
fit: BoxFit.cover, | |
); | |
}, | |
), | |
), | |
Positioned( | |
child: Container( | |
margin: const EdgeInsets.only(top: 236), | |
height: 24, | |
color: const Color.fromARGB(165, 0, 0, 0), | |
child: Align( | |
alignment: Alignment.centerLeft, | |
child: Padding( | |
padding: const EdgeInsets.only(left: 8), | |
child: RichText( | |
maxLines: 2, | |
textAlign: TextAlign.left, | |
overflow: TextOverflow.ellipsis, | |
text: TextSpan( | |
text: null, | |
style: const TextStyle( | |
fontSize: 12, color: Colors.black87), | |
children: [ | |
const WidgetSpan( | |
child: Icon( | |
Icons.watch_later_outlined, | |
size: 12, | |
color: Colors.white, | |
), | |
), | |
TextSpan( | |
text: | |
" ${DateFormat('MMM d, ' 'yy').format(item.dateOfcreation)}", | |
style: const TextStyle( | |
fontSize: 12, | |
color: Colors.white, | |
fontWeight: FontWeight.w500)), | |
]), | |
), | |
), | |
), | |
), | |
), | |
], | |
), | |
), | |
const SizedBox( | |
height: 8, | |
), | |
Align( | |
alignment: Alignment.topLeft, | |
child: Text(item.messageTitle, | |
maxLines: 2, | |
textAlign: TextAlign.left, | |
overflow: TextOverflow.ellipsis, | |
style: const TextStyle( | |
fontSize: 16, fontWeight: FontWeight.bold)), | |
), | |
// Align( | |
// alignment: Alignment.topLeft, | |
// child: Text( | |
// item | |
// .messageLabel, | |
// maxLines: 2, | |
// textAlign: TextAlign.left, | |
// overflow: TextOverflow.ellipsis, | |
// style: const TextStyle( | |
// fontSize: 14, | |
// )), | |
// ), | |
], | |
), | |
)); | |
} | |
} | |
// ignore_for_file: prefer_const_constructors | |
// ignore_for_file: public_member_api_docs, sort_constructors_first | |
class NotificationModel { | |
static List<String>? labels; | |
static List<String>? senderRoles; | |
static List<Item>? items; | |
} | |
class SenderRoles { | |
final List senderRoles; | |
SenderRoles( | |
this.senderRoles, | |
); | |
SenderRoles copyWith({ | |
List? senderRoles, | |
}) { | |
return SenderRoles( | |
senderRoles ?? this.senderRoles, | |
); | |
} | |
Map<String, dynamic> toMap() { | |
return <String, dynamic>{ | |
'senderRoles': senderRoles, | |
}; | |
} | |
factory SenderRoles.fromMap(Map<String, dynamic> map) { | |
return SenderRoles(List.from( | |
(map['senderRoles'] as List), | |
)); | |
} | |
String toJson() => json.encode(toMap()); | |
factory SenderRoles.fromJson(String source) => | |
SenderRoles.fromMap(json.decode(source) as Map<String, dynamic>); | |
@override | |
String toString() => 'SenderRoles(senderRoles: $senderRoles)'; | |
@override | |
bool operator ==(covariant SenderRoles other) { | |
if (identical(this, other)) return true; | |
final listEquals = const DeepCollectionEquality().equals; | |
return listEquals(other.senderRoles, senderRoles); | |
} | |
@override | |
int get hashCode => senderRoles.hashCode; | |
} | |
class Labels { | |
final List labels; | |
Labels( | |
this.labels, | |
); | |
Labels copyWith({ | |
List? labels, | |
}) { | |
return Labels( | |
labels ?? this.labels, | |
); | |
} | |
Map<String, dynamic> toMap() { | |
return <String, dynamic>{ | |
'labels': labels, | |
}; | |
} | |
factory Labels.fromMap(Map<String, dynamic> map) { | |
return Labels(List.from( | |
(map['labels'] as List), | |
)); | |
} | |
String toJson() => json.encode(toMap()); | |
factory Labels.fromJson(String source) => | |
Labels.fromMap(json.decode(source) as Map<String, dynamic>); | |
@override | |
String toString() => 'Labels(labels: $labels)'; | |
@override | |
bool operator ==(covariant Labels other) { | |
if (identical(this, other)) return true; | |
final listEquals = const DeepCollectionEquality().equals; | |
return listEquals(other.labels, labels); | |
} | |
@override | |
int get hashCode => labels.hashCode; | |
} | |
class Item { | |
final int messageId; | |
final String userName; | |
final String userRole; | |
final String messageTitle; | |
final String messageLabel; | |
final String userMessage; | |
final String imageUrl; | |
final DateTime dateOfcreation; | |
Item( | |
{required this.messageId, | |
required this.userName, | |
required this.userRole, | |
required this.messageTitle, | |
required this.messageLabel, | |
required this.userMessage, | |
required this.imageUrl, | |
required this.dateOfcreation}); | |
factory Item.fromMap(Map<String, dynamic> map) { | |
return Item( | |
messageId: map["message_id"], | |
userName: map["userName"], | |
userRole: map["userRole"], | |
messageTitle: map["message_title"], | |
messageLabel: map["message_label"], | |
userMessage: map["user_message"], | |
imageUrl: map["image_url"], | |
dateOfcreation: DateTime.parse(map["dateOfcreation"]), | |
); | |
} | |
toMap() => { | |
"message_id": messageId, | |
"userName": userName, | |
"userRole": userRole, | |
"message_title": messageTitle, | |
"message_label": messageLabel, | |
"user_message": userMessage, | |
"image_url": imageUrl, | |
"dateOfcreation": dateOfcreation, | |
}; | |
@override | |
String toString() { | |
return 'Item(messageId: $messageId, userName: $userName, userRole: $userRole, messageTitle: $messageTitle, messageLabel: $messageLabel, userMessage: $userMessage, imageUrl: $imageUrl, dateOfcreation: $dateOfcreation)'; | |
} | |
} | |
class NotificationWidget extends StatelessWidget { | |
const NotificationWidget({super.key, required this.item}); | |
final Item item; | |
@override | |
Widget build(BuildContext context) { | |
return Hero( | |
tag: Key(item.messageId.toString()), | |
child: SizedBox( | |
width: double.infinity, | |
// height: MediaQuery.of(context).size.height * 0.1155, | |
child: Card( | |
// color: Colors.amberAccent, | |
elevation: 0.0, | |
margin: const EdgeInsets.only(bottom: 12), | |
child: ListTile( | |
onTap: () { | |
Navigator.push( | |
context, | |
MaterialPageRoute( | |
builder: (context) => | |
NotificationDetailsPage(item: item))); | |
}, | |
leading: CircleAvatar( | |
backgroundImage: NetworkImage(item.imageUrl), | |
child: const Text('DP')), | |
title: Column( | |
crossAxisAlignment: CrossAxisAlignment.start, | |
children: [ | |
RichText( | |
maxLines: 1, | |
overflow: TextOverflow.ellipsis, | |
text: TextSpan( | |
text: item.userRole, | |
style: const TextStyle( | |
fontWeight: FontWeight.w600, color: Colors.black), | |
children: <TextSpan>[ | |
TextSpan( | |
text: " @${item.userName}", | |
style: const TextStyle(fontWeight: FontWeight.w400), | |
) | |
], | |
), | |
), | |
const SizedBox( | |
height: 1, | |
), | |
Text(item.messageTitle, | |
textScaleFactor: 0.9, | |
maxLines: 1, | |
overflow: TextOverflow.ellipsis, | |
style: const TextStyle(fontWeight: FontWeight.w600)), | |
Padding( | |
padding: const EdgeInsets.only(top: 3), | |
child: Text( | |
item.userMessage, | |
textScaleFactor: 0.9, | |
maxLines: 2, | |
overflow: TextOverflow.ellipsis, | |
), | |
), | |
], | |
), | |
trailing: Text( | |
DateFormat('MMM d, ' 'yy').format(item.dateOfcreation), | |
textAlign: TextAlign.end, | |
textScaleFactor: 0.8, | |
), | |
), | |
), | |
), | |
); | |
} | |
} | |
// ignore_for_file: prefer_const_constructors | |
class NotificationDetailsPage extends StatelessWidget { | |
const NotificationDetailsPage({ | |
Key? key, | |
required this.item, | |
}) : super(key: key); | |
final Item item; | |
@override | |
Widget build(BuildContext context) { | |
return SafeArea( | |
child: Scaffold( | |
backgroundColor: Colors.white, | |
// appBar: SliverAppBar(), | |
body: NestedScrollView( | |
floatHeaderSlivers: true, | |
headerSliverBuilder: (context, innerBoxIsScrolled) => [ | |
const SliverAppBar( | |
floating: true, | |
) | |
], | |
body: Padding( | |
padding: const EdgeInsets.only( | |
left: 24, right: 24, bottom: 54, top: 8), | |
child: SingleChildScrollView( | |
child: Column( | |
crossAxisAlignment: CrossAxisAlignment.start, | |
children: [ | |
Container( | |
margin: const EdgeInsets.only(top: 8, bottom: 16), | |
decoration: const BoxDecoration( | |
color: Color.fromRGBO(240, 221, 245, 1), | |
borderRadius: | |
BorderRadius.all(Radius.circular(10))), | |
child: Padding( | |
padding: const EdgeInsets.all(8.0), | |
child: Text( | |
item.messageLabel, | |
style: const TextStyle( | |
fontWeight: FontWeight.w500, | |
color: Color.fromRGBO(30, 29, 29, 0.8)), | |
), | |
), | |
), | |
Text( | |
item.messageTitle, | |
style: const TextStyle( | |
fontWeight: FontWeight.w400, | |
fontSize: 28, | |
color: Color.fromARGB(255, 30, 29, 29)), | |
), | |
//start | |
Padding( | |
padding: const EdgeInsets.symmetric(vertical: 16), | |
child: Row( | |
crossAxisAlignment: CrossAxisAlignment.center, | |
mainAxisAlignment: MainAxisAlignment.start, | |
children: [ | |
CircleAvatar( | |
backgroundImage: NetworkImage(item.imageUrl)), | |
const SizedBox( | |
width: 8, | |
), | |
Column( | |
crossAxisAlignment: CrossAxisAlignment.start, | |
children: [ | |
RichText( | |
text: TextSpan( | |
text: item.userRole, | |
style: const TextStyle( | |
fontWeight: FontWeight.w600, | |
color: Colors.black), | |
children: <TextSpan>[ | |
TextSpan( | |
text: " @${item.userName}", | |
style: const TextStyle( | |
fontWeight: FontWeight.w400), | |
) | |
], | |
), | |
), | |
Row( | |
children: [ | |
const Icon( | |
Icons.watch_later_outlined, | |
size: 16, | |
), | |
const SizedBox( | |
width: 2, | |
), | |
Text(timeago.format(item.dateOfcreation)), | |
], | |
), | |
], | |
) | |
], | |
), | |
), | |
Hero( | |
tag: Key(item.messageId.toString()), | |
child: Padding( | |
padding: const EdgeInsets.symmetric(vertical: 8), | |
child: ClipRRect( | |
borderRadius: | |
const BorderRadius.all(Radius.circular(16)), | |
child: CachedNetworkImage( | |
imageUrl: item.imageUrl, | |
placeholder: (context, url) { | |
return Image.asset( | |
"assets/images/placeholder.png", | |
fit: BoxFit.cover, | |
); | |
}, | |
), | |
), | |
), | |
), | |
Padding( | |
padding: const EdgeInsets.symmetric(vertical: 16), | |
child: Text( | |
item.userMessage, | |
textAlign: TextAlign.left, | |
style: const TextStyle(fontSize: 16), | |
), | |
) | |
], | |
), | |
), | |
))), | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment