@@ -53,9 +53,7 @@ class _BreweryScreenState extends State<BreweryScreen> {
5353 final theme = Theme .of (context);
5454
5555 return Scaffold (
56- appBar: AppBar (
57- title: Text (producer.name),
58- ),
56+ appBar: AppBar (),
5957 body: CustomScrollView (
6058 slivers: [
6159 SliverToBoxAdapter (
@@ -91,53 +89,210 @@ class _BreweryScreenState extends State<BreweryScreen> {
9189
9290 Widget _buildHeader (BuildContext context, Producer producer, int drinkCount) {
9391 final theme = Theme .of (context);
92+ final brightness = theme.brightness;
93+ final initials = _getInitials (producer.name);
94+
9495 return Container (
9596 width: double .infinity,
96- padding: const EdgeInsets .all (24 ),
97- color: theme.colorScheme.primaryContainer,
98- child: Column (
99- crossAxisAlignment: CrossAxisAlignment .start,
97+ decoration: BoxDecoration (
98+ gradient: LinearGradient (
99+ begin: Alignment .topLeft,
100+ end: Alignment .bottomRight,
101+ colors: brightness == Brightness .dark
102+ ? [
103+ theme.colorScheme.primaryContainer,
104+ theme.colorScheme.primaryContainer.withOpacity (0.7 ),
105+ ]
106+ : [
107+ theme.colorScheme.primaryContainer,
108+ theme.colorScheme.secondaryContainer.withOpacity (0.5 ),
109+ ],
110+ ),
111+ ),
112+ child: Stack (
100113 children: [
101- Text (
102- producer.name,
103- style: theme.textTheme.headlineMedium? .copyWith (
104- fontWeight: FontWeight .bold,
114+ // Large decorative letter pattern
115+ Positioned (
116+ right: - 40 ,
117+ top: - 20 ,
118+ child: Opacity (
119+ opacity: 0.08 ,
120+ child: Text (
121+ initials,
122+ style: TextStyle (
123+ fontSize: 180 ,
124+ fontWeight: FontWeight .w900,
125+ color: theme.colorScheme.primary,
126+ letterSpacing: - 8 ,
127+ ),
128+ ),
105129 ),
106130 ),
107- const SizedBox (height: 8 ),
108- if (producer.location.isNotEmpty)
109- Row (
131+ // Decorative circles
132+ Positioned (
133+ left: 20 ,
134+ bottom: 20 ,
135+ child: Container (
136+ width: 60 ,
137+ height: 60 ,
138+ decoration: BoxDecoration (
139+ shape: BoxShape .circle,
140+ color: theme.colorScheme.secondary.withOpacity (0.1 ),
141+ ),
142+ ),
143+ ),
144+ Positioned (
145+ left: 50 ,
146+ bottom: 40 ,
147+ child: Container (
148+ width: 40 ,
149+ height: 40 ,
150+ decoration: BoxDecoration (
151+ shape: BoxShape .circle,
152+ color: theme.colorScheme.tertiary.withOpacity (0.08 ),
153+ ),
154+ ),
155+ ),
156+ // Content
157+ Padding (
158+ padding: const EdgeInsets .all (24 ),
159+ child: Column (
160+ crossAxisAlignment: CrossAxisAlignment .start,
110161 children: [
111- Icon (
112- Icons .location_on,
113- size: 16 ,
114- color: theme.colorScheme.onPrimaryContainer.withValues (alpha: 0.7 ),
162+ Row (
163+ children: [
164+ Container (
165+ width: 64 ,
166+ height: 64 ,
167+ decoration: BoxDecoration (
168+ gradient: LinearGradient (
169+ begin: Alignment .topLeft,
170+ end: Alignment .bottomRight,
171+ colors: [
172+ theme.colorScheme.primary,
173+ theme.colorScheme.secondary,
174+ ],
175+ ),
176+ borderRadius: BorderRadius .circular (16 ),
177+ boxShadow: [
178+ BoxShadow (
179+ color: theme.colorScheme.primary.withOpacity (0.3 ),
180+ blurRadius: 8 ,
181+ offset: const Offset (0 , 2 ),
182+ ),
183+ ],
184+ ),
185+ child: Center (
186+ child: Text (
187+ initials,
188+ style: theme.textTheme.headlineSmall? .copyWith (
189+ fontWeight: FontWeight .bold,
190+ color: theme.colorScheme.onPrimary,
191+ ),
192+ ),
193+ ),
194+ ),
195+ const SizedBox (width: 16 ),
196+ Expanded (
197+ child: Text (
198+ producer.name,
199+ style: theme.textTheme.headlineMedium? .copyWith (
200+ fontWeight: FontWeight .bold,
201+ ),
202+ ),
203+ ),
204+ ],
115205 ),
116- const SizedBox (width: 4 ),
117- Text (
118- producer.location,
119- style: theme.textTheme.bodyMedium? .copyWith (
120- color: theme.colorScheme.onPrimaryContainer.withValues (alpha: 0.7 ),
206+ const SizedBox (height: 16 ),
207+ if (producer.location.isNotEmpty)
208+ Row (
209+ children: [
210+ Icon (
211+ Icons .location_on,
212+ size: 16 ,
213+ color: theme.colorScheme.onPrimaryContainer.withValues (alpha: 0.7 ),
214+ ),
215+ const SizedBox (width: 4 ),
216+ Text (
217+ producer.location,
218+ style: theme.textTheme.bodyMedium? .copyWith (
219+ color: theme.colorScheme.onPrimaryContainer.withValues (alpha: 0.7 ),
220+ ),
221+ ),
222+ ],
223+ ),
224+ if (producer.yearFounded != null ) ...[
225+ const SizedBox (height: 4 ),
226+ Row (
227+ children: [
228+ Icon (
229+ Icons .calendar_today,
230+ size: 16 ,
231+ color: theme.colorScheme.onPrimaryContainer.withValues (alpha: 0.7 ),
232+ ),
233+ const SizedBox (width: 4 ),
234+ Text (
235+ 'Est. ${producer .yearFounded }' ,
236+ style: theme.textTheme.bodyMedium? .copyWith (
237+ color: theme.colorScheme.onPrimaryContainer.withValues (alpha: 0.7 ),
238+ ),
239+ ),
240+ ],
241+ ),
242+ ],
243+ const SizedBox (height: 16 ),
244+ // Stats card
245+ Container (
246+ padding: const EdgeInsets .all (16 ),
247+ decoration: BoxDecoration (
248+ color: theme.colorScheme.surface.withOpacity (0.5 ),
249+ borderRadius: BorderRadius .circular (12 ),
250+ border: Border .all (
251+ color: theme.colorScheme.outline.withOpacity (0.2 ),
252+ ),
253+ ),
254+ child: Row (
255+ children: [
256+ Icon (
257+ Icons .local_drink,
258+ size: 20 ,
259+ color: theme.colorScheme.primary,
260+ ),
261+ const SizedBox (width: 8 ),
262+ Text (
263+ '$drinkCount drinks at this festival' ,
264+ style: theme.textTheme.bodyMedium? .copyWith (
265+ fontWeight: FontWeight .w500,
266+ ),
267+ ),
268+ ],
121269 ),
122270 ),
123271 ],
124272 ),
125- if (producer.yearFounded != null ) ...[
126- const SizedBox (height: 4 ),
127- Text (
128- 'Est. ${producer .yearFounded }' ,
129- style: theme.textTheme.bodyMedium? .copyWith (
130- color: theme.colorScheme.onPrimaryContainer.withValues (alpha: 0.7 ),
131- ),
132- ),
133- ],
134- const SizedBox (height: 8 ),
135- Text (
136- '$drinkCount drinks at this festival' ,
137- style: theme.textTheme.bodySmall,
138273 ),
139274 ],
140275 ),
141276 );
142277 }
278+
279+ /// Extract initials from brewery name (max 2 letters)
280+ String _getInitials (String name) {
281+ final words = name.trim ().split (RegExp (r'\s+' )).where ((w) => w.isNotEmpty).toList ();
282+ if (words.isEmpty) return '?' ;
283+
284+ if (words.length == 1 ) {
285+ // Single word: take first 2 letters
286+ final word = words[0 ];
287+ if (word.length < 2 ) return word.toUpperCase ();
288+ return word.substring (0 , 2 ).toUpperCase ();
289+ } else {
290+ // Multiple words: take first letter of first two words
291+ // Safe because we filtered empty words above
292+ final first = words[0 ].isNotEmpty ? words[0 ][0 ] : '' ;
293+ final second = (words.length > 1 && words[1 ].isNotEmpty) ? words[1 ][0 ] : '' ;
294+ final initials = first + second;
295+ return initials.isNotEmpty ? initials.toUpperCase () : '?' ;
296+ }
297+ }
143298}
0 commit comments