Restore contact form and make it functional with email sending
- Replace mailto link with original contact form (name, email, message fields) - Add contact API endpoint that sends email via mail() and saves to messages.json - Restore .contact-form CSS styles and translation keys Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
29
api.php
29
api.php
@@ -909,6 +909,35 @@ switch ($action) {
|
|||||||
}
|
}
|
||||||
ok(['loggedIn' => false]);
|
ok(['loggedIn' => false]);
|
||||||
|
|
||||||
|
// ─── Yhteydenotto ──────────────────────────────────────────
|
||||||
|
case 'contact':
|
||||||
|
$name = trim($body['name'] ?? '');
|
||||||
|
$email = trim($body['email'] ?? '');
|
||||||
|
$message = trim($body['message'] ?? '');
|
||||||
|
|
||||||
|
if (!$name || !$email || !$message) err('Täytä kaikki kentät.');
|
||||||
|
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) err('Sähköpostiosoite ei kelpaa.');
|
||||||
|
if (mb_strlen($message) > 5000) err('Viesti on liian pitkä.');
|
||||||
|
|
||||||
|
// Tallenna varmuuskopio
|
||||||
|
$messages = readData('messages.json', []);
|
||||||
|
$messages[] = [
|
||||||
|
'name' => htmlspecialchars($name, ENT_QUOTES | ENT_HTML5, 'UTF-8'),
|
||||||
|
'email' => htmlspecialchars($email, ENT_QUOTES | ENT_HTML5, 'UTF-8'),
|
||||||
|
'message' => htmlspecialchars($message, ENT_QUOTES | ENT_HTML5, 'UTF-8'),
|
||||||
|
'date' => date('Y-m-d H:i:s'),
|
||||||
|
];
|
||||||
|
writeData('messages.json', $messages);
|
||||||
|
|
||||||
|
// Lähetä sähköposti
|
||||||
|
$to = 'info@tykkaa.fi';
|
||||||
|
$subject = "tykkää.fi: viesti käyttäjältä $name";
|
||||||
|
$body = "Nimi: $name\nSähköposti: $email\n\nViesti:\n$message";
|
||||||
|
$headers = "From: noreply@tykkaa.fi\r\nReply-To: $email\r\nContent-Type: text/plain; charset=UTF-8";
|
||||||
|
@mail($to, $subject, $body, $headers);
|
||||||
|
|
||||||
|
ok(['sent' => true]);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
err('Unknown action');
|
err('Unknown action');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,7 +64,12 @@
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
<h2 data-i18n="contact_title"></h2>
|
<h2 data-i18n="contact_title"></h2>
|
||||||
<p data-i18n="contact_desc"></p>
|
<p data-i18n="contact_desc"></p>
|
||||||
<a href="mailto:info@tykkaa.fi" class="contact-email">info@tykkaa.fi</a>
|
<form class="contact-form" onsubmit="handleSubmit(event)">
|
||||||
|
<input type="text" id="contact-name" data-i18n-ph="name_ph" required />
|
||||||
|
<input type="email" id="contact-email" data-i18n-ph="email_ph" required />
|
||||||
|
<textarea id="contact-msg" data-i18n-ph="msg_ph" rows="4" required></textarea>
|
||||||
|
<button type="submit" class="btn" data-i18n="send_btn"></button>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|||||||
31
script.js
31
script.js
@@ -15,7 +15,9 @@ const T = {
|
|||||||
about_title: 'Mikä tykkää.fi?',
|
about_title: 'Mikä tykkää.fi?',
|
||||||
about_text: 'tykkää.fi on avoin yhteisö, jonne kuka tahansa voi tulla jakamaan asioita joista tykkää. Reseptejä, neulomisohjeita, käsityöideoita tai ihan mitä muuta kivaa — tärkeintä on jakamisen ilo. Lisää oma julkaisusi yläkulman napista!',
|
about_text: 'tykkää.fi on avoin yhteisö, jonne kuka tahansa voi tulla jakamaan asioita joista tykkää. Reseptejä, neulomisohjeita, käsityöideoita tai ihan mitä muuta kivaa — tärkeintä on jakamisen ilo. Lisää oma julkaisusi yläkulman napista!',
|
||||||
contact_title: 'Ota yhteyttä',
|
contact_title: 'Ota yhteyttä',
|
||||||
contact_desc: 'Kysyttävää tai ehdotuksia? Lähetä meille sähköpostia!',
|
contact_desc: 'Kysyttävää tai ehdotuksia? Lähetä meille viestiä!',
|
||||||
|
name_ph: 'Nimesi', email_ph: 'Sähköpostisi', msg_ph: 'Viestisi...',
|
||||||
|
send_btn: 'Lähetä viesti', msg_sent: 'Viesti lähetetty! ✓', msg_error: 'Virhe lähetyksessä. Yritä uudelleen.',
|
||||||
footer: 'Avoin yhteisö kaikille',
|
footer: 'Avoin yhteisö kaikille',
|
||||||
modal_by: 'Kirjoittanut',
|
modal_by: 'Kirjoittanut',
|
||||||
modal_ingredients: 'Ainekset', modal_steps: 'Ohjeet',
|
modal_ingredients: 'Ainekset', modal_steps: 'Ohjeet',
|
||||||
@@ -47,7 +49,9 @@ const T = {
|
|||||||
about_title: 'What is tykkää.fi?',
|
about_title: 'What is tykkää.fi?',
|
||||||
about_text: 'tykkää.fi is an open community where anyone can share things they love. Recipes, knitting patterns, craft ideas or anything fun — the joy of sharing is what matters. Add your own post using the button in the top corner!',
|
about_text: 'tykkää.fi is an open community where anyone can share things they love. Recipes, knitting patterns, craft ideas or anything fun — the joy of sharing is what matters. Add your own post using the button in the top corner!',
|
||||||
contact_title: 'Get in Touch',
|
contact_title: 'Get in Touch',
|
||||||
contact_desc: 'Questions or suggestions? Send us an email!',
|
contact_desc: 'Questions or suggestions? Send us a message!',
|
||||||
|
name_ph: 'Your name', email_ph: 'Your email', msg_ph: 'Your message...',
|
||||||
|
send_btn: 'Send Message', msg_sent: 'Message Sent! ✓', msg_error: 'Error sending. Please try again.',
|
||||||
footer: 'Open community for everyone',
|
footer: 'Open community for everyone',
|
||||||
modal_by: 'By',
|
modal_by: 'By',
|
||||||
modal_ingredients: 'Ingredients', modal_steps: 'Instructions',
|
modal_ingredients: 'Ingredients', modal_steps: 'Instructions',
|
||||||
@@ -638,6 +642,29 @@ async function submitPublicPost() {
|
|||||||
// ===========================
|
// ===========================
|
||||||
// CONTACT FORM
|
// CONTACT FORM
|
||||||
// ===========================
|
// ===========================
|
||||||
|
// ===========================
|
||||||
|
// CONTACT FORM
|
||||||
|
// ===========================
|
||||||
|
async function handleSubmit(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
const btn = e.target.querySelector('button[type="submit"]');
|
||||||
|
const name = document.getElementById('contact-name').value.trim();
|
||||||
|
const email = document.getElementById('contact-email').value.trim();
|
||||||
|
const message = document.getElementById('contact-msg').value.trim();
|
||||||
|
btn.disabled = true;
|
||||||
|
try {
|
||||||
|
await apiPost('contact', { name, email, message });
|
||||||
|
btn.textContent = t('msg_sent');
|
||||||
|
btn.style.background = '#5c8a4a';
|
||||||
|
e.target.reset();
|
||||||
|
setTimeout(() => { btn.textContent = t('send_btn'); btn.style.background = ''; btn.disabled = false; }, 4000);
|
||||||
|
} catch {
|
||||||
|
btn.textContent = t('msg_error');
|
||||||
|
btn.style.background = '#c04040';
|
||||||
|
setTimeout(() => { btn.textContent = t('send_btn'); btn.style.background = ''; btn.disabled = false; }, 4000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ===========================
|
// ===========================
|
||||||
// INIT
|
// INIT
|
||||||
// ===========================
|
// ===========================
|
||||||
|
|||||||
30
style.css
30
style.css
@@ -324,19 +324,31 @@ nav a:hover { color: #fff; }
|
|||||||
.contact h2 { font-size: 1.9rem; color: var(--warm-brown); margin-bottom: 8px; }
|
.contact h2 { font-size: 1.9rem; color: var(--warm-brown); margin-bottom: 8px; }
|
||||||
.contact > .container > p { color: var(--text-light); margin-bottom: 28px; }
|
.contact > .container > p { color: var(--text-light); margin-bottom: 28px; }
|
||||||
|
|
||||||
.contact-email {
|
.contact-form {
|
||||||
font-size: 1.3rem;
|
display: flex;
|
||||||
font-family: 'Georgia', serif;
|
flex-direction: column;
|
||||||
color: var(--accent);
|
gap: 14px;
|
||||||
text-decoration: none;
|
max-width: 520px;
|
||||||
transition: color 0.2s;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.contact-email:hover {
|
.contact-form input,
|
||||||
color: #a0522d;
|
.contact-form textarea {
|
||||||
text-decoration: underline;
|
padding: 12px 18px;
|
||||||
|
border: 2px solid var(--border);
|
||||||
|
border-radius: 10px;
|
||||||
|
font-size: 1rem;
|
||||||
|
font-family: 'Georgia', serif;
|
||||||
|
background: #fff;
|
||||||
|
color: var(--text);
|
||||||
|
outline: none;
|
||||||
|
transition: border-color 0.2s;
|
||||||
|
resize: vertical;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.contact-form input:focus,
|
||||||
|
.contact-form textarea:focus { border-color: var(--accent); }
|
||||||
|
|
||||||
/* =====================
|
/* =====================
|
||||||
FOOTER
|
FOOTER
|
||||||
===================== */
|
===================== */
|
||||||
|
|||||||
Reference in New Issue
Block a user