Add Customers/Tenants pages. Improve login page. Implemented profile page, change and request password reset pages.

This commit is contained in:
Igor Kulikov
2021-06-15 16:38:37 +03:00
parent 21e42820fd
commit 17ce15c98d
33 changed files with 1312 additions and 326 deletions

View File

@@ -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));

View File

@@ -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),
]
)
);
}
}