Doctor appointment form
Book a clinic visit. The form asks for a time and a short reason, not a diagnosis.
هذا النموذج ليس سجلاً طبياً. لا ترسلوا التشخيصات أو نتائج الفحوص أو تفاصيل صحية أخرى لا يحتاجها الطلب. البيانات الصحية فئة خاصة بموجب اللائحة العامة لحماية البيانات (GDPR).
معاينة
شيفرة النموذج
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Doctor appointment form</title>
<style>
body { font-family: "Segoe UI", sans-serif; color: #12263a; margin: 0; background: #fff; }
main { max-width: 640px; margin: 0 auto; padding: 32px 20px 64px; }
h1 { font-size: 28px; font-weight: 650; letter-spacing: -0.02em; line-height: 1.2; }
h2 { font-size: 18px; margin: 18px 0 0; }
p { line-height: 1.5; }
form { display: grid; gap: 14px; position: relative; }
.field { display: grid; gap: 6px; }
label span, .check span { font-size: 14px; }
input, select, textarea { font: inherit; color: inherit; padding: 10px 12px; border: 1px solid #b4bdce; border-radius: 8px; width: 100%; box-sizing: border-box; background: #fff; }
textarea { min-height: 96px; }
.check { display: flex; gap: 8px; align-items: flex-start; }
.check input { width: auto; margin-top: 4px; }
button { background: #3c4ad8; color: #fff; border: 0; border-radius: 8px; padding: 12px 18px; font: inherit; cursor: pointer; }
.note { background: #fff6eb; padding: 12px 14px; border-radius: 8px; }
form [data-show-if] { display: none; }
form:has(select[name="visit_for"] option[value="child"]:checked) [data-show-if="visit_for"][data-show-equals="child"] { display: grid; }
</style>
</head>
<body>
<main>
<h1 data-i18n="title">Doctor appointment form</h1>
<p data-i18n="lede">Book a clinic visit. The form asks for a time and a short reason, not a diagnosis.</p>
<p class="note" data-i18n="disclaimer">This form is not a medical record. Do not send diagnoses, test results, or other health details you do not need for the request. Health data is a special category under the GDPR.</p>
<form id="fg-form" action="https://formgong.com/submit" method="POST" enctype="multipart/form-data" data-sitekey="">
<input type="hidden" name="access_key" value="fk_your_access_key">
<div aria-hidden="true" style="position:absolute;left:-10000px;width:1px;height:1px;overflow:hidden"><label>Leave this field empty<input name="botcheck" tabindex="-1" autocomplete="off"></label></div>
<section><h2 data-i18n="section.visit">Visit</h2>
<div class="field"><label for="fg-service"><span data-i18n="service">What do you need?</span></label><select id="fg-service" name="service" required><option value="">—</option><option value="consultation" data-i18n="service.consultation">Consultation</option><option value="follow_up" data-i18n="service.follow_up">Follow-up</option><option value="vaccination" data-i18n="service.vaccination">Vaccination</option><option value="diagnostics" data-i18n="service.diagnostics">Tests</option></select></div>
<div class="field"><label for="fg-preferred_date"><span data-i18n="preferred_date">Preferred date</span></label><input id="fg-preferred_date" name="preferred_date" type="date" required></div>
<div class="field"><label for="fg-preferred_time"><span data-i18n="preferred_time">Preferred time</span></label><select id="fg-preferred_time" name="preferred_time" required><option value="">—</option><option value="morning" data-i18n="preferred_time.morning">Morning</option><option value="afternoon" data-i18n="preferred_time.afternoon">Afternoon</option><option value="evening" data-i18n="preferred_time.evening">Evening</option></select></div>
<div class="field"><label for="fg-visit_for"><span data-i18n="visit_for">Who is the visit for?</span></label><select id="fg-visit_for" name="visit_for" required><option value="">—</option><option value="self" data-i18n="visit_for.self">Me</option><option value="child" data-i18n="visit_for.child">A child</option></select></div>
<div class="field" data-show-if="visit_for" data-show-equals="child"><label for="fg-child_name"><span data-i18n="child_name">Child's name</span></label><input id="fg-child_name" name="child_name" type="text" maxlength="80" autocomplete="name"></div></section>
<section><h2 data-i18n="section.contact">Contact</h2>
<div class="field"><label for="fg-name"><span data-i18n="name">Name</span></label><input id="fg-name" name="name" type="text" required maxlength="80" autocomplete="name"></div>
<div class="field"><label for="fg-email"><span data-i18n="email">Email</span></label><input id="fg-email" name="email" type="email" maxlength="120" autocomplete="email"></div>
<div class="field"><label for="fg-phone"><span data-i18n="phone">Phone</span></label><input id="fg-phone" name="phone" type="tel" required maxlength="40" autocomplete="tel"></div></section>
<section><h2 data-i18n="section.reason">Reason</h2>
<div class="field"><label for="fg-reason"><span data-i18n="reason">Short reason for the visit</span></label><textarea id="fg-reason" name="reason" required maxlength="500"></textarea></div></section>
<section><h2 data-i18n="section.consent">Consent</h2>
<div class="field"><label class="check"><input id="fg-consent_contact" name="consent_contact" type="checkbox" value="yes" required><span data-i18n="consent_contact">I agree to be contacted about this request.</span></label></div>
<div class="field"><label class="check"><input id="fg-consent_privacy" name="consent_privacy" type="checkbox" value="yes" required><span data-i18n="consent_privacy">I agree that these answers are stored so the request can be handled.</span></label></div></section>
<!-- Set data-sitekey on this form to YOUR_TURNSTILE_SITE_KEY. Required for attachments. -->
<div data-turnstile></div>
<button type="submit" data-i18n="submit">Send</button>
<p data-status role="status"></p>
</form>
</main>
<script type="application/json" id="fg-labels">{"uk":{"title":"Форма запису до лікаря","lede":"Запис на візит до клініки. Форма питає час і коротку причину, не діагноз.","submit":"Надіслати","thanks":"Надіслано. Дякуємо.","file_too_big":"До 3 файлів, по 5 MiB, разом до 10 MiB.","disclaimer":"Ця форма не є медичним записом. Не надсилайте діагнози, результати аналізів чи інші дані про здоров'я, без яких заявку не обробити. Дані про здоров'я — особлива категорія за GDPR.","section.visit":"Візит","service":"Що потрібно?","service.consultation":"Консультація","service.follow_up":"Повторний візит","service.vaccination":"Щеплення","service.diagnostics":"Обстеження","preferred_date":"Бажана дата","preferred_time":"Бажаний час","preferred_time.morning":"Ранок","preferred_time.afternoon":"День","preferred_time.evening":"Вечір","visit_for":"Для кого візит?","visit_for.self":"Для мене","visit_for.child":"Для дитини","child_name":"Ім'я дитини","section.contact":"Контакт","name":"Ім'я","email":"Електронна пошта","phone":"Телефон","section.reason":"Причина","reason":"Коротка причина візиту","section.consent":"Згода","consent_contact":"Погоджуюсь, щоб зі мною зв'язалися щодо цієї заявки.","consent_privacy":"Погоджуюсь, що ці відповіді зберігаються, щоб заявку можна було обробити."},"en":{"title":"Doctor appointment form","lede":"Book a clinic visit. The form asks for a time and a short reason, not a diagnosis.","submit":"Send","thanks":"Sent. Thank you.","file_too_big":"Up to 3 files, 5 MiB each and 10 MiB combined.","disclaimer":"This form is not a medical record. Do not send diagnoses, test results, or other health details you do not need for the request. Health data is a special category under the GDPR.","section.visit":"Visit","service":"What do you need?","service.consultation":"Consultation","service.follow_up":"Follow-up","service.vaccination":"Vaccination","service.diagnostics":"Tests","preferred_date":"Preferred date","preferred_time":"Preferred time","preferred_time.morning":"Morning","preferred_time.afternoon":"Afternoon","preferred_time.evening":"Evening","visit_for":"Who is the visit for?","visit_for.self":"Me","visit_for.child":"A child","child_name":"Child's name","section.contact":"Contact","name":"Name","email":"Email","phone":"Phone","section.reason":"Reason","reason":"Short reason for the visit","section.consent":"Consent","consent_contact":"I agree to be contacted about this request.","consent_privacy":"I agree that these answers are stored so the request can be handled."},"pl":{"title":"Formularz zapisu do lekarza","lede":"Zapis na wizytę. Formularz pyta o termin i krótki powód, nie o rozpoznanie.","submit":"Wyślij","thanks":"Wysłano. Dziękujemy.","file_too_big":"Do 3 plików, po 5 MiB, łącznie 10 MiB.","disclaimer":"Ten formularz nie jest dokumentacją medyczną. Nie wysyłaj rozpoznań, wyników badań ani innych danych o zdrowiu, które nie są potrzebne do obsługi zgłoszenia. Dane o zdrowiu to szczególna kategoria w RODO.","section.visit":"Wizyta","service":"Czego dotyczy wizyta?","service.consultation":"Konsultacja","service.follow_up":"Wizyta kontrolna","service.vaccination":"Szczepienie","service.diagnostics":"Badania","preferred_date":"Preferowana data","preferred_time":"Preferowana pora","preferred_time.morning":"Rano","preferred_time.afternoon":"Popołudnie","preferred_time.evening":"Wieczór","visit_for":"Dla kogo jest wizyta?","visit_for.self":"Dla mnie","visit_for.child":"Dla dziecka","child_name":"Imię dziecka","section.contact":"Kontakt","name":"Imię","email":"E-mail","phone":"Telefon","section.reason":"Powód","reason":"Krótki powód wizyty","section.consent":"Zgoda","consent_contact":"Zgadzam się na kontakt w sprawie tego zgłoszenia.","consent_privacy":"Zgadzam się, aby te odpowiedzi zostały zapisane w celu obsługi zgłoszenia."},"tr":{"title":"Doktor randevu formu","lede":"Klinik ziyareti için randevu. Form saat ve kısa bir neden sorar, tanı değil.","submit":"Gönder","thanks":"Gönderildi. Teşekkürler.","file_too_big":"En fazla 3 dosya, dosya başına 5 MiB, toplam 10 MiB.","disclaimer":"Bu form bir tıbbi kayıt değildir. Tanı, tahlil sonucu veya talep için gerekmeyen başka sağlık verisi göndermeyin. Sağlık verisi GDPR'de özel nitelikli veridir.","section.visit":"Ziyaret","service":"Ne için geliyorsunuz?","service.consultation":"Muayene","service.follow_up":"Kontrol","service.vaccination":"Aşı","service.diagnostics":"Tetkik","preferred_date":"Tercih edilen tarih","preferred_time":"Tercih edilen saat","preferred_time.morning":"Sabah","preferred_time.afternoon":"Öğleden sonra","preferred_time.evening":"Akşam","visit_for":"Randevu kimin için?","visit_for.self":"Benim için","visit_for.child":"Çocuk için","child_name":"Çocuğun adı","section.contact":"İletişim","name":"Ad","email":"E-posta","phone":"Telefon","section.reason":"Neden","reason":"Ziyaretin kısa nedeni","section.consent":"Onay","consent_contact":"Bu talep hakkında benimle iletişime geçilmesini kabul ediyorum.","consent_privacy":"Bu yanıtların talebin işlenmesi için saklanmasını kabul ediyorum."}}</script>
<script>
function mountCaptcha(node, siteKey) {
if (!node || !siteKey) return () => {};
let disposed = false;
let widget;
function render() {
if (disposed || !window.turnstile) return;
window.turnstile.ready(() => {
if (disposed) return;
widget = window.turnstile.render(node, { sitekey: siteKey });
node.dataset.widgetId = widget;
});
}
if (window.turnstile) render();
else {
let script = document.querySelector('script[src^="https://challenges.cloudflare.com/turnstile/v0/api.js"]');
if (!script) {
script = document.createElement("script");
script.src = "https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit";
script.async = true;
document.head.appendChild(script);
}
script.addEventListener("load", render, { once: true });
}
return () => { disposed = true; if (widget !== undefined) window.turnstile?.remove(widget); };
}
function resetCaptcha(form) {
const widget = form.querySelector("[data-turnstile]")?.dataset.widgetId;
if (widget !== undefined) window.turnstile?.reset(widget);
}
(function () {
var MAX = 5242880;
var form = document.getElementById("fg-form");
var packNode = document.getElementById("fg-labels");
if (!form || !packNode) return;
var pack = JSON.parse(packNode.textContent);
function code() {
var q = new URLSearchParams(location.search).get("lang") || "";
var raw = (q || document.documentElement.lang || (navigator.language || "en")).slice(0, 2).toLowerCase();
return pack[raw] ? raw : "en";
}
function apply() {
var dict = pack[code()];
document.querySelectorAll("[data-i18n]").forEach(function (node) {
var key = node.getAttribute("data-i18n");
if (key && typeof dict[key] === "string") node.textContent = dict[key];
});
}
apply();
var status = form.querySelector("[data-status]");
form.addEventListener("submit", function (event) {
event.preventDefault();
var dict = pack[code()];
var body = new FormData(form);
var files = Array.from(body.values()).filter(function (value) { return value instanceof File && value.size; });
if (files.length > 3 || files.some(function (file) { return file.size > MAX; }) || files.reduce(function (sum,file) { return sum + file.size; },0) > 10 * 1024 * 1024) {
if (status) status.textContent = dict.file_too_big;
return;
}
var button = form.querySelector("button[type=submit]");
if (button) button.disabled = true;
fetch(form.action, { method: "POST", headers: { Accept: "application/json" }, body: body })
.then(function (response) { return response.json(); }).then(function (result) {
if (status) status.textContent = result && result.success ? dict.thanks : ((result && result.message) || "error");
}).catch(function () { if (status) status.textContent = "error"; })
.finally(function () { if (button) button.disabled = false; resetCaptcha(form); });
});
mountCaptcha(form.querySelector("[data-turnstile]"), form.dataset.sitekey);
})();
</script>
</body>
</html>
// Generated from src/content/industries.ts — npm run templates:write
import { useState, useEffect, useRef } from "react";
const ENDPOINT = "https://formgong.com/submit";
const FILE_MAX = 5242880;
const LABELS = {
"uk": {
"title": "Форма запису до лікаря",
"lede": "Запис на візит до клініки. Форма питає час і коротку причину, не діагноз.",
"submit": "Надіслати",
"thanks": "Надіслано. Дякуємо.",
"file_too_big": "До 3 файлів, по 5 MiB, разом до 10 MiB.",
"disclaimer": "Ця форма не є медичним записом. Не надсилайте діагнози, результати аналізів чи інші дані про здоров'я, без яких заявку не обробити. Дані про здоров'я — особлива категорія за GDPR.",
"section.visit": "Візит",
"service": "Що потрібно?",
"service.consultation": "Консультація",
"service.follow_up": "Повторний візит",
"service.vaccination": "Щеплення",
"service.diagnostics": "Обстеження",
"preferred_date": "Бажана дата",
"preferred_time": "Бажаний час",
"preferred_time.morning": "Ранок",
"preferred_time.afternoon": "День",
"preferred_time.evening": "Вечір",
"visit_for": "Для кого візит?",
"visit_for.self": "Для мене",
"visit_for.child": "Для дитини",
"child_name": "Ім'я дитини",
"section.contact": "Контакт",
"name": "Ім'я",
"email": "Електронна пошта",
"phone": "Телефон",
"section.reason": "Причина",
"reason": "Коротка причина візиту",
"section.consent": "Згода",
"consent_contact": "Погоджуюсь, щоб зі мною зв'язалися щодо цієї заявки.",
"consent_privacy": "Погоджуюсь, що ці відповіді зберігаються, щоб заявку можна було обробити."
},
"en": {
"title": "Doctor appointment form",
"lede": "Book a clinic visit. The form asks for a time and a short reason, not a diagnosis.",
"submit": "Send",
"thanks": "Sent. Thank you.",
"file_too_big": "Up to 3 files, 5 MiB each and 10 MiB combined.",
"disclaimer": "This form is not a medical record. Do not send diagnoses, test results, or other health details you do not need for the request. Health data is a special category under the GDPR.",
"section.visit": "Visit",
"service": "What do you need?",
"service.consultation": "Consultation",
"service.follow_up": "Follow-up",
"service.vaccination": "Vaccination",
"service.diagnostics": "Tests",
"preferred_date": "Preferred date",
"preferred_time": "Preferred time",
"preferred_time.morning": "Morning",
"preferred_time.afternoon": "Afternoon",
"preferred_time.evening": "Evening",
"visit_for": "Who is the visit for?",
"visit_for.self": "Me",
"visit_for.child": "A child",
"child_name": "Child's name",
"section.contact": "Contact",
"name": "Name",
"email": "Email",
"phone": "Phone",
"section.reason": "Reason",
"reason": "Short reason for the visit",
"section.consent": "Consent",
"consent_contact": "I agree to be contacted about this request.",
"consent_privacy": "I agree that these answers are stored so the request can be handled."
},
"pl": {
"title": "Formularz zapisu do lekarza",
"lede": "Zapis na wizytę. Formularz pyta o termin i krótki powód, nie o rozpoznanie.",
"submit": "Wyślij",
"thanks": "Wysłano. Dziękujemy.",
"file_too_big": "Do 3 plików, po 5 MiB, łącznie 10 MiB.",
"disclaimer": "Ten formularz nie jest dokumentacją medyczną. Nie wysyłaj rozpoznań, wyników badań ani innych danych o zdrowiu, które nie są potrzebne do obsługi zgłoszenia. Dane o zdrowiu to szczególna kategoria w RODO.",
"section.visit": "Wizyta",
"service": "Czego dotyczy wizyta?",
"service.consultation": "Konsultacja",
"service.follow_up": "Wizyta kontrolna",
"service.vaccination": "Szczepienie",
"service.diagnostics": "Badania",
"preferred_date": "Preferowana data",
"preferred_time": "Preferowana pora",
"preferred_time.morning": "Rano",
"preferred_time.afternoon": "Popołudnie",
"preferred_time.evening": "Wieczór",
"visit_for": "Dla kogo jest wizyta?",
"visit_for.self": "Dla mnie",
"visit_for.child": "Dla dziecka",
"child_name": "Imię dziecka",
"section.contact": "Kontakt",
"name": "Imię",
"email": "E-mail",
"phone": "Telefon",
"section.reason": "Powód",
"reason": "Krótki powód wizyty",
"section.consent": "Zgoda",
"consent_contact": "Zgadzam się na kontakt w sprawie tego zgłoszenia.",
"consent_privacy": "Zgadzam się, aby te odpowiedzi zostały zapisane w celu obsługi zgłoszenia."
},
"tr": {
"title": "Doktor randevu formu",
"lede": "Klinik ziyareti için randevu. Form saat ve kısa bir neden sorar, tanı değil.",
"submit": "Gönder",
"thanks": "Gönderildi. Teşekkürler.",
"file_too_big": "En fazla 3 dosya, dosya başına 5 MiB, toplam 10 MiB.",
"disclaimer": "Bu form bir tıbbi kayıt değildir. Tanı, tahlil sonucu veya talep için gerekmeyen başka sağlık verisi göndermeyin. Sağlık verisi GDPR'de özel nitelikli veridir.",
"section.visit": "Ziyaret",
"service": "Ne için geliyorsunuz?",
"service.consultation": "Muayene",
"service.follow_up": "Kontrol",
"service.vaccination": "Aşı",
"service.diagnostics": "Tetkik",
"preferred_date": "Tercih edilen tarih",
"preferred_time": "Tercih edilen saat",
"preferred_time.morning": "Sabah",
"preferred_time.afternoon": "Öğleden sonra",
"preferred_time.evening": "Akşam",
"visit_for": "Randevu kimin için?",
"visit_for.self": "Benim için",
"visit_for.child": "Çocuk için",
"child_name": "Çocuğun adı",
"section.contact": "İletişim",
"name": "Ad",
"email": "E-posta",
"phone": "Telefon",
"section.reason": "Neden",
"reason": "Ziyaretin kısa nedeni",
"section.consent": "Onay",
"consent_contact": "Bu talep hakkında benimle iletişime geçilmesini kabul ediyorum.",
"consent_privacy": "Bu yanıtların talebin işlenmesi için saklanmasını kabul ediyorum."
}
};
export function IndustryForm({ lang = "en", accessKey = "fk_your_access_key", turnstileSiteKey = "" }) {
const t = LABELS[lang] || LABELS.en;
const [status, setStatus] = useState("");
const captcha = useRef(null);
useEffect(() => mountCaptcha(captcha.current, turnstileSiteKey), [turnstileSiteKey]);
const [values, setValues] = useState({ visit_for: "" });
function setField(name, value) {
setValues((current) => ({ ...current, [name]: value }));
}
async function onSubmit(event) {
const form = event.currentTarget;
event.preventDefault();
const body = new FormData(form);
const files = Array.from(body.values()).filter(value => value instanceof File && value.size);
if (files.length > 3 || files.some(file => file.size > FILE_MAX) || files.reduce((sum,file) => sum + file.size,0) > 10 * 1024 * 1024) {
setStatus(t.file_too_big);
return;
}
const button = form.querySelector("button[type=submit]");
if (button) button.disabled = true;
try {
const response = await fetch(ENDPOINT, { method: "POST", headers: { Accept: "application/json" }, body });
const result = await response.json();
setStatus(result.success ? t.thanks : (result.message || "error"));
} catch { setStatus("error"); }
finally { if (button) button.disabled = false; resetCaptcha(form); }
}
return (
<form onSubmit={onSubmit}>
<h1>{t.title}</h1>
<p>{t.lede}</p>
{t.disclaimer ? <p>{t.disclaimer}</p> : null}
<input type="hidden" name="access_key" value={accessKey} />
<div aria-hidden="true" style={{ position: "absolute", left: "-10000px", width: 1, height: 1, overflow: "hidden" }}>
<input name="botcheck" tabIndex={-1} autoComplete="off" />
</div>
<section><h2>{t["section.visit"]}</h2>
<label><span>{t["service"]}</span><select name="service" required><option value="">—</option><option value="consultation">{t["service.consultation"]}</option><option value="follow_up">{t["service.follow_up"]}</option><option value="vaccination">{t["service.vaccination"]}</option><option value="diagnostics">{t["service.diagnostics"]}</option></select></label>
<label><span>{t["preferred_date"]}</span><input name="preferred_date" type="date" required /></label>
<label><span>{t["preferred_time"]}</span><select name="preferred_time" required><option value="">—</option><option value="morning">{t["preferred_time.morning"]}</option><option value="afternoon">{t["preferred_time.afternoon"]}</option><option value="evening">{t["preferred_time.evening"]}</option></select></label>
<label><span>{t["visit_for"]}</span><select name="visit_for" required value={values["visit_for"]} onChange={(event) => setField("visit_for", event.target.value)}><option value="">—</option><option value="self">{t["visit_for.self"]}</option><option value="child">{t["visit_for.child"]}</option></select></label>
{values["visit_for"] === "child" ? (<label><span>{t["child_name"]}</span><input name="child_name" type="text" maxLength={80} autoComplete="name" /></label>) : null}</section>
<section><h2>{t["section.contact"]}</h2>
<label><span>{t["name"]}</span><input name="name" type="text" required maxLength={80} autoComplete="name" /></label>
<label><span>{t["email"]}</span><input name="email" type="email" maxLength={120} autoComplete="email" /></label>
<label><span>{t["phone"]}</span><input name="phone" type="tel" required maxLength={40} autoComplete="tel" /></label></section>
<section><h2>{t["section.reason"]}</h2>
<label><span>{t["reason"]}</span><textarea name="reason" required maxLength={500} /></label></section>
<section><h2>{t["section.consent"]}</h2>
<label className="check"><input name="consent_contact" type="checkbox" value="yes" required /><span>{t["consent_contact"]}</span></label>
<label className="check"><input name="consent_privacy" type="checkbox" value="yes" required /><span>{t["consent_privacy"]}</span></label></section>
{/* Set turnstileSiteKey to YOUR_TURNSTILE_SITE_KEY. Required for attachments. */}
<div ref={captcha} data-turnstile />
<button type="submit">{t.submit}</button>
<p>{status}</p>
</form>
);
}
function mountCaptcha(node, siteKey) {
if (!node || !siteKey) return () => {};
let disposed = false;
let widget;
function render() {
if (disposed || !window.turnstile) return;
window.turnstile.ready(() => {
if (disposed) return;
widget = window.turnstile.render(node, { sitekey: siteKey });
node.dataset.widgetId = widget;
});
}
if (window.turnstile) render();
else {
let script = document.querySelector('script[src^="https://challenges.cloudflare.com/turnstile/v0/api.js"]');
if (!script) {
script = document.createElement("script");
script.src = "https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit";
script.async = true;
document.head.appendChild(script);
}
script.addEventListener("load", render, { once: true });
}
return () => { disposed = true; if (widget !== undefined) window.turnstile?.remove(widget); };
}
function resetCaptcha(form) {
const widget = form.querySelector("[data-turnstile]")?.dataset.widgetId;
if (widget !== undefined) window.turnstile?.reset(widget);
}
<!-- Generated from src/content/industries.ts — npm run templates:write -->
<script setup>
import { reactive, ref, computed, onMounted, onBeforeUnmount } from "vue";
const props = defineProps({
lang: { type: String, default: "en" },
accessKey: { type: String, default: "fk_your_access_key" },
turnstileSiteKey: { type: String, default: "" },
});
const ENDPOINT = "https://formgong.com/submit";
const FILE_MAX = 5242880;
const LABELS = {
"uk": {
"title": "Форма запису до лікаря",
"lede": "Запис на візит до клініки. Форма питає час і коротку причину, не діагноз.",
"submit": "Надіслати",
"thanks": "Надіслано. Дякуємо.",
"file_too_big": "До 3 файлів, по 5 MiB, разом до 10 MiB.",
"disclaimer": "Ця форма не є медичним записом. Не надсилайте діагнози, результати аналізів чи інші дані про здоров'я, без яких заявку не обробити. Дані про здоров'я — особлива категорія за GDPR.",
"section.visit": "Візит",
"service": "Що потрібно?",
"service.consultation": "Консультація",
"service.follow_up": "Повторний візит",
"service.vaccination": "Щеплення",
"service.diagnostics": "Обстеження",
"preferred_date": "Бажана дата",
"preferred_time": "Бажаний час",
"preferred_time.morning": "Ранок",
"preferred_time.afternoon": "День",
"preferred_time.evening": "Вечір",
"visit_for": "Для кого візит?",
"visit_for.self": "Для мене",
"visit_for.child": "Для дитини",
"child_name": "Ім'я дитини",
"section.contact": "Контакт",
"name": "Ім'я",
"email": "Електронна пошта",
"phone": "Телефон",
"section.reason": "Причина",
"reason": "Коротка причина візиту",
"section.consent": "Згода",
"consent_contact": "Погоджуюсь, щоб зі мною зв'язалися щодо цієї заявки.",
"consent_privacy": "Погоджуюсь, що ці відповіді зберігаються, щоб заявку можна було обробити."
},
"en": {
"title": "Doctor appointment form",
"lede": "Book a clinic visit. The form asks for a time and a short reason, not a diagnosis.",
"submit": "Send",
"thanks": "Sent. Thank you.",
"file_too_big": "Up to 3 files, 5 MiB each and 10 MiB combined.",
"disclaimer": "This form is not a medical record. Do not send diagnoses, test results, or other health details you do not need for the request. Health data is a special category under the GDPR.",
"section.visit": "Visit",
"service": "What do you need?",
"service.consultation": "Consultation",
"service.follow_up": "Follow-up",
"service.vaccination": "Vaccination",
"service.diagnostics": "Tests",
"preferred_date": "Preferred date",
"preferred_time": "Preferred time",
"preferred_time.morning": "Morning",
"preferred_time.afternoon": "Afternoon",
"preferred_time.evening": "Evening",
"visit_for": "Who is the visit for?",
"visit_for.self": "Me",
"visit_for.child": "A child",
"child_name": "Child's name",
"section.contact": "Contact",
"name": "Name",
"email": "Email",
"phone": "Phone",
"section.reason": "Reason",
"reason": "Short reason for the visit",
"section.consent": "Consent",
"consent_contact": "I agree to be contacted about this request.",
"consent_privacy": "I agree that these answers are stored so the request can be handled."
},
"pl": {
"title": "Formularz zapisu do lekarza",
"lede": "Zapis na wizytę. Formularz pyta o termin i krótki powód, nie o rozpoznanie.",
"submit": "Wyślij",
"thanks": "Wysłano. Dziękujemy.",
"file_too_big": "Do 3 plików, po 5 MiB, łącznie 10 MiB.",
"disclaimer": "Ten formularz nie jest dokumentacją medyczną. Nie wysyłaj rozpoznań, wyników badań ani innych danych o zdrowiu, które nie są potrzebne do obsługi zgłoszenia. Dane o zdrowiu to szczególna kategoria w RODO.",
"section.visit": "Wizyta",
"service": "Czego dotyczy wizyta?",
"service.consultation": "Konsultacja",
"service.follow_up": "Wizyta kontrolna",
"service.vaccination": "Szczepienie",
"service.diagnostics": "Badania",
"preferred_date": "Preferowana data",
"preferred_time": "Preferowana pora",
"preferred_time.morning": "Rano",
"preferred_time.afternoon": "Popołudnie",
"preferred_time.evening": "Wieczór",
"visit_for": "Dla kogo jest wizyta?",
"visit_for.self": "Dla mnie",
"visit_for.child": "Dla dziecka",
"child_name": "Imię dziecka",
"section.contact": "Kontakt",
"name": "Imię",
"email": "E-mail",
"phone": "Telefon",
"section.reason": "Powód",
"reason": "Krótki powód wizyty",
"section.consent": "Zgoda",
"consent_contact": "Zgadzam się na kontakt w sprawie tego zgłoszenia.",
"consent_privacy": "Zgadzam się, aby te odpowiedzi zostały zapisane w celu obsługi zgłoszenia."
},
"tr": {
"title": "Doktor randevu formu",
"lede": "Klinik ziyareti için randevu. Form saat ve kısa bir neden sorar, tanı değil.",
"submit": "Gönder",
"thanks": "Gönderildi. Teşekkürler.",
"file_too_big": "En fazla 3 dosya, dosya başına 5 MiB, toplam 10 MiB.",
"disclaimer": "Bu form bir tıbbi kayıt değildir. Tanı, tahlil sonucu veya talep için gerekmeyen başka sağlık verisi göndermeyin. Sağlık verisi GDPR'de özel nitelikli veridir.",
"section.visit": "Ziyaret",
"service": "Ne için geliyorsunuz?",
"service.consultation": "Muayene",
"service.follow_up": "Kontrol",
"service.vaccination": "Aşı",
"service.diagnostics": "Tetkik",
"preferred_date": "Tercih edilen tarih",
"preferred_time": "Tercih edilen saat",
"preferred_time.morning": "Sabah",
"preferred_time.afternoon": "Öğleden sonra",
"preferred_time.evening": "Akşam",
"visit_for": "Randevu kimin için?",
"visit_for.self": "Benim için",
"visit_for.child": "Çocuk için",
"child_name": "Çocuğun adı",
"section.contact": "İletişim",
"name": "Ad",
"email": "E-posta",
"phone": "Telefon",
"section.reason": "Neden",
"reason": "Ziyaretin kısa nedeni",
"section.consent": "Onay",
"consent_contact": "Bu talep hakkında benimle iletişime geçilmesini kabul ediyorum.",
"consent_privacy": "Bu yanıtların talebin işlenmesi için saklanmasını kabul ediyorum."
}
};
const t = computed(() => LABELS[props.lang] || LABELS.en);
const status = ref("");
const captcha = ref(null);
let disposeCaptcha;
onMounted(() => { disposeCaptcha = mountCaptcha(captcha.value, props.turnstileSiteKey); });
onBeforeUnmount(() => disposeCaptcha?.());
const values = reactive({ visit_for: "" });
function mountCaptcha(node, siteKey) {
if (!node || !siteKey) return () => {};
let disposed = false;
let widget;
function render() {
if (disposed || !window.turnstile) return;
window.turnstile.ready(() => {
if (disposed) return;
widget = window.turnstile.render(node, { sitekey: siteKey });
node.dataset.widgetId = widget;
});
}
if (window.turnstile) render();
else {
let script = document.querySelector('script[src^="https://challenges.cloudflare.com/turnstile/v0/api.js"]');
if (!script) {
script = document.createElement("script");
script.src = "https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit";
script.async = true;
document.head.appendChild(script);
}
script.addEventListener("load", render, { once: true });
}
return () => { disposed = true; if (widget !== undefined) window.turnstile?.remove(widget); };
}
function resetCaptcha(form) {
const widget = form.querySelector("[data-turnstile]")?.dataset.widgetId;
if (widget !== undefined) window.turnstile?.reset(widget);
}
async function onSubmit(event) {
const form = event.currentTarget;
event.preventDefault();
const body = new FormData(form);
const files = Array.from(body.values()).filter(value => value instanceof File && value.size);
if (files.length > 3 || files.some(file => file.size > FILE_MAX) || files.reduce((sum,file) => sum + file.size,0) > 10 * 1024 * 1024) {
status.value = t.value.file_too_big;
return;
}
const button = form.querySelector("button[type=submit]");
if (button) button.disabled = true;
try {
const response = await fetch(ENDPOINT, { method: "POST", headers: { Accept: "application/json" }, body });
const result = await response.json();
status.value = result.success ? t.value.thanks : (result.message || "error");
} catch { status.value = "error"; }
finally { if (button) button.disabled = false; resetCaptcha(form); }
}
</script>
<template>
<form @submit.prevent="onSubmit">
<h1>{{ t.title }}</h1>
<p>{{ t.lede }}</p>
<p v-if="t.disclaimer">{{ t.disclaimer }}</p>
<input type="hidden" name="access_key" :value="accessKey">
<div aria-hidden="true" style="position:absolute;left:-10000px;width:1px;height:1px;overflow:hidden">
<input name="botcheck" tabindex="-1" autocomplete="off">
</div>
<section><h2>{{ t["section.visit"] }}</h2>
<label><span>{{ t["service"] }}</span><select name="service" required><option value="">—</option><option value="consultation">{{ t["service.consultation"] }}</option><option value="follow_up">{{ t["service.follow_up"] }}</option><option value="vaccination">{{ t["service.vaccination"] }}</option><option value="diagnostics">{{ t["service.diagnostics"] }}</option></select></label>
<label><span>{{ t["preferred_date"] }}</span><input name="preferred_date" type="date" required></label>
<label><span>{{ t["preferred_time"] }}</span><select name="preferred_time" required><option value="">—</option><option value="morning">{{ t["preferred_time.morning"] }}</option><option value="afternoon">{{ t["preferred_time.afternoon"] }}</option><option value="evening">{{ t["preferred_time.evening"] }}</option></select></label>
<label><span>{{ t["visit_for"] }}</span><select name="visit_for" required v-model="values.visit_for"><option value="">—</option><option value="self">{{ t["visit_for.self"] }}</option><option value="child">{{ t["visit_for.child"] }}</option></select></label>
<template v-if="values["visit_for"] === 'child'"><label><span>{{ t["child_name"] }}</span><input name="child_name" type="text" maxlength="80" autocomplete="name"></label></template></section>
<section><h2>{{ t["section.contact"] }}</h2>
<label><span>{{ t["name"] }}</span><input name="name" type="text" required maxlength="80" autocomplete="name"></label>
<label><span>{{ t["email"] }}</span><input name="email" type="email" maxlength="120" autocomplete="email"></label>
<label><span>{{ t["phone"] }}</span><input name="phone" type="tel" required maxlength="40" autocomplete="tel"></label></section>
<section><h2>{{ t["section.reason"] }}</h2>
<label><span>{{ t["reason"] }}</span><textarea name="reason" required maxlength="500"></textarea></label></section>
<section><h2>{{ t["section.consent"] }}</h2>
<label class="check"><input name="consent_contact" type="checkbox" value="yes" required><span>{{ t["consent_contact"] }}</span></label>
<label class="check"><input name="consent_privacy" type="checkbox" value="yes" required><span>{{ t["consent_privacy"] }}</span></label></section>
<!-- Set turnstileSiteKey to YOUR_TURNSTILE_SITE_KEY. Required for attachments. -->
<div ref="captcha" data-turnstile></div>
<button type="submit">{{ t.submit }}</button>
<p>{{ status }}</p>
</form>
</template>
<!-- Generated from src/content/industries.ts — npm run templates:write -->
<script>
import { onMount } from "svelte";
let { lang = "en", accessKey = "fk_your_access_key", turnstileSiteKey = "" } = $props();
let captcha;
onMount(() => mountCaptcha(captcha, turnstileSiteKey));
const ENDPOINT = "https://formgong.com/submit";
const FILE_MAX = 5242880;
const LABELS = {
"uk": {
"title": "Форма запису до лікаря",
"lede": "Запис на візит до клініки. Форма питає час і коротку причину, не діагноз.",
"submit": "Надіслати",
"thanks": "Надіслано. Дякуємо.",
"file_too_big": "До 3 файлів, по 5 MiB, разом до 10 MiB.",
"disclaimer": "Ця форма не є медичним записом. Не надсилайте діагнози, результати аналізів чи інші дані про здоров'я, без яких заявку не обробити. Дані про здоров'я — особлива категорія за GDPR.",
"section.visit": "Візит",
"service": "Що потрібно?",
"service.consultation": "Консультація",
"service.follow_up": "Повторний візит",
"service.vaccination": "Щеплення",
"service.diagnostics": "Обстеження",
"preferred_date": "Бажана дата",
"preferred_time": "Бажаний час",
"preferred_time.morning": "Ранок",
"preferred_time.afternoon": "День",
"preferred_time.evening": "Вечір",
"visit_for": "Для кого візит?",
"visit_for.self": "Для мене",
"visit_for.child": "Для дитини",
"child_name": "Ім'я дитини",
"section.contact": "Контакт",
"name": "Ім'я",
"email": "Електронна пошта",
"phone": "Телефон",
"section.reason": "Причина",
"reason": "Коротка причина візиту",
"section.consent": "Згода",
"consent_contact": "Погоджуюсь, щоб зі мною зв'язалися щодо цієї заявки.",
"consent_privacy": "Погоджуюсь, що ці відповіді зберігаються, щоб заявку можна було обробити."
},
"en": {
"title": "Doctor appointment form",
"lede": "Book a clinic visit. The form asks for a time and a short reason, not a diagnosis.",
"submit": "Send",
"thanks": "Sent. Thank you.",
"file_too_big": "Up to 3 files, 5 MiB each and 10 MiB combined.",
"disclaimer": "This form is not a medical record. Do not send diagnoses, test results, or other health details you do not need for the request. Health data is a special category under the GDPR.",
"section.visit": "Visit",
"service": "What do you need?",
"service.consultation": "Consultation",
"service.follow_up": "Follow-up",
"service.vaccination": "Vaccination",
"service.diagnostics": "Tests",
"preferred_date": "Preferred date",
"preferred_time": "Preferred time",
"preferred_time.morning": "Morning",
"preferred_time.afternoon": "Afternoon",
"preferred_time.evening": "Evening",
"visit_for": "Who is the visit for?",
"visit_for.self": "Me",
"visit_for.child": "A child",
"child_name": "Child's name",
"section.contact": "Contact",
"name": "Name",
"email": "Email",
"phone": "Phone",
"section.reason": "Reason",
"reason": "Short reason for the visit",
"section.consent": "Consent",
"consent_contact": "I agree to be contacted about this request.",
"consent_privacy": "I agree that these answers are stored so the request can be handled."
},
"pl": {
"title": "Formularz zapisu do lekarza",
"lede": "Zapis na wizytę. Formularz pyta o termin i krótki powód, nie o rozpoznanie.",
"submit": "Wyślij",
"thanks": "Wysłano. Dziękujemy.",
"file_too_big": "Do 3 plików, po 5 MiB, łącznie 10 MiB.",
"disclaimer": "Ten formularz nie jest dokumentacją medyczną. Nie wysyłaj rozpoznań, wyników badań ani innych danych o zdrowiu, które nie są potrzebne do obsługi zgłoszenia. Dane o zdrowiu to szczególna kategoria w RODO.",
"section.visit": "Wizyta",
"service": "Czego dotyczy wizyta?",
"service.consultation": "Konsultacja",
"service.follow_up": "Wizyta kontrolna",
"service.vaccination": "Szczepienie",
"service.diagnostics": "Badania",
"preferred_date": "Preferowana data",
"preferred_time": "Preferowana pora",
"preferred_time.morning": "Rano",
"preferred_time.afternoon": "Popołudnie",
"preferred_time.evening": "Wieczór",
"visit_for": "Dla kogo jest wizyta?",
"visit_for.self": "Dla mnie",
"visit_for.child": "Dla dziecka",
"child_name": "Imię dziecka",
"section.contact": "Kontakt",
"name": "Imię",
"email": "E-mail",
"phone": "Telefon",
"section.reason": "Powód",
"reason": "Krótki powód wizyty",
"section.consent": "Zgoda",
"consent_contact": "Zgadzam się na kontakt w sprawie tego zgłoszenia.",
"consent_privacy": "Zgadzam się, aby te odpowiedzi zostały zapisane w celu obsługi zgłoszenia."
},
"tr": {
"title": "Doktor randevu formu",
"lede": "Klinik ziyareti için randevu. Form saat ve kısa bir neden sorar, tanı değil.",
"submit": "Gönder",
"thanks": "Gönderildi. Teşekkürler.",
"file_too_big": "En fazla 3 dosya, dosya başına 5 MiB, toplam 10 MiB.",
"disclaimer": "Bu form bir tıbbi kayıt değildir. Tanı, tahlil sonucu veya talep için gerekmeyen başka sağlık verisi göndermeyin. Sağlık verisi GDPR'de özel nitelikli veridir.",
"section.visit": "Ziyaret",
"service": "Ne için geliyorsunuz?",
"service.consultation": "Muayene",
"service.follow_up": "Kontrol",
"service.vaccination": "Aşı",
"service.diagnostics": "Tetkik",
"preferred_date": "Tercih edilen tarih",
"preferred_time": "Tercih edilen saat",
"preferred_time.morning": "Sabah",
"preferred_time.afternoon": "Öğleden sonra",
"preferred_time.evening": "Akşam",
"visit_for": "Randevu kimin için?",
"visit_for.self": "Benim için",
"visit_for.child": "Çocuk için",
"child_name": "Çocuğun adı",
"section.contact": "İletişim",
"name": "Ad",
"email": "E-posta",
"phone": "Telefon",
"section.reason": "Neden",
"reason": "Ziyaretin kısa nedeni",
"section.consent": "Onay",
"consent_contact": "Bu talep hakkında benimle iletişime geçilmesini kabul ediyorum.",
"consent_privacy": "Bu yanıtların talebin işlenmesi için saklanmasını kabul ediyorum."
}
};
let status = $state("");
let values = $state({ visit_for: "" });
const t = $derived(LABELS[lang] || LABELS.en);
function mountCaptcha(node, siteKey) {
if (!node || !siteKey) return () => {};
let disposed = false;
let widget;
function render() {
if (disposed || !window.turnstile) return;
window.turnstile.ready(() => {
if (disposed) return;
widget = window.turnstile.render(node, { sitekey: siteKey });
node.dataset.widgetId = widget;
});
}
if (window.turnstile) render();
else {
let script = document.querySelector('script[src^="https://challenges.cloudflare.com/turnstile/v0/api.js"]');
if (!script) {
script = document.createElement("script");
script.src = "https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit";
script.async = true;
document.head.appendChild(script);
}
script.addEventListener("load", render, { once: true });
}
return () => { disposed = true; if (widget !== undefined) window.turnstile?.remove(widget); };
}
function resetCaptcha(form) {
const widget = form.querySelector("[data-turnstile]")?.dataset.widgetId;
if (widget !== undefined) window.turnstile?.reset(widget);
}
async function onSubmit(event) {
const form = event.currentTarget;
event.preventDefault();
const body = new FormData(form);
const files = Array.from(body.values()).filter(value => value instanceof File && value.size);
if (files.length > 3 || files.some(file => file.size > FILE_MAX) || files.reduce((sum,file) => sum + file.size,0) > 10 * 1024 * 1024) {
status = t.file_too_big;
return;
}
const button = form.querySelector("button[type=submit]");
if (button) button.disabled = true;
try {
const response = await fetch(ENDPOINT, { method: "POST", headers: { Accept: "application/json" }, body });
const result = await response.json();
status = result.success ? t.thanks : (result.message || "error");
} catch { status = "error"; }
finally { if (button) button.disabled = false; resetCaptcha(form); }
}
</script>
<form onsubmit={onSubmit}>
<h1>{t.title}</h1>
<p>{t.lede}</p>
{#if t.disclaimer}<p>{t.disclaimer}</p>{/if}
<input type="hidden" name="access_key" value={accessKey}>
<div aria-hidden="true" style="position:absolute;left:-10000px;width:1px;height:1px;overflow:hidden">
<input name="botcheck" tabindex="-1" autocomplete="off">
</div>
<section><h2>{t["section.visit"]}</h2>
<label><span>{t["service"]}</span><select name="service" required><option value="">—</option><option value="consultation">{t["service.consultation"]}</option><option value="follow_up">{t["service.follow_up"]}</option><option value="vaccination">{t["service.vaccination"]}</option><option value="diagnostics">{t["service.diagnostics"]}</option></select></label>
<label><span>{t["preferred_date"]}</span><input name="preferred_date" type="date" required></label>
<label><span>{t["preferred_time"]}</span><select name="preferred_time" required><option value="">—</option><option value="morning">{t["preferred_time.morning"]}</option><option value="afternoon">{t["preferred_time.afternoon"]}</option><option value="evening">{t["preferred_time.evening"]}</option></select></label>
<label><span>{t["visit_for"]}</span><select name="visit_for" required bind:value={values.visit_for}><option value="">—</option><option value="self">{t["visit_for.self"]}</option><option value="child">{t["visit_for.child"]}</option></select></label>
{#if values.visit_for === "child"}<label><span>{t["child_name"]}</span><input name="child_name" type="text" maxlength="80"></label>{/if}</section>
<section><h2>{t["section.contact"]}</h2>
<label><span>{t["name"]}</span><input name="name" type="text" required maxlength="80"></label>
<label><span>{t["email"]}</span><input name="email" type="email" maxlength="120"></label>
<label><span>{t["phone"]}</span><input name="phone" type="tel" required maxlength="40"></label></section>
<section><h2>{t["section.reason"]}</h2>
<label><span>{t["reason"]}</span><textarea name="reason" required maxlength="500"></textarea></label></section>
<section><h2>{t["section.consent"]}</h2>
<label class="check"><input name="consent_contact" type="checkbox" value="yes" required><span>{t["consent_contact"]}</span></label>
<label class="check"><input name="consent_privacy" type="checkbox" value="yes" required><span>{t["consent_privacy"]}</span></label></section>
<!-- Set turnstileSiteKey to YOUR_TURNSTILE_SITE_KEY. Required for attachments. -->
<div bind:this={captcha} data-turnstile></div>
<button type="submit">{t.submit}</button>
<p>{status}</p>
</form>