Import sorgenti Flutter di Henflow (export da Nextcloud: lib/ + documenti di progetto)

This commit is contained in:
Carlo Baratto
2026-10-09 08:51:15 +02:00
commit bfd086c488
14 changed files with 4129 additions and 0 deletions
+480
View File
@@ -0,0 +1,480 @@
enum AppLanguage { it, en, fr, de }
class TranslationService {
static AppLanguage _currentLanguage = AppLanguage.en;
static void setLanguage(AppLanguage lang) {
_currentLanguage = lang;
}
static AppLanguage get currentLanguage => _currentLanguage;
static final Map<AppLanguage, Map<String, String>> _data = {
AppLanguage.it: {
'app_title': 'Henflow',
'daily_prod_est': 'Produzione giornaliera stimata',
'eggs_per_day': 'uova/giorno',
'no_breeds': 'Nessuna razza configurata.',
'hens': 'galline',
'eggs_per_g': 'uova/g',
'reservations': 'Prenotazioni',
'no_reservations': 'Nessuna prenotazione inserita.',
'use_button': 'Usa il pulsante "Nuovo ordine" per registrare un cliente.',
'new_order': 'Nuovo ordine',
'edit_order': 'Modifica ordine',
'breed': 'Razza',
'eggs_req': 'Uova richieste',
'delivery': 'Consegna',
'today': 'Oggi',
'ready_delivery': 'Pronti per la consegna',
'expired': 'Scaduto',
'in_day': 'Tra 1 giorno',
'in_days': 'Tra {} giorni',
'settings': 'Configurazione',
'save': 'Salva',
'available_breeds': 'Razze disponibili',
'my_coop': 'Il mio pollaio',
'no_breeds_sel': 'Nessuna razza selezionata.\\nVai in "Razze disponibili" per attivare quelle che allevi.',
'reg_hens': 'Galline registrate',
'in_laying': 'In deposizione',
'est_prod': 'Produzione stimata',
'manage_hens': 'Gestisci anagrafica galline',
'breed_sheet': 'Scheda {}',
'new_hen': 'Nuova gallina',
'egg_color': 'Colore uova',
'laying_6_months': 'Galline in deposizione (6+ mesi)',
'hen_registry': 'Anagrafica galline',
'no_hens_reg': 'Nessuna gallina registrata per questa razza.',
'birth': 'Nascita',
'age_months': 'Età: {} mesi',
'status_laying': 'Stato: in deposizione',
'status_rest': 'Stato: a riposo',
'status_young': 'Stato: troppo giovane per deporre',
'hen_name': 'Nome gallina',
'birth_date': 'Data di nascita',
'select_date': 'Seleziona data',
'cancel': 'Annulla',
'customer_name': 'Nome cliente',
'need_hen_error': 'Per creare un ordine serve almeno una gallina di 6 mesi o più in una delle razze configurate.',
'delivery_preview': 'Anteprima consegna',
'save_order': 'Salva ordine',
'language': 'Lingua',
'config_breed_first': 'Configura prima almeno una razza nelle impostazioni.',
'name_marans': 'Marans',
'name_araucana': 'Araucana',
'name_olive': 'Olive Egger',
'name_livorno': 'Livorno',
'name_sussex': 'Sussex',
'name_australorp': 'Australorp',
'name_generic': 'Ovaiola generica',
'desc_marans': 'Famosa per le sue uova color cioccolato fondente.',
'desc_araucana': 'Uccello senza coda che depone uova azzurro-verdi.',
'desc_olive': 'Incrocio che produce uova di un bellissimo verde oliva.',
'desc_livorno': 'Eccellente produttrice di uova bianche, snella e vivace.',
'desc_sussex': 'Razza versatile e docile, depone uova color crema.',
'desc_australorp': 'Detentrice del record mondiale di deposizione, uova marroni chiare.',
'desc_generic': 'Gallina ovaiola di razza mista o non specificata.',
'color_dark_brown': 'Marrone scuro',
'color_blue': 'Azzurro',
'color_olive': 'Verde Oliva',
'color_white': 'Bianco',
'color_cream': 'Crema',
'color_light_brown': 'Marrone chiaro',
'confirm_delete': 'Conferma eliminazione',
'delete_msg': 'Sei sicuro di voler eliminare questo elemento?',
'delete': 'Elimina',
'backup_restore': 'Backup e Ripristino',
'export_data': 'Esporta dati',
'import_data': 'Importa dati',
'copy_to_clipboard': 'Copia negli appunti',
'copied': 'Copiato!',
'paste_json_here': 'Incolla qui il JSON di backup',
'import_success': 'Dati importati con successo!',
'import_error': 'Errore durante l\'importazione. Controlla il formato.',
'confirm_deactivation': 'Conferma disattivazione',
'deactivation_msg': 'Disattivando questa razza, tutte le galline registrate verranno eliminate definitivamente. Vuoi procedere?',
'deactivate': 'Disattiva',
'new_customer': 'Nuovo cliente',
'first_name': 'Nome',
'last_name': 'Cognome',
'phone_number': 'Numero di telefono',
'save_customer': 'Salva cliente',
'customers_list': 'Elenco clienti',
'edit_customer': 'Modifica cliente',
'no_customers': 'Nessun cliente registrato.',
'share_order_msg': 'Ciao {}, il tuo ordine di {} uova di razza {} è previsto per il {}.',
'welcome': 'Benvenuto in Henflow!',
'intro_step1_title': '1. Seleziona le razze',
'intro_step1_desc': 'Vai nelle impostazioni e attiva le razze che allevi nel tuo pollaio.',
'intro_step2_title': '2. Aggiungi le galline',
'intro_step2_desc': 'Per ogni razza attiva, inserisci le tue galline. Solo quelle con più di 6 mesi contribuiscono alla produzione.',
'intro_step3_title': '3. Anagrafica clienti',
'intro_step3_desc': 'Registra i tuoi clienti per velocizzare la creazione degli ordini.',
'intro_step4_title': '4. Gestisci gli ordini',
'intro_step4_desc': 'Aggiungi le prenotazioni. Eggflow calcolerà automaticamente la data di consegna in base alla produzione.',
'start_app': 'Inizia ora',
'show_intro': 'Mostra introduzione',
'about': 'Informazioni',
'about_desc': 'Henflow è la tua soluzione completa per la gestione professionale di un piccolo pollaio. \\n\\nCon questa app puoi monitorare la produzione giornaliera delle tue galline, gestire un\'anagrafica clienti dettagliata e organizzare le prenotazioni delle uova con ricalcoli automatici delle date di consegna. \\n\\nProgettata per rendere semplice ed efficiente l\'attività di ogni allevatore.',
'calendar': 'Calendario',
'orders_list': 'Elenco ordini',
'warehouse': 'Magazzino',
'eggs_in_stock': 'Uova in magazzino',
'edit_stock': 'Modifica giacenza',
'last_update': 'Ultimo aggiornamento',
},
AppLanguage.en: {
'app_title': 'Henflow',
'daily_prod_est': 'Estimated daily production',
'eggs_per_day': 'eggs/day',
'no_breeds': 'No breeds configured.',
'hens': 'hens',
'eggs_per_g': 'eggs/d',
'reservations': 'Reservations',
'no_reservations': 'No reservations entered.',
'use_button': 'Use the "New order" button to register a customer.',
'new_order': 'New order',
'edit_order': 'Edit order',
'breed': 'Breed',
'eggs_req': 'Eggs requested',
'delivery': 'Delivery',
'today': 'Today',
'ready_delivery': 'Ready for delivery',
'expired': 'Expired',
'in_day': 'In 1 day',
'in_days': 'In {} days',
'settings': 'Configuration',
'save': 'Save',
'available_breeds': 'Available breeds',
'my_coop': 'My coop',
'no_breeds_sel': 'No breeds selected.\\nGo to "Available breeds" to activate the ones you raise.',
'reg_hens': 'Registered hens',
'in_laying': 'Laying',
'est_prod': 'Estimated production',
'manage_hens': 'Manage hen records',
'breed_sheet': '{} sheet',
'new_hen': 'New hen',
'egg_color': 'Egg color',
'laying_6_months': 'Laying hens (6+ months)',
'hen_registry': 'Hen registry',
'no_hens_reg': 'No hens registered for this breed.',
'birth': 'Birth',
'age_months': 'Age: {} months',
'status_laying': 'Status: laying',
'status_rest': 'Status: resting',
'status_young': 'Status: too young to lay',
'hen_name': 'Hen name',
'birth_date': 'Birth date',
'select_date': 'Select date',
'cancel': 'Cancel',
'customer_name': 'Customer name',
'need_hen_error': 'To create an order you need at least one hen 6 months or older in one of the configured breeds.',
'delivery_preview': 'Delivery preview',
'save_order': 'Save order',
'language': 'Language',
'config_breed_first': 'Configure at least one breed in settings first.',
'name_marans': 'Marans',
'name_araucana': 'Araucana',
'name_olive': 'Olive Egger',
'name_livorno': 'Leghorn',
'name_sussex': 'Sussex',
'name_australorp': 'Australorp',
'name_generic': 'Generic Layer',
'desc_marans': 'Famous for its dark chocolate-colored eggs.',
'desc_araucana': 'Rumpless bird that lays blue-green eggs.',
'desc_olive': 'Hybrid that produces beautiful olive green eggs.',
'desc_livorno': 'Excellent producer of white eggs, slender and active.',
'desc_sussex': 'Versatile and docile breed, lays cream-colored eggs.',
'desc_australorp': 'World record holder for egg laying, light brown eggs.',
'desc_generic': 'Laying hen of mixed or unspecified breed.',
'color_dark_brown': 'Dark brown',
'color_blue': 'Blue',
'color_olive': 'Olive',
'color_white': 'White',
'color_cream': 'Cream',
'color_light_brown': 'Light brown',
'confirm_delete': 'Confirm deletion',
'delete_msg': 'Are you sure you want to delete this item?',
'delete': 'Delete',
'backup_restore': 'Backup & Restore',
'export_data': 'Export data',
'import_data': 'Import data',
'copy_to_clipboard': 'Copy to clipboard',
'copied': 'Copied!',
'paste_json_here': 'Paste backup JSON here',
'import_success': 'Data imported successfully!',
'import_error': 'Import error. Check the format.',
'confirm_deactivation': 'Confirm deactivation',
'deactivation_msg': 'By deactivating this breed, all registered hens will be permanently deleted. Do you want to proceed?',
'deactivate': 'Deactivate',
'new_customer': 'New customer',
'first_name': 'First name',
'last_name': 'Last name',
'phone_number': 'Phone number',
'save_customer': 'Save customer',
'customers_list': 'Customers list',
'edit_customer': 'Edit customer',
'no_customers': 'No customers registered.',
'share_order_msg': 'Hi {}, your order for {} eggs of breed {} is scheduled for {}.',
'welcome': 'Welcome to Henflow!',
'intro_step1_title': '1. Select breeds',
'intro_step1_desc': 'Go to settings and activate the breeds you raise in your coop.',
'intro_step2_title': '2. Add hens',
'intro_step2_desc': 'For each active breed, enter your hens. Only those older than 6 months contribute to production.',
'intro_step3_title': '3. Customer records',
'intro_step3_desc': 'Register your customers to speed up order creation.',
'intro_step4_title': '4. Manage orders',
'intro_step4_desc': 'Add bookings. Eggflow will automatically calculate the delivery date based on production.',
'start_app': 'Get started',
'show_intro': 'Show introduction',
'about': 'About',
'about_desc': 'Henflow is your complete solution for professional management of a small poultry farm. \\n\\nWith this app, you can monitor the daily production of your hens, manage detailed customer records, and organize egg bookings with automatic recalculations of delivery dates. \\n\\nDesigned to make every breeder\'s activity simple and efficient.',
'calendar': 'Calendar',
'orders_list': 'Orders list',
'warehouse': 'Warehouse',
'eggs_in_stock': 'Eggs in stock',
'edit_stock': 'Edit stock',
'last_update': 'Last update',
},
AppLanguage.fr: {
'app_title': 'Henflow',
'daily_prod_est': 'Production quotidienne estimée',
'eggs_per_day': 'œufs/jour',
'no_breeds': 'Aucune race configurée.',
'hens': 'poules',
'eggs_per_g': 'œufs/j',
'reservations': 'Réservations',
'no_reservations': 'Aucune réservation saisie.',
'use_button': 'Utilisez le bouton "Nouvelle commande" pour enregistrer un client.',
'new_order': 'Nouvelle commande',
'edit_order': 'Modifier la commande',
'breed': 'Race',
'eggs_req': 'Œufs demandés',
'delivery': 'Livraison',
'today': 'Aujourd\'hui',
'ready_delivery': 'Prêt per la consegna',
'expired': 'Expiré',
'in_day': 'Dans 1 jour',
'in_days': 'Dans {} jours',
'settings': 'Configuration',
'save': 'Sauvegarder',
'available_breeds': 'Races disponibles',
'my_coop': 'Mon poulailler',
'no_breeds_sel': 'Aucune race sélectionnée.\\nAllez dans "Races disponibles" pour activer celles que vous élevez.',
'reg_hens': 'Poules enregistrées',
'in_laying': 'En ponte',
'est_prod': 'Production estimée',
'manage_hens': 'Gérer les fiches des poules',
'breed_sheet': 'Fiche {}',
'new_hen': 'Nouvelle poule',
'egg_color': 'Couleur des œufs',
'laying_6_months': 'Poules en ponte (6+ mois)',
'hen_registry': 'Registre des poules',
'no_hens_reg': 'Aucune poule enregistrée pour cette race.',
'birth': 'Naissance',
'age_months': 'Âge: {} mois',
'status_laying': 'Statut: en ponte',
'status_rest': 'Statut: au repos',
'status_young': 'Statut: trop jeune pour pondre',
'hen_name': 'Nom de la poule',
'birth_date': 'Date de naissance',
'select_date': 'Choisir une date',
'cancel': 'Annuler',
'customer_name': 'Nom du client',
'need_hen_error': 'Pour créer une commande, vous avez besoin d\'au moins une poule de 6 mois ou plus dans l\'une des races configurées.',
'delivery_preview': 'Aperçu de la livraison',
'save_order': 'Sauvegarder la commande',
'language': 'Langue',
'config_breed_first': 'Configurez d\'abord au moins une race dans les paramètres.',
'name_marans': 'Marans',
'name_araucana': 'Araucana',
'name_olive': 'Olive Egger',
'name_livorno': 'Livourne',
'name_sussex': 'Sussex',
'name_australorp': 'Australorp',
'name_generic': 'Pondeuse générique',
'desc_marans': 'Célèbre pour ses œufs couleur chocolat noir.',
'desc_araucana': 'Oiseau sans queue qui pond des œufs bleu-vert.',
'desc_olive': 'Croisement qui produit de magnifiques œufs vert olive.',
'desc_livorno': 'Excellente pondeuse d\'œufs blancs, svelte et vive.',
'desc_sussex': 'Race polyvalente et docile, pond des œufs de couleur crème.',
'desc_australorp': 'Détentrice du record mondial de ponte, œufs brun clair.',
'desc_generic': 'Poule pondeuse de race mixte ou non spécifiée.',
'color_dark_brown': 'Brun foncé',
'color_blue': 'Bleu',
'color_olive': 'Olive',
'color_white': 'Blanc',
'color_cream': 'Crème',
'color_light_brown': 'Brun clair',
'confirm_delete': 'Confirmer la suppression',
'delete_msg': 'Êtes-vous sûr de vouloir supprimer cet élément ?',
'delete': 'Supprimer',
'backup_restore': 'Sauvegarde et Restauration',
'export_data': 'Exporter les données',
'import_data': 'Importer des données',
'copy_to_clipboard': 'Copier dans le presse-papiers',
'copied': 'Copié !',
'paste_json_here': 'Collez le JSON de sauvegarde ici',
'import_success': 'Données importées avec succès !',
'import_error': 'Erreur d\'importation. Vérifiez le format.',
'confirm_deactivation': 'Confirmer la désactivation',
'deactivation_msg': 'En désactivant cette race, tutte le galline registrate verranno eliminate definitivamente. Vuoi procedere?',
'deactivate': 'Désactiver',
'new_customer': 'Nouveau client',
'first_name': 'Prénom',
'last_name': 'Nom',
'phone_number': 'Numéro de téléphone',
'save_customer': 'Sauvegarder le client',
'customers_list': 'Liste des clients',
'edit_customer': 'Modifier le client',
'no_customers': 'Aucun client enregistré.',
'share_order_msg': 'Bonjour {}, votre commande de {} œufs de race {} est prévue pour le {}.',
'welcome': 'Bienvenue sur Henflow !',
'intro_step1_title': '1. Sélectionnez les races',
'intro_step1_desc': 'Allez dans les paramètres et activez les races que vous élevez dans votre poulailler.',
'intro_step2_title': '2. Ajoutez les poules',
'intro_step2_desc': 'Pour chaque race active, saisissez vos poules. Seules celles de plus de 6 mois contribuent à la production.',
'intro_step3_title': '3. Fiches clients',
'intro_step3_desc': 'Enregistrez vos clients pour accélérer la création de commandes.',
'intro_step4_title': '4. Gérez les commandes',
'intro_step4_desc': 'Ajoutez des réservations. Eggflow calculera automaticamente la date de livraison en fonction de la production.',
'start_app': 'Commencer',
'show_intro': 'Afficher l\'introduction',
'about': 'À propos',
'about_desc': 'Henflow est votre solution complète per la gestione professionale di un piccolo pollaio. \\n\\nAvec cette application, vous pouvez surveiller la production quotidienne de vos poules, gestire un\'anagrafica clienti dettagliata e organizzare le prenotazioni delle uova con ricalcoli automatici delle date di consegna. \\n\\nConçue per rendere simple ed efficiente l\'attività di ogni allevatore.',
'calendar': 'Calendrier',
'orders_list': 'Liste des commandes',
'warehouse': 'Entrepôt',
'eggs_in_stock': 'Œufs in stock',
'edit_stock': 'Modifier le stock',
'last_update': 'Dernière mise à jour',
},
AppLanguage.de: {
'app_title': 'Henflow',
'daily_prod_est': 'Geschätzte tägliche Produktion',
'eggs_per_day': 'Eier/Tag',
'no_breeds': 'Keine Rassen konfiguriert.',
'hens': 'Hennen',
'eggs_per_g': 'Eier/Tag',
'reservations': 'Reservierungen',
'no_reservations': 'Keine Reservierungen eingetragen.',
'use_button': 'Verwenden Sie die Schaltfläche "Neue Bestellung", um einen Kunden zu registrieren.',
'new_order': 'Neue Bestellung',
'edit_order': 'Bestellung bearbeiten',
'breed': 'Rasse',
'eggs_req': 'Anzahl Eier',
'delivery': 'Lieferung',
'today': 'Heute',
'ready_delivery': 'Bereit zur Auslieferung',
'expired': 'Abgelaufen',
'in_day': 'In 1 Tag',
'in_days': 'In {} Tagen',
'settings': 'Konfiguration',
'save': 'Speichern',
'available_breeds': 'Verfügbare Rassen',
'my_coop': 'Mein Hühnerstall',
'no_breeds_sel': 'Keine Rassen ausgewählt.\\nGehen Sie zu "Verfügbare Rassen", um die von Ihnen gezüchteten zu aktivieren.',
'reg_hens': 'Registrierte Hennen',
'in_laying': 'In Legephase',
'est_prod': 'Geschätzte Produktion',
'manage_hens': 'Hühnerbestand verwalten',
'breed_sheet': 'Datenblatt {}',
'new_hen': 'Neue Henne',
'egg_color': 'Eierfarbe',
'laying_6_months': 'Legehennen (6+ Monate)',
'hen_registry': 'Hühnerregister',
'no_hens_reg': 'Keine Hennen für diese Rasse registriert.',
'birth': 'Geburt',
'age_months': 'Alter: {} Monate',
'status_laying': 'Status: legend',
'status_rest': 'Status: ruhend',
'status_young': 'Status: zu jung zum Legen',
'hen_name': 'Name der Henne',
'birth_date': 'Geburtsdatum',
'select_date': 'Datum auswählen',
'cancel': 'Abbrechen',
'customer_name': 'Kundenname',
'need_hen_error': 'Um eine Bestellung aufzugeben, benötigen Sie mindestens eine Henne, die 6 Monate oder älter ist, in einer der konfigurierten Rassen.',
'delivery_preview': 'Liefervorschau',
'save_order': 'Bestellung speichern',
'language': 'Sprache',
'config_breed_first': 'Konfigurieren Sie zuerst mindestens eine Rasse in den Einstellungen.',
'name_marans': 'Marans',
'name_araucana': 'Araucana',
'name_olive': 'Olive Egger',
'name_livorno': 'Leghorn',
'name_sussex': 'Sussex',
'name_australorp': 'Australorp',
'name_generic': 'Generische Leghenne',
'desc_marans': 'Berühmt für ihre dunklen, schokoladenbraunen Eier.',
'desc_araucana': 'Schwanzloses Huhn, das blau-grüne Eier legt.',
'desc_olive': 'Kreuzung, die wunderschöne olivgrüne Eier hervorbringt.',
'desc_livorno': 'Hervorragende Legerin von weißen Eiern, schlank und lebhaft.',
'desc_sussex': 'Vielseitige und sanftmütige Rasse, legt cremefarbene Eier.',
'desc_australorp': 'Weltrekordhalterin im Eierlegen, hellbraune Eier.',
'desc_generic': 'Legehenne gemischter oder nicht spezifizierter Rasse.',
'color_dark_brown': 'Dunkelbraun',
'color_blue': 'Blau',
'color_olive': 'Olivgrün',
'color_white': 'Weiß',
'color_cream': 'Creme',
'color_light_brown': 'Hellbraun',
'confirm_delete': 'Löschen bestätigen',
'delete_msg': 'Sind Sie sicher, dass Sie dieses Element löschen möchten?',
'delete': 'Löschen',
'backup_restore': 'Backup & Wiederherstellung',
'export_data': 'Daten exportieren',
'import_data': 'Daten importieren',
'copy_to_clipboard': 'In die Zwischenablage kopieren',
'copied': 'Kopiert!',
'paste_json_here': 'Backup-JSON hier einfügen',
'import_success': 'Daten erfolgreich importiert!',
'import_error': 'Fehler beim Importieren. Überprüfen Sie das Format.',
'confirm_deactivation': 'Deaktivierung bestätigen',
'deactivation_msg': 'Durch Deaktivieren dieser Rasse werden alle registrierten Hennen dauerhaft gelöscht. Möchten Sie fortfahren?',
'deactivate': 'Deaktivieren',
'new_customer': 'Neuer Kunde',
'first_name': 'Vorname',
'last_name': 'Nachname',
'phone_number': 'Telefonnummer',
'save_customer': 'Kunde speichern',
'customers_list': 'Kundenliste',
'edit_customer': 'Kunde bearbeiten',
'no_customers': 'Keine Kunden registriert.',
'share_order_msg': 'Hallo {}, Ihre Bestellung über {} Eier der Rasse {} ist für den {} geplant.',
'welcome': 'Willkommen bei Henflow!',
'intro_step1_title': '1. Rassen auswählen',
'intro_step1_desc': 'Gehen Sie zu den Einstellungen und aktivieren Sie die Rassen, die Sie in Ihrem Stall halten.',
'intro_step2_title': '2. Hennen hinzufügen',
'intro_step2_desc': 'Geben Sie für jede aktive Rasse Ihre Hennen ein. Nur Hennen, die älter als 6 Monate sind, tragen zur Produktion bei.',
'intro_step3_title': '3. Kundenkartei',
'intro_step3_desc': 'Registrieren Sie Ihre Kunden, um die Bestellerstellung zu beschleunigen.',
'intro_step4_title': '4. Bestellungen verwalten',
'intro_step4_desc': 'Fügen Sie Buchungen hinzu. Eggflow berechnet automatisch das Lieferdatum basierend auf der Produktion.',
'start_app': 'Jetzt starten',
'show_intro': 'Einführung anzeigen',
'about': 'Über uns',
'about_desc': 'Henflow ist Ihre Komplettlösung für die professionelle Verwaltung eines kleinen Hühnerstalls. \\n\\nMit dieser App können Sie die tägliche Produktion Ihrer Hennen überwachen, eine detaillierte Kundenkartei verwalten und Eierreservierungen mit automatischen Neuberechnungen der Liefertermine organisieren. \\n\\nEntwickelt, um die Tätigkeit jedes Züchters einfach und effizient zu gestalten.',
'calendar': 'Kalender',
'orders_list': 'Bestellliste',
'warehouse': 'Lager',
'eggs_in_stock': 'Eier auf Lager',
'edit_stock': 'Bestand bearbeiten',
'last_update': 'Letzte Aktualisierung',
},
};
static String t(String key, {dynamic arg}) {
String text = _data[_currentLanguage]?[key] ?? key;
if (arg != null) {
if (arg is List) {
for (var a in arg) {
text = text.replaceFirst('{}', a.toString());
}
} else {
text = text.replaceFirst('{}', arg.toString());
}
}
return text;
}
}
+77
View File
@@ -0,0 +1,77 @@
import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';
class DatabaseHelper {
static final DatabaseHelper instance = DatabaseHelper._init();
static Database? _database;
DatabaseHelper._init();
Future<Database> get database async {
if (_database != null) return _database!;
_database = await _initDB('egg_bookings.db');
return _database!;
}
Future<Database> _initDB(String filePath) async {
final dbPath = await getDatabasesPath();
final path = join(dbPath, filePath);
return openDatabase(
path,
version: 1,
onCreate: _createDB,
);
}
Future<void> _createDB(Database db, int version) async {
await db.execute('''
CREATE TABLE bookings (
id INTEGER PRIMARY KEY AUTOINCREMENT,
date TEXT NOT NULL,
customer_name TEXT NOT NULL,
marans INTEGER NOT NULL DEFAULT 0,
araucana INTEGER NOT NULL DEFAULT 0,
olive INTEGER NOT NULL DEFAULT 0,
note TEXT NOT NULL DEFAULT ''
)
''');
}
Future<List<Map<String, dynamic>>> getAllBookings() async {
final db = await instance.database;
return db.query(
'bookings',
orderBy: 'date ASC, customer_name ASC',
);
}
Future<int> insertBooking(Map<String, dynamic> booking) async {
final db = await instance.database;
return db.insert('bookings', booking);
}
Future<int> updateBooking(Map<String, dynamic> booking) async {
final db = await instance.database;
return db.update(
'bookings',
booking,
where: 'id = ?',
whereArgs: [booking['id']],
);
}
Future<int> deleteBooking(int id) async {
final db = await instance.database;
return db.delete(
'bookings',
where: 'id = ?',
whereArgs: [id],
);
}
Future<void> close() async {
final db = await instance.database;
db.close();
}
}
+38
View File
@@ -0,0 +1,38 @@
import 'package:flutter/material.dart';
import '../app_language.dart';
Future<bool> showDeactivateDialog(BuildContext context) async {
final t = TranslationService.t;
return await showDialog<bool>(
context: context,
builder: (ctx) => AlertDialog(
title: Text(t('confirm_deactivation')),
content: Text(t('deactivation_msg')),
actions: [
TextButton(onPressed: () => Navigator.pop(ctx, false), child: Text(t('cancel'))),
TextButton(
onPressed: () => Navigator.pop(ctx, true),
child: Text(t('deactivate'), style: const TextStyle(color: Colors.red)),
),
],
),
) ?? false;
}
Future<bool> showConfirmDialog(BuildContext context) async {
final t = TranslationService.t;
return await showDialog<bool>(
context: context,
builder: (ctx) => AlertDialog(
title: Text(t('confirm_delete')),
content: Text(t('delete_msg')),
actions: [
TextButton(onPressed: () => Navigator.pop(ctx, false), child: Text(t('cancel'))),
TextButton(
onPressed: () => Navigator.pop(ctx, true),
child: Text(t('delete'), style: const TextStyle(color: Colors.red)),
),
],
),
) ?? false;
}
+2986
View File
File diff suppressed because it is too large Load Diff
+83
View File
@@ -0,0 +1,83 @@
class BreedCatalogItem {
final String id;
final String name;
final String description;
final String eggColor;
final double eggsPerHenPerDay;
final String assetPath;
const BreedCatalogItem({
required this.id,
required this.name,
required this.description,
required this.eggColor,
required this.eggsPerHenPerDay,
required this.assetPath,
});
}
const List<BreedCatalogItem> breedCatalog = [
BreedCatalogItem(
id: 'marans',
name: 'name_marans',
description: 'desc_marans',
eggColor: 'color_dark_brown',
eggsPerHenPerDay: 1.0,
assetPath: 'assets/breeds/marans.jpg',
),
BreedCatalogItem(
id: 'araucana',
name: 'name_araucana',
description: 'desc_araucana',
eggColor: 'color_blue',
eggsPerHenPerDay: 1.0,
assetPath: 'assets/breeds/araucana.jpg',
),
BreedCatalogItem(
id: 'olive',
name: 'name_olive',
description: 'desc_olive',
eggColor: 'color_olive',
eggsPerHenPerDay: 1.0,
assetPath: 'assets/breeds/olive.jpg',
),
BreedCatalogItem(
id: 'livorno',
name: 'name_livorno',
description: 'desc_livorno',
eggColor: 'color_white',
eggsPerHenPerDay: 1.0,
assetPath: 'assets/breeds/livorno.jpg',
),
BreedCatalogItem(
id: 'sussex',
name: 'name_sussex',
description: 'desc_sussex',
eggColor: 'color_cream',
eggsPerHenPerDay: 1.0,
assetPath: 'assets/breeds/sussex.jpg',
),
BreedCatalogItem(
id: 'australorp',
name: 'name_australorp',
description: 'desc_australorp',
eggColor: 'color_light_brown',
eggsPerHenPerDay: 1.0,
assetPath: 'assets/breeds/australorp.jpg',
),
BreedCatalogItem(
id: 'generic',
name: 'name_generic',
description: 'desc_generic',
eggColor: 'color_light_brown',
eggsPerHenPerDay: 1.0,
assetPath: 'assets/breeds/generic.jpg',
),
];
BreedCatalogItem breedFromId(String id) {
return breedCatalog.firstWhere(
(e) => e.id == id,
orElse: () => breedCatalog.first,
);
}
+35
View File
@@ -0,0 +1,35 @@
import 'breed_catalog.dart';
import 'hen.dart';
class BreedSetting {
final String breedId;
List<Hen> hens;
BreedSetting({
required this.breedId,
required this.hens,
});
Map<String, dynamic> toMap() {
return {
'breedId': breedId,
'hens': hens.map((e) => e.toMap()).toList(),
};
}
factory BreedSetting.fromMap(Map<String, dynamic> map) {
return BreedSetting(
breedId: map['breedId'],
hens: ((map['hens'] ?? []) as List)
.map((e) => Hen.fromMap(Map<String, dynamic>.from(e)))
.toList(),
);
}
int get activeHensCount {
return hens.where((hen) => hen.isLaying).length;
}
double get dailyProduction =>
activeHensCount * breedFromId(breedId).eggsPerHenPerDay;
}
+33
View File
@@ -0,0 +1,33 @@
class Customer {
final String id;
final String firstName;
final String lastName;
final String phoneNumber;
Customer({
required this.id,
required this.firstName,
required this.lastName,
required this.phoneNumber,
});
String get fullName => '$firstName $lastName'.trim();
Map<String, dynamic> toMap() {
return {
'id': id,
'firstName': firstName,
'lastName': lastName,
'phoneNumber': phoneNumber,
};
}
factory Customer.fromMap(Map<String, dynamic> map) {
return Customer(
id: map['id'],
firstName: map['firstName'],
lastName: map['lastName'],
phoneNumber: map['phoneNumber'],
);
}
}
+31
View File
@@ -0,0 +1,31 @@
class Hen {
final String id;
final String name;
final DateTime birthDate;
bool isLaying;
Hen({
required this.id,
required this.name,
required this.birthDate,
this.isLaying = true,
});
Map<String, dynamic> toMap() {
return {
'id': id,
'name': name,
'birthDate': birthDate.toIso8601String(),
'isLaying': isLaying,
};
}
factory Hen.fromMap(Map<String, dynamic> map) {
return Hen(
id: map['id'],
name: map['name'],
birthDate: DateTime.parse(map['birthDate']),
isLaying: map['isLaying'] ?? true,
);
}
}
+43
View File
@@ -0,0 +1,43 @@
class Reservation {
final String id;
final String customerName;
final String breedId;
final int eggsRequested;
final DateTime createdAt;
final DateTime deliveryDate;
bool isDelivered;
Reservation({
required this.id,
required this.customerName,
required this.breedId,
required this.eggsRequested,
required this.createdAt,
required this.deliveryDate,
this.isDelivered = false,
});
Map<String, dynamic> toMap() {
return {
'id': id,
'customerName': customerName,
'breedId': breedId,
'eggsRequested': eggsRequested,
'createdAt': createdAt.toIso8601String(),
'deliveryDate': deliveryDate.toIso8601String(),
'isDelivered': isDelivered,
};
}
factory Reservation.fromMap(Map<String, dynamic> map) {
return Reservation(
id: map['id'],
customerName: map['customerName'],
breedId: map['breedId'],
eggsRequested: map['eggsRequested'],
createdAt: DateTime.parse(map['createdAt']),
deliveryDate: DateTime.parse(map['deliveryDate']),
isDelivered: map['isDelivered'] ?? false,
);
}
}
+77
View File
@@ -0,0 +1,77 @@
import 'dart:convert';
import 'package:shared_preferences/shared_preferences.dart';
import '../models/breed_setting.dart';
import '../models/reservation.dart';
import '../models/customer.dart';
class StorageService {
static const String breedsKey = 'breed_settings_v2';
static const String reservationsKey = 'reservations_v2';
static const String customersKey = 'customers_v1';
static const String warehouseStockKey = 'warehouse_stock_v1';
static const String lastProductionUpdateKey = 'last_production_update_v1';
static Future<Map<String, double>> loadWarehouseStock() async {
final prefs = await SharedPreferences.getInstance();
final raw = prefs.getString(warehouseStockKey);
if (raw == null || raw.isEmpty) return {};
final map = jsonDecode(raw) as Map<String, dynamic>;
return map.map((k, v) => MapEntry(k, (v as num).toDouble()));
}
static Future<void> saveWarehouseStock(Map<String, double> stock) async {
final prefs = await SharedPreferences.getInstance();
await prefs.setString(warehouseStockKey, jsonEncode(stock));
}
static Future<DateTime?> loadLastProductionUpdate() async {
final prefs = await SharedPreferences.getInstance();
final raw = prefs.getString(lastProductionUpdateKey);
if (raw == null || raw.isEmpty) return null;
return DateTime.parse(raw);
}
static Future<void> saveLastProductionUpdate(DateTime date) async {
final prefs = await SharedPreferences.getInstance();
await prefs.setString(lastProductionUpdateKey, date.toIso8601String());
}
static Future<List<BreedSetting>> loadBreedSettings() async {
final prefs = await SharedPreferences.getInstance();
final raw = prefs.getString(breedsKey);
if (raw == null || raw.isEmpty) return [];
final list = jsonDecode(raw) as List;
return list.map((e) => BreedSetting.fromMap(Map<String, dynamic>.from(e))).toList();
}
static Future<void> saveBreedSettings(List<BreedSetting> items) async {
final prefs = await SharedPreferences.getInstance();
await prefs.setString(breedsKey, jsonEncode(items.map((e) => e.toMap()).toList()));
}
static Future<List<Reservation>> loadReservations() async {
final prefs = await SharedPreferences.getInstance();
final raw = prefs.getString(reservationsKey);
if (raw == null || raw.isEmpty) return [];
final list = jsonDecode(raw) as List;
return list.map((e) => Reservation.fromMap(Map<String, dynamic>.from(e))).toList();
}
static Future<void> saveReservations(List<Reservation> items) async {
final prefs = await SharedPreferences.getInstance();
await prefs.setString(reservationsKey, jsonEncode(items.map((e) => e.toMap()).toList()));
}
static Future<List<Customer>> loadCustomers() async {
final prefs = await SharedPreferences.getInstance();
final raw = prefs.getString(customersKey);
if (raw == null || raw.isEmpty) return [];
final list = jsonDecode(raw) as List;
return list.map((e) => Customer.fromMap(Map<String, dynamic>.from(e))).toList();
}
static Future<void> saveCustomers(List<Customer> items) async {
final prefs = await SharedPreferences.getInstance();
await prefs.setString(customersKey, jsonEncode(items.map((e) => e.toMap()).toList()));
}
}
+64
View File
@@ -0,0 +1,64 @@
import 'package:flutter/material.dart';
class CoopIcon extends StatelessWidget {
final double size;
final Color? color;
const CoopIcon({super.key, this.size = 24, this.color});
@override
Widget build(BuildContext context) {
final iconColor = color ?? Theme.of(context).colorScheme.primary;
return SizedBox(
width: size,
height: size,
child: CustomPaint(
painter: _CoopPainter(iconColor),
),
);
}
}
class _CoopPainter extends CustomPainter {
final Color color;
_CoopPainter(this.color);
@override
void paint(Canvas canvas, Size size) {
final paint = Paint()
..color = color
..style = PaintingStyle.stroke
..strokeWidth = size.width / 12
..strokeCap = StrokeCap.round
..strokeJoin = StrokeJoin.round;
final w = size.width;
final h = size.height;
final path = Path();
// Main structure
path.moveTo(w * 0.2, h * 0.85);
path.lineTo(w * 0.8, h * 0.85);
path.lineTo(w * 0.8, h * 0.4);
path.lineTo(w * 0.2, h * 0.4);
path.close();
// Roof
path.moveTo(w * 0.1, h * 0.4);
path.lineTo(w * 0.5, h * 0.1);
path.lineTo(w * 0.9, h * 0.4);
// Legs
path.moveTo(w * 0.3, h * 0.85);
path.lineTo(w * 0.3, h * 1.0);
path.moveTo(w * 0.7, h * 0.85);
path.lineTo(w * 0.7, h * 1.0);
// Window/Mesh
path.addRect(Rect.fromLTWH(w * 0.4, h * 0.55, w * 0.2, h * 0.2));
canvas.drawPath(path, paint);
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}