refactor: add optional subtitle to various widgets for enhanced context
This commit is contained in:
@@ -74,23 +74,32 @@ class ClientHomePage extends StatelessWidget {
|
|||||||
|
|
||||||
/// Builds the widget list in normal mode with visibility filters.
|
/// Builds the widget list in normal mode with visibility filters.
|
||||||
Widget _buildNormalModeList(ClientHomeState state) {
|
Widget _buildNormalModeList(ClientHomeState state) {
|
||||||
return ListView(
|
return ListView.separated(
|
||||||
padding: const EdgeInsets.fromLTRB(
|
padding: const EdgeInsets.only(bottom: 100),
|
||||||
UiConstants.space4,
|
separatorBuilder: (BuildContext context, int index) {
|
||||||
0,
|
return const Divider(color: UiColors.border, height: 0.2);
|
||||||
UiConstants.space4,
|
},
|
||||||
100,
|
itemCount: state.widgetOrder.length,
|
||||||
|
itemBuilder: (BuildContext context, int index) {
|
||||||
|
final String id = state.widgetOrder[index];
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: <Widget>[
|
||||||
|
if (index != 0) const SizedBox(height: UiConstants.space8),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: UiConstants.space4,
|
||||||
),
|
),
|
||||||
children: state.widgetOrder.map((String id) {
|
|
||||||
return Padding(
|
|
||||||
padding: const EdgeInsets.only(bottom: UiConstants.space4),
|
|
||||||
child: DashboardWidgetBuilder(
|
child: DashboardWidgetBuilder(
|
||||||
id: id,
|
id: id,
|
||||||
state: state,
|
state: state,
|
||||||
isEditMode: false,
|
isEditMode: false,
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: UiConstants.space8),
|
||||||
|
],
|
||||||
);
|
);
|
||||||
}).toList(),
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,11 +10,15 @@ class ActionsWidget extends StatelessWidget {
|
|||||||
/// Callback when Create Order is pressed.
|
/// Callback when Create Order is pressed.
|
||||||
final VoidCallback onCreateOrderPressed;
|
final VoidCallback onCreateOrderPressed;
|
||||||
|
|
||||||
|
/// Optional subtitle for the section.
|
||||||
|
final String? subtitle;
|
||||||
|
|
||||||
/// Creates an [ActionsWidget].
|
/// Creates an [ActionsWidget].
|
||||||
const ActionsWidget({
|
const ActionsWidget({
|
||||||
super.key,
|
super.key,
|
||||||
required this.onRapidPressed,
|
required this.onRapidPressed,
|
||||||
required this.onCreateOrderPressed,
|
required this.onCreateOrderPressed,
|
||||||
|
this.subtitle,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -22,7 +26,10 @@ class ActionsWidget extends StatelessWidget {
|
|||||||
// Check if client_home exists in t
|
// Check if client_home exists in t
|
||||||
final TranslationsClientHomeActionsEn i18n = t.client_home.actions;
|
final TranslationsClientHomeActionsEn i18n = t.client_home.actions;
|
||||||
|
|
||||||
return Row(
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: <Widget>[
|
||||||
|
Row(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
/// TODO: FEATURE_NOT_YET_IMPLEMENTED
|
/// TODO: FEATURE_NOT_YET_IMPLEMENTED
|
||||||
// Expanded(
|
// Expanded(
|
||||||
@@ -55,6 +62,8 @@ class ActionsWidget extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,17 +12,22 @@ class CoverageWidget extends StatelessWidget {
|
|||||||
/// The percentage of coverage (0-100).
|
/// The percentage of coverage (0-100).
|
||||||
final int coveragePercent;
|
final int coveragePercent;
|
||||||
|
|
||||||
|
/// Optional subtitle for the section.
|
||||||
|
final String? subtitle;
|
||||||
|
|
||||||
/// Creates a [CoverageWidget].
|
/// Creates a [CoverageWidget].
|
||||||
const CoverageWidget({
|
const CoverageWidget({
|
||||||
super.key,
|
super.key,
|
||||||
this.totalNeeded = 0,
|
this.totalNeeded = 0,
|
||||||
this.totalConfirmed = 0,
|
this.totalConfirmed = 0,
|
||||||
this.coveragePercent = 0,
|
this.coveragePercent = 0,
|
||||||
|
this.subtitle,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Column(
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
@@ -53,6 +58,12 @@ class CoverageWidget extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
if (subtitle != null) ...<Widget>[
|
||||||
|
Text(
|
||||||
|
subtitle!,
|
||||||
|
style: UiTypography.body2r.textSecondary,
|
||||||
|
),
|
||||||
|
],
|
||||||
const SizedBox(height: UiConstants.space2),
|
const SizedBox(height: UiConstants.space2),
|
||||||
Row(
|
Row(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
|
|||||||
@@ -56,11 +56,15 @@ class DashboardWidgetBuilder extends StatelessWidget {
|
|||||||
|
|
||||||
/// Builds the actual widget content based on the widget ID.
|
/// Builds the actual widget content based on the widget ID.
|
||||||
Widget _buildWidgetContent(BuildContext context) {
|
Widget _buildWidgetContent(BuildContext context) {
|
||||||
|
// Only show subtitle in normal mode
|
||||||
|
final String? subtitle = !isEditMode ? _getWidgetSubtitle(id) : null;
|
||||||
|
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case 'actions':
|
case 'actions':
|
||||||
return ActionsWidget(
|
return ActionsWidget(
|
||||||
onRapidPressed: () => Modular.to.pushRapidOrder(),
|
onRapidPressed: () => Modular.to.pushRapidOrder(),
|
||||||
onCreateOrderPressed: () => Modular.to.pushCreateOrder(),
|
onCreateOrderPressed: () => Modular.to.pushCreateOrder(),
|
||||||
|
subtitle: subtitle,
|
||||||
);
|
);
|
||||||
case 'reorder':
|
case 'reorder':
|
||||||
return ReorderWidget(
|
return ReorderWidget(
|
||||||
@@ -88,6 +92,7 @@ class DashboardWidgetBuilder extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
subtitle: subtitle,
|
||||||
);
|
);
|
||||||
case 'spending':
|
case 'spending':
|
||||||
return SpendingWidget(
|
return SpendingWidget(
|
||||||
@@ -95,6 +100,7 @@ class DashboardWidgetBuilder extends StatelessWidget {
|
|||||||
next7DaysSpending: state.dashboardData.next7DaysSpending,
|
next7DaysSpending: state.dashboardData.next7DaysSpending,
|
||||||
weeklyShifts: state.dashboardData.weeklyShifts,
|
weeklyShifts: state.dashboardData.weeklyShifts,
|
||||||
next7DaysScheduled: state.dashboardData.next7DaysScheduled,
|
next7DaysScheduled: state.dashboardData.next7DaysScheduled,
|
||||||
|
subtitle: subtitle,
|
||||||
);
|
);
|
||||||
case 'coverage':
|
case 'coverage':
|
||||||
return CoverageWidget(
|
return CoverageWidget(
|
||||||
@@ -106,10 +112,12 @@ class DashboardWidgetBuilder extends StatelessWidget {
|
|||||||
100)
|
100)
|
||||||
.toInt()
|
.toInt()
|
||||||
: 0,
|
: 0,
|
||||||
|
subtitle: subtitle,
|
||||||
);
|
);
|
||||||
case 'liveActivity':
|
case 'liveActivity':
|
||||||
return LiveActivityWidget(
|
return LiveActivityWidget(
|
||||||
onViewAllPressed: () => Modular.to.navigate('/client-main/coverage/'),
|
onViewAllPressed: () => Modular.to.navigate('/client-main/coverage/'),
|
||||||
|
subtitle: subtitle,
|
||||||
);
|
);
|
||||||
default:
|
default:
|
||||||
return const SizedBox.shrink();
|
return const SizedBox.shrink();
|
||||||
@@ -133,4 +141,21 @@ class DashboardWidgetBuilder extends StatelessWidget {
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String _getWidgetSubtitle(String id) {
|
||||||
|
switch (id) {
|
||||||
|
case 'actions':
|
||||||
|
return 'Quick access to create and manage orders';
|
||||||
|
case 'reorder':
|
||||||
|
return 'Easily reorder from your past activity';
|
||||||
|
case 'spending':
|
||||||
|
return 'Track your spending and budget in real-time';
|
||||||
|
case 'coverage':
|
||||||
|
return 'Overview of your current shift coverage';
|
||||||
|
case 'liveActivity':
|
||||||
|
return 'Real-time updates on your active shifts';
|
||||||
|
default:
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,8 +10,15 @@ class LiveActivityWidget extends StatefulWidget {
|
|||||||
/// Callback when "View all" is pressed.
|
/// Callback when "View all" is pressed.
|
||||||
final VoidCallback onViewAllPressed;
|
final VoidCallback onViewAllPressed;
|
||||||
|
|
||||||
|
/// Optional subtitle for the section.
|
||||||
|
final String? subtitle;
|
||||||
|
|
||||||
/// Creates a [LiveActivityWidget].
|
/// Creates a [LiveActivityWidget].
|
||||||
const LiveActivityWidget({super.key, required this.onViewAllPressed});
|
const LiveActivityWidget({
|
||||||
|
super.key,
|
||||||
|
required this.onViewAllPressed,
|
||||||
|
this.subtitle
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<LiveActivityWidget> createState() => _LiveActivityWidgetState();
|
State<LiveActivityWidget> createState() => _LiveActivityWidgetState();
|
||||||
@@ -100,6 +107,7 @@ class _LiveActivityWidgetState extends State<LiveActivityWidget> {
|
|||||||
final TranslationsClientHomeEn i18n = t.client_home;
|
final TranslationsClientHomeEn i18n = t.client_home;
|
||||||
|
|
||||||
return Column(
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
@@ -121,6 +129,13 @@ class _LiveActivityWidgetState extends State<LiveActivityWidget> {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
if (widget.subtitle != null) ...<Widget>[
|
||||||
|
const SizedBox(height: UiConstants.space1),
|
||||||
|
Text(
|
||||||
|
widget.subtitle!,
|
||||||
|
style: UiTypography.body2r.textSecondary,
|
||||||
|
),
|
||||||
|
],
|
||||||
const SizedBox(height: UiConstants.space2),
|
const SizedBox(height: UiConstants.space2),
|
||||||
FutureBuilder<_LiveActivityData>(
|
FutureBuilder<_LiveActivityData>(
|
||||||
future: _liveActivityFuture,
|
future: _liveActivityFuture,
|
||||||
|
|||||||
@@ -11,11 +11,15 @@ class ReorderWidget extends StatelessWidget {
|
|||||||
/// Callback when a reorder button is pressed.
|
/// Callback when a reorder button is pressed.
|
||||||
final Function(Map<String, dynamic> shiftData) onReorderPressed;
|
final Function(Map<String, dynamic> shiftData) onReorderPressed;
|
||||||
|
|
||||||
|
/// Optional subtitle for the section.
|
||||||
|
final String? subtitle;
|
||||||
|
|
||||||
/// Creates a [ReorderWidget].
|
/// Creates a [ReorderWidget].
|
||||||
const ReorderWidget({
|
const ReorderWidget({
|
||||||
super.key,
|
super.key,
|
||||||
required this.orders,
|
required this.orders,
|
||||||
required this.onReorderPressed,
|
required this.onReorderPressed,
|
||||||
|
this.subtitle,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -33,6 +37,13 @@ class ReorderWidget extends StatelessWidget {
|
|||||||
letterSpacing: 0.5,
|
letterSpacing: 0.5,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
if (subtitle != null) ...<Widget>[
|
||||||
|
const SizedBox(height: UiConstants.space1),
|
||||||
|
Text(
|
||||||
|
subtitle!,
|
||||||
|
style: UiTypography.body2r.textSecondary,
|
||||||
|
),
|
||||||
|
],
|
||||||
const SizedBox(height: UiConstants.space2),
|
const SizedBox(height: UiConstants.space2),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: 140,
|
height: 140,
|
||||||
|
|||||||
@@ -16,6 +16,9 @@ class SpendingWidget extends StatelessWidget {
|
|||||||
/// The number of scheduled shifts for next 7 days.
|
/// The number of scheduled shifts for next 7 days.
|
||||||
final int next7DaysScheduled;
|
final int next7DaysScheduled;
|
||||||
|
|
||||||
|
/// Optional subtitle for the section.
|
||||||
|
final String? subtitle;
|
||||||
|
|
||||||
/// Creates a [SpendingWidget].
|
/// Creates a [SpendingWidget].
|
||||||
const SpendingWidget({
|
const SpendingWidget({
|
||||||
super.key,
|
super.key,
|
||||||
@@ -23,6 +26,7 @@ class SpendingWidget extends StatelessWidget {
|
|||||||
required this.next7DaysSpending,
|
required this.next7DaysSpending,
|
||||||
required this.weeklyShifts,
|
required this.weeklyShifts,
|
||||||
required this.next7DaysScheduled,
|
required this.next7DaysScheduled,
|
||||||
|
this.subtitle,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -38,6 +42,13 @@ class SpendingWidget extends StatelessWidget {
|
|||||||
letterSpacing: 0.5,
|
letterSpacing: 0.5,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
if (subtitle != null) ...<Widget>[
|
||||||
|
const SizedBox(height: UiConstants.space1),
|
||||||
|
Text(
|
||||||
|
subtitle!,
|
||||||
|
style: UiTypography.body2r.textSecondary,
|
||||||
|
),
|
||||||
|
],
|
||||||
const SizedBox(height: UiConstants.space2),
|
const SizedBox(height: UiConstants.space2),
|
||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.all(UiConstants.space3),
|
padding: const EdgeInsets.all(UiConstants.space3),
|
||||||
|
|||||||
Reference in New Issue
Block a user