242 lines
8.4 KiB
TypeScript
242 lines
8.4 KiB
TypeScript
'use server'
|
||
import { cache } from 'react';
|
||
import sql from '@/lib/db';
|
||
import { Resend } from 'resend';
|
||
|
||
const resend = new Resend(process.env.RESEND_API_KEY);
|
||
|
||
// Vercel Best Practice: server-cache-react - Deduplicate data fetching per request
|
||
export const getSettings = cache(async function() {
|
||
try {
|
||
const settings = await sql`SELECT * FROM settings WHERE id = 1 LIMIT 1`;
|
||
return settings[0] || null;
|
||
} catch (error) {
|
||
console.error('Error fetching settings:', error);
|
||
return null;
|
||
}
|
||
});
|
||
|
||
export async function getFeaturedServices() {
|
||
try {
|
||
const services = await sql`SELECT * FROM services WHERE is_featured = true ORDER BY display_order ASC LIMIT 4`;
|
||
return services;
|
||
} catch (error) {
|
||
console.error('Error fetching services:', error);
|
||
return [];
|
||
}
|
||
}
|
||
|
||
export async function getFeaturedProjects() {
|
||
try {
|
||
const projects = await sql`SELECT * FROM projects WHERE is_featured = true ORDER BY created_at DESC LIMIT 6`;
|
||
return projects;
|
||
} catch (error) {
|
||
console.error('Error fetching projects:', error);
|
||
return [];
|
||
}
|
||
}
|
||
|
||
export async function submitLead(formData: {
|
||
firstName: string;
|
||
lastName: string;
|
||
email: string;
|
||
projectType: string;
|
||
message: string;
|
||
}) {
|
||
const fullName = `${formData.firstName} ${formData.lastName}`;
|
||
console.log(`[Lead] Submitting lead for ${fullName}...`);
|
||
|
||
try {
|
||
// 1. Save to Database First
|
||
await sql`
|
||
INSERT INTO leads (full_name, email, service_type, message, status)
|
||
VALUES (${fullName}, ${formData.email}, ${formData.projectType}, ${formData.message}, 'new')
|
||
`;
|
||
console.log(`[Lead] Successfully saved to database.`);
|
||
|
||
// 2. Try sending email in a separate block
|
||
try {
|
||
const settings = await getSettings();
|
||
const destEmail = settings?.contact_email || 'ayrisdev@gmail.com';
|
||
|
||
console.log(`[Lead] Attempting to send notification to ${destEmail}...`);
|
||
|
||
const emailResult = await resend.emails.send({
|
||
from: 'Muğla Dijital <onboarding@resend.dev>',
|
||
to: destEmail,
|
||
subject: `Yeni Mesaj: ${fullName} - ${formData.projectType}`,
|
||
html: `
|
||
<div style="font-family: sans-serif; max-width: 600px; margin: 0 auto; padding: 20px; border: 1px solid #eee;">
|
||
<h2 style="color: #000; border-bottom: 2px solid #ff0000; padding-bottom: 10px;">Yeni İletişim Formu Mesajı</h2>
|
||
<p><strong>Gönderen:</strong> ${fullName}</p>
|
||
<p><strong>E-posta:</strong> ${formData.email}</p>
|
||
<p><strong>Hizmet:</strong> ${formData.projectType}</p>
|
||
<p><strong>Mesaj:</strong></p>
|
||
<div style="background: #f9f9f9; padding: 15px; border-radius: 5px;">
|
||
${formData.message.replace(/\n/g, '<br/>')}
|
||
</div>
|
||
<hr style="margin-top: 30px; border: 0; border-top: 1px solid #eee;" />
|
||
<p style="font-size: 12px; color: #999;">Bu mesaj Muğla Dijital web sitesi üzerinden gönderilmiştir.</p>
|
||
</div>
|
||
`
|
||
});
|
||
|
||
if (emailResult.error) {
|
||
console.error(`[Lead] Resend Error:`, emailResult.error);
|
||
} else {
|
||
console.log(`[Lead] Email sent successfully:`, emailResult.data?.id);
|
||
}
|
||
} catch (emailErr) {
|
||
// We don't want to fail the whole action if only email fails
|
||
console.error(`[Lead] Email sending failed but DB record was saved:`, emailErr);
|
||
}
|
||
|
||
return { success: true };
|
||
} catch (error) {
|
||
console.error('[Lead] Critical Error submitting lead:', error);
|
||
return { error: 'Form gönderilirken bir hata oluştu. Lütfen teknik ekiple iletişime geçin.' };
|
||
}
|
||
}
|
||
export async function getPartners() {
|
||
try {
|
||
return await sql`
|
||
SELECT p.*, (
|
||
SELECT slug FROM projects
|
||
WHERE LOWER(TRIM(p.name)) LIKE '%' || LOWER(TRIM(title)) || '%'
|
||
OR LOWER(TRIM(title)) LIKE '%' || LOWER(TRIM(p.name)) || '%'
|
||
LIMIT 1
|
||
) as project_slug
|
||
FROM partners p
|
||
ORDER BY p.display_order ASC
|
||
`;
|
||
} catch (error) {
|
||
console.error('Error fetching partners:', error);
|
||
return [];
|
||
}
|
||
}
|
||
|
||
export async function getFeaturedPartners() {
|
||
try {
|
||
// Try to fetch featured partners (max 5)
|
||
const featured = await sql`
|
||
SELECT p.*, (
|
||
SELECT slug FROM projects
|
||
WHERE LOWER(TRIM(p.name)) LIKE '%' || LOWER(TRIM(title)) || '%'
|
||
OR LOWER(TRIM(title)) LIKE '%' || LOWER(TRIM(p.name)) || '%'
|
||
LIMIT 1
|
||
) as project_slug
|
||
FROM partners p
|
||
WHERE p.is_featured = true
|
||
ORDER BY p.display_order ASC
|
||
LIMIT 5
|
||
`;
|
||
|
||
if (featured.length > 0) {
|
||
return featured;
|
||
}
|
||
|
||
// Fallback to top 5 standard partners if none are marked featured
|
||
return await sql`
|
||
SELECT p.*, (
|
||
SELECT slug FROM projects
|
||
WHERE LOWER(TRIM(p.name)) LIKE '%' || LOWER(TRIM(title)) || '%'
|
||
OR LOWER(TRIM(title)) LIKE '%' || LOWER(TRIM(p.name)) || '%'
|
||
LIMIT 1
|
||
) as project_slug
|
||
FROM partners p
|
||
ORDER BY p.display_order ASC
|
||
LIMIT 5
|
||
`;
|
||
} catch (error) {
|
||
console.error('Error fetching featured partners:', error);
|
||
return [];
|
||
}
|
||
}
|
||
|
||
export const getProjectBySlug = cache(async function(slug: string) {
|
||
try {
|
||
const projects = await sql`SELECT * FROM projects WHERE slug = ${slug} LIMIT 1`;
|
||
if (projects.length === 0) return null;
|
||
|
||
const project = projects[0];
|
||
|
||
// Fetch next project for the bottom section
|
||
const nextProjects = await sql`
|
||
SELECT * FROM projects
|
||
WHERE created_at < ${project.created_at}
|
||
ORDER BY created_at DESC
|
||
LIMIT 1
|
||
`;
|
||
|
||
// If no older project, fetch the newest one
|
||
let nextProject: any = nextProjects[0] || null;
|
||
if (!nextProject) {
|
||
const newest = await sql`SELECT * FROM projects ORDER BY created_at DESC LIMIT 1`;
|
||
nextProject = newest[0] !== project ? newest[0] : null;
|
||
}
|
||
|
||
return { project, nextProject };
|
||
} catch (error) {
|
||
console.error('Error fetching project:', error);
|
||
return null;
|
||
}
|
||
});
|
||
|
||
export const getServiceBySlug = cache(async function(slug: string) {
|
||
try {
|
||
const services = await sql`SELECT * FROM services WHERE slug = ${slug} LIMIT 1`;
|
||
return services[0] || null;
|
||
} catch (error) {
|
||
console.error('Error fetching service:', error);
|
||
return null;
|
||
}
|
||
});
|
||
|
||
export const getLocationBySlug = cache(async function(slug: string) {
|
||
try {
|
||
const locations = await sql`SELECT * FROM locations WHERE slug = ${slug} LIMIT 1`;
|
||
return locations[0] || null;
|
||
} catch (error) {
|
||
console.error('Error fetching location:', error);
|
||
return null;
|
||
}
|
||
});
|
||
|
||
|
||
export async function getProjectsByService(serviceName: string) {
|
||
try {
|
||
// Search projects where the serviceName is in the title or categories
|
||
// serviceName is expected to be something like "Drone Çekimi"
|
||
return await sql`
|
||
SELECT * FROM projects
|
||
WHERE title ILIKE ${'%' + serviceName + '%'}
|
||
OR categories::text ILIKE ${'%' + serviceName + '%'}
|
||
ORDER BY created_at DESC
|
||
LIMIT 4
|
||
`;
|
||
} catch (error) {
|
||
console.error('Error fetching projects by service:', error);
|
||
return [];
|
||
}
|
||
}
|
||
|
||
export async function getLocations() {
|
||
try {
|
||
const locations = await sql`SELECT * FROM locations ORDER BY name ASC`;
|
||
return locations;
|
||
} catch (error) {
|
||
console.error('Error fetching locations:', error);
|
||
return [];
|
||
}
|
||
}
|
||
|
||
export async function getServices() {
|
||
try {
|
||
const services = await sql`SELECT * FROM services ORDER BY display_order ASC`;
|
||
return services;
|
||
} catch (error) {
|
||
console.error('Error fetching services:', error);
|
||
return [];
|
||
}
|
||
}
|