marco.pms.mobile/lib/view/apps/kan_ban_board_screen.dart
2025-04-02 19:11:36 +05:30

223 lines
7.7 KiB
Dart

import 'package:appflowy_board/appflowy_board.dart';
import 'package:flutter/material.dart';
import 'package:flutter_lucide/flutter_lucide.dart';
import 'package:get/get.dart';
import 'package:maxdash/controller/apps/kan_ban_board_cotnroller.dart';
import 'package:maxdash/helpers/theme/app_theme.dart';
import 'package:maxdash/helpers/utils/mixins/ui_mixin.dart';
import 'package:maxdash/helpers/utils/my_shadow.dart';
import 'package:maxdash/helpers/widgets/my_breadcrumb.dart';
import 'package:maxdash/helpers/widgets/my_breadcrumb_item.dart';
import 'package:maxdash/helpers/widgets/my_card.dart';
import 'package:maxdash/helpers/widgets/my_container.dart';
import 'package:maxdash/helpers/widgets/my_spacing.dart';
import 'package:maxdash/helpers/widgets/my_text.dart';
import 'package:maxdash/view/layouts/layout.dart';
class KanBanBoardScreen extends StatefulWidget {
const KanBanBoardScreen({super.key});
@override
State<KanBanBoardScreen> createState() => _KanBanBoardScreenState();
}
class _KanBanBoardScreenState extends State<KanBanBoardScreen> with SingleTickerProviderStateMixin, UIMixin {
late KanBanBoardController controller;
late ScrollController _controller;
@override
void initState() {
controller = KanBanBoardController();
controller.boardController = AppFlowyBoardScrollController();
_controller = ScrollController();
super.initState();
}
@override
Widget build(BuildContext context) {
return Layout(
child: GetBuilder(
init: controller,
tag: 'kanban_controller',
builder: (controller) {
return Column(
children: [
Padding(
padding: MySpacing.x(flexSpacing),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
MyText.titleMedium(
"Kanban",
fontSize: 18,
fontWeight: 600,
),
MyBreadcrumb(
children: [
MyBreadcrumbItem(name: 'App'),
MyBreadcrumbItem(name: 'Kanban'),
],
),
],
),
),
MySpacing.height(flexSpacing),
AppFlowyBoard(
config: AppFlowyBoardConfig(stretchGroupHeight: false, groupBackgroundColor: contentTheme.primary.withAlpha(20)),
controller: controller.boardData,
cardBuilder: (context, group, groupItem) {
return AppFlowyGroupCard(
key: ValueKey(groupItem.id),
decoration: BoxDecoration(borderRadius: BorderRadius.circular(4)),
child: MyCard.bordered(
borderRadiusAll: 4,
border: Border.all(color: Colors.grey.withValues(alpha:.2)),
shadow: MyShadow(elevation: 1, position: MyShadowPosition.bottom),
paddingAll: 24,
child: buildCard(groupItem)));
},
boardScrollController: controller.boardController,
footerBuilder: (context, columnData) {
return MySpacing.height(16);
},
headerBuilder: (context, columnData) {
return SizedBox(
height: 40,
child: ListView.builder(
controller: _controller,
shrinkWrap: true,
itemBuilder: (context, index) {
return AppFlowyGroupHeader(
title: MyText.bodyMedium(columnData.headerData.groupName, fontSize: 16, fontWeight: 600, muted: true),
margin: MySpacing.x(24),
height: 40);
},
),
);
},
groupConstraints: BoxConstraints.tightFor(width: 400),
),
],
);
},
),
);
}
Widget buildCard(AppFlowyGroupItem item) {
if (item is TextItem) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
MyText.bodyMedium(item.title, fontWeight: 600),
MySpacing.height(12),
MyText.bodyMedium(item.date, muted: true, fontWeight: 600),
MySpacing.height(12),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
MyContainer.rounded(paddingAll: 0, height: 32, clipBehavior: Clip.antiAliasWithSaveLayer, child: Image.asset(item.image)),
MySpacing.width(8),
MyText.bodyMedium(item.name, fontWeight: 600),
],
),
MyContainer.none(
paddingAll: 8,
borderRadiusAll: 5,
child: PopupMenuButton(
offset: Offset(-150, 15),
position: PopupMenuPosition.under,
itemBuilder: (BuildContext context) => [
PopupMenuItem(
padding: MySpacing.xy(16, 8),
height: 10,
child: Row(
children: [Icon(LucideIcons.circle_plus, size: 20), MySpacing.width(8), MyText.bodySmall("Add People", fontWeight: 600)],
)),
PopupMenuItem(
padding: MySpacing.xy(16, 8),
height: 10,
child: Row(
children: [Icon(LucideIcons.pencil, size: 20), MySpacing.width(8), MyText.bodySmall("Edit", fontWeight: 600)],
)),
PopupMenuItem(
padding: MySpacing.xy(16, 8),
height: 10,
child: Row(
children: [Icon(LucideIcons.trash, size: 20), MySpacing.width(8), MyText.bodySmall("Delete", fontWeight: 600)],
)),
PopupMenuItem(
padding: MySpacing.xy(16, 8),
height: 10,
child: Row(
children: [Icon(LucideIcons.log_out, size: 20), MySpacing.width(8), MyText.bodySmall("Leave", fontWeight: 600)],
)),
],
child: Icon(LucideIcons.ellipsis_vertical, size: 18),
),
),
],
)
],
);
}
if (item is RichTextItem) {
return RichTextCard(item: item);
}
throw UnimplementedError();
}
}
class RichTextCard extends StatefulWidget {
final RichTextItem item;
const RichTextCard({
required this.item,
super.key,
});
@override
State<RichTextCard> createState() => _RichTextCardState();
}
class _RichTextCardState extends State<RichTextCard> {
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return Align(
alignment: Alignment.centerLeft,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
widget.item.title,
style: const TextStyle(fontSize: 14),
textAlign: TextAlign.left,
),
],
),
),
);
}
}
class RichTextItem extends AppFlowyGroupItem {
final String title;
final String subtitle;
RichTextItem({required this.title, required this.subtitle});
@override
String get id => title;
}