♻️ Breakdown of the site detail page

This commit is contained in:
2025-11-21 00:34:39 +08:00
parent fc65440420
commit c03ba3bc3a
10 changed files with 1580 additions and 1503 deletions

View File

@@ -0,0 +1,135 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:gap/gap.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:island/models/publication_site.dart';
import 'package:island/pods/site_pages.dart';
import 'package:island/widgets/sites/page_form.dart';
import 'package:material_symbols_icons/symbols.dart';
import 'package:styled_widget/styled_widget.dart';
class PageItem extends HookConsumerWidget {
final SnPublicationPage page;
final SnPublicationSite site;
final String pubName;
const PageItem({
required this.page,
required this.site,
required this.pubName,
});
@override
Widget build(BuildContext context, WidgetRef ref) {
final theme = Theme.of(context);
return Card(
color: Theme.of(context).colorScheme.surfaceContainerHigh,
elevation: 0,
child: ListTile(
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(8)),
),
leading: Icon(Symbols.article, color: theme.colorScheme.primary),
title: Text(page.path ?? '/'),
subtitle: Text(page.config?['title'] ?? 'Untitled'),
trailing: PopupMenuButton<String>(
itemBuilder:
(context) => [
PopupMenuItem(
value: 'edit',
child: Row(
children: [
const Icon(Symbols.edit),
const Gap(16),
Text('edit'.tr()),
],
),
),
PopupMenuItem(
value: 'delete',
child: Row(
children: [
const Icon(Symbols.delete, color: Colors.red),
const Gap(16),
Text('delete'.tr()).textColor(Colors.red),
],
),
),
],
onSelected: (value) async {
switch (value) {
case 'edit':
// Open page edit dialog
showModalBottomSheet(
context: context,
isScrollControlled: true,
builder:
(context) =>
PageForm(site: site, pubName: pubName, page: page),
).then((_) {
// Refresh pages after editing
ref.invalidate(sitePagesProvider(pubName, site.slug));
});
break;
case 'delete':
final confirmed = await showDialog<bool>(
context: context,
builder:
(context) => AlertDialog(
title: const Text('Delete Page'),
content: const Text(
'Are you sure you want to delete this page?',
),
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(false),
child: const Text('Cancel'),
),
TextButton(
onPressed: () => Navigator.of(context).pop(true),
child: const Text('Delete'),
),
],
),
);
if (confirmed == true) {
try {
await ref
.read(
sitePagesNotifierProvider((
pubName: pubName,
siteSlug: site.slug,
)).notifier,
)
.deletePage(page.id);
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Page deleted successfully'),
),
);
}
} catch (e) {
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Failed to delete page')),
);
}
}
}
break;
}
},
),
onTap: () {
// TODO: Open page preview or edit
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Opening page: ${page.path ?? '/'}')),
);
},
),
);
}
}