Files
Kifi/kifi-app/lib/features/barcode_designer/presentation/saved_templates_screen.dart

243 lines
11 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:lucide_icons_flutter/lucide_icons.dart';
import '../providers/barcode_templates_provider.dart';
import '../providers/barcode_designer_provider.dart';
import 'barcode_designer_screen.dart';
class SavedTemplatesScreen extends ConsumerWidget {
const SavedTemplatesScreen({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final templatesAsync = ref.watch(barcodeTemplatesProvider);
final isDark = Theme.of(context).brightness == Brightness.dark;
return Scaffold(
appBar: AppBar(
title: const Text('Saved Label Templates'),
actions: [
IconButton(
icon: const Icon(LucideIcons.refreshCw),
tooltip: 'Refresh',
onPressed: () => ref.read(barcodeTemplatesProvider.notifier).refresh(),
),
],
),
floatingActionButton: FloatingActionButton.extended(
icon: const Icon(LucideIcons.plus),
label: const Text('New Template'),
onPressed: () {
ref.read(barcodeDesignerProvider.notifier).resetToNew(50.0, 25.0);
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (_) => const BarcodeDesignerScreen()),
);
},
),
body: templatesAsync.when(
loading: () => const Center(child: CircularProgressIndicator()),
error: (err, _) => Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(LucideIcons.circleAlert, size: 48, color: Colors.red),
const SizedBox(height: 12),
Text('Error loading templates: $err'),
const SizedBox(height: 12),
ElevatedButton(
onPressed: () => ref.read(barcodeTemplatesProvider.notifier).refresh(),
child: const Text('Retry'),
),
],
),
),
data: (templates) {
if (templates.isEmpty) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.blue.withValues(alpha: 0.1),
shape: BoxShape.circle,
),
child: const Icon(LucideIcons.barcode, size: 48, color: Colors.blue),
),
const SizedBox(height: 16),
const Text(
'No templates saved yet',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
const SizedBox(height: 8),
Text(
'Create your first custom barcode and label template',
style: TextStyle(color: Colors.grey.shade500, fontSize: 13),
),
const SizedBox(height: 20),
ElevatedButton.icon(
icon: const Icon(LucideIcons.plus, size: 18),
label: const Text('Create New Template'),
onPressed: () {
ref.read(barcodeDesignerProvider.notifier).resetToNew(50.0, 25.0);
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (_) => const BarcodeDesignerScreen()),
);
},
),
],
),
);
}
return GridView.builder(
padding: const EdgeInsets.all(20),
gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 360,
mainAxisExtent: 180,
crossAxisSpacing: 16,
mainAxisSpacing: 16,
),
itemCount: templates.length,
itemBuilder: (context, index) {
final item = templates[index];
return Container(
decoration: BoxDecoration(
color: isDark ? const Color(0xFF1E293B) : Colors.white,
borderRadius: BorderRadius.circular(16),
border: Border.all(
color: isDark ? Colors.white10 : Colors.grey.shade200,
),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: isDark ? 0.2 : 0.04),
blurRadius: 10,
offset: const Offset(0, 4),
),
],
),
child: Material(
color: Colors.transparent,
borderRadius: BorderRadius.circular(16),
child: InkWell(
onTap: () {
final doc = item.toLabelDocument();
ref.read(barcodeDesignerProvider.notifier).loadDocument(doc, item.id);
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (_) => BarcodeDesignerScreen(initialTemplate: item),
),
);
},
borderRadius: BorderRadius.circular(16),
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
color: Colors.blue.withValues(alpha: 0.12),
borderRadius: BorderRadius.circular(10),
),
child: const Icon(LucideIcons.barcode, color: Colors.blue, size: 20),
),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
item.templateName,
style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 14),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
Text(
'${item.labelWidthMm.round()} × ${item.labelHeightMm.round()} mm • ${item.printerLanguage}',
style: TextStyle(color: Colors.grey.shade500, fontSize: 11),
),
],
),
),
PopupMenuButton<String>(
icon: const Icon(LucideIcons.ellipsisVertical, size: 18),
onSelected: (val) async {
if (val == 'delete' && item.id != null) {
final confirm = await showDialog<bool>(
context: context,
builder: (_) => AlertDialog(
title: const Text('Delete Template'),
content: Text('Are you sure you want to delete "${item.templateName}"?'),
actions: [
TextButton(onPressed: () => Navigator.pop(context, false), child: const Text('Cancel')),
ElevatedButton(
style: ElevatedButton.styleFrom(backgroundColor: Colors.red),
onPressed: () => Navigator.pop(context, true),
child: const Text('Delete', style: TextStyle(color: Colors.white)),
),
],
),
);
if (confirm == true) {
ref.read(barcodeTemplatesProvider.notifier).deleteTemplate(item.id!);
}
}
},
itemBuilder: (_) => [
const PopupMenuItem(
value: 'delete',
child: Row(
children: [
Icon(LucideIcons.trash2, color: Colors.red, size: 16),
SizedBox(width: 8),
Text('Delete', style: TextStyle(color: Colors.red)),
],
),
),
],
),
],
),
const Spacer(),
Container(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6),
decoration: BoxDecoration(
color: isDark ? Colors.black26 : Colors.grey.shade100,
borderRadius: BorderRadius.circular(8),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'DPI: ${item.dpi}',
style: TextStyle(fontSize: 11, color: Colors.grey.shade600),
),
Text(
'v${item.version}',
style: TextStyle(fontSize: 11, color: Colors.grey.shade600),
),
],
),
),
],
),
),
),
),
);
},
);
},
),
);
}
}