Add Customers/Tenants pages. Improve login page. Implemented profile page, change and request password reset pages.
This commit is contained in:
@@ -6,6 +6,7 @@ import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:thingsboard_app/core/context/tb_context.dart';
|
||||
import 'package:thingsboard_app/core/context/tb_context_widget.dart';
|
||||
import 'package:thingsboard_app/utils/utils.dart';
|
||||
import 'package:thingsboard_client/thingsboard_client.dart';
|
||||
|
||||
const Map<EntityType, String> entityTypeTranslations = {
|
||||
@@ -75,6 +76,77 @@ mixin EntitiesBase<T, P> on HasTbContext {
|
||||
|
||||
}
|
||||
|
||||
mixin ContactBasedBase<T extends ContactBased, P> on EntitiesBase<T,P> {
|
||||
|
||||
@override
|
||||
Widget buildEntityListCard(BuildContext context, T contact) {
|
||||
var address = Utils.contactToShortAddress(contact);
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(vertical: 12, horizontal: 16),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Flexible(
|
||||
fit: FlexFit.tight,
|
||||
child:
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
FittedBox(
|
||||
fit: BoxFit.fitWidth,
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text('${contact.getName()}',
|
||||
style: TextStyle(
|
||||
color: Color(0xFF282828),
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
height: 20 / 14
|
||||
))
|
||||
),
|
||||
Text(entityDateFormat.format(DateTime.fromMillisecondsSinceEpoch(contact.createdTime!)),
|
||||
style: TextStyle(
|
||||
color: Color(0xFFAFAFAF),
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.normal,
|
||||
height: 16 / 12
|
||||
))
|
||||
]
|
||||
),
|
||||
SizedBox(height: 4),
|
||||
if (contact.email != null) Text(contact.email!,
|
||||
style: TextStyle(
|
||||
color: Color(0xFFAFAFAF),
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.normal,
|
||||
height: 16 / 12
|
||||
)),
|
||||
if (contact.email == null)
|
||||
SizedBox(height: 16),
|
||||
if (address != null) SizedBox(height: 4),
|
||||
if (address != null) Text(address,
|
||||
style: TextStyle(
|
||||
color: Color(0xFFAFAFAF),
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.normal,
|
||||
height: 16 / 12
|
||||
)),
|
||||
],
|
||||
)
|
||||
),
|
||||
SizedBox(width: 16),
|
||||
Icon(Icons.chevron_right, color: Color(0xFFACACAC)),
|
||||
SizedBox(width: 8)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class PageKeyController<P> extends ValueNotifier<PageKeyValue<P>> {
|
||||
|
||||
PageKeyController(P initialPageKey) : super(PageKeyValue(initialPageKey));
|
||||
|
||||
@@ -9,8 +9,21 @@ import 'package:thingsboard_client/thingsboard_client.dart';
|
||||
|
||||
abstract class EntityDetailsPage<T extends BaseData> extends TbPageWidget<EntityDetailsPage<T>, _EntityDetailsPageState<T>> {
|
||||
|
||||
final labelTextStyle = TextStyle(
|
||||
color: Color(0xFF757575),
|
||||
fontSize: 14,
|
||||
height: 20 / 14
|
||||
);
|
||||
|
||||
final valueTextStyle = TextStyle(
|
||||
color: Color(0xFF282828),
|
||||
fontSize: 14,
|
||||
height: 20 / 14
|
||||
);
|
||||
|
||||
final String _defaultTitle;
|
||||
final String _entityId;
|
||||
final String? _subTitle;
|
||||
final bool _showLoadingIndicator;
|
||||
final bool _hideAppBar;
|
||||
final double? _appBarElevation;
|
||||
@@ -18,11 +31,13 @@ abstract class EntityDetailsPage<T extends BaseData> extends TbPageWidget<Entity
|
||||
EntityDetailsPage(TbContext tbContext,
|
||||
{required String defaultTitle,
|
||||
required String entityId,
|
||||
String? subTitle,
|
||||
bool showLoadingIndicator = true,
|
||||
bool hideAppBar = false,
|
||||
double? appBarElevation}):
|
||||
this._defaultTitle = defaultTitle,
|
||||
this._entityId = entityId,
|
||||
this._subTitle = subTitle,
|
||||
this._showLoadingIndicator = showLoadingIndicator,
|
||||
this._hideAppBar = hideAppBar,
|
||||
this._appBarElevation = appBarElevation,
|
||||
@@ -66,17 +81,33 @@ class _EntityDetailsPageState<T extends BaseData> extends TbPageState<EntityDeta
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.white,
|
||||
appBar: widget._hideAppBar ? null : TbAppBar(
|
||||
tbContext,
|
||||
showLoadingIndicator: widget._showLoadingIndicator,
|
||||
elevation: widget._appBarElevation,
|
||||
title: ValueListenableBuilder<String>(
|
||||
valueListenable: titleValue,
|
||||
builder: (context, title, widget) {
|
||||
return FittedBox(
|
||||
fit: BoxFit.fitWidth,
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(title)
|
||||
builder: (context, title, _widget) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
FittedBox(
|
||||
fit: BoxFit.fitWidth,
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text(title,
|
||||
style: widget._subTitle != null ? Theme.of(context).primaryTextTheme.headline6!.copyWith(
|
||||
fontSize: 16
|
||||
) : null
|
||||
)
|
||||
),
|
||||
if (widget._subTitle != null) Text(widget._subTitle!, style: TextStyle(
|
||||
color: Theme.of(context).primaryTextTheme.headline6!.color!.withAlpha((0.38 * 255).ceil()),
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.normal,
|
||||
height: 16 / 12
|
||||
))
|
||||
]
|
||||
);
|
||||
},
|
||||
),
|
||||
@@ -98,3 +129,77 @@ class _EntityDetailsPageState<T extends BaseData> extends TbPageState<EntityDeta
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
abstract class ContactBasedDetailsPage<T extends ContactBased> extends EntityDetailsPage<T> {
|
||||
|
||||
ContactBasedDetailsPage(TbContext tbContext,
|
||||
{ required String defaultTitle,
|
||||
required String entityId,
|
||||
String? subTitle,
|
||||
bool showLoadingIndicator = true,
|
||||
bool hideAppBar = false,
|
||||
double? appBarElevation}):
|
||||
super(tbContext, defaultTitle: defaultTitle, entityId: entityId,
|
||||
subTitle: subTitle, showLoadingIndicator: showLoadingIndicator,
|
||||
hideAppBar: hideAppBar, appBarElevation: appBarElevation);
|
||||
|
||||
@override
|
||||
Widget buildEntityDetails(BuildContext context, T contact) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.all(16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Text('Title', style: labelTextStyle),
|
||||
Text(contact.getName(), style: valueTextStyle),
|
||||
SizedBox(height: 16),
|
||||
Text('Country', style: labelTextStyle),
|
||||
Text(contact.country ?? '', style: valueTextStyle),
|
||||
SizedBox(height: 16),
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Flexible(
|
||||
fit: FlexFit.tight,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Text('City', style: labelTextStyle),
|
||||
Text(contact.city ?? '', style: valueTextStyle),
|
||||
],
|
||||
)),
|
||||
Flexible(
|
||||
fit: FlexFit.tight,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Text('State / Province', style: labelTextStyle),
|
||||
Text(contact.state ?? '', style: valueTextStyle),
|
||||
],
|
||||
)),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
Text('Zip / Postal Code', style: labelTextStyle),
|
||||
Text(contact.zip ?? '', style: valueTextStyle),
|
||||
SizedBox(height: 16),
|
||||
Text('Address', style: labelTextStyle),
|
||||
Text(contact.address ?? '', style: valueTextStyle),
|
||||
SizedBox(height: 16),
|
||||
Text('Address 2', style: labelTextStyle),
|
||||
Text(contact.address2 ?? '', style: valueTextStyle),
|
||||
SizedBox(height: 16),
|
||||
Text('Phone', style: labelTextStyle),
|
||||
Text(contact.phone ?? '', style: valueTextStyle),
|
||||
SizedBox(height: 16),
|
||||
Text('Email', style: labelTextStyle),
|
||||
Text(contact.email ?? '', style: valueTextStyle),
|
||||
]
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user