Skip to content

Commit

Permalink
feat: delete notice (#118)
Browse files Browse the repository at this point in the history
* feat: add notice setting bottom sheet

* feat: delete notice

* chore: remove another setting actions except for delete
  • Loading branch information
2paperstar authored Nov 16, 2023
1 parent 880f524 commit 70b1a74
Show file tree
Hide file tree
Showing 10 changed files with 140 additions and 0 deletions.
12 changes: 12 additions & 0 deletions assets/i18n/article.i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,17 @@
"description": "Once reported, the administrator will review this notice and take action.",
"yes": "Report",
"no": "Cancel"
},
"settings": {
"title": "Settings",
"delete": {
"action": "Delete this notice",
"title": "Are you sure you want to delete this notice?",
"description": "Once deleted, it cannot be restored.",
"yes": "Delete",
"no": "Cancel"
},
"writeTranslation": "Add english translation",
"additional": "Write additional notice"
}
}
12 changes: 12 additions & 0 deletions assets/i18n/article_ko.i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,17 @@
"description": "신고가 접수되면 관리자가 이 공지를 살펴보고 조치를 취할 것입니다.",
"yes": "",
"no": "아니오"
},
"settings": {
"title": "작성자 설정",
"delete": {
"action": "이 공지 삭제하기",
"title": "게시글을 삭제하시겠습니까?",
"description": "공지 삭제 시 복구가 불가능합니다.",
"yes": "삭제",
"no": "취소"
},
"writeTranslation": "영어 공지 작성하기",
"additional": "추가 공지 작성하기"
}
}
1 change: 1 addition & 0 deletions lib/app/core/values/palette.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ abstract class Palette {
static const deselected = Color(0xffd6d6d6);
static const placeholder = Color(0xffe3e3e3);
static const light = Color(0xfff5f5f5);
static const settings = Color(0xff344fae);
}
3 changes: 3 additions & 0 deletions lib/app/modules/notices/data/data_sources/notice_api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ abstract class NoticeApi {
@GET('{id}')
Future<NoticeModel> getNotice(@Path() int id);

@DELETE('{id}')
Future<void> deleteNotice(@Path() int id);

@POST('{id}/reminder')
Future setReminder(@Path() int id);

Expand Down
1 change: 1 addition & 0 deletions lib/app/modules/notices/data/models/notice_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class NoticeModel with _$NoticeModel implements NoticeEntity {
required List<ContentModel> contents,
@Default([]) List<String> imagesUrl,
@Default([]) List<TagModel> tags,
required String authorId,
required String author,
required bool reminder,
}) = _NoticeModel;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ class RestNoticesRepository implements NoticesRepository {
);
}

@override
Future<void> deleteNotice(NoticeSummaryEntity summary) {
return _api.deleteNotice(summary.id);
}

@override
Future<void> setReminder(NoticeEntity notice) {
return _api.setReminder(notice.id);
Expand Down
2 changes: 2 additions & 0 deletions lib/app/modules/notices/domain/entities/notice_entity.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class NoticeEntity {
final List<ContentEntity> contents;
final List<String> imagesUrl;
final List<TagEntity> tags;
final String authorId;
final String author;
final bool reminder;

Expand All @@ -21,6 +22,7 @@ class NoticeEntity {
required this.contents,
this.imagesUrl = const [],
this.tags = const [],
this.authorId = "",
this.author = "",
this.reminder = false,
}) : assert(contents.isNotEmpty);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import '../entities/notice_summary_entity.dart';
abstract class NoticesRepository {
Future<NoticeListEntity> getNotices(NoticeSearchQueryEntity query);
Future<NoticeEntity> getNotice(NoticeSummaryEntity summary);
Future<void> deleteNotice(NoticeSummaryEntity summary);
Future<void> setReminder(NoticeEntity notice);
Future<void> cancelReminder(NoticeEntity notice);
Future<NoticeEntity> writeNotice(NoticeWriteEntity writing);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class NoticesBloc extends Bloc<NoticesEvent, NoticesState> {
events.throttleTime(_throttleTime).switchMap(mapper),
);
on<_FetchOne>(_fetchOne);
on<_Delete>(_delete);
}

FutureOr<void> _fetchOne(_FetchOne event, Emitter<NoticesState> emit) async {
Expand Down Expand Up @@ -61,13 +62,20 @@ class NoticesBloc extends Bloc<NoticesEvent, NoticesState> {
event.query,
));
}

FutureOr<void> _delete(_Delete event, Emitter<NoticesState> emit) async {
emit(NoticesState.loading([event.summary]));
await _repository.deleteNotice(event.summary);
emit(const NoticesState.initial());
}
}

@freezed
sealed class NoticesEvent with _$NoticesEvent {
const factory NoticesEvent.fetch(NoticeSearchQueryEntity query) = _Fetch;
const factory NoticesEvent.fetchOne(NoticeSummaryEntity summary) = _FetchOne;
const factory NoticesEvent.loadMore() = _LoadMore;
const factory NoticesEvent.delete(NoticeSummaryEntity summary) = _Delete;
}

@freezed
Expand Down
95 changes: 95 additions & 0 deletions lib/app/modules/notices/presentation/pages/notice_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:go_router/go_router.dart';
import 'package:ziggle/app/common/domain/repositories/analytics_repository.dart';
import 'package:ziggle/app/common/presentaion/widgets/bottom_sheet.dart';
import 'package:ziggle/app/common/presentaion/widgets/button.dart';
import 'package:ziggle/app/core/di/locator.dart';
import 'package:ziggle/app/core/routes/routes.dart';
import 'package:ziggle/app/core/themes/text.dart';
Expand Down Expand Up @@ -127,6 +128,35 @@ class _Layout extends StatelessWidget {
),
],
),
floatingActionButton: BlocBuilder<NoticesBloc, NoticesState>(
builder: (context, state) => state.single == null ||
context.read<AuthBloc>().state.user?.id !=
state.single!.authorId
? const SizedBox.shrink()
: FloatingActionButton.extended(
foregroundColor: Palette.white,
backgroundColor: Palette.settings,
icon: const Icon(Icons.settings),
label: Text(t.article.settings.title),
onPressed: () => showModalBottomSheet(
context: context,
builder: (modelConext) => _SettingSheet(
onDelete: () async {
final bloc = context.read<NoticesBloc>();
bloc.add(
NoticesEvent.delete(
context.read<NoticesBloc>().state.partial!,
),
);
await bloc.stream.firstWhere(
(s) => s.mapOrNull(initial: (_) => true) ?? false);
if (!context.mounted) return;
context.go(Paths.home);
},
),
),
),
),
body: BlocBuilder<NoticesBloc, NoticesState>(
builder: (context, state) => state.partial == null
? const Center(child: CircularProgressIndicator.adaptive())
Expand Down Expand Up @@ -161,6 +191,71 @@ class _Layout extends StatelessWidget {
}
}

class _SettingSheet extends StatelessWidget {
final VoidCallback onDelete;
const _SettingSheet({required this.onDelete});

@override
Widget build(BuildContext context) {
return ZiggleBottomSheet(
child: SafeArea(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 30),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const SizedBox(height: 12),
_buildButton(
Icons.delete,
t.article.settings.delete.action,
() async {
final result = await showCupertinoDialog(
context: context,
barrierDismissible: true,
builder: (dialogContext) => CupertinoAlertDialog(
title: Text(t.article.settings.delete.title),
content: Text(t.article.settings.delete.title),
actions: [
CupertinoActionSheetAction(
isDestructiveAction: true,
onPressed: () => Navigator.pop(dialogContext, true),
child: Text(t.article.settings.delete.yes),
),
CupertinoActionSheetAction(
isDefaultAction: true,
onPressed: () => Navigator.pop(dialogContext),
child: Text(t.article.settings.delete.no),
),
],
),
);
if (result == null || !result) return;
onDelete();
},
),
],
),
),
),
);
}

Widget _buildButton(IconData icon, String label, VoidCallback onTap) {
return ZiggleButton(
onTap: onTap,
color: Colors.transparent,
padding: const EdgeInsets.all(8),
child: Row(
children: [
Icon(icon),
const SizedBox(width: 4),
Text(label, style: TextStyles.label),
],
),
);
}
}

class _ScrollableDraggableContent extends StatefulWidget {
final NoticeEntity notice;
final Widget child;
Expand Down

0 comments on commit 70b1a74

Please sign in to comment.