feat: add email sending via Mail API

This commit is contained in:
Pablo de la Torre Jamardo 2025-09-21 09:16:54 +02:00
parent 0141657e14
commit 6cd1f7d620
4 changed files with 49 additions and 22 deletions

10
package-lock.json generated
View File

@ -12,6 +12,7 @@
"vue": "^3.4.21",
"vue-loading-overlay": "^6.0.6",
"vue-preloader": "^1.1.4",
"vue-toastification": "^2.0.0-rc.5",
"vue-typer": "^1.2.0",
"vue3-typer": "^1.0.0"
},
@ -2963,6 +2964,15 @@
"node": ">=14"
}
},
"node_modules/vue-toastification": {
"version": "2.0.0-rc.5",
"resolved": "https://registry.npmjs.org/vue-toastification/-/vue-toastification-2.0.0-rc.5.tgz",
"integrity": "sha512-q73e5jy6gucEO/U+P48hqX+/qyXDozAGmaGgLFm5tXX4wJBcVsnGp4e/iJqlm9xzHETYOilUuwOUje2Qg1JdwA==",
"license": "MIT",
"peerDependencies": {
"vue": "^3.0.2"
}
},
"node_modules/vue-typer": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/vue-typer/-/vue-typer-1.2.0.tgz",

View File

@ -30,6 +30,7 @@
"vue": "^3.4.21",
"vue-loading-overlay": "^6.0.6",
"vue-preloader": "^1.1.4",
"vue-toastification": "^2.0.0-rc.5",
"vue-typer": "^1.2.0",
"vue3-typer": "^1.0.0"
},

View File

@ -2,7 +2,8 @@
import {ref} from 'vue'
import {Github, Globe, Linkedin, Mail, MapPin, Phone} from 'lucide-vue-next'
import type {Profile} from '@/domain/models/Profile'
import { useToast } from "vue-toastification";
const toast = useToast();
defineProps<{
profile: Profile
}>()
@ -27,23 +28,37 @@ function getSocialIcon(platform) {
async function handleSubmit() {
isSubmitting.value = true
// Simulate form submission
await new Promise(resolve => setTimeout(resolve, 1000))
try {
const payload = {
from: form.value.email,
subject: form.value.name,
body: form.value.message
}
// Here you would typically send the form data to your backend
console.log('Form submitted:', form.value)
const response = await fetch(`${import.meta.env.VITE_MAIL_API_URL}/mail`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(payload)
})
// Reset form
form.value = {
name: '',
email: '',
message: ''
if (!response.ok) {
throw new Error(`Error en el envío: ${response.status}`)
}
form.value = {
name: '',
email: '',
message: ''
}
toast.success("✅ ¡Mensaje enviado correctamente! Te responderé pronto.")
} catch (error) {
toast.error("❌ Hubo un error al enviar el mensaje. Inténtalo de nuevo.")
} finally {
isSubmitting.value = false
}
isSubmitting.value = false
// Show success message (you could use a toast notification)
alert('¡Mensaje enviado correctamente! Te responderé pronto.')
}
</script>
@ -117,15 +132,12 @@ async function handleSubmit() {
<!-- Contact Form -->
<div class="bg-gray-50 dark:bg-gray-700 rounded-xl p-8">
<p class="m-5">¡Hola! Por el momento mi servidor SMTP está de vacaciones 😅.</p>
<p class="m-5">Si quieres contactarme, envíame un correo electrónico directamente y prometo responderte
rápido.</p>
<form @submit.prevent="handleSubmit" class="space-y-6">
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
Nombre
</label>
<input disabled
<input
v-model="form.name"
type="text"
required
@ -137,7 +149,7 @@ async function handleSubmit() {
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
Email
</label>
<input disabled
<input
v-model="form.email"
type="email"
required
@ -149,7 +161,7 @@ async function handleSubmit() {
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
Mensaje
</label>
<textarea disabled
<textarea
v-model="form.message"
rows="4"
required
@ -159,7 +171,7 @@ async function handleSubmit() {
<button
type="submit"
:disabled="isSubmitting || 1===1"
:disabled="isSubmitting"
class="w-full px-6 py-3 bg-purple-600 hover:bg-purple-700 disabled:opacity-50 text-white rounded-lg font-semibold transition-colors"
>
{{ isSubmitting ? 'Enviando...' : 'Enviar Mensaje' }}

View File

@ -3,10 +3,14 @@ import "./style.css"
import VueTyper from 'vue3-typer'
import "vue3-typer/dist/vue-typer.css"
import App from "./App.vue";
import Toast from "vue-toastification";
import "vue-toastification/dist/index.css";
const app = createApp(App)
app.component('VueTyper', VueTyper)
app.use(Toast, {});
// Global error handler
app.config.errorHandler = (err, vm, info) => {
console.error("Global error:", err, info)