creek
The AI Image Editor of 2030git clone https://github.com/maydayv7/creek
lib/ui/pages/project_board_page_alternate.dart (5016B)
1import 'package:flutter/material.dart';
2import 'package:creekui/ui/styles/variables.dart';
3import 'package:creekui/data/models/image_model.dart';
4import 'package:creekui/data/repos/image_repo.dart';
5import 'package:creekui/ui/widgets/moodboard_image_card.dart';
6import 'package:creekui/ui/widgets/empty_state.dart';
7import 'image_details_page.dart';
8
9class ProjectBoardPageAlternate extends StatefulWidget {
10 final int projectId;
11 const ProjectBoardPageAlternate({super.key, required this.projectId});
12
13 @override
14 State<ProjectBoardPageAlternate> createState() =>
15 ProjectBoardPageAlternateState();
16}
17
18class ProjectBoardPageAlternateState extends State<ProjectBoardPageAlternate> {
19 final _imageRepo = ImageRepo();
20 List<ImageModel> _allImages = [];
21 List<ImageModel> _filteredImages = [];
22 List<String> _allTags = [];
23 final Set<String> _selectedTags = {};
24 bool _isLoading = true;
25
26 @override
27 void initState() {
28 super.initState();
29 _loadData();
30 }
31
32 @override
33 void didUpdateWidget(covariant ProjectBoardPageAlternate oldWidget) {
34 super.didUpdateWidget(oldWidget);
35 if (oldWidget.projectId != widget.projectId) _loadData();
36 }
37
38 void refreshData() => _loadData();
39
40 Future<void> _loadData() async {
41 setState(() => _isLoading = true);
42 final images = await _imageRepo.getImages(widget.projectId);
43 final Set<String> tags = {};
44 for (var img in images) {
45 tags.addAll(img.tags);
46 }
47
48 if (mounted) {
49 setState(() {
50 _allImages = images;
51 _filteredImages = images;
52 _allTags = tags.toList()..sort();
53 _isLoading = false;
54 });
55 if (_selectedTags.isNotEmpty) _applyFilter();
56 }
57 }
58
59 void _applyFilter() {
60 setState(() {
61 _filteredImages =
62 _selectedTags.isEmpty
63 ? _allImages
64 : _allImages
65 .where(
66 (img) =>
67 img.tags.toSet().intersection(_selectedTags).isNotEmpty,
68 )
69 .toList();
70 });
71 }
72
73 @override
74 Widget build(BuildContext context) {
75 if (_isLoading) return const Center(child: CircularProgressIndicator());
76
77 final leftColumn = <Widget>[];
78 final rightColumn = <Widget>[];
79
80 for (int i = 0; i < _filteredImages.length; i++) {
81 final item = MoodboardImageCard(
82 image: _filteredImages[i],
83 height: (i % 3 == 0) ? 240 : 180,
84 showTags: true,
85 onTap:
86 () => Navigator.push(
87 context,
88 MaterialPageRoute(
89 builder:
90 (_) => ImageDetailsPage(
91 imagePath: _filteredImages[i].filePath,
92 imageId: _filteredImages[i].id,
93 projectId: widget.projectId,
94 ),
95 ),
96 ),
97 onDeleted: refreshData,
98 );
99
100 if (i % 2 == 0) {
101 leftColumn.add(
102 Padding(padding: const EdgeInsets.only(bottom: 12), child: item),
103 );
104 } else {
105 rightColumn.add(
106 Padding(padding: const EdgeInsets.only(bottom: 12), child: item),
107 );
108 }
109 }
110
111 return Column(
112 children: [
113 // Context Info Row (Image Count + Active Filters)
114 Padding(
115 padding: const EdgeInsets.fromLTRB(16, 0, 16, 16),
116 child: Row(
117 children: [
118 const Spacer(),
119 if (_selectedTags.isNotEmpty)
120 Container(
121 padding: const EdgeInsets.symmetric(
122 horizontal: 8,
123 vertical: 4,
124 ),
125 decoration: BoxDecoration(
126 color: Variables.textPrimary,
127 borderRadius: BorderRadius.circular(12),
128 ),
129 child: Text(
130 "${_selectedTags.length} Active",
131 style: Variables.captionStyle.copyWith(
132 color: Colors.white,
133 fontWeight: FontWeight.bold,
134 ),
135 ),
136 ),
137 ],
138 ),
139 ),
140
141 // Masonry Grid
142 Expanded(
143 child:
144 _filteredImages.isEmpty
145 ? const EmptyState(
146 icon: Icons.image_not_supported_outlined,
147 title: "No images found",
148 subtitle: "Try removing filters or adding new images",
149 )
150 : SingleChildScrollView(
151 padding: const EdgeInsets.fromLTRB(16, 0, 16, 80),
152 child: Row(
153 crossAxisAlignment: CrossAxisAlignment.start,
154 children: [
155 Expanded(child: Column(children: leftColumn)),
156 const SizedBox(width: 12),
157 Expanded(child: Column(children: rightColumn)),
158 ],
159 ),
160 ),
161 ),
162 ],
163 );
164 }
165}