Formularz aplikacyjny
Aplikacja na stanowisko. Krótkie CV można dołączyć, większy plik podaj jako link.
Plik do 24 KB jest wysyłany jako tekst razem ze zgłoszeniem. Większy plik podaj jako link. Formgong nie przechowuje osobnego pliku.
Podgląd
Kod formularza
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Job application 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; }
</style>
</head>
<body>
<main>
<h1 data-i18n="title">Job application form</h1>
<p data-i18n="lede">Apply for a role. A short CV can be attached; a larger file should be a link.</p>
<form id="fg-form" action="https://formgong.com/submit" method="POST">
<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.role">Role</h2>
<div class="field"><label for="fg-role"><span data-i18n="role">Role</span></label><input id="fg-role" name="role" type="text" required maxlength="120"></div>
<div class="field"><label for="fg-city"><span data-i18n="city">City</span></label><input id="fg-city" name="city" type="text" maxlength="80" autocomplete="address-level2"></div>
<div class="field"><label for="fg-start_date"><span data-i18n="start_date">Available from</span></label><input id="fg-start_date" name="start_date" type="date"></div>
<div class="field"><label for="fg-work_mode"><span data-i18n="work_mode">Work mode</span></label><select id="fg-work_mode" name="work_mode" required><option value="">—</option><option value="office" data-i18n="work_mode.office">Office</option><option value="remote" data-i18n="work_mode.remote">Remote</option><option value="hybrid" data-i18n="work_mode.hybrid">Hybrid</option></select></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" required 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.experience">Experience</h2>
<div class="field"><label for="fg-years"><span data-i18n="years">Years in this kind of work</span></label><input id="fg-years" name="years" type="number" min="0" max="60"></div>
<div class="field"><label for="fg-portfolio"><span data-i18n="portfolio">Portfolio or LinkedIn</span></label><input id="fg-portfolio" name="portfolio" type="url" maxlength="300"></div>
<div class="field"><label for="fg-summary"><span data-i18n="summary">Short summary</span></label><textarea id="fg-summary" name="summary" required maxlength="800"></textarea></div></section>
<section><h2 data-i18n="section.cv">CV</h2>
<div class="field"><label for="fg-cv"><span data-i18n="cv">CV file, up to 24 KB (PDF or Word)</span></label><input id="fg-cv" name="cv" type="file" accept=".pdf,.doc,.docx,application/pdf"></div>
<div class="field"><label for="fg-cv_url"><span data-i18n="cv_url">Or a link to the CV</span></label><input id="fg-cv_url" name="cv_url" type="url" maxlength="300"></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>
<!-- Turnstile hook: enable Turnstile on this form in Formgong, then set your site key.
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>
<div class="cf-turnstile" data-sitekey="YOUR_TURNSTILE_SITE_KEY"></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":"Відгук на вакансію. Коротке CV можна прикріпити, більший файл — посиланням.","submit":"Надіслати","thanks":"Надіслано. Дякуємо.","file_too_big":"Файл більший за 24 КБ. Додайте посилання.","section.role":"Вакансія","role":"Посада","city":"Місто","start_date":"Можу вийти з","work_mode":"Формат","work_mode.office":"Офіс","work_mode.remote":"Віддалено","work_mode.hybrid":"Гібрид","section.contact":"Контакт","name":"Ім'я","email":"Електронна пошта","phone":"Телефон","section.experience":"Досвід","years":"Років у подібній роботі","portfolio":"Портфоліо або LinkedIn","summary":"Коротко про себе","section.cv":"Резюме","cv":"Файл резюме, до 24 КБ (PDF або Word)","cv_url":"Або посилання на резюме","section.consent":"Згода","consent_contact":"Погоджуюсь, щоб зі мною зв'язалися щодо цієї заявки.","consent_privacy":"Погоджуюсь, що ці відповіді зберігаються, щоб заявку можна було обробити."},"en":{"title":"Job application form","lede":"Apply for a role. A short CV can be attached; a larger file should be a link.","submit":"Send","thanks":"Sent. Thank you.","file_too_big":"That file is over 24 KB. Paste a link instead.","section.role":"Role","role":"Role","city":"City","start_date":"Available from","work_mode":"Work mode","work_mode.office":"Office","work_mode.remote":"Remote","work_mode.hybrid":"Hybrid","section.contact":"Contact","name":"Name","email":"Email","phone":"Phone","section.experience":"Experience","years":"Years in this kind of work","portfolio":"Portfolio or LinkedIn","summary":"Short summary","section.cv":"CV","cv":"CV file, up to 24 KB (PDF or Word)","cv_url":"Or a link to the CV","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 aplikacyjny","lede":"Aplikacja na stanowisko. Krótkie CV można dołączyć, większy plik podaj jako link.","submit":"Wyślij","thanks":"Wysłano. Dziękujemy.","file_too_big":"Plik ma ponad 24 KB. Wklej link.","section.role":"Stanowisko","role":"Stanowisko","city":"Miasto","start_date":"Dostępność od","work_mode":"Tryb pracy","work_mode.office":"Biuro","work_mode.remote":"Zdalnie","work_mode.hybrid":"Hybrydowo","section.contact":"Kontakt","name":"Imię","email":"E-mail","phone":"Telefon","section.experience":"Doświadczenie","years":"Lata w podobnej pracy","portfolio":"Portfolio albo LinkedIn","summary":"Krótko o sobie","section.cv":"CV","cv":"Plik CV, do 24 KB (PDF albo Word)","cv_url":"Albo link do CV","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":"İş başvuru formu","lede":"Bir ilana başvuru. Kısa bir CV eklenebilir; daha büyük dosya bağlantı olsun.","submit":"Gönder","thanks":"Gönderildi. Teşekkürler.","file_too_big":"Dosya 24 KB'den büyük. Bağlantı ekleyin.","section.role":"Pozisyon","role":"Pozisyon","city":"Şehir","start_date":"Başlayabileceğim tarih","work_mode":"Çalışma biçimi","work_mode.office":"Ofis","work_mode.remote":"Uzaktan","work_mode.hybrid":"Hibrit","section.contact":"İletişim","name":"Ad","email":"E-posta","phone":"Telefon","section.experience":"Deneyim","years":"Bu tür işte yıl","portfolio":"Portföy ya da LinkedIn","summary":"Kısa özet","section.cv":"Özgeçmiş","cv":"CV dosyası, en fazla 24 KB (PDF veya Word)","cv_url":"Ya da CV bağlantısı","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 () {
var MAX = 24576;
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 = {};
var files = [];
new FormData(form).forEach(function (value, key) {
if (typeof File !== "undefined" && value instanceof File) {
if (value.size) files.push([key, value]);
return;
}
body[key] = String(value);
});
if (files.some(function (pair) { return pair[1].size > MAX; })) {
if (status) status.textContent = dict.file_too_big;
return;
}
Promise.all(files.map(function (pair) {
return readFile(pair[1]).then(function (data) {
body[pair[0] + "_filename"] = pair[1].name;
body[pair[0] + "_data"] = data;
});
})).then(function () {
return fetch(form.action, {
method: "POST",
headers: { "Content-Type": "application/json", Accept: "application/json" },
body: JSON.stringify(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";
});
});
function readFile(file) {
return new Promise(function (resolve, reject) {
var reader = new FileReader();
reader.onload = function () {
var raw = String(reader.result || "");
var comma = raw.indexOf(",");
resolve(comma === -1 ? raw : raw.slice(comma + 1));
};
reader.onerror = function () { reject(reader.error); };
reader.readAsDataURL(file);
});
}
})();
</script>
</body>
</html>
// Generated from src/content/industries.ts — npm run templates:write
import { useState } from "react";
const ENDPOINT = "https://formgong.com/submit";
const FILE_MAX = 24576;
const LABELS = {
"uk": {
"title": "Форма відгуку на вакансію",
"lede": "Відгук на вакансію. Коротке CV можна прикріпити, більший файл — посиланням.",
"submit": "Надіслати",
"thanks": "Надіслано. Дякуємо.",
"file_too_big": "Файл більший за 24 КБ. Додайте посилання.",
"section.role": "Вакансія",
"role": "Посада",
"city": "Місто",
"start_date": "Можу вийти з",
"work_mode": "Формат",
"work_mode.office": "Офіс",
"work_mode.remote": "Віддалено",
"work_mode.hybrid": "Гібрид",
"section.contact": "Контакт",
"name": "Ім'я",
"email": "Електронна пошта",
"phone": "Телефон",
"section.experience": "Досвід",
"years": "Років у подібній роботі",
"portfolio": "Портфоліо або LinkedIn",
"summary": "Коротко про себе",
"section.cv": "Резюме",
"cv": "Файл резюме, до 24 КБ (PDF або Word)",
"cv_url": "Або посилання на резюме",
"section.consent": "Згода",
"consent_contact": "Погоджуюсь, щоб зі мною зв'язалися щодо цієї заявки.",
"consent_privacy": "Погоджуюсь, що ці відповіді зберігаються, щоб заявку можна було обробити."
},
"en": {
"title": "Job application form",
"lede": "Apply for a role. A short CV can be attached; a larger file should be a link.",
"submit": "Send",
"thanks": "Sent. Thank you.",
"file_too_big": "That file is over 24 KB. Paste a link instead.",
"section.role": "Role",
"role": "Role",
"city": "City",
"start_date": "Available from",
"work_mode": "Work mode",
"work_mode.office": "Office",
"work_mode.remote": "Remote",
"work_mode.hybrid": "Hybrid",
"section.contact": "Contact",
"name": "Name",
"email": "Email",
"phone": "Phone",
"section.experience": "Experience",
"years": "Years in this kind of work",
"portfolio": "Portfolio or LinkedIn",
"summary": "Short summary",
"section.cv": "CV",
"cv": "CV file, up to 24 KB (PDF or Word)",
"cv_url": "Or a link to the CV",
"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 aplikacyjny",
"lede": "Aplikacja na stanowisko. Krótkie CV można dołączyć, większy plik podaj jako link.",
"submit": "Wyślij",
"thanks": "Wysłano. Dziękujemy.",
"file_too_big": "Plik ma ponad 24 KB. Wklej link.",
"section.role": "Stanowisko",
"role": "Stanowisko",
"city": "Miasto",
"start_date": "Dostępność od",
"work_mode": "Tryb pracy",
"work_mode.office": "Biuro",
"work_mode.remote": "Zdalnie",
"work_mode.hybrid": "Hybrydowo",
"section.contact": "Kontakt",
"name": "Imię",
"email": "E-mail",
"phone": "Telefon",
"section.experience": "Doświadczenie",
"years": "Lata w podobnej pracy",
"portfolio": "Portfolio albo LinkedIn",
"summary": "Krótko o sobie",
"section.cv": "CV",
"cv": "Plik CV, do 24 KB (PDF albo Word)",
"cv_url": "Albo link do CV",
"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": "İş başvuru formu",
"lede": "Bir ilana başvuru. Kısa bir CV eklenebilir; daha büyük dosya bağlantı olsun.",
"submit": "Gönder",
"thanks": "Gönderildi. Teşekkürler.",
"file_too_big": "Dosya 24 KB'den büyük. Bağlantı ekleyin.",
"section.role": "Pozisyon",
"role": "Pozisyon",
"city": "Şehir",
"start_date": "Başlayabileceğim tarih",
"work_mode": "Çalışma biçimi",
"work_mode.office": "Ofis",
"work_mode.remote": "Uzaktan",
"work_mode.hybrid": "Hibrit",
"section.contact": "İletişim",
"name": "Ad",
"email": "E-posta",
"phone": "Telefon",
"section.experience": "Deneyim",
"years": "Bu tür işte yıl",
"portfolio": "Portföy ya da LinkedIn",
"summary": "Kısa özet",
"section.cv": "Özgeçmiş",
"cv": "CV dosyası, en fazla 24 KB (PDF veya Word)",
"cv_url": "Ya da CV bağlantısı",
"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" }) {
const t = LABELS[lang] || LABELS.en;
const [status, setStatus] = useState("");
async function onSubmit(event) {
const form = event.currentTarget;
event.preventDefault();
const body = {};
const files = [];
for (const [key, value] of new FormData(form).entries()) {
if (value instanceof File) {
if (value.size) files.push([key, value]);
continue;
}
body[key] = String(value);
}
if (files.some((pair) => pair[1].size > FILE_MAX)) {
setStatus(t.file_too_big);
return;
}
for (const [key, file] of files) {
body[key + "_filename"] = file.name;
body[key + "_data"] = await readFile(file);
}
const response = await fetch(ENDPOINT, {
method: "POST",
headers: { "Content-Type": "application/json", Accept: "application/json" },
body: JSON.stringify(body),
});
const result = await response.json();
setStatus(result.success ? t.thanks : (result.message || "error"));
}
return (
<form onSubmit={onSubmit}>
<h1>{t.title}</h1>
<p>{t.lede}</p>
<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.role"]}</h2>
<label><span>{t["role"]}</span><input name="role" type="text" required maxLength={120} /></label>
<label><span>{t["city"]}</span><input name="city" type="text" maxLength={80} autoComplete="address-level2" /></label>
<label><span>{t["start_date"]}</span><input name="start_date" type="date" /></label>
<label><span>{t["work_mode"]}</span><select name="work_mode" required><option value="">—</option><option value="office">{t["work_mode.office"]}</option><option value="remote">{t["work_mode.remote"]}</option><option value="hybrid">{t["work_mode.hybrid"]}</option></select></label></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" required 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.experience"]}</h2>
<label><span>{t["years"]}</span><input name="years" type="number" min={0} max={60} /></label>
<label><span>{t["portfolio"]}</span><input name="portfolio" type="url" maxLength={300} /></label>
<label><span>{t["summary"]}</span><textarea name="summary" required maxLength={800} /></label></section>
<section><h2>{t["section.cv"]}</h2>
<label><span>{t["cv"]}</span><input name="cv" type="file" accept=".pdf,.doc,.docx,application/pdf" /></label>
<label><span>{t["cv_url"]}</span><input name="cv_url" type="url" maxLength={300} /></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>
{/* Turnstile hook: enable Turnstile on this form in Formgong, load https://challenges.cloudflare.com/turnstile/v0/api.js, and render <div className="cf-turnstile" data-sitekey="YOUR_TURNSTILE_SITE_KEY" /> */}
<button type="submit">{t.submit}</button>
<p>{status}</p>
</form>
);
}
function readFile(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => {
const raw = String(reader.result || "");
const comma = raw.indexOf(",");
resolve(comma === -1 ? raw : raw.slice(comma + 1));
};
reader.onerror = () => reject(reader.error);
reader.readAsDataURL(file);
});
}
<!-- Generated from src/content/industries.ts — npm run templates:write -->
<script setup>
import { ref, computed } from "vue";
const props = defineProps({
lang: { type: String, default: "en" },
accessKey: { type: String, default: "fk_your_access_key" },
});
const ENDPOINT = "https://formgong.com/submit";
const FILE_MAX = 24576;
const LABELS = {
"uk": {
"title": "Форма відгуку на вакансію",
"lede": "Відгук на вакансію. Коротке CV можна прикріпити, більший файл — посиланням.",
"submit": "Надіслати",
"thanks": "Надіслано. Дякуємо.",
"file_too_big": "Файл більший за 24 КБ. Додайте посилання.",
"section.role": "Вакансія",
"role": "Посада",
"city": "Місто",
"start_date": "Можу вийти з",
"work_mode": "Формат",
"work_mode.office": "Офіс",
"work_mode.remote": "Віддалено",
"work_mode.hybrid": "Гібрид",
"section.contact": "Контакт",
"name": "Ім'я",
"email": "Електронна пошта",
"phone": "Телефон",
"section.experience": "Досвід",
"years": "Років у подібній роботі",
"portfolio": "Портфоліо або LinkedIn",
"summary": "Коротко про себе",
"section.cv": "Резюме",
"cv": "Файл резюме, до 24 КБ (PDF або Word)",
"cv_url": "Або посилання на резюме",
"section.consent": "Згода",
"consent_contact": "Погоджуюсь, щоб зі мною зв'язалися щодо цієї заявки.",
"consent_privacy": "Погоджуюсь, що ці відповіді зберігаються, щоб заявку можна було обробити."
},
"en": {
"title": "Job application form",
"lede": "Apply for a role. A short CV can be attached; a larger file should be a link.",
"submit": "Send",
"thanks": "Sent. Thank you.",
"file_too_big": "That file is over 24 KB. Paste a link instead.",
"section.role": "Role",
"role": "Role",
"city": "City",
"start_date": "Available from",
"work_mode": "Work mode",
"work_mode.office": "Office",
"work_mode.remote": "Remote",
"work_mode.hybrid": "Hybrid",
"section.contact": "Contact",
"name": "Name",
"email": "Email",
"phone": "Phone",
"section.experience": "Experience",
"years": "Years in this kind of work",
"portfolio": "Portfolio or LinkedIn",
"summary": "Short summary",
"section.cv": "CV",
"cv": "CV file, up to 24 KB (PDF or Word)",
"cv_url": "Or a link to the CV",
"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 aplikacyjny",
"lede": "Aplikacja na stanowisko. Krótkie CV można dołączyć, większy plik podaj jako link.",
"submit": "Wyślij",
"thanks": "Wysłano. Dziękujemy.",
"file_too_big": "Plik ma ponad 24 KB. Wklej link.",
"section.role": "Stanowisko",
"role": "Stanowisko",
"city": "Miasto",
"start_date": "Dostępność od",
"work_mode": "Tryb pracy",
"work_mode.office": "Biuro",
"work_mode.remote": "Zdalnie",
"work_mode.hybrid": "Hybrydowo",
"section.contact": "Kontakt",
"name": "Imię",
"email": "E-mail",
"phone": "Telefon",
"section.experience": "Doświadczenie",
"years": "Lata w podobnej pracy",
"portfolio": "Portfolio albo LinkedIn",
"summary": "Krótko o sobie",
"section.cv": "CV",
"cv": "Plik CV, do 24 KB (PDF albo Word)",
"cv_url": "Albo link do CV",
"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": "İş başvuru formu",
"lede": "Bir ilana başvuru. Kısa bir CV eklenebilir; daha büyük dosya bağlantı olsun.",
"submit": "Gönder",
"thanks": "Gönderildi. Teşekkürler.",
"file_too_big": "Dosya 24 KB'den büyük. Bağlantı ekleyin.",
"section.role": "Pozisyon",
"role": "Pozisyon",
"city": "Şehir",
"start_date": "Başlayabileceğim tarih",
"work_mode": "Çalışma biçimi",
"work_mode.office": "Ofis",
"work_mode.remote": "Uzaktan",
"work_mode.hybrid": "Hibrit",
"section.contact": "İletişim",
"name": "Ad",
"email": "E-posta",
"phone": "Telefon",
"section.experience": "Deneyim",
"years": "Bu tür işte yıl",
"portfolio": "Portföy ya da LinkedIn",
"summary": "Kısa özet",
"section.cv": "Özgeçmiş",
"cv": "CV dosyası, en fazla 24 KB (PDF veya Word)",
"cv_url": "Ya da CV bağlantısı",
"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("");
function readFile(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => {
const raw = String(reader.result || "");
const comma = raw.indexOf(",");
resolve(comma === -1 ? raw : raw.slice(comma + 1));
};
reader.onerror = () => reject(reader.error);
reader.readAsDataURL(file);
});
}
async function onSubmit(event) {
const form = event.currentTarget;
event.preventDefault();
const body = {};
const files = [];
for (const [key, value] of new FormData(form).entries()) {
if (value instanceof File) {
if (value.size) files.push([key, value]);
continue;
}
body[key] = String(value);
}
if (files.some((pair) => pair[1].size > FILE_MAX)) {
status.value = t.value.file_too_big;
return;
}
for (const [key, file] of files) {
body[key + "_filename"] = file.name;
body[key + "_data"] = await readFile(file);
}
const response = await fetch(ENDPOINT, {
method: "POST",
headers: { "Content-Type": "application/json", Accept: "application/json" },
body: JSON.stringify(body),
});
const result = await response.json();
status.value = result.success ? t.value.thanks : (result.message || "error");
}
</script>
<template>
<form @submit.prevent="onSubmit">
<h1>{{ t.title }}</h1>
<p>{{ t.lede }}</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.role"] }}</h2>
<label><span>{{ t["role"] }}</span><input name="role" type="text" required maxlength="120"></label>
<label><span>{{ t["city"] }}</span><input name="city" type="text" maxlength="80" autocomplete="address-level2"></label>
<label><span>{{ t["start_date"] }}</span><input name="start_date" type="date"></label>
<label><span>{{ t["work_mode"] }}</span><select name="work_mode" required><option value="">—</option><option value="office">{{ t["work_mode.office"] }}</option><option value="remote">{{ t["work_mode.remote"] }}</option><option value="hybrid">{{ t["work_mode.hybrid"] }}</option></select></label></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" required 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.experience"] }}</h2>
<label><span>{{ t["years"] }}</span><input name="years" type="number" min="0" max="60"></label>
<label><span>{{ t["portfolio"] }}</span><input name="portfolio" type="url" maxlength="300"></label>
<label><span>{{ t["summary"] }}</span><textarea name="summary" required maxlength="800"></textarea></label></section>
<section><h2>{{ t["section.cv"] }}</h2>
<label><span>{{ t["cv"] }}</span><input name="cv" type="file" accept=".pdf,.doc,.docx,application/pdf"></label>
<label><span>{{ t["cv_url"] }}</span><input name="cv_url" type="url" maxlength="300"></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>
<!-- Turnstile hook: enable Turnstile on this form in Formgong, add the api.js script, and a div.cf-turnstile with data-sitekey="YOUR_TURNSTILE_SITE_KEY". -->
<button type="submit">{{ t.submit }}</button>
<p>{{ status }}</p>
</form>
</template>
<!-- Generated from src/content/industries.ts — npm run templates:write -->
<script>
let { lang = "en", accessKey = "fk_your_access_key" } = $props();
const ENDPOINT = "https://formgong.com/submit";
const FILE_MAX = 24576;
const LABELS = {
"uk": {
"title": "Форма відгуку на вакансію",
"lede": "Відгук на вакансію. Коротке CV можна прикріпити, більший файл — посиланням.",
"submit": "Надіслати",
"thanks": "Надіслано. Дякуємо.",
"file_too_big": "Файл більший за 24 КБ. Додайте посилання.",
"section.role": "Вакансія",
"role": "Посада",
"city": "Місто",
"start_date": "Можу вийти з",
"work_mode": "Формат",
"work_mode.office": "Офіс",
"work_mode.remote": "Віддалено",
"work_mode.hybrid": "Гібрид",
"section.contact": "Контакт",
"name": "Ім'я",
"email": "Електронна пошта",
"phone": "Телефон",
"section.experience": "Досвід",
"years": "Років у подібній роботі",
"portfolio": "Портфоліо або LinkedIn",
"summary": "Коротко про себе",
"section.cv": "Резюме",
"cv": "Файл резюме, до 24 КБ (PDF або Word)",
"cv_url": "Або посилання на резюме",
"section.consent": "Згода",
"consent_contact": "Погоджуюсь, щоб зі мною зв'язалися щодо цієї заявки.",
"consent_privacy": "Погоджуюсь, що ці відповіді зберігаються, щоб заявку можна було обробити."
},
"en": {
"title": "Job application form",
"lede": "Apply for a role. A short CV can be attached; a larger file should be a link.",
"submit": "Send",
"thanks": "Sent. Thank you.",
"file_too_big": "That file is over 24 KB. Paste a link instead.",
"section.role": "Role",
"role": "Role",
"city": "City",
"start_date": "Available from",
"work_mode": "Work mode",
"work_mode.office": "Office",
"work_mode.remote": "Remote",
"work_mode.hybrid": "Hybrid",
"section.contact": "Contact",
"name": "Name",
"email": "Email",
"phone": "Phone",
"section.experience": "Experience",
"years": "Years in this kind of work",
"portfolio": "Portfolio or LinkedIn",
"summary": "Short summary",
"section.cv": "CV",
"cv": "CV file, up to 24 KB (PDF or Word)",
"cv_url": "Or a link to the CV",
"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 aplikacyjny",
"lede": "Aplikacja na stanowisko. Krótkie CV można dołączyć, większy plik podaj jako link.",
"submit": "Wyślij",
"thanks": "Wysłano. Dziękujemy.",
"file_too_big": "Plik ma ponad 24 KB. Wklej link.",
"section.role": "Stanowisko",
"role": "Stanowisko",
"city": "Miasto",
"start_date": "Dostępność od",
"work_mode": "Tryb pracy",
"work_mode.office": "Biuro",
"work_mode.remote": "Zdalnie",
"work_mode.hybrid": "Hybrydowo",
"section.contact": "Kontakt",
"name": "Imię",
"email": "E-mail",
"phone": "Telefon",
"section.experience": "Doświadczenie",
"years": "Lata w podobnej pracy",
"portfolio": "Portfolio albo LinkedIn",
"summary": "Krótko o sobie",
"section.cv": "CV",
"cv": "Plik CV, do 24 KB (PDF albo Word)",
"cv_url": "Albo link do CV",
"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": "İş başvuru formu",
"lede": "Bir ilana başvuru. Kısa bir CV eklenebilir; daha büyük dosya bağlantı olsun.",
"submit": "Gönder",
"thanks": "Gönderildi. Teşekkürler.",
"file_too_big": "Dosya 24 KB'den büyük. Bağlantı ekleyin.",
"section.role": "Pozisyon",
"role": "Pozisyon",
"city": "Şehir",
"start_date": "Başlayabileceğim tarih",
"work_mode": "Çalışma biçimi",
"work_mode.office": "Ofis",
"work_mode.remote": "Uzaktan",
"work_mode.hybrid": "Hibrit",
"section.contact": "İletişim",
"name": "Ad",
"email": "E-posta",
"phone": "Telefon",
"section.experience": "Deneyim",
"years": "Bu tür işte yıl",
"portfolio": "Portföy ya da LinkedIn",
"summary": "Kısa özet",
"section.cv": "Özgeçmiş",
"cv": "CV dosyası, en fazla 24 KB (PDF veya Word)",
"cv_url": "Ya da CV bağlantısı",
"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("");
const t = $derived(LABELS[lang] || LABELS.en);
function readFile(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => {
const raw = String(reader.result || "");
const comma = raw.indexOf(",");
resolve(comma === -1 ? raw : raw.slice(comma + 1));
};
reader.onerror = () => reject(reader.error);
reader.readAsDataURL(file);
});
}
async function onSubmit(event) {
const form = event.currentTarget;
event.preventDefault();
const body = {};
const files = [];
for (const [key, value] of new FormData(form).entries()) {
if (value instanceof File) {
if (value.size) files.push([key, value]);
continue;
}
body[key] = String(value);
}
if (files.some((pair) => pair[1].size > FILE_MAX)) {
status = t.file_too_big;
return;
}
for (const [key, file] of files) {
body[key + "_filename"] = file.name;
body[key + "_data"] = await readFile(file);
}
const response = await fetch(ENDPOINT, {
method: "POST",
headers: { "Content-Type": "application/json", Accept: "application/json" },
body: JSON.stringify(body),
});
const result = await response.json();
status = result.success ? t.thanks : (result.message || "error");
}
</script>
<form onsubmit={onSubmit}>
<h1>{t.title}</h1>
<p>{t.lede}</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.role"]}</h2>
<label><span>{t["role"]}</span><input name="role" type="text" required maxlength="120"></label>
<label><span>{t["city"]}</span><input name="city" type="text" maxlength="80"></label>
<label><span>{t["start_date"]}</span><input name="start_date" type="date"></label>
<label><span>{t["work_mode"]}</span><select name="work_mode" required><option value="">—</option><option value="office">{t["work_mode.office"]}</option><option value="remote">{t["work_mode.remote"]}</option><option value="hybrid">{t["work_mode.hybrid"]}</option></select></label></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" required maxlength="120"></label>
<label><span>{t["phone"]}</span><input name="phone" type="tel" required maxlength="40"></label></section>
<section><h2>{t["section.experience"]}</h2>
<label><span>{t["years"]}</span><input name="years" type="number" min="0" max="60"></label>
<label><span>{t["portfolio"]}</span><input name="portfolio" type="url" maxlength="300"></label>
<label><span>{t["summary"]}</span><textarea name="summary" required maxlength="800"></textarea></label></section>
<section><h2>{t["section.cv"]}</h2>
<label><span>{t["cv"]}</span><input name="cv" type="file" accept=".pdf,.doc,.docx,application/pdf"></label>
<label><span>{t["cv_url"]}</span><input name="cv_url" type="url" maxlength="300"></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>
<!-- Turnstile hook: enable Turnstile on this form in Formgong, add the api.js script, and a div.cf-turnstile with data-sitekey="YOUR_TURNSTILE_SITE_KEY". -->
<button type="submit">{t.submit}</button>
<p>{status}</p>
</form>