Created
April 29, 2026 12:30
-
-
Save Aminigbo/80b0b48d8e1e3bfcf8c02a03fa9c158b to your computer and use it in GitHub Desktop.
local storage
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Event Form UI</title> | |
| <style> | |
| :root { | |
| --bg: #eef2f8; | |
| --card: #ffffff; | |
| --field: #f8faff; | |
| --line: #dbe3f3; | |
| --text: #19233a; | |
| --muted: #667085; | |
| --heading: #0f2f68; | |
| --primary: #2453cc; | |
| --primary-dark: #1d46af; | |
| --danger-bg: #feecef; | |
| --danger-text: #b42336; | |
| } | |
| * { | |
| box-sizing: border-box; | |
| margin: 0; | |
| padding: 0; | |
| font-family: Inter, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; | |
| } | |
| body { | |
| background: | |
| radial-gradient(circle at 0 0, #f7f9ff 0%, transparent 40%), | |
| radial-gradient(circle at 100% 0, #edf4ff 0%, transparent 36%), | |
| var(--bg); | |
| color: var(--text); | |
| line-height: 1.45; | |
| } | |
| .nav { | |
| background: #08152f; | |
| color: #fff; | |
| padding: 16px 36px; | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| border-bottom: 1px solid rgba(255, 255, 255, 0.08); | |
| position: sticky; | |
| top: 0; | |
| z-index: 10; | |
| } | |
| .logo { | |
| font-size: 30px; | |
| font-weight: 800; | |
| letter-spacing: 0.4px; | |
| color: #29a5ff; | |
| } | |
| .nav ul { | |
| list-style: none; | |
| display: flex; | |
| gap: 26px; | |
| font-size: 14px; | |
| color: rgba(255, 255, 255, 0.9); | |
| } | |
| .wrap { | |
| max-width: 1180px; | |
| margin: 30px auto 42px; | |
| padding: 0 16px; | |
| } | |
| .card { | |
| background: var(--card); | |
| border: 1px solid var(--line); | |
| border-radius: 16px; | |
| padding: 26px; | |
| box-shadow: 0 14px 36px rgba(20, 44, 95, 0.08); | |
| } | |
| .grid { | |
| display: grid; | |
| grid-template-columns: 300px 1fr; | |
| gap: 24px; | |
| } | |
| .upload { | |
| min-height: 272px; | |
| border: 1px dashed #b8c7e9; | |
| background: linear-gradient(180deg, #f8fbff 0%, #f4f7ff 100%); | |
| border-radius: 14px; | |
| display: grid; | |
| place-content: center; | |
| text-align: center; | |
| gap: 12px; | |
| padding: 18px; | |
| color: var(--muted); | |
| } | |
| label, | |
| .title { | |
| display: block; | |
| font-size: 18px; | |
| font-weight: 700; | |
| margin: 0 0 8px; | |
| color: var(--heading); | |
| letter-spacing: 0.2px; | |
| } | |
| .title { | |
| margin-top: 4px; | |
| } | |
| .group { | |
| margin-bottom: 16px; | |
| } | |
| input, | |
| textarea, | |
| select { | |
| width: 100%; | |
| padding: 12px 14px; | |
| border: 1px solid #d8e0f0; | |
| background: var(--field); | |
| border-radius: 10px; | |
| font-size: 14px; | |
| color: var(--text); | |
| transition: border-color 0.15s ease, box-shadow 0.15s ease, background 0.15s ease; | |
| } | |
| input::placeholder, | |
| textarea::placeholder { | |
| color: #9aa3b2; | |
| } | |
| input:focus, | |
| textarea:focus, | |
| select:focus { | |
| outline: none; | |
| border-color: #88a7eb; | |
| background: #ffffff; | |
| box-shadow: 0 0 0 4px rgba(36, 83, 204, 0.12); | |
| } | |
| textarea { | |
| min-height: 112px; | |
| resize: vertical; | |
| } | |
| .count { | |
| text-align: right; | |
| color: var(--muted); | |
| font-size: 12px; | |
| margin-top: 4px; | |
| } | |
| .r4, | |
| .r2, | |
| .r3 { | |
| display: grid; | |
| gap: 14px; | |
| margin-top: 14px; | |
| } | |
| .r4 { grid-template-columns: repeat(4, 1fr); } | |
| .r2 { grid-template-columns: repeat(2, 1fr); } | |
| .r3 { grid-template-columns: 1.2fr 1fr 1fr; } | |
| .ticket-list { | |
| display: grid; | |
| gap: 10px; | |
| } | |
| .ticket { | |
| display: flex; | |
| justify-content: space-between; | |
| padding: 12px 14px; | |
| border: 1px solid #dfe7f6; | |
| border-radius: 10px; | |
| background: var(--field); | |
| color: #1f3a6d; | |
| font-weight: 600; | |
| } | |
| .accept { | |
| margin: 22px 0; | |
| display: flex; | |
| gap: 10px; | |
| align-items: flex-start; | |
| font-size: 14px; | |
| color: #3a4b6a; | |
| } | |
| .accept input { | |
| width: 18px; | |
| height: 18px; | |
| margin-top: 1px; | |
| accent-color: var(--primary); | |
| } | |
| .actions { | |
| display: flex; | |
| justify-content: center; | |
| gap: 12px; | |
| flex-wrap: wrap; | |
| } | |
| button { | |
| border: none; | |
| border-radius: 10px; | |
| padding: 12px 20px; | |
| font-weight: 700; | |
| font-size: 14px; | |
| cursor: pointer; | |
| transition: transform 0.12s ease, filter 0.12s ease; | |
| } | |
| button:hover { | |
| transform: translateY(-1px); | |
| filter: brightness(0.98); | |
| } | |
| .primary { | |
| background: linear-gradient(180deg, var(--primary) 0%, var(--primary-dark) 100%); | |
| color: #fff; | |
| min-width: 220px; | |
| box-shadow: 0 10px 22px rgba(36, 83, 204, 0.28); | |
| } | |
| .edit { | |
| background: #dce8ff; | |
| color: #153d8b; | |
| } | |
| .delete { | |
| background: var(--danger-bg); | |
| color: var(--danger-text); | |
| } | |
| .hidden { | |
| display: none; | |
| } | |
| .saved h2 { | |
| font-size: 28px; | |
| font-weight: 800; | |
| color: var(--heading); | |
| margin-bottom: 14px; | |
| letter-spacing: 0.2px; | |
| } | |
| .item { | |
| background: #f8faff; | |
| border: 1px solid #e2e9f9; | |
| border-radius: 10px; | |
| padding: 12px; | |
| margin-bottom: 10px; | |
| font-size: 14px; | |
| } | |
| .item strong { | |
| display: inline-block; | |
| min-width: 170px; | |
| color: #1a3f7f; | |
| } | |
| @media (max-width: 920px) { | |
| .grid, | |
| .r4, | |
| .r2, | |
| .r3 { | |
| grid-template-columns: 1fr; | |
| } | |
| .nav { | |
| flex-direction: column; | |
| align-items: flex-start; | |
| gap: 10px; | |
| } | |
| .item strong { | |
| display: block; | |
| min-width: 0; | |
| margin-bottom: 4px; | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <header class="nav"> | |
| <div class="logo">Reelwod</div> | |
| <ul><li>Home</li><li>Upcoming</li><li>Contact Us</li><li>Help</li><li>Account</li></ul> | |
| </header> | |
| <main class="wrap"> | |
| <!-- Form view: used for creating and editing event details --> | |
| <section id="formView" class="card"> | |
| <form id="eventForm"> | |
| <div class="grid"> | |
| <div class="upload"> | |
| <input id="eventImage" type="file" accept="image/*"> | |
| <small>(1400px x 400px not larger than 5mb)</small> | |
| </div> | |
| <div> | |
| <div class="group"> | |
| <label for="eventTitle">Event title</label> | |
| <input id="eventTitle" name="eventTitle" required> | |
| </div> | |
| <div class="group"> | |
| <label for="eventHost">Event Host</label> | |
| <input id="eventHost" name="eventHost" required> | |
| </div> | |
| <div class="group"> | |
| <label for="eventDescription">Event Description</label> | |
| <textarea id="eventDescription" name="eventDescription" maxlength="200" required></textarea> | |
| <p class="count"><span id="descCount">0</span>/200</p> | |
| </div> | |
| </div> | |
| </div> | |
| <p class="title">Time & Date</p> | |
| <div class="r4"> | |
| <input id="startDate" name="startDate" type="date" required> | |
| <input id="startTime" name="startTime" type="time" required> | |
| <input id="endDate" name="endDate" type="date" required> | |
| <input id="endTime" name="endTime" type="time" required> | |
| </div> | |
| <div class="r2"> | |
| <div class="group"><label for="eventLocation">Event Location</label><input id="eventLocation" name="eventLocation" required></div> | |
| <div class="group"><label for="locationUrl">Enter location url</label><input id="locationUrl" name="locationUrl" type="url" placeholder="https://..." required></div> | |
| </div> | |
| <div class="r2"> | |
| <div class="group"> | |
| <label for="eventCategory">Event category</label> | |
| <select id="eventCategory" name="eventCategory" required> | |
| <option value="">Select category</option><option>Music</option><option>Conference</option><option>Workshop</option><option>Sports</option> | |
| </select> | |
| </div> | |
| <div class="group"> | |
| <label for="ticketType">Ticket type</label> | |
| <select id="ticketType" name="ticketType" required> | |
| <option value="">Select type</option><option>Paid</option><option>Free</option><option>Invite-only</option> | |
| </select> | |
| </div> | |
| </div> | |
| <div class="r3"> | |
| <div class="group"> | |
| <label>Tickets category</label> | |
| <div class="ticket-list"> | |
| <div class="ticket"><span>Regular</span><span>+</span></div> | |
| <div class="ticket"><span>VIP</span><span>+</span></div> | |
| <div class="ticket"><span>Gold table</span><span>+</span></div> | |
| <div class="ticket"><span>VVIP</span><span>+</span></div> | |
| </div> | |
| </div> | |
| <div class="group"> | |
| <label for="regularPrice">Ticket price</label> | |
| <input id="regularPrice" name="regularPrice" placeholder="₦10,000" required> | |
| <input id="vipPrice" name="vipPrice" placeholder="₦20,000"> | |
| <input id="goldPrice" name="goldPrice" placeholder="₦150,000"> | |
| <input id="vvipPrice" name="vvipPrice" placeholder="₦100,000"> | |
| </div> | |
| <div class="group"> | |
| <label for="regularQty">Ticket maximum quantity</label> | |
| <input id="regularQty" name="regularQty" type="number" min="0" placeholder="300" required> | |
| <input id="vipQty" name="vipQty" type="number" min="0" placeholder="200"> | |
| <input id="goldQty" name="goldQty" type="number" min="0" placeholder="100"> | |
| <input id="vvipQty" name="vvipQty" type="number" min="0" placeholder="100"> | |
| </div> | |
| </div> | |
| <label class="accept"><input id="terms" type="checkbox" required><span>I accept the terms and conditions for using this service, and hereby confirm I have read the Agreement.</span></label> | |
| <div class="actions"><button class="primary" type="submit">Post Event</button></div> | |
| </form> | |
| </section> | |
| <!-- Saved view: shown after details are saved --> | |
| <section id="savedView" class="card saved hidden"> | |
| <h2>Saved Event Details</h2> | |
| <div id="savedContent"></div> | |
| <div class="actions"> | |
| <button id="editBtn" class="edit" type="button">Edit</button> | |
| <button id="deleteBtn" class="delete" type="button">Delete Saved Data</button> | |
| </div> | |
| </section> | |
| </main> | |
| <script> | |
| const STORAGE_KEY = "shareviralEventFormData"; | |
| const form = document.getElementById("eventForm"); | |
| const formView = document.getElementById("formView"); | |
| const savedView = document.getElementById("savedView"); | |
| const savedContent = document.getElementById("savedContent"); | |
| const description = document.getElementById("eventDescription"); | |
| const descCount = document.getElementById("descCount"); | |
| const editBtn = document.getElementById("editBtn"); | |
| const deleteBtn = document.getElementById("deleteBtn"); | |
| // Keep character count in sync with the description textarea. | |
| function updateDescriptionCount() { | |
| descCount.textContent = description.value.length; | |
| } | |
| // Convert form data into a plain object for storage and display. | |
| function getFormData() { | |
| const fd = new FormData(form); | |
| return { | |
| eventTitle: fd.get("eventTitle"), | |
| eventHost: fd.get("eventHost"), | |
| eventDescription: fd.get("eventDescription"), | |
| startDate: fd.get("startDate"), | |
| startTime: fd.get("startTime"), | |
| endDate: fd.get("endDate"), | |
| endTime: fd.get("endTime"), | |
| eventLocation: fd.get("eventLocation"), | |
| locationUrl: fd.get("locationUrl"), | |
| eventCategory: fd.get("eventCategory"), | |
| ticketType: fd.get("ticketType"), | |
| regularPrice: fd.get("regularPrice"), | |
| vipPrice: fd.get("vipPrice"), | |
| goldPrice: fd.get("goldPrice"), | |
| vvipPrice: fd.get("vvipPrice"), | |
| regularQty: fd.get("regularQty"), | |
| vipQty: fd.get("vipQty"), | |
| goldQty: fd.get("goldQty"), | |
| vvipQty: fd.get("vvipQty") | |
| }; | |
| } | |
| // Fill the form when user clicks Edit. | |
| function setFormData(data) { | |
| Object.entries(data).forEach(([key, value]) => { | |
| if (form.elements[key]) form.elements[key].value = value || ""; | |
| }); | |
| updateDescriptionCount(); | |
| const terms = document.getElementById("terms"); | |
| terms.checked = true; | |
| } | |
| // Build the "saved info" UI from stored data. | |
| function renderSavedData(data) { | |
| const rows = [ | |
| ["Event title", data.eventTitle], | |
| ["Event host", data.eventHost], | |
| ["Description", data.eventDescription], | |
| ["Start", `${data.startDate || "-"} ${data.startTime || ""}`.trim()], | |
| ["End", `${data.endDate || "-"} ${data.endTime || ""}`.trim()], | |
| ["Location", data.eventLocation], | |
| ["Location URL", data.locationUrl], | |
| ["Category", data.eventCategory], | |
| ["Ticket type", data.ticketType], | |
| ["Regular ticket", `${data.regularPrice || "-"} | Qty: ${data.regularQty || "-"}`], | |
| ["VIP ticket", `${data.vipPrice || "-"} | Qty: ${data.vipQty || "-"}`], | |
| ["Gold table", `${data.goldPrice || "-"} | Qty: ${data.goldQty || "-"}`], | |
| ["VVIP ticket", `${data.vvipPrice || "-"} | Qty: ${data.vvipQty || "-"}`] | |
| ]; | |
| savedContent.innerHTML = rows.map(([label, value]) => | |
| `<div class="item"><strong>${label}:</strong> ${value || "-"}</div>` | |
| ).join(""); | |
| } | |
| // Switch between form and saved-data interfaces. | |
| function showSavedView(data) { | |
| renderSavedData(data); | |
| formView.classList.add("hidden"); | |
| savedView.classList.remove("hidden"); | |
| } | |
| function showFormView() { | |
| savedView.classList.add("hidden"); | |
| formView.classList.remove("hidden"); | |
| } | |
| // Save form data and immediately show it in the second UI. | |
| form.addEventListener("submit", (event) => { | |
| event.preventDefault(); | |
| const data = getFormData(); | |
| localStorage.setItem(STORAGE_KEY, JSON.stringify(data)); | |
| showSavedView(data); | |
| }); | |
| // Edit button: bring back form prefilled with saved values. | |
| editBtn.addEventListener("click", () => { | |
| const saved = localStorage.getItem(STORAGE_KEY); | |
| if (!saved) return; | |
| setFormData(JSON.parse(saved)); | |
| showFormView(); | |
| }); | |
| // Delete button: remove saved data and reset UI to empty form. | |
| deleteBtn.addEventListener("click", () => { | |
| localStorage.removeItem(STORAGE_KEY); | |
| form.reset(); | |
| updateDescriptionCount(); | |
| showFormView(); | |
| }); | |
| // On page load, automatically show saved view if data exists. | |
| window.addEventListener("DOMContentLoaded", () => { | |
| updateDescriptionCount(); | |
| description.addEventListener("input", updateDescriptionCount); | |
| const saved = localStorage.getItem(STORAGE_KEY); | |
| if (saved) showSavedView(JSON.parse(saved)); | |
| }); | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment