Skip to content

Commit

Permalink
feat: add TaskTemplate bottom sheets
Browse files Browse the repository at this point in the history
  • Loading branch information
DasProffi committed Oct 4, 2024
1 parent 1d70bfb commit 24dc8aa
Show file tree
Hide file tree
Showing 31 changed files with 956 additions and 54 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ import 'package:provider/provider.dart';
import 'package:tasks/components/bottom_sheet_pages/room_overview_bottom_sheet.dart';
import 'package:tasks/screens/settings_screen.dart';

class WardOverviewBottomSheetPage extends StatelessWidget {
class RoomsBottomSheetPage extends StatelessWidget {
final String wardId;

const WardOverviewBottomSheetPage({super.key, required this.wardId});
const RoomsBottomSheetPage({super.key, required this.wardId});

@override
Widget build(BuildContext context) {
Expand All @@ -29,7 +29,7 @@ class WardOverviewBottomSheetPage extends StatelessWidget {
children: [
Text(context.localization!.rooms, style: context.theme.textTheme.titleMedium),
LoadingFutureBuilder(
future: WardService().getWard(id: wardId),
future: WardService().get(id: wardId),
thenBuilder: (context, ward) {
return Text(ward.name, style: TextStyle(color: context.theme.hintColor));
}),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
import 'package:flutter/material.dart';
import 'package:helpwave_localization/localization.dart';
import 'package:helpwave_service/tasks.dart';
import 'package:helpwave_theme/constants.dart';
import 'package:helpwave_theme/util.dart';
import 'package:helpwave_util/lists.dart';
import 'package:helpwave_widget/bottom_sheets.dart';
import 'package:helpwave_widget/lists.dart';
import 'package:helpwave_widget/loading.dart';
import 'package:helpwave_widget/navigation.dart';
import 'package:helpwave_widget/shapes.dart';
import 'package:helpwave_widget/text_input.dart';
import 'package:provider/provider.dart';

import '../subtask_list.dart';

class TaskTemplateBottomSheetPage extends StatelessWidget {
final TaskTemplate? template;
final String? templateId;

const TaskTemplateBottomSheetPage({
super.key,
this.templateId,
this.template,
}) : assert(templateId != null || template != null, "either template or templateId must be provided");

@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (_) => TaskTemplateController(
templateId: templateId,
taskTemplate: templateId == null ? template : null,
),
builder: (context, _) => BottomSheetPage(
header: Consumer<TaskTemplateController>(builder: (context, controller, _) {
return BottomSheetHeader.navigation(
context,
title: Column(
mainAxisSize: MainAxisSize.min,
children: [
LoadingAndErrorWidget(
state: controller.state,
loadingWidget: const PulsingContainer(width: 60),
child: Text(
controller.taskTemplate.name,
style: const TextStyle(fontWeight: FontWeight.w800, fontSize: 16),
),
),
controller.taskTemplate.wardId != null
? LoadingFutureBuilder(
future: WardService().get(id: controller.taskTemplate.wardId!),
thenBuilder: (context, data) => Text(
data.name,
style: TextStyle(color: context.theme.hintColor),
),
loadingWidget: const PulsingContainer(width: 60, height: 40),
errorWidget: LoadErrorWidget(
errorText: controller.error.toString(),
),
)
: const SizedBox(),
],
),
trailing: controller.isCreating
? BottomSheetAction(
icon: Icons.check,
onPressed: () {
controller.create().then((_) {
NavigationStackController.of(context).pop();
});
},
)
: null, // TODO consider screen for using task template
);
}),
child: Flexible(
child: Consumer<TaskTemplateController>(
builder: (context, controller, child) {
return LoadingAndErrorWidget(
state: controller.state,
child: ListView(
children: [
Text(context.localization!.name, style: context.theme.textTheme.titleSmall),
const SizedBox(height: distanceTiny),
TextFormFieldWithTimer(
initialValue: controller.taskTemplate.name,
onUpdate: (value) => controller.update(name: value),
),
const SizedBox(height: distanceMedium),
Text(context.localization!.notes, style: context.theme.textTheme.titleSmall),
const SizedBox(height: distanceTiny),
TextFormFieldWithTimer(
initialValue: controller.taskTemplate.description,
onUpdate: (value) => controller.update(description: value),
maxLines: 6,
decoration:
InputDecoration(hintText: "${context.localization!.add} ${context.localization!.notes}"),
),
const SizedBox(height: distanceMedium),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(context.localization!.subtasks, style: context.theme.textTheme.titleSmall),
TextButton(
onPressed: () {
controller.createSubtask(TaskTemplateSubtask(
templateId: controller.templateId,
name: context.localization!.subtask,
));
},
child: Text("+ ${context.localization!.add} ${context.localization!.subtask}"),
),
],
),
const SizedBox(height: distanceTiny),
RoundedListTiles(
children: controller.taskTemplate.subtasks.mapWithIndex(
(subtask, index) => ListTile(
leading: Circle(diameter: 16, color: context.theme.colorScheme.primary),
title: Text(subtask.name),
onTap: () {
showDialog<String>(
context: context,
builder: (context) => SubTaskChangeDialog(initialName: subtask.name)).then((value) {
if (value != null) {
controller.updateSubtaskByIndex(index: index, name: value);
}
});
},
trailing: IconButton(
onPressed: () {
controller.deleteSubtaskByIndex(index: index);
},
// TODO get color from theme
icon: const Icon(
Icons.delete,
color: Colors.red,
),
),
),
),
)
],
),
);
},
),
),
),
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import 'package:flutter/material.dart';
import 'package:helpwave_localization/localization.dart';
import 'package:helpwave_service/tasks.dart';
import 'package:helpwave_theme/constants.dart';
import 'package:helpwave_theme/util.dart';
import 'package:helpwave_widget/bottom_sheets.dart';
import 'package:helpwave_widget/lists.dart';
import 'package:helpwave_widget/loading.dart';
import 'package:helpwave_widget/navigation.dart';
import 'package:tasks/components/bottom_sheet_pages/task_template_bottom_sheet.dart';
import 'package:tasks/screens/settings_screen.dart';

class TaskTemplatesBottomSheetPage extends StatelessWidget {
final bool isPersonal;
final String? wardId;

const TaskTemplatesBottomSheetPage({
super.key,
this.isPersonal = false,
this.wardId,
});

@override
Widget build(BuildContext context) {
return BottomSheetPage(
header: BottomSheetHeader.navigation(
context,
title: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
context.localization!.taskTemplates,
style: const TextStyle(fontWeight: FontWeight.w800, fontSize: 16),
),
wardId == null
? const SizedBox()
: LoadingFutureBuilder(
future: WardService().get(id: wardId ?? ""),
thenBuilder: (context, data) => Text(
data.name,
style: TextStyle(color: context.theme.hintColor),
),
loadingWidget: const PulsingContainer(width: 60),
),
],
),
trailing: BottomSheetAction(
icon: Icons.add,
onPressed: () {
NavigationStackController.of(context).push(TaskTemplateBottomSheetPage(
template: TaskTemplate(
name: context.localization!.task,
wardId: wardId,
isPublicVisible: !isPersonal,
),
));
}),
),
child: Flexible(
child: LoadingFutureBuilder(
future: TaskTemplateService().getMany(wardId: wardId, privateOnly: isPersonal),
thenBuilder: (context, data) => ListView(
shrinkWrap: true,
children: [
const SizedBox(height: distanceMedium),
RoundedListTiles(
children: data
.map(
(template) => NavigationListTile(
icon: Icons.fact_check_rounded,
title: template.name,
onTap: () {
NavigationStackController.of(context).push(TaskTemplateBottomSheetPage(
templateId: template.id!,
));
},
),
)
.toList()),
],
),
),
),
);
}
}
113 changes: 113 additions & 0 deletions apps/tasks/lib/components/bottom_sheet_pages/ward_bottom_sheet.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import 'package:flutter/material.dart';
import 'package:helpwave_localization/localization.dart';
import 'package:helpwave_service/tasks.dart';
import 'package:helpwave_theme/constants.dart';
import 'package:helpwave_theme/util.dart';
import 'package:helpwave_util/loading.dart';
import 'package:helpwave_widget/bottom_sheets.dart';
import 'package:helpwave_widget/lists.dart';
import 'package:helpwave_widget/loading.dart';
import 'package:helpwave_widget/navigation.dart';
import 'package:helpwave_widget/text_input.dart';
import 'package:helpwave_widget/widgets.dart';
import 'package:provider/provider.dart';
import 'package:tasks/components/bottom_sheet_pages/rooms_bottom_sheet.dart';
import 'package:tasks/components/bottom_sheet_pages/task_templates_bottom_sheet.dart';
import 'package:tasks/screens/settings_screen.dart';

class WardBottomSheetPage extends StatelessWidget {
final String wardId;

const WardBottomSheetPage({super.key, required this.wardId});

@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (context) => WardController(wardId: wardId),
child: BottomSheetPage(
header: BottomSheetHeader.navigation(
context,
title: Consumer<WardController>(
builder: (context, controller, _) {
return LoadingAndErrorWidget.pulsing(
state: controller.state,
child: Text(
controller.ward.name,
style: const TextStyle(fontWeight: FontWeight.w800, fontSize: 16),
),
);
},
),
),
child: Flexible(
child: ListView(
shrinkWrap: true,
children: [
Consumer<WardController>(
builder: (context, controller, child) {
return LoadingAndErrorWidget(
state: controller.state,
loadingWidget: const PulsingContainer(height: 80),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(context.localization!.name, style: context.theme.textTheme.titleSmall),
const SizedBox(height: distanceTiny),
TextFormFieldWithTimer(
initialValue: controller.state == LoadingState.loaded ? controller.ward.name : "",
onUpdate: (value) => controller.update(name: value),
),
],
),
);
},
),
const SizedBox(height: distanceMedium),
Text(context.localization!.settings, style: context.theme.textTheme.titleMedium),
const SizedBox(height: distanceTiny),
RoundedListTiles(
children: [
NavigationListTile(
icon: Icons.house_rounded,
title: context.localization!.rooms,
onTap: () {
NavigationStackController.of(context).push(RoomsBottomSheetPage(wardId: wardId));
},
),
NavigationListTile(
icon: Icons.checklist_rounded,
title: context.localization!.taskTemplates,
onTap: () {
NavigationStackController.of(context).push(TaskTemplatesBottomSheetPage(wardId: wardId));
},
),
NavigationListTile(
icon: Icons.label,
title: context.localization!.properties,
onTap: () {
// TODO navigate to properties page
},
)
],
),
const SizedBox(height: distanceMedium),
Text(context.localization!.dangerZone, style: context.theme.textTheme.titleMedium),
Text(
context.localization!.organizationDangerZoneDescription,
style: TextStyle(color: context.theme.hintColor),
),
PressableText(
text: "${context.localization!.delete} ${context.localization!.organization}",
style: const TextStyle(color: Colors.red, fontWeight: FontWeight.w700), // TODO get from theme
onPressed: () {
// TODO show modal and delete organization
},
),
],
),
),
),
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import 'package:helpwave_widget/bottom_sheets.dart';
import 'package:helpwave_widget/lists.dart';
import 'package:helpwave_widget/loading.dart';
import 'package:helpwave_widget/navigation.dart';
import 'package:tasks/components/bottom_sheet_pages/ward_overview_bottom_sheet.dart';
import 'package:tasks/components/bottom_sheet_pages/ward_bottom_sheet.dart';
import 'package:tasks/screens/settings_screen.dart';

class WardsBottomSheetPage extends StatelessWidget {
Expand Down Expand Up @@ -53,7 +53,7 @@ class WardsBottomSheetPage extends StatelessWidget {
icon: Icons.house_rounded,
title: ward.name,
onTap: () {
NavigationStackController.of(context).push(WardOverviewBottomSheetPage(wardId: ward.id));
NavigationStackController.of(context).push(WardBottomSheetPage(wardId: ward.id));
},
),
)
Expand Down
Loading

0 comments on commit 24dc8aa

Please sign in to comment.