schermate di configurazione complete: razze disponibili, mio pollaio, registro galline, clienti, backup/ripristino nel formato dell'app Android, lingua a runtime, introduzione e informazioni

- datastore: export/import JSON con le chiavi camelCase dell'app Android (breedSettings/reservations/customers), scorte e ultimo aggiornamento preservati al ripristino
- settings: flag 'introduzione vista'
- desktop: permesso Documents (dove finisce il backup)
- nuovi controlli: tools/check_qml.py (chiavi di traduzione, simboli JS, pagine, componenti) e qmllint nella suite
- versione 0.2.0
This commit is contained in:
2026-10-09 09:21:47 +02:00
parent a73d94a74e
commit 248e0db899
25 changed files with 2060 additions and 74 deletions
+119
View File
@@ -0,0 +1,119 @@
import QtQuick 2.2
import Sailfish.Silica 1.0
import "../js/henflow.js" as HF
import "../js/i18n.js" as I18N
// Nuovo cliente / modifica: nome di battesimo (obbligatorio), cognome e
// telefono. Stessa regola dell'app Flutter: senza nome non si salva.
Page {
id: page
allowedOrientations: Orientation.All
property var customer: null // null = nuovo cliente
property var onSaved: null
property string lang: "en"
property string errorMsg: ""
function tr(key, arg) { return I18N.t(key, arg, page.lang) }
function reload() {
page.lang = I18N.langFor(appSettings.language, Qt.locale().name)
if (page.customer) {
firstNameField.text = page.customer.firstName || ""
lastNameField.text = page.customer.lastName || ""
phoneField.text = page.customer.phoneNumber || ""
}
}
function save() {
var first = firstNameField.text.trim()
if (first.length === 0) {
page.errorMsg = page.tr("first_name")
return
}
var list = appData.customers().slice()
var record = {
"id": page.customer ? page.customer.id : HF.newId(),
"firstName": first,
"lastName": lastNameField.text.trim(),
"phoneNumber": phoneField.text.trim()
}
if (page.customer) {
for (var i = 0; i < list.length; i++) {
if (list[i].id === record.id)
list[i] = record
}
} else {
list.push(record)
}
appData.saveCustomers(list)
if (page.onSaved)
page.onSaved()
pageStack.pop()
}
Component.onCompleted: page.reload()
SilicaFlickable {
anchors.fill: parent
contentHeight: form.height
Column {
id: form
width: parent.width
spacing: Theme.paddingMedium
PageHeader {
title: page.customer ? page.tr("edit_customer") : page.tr("new_customer")
}
TextField {
id: firstNameField
width: parent.width
label: page.tr("first_name")
EnterKey.enabled: true
EnterKey.onClicked: page.save()
}
TextField {
id: lastNameField
width: parent.width
label: page.tr("last_name")
EnterKey.enabled: true
EnterKey.onClicked: page.save()
}
TextField {
id: phoneField
width: parent.width
label: page.tr("phone_number")
inputMethodHints: Qt.ImhDialableCharactersOnly
EnterKey.enabled: true
EnterKey.onClicked: page.save()
}
Label {
x: Theme.horizontalPageMargin
width: parent.width - 2 * Theme.horizontalPageMargin
text: page.errorMsg
color: Theme.errorColor
font.pixelSize: Theme.fontSizeSmall
wrapMode: Text.Wrap
visible: text.length > 0
}
Button {
anchors.horizontalCenter: parent.horizontalCenter
text: page.tr("save")
onClicked: page.save()
}
Item { width: parent.width; height: Theme.paddingLarge }
}
VerticalScrollDecorator {}
}
}