creek
The AI Image Editor of 2030git clone https://github.com/maydayv7/creek
lib/ui/widgets/note_input_sheet.dart (6737B)
1import 'package:flutter/material.dart';
2import 'package:shared_preferences/shared_preferences.dart';
3import 'package:creekui/ui/styles/variables.dart';
4
5class NoteInputSheet extends StatefulWidget {
6 final List<String> categories;
7 final String initialCategory;
8 final Function(String content, String category) onSubmit;
9
10 const NoteInputSheet({
11 super.key,
12 required this.categories,
13 required this.initialCategory,
14 required this.onSubmit,
15 });
16
17 @override
18 State<NoteInputSheet> createState() => _NoteInputSheetState();
19}
20
21class _NoteInputSheetState extends State<NoteInputSheet> {
22 late String _selectedCategory;
23 final TextEditingController _controller = TextEditingController();
24 String _userName = "Alex"; // Default
25
26 @override
27 void initState() {
28 super.initState();
29 _selectedCategory = widget.initialCategory;
30 _loadUserName();
31 }
32
33 Future<void> _loadUserName() async {
34 final prefs = await SharedPreferences.getInstance();
35 if (mounted) {
36 setState(() {
37 _userName = prefs.getString('user_name') ?? "Alex";
38 });
39 }
40 }
41
42 @override
43 void dispose() {
44 _controller.dispose();
45 super.dispose();
46 }
47
48 @override
49 Widget build(BuildContext context) {
50 return Padding(
51 padding: const EdgeInsets.all(16),
52 child: Column(
53 mainAxisSize: MainAxisSize.min,
54 children: [
55 // Header Row
56 Row(
57 children: [
58 Container(
59 width: 30,
60 height: 30,
61 decoration: BoxDecoration(
62 shape: BoxShape.circle,
63 border: Border.all(
64 color: Variables.surfaceBackground,
65 width: 1.25,
66 ),
67 ),
68 child: const CircleAvatar(
69 radius: 15,
70 backgroundColor: Colors.grey,
71 child: Icon(Icons.person, color: Colors.white, size: 18),
72 ),
73 ),
74 const SizedBox(width: 10),
75 Text(
76 _userName,
77 style: Variables.bodyStyle.copyWith(
78 fontSize: 12,
79 fontWeight: FontWeight.w500,
80 ),
81 ),
82 const Spacer(),
83 Container(
84 padding: const EdgeInsets.symmetric(
85 horizontal: 12,
86 vertical: 6,
87 ),
88 decoration: BoxDecoration(
89 color: Variables.chipBackground,
90 borderRadius: BorderRadius.circular(1000),
91 ),
92 child: DropdownButtonHideUnderline(
93 child: DropdownButton<String>(
94 value:
95 widget.categories.contains(_selectedCategory)
96 ? _selectedCategory
97 : null,
98 hint: Text(
99 "Type",
100 style: Variables.bodyStyle.copyWith(fontSize: 12),
101 ),
102 isDense: true,
103 icon: const Icon(
104 Icons.arrow_drop_down,
105 size: 20,
106 color: Variables.textPrimary,
107 ),
108 style: Variables.bodyStyle.copyWith(fontSize: 12),
109 dropdownColor: Colors.white,
110 items:
111 widget.categories
112 .map(
113 (c) => DropdownMenuItem(value: c, child: Text(c)),
114 )
115 .toList(),
116 onChanged: (v) {
117 if (v != null) setState(() => _selectedCategory = v);
118 },
119 ),
120 ),
121 ),
122 ],
123 ),
124 const SizedBox(height: 16),
125 // Input Row
126 Row(
127 crossAxisAlignment: CrossAxisAlignment.end,
128 children: [
129 Expanded(
130 child: Container(
131 decoration: BoxDecoration(
132 color: Variables.surfaceSubtle,
133 border: Border.all(color: Variables.borderSubtle),
134 borderRadius: BorderRadius.circular(8),
135 ),
136 child: TextField(
137 controller: _controller,
138 autofocus: true,
139 maxLines: null,
140 style: Variables.bodyStyle.copyWith(fontSize: 12),
141 decoration: const InputDecoration(
142 hintText: "Enter note details...",
143 border: InputBorder.none,
144 contentPadding: EdgeInsets.symmetric(
145 horizontal: 12,
146 vertical: 10,
147 ),
148 ),
149 ),
150 ),
151 ),
152 const SizedBox(width: 8),
153 IconButton(
154 icon: const Icon(
155 Icons.send,
156 color: Variables.textPrimary,
157 size: 24,
158 ),
159 onPressed: () {
160 if (_controller.text.isNotEmpty) {
161 widget.onSubmit(_controller.text.trim(), _selectedCategory);
162 }
163 },
164 padding: EdgeInsets.zero,
165 constraints: const BoxConstraints(minWidth: 24, minHeight: 24),
166 ),
167 ],
168 ),
169 const SizedBox(height: 10),
170 ],
171 ),
172 );
173 }
174}
175
176class NoteModalOverlay extends StatelessWidget {
177 final Widget modalContent;
178 final Size screenSize;
179
180 const NoteModalOverlay({
181 super.key,
182 required this.modalContent,
183 required this.screenSize,
184 });
185
186 @override
187 Widget build(BuildContext context) {
188 final mq = MediaQuery.of(context);
189 return Align(
190 alignment: Alignment.bottomCenter,
191 child: AnimatedPadding(
192 duration: const Duration(milliseconds: 250),
193 curve: Curves.easeOut,
194 padding: EdgeInsets.only(bottom: mq.viewInsets.bottom),
195 child: ConstrainedBox(
196 constraints: BoxConstraints(maxHeight: screenSize.height),
197 child: Material(
198 color: Colors.white,
199 elevation: 10,
200 shadowColor: Colors.black26,
201 borderRadius: const BorderRadius.vertical(top: Radius.circular(20)),
202 clipBehavior: Clip.antiAlias,
203 child: SingleChildScrollView(
204 padding: EdgeInsets.only(bottom: mq.padding.bottom),
205 child: modalContent,
206 ),
207 ),
208 ),
209 ),
210 );
211 }
212}