diff --git a/views/global.css b/views/global.css new file mode 100644 index 0000000..f1e7502 --- /dev/null +++ b/views/global.css @@ -0,0 +1,979 @@ +:root { + /* Scandinavian Industrial Palette */ + --color-bg: #f5f7fa; + /* Very light cool gray - Scandi base */ + --color-surface: #ffffff; + /* White - Scandi cleanliness */ + --color-primary: #34495e; + /* Dark slate blue/gray - Industrial strength */ + --color-primary-rgb: 52, 73, 94; + --color-secondary: #7f8c8d; + /* Grayish cyan/slate - Industrial accent */ + --color-accent: #c09574; + /* Muted tan/light wood - Scandi warmth */ + --color-accent-rgb: 192, 149, 116; + --color-text: #2c3e50; + /* Dark, similar to primary for harmony */ + --color-text-light: #566573; + /* Lighter gray for secondary text */ + --color-border: #e1e5ea; + /* Light, cool gray for subtle borders */ + + --color-success: #27ae60; + /* Clear Green */ + --color-success-bg: rgba(39, 174, 96, 0.1); + --color-pending: #f39c12; + /* Clear Amber/Orange */ + --color-pending-bg: rgba(243, 156, 18, 0.1); + --color-archived: #95a5a6; + /* Muted Silver/Gray */ + --color-archived-bg: rgba(149, 165, 166, 0.15); + --color-danger: #c0392b; + /* Clear, strong Red */ + --color-danger-bg: rgba(192, 57, 43, 0.1); + + --shadow-sm: 0 2px 4px rgba(0, 0, 0, 0.05); + /* Softer, more diffuse */ + --shadow-md: 0 5px 15px rgba(0, 0, 0, 0.08); + /* Softer, more diffuse */ + --border-radius: 4px; + /* Slightly sharper edges */ +} + +* { + margin: 0; + padding: 0; + box-sizing: border-box; + font-family: "Inter", "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; + /* Modern sans-serif */ +} + +body { + background-color: var(--color-bg); + color: var(--color-text); + min-height: 100vh; + padding: 20px; + /* Removed background pattern for cleaner look */ +} + +main { + display: block; +} + +.container { + max-width: 1200px; + width: 100%; + margin: 0 auto; +} + +.skip-link { + position: absolute; + left: -9999px; + top: auto; + width: 1px; + height: 1px; + overflow: hidden; + z-index: -9999; +} + +.skip-link:focus, +.skip-link:active { + display: block; + position: static; + width: auto; + height: auto; + overflow: visible; + padding: 10px 15px; + margin: 10px auto; + background-color: var(--color-primary); + color: var(--color-surface); + border-radius: var(--border-radius); + text-decoration: none; + font-size: 1rem; + z-index: 100000; + text-align: center; +} + +.visually-hidden { + position: absolute; + width: 1px; + height: 1px; + margin: -1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; +} + + +/* Titles */ +.page-title { + font-size: 2.1rem; + /* Slightly larger */ + font-weight: 700; + color: var(--color-primary); + line-height: 1.2; + margin-bottom: 32px; + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.07); + /* Very subtle shadow */ +} + +.section-title { + font-size: 1.4rem; + /* Slightly larger */ + font-weight: 600; + color: var(--color-primary); + display: flex; + align-items: center; + gap: 12px; + margin-bottom: 24px; +} + +.section-title svg { + color: var(--color-accent); + flex-shrink: 0; +} + + +/* Buttons */ +.button { + background-color: var(--color-primary); + color: var(--color-surface); + /* Changed to var for consistency, typically white */ + border: 1px solid var(--color-primary); + /* Ensure border for consistency */ + padding: 10px 18px; + border-radius: var(--border-radius); + font-weight: 500; + font-size: 0.9rem; + cursor: pointer; + display: inline-flex; + align-items: center; + gap: 8px; + transition: all 0.2s ease; + text-decoration: none; + line-height: 1.5; + user-select: none; + box-shadow: var(--shadow-sm); +} + +.button svg { + flex-shrink: 0; +} + +.button:hover { + background-color: #2c3e50; + /* Darker primary */ + border-color: #2c3e50; + box-shadow: var(--shadow-md); + transform: translateY(-2px); +} + +.button:active { + background-color: #212f3c; + /* Even darker primary */ + border-color: #212f3c; + box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.2); + transform: translateY(0); +} + +.button:focus-visible { + outline: 2px solid var(--color-accent); + outline-offset: 3px; +} + +.button-secondary { + background-color: var(--color-surface); + color: var(--color-primary); + border: 1px solid var(--color-border); + box-shadow: none; +} + +.button-secondary:hover { + background-color: var(--color-bg); + border-color: #c8ced3; + /* Darker border */ + box-shadow: var(--shadow-sm); + transform: translateY(-1px); +} + +.button-secondary:active { + background-color: #e0e5ea; + /* Darker bg */ + box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1); + transform: translateY(0); +} + +.button-secondary:focus-visible { + outline: 2px solid var(--color-accent); + outline-offset: 3px; +} + + +.button.button-sm { + padding: 6px 12px; + font-size: 0.8rem; + box-shadow: none; +} + +.button.button-sm:hover { + box-shadow: var(--shadow-sm); + transform: translateY(-1px); +} + +.button.button-sm:active { + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); + transform: translateY(0); +} + + +.button.button-danger { + background-color: var(--color-danger); + border-color: var(--color-danger); + color: white; +} + +.button.button-danger:hover { + background-color: #a93226; + /* Darker danger */ + border-color: #a93226; + box-shadow: var(--shadow-md); + transform: translateY(-2px); +} + +.button.button-danger:active { + background-color: #922b21; + /* Even darker danger */ + border-color: #922b21; + box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.2); + transform: translateY(0); +} + +.button.button-danger:focus-visible { + outline: 2px solid var(--color-danger); + outline-offset: 3px; +} + + +/* Generic Card */ +.simple-card { + background-color: var(--color-surface); + border-radius: var(--border-radius); + padding: 20px; + box-shadow: var(--shadow-sm); + border: 1px solid var(--color-border); + margin-bottom: 24px; + transition: box-shadow 0.2s ease, transform 0.2s ease; +} + +.simple-card:hover { + box-shadow: var(--shadow-md); + transform: translateY(-2px); + /* Standardized lift */ +} + +.simple-card .card-title { + font-size: 1.1rem; + font-weight: 600; + color: var(--color-primary); + margin-bottom: 16px; +} + +/* Form Card (for listing forms) */ +.form-card { + background-color: var(--color-surface); + border-radius: var(--border-radius); + box-shadow: var(--shadow-sm); + border: 1px solid var(--color-border); + transition: all 0.2s ease; + display: flex; + flex-direction: column; + margin-bottom: 20px; +} + +.form-card:hover { + box-shadow: var(--shadow-md); + /* transform: translateY(-2px); */ + /* Standardized lift */ + border-color: var(--color-accent); +} + +.form-card-header { + padding: 16px; + background-color: var(--color-surface); + /* Clean header */ + border-bottom: 1px solid var(--color-border); + display: flex; + justify-content: space-between; + align-items: center; +} + +.form-title { + font-weight: 600; + font-size: 1rem; + color: var(--color-primary); + display: flex; + align-items: center; +} + +.form-menu { + color: var(--color-text-light); + cursor: pointer; + padding: 6px; + border-radius: var(--border-radius); + transition: background-color 0.2s ease, color 0.2s ease; + background: none; + border: none; + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; +} + +.form-menu:hover { + background-color: var(--color-bg); + color: var(--color-primary); +} + +.form-menu:focus-visible { + outline: 2px solid var(--color-accent); + outline-offset: 1px; + background-color: var(--color-bg); + color: var(--color-primary); +} + + +.form-card-content { + padding: 16px; + flex-grow: 1; +} + +.form-submission-count { + font-size: 0.85rem; + color: var(--color-text-light); + margin-bottom: 8px; +} + +.form-url-info { + font-size: 0.8rem; + color: var(--color-text-light); + margin-top: 12px; + display: flex; + align-items: center; + gap: 8px; + word-break: break-all; + background-color: var(--color-bg); + /* Use main BG for slight recess */ + padding: 8px 12px; + border-radius: var(--border-radius); + border: 1px solid var(--color-border); +} + +.form-url-info input[type="text"] { + flex-grow: 1; + font-size: 0.8rem; + padding: 0; + background-color: transparent; + cursor: text; + border: none; + color: var(--color-text); + /* Ensure text color is readable */ +} + +.form-url-info input[type="text"]:focus-visible { + outline: none; + box-shadow: none; +} + + +.form-badge { + font-size: 0.75rem; + padding: 4px 10px; + border-radius: 12px; + font-weight: 500; + line-height: 1.2; + white-space: nowrap; + margin-left: 8px; + display: inline-block; +} + +.form-badge.archived { + background-color: var(--color-archived-bg); + color: var(--color-archived); +} + +.form-badge.active { + background-color: var(--color-success-bg); + color: var(--color-success); +} + + +/* Dropdown Menu */ +.dropdown { + position: relative; + display: inline-block; +} + +.dropdown-menu { + display: none; + position: absolute; + right: 0; + top: 100%; + background-color: var(--color-surface); + min-width: 200px; + box-shadow: var(--shadow-md); + border: 1px solid var(--color-border); + border-radius: var(--border-radius); + z-index: 1000; + padding: 8px 0; + margin-top: 4px; + list-style: none; + opacity: 0; + transform: translateY(10px); + transition: opacity 0.2s ease, transform 0.2s ease; +} + +.dropdown-menu.show { + display: block; + opacity: 1; + transform: translateY(0); +} + +.dropdown-item { + display: block; + width: 100%; + padding: 8px 16px; + text-align: left; + text-decoration: none; + color: var(--color-text); + background-color: transparent; + border: none; + cursor: pointer; + font-size: 0.9rem; + white-space: nowrap; + transition: background-color 0.2s ease, color 0.2s ease; +} + +.dropdown-item:hover { + background-color: var(--color-bg); + color: var(--color-primary); +} + +.dropdown-item:focus-visible { + outline: 2px solid var(--color-accent); + outline-offset: -2px; + /* Inset outline */ + background-color: var(--color-bg); + color: var(--color-primary); +} + + +.dropdown-divider { + height: 1px; + background-color: var(--color-border); + margin: 8px 0; +} + +.dropdown-item.text-danger { + color: var(--color-danger); +} + +.dropdown-item.text-danger:hover { + background-color: var(--color-danger-bg); + color: var(--color-danger); + /* Keep text color as danger */ +} + +.dropdown-item.text-danger:focus-visible { + outline: 2px solid var(--color-danger); + background-color: var(--color-danger-bg); + color: var(--color-danger); +} + + +/* Modals */ +.modal { + display: none; + position: fixed; + z-index: 1050; + left: 0; + top: 0; + width: 100%; + height: 100%; + overflow-y: auto; + background-color: rgba(var(--color-primary-rgb), 0.6); + /* Primary color backdrop */ + backdrop-filter: blur(4px); + /* Increased blur */ + opacity: 0; + transition: opacity 0.3s ease; +} + +.modal.show { + display: flex; + align-items: center; + justify-content: center; + opacity: 1; +} + +.modal-dialog { + background-color: var(--color-surface); + padding: 24px; + border: 1px solid var(--color-border); + border-radius: var(--border-radius); + width: 95%; + max-width: 500px; + box-shadow: var(--shadow-md); + position: relative; + margin: 20px; + box-sizing: border-box; + transform: translateY(-20px); + opacity: 0; + transition: opacity 0.3s ease, transform 0.3s ease; +} + +.modal.show .modal-dialog { + transform: translateY(0); + opacity: 1; +} + +.modal-header { + display: flex; + justify-content: space-between; + align-items: center; + padding-bottom: 16px; + margin-bottom: 16px; + border-bottom: 1px solid var(--color-border); +} + +.modal-title { + font-size: 1.3rem; + font-weight: 600; + color: var(--color-primary); + margin: 0; +} + +.btn-close { + background: transparent; + border: none; + font-size: 1.8rem; + font-weight: bold; + color: var(--color-text-light); + cursor: pointer; + padding: 0.5rem; + margin: -0.5rem; + line-height: 1; + transition: color 0.2s ease; + border-radius: var(--border-radius); +} + +.btn-close:hover { + color: var(--color-primary); +} + +.btn-close:focus-visible { + outline: 2px solid var(--color-accent); + outline-offset: 2px; + color: var(--color-primary); +} + + +.modal-body { + padding-bottom: 16px; +} + +.modal-footer { + display: flex; + justify-content: flex-end; + gap: 10px; + padding-top: 16px; + margin-top: 16px; + border-top: 1px solid var(--color-border); +} + +/* Form Elements (inputs, labels) */ +.form-label { + display: block; + margin-bottom: 8px; + font-weight: 500; + color: var(--color-text); + font-size: 0.9rem; +} + +.form-group { + margin-bottom: 1rem; +} + +input[type="text"], +input[type="email"], +textarea { + width: 100%; + padding: 10px 12px; + border: 1px solid var(--color-border); + border-radius: var(--border-radius); + background-color: var(--color-surface); + color: var(--color-text); + font-size: 0.9rem; + line-height: 1.5; + transition: border-color 0.2s ease, box-shadow 0.2s ease; +} + +input[type="text"]:focus-visible, +textarea:focus-visible { + outline: none; + border-color: var(--color-accent); + box-shadow: 0 0 0 3px rgba(var(--color-accent-rgb), 0.25); + /* Accent glow */ +} + +/* Specific style for the read-only URL input inside .form-url-info */ +.form-url-info input[type="text"].form-url-display { + /* Inherits styles from .form-url-info input[type="text"] */ +} + +.form-text { + font-size: 0.8rem; + color: var(--color-text-light); + margin-top: 4px; + display: block; +} + +/* For Form Manager Specific Layouts */ +.create-form-section { + background-color: var(--color-surface); + border-radius: var(--border-radius); + padding: 24px; + box-shadow: var(--shadow-sm); + border: 1px solid var(--color-border); + margin-bottom: 40px; +} + +.create-form-section .section-title { + margin-bottom: 20px; +} + +.create-form-section .form-group { + margin-bottom: 24px; +} + +/* Copy URL Button Specifics */ +.copy-button { + flex-shrink: 0; + padding: 6px 10px; + font-size: 0.8rem; + background-color: var(--color-surface); + color: var(--color-primary); + border: 1px solid var(--color-border); + box-shadow: none; + gap: 4px; +} + +.copy-button:hover { + background-color: var(--color-bg); + /* Use main BG for hover */ + border-color: #c8ced3; + /* Darker border */ + box-shadow: var(--shadow-sm); + transform: translateY(-1px); + color: var(--color-accent); +} + +.copy-button:active { + background-color: #e0e5ea; + /* Darker bg */ + box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); + transform: translateY(0); +} + +.copy-button .copy-text { + display: inline-block; + min-width: 35px; + text-align: center; +} + +.copy-button.copied .copy-text { + color: var(--color-success); + font-weight: 600; +} + +.copy-button.copied svg { + color: var(--color-success); +} + + +/* Submissions Page specific */ +.dashboard-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 32px; + flex-wrap: wrap; + gap: 16px; +} + +.dashboard-title { + font-size: 2.1rem; + /* Matched page-title */ + font-weight: 700; + color: var(--color-primary); + line-height: 1.2; + margin: 0; + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.07); + /* Matched page-title */ +} + +.alert-info-custom { + padding: 16px; + background-color: var(--color-surface); + border: 1px solid var(--color-border); + border-left: 4px solid var(--color-accent); + border-radius: var(--border-radius); + margin-bottom: 24px; + color: var(--color-text-light); + font-size: 0.9rem; + box-shadow: var(--shadow-sm); +} + +/* Submissions Table */ +.submissions-table-wrapper { + overflow-x: auto; + background-color: var(--color-surface); + border-radius: var(--border-radius); + box-shadow: var(--shadow-sm); + border: 1px solid var(--color-border); + margin-bottom: 24px; +} + +.submissions-table { + width: 100%; + border-collapse: collapse; + min-width: 700px; + caption-side: bottom; +} + +.submissions-table caption { + padding: 10px; + font-size: 0.85rem; + color: var(--color-text-light); + text-align: left; +} + +.submissions-table th, +.submissions-table td { + padding: 14px 16px; + text-align: left; + border-bottom: 1px solid var(--color-border); + vertical-align: top; + font-size: 0.9rem; +} + +.submissions-table th { + font-weight: 600; + color: var(--color-primary); + font-size: 0.85rem; + background-color: var(--color-bg); + /* Use main BG for header */ + white-space: nowrap; +} + +.submissions-table th:first-child { + /* No specific radius if table wrapper has it */ +} + +.submissions-table th:last-child { + /* No specific radius if table wrapper has it */ + text-align: right; +} + +.submissions-table tbody tr:last-child td { + border-bottom: none; +} + +.submissions-table tbody tr:hover { + background-color: color-mix(in srgb, var(--color-bg), #000000 3%); + /* Subtle darker BG hover */ +} + +.submissions-table td:last-child { + text-align: right; +} + +.table-actions { + display: flex; + gap: 8px; + justify-content: flex-end; + align-items: center; +} + +.table-action { + color: var(--color-text-light); + cursor: pointer; + transition: color 0.2s ease, transform 0.1s ease; + display: flex; + align-items: center; + background: none; + border: none; + padding: 4px; + border-radius: var(--border-radius); +} + +.table-action:hover { + color: var(--color-accent); + transform: scale(1.1); +} + +.table-action:focus-visible { + outline: 2px solid var(--color-accent); + outline-offset: 2px; + color: var(--color-accent); +} + +.table-action.delete:hover { + color: var(--color-danger); +} + +.table-action.delete:focus-visible { + outline: 2px solid var(--color-danger); + outline-offset: 2px; + color: var(--color-danger); +} + + +.submission-data-item { + margin-bottom: 8px; + word-break: break-word; + padding-bottom: 4px; + border-bottom: 1px dashed var(--color-border); +} + +.submission-data-item:last-child { + margin-bottom: 0; + border-bottom: none; +} + +.submission-data-item strong { + color: var(--color-primary); + margin-right: 6px; + font-weight: 600; +} + +/* Pagination */ +.pagination { + display: flex; + justify-content: center; + align-items: center; + list-style: none; + padding: 0; + margin: 32px 0 16px 0; + gap: 8px; + flex-wrap: wrap; +} + +.page-item .page-link { + display: inline-block; + padding: 8px 12px; + text-decoration: none; + color: var(--color-primary); + background-color: var(--color-surface); + border: 1px solid var(--color-border); + border-radius: var(--border-radius); + transition: all 0.2s ease; + font-size: 0.9rem; + min-width: 38px; + text-align: center; +} + +.page-item .page-link:hover { + background-color: var(--color-bg); + border-color: var(--color-accent); + color: var(--color-accent); +} + +.page-item .page-link:focus-visible { + outline: 2px solid var(--color-accent); + outline-offset: 2px; + background-color: var(--color-bg); + border-color: var(--color-accent); + color: var(--color-accent); +} + + +.page-item.active .page-link { + background-color: var(--color-primary); + color: var(--color-surface); + border-color: var(--color-primary); + font-weight: 600; + box-shadow: var(--shadow-sm); +} + +.page-item.active .page-link:hover { + background-color: #2c3e50; + /* Darker primary */ + border-color: #2c3e50; + box-shadow: var(--shadow-md); + color: var(--color-surface); +} + +.page-item.disabled .page-link { + color: var(--color-text-light); + pointer-events: none; + background-color: var(--color-bg); + border-color: var(--color-border); + opacity: 0.7; + cursor: not-allowed; + box-shadow: none; +} + +.page-item.disabled .page-link:focus-visible { + outline: none; +} + + +.pagination-info { + text-align: center; + color: var(--color-text-light); + font-size: 0.85rem; + margin-top: 0; + margin-bottom: 32px; +} + +/* Utility classes */ +.mb-2 { + margin-bottom: 0.5rem !important; +} + +.mt-2 { + margin-top: 0.5rem !important; +} + +.me-2 { + margin-right: 0.5rem !important; +} + +.mb-3 { + margin-bottom: 1rem !important; +} + +.mt-3 { + margin-top: 1rem !important; +} + +.me-3 { + margin-right: 1rem !important; +} + +.d-flex { + display: flex !important; +} + +.justify-content-between { + justify-content: space-between !important; +} + +.align-items-center { + align-items: center !important; +} + +.align-items-start { + align-items: flex-start !important; +} \ No newline at end of file diff --git a/views/index.ejs b/views/index.ejs new file mode 100644 index 0000000..03b9cc8 --- /dev/null +++ b/views/index.ejs @@ -0,0 +1,240 @@ + + + + + + + formies + + + + + + +
+

formies

+ +
+ +
+

+ + Create New Form +

+
+
+ + + A descriptive name for your new form. +
+ +
+
+ + +
+

+ + Your Forms +

+ <% if (forms.length===0) { %> +

No forms created yet. Create your first form above!

+ <% } else { %> + <% forms.forEach(form=> { %> +
+
+

+ + <%= form.name %> + + <% if (form.is_archived) { %> + Archived + <% } %> +

+ +
+ +
+

+ <%= form.submission_count %> submission<%= form.submission_count !==1 ? 's' : '' + %> +

+
+ + + +
+
+
+ + + + + + + <% }); %> + <% } %> +
+
+
+ + + + + \ No newline at end of file diff --git a/views/main.js b/views/main.js new file mode 100644 index 0000000..4579e77 --- /dev/null +++ b/views/main.js @@ -0,0 +1,71 @@ +// Dropdown functionality +function toggleDropdown(button) { + // Find the closest .dropdown and then the .dropdown-menu inside it + const dropdown = button.closest('.dropdown'); + if (!dropdown) return; + const dropdownMenu = dropdown.querySelector('.dropdown-menu'); + if (dropdownMenu) { + dropdownMenu.classList.toggle('show'); + } +} + +// Modal functionality +function showModal(modalId) { + document.getElementById(modalId).classList.add('show'); +} + +function hideModal(modalId) { + document.getElementById(modalId).classList.remove('show'); +} + +// Initialize all event listeners +document.addEventListener('DOMContentLoaded', function () { + // Handle dropdown toggles + document.querySelectorAll('[data-action="toggle-dropdown"]').forEach(button => { + button.addEventListener('click', function () { + toggleDropdown(this); + }); + }); + + // Handle modal show buttons + document.querySelectorAll('[data-action="show-modal"]').forEach(button => { + button.addEventListener('click', function () { + const modalId = this.dataset.modal; + showModal(modalId); + }); + }); + + // Handle modal hide buttons + document.querySelectorAll('[data-action="hide-modal"]').forEach(button => { + button.addEventListener('click', function () { + const modalId = this.dataset.modal; + hideModal(modalId); + }); + }); + + // Handle test notification buttons + document.querySelectorAll('[data-action="test-notification"]').forEach(button => { + button.addEventListener('click', function () { + const formId = this.dataset.formId; + // Implement test notification functionality here + console.log('Testing notification for form:', formId); + }); + }); + + // Close dropdowns when clicking outside + document.addEventListener('click', function (event) { + // Only close if click is outside any .dropdown + if (!event.target.closest('.dropdown')) { + document.querySelectorAll('.dropdown-menu.show').forEach(menu => { + menu.classList.remove('show'); + }); + } + }); + + // Close modals when clicking outside + document.addEventListener('click', function (event) { + if (event.target.classList.contains('modal')) { + event.target.classList.remove('show'); + } + }); +}); \ No newline at end of file diff --git a/views/submissions.ejs b/views/submissions.ejs new file mode 100644 index 0000000..fc6cb06 --- /dev/null +++ b/views/submissions.ejs @@ -0,0 +1,177 @@ + + + + + + + Submissions - <%= formName %> + + + + + + + +
+
+
+

Submissions for <%= formName %> +

+
+ + + Back to Forms + + + + Export CSV + +
+ +
+
+
+ + <% if (submissions.length===0) { %> +
No submissions yet for this form.
+ <% } else { %> +
+ + + + + + + + + + + + <% submissions.forEach(submission=> { %> + + + + + + + <% }); %> + +
List of submissions for the form named <%= formName %>. +
Submitted AtIP AddressDataActions
+ <%= new Date(submission.submitted_at).toLocaleString() %> + + <%= submission.ip_address %> + + <% const data=JSON.parse(submission.data); %> + <% Object.entries(data).forEach(([key, value])=> { %> + <% if (key !=='honeypot_field' && key !=='_thankyou' ) { %> +
+ + <%= key %>: + + + <%= typeof value==='object' ? JSON.stringify(value) : + value %> + +
+ <% } %> + <% }); %> +
+
+
+ +
+
+
+
+ + + <% if (pagination.totalPages> 1) { %> + +
+ Showing <%= (pagination.currentPage - 1) * pagination.limit + 1 %> to <%= + Math.min(pagination.currentPage * pagination.limit, pagination.totalSubmissions) %> + of <%= pagination.totalSubmissions %> submissions +
+ <% } %> + <% } %> +
+
+ + + + \ No newline at end of file