{
  "name": "VNTANA Showroom — Populate Google Sheet",
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "vntana-showroom-populate",
        "responseMode": "responseNode",
        "options": {}
      },
      "id": "webhook",
      "name": "Webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        240,
        300
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api-platform.vntana.com/v2/showrooms/get-by-uuid",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "vntanaApi",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({ uuid: $json.body.showroomUuid }) }}",
        "options": {}
      },
      "id": "get-showroom",
      "name": "GET Showroom",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        460,
        300
      ]
    },
    {
      "parameters": {
        "jsCode": "const body     = $('Webhook').first().json.body;\nconst showroom = $input.item.json.response;\nconst products = showroom.products || [];\nconst viewInfo = showroom.viewInfo || {};\nconst groups   = viewInfo.groups   || [];\nconst layout   = viewInfo.layoutAttributes || {};\n\n// Build productUuid → { groupTitle, order } lookup\n// productsInfo[].product.uuid holds the asset UUID\nconst productGroupMap = {};\ngroups.forEach(g => {\n  (g.productsInfo || []).forEach(p => {\n    const uuid = p.product ? p.product.uuid : p.productUuid;\n    if (uuid) productGroupMap[uuid] = { groupTitle: g.title != null ? String(g.title) : '', order: p.order != null ? p.order : null };\n  });\n});\n\nreturn [{\n  json: {\n    showroomUuid:    showroom.uuid,\n    showroomName:    showroom.name || 'VNTANA Showroom',\n    shareLinkUuid:   body.shareLinkUuid || '',\n    products,\n    groups,\n    productGroupMap,\n    layout\n  }\n}];"
      },
      "id": "extract",
      "name": "Extract Assets",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        680,
        300
      ]
    },
    {
      "parameters": {
        "resource": "spreadsheet",
        "title": "=VNTANA Showroom — {{ $json.showroomName }}",
        "sheetsUi": {
          "sheetValues": [
            {
              "title": "Instructions"
            },
            {
              "title": "Assets"
            },
            {
              "title": "Groups"
            },
            {
              "title": "Styling"
            }
          ]
        },
        "options": {}
      },
      "id": "create-sheet",
      "name": "Create Spreadsheet",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.4,
      "position": [
        900,
        300
      ],
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "",
          "name": "Google Sheets account 3"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "const rows = [\n  { 'Section': 'ASSETS TAB',       'Column / Field': 'Asset UUID',      'How to use it': 'Do not edit. Unique identifier used by the API.' },\n  { 'Section': '',                 'Column / Field': 'Asset Name',      'How to use it': 'Do not edit. Display name for reference.' },\n  { 'Section': '',                 'Column / Field': 'Style #',         'How to use it': 'Do not edit. SKU / style number from VNTANA.' },\n  { 'Section': '',                 'Column / Field': 'Group',           'How to use it': 'The group this asset belongs to. Must exactly match a Group Title in the Groups tab. Leave blank for ungrouped.' },\n  { 'Section': '',                 'Column / Field': 'Order',           'How to use it': 'Controls position within the group. Lower number = appears first. Edit the number to reorder — do not move rows.' },\n  { 'Section': '',                 'Column / Field': 'Quantity',        'How to use it': 'Enter a number > 0 to submit an order for this asset. Leave blank to skip ordering.' },\n  { 'Section': '',                 'Column / Field': 'Notes',           'How to use it': 'Optional. For your reference only — not sent to VNTANA.' },\n  { 'Section': 'GROUPS TAB',       'Column / Field': 'Group Title',     'How to use it': 'Name shown as the group header in the showroom. Must match Group values in the Assets tab exactly.' },\n  { 'Section': '',                 'Column / Field': 'Divider Top',     'How to use it': 'Yes or No — adds a horizontal divider above the group.' },\n  { 'Section': '',                 'Column / Field': 'Divider Bottom',  'How to use it': 'Yes or No — adds a horizontal divider below the group.' },\n  { 'Section': '',                 'Column / Field': 'Visible',         'How to use it': 'Yes or No — controls whether this group is visible in share links.' },\n  { 'Section': '',                 'Column / Field': 'Adding a group',  'How to use it': 'Add a new row here, then set the Group column in the Assets tab to match the new Group Title.' },\n  { 'Section': 'STYLING TAB',      'Column / Field': 'Colors',          'How to use it': 'Hex format e.g. #FFFFFF. Use Google Sheets color picker: Format > Text color, then copy the hex into the Value cell.' },\n  { 'Section': '',                 'Column / Field': 'Font Family',     'How to use it': 'Options: Roboto, Arial, Times New Roman, Georgia, Courier New' },\n  { 'Section': '',                 'Column / Field': 'Products Per Row','How to use it': 'Number from 1 to 5.' },\n  { 'Section': '',                 'Column / Field': 'Image Style',     'How to use it': 'Options: Cover, Contain, Tile' },\n  { 'Section': '',                 'Column / Field': 'Blank values',    'How to use it': 'Leave any styling field blank to keep its current value in VNTANA.' },\n  { 'Section': 'SUBMITTING',       'Column / Field': 'First time setup','How to use it': 'Extensions > Apps Script — paste the code from the web page — Save — reload this sheet. A VNTANA menu appears.' },\n  { 'Section': '',                 'Column / Field': 'Submit',          'How to use it': 'Click VNTANA > Submit to VNTANA. Orders, group changes, and styling updates all go in one pass.' }\n];\n\nreturn rows.map(r => ({ json: r }));"
      },
      "id": "prep-instructions-rows",
      "name": "Prep Instructions Rows",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1120,
        300
      ]
    },
    {
      "parameters": {
        "operation": "append",
        "documentId": {
          "value": "={{ $('Create Spreadsheet').first().json.spreadsheetId }}",
          "mode": "id"
        },
        "sheetName": {
          "value": "Instructions",
          "mode": "name"
        },
        "columns": {
          "mappingMode": "autoMapInputData",
          "value": {}
        },
        "options": {
          "valueInputMode": "USER_ENTERED"
        }
      },
      "id": "write-instructions",
      "name": "Write Instructions",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.4,
      "position": [
        1340,
        300
      ],
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "",
          "name": "Google Sheets account 3"
        }
      }
    },
    {
      "parameters": {
        "aggregate": "aggregateAllItemData",
        "options": {}
      },
      "id": "agg-instructions",
      "name": "Aggregate Instructions",
      "type": "n8n-nodes-base.aggregate",
      "typeVersion": 1,
      "position": [
        1560,
        300
      ]
    },
    {
      "parameters": {
        "jsCode": "const data = $('Extract Assets').first().json;\nconst map  = data.productGroupMap || {};\n\nconst rows = data.products.map(a => {\n  const g = map[a.uuid] || {};\n  return {\n    'Asset UUID': a.uuid || '',\n    'Asset Name': a.name || '',\n    'Style #':    a.styleNumber || a.sku || '',\n    'Group':      g.groupTitle != null ? String(g.groupTitle) : '',\n    'Order':      g.order      != null ? g.order : '',\n    'Quantity':   '',\n    'Notes':      ''\n  };\n});\n\nreturn rows.map(r => ({ json: r }));"
      },
      "id": "prep-asset-rows",
      "name": "Prep Asset Rows",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1120,
        120
      ]
    },
    {
      "parameters": {
        "operation": "append",
        "documentId": {
          "value": "={{ $('Create Spreadsheet').first().json.spreadsheetId }}",
          "mode": "id"
        },
        "sheetName": {
          "value": "Assets",
          "mode": "name"
        },
        "columns": {
          "mappingMode": "autoMapInputData",
          "value": {}
        },
        "options": {
          "valueInputMode": "USER_ENTERED"
        }
      },
      "id": "write-assets",
      "name": "Write Assets",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.4,
      "position": [
        1340,
        120
      ],
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "",
          "name": "Google Sheets account 3"
        }
      }
    },
    {
      "parameters": {
        "aggregate": "aggregateAllItemData",
        "options": {}
      },
      "id": "agg-assets",
      "name": "Aggregate Assets",
      "type": "n8n-nodes-base.aggregate",
      "typeVersion": 1,
      "position": [
        1560,
        120
      ]
    },
    {
      "parameters": {
        "jsCode": "const data = $('Extract Assets').first().json;\n\nconst rows = (data.groups || []).map(g => ({\n  'Group Title':    g.title || '',\n  'Divider Top':    (g.dividers || []).includes('TOP')    ? 'Yes' : 'No',\n  'Divider Bottom': (g.dividers || []).includes('BOTTOM') ? 'Yes' : 'No',\n  'Visible':        g.visible !== false ? 'Yes' : 'No'\n}));\n\nif (rows.length === 0) {\n  rows.push({ 'Group Title': '', 'Divider Top': 'No', 'Divider Bottom': 'No', 'Visible': 'Yes' });\n}\n\nreturn rows.map(r => ({ json: r }));"
      },
      "id": "prep-group-rows",
      "name": "Prep Group Rows",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1780,
        120
      ]
    },
    {
      "parameters": {
        "operation": "append",
        "documentId": {
          "value": "={{ $('Create Spreadsheet').first().json.spreadsheetId }}",
          "mode": "id"
        },
        "sheetName": {
          "value": "Groups",
          "mode": "name"
        },
        "columns": {
          "mappingMode": "autoMapInputData",
          "value": {}
        },
        "options": {
          "valueInputMode": "USER_ENTERED"
        }
      },
      "id": "write-groups",
      "name": "Write Groups",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.4,
      "position": [
        2000,
        120
      ],
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "",
          "name": "Google Sheets account 3"
        }
      }
    },
    {
      "parameters": {
        "aggregate": "aggregateAllItemData",
        "options": {}
      },
      "id": "agg-groups",
      "name": "Aggregate Groups",
      "type": "n8n-nodes-base.aggregate",
      "typeVersion": 1,
      "position": [
        2220,
        120
      ]
    },
    {
      "parameters": {
        "jsCode": "const data   = $('Extract Assets').first().json;\nconst layout = data.layout || {};\n\nconst rows = [\n  { 'Field': '— IDENTIFIERS —',  'Value': '',                             'Options / Notes': '' },\n  { 'Field': 'Showroom UUID',    'Value': data.showroomUuid,              'Options / Notes': '' },\n  { 'Field': 'Showroom Name',    'Value': data.showroomName,              'Options / Notes': 'Reference only' },\n  { 'Field': 'Share Link UUID',  'Value': data.shareLinkUuid,             'Options / Notes': 'Used for order entry' },\n  { 'Field': '— TYPOGRAPHY —',   'Value': '',                             'Options / Notes': '' },\n  { 'Field': 'Font Family',      'Value': 'APPLY FONT HERE',                                     'Options / Notes': 'Format the Value cell with your chosen font — it will be read on submit' },\n  { 'Field': '— COLORS —',       'Value': '',                             'Options / Notes': '',                                      'Color Swatch': '' },\n  { 'Field': 'Background Color', 'Value': layout.BACKGROUND_COLOR   || '#FFFFFF',  'Options / Notes': 'Hex format e.g. #FFFFFF',               'Color Swatch': 'Fill this cell with your color, then VNTANA > Read Color Swatches' },\n  { 'Field': 'Text Color',       'Value': layout.TEXT_COLOR         || '#111111',  'Options / Notes': 'Hex format',                            'Color Swatch': 'Fill this cell with your color, then VNTANA > Read Color Swatches' },\n  { 'Field': 'Divider Color',    'Value': layout.DIVIDER_COLOR      || '#E2E2E0',  'Options / Notes': 'Hex format',                            'Color Swatch': 'Fill this cell with your color, then VNTANA > Read Color Swatches' },\n  { 'Field': '— LAYOUT —',       'Value': '',                             'Options / Notes': '' },\n  { 'Field': 'Products Per Row', 'Value': layout.PRODUCTS_PER_ROW   || 4,          'Options / Notes': '1 to 5' },\n  { 'Field': 'Image Style',      'Value': (layout.IMAGE_STYLE || 'Cover').charAt(0).toUpperCase() + (layout.IMAGE_STYLE || 'Cover').slice(1).toLowerCase(), 'Options / Notes': 'Cover / Contain / Tile' }\n];\n\nreturn rows.map(r => ({ json: r }));"
      },
      "id": "prep-styling-rows",
      "name": "Prep Styling Rows",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2440,
        120
      ]
    },
    {
      "parameters": {
        "operation": "append",
        "documentId": {
          "value": "={{ $('Create Spreadsheet').first().json.spreadsheetId }}",
          "mode": "id"
        },
        "sheetName": {
          "value": "Styling",
          "mode": "name"
        },
        "columns": {
          "mappingMode": "autoMapInputData",
          "value": {}
        },
        "options": {
          "valueInputMode": "USER_ENTERED"
        }
      },
      "id": "write-styling",
      "name": "Write Styling",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.4,
      "position": [
        2660,
        120
      ],
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "",
          "name": "Google Sheets account 3"
        }
      }
    },
    {
      "parameters": {
        "aggregate": "aggregateAllItemData",
        "options": {}
      },
      "id": "agg-styling",
      "name": "Aggregate Styling",
      "type": "n8n-nodes-base.aggregate",
      "typeVersion": 1,
      "position": [
        2880,
        120
      ]
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ JSON.stringify({ sheetUrl: 'https://docs.google.com/spreadsheets/d/' + $('Create Spreadsheet').first().json.spreadsheetId, assetCount: $('Extract Assets').first().json.products.length, groupCount: ($('Extract Assets').first().json.groups || []).length }) }}",
        "options": {
          "responseCode": 200
        }
      },
      "id": "respond",
      "name": "Respond",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1,
      "position": [
        3100,
        120
      ]
    }
  ],
  "connections": {
    "Webhook": {
      "main": [
        [
          {
            "node": "GET Showroom",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "GET Showroom": {
      "main": [
        [
          {
            "node": "Extract Assets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Assets": {
      "main": [
        [
          {
            "node": "Create Spreadsheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Spreadsheet": {
      "main": [
        [
          {
            "node": "Prep Instructions Rows",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prep Instructions Rows": {
      "main": [
        [
          {
            "node": "Write Instructions",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Write Instructions": {
      "main": [
        [
          {
            "node": "Aggregate Instructions",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate Instructions": {
      "main": [
        [
          {
            "node": "Prep Asset Rows",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prep Asset Rows": {
      "main": [
        [
          {
            "node": "Write Assets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Write Assets": {
      "main": [
        [
          {
            "node": "Aggregate Assets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate Assets": {
      "main": [
        [
          {
            "node": "Prep Group Rows",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prep Group Rows": {
      "main": [
        [
          {
            "node": "Write Groups",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Write Groups": {
      "main": [
        [
          {
            "node": "Aggregate Groups",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate Groups": {
      "main": [
        [
          {
            "node": "Prep Styling Rows",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prep Styling Rows": {
      "main": [
        [
          {
            "node": "Write Styling",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Write Styling": {
      "main": [
        [
          {
            "node": "Aggregate Styling",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate Styling": {
      "main": [
        [
          {
            "node": "Respond",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  },
  "staticData": null
}