added login menu for further login options in the future

This commit is contained in:
Keep Creating Online
2025-02-01 14:01:48 -05:00
parent d1a809b99b
commit f5a1b6471b
9 changed files with 343 additions and 80 deletions

View File

@@ -0,0 +1,105 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Application Form</title>
<!-- Include Tailwind CSS -->
<link href="css/tailwind.min.css" rel="stylesheet" />
</head>
<body class="bg-gray-900 text-gray-100">
<!-- Button to open the modal -->
<div class="p-4">
<button
id="openNostrForm"
class="bg-blue-500 px-4 py-2 rounded hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500"
>
Open Nostr Form
</button>
</div>
<!-- Modal Container -->
<div
id="nostrFormModal"
class="fixed inset-0 z-50 hidden"
style="background: transparent"
>
<!-- Overlay Layer with dark background and blur -->
<div
class="absolute inset-0 z-10"
style="
background-color: rgba(0, 0, 0, 0.9);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
"
></div>
<!-- Modal Container -->
<div
class="relative modal-container h-full w-full flex items-center justify-center overflow-y-auto z-20"
>
<div
class="modal-content bg-gray-900 w-full max-w-lg md:max-w-2xl my-0 rounded-lg overflow-hidden relative max-h-[90vh]"
>
<!-- Top Bar -->
<div
class="sticky top-0 bg-gradient-to-b from-black/80 to-transparent transition-transform duration-300 p-4 flex items-center justify-between"
>
<h2 class="text-xl font-bold text-white">My Nostr Form</h2>
<button
id="closeNostrFormModal"
class="flex items-center justify-center w-10 h-10 rounded-full bg-black/50 hover:bg-black/70 transition-all duration-200 backdrop-blur focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-black focus:ring-blue-500"
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="w-6 h-6 text-gray-300"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M6 18L18 6M6 6l12 12"
/>
</svg>
</button>
</div>
<!-- Modal Content -->
<div class="p-6">
<div class="flex justify-center">
<iframe
src="https://formstr.app/#/f/naddr1qvzqqqr4mqpzphm2csv2s3ehude2dc0yd0t06psy6kkek0gcpddputetum4yfxnsqythwumn8ghj7un9d3shjtnwdaehgu3wvfskuep0qqsky6t5we5kggzhdp5hgetvd9ehggzpwpcxc6trv96xjmmwyprx7und8lh48n"
height="700px"
width="480px"
frameborder="0"
style="
border-style: none;
box-shadow: 0px 0px 2px 2px rgba(0, 0, 0, 0.2);
"
cellspacing="0"
></iframe>
</div>
</div>
</div>
</div>
</div>
<!-- Script to toggle modal -->
<script>
const openBtn = document.getElementById("openNostrForm");
const modal = document.getElementById("nostrFormModal");
const closeBtn = document.getElementById("closeNostrFormModal");
openBtn.addEventListener("click", () => {
modal.classList.remove("hidden");
});
closeBtn.addEventListener("click", () => {
modal.classList.add("hidden");
});
</script>
</body>
</html>

View File

@@ -0,0 +1,67 @@
<div
id="loginModal"
class="fixed inset-0 z-50 hidden"
style="background: transparent"
>
<!-- Dark overlay -->
<div
class="absolute inset-0 z-10"
style="
background-color: rgba(0, 0, 0, 0.9);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
"
></div>
<!-- Modal container -->
<div
class="relative modal-container h-full w-full flex items-center justify-center overflow-y-auto z-20"
>
<div
class="modal-content bg-gray-900 w-full max-w-md my-0 rounded-lg overflow-hidden relative max-h-[90vh]"
>
<!-- Header -->
<div
class="sticky top-0 bg-gradient-to-b from-black/80 to-transparent p-4 flex items-center justify-between"
>
<h2 class="text-xl font-bold text-white">Login Options</h2>
<button
id="closeLoginModal"
class="flex items-center justify-center w-10 h-10 rounded-full bg-black/50 hover:bg-black/70 transition-all duration-200 backdrop-blur focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-black focus:ring-blue-500"
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="w-6 h-6 text-gray-300"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M6 18L18 6M6 6l12 12"
/>
</svg>
</button>
</div>
<!-- Body with login buttons -->
<div class="p-6 space-y-4">
<button
id="loginNIP07"
class="w-full bg-blue-500 text-white px-4 py-2 rounded-md hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2"
>
Login with Extension (NIP-07)
</button>
<button
id="loginNSEC"
class="w-full bg-gray-500 text-white px-4 py-2 rounded-md cursor-not-allowed"
disabled
>
Login with NSEC (Coming Soon)
</button>
</div>
</div>
</div>
</div>

View File

@@ -1,10 +1,25 @@
<!-- components/profile-modal.html --> <!-- components/profile-modal.html -->
<div id="profileModal" class="fixed inset-0 bg-black/90 z-50 hidden"> <div
id="profileModal"
class="fixed inset-0 z-50 hidden"
style="background: transparent"
>
<!-- Overlay Layer with dark background and blur -->
<div <div
class="modal-container h-full w-full flex items-start justify-center overflow-y-auto" class="absolute inset-0 z-10"
style="
background-color: rgba(0, 0, 0, 0.9);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
"
></div>
<!-- Modal Container -->
<div
class="relative modal-container h-full w-full flex items-start md:items-center justify-center overflow-y-auto z-20"
> >
<div <div
class="modal-content bg-gray-900 w-full max-w-sm my-8 rounded-lg overflow-hidden relative flex flex-col" class="modal-content bg-gray-900 w-full max-w-sm md:max-w-md my-0 rounded-lg overflow-hidden relative flex flex-col max-h-[90vh]"
> >
<!-- Modal Header --> <!-- Modal Header -->
<div <div

View File

@@ -1,10 +1,25 @@
<!-- components/upload-modal.html --> <!-- components/upload-modal.html -->
<div id="uploadModal" class="fixed inset-0 bg-black/90 z-50 hidden"> <div
id="uploadModal"
class="fixed inset-0 z-50 hidden"
style="background: transparent"
>
<!-- Overlay Layer with dark background and blur -->
<div <div
class="modal-container h-full w-full flex items-start justify-center overflow-y-auto" class="absolute inset-0 z-10"
style="
background-color: rgba(0, 0, 0, 0.9);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
"
></div>
<!-- Modal Container -->
<div
class="relative modal-container h-full w-full flex items-start md:items-center justify-center overflow-y-auto z-20"
> >
<div <div
class="modal-content bg-gray-900 w-full max-w-lg my-8 rounded-lg overflow-hidden relative" class="modal-content bg-gray-900 w-full max-w-lg md:max-w-2xl my-0 rounded-lg overflow-hidden relative max-h-[90vh]"
> >
<!-- Top Bar (similar to video-modal) --> <!-- Top Bar (similar to video-modal) -->
<div <div

Binary file not shown.

View File

@@ -89,12 +89,21 @@ header img {
#playerModal { #playerModal {
position: fixed; position: fixed;
inset: 0; inset: 0;
background-color: rgb(0 0 0 / 0.9); background-color: rgb(0 0 0 / 0.9); /* You can adjust opacity if needed */
z-index: 50; z-index: 50;
display: none; /* Hidden by default */ display: none; /* Hidden by default */
flex-direction: column; flex-direction: column;
overflow-y: auto; overflow-y: auto;
overscroll-behavior: contain; overscroll-behavior: contain;
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px); /* For Safari support */
}
#nostrFormModal,
#profileModal,
#uploadModal {
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px); /* For Safari */
} }
/* If you ever want to show it, add ".flex" class dynamically */ /* If you ever want to show it, add ".flex" class dynamically */

View File

@@ -38,7 +38,6 @@
<link href="css/tailwind.min.css" rel="stylesheet" /> <link href="css/tailwind.min.css" rel="stylesheet" />
<link href="css/style.css" rel="stylesheet" /> <link href="css/style.css" rel="stylesheet" />
</head> </head>
<body class="bg-gray-100"> <body class="bg-gray-100">
<div <div
id="app" id="app"
@@ -59,26 +58,26 @@
<button <button
id="loginButton" id="loginButton"
style="background-color: #fe0032" style="background-color: #fe0032"
class="inline-flex items-center justify-center w-12 h-12 rounded-full text-white text-sm font-bold leading-none whitespace-nowrap appearance-none hover:bg-[#e6002c] focus:outline-none focus:ring-2 focus:ring-black focus:ring-offset-2" class="inline-flex items-center justify-center w-12 h-12 rounded-full text-white text-sm font-bold leading-none hover:bg-[#e6002c] focus:outline-none focus:ring-2 focus:ring-black focus:ring-offset-2"
> >
NIP-07 login
</button> </button>
<!-- Upload (Add Video) Button --> <!-- Upload Button (hidden by default) -->
<button <button
id="uploadButton" id="uploadButton"
style="background-color: #fe0032" style="background-color: #fe0032"
class="inline-flex items-center justify-center w-12 h-12 rounded-full text-white text-xl font-bold leading-none whitespace-nowrap appearance-none hover:bg-[#e6002c] focus:outline-none focus:ring-2 focus:ring-black focus:ring-offset-2 hidden" class="hidden inline-flex items-center justify-center w-12 h-12 rounded-full text-white text-xl font-bold leading-none hover:bg-[#e6002c] focus:outline-none focus:ring-2 focus:ring-black focus:ring-offset-2"
> >
+ +
</button> </button>
<!-- Profile Button --> <!-- Profile Button (hidden by default) -->
<button <button
id="profileButton" id="profileButton"
class="inline-flex items-center justify-center w-12 h-12 rounded-full bg-black text-white text-sm leading-none hover:bg-neutral-800 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-black hidden" class="hidden inline-flex items-center justify-center w-12 h-12 rounded-full bg-black text-white text-sm leading-none hover:bg-neutral-800 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-black"
> >
<!-- Ensures a border around the smaller avatar --> <!-- This inner DIV is just an avatar container, if you like -->
<div class="w-10 h-10 rounded-full overflow-hidden"> <div class="w-10 h-10 rounded-full overflow-hidden">
<img <img
id="profileAvatar" id="profileAvatar"
@@ -95,24 +94,17 @@
<div <div
id="errorContainer" id="errorContainer"
class="hidden bg-red-100 text-red-900 p-4 rounded-md mb-4" class="hidden bg-red-100 text-red-900 p-4 rounded-md mb-4"
> ></div>
<!-- Error messages will appear here -->
</div>
<!-- Success Container --> <!-- Success Container -->
<div <div
id="successContainer" id="successContainer"
class="hidden bg-green-100 text-green-900 p-4 rounded-md mb-4" class="hidden bg-green-100 text-green-900 p-4 rounded-md mb-4"
> ></div>
<!-- Success messages will appear here -->
</div>
<!-- Main container for dynamic views --> <!-- Main container for dynamic views (most-recent-videos.html, etc.) -->
<main id="viewContainer" class="flex-grow mb-8"> <main id="viewContainer" class="flex-grow mb-8"></main>
<!-- We'll load "most-recent-videos.html" or other views here -->
</main>
<!-- Imported Video Player Modal (goes into modalContainer) --> <!-- Modal Container (external modals will be injected here) -->
<div id="modalContainer"></div> <div id="modalContainer"></div>
<!-- Tagline / Slogan --> <!-- Tagline / Slogan -->
@@ -122,7 +114,7 @@
</h2> </h2>
</div> </div>
<!-- Disclaimer Modal --> <!-- Disclaimer Modal (inline markup; adjust as needed) -->
<div id="disclaimerModal" class="hidden"> <div id="disclaimerModal" class="hidden">
<div class="modal-content"> <div class="modal-content">
<div class="modal-scroll"> <div class="modal-scroll">
@@ -133,11 +125,9 @@
class="h-16" class="h-16"
/> />
</div> </div>
<h2 class="text-2xl font-bold mb-4 text-center text-white"> <h2 class="text-2xl font-bold mb-4 text-center text-white">
Welcome to bitvid Welcome to bitvid
</h2> </h2>
<!-- Warning Alert --> <!-- Warning Alert -->
<div <div
class="bg-yellow-900/20 border border-yellow-700/50 rounded-lg p-4 mb-6 flex items-start" class="bg-yellow-900/20 border border-yellow-700/50 rounded-lg p-4 mb-6 flex items-start"
@@ -163,14 +153,12 @@
load initially. load initially.
</p> </p>
</div> </div>
<div class="space-y-6 text-gray-300"> <div class="space-y-6 text-gray-300">
<p> <p>
bitvid is a decentralized video platform where content is shared bitvid is a decentralized video platform where content is shared
directly between users. We want you to understand a few directly between users. We want you to understand a few
important points before you continue: important points before you continue:
</p> </p>
<div class="space-y-4"> <div class="space-y-4">
<div class="bg-gray-800 rounded-lg p-4"> <div class="bg-gray-800 rounded-lg p-4">
<h3 class="text-white font-semibold mb-2"> <h3 class="text-white font-semibold mb-2">
@@ -183,7 +171,6 @@
maintain quality content during our early stages. maintain quality content during our early stages.
</p> </p>
</div> </div>
<div class="bg-gray-800 rounded-lg p-4"> <div class="bg-gray-800 rounded-lg p-4">
<h3 class="text-white font-semibold mb-2"> <h3 class="text-white font-semibold mb-2">
Content Responsibility & Moderation Content Responsibility & Moderation
@@ -195,7 +182,6 @@
content must follow local laws and platform guidelines. content must follow local laws and platform guidelines.
</p> </p>
</div> </div>
<div class="bg-gray-800 rounded-lg p-4"> <div class="bg-gray-800 rounded-lg p-4">
<h3 class="text-white font-semibold mb-2">Platform Status</h3> <h3 class="text-white font-semibold mb-2">Platform Status</h3>
<p class="text-gray-400"> <p class="text-gray-400">
@@ -204,7 +190,6 @@
patience help us build a better platform. patience help us build a better platform.
</p> </p>
</div> </div>
<div class="bg-gray-800 rounded-lg p-4"> <div class="bg-gray-800 rounded-lg p-4">
<h3 class="text-white font-semibold mb-2">Get Involved</h3> <h3 class="text-white font-semibold mb-2">Get Involved</h3>
<p class="text-gray-400"> <p class="text-gray-400">
@@ -216,7 +201,6 @@
</div> </div>
</div> </div>
</div> </div>
<div class="button-container"> <div class="button-container">
<button <button
id="acceptDisclaimer" id="acceptDisclaimer"
@@ -339,6 +323,36 @@
</a> </a>
</p> </p>
</footer> </footer>
</div>
<!-- Load external modal components -->
<script>
async function loadModal(url) {
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error("Failed to load " + url);
}
const html = await response.text();
document
.getElementById("modalContainer")
.insertAdjacentHTML("beforeend", html);
console.log(url, "loaded");
} catch (err) {
console.error(err);
}
}
// Just load the login modal (or any others), without adding event listeners here.
// The logic to open/close the modal is all in app.js now.
Promise.all([
loadModal("components/login-modal.html"),
// e.g. loadModal("components/upload-modal.html"),
// loadModal("components/profile-modal.html"),
]).then(() => {
console.log("Modals loaded (login-modal.html, etc.)");
});
</script>
<!-- Scripts --> <!-- Scripts -->
<script src="js/libs/nostr.bundle.js"></script> <script src="js/libs/nostr.bundle.js"></script>
@@ -347,12 +361,7 @@
<script type="module" src="js/accessControl.js"></script> <script type="module" src="js/accessControl.js"></script>
<script type="module" src="js/webtorrent.js"></script> <script type="module" src="js/webtorrent.js"></script>
<script type="module" src="js/nostr.js"></script> <script type="module" src="js/nostr.js"></script>
<!-- Optional: a separate manager for view loading -->
<script type="module" src="js/viewManager.js"></script> <script type="module" src="js/viewManager.js"></script>
<!-- Main app script -->
<script type="module" src="js/app.js"></script> <script type="module" src="js/app.js"></script>
</div>
</body> </body>
</html> </html>

View File

@@ -70,17 +70,18 @@ class bitvidApp {
// Auth state // Auth state
this.pubkey = null; this.pubkey = null;
// Currently playing magnet
this.currentMagnetUri = null; this.currentMagnetUri = null;
// The active video object
this.currentVideo = null; this.currentVideo = null;
// Subscription reference (for unsubscribing)
this.videoSubscription = null; this.videoSubscription = null;
// Videos stored as a Map (key=event.id) // Videos stored as a Map (key=event.id)
this.videosMap = new Map(); this.videosMap = new Map();
// Simple cache for user profiles // Simple cache for user profiles
this.profileCache = new Map(); this.profileCache = new Map();
// NEW: reference to the login modal's close button
this.closeLoginModalBtn =
document.getElementById("closeLoginModal") || null;
} }
async init() { async init() {
@@ -107,7 +108,7 @@ class bitvidApp {
this.setupEventListeners(); this.setupEventListeners();
disclaimerModal.show(); disclaimerModal.show();
// 6. Load the default view // 6. Load the default view (most-recent-videos.html)
await loadView("views/most-recent-videos.html"); await loadView("views/most-recent-videos.html");
// 7. Once loaded, get a reference to #videoList // 7. Once loaded, get a reference to #videoList
@@ -119,8 +120,7 @@ class bitvidApp {
// 9. Check URL ?v= param // 9. Check URL ?v= param
this.checkUrlParams(); this.checkUrlParams();
// (Recommended) Keep an array of active interval IDs // Keep an array of active interval IDs so we can clear them on modal close
// so we can clear them when the modal closes:
this.activeIntervals = []; this.activeIntervals = [];
} catch (error) { } catch (error) {
console.error("Init failed:", error); console.error("Init failed:", error);
@@ -143,9 +143,13 @@ class bitvidApp {
if (!modalContainer) { if (!modalContainer) {
throw new Error("Modal container element not found!"); throw new Error("Modal container element not found!");
} }
modalContainer.innerHTML = html;
// Confirm we have a close button, etc. // Instead of overwriting, we append a new DIV with the fetched HTML
const wrapper = document.createElement("div");
wrapper.innerHTML = html; // set the markup
modalContainer.appendChild(wrapper); // append the markup
// Now we can safely find elements inside:
const closeButton = document.getElementById("closeModal"); const closeButton = document.getElementById("closeModal");
if (!closeButton) { if (!closeButton) {
throw new Error("Close button not found in video-modal!"); throw new Error("Close button not found in video-modal!");
@@ -353,29 +357,17 @@ class bitvidApp {
} }
/** /**
* Setup general event listeners for login, logout, modals, etc. * Setup general event listeners for logout, modals, etc.
*/ */
setupEventListeners() { setupEventListeners() {
// Login // 1) Logout button
if (this.loginButton) {
this.loginButton.addEventListener("click", async () => {
try {
const pubkey = await nostrClient.login();
this.login(pubkey, true);
} catch (err) {
this.showError("Failed to login. Please try again.");
}
});
}
// Logout
if (this.logoutButton) { if (this.logoutButton) {
this.logoutButton.addEventListener("click", () => { this.logoutButton.addEventListener("click", () => {
this.logout(); this.logout();
}); });
} }
// Profile button (if used) // 2) Profile button
if (this.profileButton) { if (this.profileButton) {
this.profileButton.addEventListener("click", () => { this.profileButton.addEventListener("click", () => {
if (this.profileModal) { if (this.profileModal) {
@@ -384,7 +376,7 @@ class bitvidApp {
}); });
} }
// Upload button => show upload modal // 3) Upload button => show upload modal
if (this.uploadButton) { if (this.uploadButton) {
this.uploadButton.addEventListener("click", () => { this.uploadButton.addEventListener("click", () => {
if (this.uploadModal) { if (this.uploadModal) {
@@ -393,12 +385,58 @@ class bitvidApp {
}); });
} }
// Cleanup on page unload // 4) Login button => show the login modal
if (this.loginButton) {
this.loginButton.addEventListener("click", () => {
console.log("Login button clicked!");
const loginModal = document.getElementById("loginModal");
if (loginModal) {
loginModal.classList.remove("hidden");
}
});
}
// 5) Close login modal button => hide modal
if (this.closeLoginModalBtn) {
this.closeLoginModalBtn.addEventListener("click", () => {
console.log("[app.js] closeLoginModal button clicked!");
const loginModal = document.getElementById("loginModal");
if (loginModal) {
loginModal.classList.add("hidden");
}
});
}
// 6) NIP-07 button inside the login modal => call the extension & login
const nip07Button = document.getElementById("loginNIP07");
if (nip07Button) {
nip07Button.addEventListener("click", async () => {
console.log(
"[app.js] loginNIP07 clicked! Attempting extension login..."
);
try {
const pubkey = await nostrClient.login(); // call the extension
console.log("[NIP-07] login returned pubkey:", pubkey);
this.login(pubkey, true);
// Hide the login modal
const loginModal = document.getElementById("loginModal");
if (loginModal) {
loginModal.classList.add("hidden");
}
} catch (err) {
console.error("[NIP-07 login error]", err);
this.showError("Failed to login with NIP-07. Please try again.");
}
});
}
// 7) Cleanup on page unload
window.addEventListener("beforeunload", async () => { window.addEventListener("beforeunload", async () => {
await this.cleanup(); await this.cleanup();
}); });
// Handle back/forward navigation => hide video modal // 8) Handle back/forward nav => hide video modal
window.addEventListener("popstate", async () => { window.addEventListener("popstate", async () => {
console.log("[popstate] user navigated back/forward; cleaning modal..."); console.log("[popstate] user navigated back/forward; cleaning modal...");
await this.hideModal(); await this.hideModal();
@@ -496,13 +534,16 @@ class bitvidApp {
* Called upon successful login. * Called upon successful login.
*/ */
login(pubkey, saveToStorage = true) { login(pubkey, saveToStorage = true) {
console.log("[app.js] login() called with pubkey =", pubkey);
this.pubkey = pubkey; this.pubkey = pubkey;
// Hide login button if present // Hide the login button if present
if (this.loginButton) { if (this.loginButton) {
this.loginButton.classList.add("hidden"); this.loginButton.classList.add("hidden");
} }
// We can hide logout or userStatus if we want (or they might not exist)
// Hide logout / userStatus if youre not using them
if (this.logoutButton) { if (this.logoutButton) {
this.logoutButton.classList.add("hidden"); this.logoutButton.classList.add("hidden");
} }
@@ -510,7 +551,7 @@ class bitvidApp {
this.userStatus.classList.add("hidden"); this.userStatus.classList.add("hidden");
} }
// Show the upload button, profile button, etc. // IMPORTANT: Unhide the Upload & Profile buttons
if (this.uploadButton) { if (this.uploadButton) {
this.uploadButton.classList.remove("hidden"); this.uploadButton.classList.remove("hidden");
} }
@@ -518,9 +559,10 @@ class bitvidApp {
this.profileButton.classList.remove("hidden"); this.profileButton.classList.remove("hidden");
} }
// If you want to fetch your own profile to update UI // Optionally load the user's own profile
this.loadOwnProfile(pubkey); this.loadOwnProfile(pubkey);
// Save pubkey in localStorage (if desired)
if (saveToStorage) { if (saveToStorage) {
localStorage.setItem("userPubKey", pubkey); localStorage.setItem("userPubKey", pubkey);
} }

1
whitelistform.txt Normal file
View File

@@ -0,0 +1 @@
<iframe src="https://formstr.app/#/f/naddr1qvzqqqr4mqpzpkha64cj06g8sk2hqgq0yn4gqalgxxsta7x8lmvy8jr7pqfm5l9yqy2hwumn8ghj7un9d3shjtnyv9kh2uewd9hj7qppvf5hganfvss9w6rfw3jkc6tnwssyzursd35kxct5d9hkugzxdaex6udmmth" height="700px" width="480px" frameborder="0" style="border-style:none;box-shadow:0px 0px 2px 2px rgba(0,0,0,0.2);" cellspacing="0" ></iframe>