S SmartDocs
Serie: vibe coding javascript 110 líneas · Actualizado 2026-04-26

Contact.jsx

vibe_coding/src/pages/Contact.jsx

import { useState } from 'react';
import { useTranslation } from 'react-i18next';

const FORMSPREE_ENDPOINT = import.meta.env.VITE_FORMSPREE_ENDPOINT || '';

export default function Contact() {
  const { t } = useTranslation();
  const [status, setStatus] = useState('idle');
  const [error, setError] = useState('');

  const onSubmit = async (e) => {
    e.preventDefault();
    setStatus('sending');
    setError('');
    const data = new FormData(e.currentTarget);

    if (!FORMSPREE_ENDPOINT) {
      console.info('Formspree endpoint not configured. Submission:', Object.fromEntries(data));
      setTimeout(() => setStatus('ok'), 600);
      e.currentTarget.reset();
      return;
    }

    try {
      const res = await fetch(FORMSPREE_ENDPOINT, {
        method: 'POST',
        body: data,
        headers: { Accept: 'application/json' }
      });
      if (res.ok) {
        setStatus('ok');
        e.currentTarget.reset();
      } else {
        setStatus('err');
        setError(t('contact.error'));
      }
    } catch (err) {
      setStatus('err');
      setError(t('contact.error'));
    }
  };

  return (
    <>
      <header className="page-head">
        <span className="eyebrow">{t('nav.contact')}</span>
        <h1>{t('contact.title')}</h1>
        <p>{t('contact.subtitle')}</p>
      </header>

      <section className="section">
        <div className="container">
          <div className="contact">
            <aside className="contact__info">
              <h3>{t('contact.infoTitle')}</h3>
              <ul>
                <li>
                  <small>Email</small>
                  <a href="mailto:hola@chijia.design">hola@chijia.design</a>
                </li>
                <li>
                  <small>LinkedIn</small>
                  <a href="https://www.linkedin.com/" target="_blank" rel="noopener noreferrer">
                    linkedin.com/in/chijia
                  </a>
                </li>
                <li>
                  <small>{t('contact.city')}</small>
                  <span>Madrid, España</span>
                </li>
              </ul>
            </aside>

            <form className="contact__form" onSubmit={onSubmit} noValidate>
              <h3 style={{ marginTop: 0 }}>{t('contact.formTitle')}</h3>

              <div className="field">
                <label htmlFor="name">{t('contact.name')}</label>
                <input id="name" name="name" type="text" required />
              </div>

              <div className="field">
                <label htmlFor="email">{t('contact.email')}</label>
                <input id="email" name="email" type="email" required />
              </div>

              <div className="field">
                <label htmlFor="message">{t('contact.message')}</label>
                <textarea id="message" name="message" required />
              </div>

              <button type="submit" className="btn btn--primary" disabled={status === 'sending'}>
                {status === 'sending' ? t('contact.sending') : t('contact.send')}
              </button>

              {status === 'ok' && (
                <p className="form-status form-status--ok">{t('contact.success')}</p>
              )}
              {status === 'err' && (
                <p className="form-status form-status--err">{error}</p>
              )}
            </form>
          </div>

          <p className="contact__closing">{t('contact.closing')}</p>
        </div>
      </section>
    </>
  );
}

Artículos relacionados