Add Hungarian English language switcher

This commit is contained in:
zsolt
2026-08-13 13:43:57 +02:00
parent 1b0734cf7b
commit aea92b0eed
8 changed files with 262 additions and 35 deletions
+138 -16
View File
@@ -18,6 +18,7 @@ class _OtthonAppState extends State<OtthonApp> {
String googleServerClientId = googleCalendarServerClientId; String googleServerClientId = googleCalendarServerClientId;
WeatherSnapshot? weather; WeatherSnapshot? weather;
String themeId = 'sage'; String themeId = 'sage';
String languageCode = defaultLanguageCode;
bool loaded = false; bool loaded = false;
AppThemeStyle get activeTheme => appThemes.firstWhere( AppThemeStyle get activeTheme => appThemes.firstWhere(
@@ -43,6 +44,7 @@ class _OtthonAppState extends State<OtthonApp> {
jarvisSettings = settings.jarvisSettings; jarvisSettings = settings.jarvisSettings;
googleServerClientId = settings.googleServerClientId; googleServerClientId = settings.googleServerClientId;
themeId = settings.themeId; themeId = settings.themeId;
languageCode = settings.languageCode;
loaded = true; loaded = true;
}); });
_loadRemoteAppConfig(); _loadRemoteAppConfig();
@@ -53,6 +55,7 @@ class _OtthonAppState extends State<OtthonApp> {
AppSettings( AppSettings(
people: people, people: people,
themeId: themeId, themeId: themeId,
languageCode: languageCode,
googleConnections: googleConnections, googleConnections: googleConnections,
syncedEvents: syncedEvents, syncedEvents: syncedEvents,
todoSuggestions: todoSuggestions, todoSuggestions: todoSuggestions,
@@ -100,6 +103,11 @@ class _OtthonAppState extends State<OtthonApp> {
_saveSettings(); _saveSettings();
} }
void _updateLanguage(String nextLanguageCode) {
setState(() => languageCode = nextLanguageCode == 'en' ? 'en' : 'hu');
_saveSettings();
}
void _updateGoogleConnections( void _updateGoogleConnections(
List<GoogleCalendarConnection> nextConnections, List<GoogleCalendarConnection> nextConnections,
) { ) {
@@ -132,9 +140,17 @@ class _OtthonAppState extends State<OtthonApp> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final theme = activeTheme; final theme = activeTheme;
final text = AppText.of(languageCode);
return MaterialApp( return MaterialApp(
debugShowCheckedModeBanner: false, debugShowCheckedModeBanner: false,
title: 'K\u00f6z\u00f6sT\u00e9r', title: text.appTitle,
locale: text.locale,
supportedLocales: const [Locale('hu'), Locale('en')],
localizationsDelegates: const [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
theme: ThemeData( theme: ThemeData(
useMaterial3: true, useMaterial3: true,
colorScheme: ColorScheme.fromSeed( colorScheme: ColorScheme.fromSeed(
@@ -168,9 +184,11 @@ class _OtthonAppState extends State<OtthonApp> {
googleServerClientId: googleServerClientId, googleServerClientId: googleServerClientId,
weather: weather, weather: weather,
themeId: themeId, themeId: themeId,
languageCode: languageCode,
loaded: loaded, loaded: loaded,
onPeopleChanged: _updatePeople, onPeopleChanged: _updatePeople,
onThemeChanged: _updateTheme, onThemeChanged: _updateTheme,
onLanguageChanged: _updateLanguage,
onGoogleConnectionsChanged: _updateGoogleConnections, onGoogleConnectionsChanged: _updateGoogleConnections,
onSyncedEventsChanged: _updateSyncedEvents, onSyncedEventsChanged: _updateSyncedEvents,
onTodoSuggestionsChanged: _updateTodoSuggestions, onTodoSuggestionsChanged: _updateTodoSuggestions,
@@ -191,9 +209,11 @@ class HomeShell extends StatefulWidget {
required this.googleServerClientId, required this.googleServerClientId,
required this.weather, required this.weather,
required this.themeId, required this.themeId,
required this.languageCode,
required this.loaded, required this.loaded,
required this.onPeopleChanged, required this.onPeopleChanged,
required this.onThemeChanged, required this.onThemeChanged,
required this.onLanguageChanged,
required this.onGoogleConnectionsChanged, required this.onGoogleConnectionsChanged,
required this.onSyncedEventsChanged, required this.onSyncedEventsChanged,
required this.onTodoSuggestionsChanged, required this.onTodoSuggestionsChanged,
@@ -208,9 +228,11 @@ class HomeShell extends StatefulWidget {
final String googleServerClientId; final String googleServerClientId;
final WeatherSnapshot? weather; final WeatherSnapshot? weather;
final String themeId; final String themeId;
final String languageCode;
final bool loaded; final bool loaded;
final ValueChanged<List<Person>> onPeopleChanged; final ValueChanged<List<Person>> onPeopleChanged;
final ValueChanged<String> onThemeChanged; final ValueChanged<String> onThemeChanged;
final ValueChanged<String> onLanguageChanged;
final ValueChanged<List<GoogleCalendarConnection>> onGoogleConnectionsChanged; final ValueChanged<List<GoogleCalendarConnection>> onGoogleConnectionsChanged;
final ValueChanged<List<CalendarEvent>> onSyncedEventsChanged; final ValueChanged<List<CalendarEvent>> onSyncedEventsChanged;
final ValueChanged<List<String>> onTodoSuggestionsChanged; final ValueChanged<List<String>> onTodoSuggestionsChanged;
@@ -328,15 +350,6 @@ class _HomeShellState extends State<HomeShell> {
List<CalendarEvent> get allEvents => [...events, ...widget.syncedEvents]; List<CalendarEvent> get allEvents => [...events, ...widget.syncedEvents];
final labels = const [
'Napt\u00e1r',
'Bev\u00e1s\u00e1rl\u00e1s',
'K\u00e9szlet',
'Csal\u00e1dtagok',
'St\u00edlus',
'Fi\u00f3kok',
];
final icons = const [ final icons = const [
Icons.calendar_month_rounded, Icons.calendar_month_rounded,
Icons.shopping_basket_outlined, Icons.shopping_basket_outlined,
@@ -349,6 +362,15 @@ class _HomeShellState extends State<HomeShell> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final wide = MediaQuery.sizeOf(context).width >= 850; final wide = MediaQuery.sizeOf(context).width >= 850;
final text = AppText.of(widget.languageCode);
final labels = [
text.calendar,
text.shopping,
text.stock,
text.familyMembers,
text.style,
text.accounts,
];
final body = IndexedStack( final body = IndexedStack(
index: selected, index: selected,
children: [ children: [
@@ -362,11 +384,13 @@ class _HomeShellState extends State<HomeShell> {
), ),
ShoppingPage( ShoppingPage(
items: shopping, items: shopping,
languageCode: widget.languageCode,
onChanged: () => setState(() {}), onChanged: () => setState(() {}),
onAdd: _addShopping, onAdd: _addShopping,
), ),
StockPage( StockPage(
items: stock, items: stock,
languageCode: widget.languageCode,
onChanged: () => setState(() {}), onChanged: () => setState(() {}),
onAdd: _addStock, onAdd: _addStock,
onEdit: _editStock, onEdit: _editStock,
@@ -375,12 +399,14 @@ class _HomeShellState extends State<HomeShell> {
PersonsPage( PersonsPage(
people: widget.people, people: widget.people,
events: allEvents, events: allEvents,
languageCode: widget.languageCode,
onAdd: _addPerson, onAdd: _addPerson,
onEdit: _editPerson, onEdit: _editPerson,
onDelete: _deletePerson, onDelete: _deletePerson,
), ),
StylePage( StylePage(
themeId: widget.themeId, themeId: widget.themeId,
languageCode: widget.languageCode,
onThemeChanged: widget.onThemeChanged, onThemeChanged: widget.onThemeChanged,
), ),
AccountsPage( AccountsPage(
@@ -389,6 +415,7 @@ class _HomeShellState extends State<HomeShell> {
people: widget.people, people: widget.people,
jarvisSettings: widget.jarvisSettings, jarvisSettings: widget.jarvisSettings,
serverClientId: widget.googleServerClientId, serverClientId: widget.googleServerClientId,
languageCode: widget.languageCode,
onChanged: widget.onGoogleConnectionsChanged, onChanged: widget.onGoogleConnectionsChanged,
onSyncedEventsChanged: widget.onSyncedEventsChanged, onSyncedEventsChanged: widget.onSyncedEventsChanged,
), ),
@@ -451,11 +478,11 @@ class _HomeShellState extends State<HomeShell> {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
const Text( Text(
'K\u00f6z\u00f6sT\u00e9r', text.appTitle,
maxLines: 1, maxLines: 1,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: TextStyle( style: const TextStyle(
fontSize: 18, fontSize: 18,
fontWeight: FontWeight.w900, fontWeight: FontWeight.w900,
color: ink, color: ink,
@@ -464,8 +491,8 @@ class _HomeShellState extends State<HomeShell> {
), ),
Text( Text(
widget.loaded widget.loaded
? 'Tervez\u0151' ? text.appSubtitle
: 'JSON bet\u00f6lt\u00e9se\u2026', : text.loadingJson,
style: const TextStyle( style: const TextStyle(
fontSize: 11, fontSize: 11,
color: Colors.black45, color: Colors.black45,
@@ -473,6 +500,12 @@ class _HomeShellState extends State<HomeShell> {
), ),
), ),
const SizedBox(height: 2), const SizedBox(height: 2),
LanguageSwitcher(
languageCode: widget.languageCode,
onChanged: widget.onLanguageChanged,
labels: text,
),
const SizedBox(height: 2),
const Text( const Text(
appVersionLabel, appVersionLabel,
style: TextStyle( style: TextStyle(
@@ -485,7 +518,7 @@ class _HomeShellState extends State<HomeShell> {
), ),
), ),
IconButton( IconButton(
tooltip: 'JARVIS be\u00e1ll\u00edt\u00e1sok', tooltip: text.jarvisSettings,
onPressed: _openJarvisSettings, onPressed: _openJarvisSettings,
icon: const Icon( icon: const Icon(
Icons.settings_outlined, Icons.settings_outlined,
@@ -1215,3 +1248,92 @@ class _HomeShellState extends State<HomeShell> {
} }
} }
} }
class LanguageSwitcher extends StatelessWidget {
const LanguageSwitcher({
super.key,
required this.languageCode,
required this.onChanged,
required this.labels,
});
final String languageCode;
final ValueChanged<String> onChanged;
final AppText labels;
@override
Widget build(BuildContext context) {
return Container(
height: 24,
padding: const EdgeInsets.all(2),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(999),
border: Border.all(color: sage.withValues(alpha: .16)),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
_LanguagePill(
selected: languageCode != 'en',
flag: '🇭🇺',
label: labels.hunShort,
onTap: () => onChanged('hu'),
),
_LanguagePill(
selected: languageCode == 'en',
flag: '🇬🇧',
label: labels.engShort,
onTap: () => onChanged('en'),
),
],
),
);
}
}
class _LanguagePill extends StatelessWidget {
const _LanguagePill({
required this.selected,
required this.flag,
required this.label,
required this.onTap,
});
final bool selected;
final String flag;
final String label;
final VoidCallback onTap;
@override
Widget build(BuildContext context) {
return InkWell(
borderRadius: BorderRadius.circular(999),
onTap: selected ? null : onTap,
child: AnimatedContainer(
duration: const Duration(milliseconds: 180),
padding: const EdgeInsets.symmetric(horizontal: 7, vertical: 2),
decoration: BoxDecoration(
color: selected ? sage : Colors.transparent,
borderRadius: BorderRadius.circular(999),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Text(flag, style: const TextStyle(fontSize: 11)),
const SizedBox(width: 3),
Text(
label,
style: TextStyle(
fontSize: 9,
height: 1,
fontWeight: FontWeight.w900,
color: selected ? Colors.white : Colors.black45,
),
),
],
),
),
);
}
}
+6
View File
@@ -122,6 +122,7 @@ class AppJsonStore {
final settings = AppSettings( final settings = AppSettings(
people: defaultPeople(), people: defaultPeople(),
themeId: 'sage', themeId: 'sage',
languageCode: defaultLanguageCode,
googleConnections: defaultGoogleConnections(), googleConnections: defaultGoogleConnections(),
syncedEvents: const [], syncedEvents: const [],
todoSuggestions: const [], todoSuggestions: const [],
@@ -139,6 +140,7 @@ class AppJsonStore {
return AppSettings( return AppSettings(
people: defaultPeople(), people: defaultPeople(),
themeId: 'sage', themeId: 'sage',
languageCode: defaultLanguageCode,
googleConnections: defaultGoogleConnections(), googleConnections: defaultGoogleConnections(),
syncedEvents: const [], syncedEvents: const [],
todoSuggestions: const [], todoSuggestions: const [],
@@ -160,6 +162,7 @@ class AppSettings {
AppSettings({ AppSettings({
required this.people, required this.people,
required this.themeId, required this.themeId,
required this.languageCode,
required this.googleConnections, required this.googleConnections,
required this.syncedEvents, required this.syncedEvents,
required this.todoSuggestions, required this.todoSuggestions,
@@ -169,6 +172,7 @@ class AppSettings {
final List<Person> people; final List<Person> people;
final String themeId; final String themeId;
final String languageCode;
final List<GoogleCalendarConnection> googleConnections; final List<GoogleCalendarConnection> googleConnections;
final List<CalendarEvent> syncedEvents; final List<CalendarEvent> syncedEvents;
final List<String> todoSuggestions; final List<String> todoSuggestions;
@@ -191,6 +195,7 @@ class AppSettings {
) )
: defaultPeople(), : defaultPeople(),
themeId: json['themeId'] as String? ?? 'sage', themeId: json['themeId'] as String? ?? 'sage',
languageCode: json['languageCode'] == 'en' ? 'en' : defaultLanguageCode,
googleConnections: rawConnections is List googleConnections: rawConnections is List
? rawConnections ? rawConnections
.whereType<Map<String, dynamic>>() .whereType<Map<String, dynamic>>()
@@ -218,6 +223,7 @@ class AppSettings {
Map<String, dynamic> toJson() => { Map<String, dynamic> toJson() => {
'themeId': themeId, 'themeId': themeId,
'languageCode': languageCode,
'people': people.map((person) => person.toJson()).toList(), 'people': people.map((person) => person.toJson()).toList(),
'googleConnections': googleConnections 'googleConnections': googleConnections
.map((connection) => connection.toJson()) .map((connection) => connection.toJson())
+6 -3
View File
@@ -8,6 +8,7 @@ class AccountsPage extends StatefulWidget {
required this.people, required this.people,
required this.jarvisSettings, required this.jarvisSettings,
required this.serverClientId, required this.serverClientId,
required this.languageCode,
required this.onChanged, required this.onChanged,
required this.onSyncedEventsChanged, required this.onSyncedEventsChanged,
}); });
@@ -17,6 +18,7 @@ class AccountsPage extends StatefulWidget {
final List<Person> people; final List<Person> people;
final JarvisSettings jarvisSettings; final JarvisSettings jarvisSettings;
final String serverClientId; final String serverClientId;
final String languageCode;
final ValueChanged<List<GoogleCalendarConnection>> onChanged; final ValueChanged<List<GoogleCalendarConnection>> onChanged;
final ValueChanged<List<CalendarEvent>> onSyncedEventsChanged; final ValueChanged<List<CalendarEvent>> onSyncedEventsChanged;
@@ -354,6 +356,7 @@ class _AccountsPageState extends State<AccountsPage> with WidgetsBindingObserver
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final text = AppText.of(widget.languageCode);
final current = connection; final current = connection;
final hasConnection = current != null && current.accountEmail.isNotEmpty; final hasConnection = current != null && current.accountEmail.isNotEmpty;
final cachedUncategorized = widget.cachedEvents final cachedUncategorized = widget.cachedEvents
@@ -361,13 +364,13 @@ class _AccountsPageState extends State<AccountsPage> with WidgetsBindingObserver
.length; .length;
return PageFrame( return PageFrame(
eyebrow: 'JARVIS Google Calendar szinkron', eyebrow: text.googleSyncEyebrow,
title: 'Google napt\u00e1rak', title: text.googleCalendars,
action: FilledButton.icon( action: FilledButton.icon(
onPressed: loadingCalendars ? null : _startGoogleConnection, onPressed: loadingCalendars ? null : _startGoogleConnection,
icon: const Icon(Icons.open_in_browser), icon: const Icon(Icons.open_in_browser),
label: Text( label: Text(
hasConnection ? 'Google \u00f6sszek\u00f6t\u00e9s \u00fajranyit\u00e1sa' : 'Google \u00f6sszek\u00f6t\u00e9s', hasConnection ? text.googleReconnect : text.googleConnect,
), ),
), ),
child: ListView( child: ListView(
+68
View File
@@ -0,0 +1,68 @@
part of 'main.dart';
const defaultLanguageCode = 'hu';
class AppText {
const AppText._(this.languageCode);
final String languageCode;
static AppText of(String languageCode) =>
languageCode == 'en' ? const AppText._('en') : const AppText._('hu');
Locale get locale => Locale(languageCode);
bool get isHungarian => languageCode == 'hu';
String get appTitle => isHungarian ? 'KözösTér' : 'CommonSpace';
String get appSubtitle => isHungarian ? 'Tervező' : 'Organizer';
String get loadingJson => isHungarian ? 'JSON betöltése…' : 'Loading JSON…';
String get jarvisSettings => isHungarian
? 'JARVIS beállítások'
: 'JARVIS settings';
String get calendar => isHungarian ? 'Naptár' : 'Calendar';
String get shopping => isHungarian ? 'Bevásárlás' : 'Shopping';
String get stock => isHungarian ? 'Készlet' : 'Stock';
String get familyMembers => isHungarian ? 'Családtagok' : 'Family';
String get style => isHungarian ? 'Stílus' : 'Style';
String get accounts => isHungarian ? 'Fiókok' : 'Accounts';
String familyCount(int count) =>
isHungarian ? '$count családtag' : '$count family members';
String get noFamilyMembers => isHungarian
? 'Még nincs családtag'
: 'No family members yet';
String get noFamilyMembersSubtitle => isHungarian
? 'Vegyél fel családtagokat, gyerekeket vagy bárkit.'
: 'Add family members, kids, or anyone you plan around.';
String get newFamilyMember => isHungarian ? 'Új családtag' : 'New member';
String get renameAvatar => isHungarian
? 'Átnevezés / avatar'
: 'Rename / avatar';
String get delete => isHungarian ? 'Törlés' : 'Delete';
String get themeAndStyles => isHungarian
? 'Téma és stílusok'
: 'Theme and styles';
String get appearance => isHungarian ? 'Megjelenés' : 'Appearance';
String remainingItems(int count) =>
isHungarian ? '$count tétel van hátra' : '$count items left';
String get shoppingList => isHungarian ? 'Bevásárlólista' : 'Shopping list';
String stockCount(int count) =>
isHungarian ? '$count termék nyilvántartva' : '$count products tracked';
String get homeStock => isHungarian ? 'Otthoni készlet' : 'Home stock';
String get googleSyncEyebrow => isHungarian
? 'JARVIS Google Calendar szinkron'
: 'JARVIS Google Calendar sync';
String get googleCalendars => isHungarian ? 'Google naptárak' : 'Google calendars';
String get googleConnect => isHungarian ? 'Google összekötés' : 'Connect Google';
String get googleReconnect => isHungarian
? 'Google összekötés újranyitása'
: 'Reconnect Google';
String get hunShort => 'HUN';
String get engShort => 'ENG';
}
+2
View File
@@ -5,6 +5,7 @@ import 'dart:math' as math;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:geocoding/geocoding.dart' as geocoding; import 'package:geocoding/geocoding.dart' as geocoding;
import 'package:geolocator/geolocator.dart'; import 'package:geolocator/geolocator.dart';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
@@ -14,6 +15,7 @@ import 'package:timezone/data/latest.dart' as timezone_data;
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
part 'data.dart'; part 'data.dart';
part 'localization.dart';
part 'app_shell.dart'; part 'app_shell.dart';
part 'calendar_widgets.dart'; part 'calendar_widgets.dart';
part 'pages.dart'; part 'pages.dart';
+27 -16
View File
@@ -5,6 +5,7 @@ class PersonsPage extends StatelessWidget {
super.key, super.key,
required this.people, required this.people,
required this.events, required this.events,
required this.languageCode,
required this.onAdd, required this.onAdd,
required this.onEdit, required this.onEdit,
required this.onDelete, required this.onDelete,
@@ -12,26 +13,27 @@ class PersonsPage extends StatelessWidget {
final List<Person> people; final List<Person> people;
final List<CalendarEvent> events; final List<CalendarEvent> events;
final String languageCode;
final VoidCallback onAdd; final VoidCallback onAdd;
final ValueChanged<Person> onEdit; final ValueChanged<Person> onEdit;
final ValueChanged<Person> onDelete; final ValueChanged<Person> onDelete;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final text = AppText.of(languageCode);
return PageFrame( return PageFrame(
eyebrow: '${people.length} csal\u00e1dtag', eyebrow: text.familyCount(people.length),
title: 'Csal\u00e1dtagok', title: text.familyMembers,
action: FilledButton.icon( action: FilledButton.icon(
onPressed: onAdd, onPressed: onAdd,
icon: const Icon(Icons.add), icon: const Icon(Icons.add),
label: const Text('\u00daj csal\u00e1dtag'), label: Text(text.newFamilyMember),
), ),
child: people.isEmpty child: people.isEmpty
? const EmptyState( ? EmptyState(
icon: Icons.group_add_outlined, icon: Icons.group_add_outlined,
title: 'M\u00e9g nincs csal\u00e1dtag', title: text.noFamilyMembers,
subtitle: subtitle: text.noFamilyMembersSubtitle,
'Vegy\u00e9l fel csal\u00e1dtagokat, gyerekeket vagy b\u00e1rkit.',
) )
: ListView.separated( : ListView.separated(
padding: const EdgeInsets.only(bottom: 24), padding: const EdgeInsets.only(bottom: 24),
@@ -90,14 +92,14 @@ class PersonsPage extends StatelessWidget {
if (value == 'edit') onEdit(person); if (value == 'edit') onEdit(person);
if (value == 'delete') onDelete(person); if (value == 'delete') onDelete(person);
}, },
itemBuilder: (_) => const [ itemBuilder: (_) => [
PopupMenuItem( PopupMenuItem(
value: 'edit', value: 'edit',
child: Text('\u00c1tnevez\u00e9s / avatar'), child: Text(text.renameAvatar),
), ),
PopupMenuItem( PopupMenuItem(
value: 'delete', value: 'delete',
child: Text('T\u00f6rl\u00e9s'), child: Text(text.delete),
), ),
], ],
), ),
@@ -115,17 +117,20 @@ class StylePage extends StatelessWidget {
const StylePage({ const StylePage({
super.key, super.key,
required this.themeId, required this.themeId,
required this.languageCode,
required this.onThemeChanged, required this.onThemeChanged,
}); });
final String themeId; final String themeId;
final String languageCode;
final ValueChanged<String> onThemeChanged; final ValueChanged<String> onThemeChanged;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final text = AppText.of(languageCode);
return PageFrame( return PageFrame(
eyebrow: 'T\u00e9ma \u00e9s st\u00edlusok', eyebrow: text.themeAndStyles,
title: 'Megjelen\u00e9s', title: text.appearance,
child: ListView( child: ListView(
padding: const EdgeInsets.only(bottom: 24), padding: const EdgeInsets.only(bottom: 24),
children: [ children: [
@@ -187,20 +192,23 @@ class ShoppingPage extends StatelessWidget {
const ShoppingPage({ const ShoppingPage({
super.key, super.key,
required this.items, required this.items,
required this.languageCode,
required this.onChanged, required this.onChanged,
required this.onAdd, required this.onAdd,
}); });
final List<ShoppingItem> items; final List<ShoppingItem> items;
final String languageCode;
final VoidCallback onChanged; final VoidCallback onChanged;
final VoidCallback onAdd; final VoidCallback onAdd;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final text = AppText.of(languageCode);
final remaining = items.where((e) => !e.done).length; final remaining = items.where((e) => !e.done).length;
return PageFrame( return PageFrame(
eyebrow: '$remaining t\u00e9tel van h\u00e1tra', eyebrow: text.remainingItems(remaining),
title: 'Bev\u00e1s\u00e1rl\u00f3lista', title: text.shoppingList,
action: IconButton.filled(onPressed: onAdd, icon: const Icon(Icons.add)), action: IconButton.filled(onPressed: onAdd, icon: const Icon(Icons.add)),
child: Column( child: Column(
children: [ children: [
@@ -278,6 +286,7 @@ class StockPage extends StatefulWidget {
const StockPage({ const StockPage({
super.key, super.key,
required this.items, required this.items,
required this.languageCode,
required this.onChanged, required this.onChanged,
required this.onAdd, required this.onAdd,
required this.onEdit, required this.onEdit,
@@ -285,6 +294,7 @@ class StockPage extends StatefulWidget {
}); });
final List<StockItem> items; final List<StockItem> items;
final String languageCode;
final VoidCallback onChanged; final VoidCallback onChanged;
final VoidCallback onAdd; final VoidCallback onAdd;
final ValueChanged<StockItem> onEdit; final ValueChanged<StockItem> onEdit;
@@ -299,10 +309,11 @@ class _StockPageState extends State<StockPage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final text = AppText.of(widget.languageCode);
final filtered = widget.items.where((e) => e.location == location).toList(); final filtered = widget.items.where((e) => e.location == location).toList();
return PageFrame( return PageFrame(
eyebrow: '${widget.items.length} term\u00e9k nyilv\u00e1ntartva', eyebrow: text.stockCount(widget.items.length),
title: 'Otthoni k\u00e9szlet', title: text.homeStock,
action: IconButton.filled( action: IconButton.filled(
onPressed: widget.onAdd, onPressed: widget.onAdd,
icon: const Icon(Icons.add), icon: const Icon(Icons.add),
+13
View File
@@ -190,6 +190,11 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.0.0" version: "6.0.0"
flutter_localizations:
dependency: "direct main"
description: flutter
source: sdk
version: "0.0.0"
flutter_test: flutter_test:
dependency: "direct dev" dependency: "direct dev"
description: flutter description: flutter
@@ -344,6 +349,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.1.2" version: "4.1.2"
intl:
dependency: transitive
description:
name: intl
sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5"
url: "https://pub.dev"
source: hosted
version: "0.20.2"
jni: jni:
dependency: transitive dependency: transitive
description: description:
+2
View File
@@ -30,6 +30,8 @@ environment:
dependencies: dependencies:
flutter: flutter:
sdk: flutter sdk: flutter
flutter_localizations:
sdk: flutter
# The following adds the Cupertino Icons font to your application. # The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons. # Use with the CupertinoIcons class for iOS style icons.