diff --git a/lib/src/models/user.dart b/lib/src/models/user.dart index 83e62ff..a4ee6e0 100644 --- a/lib/src/models/user.dart +++ b/lib/src/models/user.dart @@ -3,6 +3,9 @@ import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:profile/profile.dart'; +/// User is used to contain all user data. It consists of three standard fields: firstName, lastName and image. +/// +/// For additional data profileData can be used. class User { String? firstName; String? lastName; @@ -35,6 +38,11 @@ class User { } } +/// ProfileData is used to store custom/addintional data for a user. +/// +/// The MapWidget method is used to bind a [Widget] to one of the keys. This will override the standard textfield. +/// +/// The Builditems method is used to make the list of field to house the user data. abstract class ProfileData { const ProfileData(); diff --git a/lib/src/services/profile_service.dart b/lib/src/services/profile_service.dart index c1a35ce..f9d27f0 100644 --- a/lib/src/services/profile_service.dart +++ b/lib/src/services/profile_service.dart @@ -1,6 +1,13 @@ import 'package:flutter/material.dart'; import 'package:profile/profile.dart'; +/// ProfileService can be extended and set for the profilePage. The following method can be overriden. +/// +/// DeleteProfile is called when the user want to delete their profile. +/// +/// EditProfile is called when a user changes and submits a standard textfields. +/// +/// UploadImage is called when te user presses the avatar. abstract class ProfileService { const ProfileService(); diff --git a/lib/src/widgets/avatar/avatar_style.dart b/lib/src/widgets/avatar/avatar_style.dart index c944e24..3107a90 100644 --- a/lib/src/widgets/avatar/avatar_style.dart +++ b/lib/src/widgets/avatar/avatar_style.dart @@ -1,5 +1,14 @@ import 'package:flutter/material.dart'; +/// AvatarStyle is used to set the style of the avatar displayed at the top of the [ProfilePage]. +/// +/// Width is used to set the width of the avatar. Defaults to 100. +/// +/// Height is used to set the height of the avatar. Defaults to 100. +/// +/// InitialStyle sets the [TextStyle] of the initial which are shown when no image is provided. +/// +/// DisplayNameStyle sets the [TextStyle] for the displayname underneath the avatar. class AvatarStyle { const AvatarStyle({ this.width = 100, diff --git a/lib/src/widgets/item_builder/item_builder.dart b/lib/src/widgets/item_builder/item_builder.dart index f28bdf9..70e81fb 100644 --- a/lib/src/widgets/item_builder/item_builder.dart +++ b/lib/src/widgets/item_builder/item_builder.dart @@ -1,6 +1,9 @@ import 'package:flutter/material.dart'; import 'package:profile/src/widgets/item_builder/item_builder_options.dart'; +/// ItemBuilder is used to set the standard textfield for each undefined users data item. +/// +/// Options sets options for the textfield. class ItemBuilder { ItemBuilder({ required this.options, diff --git a/lib/src/widgets/item_builder/item_builder_options.dart b/lib/src/widgets/item_builder/item_builder_options.dart index 2ab6356..b6d60a3 100644 --- a/lib/src/widgets/item_builder/item_builder_options.dart +++ b/lib/src/widgets/item_builder/item_builder_options.dart @@ -1,5 +1,12 @@ import 'package:flutter/material.dart'; +/// ItemBuilderOptions is a class to store all settings for a field in the profile page. +/// +/// InputDecoration sets the decoration for all standard textfields. This is overridden if a field specific decoration is set by inputDecorationField. +/// +/// inputDecorationField sets the inputdecoration by key of the user data field. So a field can have its own specific decoration. +/// +/// Validator can be used to set a validator for the standard textfield. class ItemBuilderOptions { ItemBuilderOptions({ this.inputDecoration = const InputDecoration(), diff --git a/lib/src/widgets/profile/profile_page.dart b/lib/src/widgets/profile/profile_page.dart index a87d1f1..59fc135 100644 --- a/lib/src/widgets/profile/profile_page.dart +++ b/lib/src/widgets/profile/profile_page.dart @@ -1,7 +1,24 @@ import 'package:flutter/material.dart'; import 'package:profile/profile.dart'; -import 'package:profile/src/widgets/avatar/avatar.dart'; +import 'package:profile/src/widgets/profile/proifle_wrapper.dart'; +/// The ProfilePage widget is able to show the data of a user. By default the user is able to change this data. The widget has a couple of parameters listed below: +/// +/// User will contain the data of the user which atleast contain a first name, last name and an avatar/image. Besides this information the [ProfileData] can be used to set custom user fields. +/// +/// With the use of the service set by a [ProfileService] some actions can be determined what should occur when the user does the following actions: Deleting/editing the profile or uploading an image. +/// +/// The style can be used the set some style options regarding the whole form. This is done by setting a [ProfileStyle]. The following styling can be set: The style of the avatar, the padding of the page and default padding between items. +/// +/// CustomAvatar can be set to override the standard avatar using any [Widget]. +/// +/// ShowAvatar can be set using a [bool] to determine whether the avatar should be shown and be able to be set by the user. Default set to true. +/// +/// ShowDeleteProfile can be set using a [bool] set determine whether te user can delete the profile. Default set to true. +/// +/// ItemBuilder is used to determine how the user data is represented. +/// +/// ItemBuilderOptions can be used to just set the settings for fields instead of defining the field itself and how it is used. This field should not be used when the itemBuilder is set. class ProfilePage extends StatefulWidget { const ProfilePage({ Key? key, @@ -15,14 +32,28 @@ class ProfilePage extends StatefulWidget { this.showDeleteProfile = true, }) : super(key: key); + /// User containing all the user data. final User user; + + /// The service the determine what should happen when the user takes action. final ProfileService service; + + /// Style to set some general styling parameters fot the whole page. final ProfileStyle style; + + /// The way to override the standard avatar is needed. final Widget? customAvatar; + + /// Whether to show the users avatar. final bool showAvatar; + + /// Whether to give the user the option to delete their own profile. final bool showDeleteProfile; + + /// Itembuilder is used the build each field in the user. final ItemBuilder? itemBuilder; + /// Used to set settings of eacht field in user. final ItemBuilderOptions? itemBuilderOptions; @override @@ -48,140 +79,3 @@ class _ProfilePageState extends State { ); } } - -class ProfileWrapper extends StatefulWidget { - const ProfileWrapper({ - Key? key, - required this.user, - required this.service, - required this.rebuild, - this.style = const ProfileStyle(), - this.customAvatar, - this.showAvatar = true, - this.itemBuilder, - this.itemBuilderOptions, - this.showDeleteProfile = true, - }) : super(key: key); - - final User user; - final ProfileService service; - final ProfileStyle style; - final Widget? customAvatar; - final bool showAvatar; - final bool showDeleteProfile; - final ItemBuilder? itemBuilder; - final Function rebuild; - final ItemBuilderOptions? itemBuilderOptions; - - @override - State createState() => _ProfileWrapperState(); -} - -class _ProfileWrapperState extends State { - List defaultItems = []; - - @override - void initState() { - super.initState(); - - if (widget.itemBuilder == null) { - ItemBuilder builder = ItemBuilder( - options: widget.itemBuilderOptions ?? ItemBuilderOptions(), - ); - defaultItems - .add(builder.build('firstName', widget.user.firstName, null, (v) { - widget.user.firstName = v; - - widget.service.editProfile(widget.user, 'firstName', v); - })); - defaultItems.add( - SizedBox( - height: widget.style.betweenDefaultItemPadding, - ), - ); - defaultItems - .add(builder.build('lastName', widget.user.lastName, null, (v) { - widget.user.lastName = v; - - widget.service.editProfile(widget.user, 'lastName', v); - })); - } else { - defaultItems.add(widget.itemBuilder! - .build('firstName', widget.user.firstName, null, (v) { - widget.user.firstName = v; - - widget.service.editProfile(widget.user, 'firstname', v); - })); - defaultItems.add( - SizedBox( - height: widget.style.betweenDefaultItemPadding, - ), - ); - defaultItems.add(widget.itemBuilder! - .build('lastName', widget.user.lastName, null, (v) { - widget.user.lastName = v; - - widget.service.editProfile(widget.user, 'lastName', v); - })); - } - } - - @override - Widget build(BuildContext context) { - return Material( - color: Colors.transparent, - child: Padding( - padding: widget.style.pagePadding, - child: Column( - children: [ - if (widget.showAvatar) - InkWell( - onTap: () async { - await widget.service.uploadImage(context); - }, - child: Avatar( - firstName: widget.user.firstName, - lastName: widget.user.lastName, - style: widget.style.avatarStyle, - avatar: widget.customAvatar, - image: widget.user.image, - ), - ), - if (widget.showAvatar) - SizedBox( - height: widget.style.betweenDefaultItemPadding, - ), - ...defaultItems, - ...widget.user.profileData!.buildItems( - widget.user.profileData!.toMap(), - widget.user.profileData!.mapWidget( - () { - widget.rebuild(); - }, - context, - ), - widget.style.betweenDefaultItemPadding, - (key, value) { - widget.service.editProfile(widget.user, key, value); - }, - itemBuilder: widget.itemBuilder, - itemBuilderOptions: widget.itemBuilderOptions, - ), - if (widget.showDeleteProfile) - SizedBox( - height: widget.style.betweenDefaultItemPadding, - ), - const Spacer(), - if (widget.showDeleteProfile) - InkWell( - onTap: () { - widget.service.deleteProfile(); - }, - child: const Text('Profiel verwijderen'), - ), - ], - ), - ), - ); - } -} diff --git a/lib/src/widgets/profile/profile_style.dart b/lib/src/widgets/profile/profile_style.dart index cbdded8..1d38b0d 100644 --- a/lib/src/widgets/profile/profile_style.dart +++ b/lib/src/widgets/profile/profile_style.dart @@ -1,6 +1,13 @@ import 'package:flutter/material.dart'; import 'package:profile/src/widgets/avatar/avatar_style.dart'; +/// ProfielStyle is used to set a couple of style paramaters for the whole profile page. +/// +/// AvatarStyle is used to set some styling for the avatar using [AvatarStyle]. +/// +/// PagePaddign is used to set the padding around the whole profile page with its parent. +/// +/// BetweenDefaultitemPadding sets te padding between each user data item. class ProfileStyle { const ProfileStyle({ this.avatarStyle = const AvatarStyle(), @@ -8,7 +15,12 @@ class ProfileStyle { this.pagePadding = EdgeInsets.zero, }); + /// AvatarStyle can be used to set some avatar styling parameters. final AvatarStyle avatarStyle; + + /// PagePadding can be set to determine the padding of the whole page againt the profile page parent. final EdgeInsetsGeometry pagePadding; + + /// BetweenDefaultItemPadding sets the final double betweenDefaultItemPadding; } diff --git a/lib/src/widgets/profile/proifle_wrapper.dart b/lib/src/widgets/profile/proifle_wrapper.dart new file mode 100644 index 0000000..e760ea0 --- /dev/null +++ b/lib/src/widgets/profile/proifle_wrapper.dart @@ -0,0 +1,144 @@ +import 'package:flutter/material.dart'; +import 'package:profile/src/models/user.dart'; +import 'package:profile/src/services/profile_service.dart'; +import 'package:profile/src/widgets/avatar/avatar.dart'; +import 'package:profile/src/widgets/item_builder/item_builder.dart'; +import 'package:profile/src/widgets/item_builder/item_builder_options.dart'; +import 'package:profile/src/widgets/profile/profile_style.dart'; + +class ProfileWrapper extends StatefulWidget { + const ProfileWrapper({ + Key? key, + required this.user, + required this.service, + required this.rebuild, + this.style = const ProfileStyle(), + this.customAvatar, + this.showAvatar = true, + this.itemBuilder, + this.itemBuilderOptions, + this.showDeleteProfile = true, + }) : super(key: key); + + final User user; + final ProfileService service; + final ProfileStyle style; + final Widget? customAvatar; + final bool showAvatar; + final bool showDeleteProfile; + final ItemBuilder? itemBuilder; + final Function rebuild; + final ItemBuilderOptions? itemBuilderOptions; + + @override + State createState() => _ProfileWrapperState(); +} + +class _ProfileWrapperState extends State { + List defaultItems = []; + + @override + void initState() { + super.initState(); + + if (widget.itemBuilder == null) { + ItemBuilder builder = ItemBuilder( + options: widget.itemBuilderOptions ?? ItemBuilderOptions(), + ); + defaultItems + .add(builder.build('firstName', widget.user.firstName, null, (v) { + widget.user.firstName = v; + + widget.service.editProfile(widget.user, 'firstName', v); + })); + defaultItems.add( + SizedBox( + height: widget.style.betweenDefaultItemPadding, + ), + ); + defaultItems + .add(builder.build('lastName', widget.user.lastName, null, (v) { + widget.user.lastName = v; + + widget.service.editProfile(widget.user, 'lastName', v); + })); + } else { + defaultItems.add(widget.itemBuilder! + .build('firstName', widget.user.firstName, null, (v) { + widget.user.firstName = v; + + widget.service.editProfile(widget.user, 'firstname', v); + })); + defaultItems.add( + SizedBox( + height: widget.style.betweenDefaultItemPadding, + ), + ); + defaultItems.add(widget.itemBuilder! + .build('lastName', widget.user.lastName, null, (v) { + widget.user.lastName = v; + + widget.service.editProfile(widget.user, 'lastName', v); + })); + } + } + + @override + Widget build(BuildContext context) { + return Material( + color: Colors.transparent, + child: Padding( + padding: widget.style.pagePadding, + child: Column( + children: [ + if (widget.showAvatar) + InkWell( + onTap: () async { + await widget.service.uploadImage(context); + }, + child: Avatar( + firstName: widget.user.firstName, + lastName: widget.user.lastName, + style: widget.style.avatarStyle, + avatar: widget.customAvatar, + image: widget.user.image, + ), + ), + if (widget.showAvatar) + SizedBox( + height: widget.style.betweenDefaultItemPadding, + ), + ...defaultItems, + ...widget.user.profileData!.buildItems( + widget.user.profileData!.toMap(), + widget.user.profileData!.mapWidget( + () { + widget.rebuild(); + }, + context, + ), + widget.style.betweenDefaultItemPadding, + (key, value) { + widget.service.editProfile(widget.user, key, value); + }, + itemBuilder: widget.itemBuilder, + itemBuilderOptions: widget.itemBuilderOptions, + ), + if (widget.showDeleteProfile) + SizedBox( + height: widget.style.betweenDefaultItemPadding, + ), + const Spacer(), + if (widget.showDeleteProfile) + InkWell( + onTap: () { + widget.service.deleteProfile(); + }, + child: const Text('Profiel verwijderen'), + ), + ], + ), + ), + ); + } +}