// --- CONFIGURATION --- const FOLDER_ID = "1rLQ6UZ4GVYau6qW0yTAHbtiGyP81Qfgk"; const SPREADSHEET_ID = "1KioH_lA-6DXWgK6D2UhYvAi3WpgwfkLUlt2IeaVT3Bk"; function doGet(e) { const callback = (e && e.parameter && e.parameter.callback) || 'callback'; const action = e && e.parameter && e.parameter.action; let result = (action === 'getSubmissions') ? getSubmissionsData() : getCurriculumData(); return ContentService.createTextOutput(callback + "(" + JSON.stringify(result) + ");") .setMimeType(ContentService.MimeType.JAVASCRIPT); } function doPost(e) { try { const rawData = (e && e.postData && e.postData.contents) ? e.postData.contents : "{}"; const payload = JSON.parse(rawData); // Action 1: Upload a single file and return its Google Drive URL if (payload.action === "uploadFile") { const folder = DriveApp.getFolderById(FOLDER_ID.trim()); const splitData = payload.fileBase64.split(","); const contentType = splitData[0].match(/:(.*?);/)[1]; const bytes = Utilities.base64Decode(splitData[1]); const blob = Utilities.newBlob(bytes, contentType, payload.fileName); const file = folder.createFile(blob); file.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.VIEW); return ContentService.createTextOutput(JSON.stringify({ success: true, fileUrl: file.getUrl() })).setMimeType(ContentService.MimeType.JSON); } // Action 2: Standard form submission (text + pre-uploaded file URLs) const result = submitPlaybook(payload); return ContentService.createTextOutput(JSON.stringify(result)) .setMimeType(ContentService.MimeType.JSON); } catch (err) { return ContentService.createTextOutput(JSON.stringify({ success: false, message: "Server error: " + err.toString() })).setMimeType(ContentService.MimeType.JSON); } } function getCurriculumData() { try { const ss = SpreadsheetApp.openById(SPREADSHEET_ID.trim()); const sheet = ss.getSheetByName('Curriculum'); if (!sheet) return { success: false, error: 'Curriculum tab not found.' }; const lastRow = sheet.getLastRow(); if (lastRow <= 1) return { success: false, error: 'No data rows in Curriculum.' }; const values = sheet.getRange(2, 1, lastRow - 1, 6).getValues(); const data = {}; values.forEach(function(row) { const topic = row[0] ? String(row[0]).trim() : ''; const title = row[1] ? String(row[1]).trim() : ''; if (!topic || !title) return; if (!data[topic]) data[topic] = []; data[topic].push({ title: title, desc: row[2] ? String(row[2]).trim() : '', visualUrl: row[3] ? String(row[3]).trim() : '', callHint: row[4] ? String(row[4]).trim() : 'Your 1-word call', sigHint: row[5] ? String(row[5]).trim() : 'Your hand/body signal' }); }); return { success: true, data: data }; } catch (err) { return { success: false, error: err.toString() }; } } function createSubmissionPdf(playerName, topic, answers) { const folder = DriveApp.getFolderById(FOLDER_ID.trim()); let cardsHtml = ''; const safeAnswers = Array.isArray(answers) ? answers : []; safeAnswers.forEach(function(ans, i) { const fileRow = (ans.fileUrl && ans.fileUrl !== 'No file attached') ? '