Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Google Apps Script Generator</title> | |
| <link href="https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css" rel="stylesheet"> | |
| <style> | |
| .code-block { | |
| font-family: 'Courier New', Courier, monospace; | |
| white-space: pre-wrap; | |
| background: #000000; | |
| color: #e2e8f0; | |
| padding: 1rem; | |
| border-radius: 0.5rem; | |
| height: calc(100vh - 14rem); | |
| overflow-y: auto; | |
| box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); | |
| border: 1px solid rgba(255, 255, 255, 0.2); | |
| } | |
| .section { display: none; } | |
| .section.active { display: block; } | |
| .input-field { | |
| transition: border-color 0.2s ease, box-shadow 0.2s ease; | |
| background: rgba(255, 255, 255, 0.2); | |
| color: #1e293b; | |
| border: 1px solid rgba(255, 255, 255, 0.3); | |
| width: 100%; | |
| } | |
| .input-field:focus { | |
| border-color: #3b82f6; | |
| box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.3); | |
| } | |
| .btn { | |
| transition: background-color 0.2s ease, transform 0.1s ease; | |
| backdrop-filter: blur(8px); | |
| border: 1px solid rgba(255, 255, 255, 0.2); | |
| } | |
| .btn.bg-blue-600 { background: #2563eb; } | |
| .btn.bg-green-600 { background: #16a34a; } | |
| .btn.bg-gray-700 { background: #374151; } | |
| .btn.bg-gray-600 { background: #4b5563; } | |
| .btn.bg-red-600 { background: #dc2626; } | |
| .btn.bg-gray-200 { background: #e5e7eb; color: #1f2937; } | |
| .btn.bg-blue-600:hover { background: #1d4ed8; transform: translateY(-1px); } | |
| .btn.bg-green-600:hover { background: #15803d; transform: translateY(-1px); } | |
| .btn.bg-gray-700:hover { background: #1f2937; transform: translateY(-1px); } | |
| .btn.bg-gray-600:hover { background: #374151; transform: translateY(-1px); } | |
| .btn.bg-red-600:hover { background: #b91c1c; transform: translateY(-1px); } | |
| .btn.bg-gray-200:hover { background: #d1d5db; transform: translateY(-1px); } | |
| .btn:active { transform: translateY(0); } | |
| .step-indicator { | |
| background: rgba(255, 255, 255, 0.1); | |
| backdrop-filter: blur(5px); | |
| border: 1px solid rgba(255, 255, 255, 0.2); | |
| } | |
| .step-indicator.active { | |
| background: rgba(59, 130, 246, 0.8); | |
| color: white; | |
| } | |
| .glass-container { | |
| background: rgba(255, 255, 255, 0.1); | |
| backdrop-filter: blur(12px); | |
| border: 1px solid rgba(255, 255, 255, 0.2); | |
| box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); | |
| } | |
| .header { | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| padding: 1rem; | |
| background: rgba(255, 255, 255, 0.2); | |
| border-bottom: 1px solid rgba(255, 255, 255, 0.3); | |
| } | |
| /* Responsive Styles */ | |
| @media (max-width: 640px) { | |
| body { | |
| padding: 0.5rem; | |
| margin: 0; | |
| } | |
| .header { | |
| flex-direction: column; | |
| text-align: center; | |
| padding: 0.5rem; | |
| } | |
| .header h1 { | |
| font-size: 1.5rem; | |
| } | |
| .header span { | |
| font-size: 1rem; | |
| margin-top: 0.5rem; | |
| } | |
| .glass-container { | |
| padding: 0.5rem; | |
| margin: 0; | |
| } | |
| .code-block { | |
| height: calc(100vh - 20rem); | |
| padding: 0.5rem; | |
| } | |
| .flex { | |
| flex-direction: column; | |
| } | |
| .space-x-3 > * + * { | |
| margin-left: 0; | |
| margin-top: 0.5rem; | |
| } | |
| .space-x-4 > * + * { | |
| margin-left: 0; | |
| margin-top: 0.75rem; | |
| } | |
| .btn { | |
| width: 100%; | |
| margin-bottom: 0.5rem; | |
| padding: 0.75rem; | |
| } | |
| .step-indicator { | |
| width: 2rem; | |
| height: 2rem; | |
| font-size: 0.875rem; | |
| } | |
| .text-2xl { | |
| font-size: 1.25rem; | |
| } | |
| .text-xl { | |
| font-size: 1.125rem; | |
| } | |
| .mb-6 { | |
| margin-bottom: 1rem; | |
| } | |
| .space-y-4 > * + * { | |
| margin-top: 1rem; | |
| } | |
| .column-input { | |
| padding: 0.5rem; | |
| } | |
| .flex-wrap { | |
| flex-wrap: wrap; | |
| } | |
| .gap-2 { | |
| gap: 0.5rem; | |
| } | |
| } | |
| @media (min-width: 641px) { | |
| body { | |
| padding: 2rem; | |
| } | |
| .glass-container { | |
| padding: 1.5rem; | |
| } | |
| .header h1 { | |
| font-size: 2rem; | |
| } | |
| .header span { | |
| font-size: 1.25rem; | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-gradient-to-br from-gray-200 via-gray-300 to-gray-400 min-h-screen font-sans"> | |
| <!-- Header --> | |
| <div class="header"> | |
| <h1 class="text-2xl font-bold text-gray-900">FREE GSHEET2DB</h1> | |
| <span id="crud-title" class="text-xl font-semibold text-gray-800 hidden">GENERATE CODE FOR GSHEET TO DB CRUD</span> | |
| </div> | |
| <!-- Progress Steps --> | |
| <div class="flex justify-center space-x-4 mb-6"> | |
| <div class="step-indicator flex items-center justify-center w-10 h-10 rounded-full text-gray-700 font-semibold">1</div> | |
| <div class="step-indicator flex items-center justify-center w-10 h-10 rounded-full text-gray-700 font-semibold">2</div> | |
| <div class="step-indicator flex items-center justify-center w-10 h-10 rounded-full text-gray-700 font-semibold">3</div> | |
| </div> | |
| <!-- Main Content Sections --> | |
| <div class="max-w-4xl mx-auto glass-container rounded-xl"> | |
| <!-- Set Columns Section --> | |
| <div id="columns" class="section active"> | |
| <h1 class="text-2xl font-extrabold text-gray-900 mb-6 text-center">Set Columns</h1> | |
| <div id="columnInputs" class="space-y-4"> | |
| <div class="flex space-x-3"> | |
| <input type="text" class="column-input input-field flex-1 px-3 py-2 rounded-lg" placeholder="Column name (e.g., Status)" value="word"> | |
| <button onclick="removeColumn(this)" class="delete-btn btn bg-red-600 text-white p-2 rounded-lg"> | |
| <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"> | |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" /> | |
| </svg> | |
| </button> | |
| </div> | |
| <div class="flex space-x-3"> | |
| <input type="text" class="column-input input-field flex-1 px-3 py-2 rounded-lg" placeholder="Column name (e.g., Category)" value="meaning"> | |
| <button onclick="removeColumn(this)" class="delete-btn btn bg-red-600 text-white p-2 rounded-lg"> | |
| <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"> | |
| <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" /> | |
| </svg> | |
| </button> | |
| </div> | |
| </div> | |
| <div class="flex flex-col sm:flex-row justify-between mt-6 space-y-3 sm:space-x-4"> | |
| <button onclick="addColumn()" class="btn bg-blue-600 text-white px-4 py-3 rounded-lg text-base font-medium">Add Column</button> | |
| <button onclick="nextSection('code')" class="btn bg-green-600 text-white px-6 py-3 rounded-lg text-base font-medium">Next</button> | |
| </div> | |
| </div> | |
| <!-- Generated Code Section --> | |
| <div id="code" class="section"> | |
| <h1 class="text-2xl font-extrabold text-gray-900 mb-6 text-center">Generated Code</h1> | |
| <div class="flex flex-col sm:flex-row justify-between items-center mb-4 space-y-3"> | |
| <h2 class="text-xl font-semibold text-gray-800">Code Preview</h2> | |
| <button onclick="copyCode()" class="btn bg-gray-700 p-2 rounded-lg" title="Copy to clipboard"> | |
| <svg class="w-6 h-6 text-gray-300" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 5H6a2 2 0 00-2 2v12a2 2 0 002 2h12a2 2 0 002-2V7a2 2 0 00-2-2h-2M8 5a2 2 0 002 2h4a2 2 0 002-2M8 5a2 2 0 012-2h4a2 2 0 012 2"></path></svg> | |
| </button> | |
| </div> | |
| <div id="codePreview" class="code-block"></div> | |
| <div class="flex flex-col sm:flex-row justify-between mt-6 space-y-3 sm:space-x-4"> | |
| <button onclick="nextSection('columns')" class="btn bg-gray-600 text-white px-6 py-3 rounded-lg text-base font-medium">Back</button> | |
| <button onclick="nextSection('howto')" class="btn bg-green-600 text-white px-6 py-3 rounded-lg text-base font-medium">Next</button> | |
| </div> | |
| </div> | |
| <!-- How to Use Section --> | |
| <div id="howto" class="section"> | |
| <h1 class="text-2xl font-extrabold text-gray-900 mb-6 text-center">How to Use</h1> | |
| <div class="flex flex-wrap gap-2 mb-6 overflow-x-auto pb-2"> | |
| <button class="curl-button btn px-4 py-2 bg-gray-200 rounded-lg text-sm font-medium" onclick="showCurlExample('appendSingle')">Append Single</button> | |
| <button class="curl-button btn px-4 py-2 bg-gray-200 rounded-lg text-sm font-medium" onclick="showCurlExample('appendMultiple')">Append Multiple</button> | |
| <button class="curl-button btn px-4 py-2 bg-gray-200 rounded-lg text-sm font-medium" onclick="showCurlExample('fetchAll')">Fetch All</button> | |
| <button class="curl-button btn px-4 py-2 bg-gray-200 rounded-lg text-sm font-medium" onclick="showCurlExample('fetchRange')">Fetch Range</button> | |
| <button class="curl-button btn px-4 py-2 bg-gray-200 rounded-lg text-sm font-medium" onclick="showCurlExample('search')">Search</button> | |
| <button class="curl-button btn px-4 py-2 bg-gray-200 rounded-lg text-sm font-medium" onclick="showCurlExample('update')">Update</button> | |
| <button class="curl-button btn px-4 py-2 bg-gray-200 rounded-lg text-sm font-medium" onclick="showCurlExample('delete')">Delete</button> | |
| </div> | |
| <div id="curlExamples" class="code-block"></div> | |
| <div class="flex justify-start mt-6"> | |
| <button onclick="nextSection('code')" class="btn bg-gray-600 text-white px-6 py-3 rounded-lg text-base font-medium">Back</button> | |
| </div> | |
| </div> | |
| </div> | |
| <script> | |
| function nextSection(sectionId) { | |
| document.querySelectorAll('.section').forEach(section => section.classList.remove('active')); | |
| document.getElementById(sectionId).classList.add('active'); | |
| const steps = ['columns', 'code', 'howto']; | |
| const currentStep = steps.indexOf(sectionId); | |
| document.querySelectorAll('.step-indicator').forEach((indicator, index) => { | |
| indicator.classList.toggle('active', index === currentStep); | |
| }); | |
| // Show/hide CRUD title based on active section | |
| const crudTitle = document.getElementById('crud-title'); | |
| if (sectionId === 'columns') { | |
| crudTitle.classList.remove('hidden'); | |
| } else { | |
| crudTitle.classList.add('hidden'); | |
| } | |
| } | |
| document.querySelector('.step-indicator').classList.add('active'); | |
| // Initially show CRUD title since 'columns' is active by default | |
| document.getElementById('crud-title').classList.remove('hidden'); | |
| </script> | |
| <script src="script.js"></script> | |
| </body> | |
| </html> |