{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://groceryai.ai/schemas/testi.schema.json",
  "title": "I testi e il sito del negozio (testi.json)",
  "description": "Il documento di PUT /v1/store_texts e delle pagine «Testi e tono» e «Sito» del portale (corsia DATA-C4, contratto del portale §3.20). Tutti i campi sono facoltativi: si manda solo cio' che cambia.",
  "type": "object",
  "additionalProperties": false,
  "properties": {
    "$schema": { "type": "string" },
    "phrases": {
      "type": "array", "maxItems": 100,
      "description": "Le frasi-modello del pacchetto lingua, riscritte una per una. La frase tiene i segnaposto di quella di partenza ({name}, {title}, …: SEGNAPOSTO_DIVERSI), non porta link (LINK_NELLA_FRASE); text null torna alla frase di partenza.",
      "items": {
        "type": "object", "additionalProperties": false, "required": ["lang", "key", "text"],
        "properties": {
          "lang": { "type": "string" },
          "key": { "enum": ["greeting_named", "greeting_anonymous", "greeting_named_text_only", "greeting_anonymous_text_only", "welcome_new", "welcome_back", "cta_look", "usual_added", "usuals_added", "list_usuals_ask"] },
          "text": { "type": ["string", "null"], "maxLength": 400 }
        }
      }
    },
    "assistant_hours": {
      "description": "Gli orari dell'assistente: la forma degli orari degli operatori (giorni da 0, domenica, a 6).",
      "oneOf": [
        { "type": "null" },
        { "type": "object", "additionalProperties": false, "required": ["always"], "properties": { "always": { "const": true }, "tz": { "type": "string" } } },
        {
          "type": "object", "additionalProperties": false, "required": ["windows"],
          "properties": {
            "tz": { "type": "string" },
            "windows": {
              "type": "array", "minItems": 1, "maxItems": 14,
              "items": {
                "type": "object", "additionalProperties": false, "required": ["days", "from", "to"],
                "properties": {
                  "days": { "type": "array", "minItems": 1, "items": { "type": "integer", "minimum": 0, "maximum": 6 } },
                  "from": { "type": "string", "pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$" },
                  "to": { "type": "string", "pattern": "^([01][0-9]|2[0-4]):[0-5][0-9]$" }
                }
              }
            }
          }
        }
      ]
    },
    "departments": {
      "type": "array", "maxItems": 40, "description": "Le intestazioni di reparto del carrello: la categoria come nel catalogo, con un'emoji.",
      "items": {
        "type": "object", "additionalProperties": false, "required": ["category"],
        "properties": { "category": { "type": "string", "minLength": 1, "maxLength": 80 }, "emoji": { "type": ["string", "null"], "maxLength": 16 } }
      }
    },
    "weekly_shop_base_list": { "type": "array", "maxItems": 30, "items": { "type": "string", "minLength": 2, "maxLength": 40 }, "description": "La spesa di base per il cliente senza storico: termini di ricerca nella lingua del catalogo." },
    "site": {
      "type": "object", "additionalProperties": false,
      "description": "I percorsi del sito del negozio (il dominio si scrive in «Il tuo negozio»): minuscole, cifre, trattini e barre, al piu' 120 caratteri; null toglie.",
      "properties": {
        "category_paths": { "type": "array", "maxItems": 500, "items": { "type": "string", "pattern": "^/?[a-z0-9][a-z0-9-]*(/[a-z0-9][a-z0-9-]*)*$" } },
        "faq_path": { "type": ["string", "null"] },
        "offers_path": { "type": ["string", "null"] },
        "delivery_rates_path": { "type": ["string", "null"] }
      }
    }
  }
}
