Autosave: 20260228-233420

This commit is contained in:
Flatlogic Bot 2026-02-28 23:34:20 +00:00
parent 7a2e8f89f4
commit 8b2b855f30
28 changed files with 1647 additions and 171 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 KiB

View File

@ -0,0 +1,41 @@
module.exports = {
async up(queryInterface, Sequelize) {
const createdAt = new Date();
const updatedAt = new Date();
const [publicRole] = await queryInterface.sequelize.query(
`SELECT id FROM "roles" WHERE name = 'Public' LIMIT 1;`
);
if (publicRole && publicRole.length > 0) {
const publicRoleId = publicRole[0].id;
const permissionsToGrant = [
'CREATE_LEADS',
'READ_SERVICES',
'READ_PROJECTS',
'READ_TESTIMONIALS',
'READ_MEDIA_ASSETS',
'READ_FAQS'
];
const [permissions] = await queryInterface.sequelize.query(
`SELECT id FROM "permissions" WHERE name IN (${permissionsToGrant.map(p => `'${p}'`).join(',')});`
);
const rolesPermissions = permissions.map(permission => ({
createdAt,
updatedAt,
roles_permissionsId: publicRoleId,
permissionId: permission.id
}));
await queryInterface.bulkInsert('rolesPermissionsPermissions', rolesPermissions);
}
},
async down(queryInterface, Sequelize) {
// Optional: remove permissions from Public role
}
};

View File

@ -1,4 +1,3 @@
const express = require('express');
const cors = require('cors');
const app = express();
@ -117,19 +116,19 @@ app.use('/api/pages', passport.authenticate('jwt', {session: false}), pagesRoute
app.use('/api/service_categories', passport.authenticate('jwt', {session: false}), service_categoriesRoutes);
app.use('/api/services', passport.authenticate('jwt', {session: false}), servicesRoutes);
app.use('/api/services', servicesRoutes);
app.use('/api/projects', passport.authenticate('jwt', {session: false}), projectsRoutes);
app.use('/api/projects', projectsRoutes);
app.use('/api/testimonials', passport.authenticate('jwt', {session: false}), testimonialsRoutes);
app.use('/api/testimonials', testimonialsRoutes);
app.use('/api/faqs', passport.authenticate('jwt', {session: false}), faqsRoutes);
app.use('/api/faqs', faqsRoutes);
app.use('/api/leads', passport.authenticate('jwt', {session: false}), leadsRoutes);
app.use('/api/leads', leadsRoutes);
app.use('/api/media_assets', passport.authenticate('jwt', {session: false}), media_assetsRoutes);
app.use('/api/media_assets', media_assetsRoutes);
app.use('/api/home_sections', passport.authenticate('jwt', {session: false}), home_sectionsRoutes);
app.use('/api/home_sections', home_sectionsRoutes);
app.use(
'/api/openai',
@ -175,4 +174,4 @@ db.sequelize.sync().then(function () {
});
});
module.exports = app;
module.exports = app;

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

View File

@ -0,0 +1,111 @@
import React from 'react';
import { mdiCheckBold, mdiShieldCheck, mdiLightbulbOn, mdiStar } from '@mdi/js';
import BaseIcon from '../BaseIcon';
import ScrollReveal from './ScrollReveal';
const features = [
{
title: 'Garantili İşçilik',
description: 'Tüm uygulamalarımızda uzun ömürlü ve garantili işçilik sunuyoruz.',
icon: mdiShieldCheck
},
{
title: 'Modern Tasarımlar',
description: 'En son trendlere uygun, estetik ve modern mekanlar tasarlıyoruz.',
icon: mdiLightbulbOn
},
{
title: 'En İyi Malzeme',
description: 'Sektördeki en kaliteli ve dayanıklı malzemeleri kullanıyoruz.',
icon: mdiStar
}
];
const About = () => {
return (
<section id="hakkimizda" className="py-24 bg-white overflow-hidden">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex flex-col lg:flex-row items-center gap-16 lg:gap-24">
<div className="lg:w-1/2 relative">
<ScrollReveal animation="fade-in-left">
<div className="relative z-10 rounded-3xl overflow-hidden shadow-2xl group">
<img
src="https://images.pexels.com/photos/1571470/pexels-photo-1571470.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2"
alt="Beka Kaplama Hakkımızda"
className="w-full h-full object-cover aspect-[4/5] group-hover:scale-105 transition-transform duration-700"
/>
</div>
</ScrollReveal>
{/* Experience Badge */}
<ScrollReveal animation="scale-in" delay={300}>
<div className="absolute -bottom-10 -right-10 bg-amber-600 p-10 rounded-3xl shadow-2xl z-20 hidden md:block border-8 border-white hover:scale-110 transition-transform duration-500">
<div className="text-5xl font-black text-white mb-2 tracking-tighter animate-pulse font-sans">15+</div>
<div className="text-sm font-bold text-amber-100 uppercase tracking-widest leading-tight font-body">Yıllık Sektörel<br />Tecrübe</div>
</div>
</ScrollReveal>
{/* Background Decoration */}
<div className="absolute -top-10 -left-10 w-40 h-40 bg-amber-100 rounded-full blur-3xl opacity-50 -z-10 animate-pulse"></div>
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-full h-full border-2 border-amber-600/10 rounded-3xl -rotate-6 -z-10"></div>
</div>
<div className="lg:w-1/2">
<ScrollReveal animation="fade-in-up" delay={100}>
<h2 className="text-xs font-black text-amber-600 uppercase tracking-[0.2em] mb-4 font-sans">Biz Kimiz?</h2>
<h3 className="text-4xl md:text-5xl font-black text-gray-900 mb-8 leading-tight font-sans">Mekanlarınıza Değer <br />Katan Vizyon</h3>
</ScrollReveal>
<ScrollReveal animation="fade-in-up" delay={200}>
<p className="text-xl text-gray-500 mb-10 leading-relaxed font-medium italic border-l-4 border-amber-600 pl-6 bg-amber-50 py-4 pr-4 rounded-r-xl font-serif">
&quot;Beka Kaplama olarak, sadece duvarları kaplamıyor, yaşam alanlarınızın ruhunu değiştiriyoruz.&quot;
</p>
</ScrollReveal>
<ScrollReveal animation="fade-in-up" delay={300}>
<p className="text-gray-600 mb-10 leading-relaxed font-body">
Kurulduğumuz günden bu yana, modern mimari trendlerini takip ederek müşterilerimize en kaliteli kaplama çözümlerini sunuyoruz. Akustik panel sistemlerinden PU cephe lambri uygulamalarına kadar geniş ürün yelpazemiz ve uzman ekibimizle projelerinize estetik ve dayanıklılık katıyoruz.
</p>
</ScrollReveal>
<div className="grid grid-cols-1 md:grid-cols-2 gap-8 mb-12">
<ScrollReveal animation="fade-in-up" delay={400} className="space-y-4">
{['Müşteri Odaklılık', 'Kaliteli Malzeme', 'Hızlı Uygulama'].map((item, i) => (
<div key={i} className="flex items-center space-x-3 text-gray-800 font-bold hover:translate-x-2 transition-transform cursor-default font-body">
<div className="p-1 bg-green-100 rounded-full group">
<BaseIcon path={mdiCheckBold} size={18} className="text-green-600" />
</div>
<span>{item}</span>
</div>
))}
</ScrollReveal>
<ScrollReveal animation="fade-in-up" delay={500} className="space-y-4">
{['Estetik Tasarım', 'Ekonomik Çözümler', 'Uzman Kadro'].map((item, i) => (
<div key={i} className="flex items-center space-x-3 text-gray-800 font-bold hover:translate-x-2 transition-transform cursor-default font-body">
<div className="p-1 bg-green-100 rounded-full">
<BaseIcon path={mdiCheckBold} size={18} className="text-green-600" />
</div>
<span>{item}</span>
</div>
))}
</ScrollReveal>
</div>
<ScrollReveal animation="fade-in-up" delay={600} className="grid grid-cols-3 gap-6">
{features.map((feature, index) => (
<div key={index} className="text-center group cursor-default">
<div className="inline-flex p-3 bg-gray-50 rounded-2xl group-hover:bg-amber-600 group-hover:scale-110 transition-all duration-300 mb-4 border border-gray-100">
<BaseIcon path={feature.icon} size={24} className="text-amber-600 group-hover:text-white transition-colors" />
</div>
<h4 className="text-xs font-black text-gray-900 uppercase tracking-widest font-sans">{feature.title}</h4>
</div>
))}
</ScrollReveal>
</div>
</div>
</div>
</section>
);
};
export default About;

View File

@ -0,0 +1,217 @@
import React, { useState } from 'react';
import axios from 'axios';
import { mdiSend, mdiPhone, mdiEmail, mdiMapMarker, mdiCheckCircleOutline } from '@mdi/js';
import BaseIcon from '../BaseIcon';
import ScrollReveal from './ScrollReveal';
const ContactForm = () => {
const [formData, setFormData] = useState({
full_name: '',
email: '',
phone: '',
message: '',
city: '',
preferred_contact_method: 'phone'
});
const [isSubmitting, setIsSubmitting] = useState(false);
const [isSuccess, setIsSuccess] = useState(false);
const [error, setError] = useState('');
const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>) => {
setFormData({
...formData,
[e.target.name]: e.target.value
});
};
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setIsSubmitting(true);
setError('');
try {
await axios.post('/leads', {
data: {
...formData,
source: 'website_form',
requested_at: new Date().toISOString(),
consent_to_contact: true
}
});
setIsSuccess(true);
setFormData({
full_name: '',
email: '',
phone: '',
message: '',
city: '',
preferred_contact_method: 'phone'
});
} catch (err) {
console.error(err);
setError('Mesajınız iletilemedi. Lütfen daha sonra tekrar deneyiniz.');
} finally {
setIsSubmitting(false);
}
};
return (
<section id="iletisim" className="py-24 bg-gray-50 overflow-hidden relative">
{/* Background Decor */}
<div className="absolute top-0 right-0 w-1/3 h-full bg-amber-600/5 -skew-x-12 translate-x-1/2 -z-10"></div>
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 relative z-10">
<div className="grid grid-cols-1 lg:grid-cols-2 gap-20 items-center">
<div>
<ScrollReveal animation="fade-in-left">
<h2 className="text-xs font-black text-amber-600 uppercase tracking-[0.2em] mb-4 font-sans">Hemen İletişime Geçin</h2>
<h3 className="text-4xl md:text-5xl font-black text-gray-900 mb-8 leading-tight font-sans">Projeniz İçin Ücretsiz <br />Keşif ve Fiyat Alın</h3>
<p className="text-xl text-gray-500 mb-12 max-w-lg leading-relaxed font-medium font-body">
Uzman ekibimizle en kısa sürede size geri dönüş sağlayacağız. İster arayın, ister formu doldurun.
</p>
</ScrollReveal>
<div className="space-y-8">
{[
{ icon: mdiPhone, label: 'Telefon', value: '+90 500 000 00 00', delay: 100 },
{ icon: mdiEmail, label: 'E-Posta', value: 'info@bekakaplama.com', delay: 200 },
{ icon: mdiMapMarker, label: 'Adres', value: 'İstanbul, Türkiye', delay: 300 }
].map((item, i) => (
<ScrollReveal key={i} animation="fade-in-left" delay={item.delay}>
<div className="flex items-start space-x-6 group cursor-default">
<div className="p-5 bg-white shadow-lg rounded-2xl group-hover:bg-amber-600 group-hover:scale-110 transition-all duration-300 border border-gray-100">
<BaseIcon path={item.icon} size={28} className="text-amber-600 group-hover:text-white transition-colors" />
</div>
<div>
<h4 className="text-xs font-black text-amber-600 uppercase tracking-widest mb-1 font-sans">{item.label}</h4>
<p className="text-2xl font-black text-gray-900 group-hover:text-amber-600 transition-colors font-sans">{item.value}</p>
</div>
</div>
</ScrollReveal>
))}
</div>
</div>
<ScrollReveal animation="fade-in-right" delay={200}>
<div className="bg-white p-10 rounded-[3rem] shadow-2xl border border-gray-100 relative overflow-hidden group">
{/* Decorative circle */}
<div className="absolute -top-24 -right-24 w-48 h-48 bg-amber-600/5 rounded-full blur-3xl transition-all duration-1000 group-hover:bg-amber-600/10"></div>
{isSuccess ? (
<div className="text-center py-20 animate-scale-in">
<div className="w-24 h-24 bg-green-100 rounded-full flex items-center justify-center mx-auto mb-8 animate-bounce">
<BaseIcon path={mdiCheckCircleOutline} size={48} className="text-green-600" />
</div>
<h4 className="text-3xl font-black text-gray-900 mb-4 tracking-tight font-sans">Mesajınız Alındı!</h4>
<p className="text-gray-600 mb-10 font-medium font-body">En kısa sürede uzman ekibimiz tarafından aranacaksınız.</p>
<button
onClick={() => setIsSuccess(false)}
className="px-10 py-4 bg-amber-600 text-white rounded-2xl font-black hover:bg-amber-700 transition-all shadow-xl shadow-amber-900/20 active:scale-95 font-sans"
>
Yeni Mesaj Gönder
</button>
</div>
) : (
<form onSubmit={handleSubmit} className="space-y-6 relative z-10 font-sans">
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div className="space-y-2">
<label className="text-xs font-black text-gray-400 uppercase tracking-widest px-1">Ad Soyad</label>
<input
type="text"
name="full_name"
required
value={formData.full_name}
onChange={handleChange}
placeholder="Örn: Ahmet Yılmaz"
className="w-full px-6 py-4 bg-gray-50 border-2 border-transparent rounded-2xl focus:outline-none focus:bg-white focus:border-amber-600 transition-all font-bold text-gray-800 placeholder:font-medium placeholder:text-gray-300"
/>
</div>
<div className="space-y-2">
<label className="text-xs font-black text-gray-400 uppercase tracking-widest px-1">Telefon</label>
<input
type="tel"
name="phone"
required
value={formData.phone}
onChange={handleChange}
placeholder="05XX XXX XX XX"
className="w-full px-6 py-4 bg-gray-50 border-2 border-transparent rounded-2xl focus:outline-none focus:bg-white focus:border-amber-600 transition-all font-bold text-gray-800 placeholder:font-medium placeholder:text-gray-300"
/>
</div>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div className="space-y-2">
<label className="text-xs font-black text-gray-400 uppercase tracking-widest px-1">E-Posta (İsteğe Bağlı)</label>
<input
type="email"
name="email"
value={formData.email}
onChange={handleChange}
placeholder="ahmet@example.com"
className="w-full px-6 py-4 bg-gray-50 border-2 border-transparent rounded-2xl focus:outline-none focus:bg-white focus:border-amber-600 transition-all font-bold text-gray-800 placeholder:font-medium placeholder:text-gray-300"
/>
</div>
<div className="space-y-2">
<label className="text-xs font-black text-gray-400 uppercase tracking-widest px-1">Şehir</label>
<input
type="text"
name="city"
value={formData.city}
onChange={handleChange}
placeholder="Örn: İstanbul"
className="w-full px-6 py-4 bg-gray-50 border-2 border-transparent rounded-2xl focus:outline-none focus:bg-white focus:border-amber-600 transition-all font-bold text-gray-800 placeholder:font-medium placeholder:text-gray-300"
/>
</div>
</div>
<div className="space-y-2">
<label className="text-xs font-black text-gray-400 uppercase tracking-widest px-1">Ulaşım Tercihi</label>
<select
name="preferred_contact_method"
value={formData.preferred_contact_method}
onChange={handleChange}
className="w-full px-6 py-4 bg-gray-50 border-2 border-transparent rounded-2xl focus:outline-none focus:bg-white focus:border-amber-600 transition-all font-black text-gray-700 appearance-none cursor-pointer"
>
<option value="phone">Telefon Araması</option>
<option value="whatsapp">WhatsApp Mesajı</option>
<option value="email">E-Posta</option>
</select>
</div>
<div className="space-y-2">
<label className="text-xs font-black text-gray-400 uppercase tracking-widest px-1">Mesajınız</label>
<textarea
name="message"
required
rows={4}
value={formData.message}
onChange={handleChange}
placeholder="Projeniz hakkında kısa bir bilgi veriniz..."
className="w-full px-6 py-4 bg-gray-50 border-2 border-transparent rounded-2xl focus:outline-none focus:bg-white focus:border-amber-600 transition-all font-bold text-gray-800 placeholder:font-medium placeholder:text-gray-300 resize-none"
></textarea>
</div>
{error && <p className="text-red-500 font-bold text-center animate-pulse">{error}</p>}
<button
type="submit"
disabled={isSubmitting}
className="w-full py-5 bg-amber-600 text-white rounded-[1.5rem] font-black text-lg hover:bg-amber-700 transition-all flex items-center justify-center space-x-3 shadow-xl shadow-amber-900/20 disabled:opacity-70 group active:scale-95 font-sans"
>
<span>{isSubmitting ? 'Gönderiliyor...' : 'Teklif Almayı Tamamla'}</span>
{!isSubmitting && <BaseIcon path={mdiSend} size={24} className="group-hover:translate-x-1 group-hover:-translate-y-1 transition-transform" />}
</button>
</form>
)}
</div>
</ScrollReveal>
</div>
</div>
</section>
);
};
export default ContactForm;

View File

@ -0,0 +1,111 @@
import React from 'react';
import Link from 'next/link';
import { mdiFacebook, mdiInstagram, mdiLinkedin, mdiTwitter } from '@mdi/js';
import BaseIcon from '../BaseIcon';
import ScrollReveal from './ScrollReveal';
const Footer = () => {
return (
<footer className="bg-gray-950 text-white pt-24 pb-12 overflow-hidden relative">
<div className="absolute top-0 left-0 w-full h-px bg-gradient-to-r from-transparent via-amber-600/30 to-transparent"></div>
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 relative z-10">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-16 mb-20">
<ScrollReveal animation="fade-in-up">
<div className="col-span-1 lg:col-span-1">
<Link href="/" className="inline-block mb-10 group transition-transform duration-500 hover:scale-105 active:scale-95">
<div className="bg-white p-2.5 rounded-[1.5rem] shadow-2xl flex items-center justify-center w-fit border border-white/10 group-hover:border-amber-600/30 transition-colors">
<img src="/logo-beka.png" alt="Beka Kaplama" className="h-16 w-auto object-contain" />
</div>
</Link>
<p className="text-gray-400 leading-relaxed mb-10 max-w-sm font-medium font-body">
Yaşam alanlarınıza estetik, konfor ve değer katan modern kaplama çözümleri sunuyoruz. Yılların tecrübesi ve uzman ekibimizle projelerinizi hayata geçiriyoruz.
</p>
<div className="flex space-x-4">
{[mdiFacebook, mdiInstagram, mdiLinkedin, mdiTwitter].map((icon, i) => (
<a key={i} href="#" className="p-3 bg-white/5 border border-white/10 rounded-2xl hover:bg-amber-600 hover:border-amber-600 transition-all duration-300 hover:-translate-y-1.5 active:scale-90 group">
<BaseIcon path={icon} size={22} className="text-gray-400 group-hover:text-white transition-colors" />
</a>
))}
</div>
</div>
</ScrollReveal>
<ScrollReveal animation="fade-in-up" delay={100}>
<div>
<h4 className="text-xs font-black uppercase tracking-[0.2em] text-amber-500 mb-10 px-1 border-l-4 border-amber-600 pl-4 font-sans">Kurumsal</h4>
<ul className="space-y-5 font-bold font-sans">
{[
{ name: 'Anasayfa', href: '/' },
{ name: 'Hakkımızda', href: '/hakkimizda' },
{ name: 'Referanslar', href: '/projeler' },
{ name: 'İletişim', href: '/iletisim' }
].map((link, i) => (
<li key={i}>
<Link href={link.href} className="text-gray-400 hover:text-white transition-all flex items-center group">
<span className="w-0 group-hover:w-3 h-0.5 bg-amber-600 mr-0 group-hover:mr-3 transition-all"></span>
{link.name}
</Link>
</li>
))}
</ul>
</div>
</ScrollReveal>
<ScrollReveal animation="fade-in-up" delay={200}>
<div>
<h4 className="text-xs font-black uppercase tracking-[0.2em] text-amber-500 mb-10 px-1 border-l-4 border-amber-600 pl-4 font-sans">Hizmetlerimiz</h4>
<ul className="space-y-5 font-bold font-sans">
{[
'Akustik Panel Sistemleri',
'PU Cephe Lambri Kaplama',
'PVC Mermer Plaka Uygulamaları',
'Özel 3D Duvar Tasarımları'
].map((item, i) => (
<li key={i}>
<Link href="/hizmetler" className="text-gray-400 hover:text-white transition-all flex items-center group">
<span className="w-0 group-hover:w-3 h-0.5 bg-amber-600 mr-0 group-hover:mr-3 transition-all"></span>
{item}
</Link>
</li>
))}
</ul>
</div>
</ScrollReveal>
<ScrollReveal animation="fade-in-up" delay={300}>
<div className="bg-white/5 border border-white/10 p-10 rounded-[2.5rem] relative overflow-hidden group">
<div className="absolute -top-10 -right-10 w-32 h-32 bg-amber-600/10 rounded-full blur-2xl group-hover:scale-150 transition-transform duration-1000"></div>
<h4 className="text-xs font-black uppercase tracking-[0.2em] text-amber-500 mb-6 px-1 border-l-4 border-amber-600 pl-4 relative z-10 font-sans">Teklif Al</h4>
<p className="text-gray-400 mb-8 font-medium relative z-10 leading-relaxed font-body">Bize projelerinizden bahsedin, size en uygun çözümü sunalım.</p>
<Link
href="/iletisim"
className="block w-full text-center py-5 bg-amber-600 text-white rounded-[1.25rem] font-black hover:bg-amber-700 transition-all shadow-xl shadow-amber-900/20 active:scale-95 relative z-10 uppercase tracking-widest text-xs font-sans"
>
Ücretsiz Keşif İste
</Link>
</div>
</ScrollReveal>
</div>
<div className="pt-12 border-t border-white/5 flex flex-col md:flex-row justify-between items-center space-y-6 md:space-y-0 text-[10px] font-black uppercase tracking-[0.2em] text-gray-500 font-sans">
<p className="hover:text-gray-300 transition-colors">© 2026 Beka Kaplama Sistemleri. Tüm Hakları Saklıdır.</p>
<div className="flex flex-wrap justify-center gap-8">
<Link href="/privacy-policy" className="hover:text-amber-500 transition-colors">Gizlilik</Link>
<Link href="/terms-of-use" className="hover:text-amber-500 transition-colors">Şartlar</Link>
<Link href="/login" className="hover:text-white transition-colors text-gray-500 flex items-center space-x-1 group">
<span className="w-1.5 h-1.5 rounded-full bg-gray-700 group-hover:bg-amber-600 transition-colors"></span>
<span>Yönetici Paneli</span>
</Link>
</div>
</div>
</div>
{/* Footer Accent Bar */}
<div className="absolute bottom-0 left-0 w-full h-1 bg-gradient-to-r from-transparent via-amber-600 to-transparent opacity-50"></div>
</footer>
);
};
export default Footer;

View File

@ -0,0 +1,88 @@
import React from 'react';
import Link from 'next/link';
import { mdiArrowRight, mdiWhatsapp } from '@mdi/js';
import BaseIcon from '../BaseIcon';
const Hero = () => {
return (
<section className="relative h-screen flex items-center bg-gray-900 overflow-hidden pt-20">
{/* Background with Animation */}
<div className="absolute inset-0 opacity-40 scale-110 animate-[pulse_10s_infinite]">
<img
src="https://images.pexels.com/photos/1571460/pexels-photo-1571460.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2"
alt="Beka Kaplama Hero"
className="w-full h-full object-cover transition-transform duration-[10000ms] hover:scale-105"
/>
<div className="absolute inset-0 bg-gradient-to-r from-gray-900 via-gray-900/60 to-transparent"></div>
</div>
<div className="relative max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 w-full z-10">
<div className="max-w-2xl">
{/* Badge with Animation */}
<div className="inline-flex items-center space-x-2 px-3 py-1 bg-amber-600/20 border border-amber-600/30 rounded-full mb-6 animate-fade-in-left">
<span className="w-2 h-2 bg-amber-600 rounded-full animate-pulse"></span>
<span className="text-xs font-bold text-amber-500 uppercase tracking-widest font-sans">Modern Kaplama Sistemleri</span>
</div>
{/* Headline with Animation */}
<h1 className="text-5xl md:text-7xl font-black text-white leading-tight mb-8 animate-fade-in-up [animation-delay:200ms] font-sans">
Mekanlarınıza <br />
<span className="font-serif italic text-transparent bg-clip-text bg-gradient-to-r from-amber-400 to-amber-600 underline decoration-amber-600/30">Estetik ve Güç</span> <br />
Katıyoruz.
</h1>
{/* Subtext with Animation */}
<p className="text-xl text-gray-300 mb-10 leading-relaxed max-w-xl animate-fade-in-up [animation-delay:400ms] font-body">
Akustik panelden PVC mermer plakaya, 3D uygulamalardan PU cephe lambri sistemlerine kadar geniş ürün yelpazemizle hayalinizdeki mekanları gerçeğe dönüştürüyoruz.
</p>
{/* Buttons with Animation */}
<div className="flex flex-col sm:flex-row space-y-4 sm:space-y-0 sm:space-x-6 animate-fade-in-up [animation-delay:600ms]">
<Link
href="/iletisim"
className="px-8 py-4 bg-amber-600 text-white rounded-xl font-black hover:bg-amber-700 transition-all flex items-center justify-center space-x-2 shadow-xl shadow-amber-900/20 group hover:-translate-y-1 active:scale-95 font-sans"
>
<span>Ücretsiz Teklif Al</span>
<BaseIcon path={mdiArrowRight} size={20} className="group-hover:translate-x-1 transition-transform" />
</Link>
<a
href="https://wa.me/905000000000"
target="_blank"
rel="noreferrer"
className="px-8 py-4 bg-white/10 backdrop-blur-md text-white border border-white/20 rounded-xl font-black hover:bg-white/20 transition-all flex items-center justify-center space-x-2 hover:-translate-y-1 active:scale-95 font-sans"
>
<BaseIcon path={mdiWhatsapp} size={24} className="text-green-400" />
<span>WhatsApp Destek</span>
</a>
</div>
{/* Stats with Animation */}
<div className="mt-16 flex items-center space-x-12 opacity-70 border-t border-white/10 pt-10 animate-fade-in [animation-delay:800ms]">
<div className="hover:opacity-100 transition-opacity cursor-default group">
<div className="text-3xl font-black text-white group-hover:text-amber-500 transition-colors font-sans">100+</div>
<div className="text-xs text-gray-400 uppercase tracking-widest mt-1 font-body">Tamamlanan Proje</div>
</div>
<div className="hover:opacity-100 transition-opacity cursor-default group">
<div className="text-3xl font-black text-white group-hover:text-amber-500 transition-colors font-sans">15+</div>
<div className="text-xs text-gray-400 uppercase tracking-widest mt-1 font-body">Yıllık Tecrübe</div>
</div>
<div className="hover:opacity-100 transition-opacity cursor-default group">
<div className="text-3xl font-black text-white group-hover:text-amber-500 transition-colors font-sans">%100</div>
<div className="text-xs text-gray-400 uppercase tracking-widest mt-1 font-body">Müşteri Memnuniyeti</div>
</div>
</div>
</div>
</div>
{/* Scroll Down Indicator */}
<div className="absolute bottom-10 left-1/2 -translate-x-1/2 animate-bounce-soft hidden md:block">
<div className="w-6 h-10 border-2 border-white/30 rounded-full flex justify-center p-1">
<div className="w-1 h-2 bg-white/60 rounded-full"></div>
</div>
</div>
</section>
);
};
export default Hero;

View File

@ -0,0 +1,172 @@
import React, { useState, useEffect } from 'react';
import Link from 'next/link';
import { useRouter } from 'next/router';
import { mdiMenu, mdiClose, mdiPhone } from '@mdi/js';
import BaseIcon from '../BaseIcon';
const Navbar = () => {
const [isOpen, setIsOpen] = useState(false);
const [isScrolled, setIsScrolled] = useState(false);
const router = useRouter();
useEffect(() => {
const handleScroll = () => {
if (window.scrollY > 50) {
setIsScrolled(true);
} else {
setIsScrolled(false);
}
};
window.addEventListener('scroll', handleScroll);
return () => window.removeEventListener('scroll', handleScroll);
}, []);
// Determine if we are on the home page
const isHome = router.pathname === '/';
const navLinks = [
{ name: 'Anasayfa', href: '/' },
{ name: 'Hakkımızda', href: '/hakkimizda' },
{ name: 'Hizmetler', href: '/hizmetler' },
{ name: 'Projeler', href: '/projeler' },
{ name: 'İletişim', href: '/iletisim' },
];
return (
<nav className={`fixed w-full z-50 transition-all duration-500 ease-in-out ${
isScrolled || !isHome
? 'bg-white/90 backdrop-blur-xl shadow-2xl py-2 border-b border-gray-100'
: 'bg-transparent py-6'
}`}>
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex justify-between items-center h-16">
<div className="flex items-center">
<Link href="/" className="flex items-center group transition-transform duration-300 hover:scale-105 active:scale-95">
<div className={`p-1.5 rounded-2xl transition-all duration-500 flex items-center justify-center ${
isScrolled || !isHome ? 'bg-white shadow-xl shadow-black/5' : 'bg-white/10 backdrop-blur-md'
}`}>
<img
src="/logo-beka.png"
alt="Beka Kaplama"
className="h-10 md:h-12 w-auto object-contain"
/>
</div>
</Link>
</div>
<div className="hidden md:flex items-center space-x-2 font-sans">
<div className="flex items-center space-x-8 px-8 border-r border-gray-200">
{navLinks.map((link) => (
<Link
key={link.name}
href={link.href}
className={`font-black transition-all text-[11px] uppercase tracking-[0.2em] relative group ${
isScrolled || !isHome ? 'text-gray-900' : 'text-white'
}`}
>
<span className={`group-hover:text-amber-600 transition-colors ${
router.pathname === link.href ? 'text-amber-600' : ''
}`}>
{link.name}
</span>
<span className={`absolute -bottom-2 left-0 h-0.5 bg-amber-600 transition-all duration-300 ${
router.pathname === link.href ? 'w-full' : 'w-0 group-hover:w-full'
}`}></span>
</Link>
))}
</div>
<div className="flex items-center space-x-4 pl-4">
<a
href="tel:+905000000000"
className={`flex items-center space-x-2 transition-colors ${
isScrolled || !isHome ? 'text-gray-600 hover:text-amber-600' : 'text-white/80 hover:text-white'
}`}
>
<BaseIcon path={mdiPhone} size={18} />
<span className="text-sm font-black tracking-tight">+90 500 000 00 00</span>
</a>
<Link
href="/iletisim"
className="px-6 py-3 bg-amber-600 text-white rounded-[1rem] font-black hover:bg-amber-700 transition-all shadow-xl shadow-amber-900/20 text-xs uppercase tracking-widest hover:-translate-y-0.5 active:scale-95"
>
Ücretsiz Teklif Al
</Link>
</div>
</div>
<div className="md:hidden flex items-center">
<button
onClick={() => setIsOpen(!isOpen)}
className={`p-2 rounded-xl transition-all ${
isScrolled || !isHome
? 'text-gray-900 bg-gray-50'
: 'text-white bg-white/10 backdrop-blur-md'
} focus:outline-none`}
>
<BaseIcon path={isOpen ? mdiClose : mdiMenu} size={32} />
</button>
</div>
</div>
</div>
{/* Mobile Menu Overlay */}
<div className={`fixed inset-0 bg-gray-900/40 backdrop-blur-sm z-40 md:hidden transition-all duration-500 ${
isOpen ? 'opacity-100 visible' : 'opacity-0 invisible'
}`} onClick={() => setIsOpen(false)}></div>
{/* Mobile Menu Content */}
<div className={`fixed inset-y-0 right-0 w-[80%] bg-white z-50 md:hidden transition-all duration-500 ease-in-out transform ${
isOpen ? 'translate-x-0' : 'translate-x-full'
}`}>
<div className="flex flex-col h-full font-sans">
<div className="flex justify-between items-center p-8 border-b border-gray-100">
<div className="bg-white p-2 rounded-2xl shadow-xl shadow-black/5 border border-gray-100">
<img src="/logo-beka.png" alt="Beka Kaplama" className="h-10 w-auto object-contain" />
</div>
<button
onClick={() => setIsOpen(false)}
className="p-2 text-gray-400 hover:text-amber-600 transition-colors"
>
<BaseIcon path={mdiClose} size={32} />
</button>
</div>
<div className="flex flex-col space-y-6 p-8 overflow-y-auto">
{navLinks.map((link, i) => (
<Link
key={link.name}
href={link.href}
onClick={() => setIsOpen(false)}
className={`text-4xl font-black tracking-tighter transition-all duration-300 ${
router.pathname === link.href ? 'text-amber-600 pl-4 border-l-8 border-amber-600' : 'text-gray-900 hover:text-amber-600 hover:pl-4'
}`}
style={{ transitionDelay: `${i * 50}ms` }}
>
{link.name}
</Link>
))}
</div>
<div className="mt-auto p-8 bg-gray-50 border-t border-gray-100">
<Link
href="/iletisim"
onClick={() => setIsOpen(false)}
className="w-full text-center px-8 py-6 bg-amber-600 text-white rounded-3xl font-black text-xl shadow-2xl shadow-amber-900/40 mb-8 block hover:bg-amber-700 active:scale-95 transition-all"
>
Ücretsiz Teklif Al
</Link>
<div className="text-center">
<p className="text-gray-400 font-bold uppercase tracking-widest text-[10px] mb-2">Bize Ulaşın</p>
<a href="tel:+905000000000" className="text-2xl font-black text-gray-900 hover:text-amber-600 transition-colors">+90 500 000 00 00</a>
</div>
</div>
</div>
</div>
</nav>
);
};
export default Navbar;

View File

@ -0,0 +1,59 @@
import React from 'react';
import ScrollReveal from './ScrollReveal';
interface PageHeroProps {
title: string;
subtitle: string;
image?: string;
}
const PageHero = ({
title,
subtitle,
image = "https://images.pexels.com/photos/1571460/pexels-photo-1571460.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2"
}: PageHeroProps) => {
return (
<section className="relative py-32 bg-gray-900 overflow-hidden">
{/* Background with subtle animation */}
<div className="absolute inset-0 opacity-40 animate-[pulse_15s_infinite]">
<img
src={image}
alt={title}
className="w-full h-full object-cover"
/>
<div className="absolute inset-0 bg-gradient-to-b from-gray-900 via-gray-900/80 to-gray-950"></div>
</div>
<div className="relative max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center z-10">
<ScrollReveal animation="fade-in-up">
<h1 className="text-5xl md:text-7xl font-black text-white leading-tight mb-8 tracking-tighter font-sans">
{title}
</h1>
</ScrollReveal>
<ScrollReveal animation="fade-in-up" delay={200}>
<div className="flex items-center justify-center space-x-4 mb-8">
<div className="w-12 h-1 bg-amber-600 rounded-full"></div>
<p className="text-xl md:text-2xl text-amber-500 font-bold uppercase tracking-[0.3em] font-sans">
{subtitle}
</p>
<div className="w-12 h-1 bg-amber-600 rounded-full"></div>
</div>
</ScrollReveal>
<ScrollReveal animation="fade-in-up" delay={400}>
<div className="inline-flex items-center space-x-2 text-xs font-black text-gray-500 uppercase tracking-widest bg-white/5 backdrop-blur-md px-4 py-2 rounded-full border border-white/10 font-sans">
<span>Anasayfa</span>
<span className="text-amber-600">/</span>
<span className="text-white">{title}</span>
</div>
</ScrollReveal>
</div>
{/* Accent decoration */}
<div className="absolute bottom-0 left-0 w-full h-24 bg-gradient-to-t from-white to-transparent opacity-10"></div>
</section>
);
};
export default PageHero;

View File

@ -0,0 +1,147 @@
import React, { useState } from 'react';
import { mdiArrowRight, mdiMagnifyPlusOutline } from '@mdi/js';
import BaseIcon from '../BaseIcon';
import ScrollReveal from './ScrollReveal';
const projects = [
{
title: 'Modern Ofis Akustik Panel',
category: 'Akustik Panel',
image: 'https://images.pexels.com/photos/1571460/pexels-photo-1571460.jpeg?auto=compress&cs=tinysrgb&w=800'
},
{
title: 'Dış Cephe PU Lambri',
category: 'PU Lambri',
image: 'https://images.pexels.com/photos/1571470/pexels-photo-1571470.jpeg?auto=compress&cs=tinysrgb&w=800'
},
{
title: 'Mutfak PVC Mermer Kaplama',
category: 'PVC Mermer',
image: 'https://images.pexels.com/photos/1571460/pexels-photo-1571460.jpeg?auto=compress&cs=tinysrgb&w=800'
},
{
title: 'Oturma Odası 3D Duvar',
category: '3D Uygulamalar',
image: 'https://images.pexels.com/photos/1571470/pexels-photo-1571470.jpeg?auto=compress&cs=tinysrgb&w=800'
},
{
title: 'Restoran Ses Yalıtımı',
category: 'Akustik Çözümler',
image: 'https://images.pexels.com/photos/1571460/pexels-photo-1571460.jpeg?auto=compress&cs=tinysrgb&w=800'
},
{
title: 'Villa Dış Cephe Kaplama',
category: 'PU Cephe',
image: 'https://images.pexels.com/photos/1571470/pexels-photo-1571470.jpeg?auto=compress&cs=tinysrgb&w=800'
}
];
const categories = ['Tümü', 'Akustik Panel', 'PU Lambri', 'PVC Mermer', '3D Uygulamalar'];
const Projects = () => {
const [activeCategory, setActiveCategory] = useState('Tümü');
const filteredProjects = activeCategory === 'Tümü'
? projects
: projects.filter(p => p.category === activeCategory);
return (
<section id="projeler" className="py-24 bg-white overflow-hidden relative">
{/* Background Decoration */}
<div className="absolute top-0 left-0 w-full h-full opacity-[0.03] pointer-events-none -z-10">
<svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="grid" width="40" height="40" patternUnits="userSpaceOnUse">
<path d="M 40 0 L 0 0 0 40" fill="none" stroke="currentColor" strokeWidth="1"/>
</pattern>
</defs>
<rect width="100%" height="100%" fill="url(#grid)" />
</svg>
</div>
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex flex-col md:flex-row justify-between items-end mb-16 gap-8">
<ScrollReveal animation="fade-in-left">
<div>
<h2 className="text-xs font-black text-amber-600 uppercase tracking-[0.2em] mb-4 text-center md:text-left font-sans">Referans Projelerimiz</h2>
<h3 className="text-4xl md:text-5xl font-black text-gray-900 leading-tight text-center md:text-left font-sans">Hayata Geçirdiğimiz <br />En Seçkin Projeler</h3>
</div>
</ScrollReveal>
<ScrollReveal animation="fade-in-right" delay={200}>
<div className="flex flex-wrap gap-2 justify-center font-sans">
{categories.map((cat) => (
<button
key={cat}
onClick={() => setActiveCategory(cat)}
className={`px-6 py-2.5 rounded-full text-sm font-bold transition-all border ${
activeCategory === cat
? 'bg-amber-600 text-white border-amber-600 shadow-lg shadow-amber-900/10 scale-105'
: 'bg-white text-gray-600 border-gray-200 hover:border-amber-600 hover:text-amber-600'
}`}
>
{cat}
</button>
))}
</div>
</ScrollReveal>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-10">
{filteredProjects.map((project, index) => (
<ScrollReveal
key={`${project.title}-${index}`}
animation="scale-in"
delay={index * 100}
>
<div className="group relative rounded-3xl overflow-hidden bg-white shadow-sm hover:shadow-2xl transition-all duration-500 hover:-translate-y-3 border border-gray-100 active:scale-95">
<div className="aspect-[4/5] overflow-hidden">
<img
src={project.image}
alt={project.title}
className="w-full h-full object-cover group-hover:scale-110 transition-transform duration-1000"
/>
</div>
{/* Overlay */}
<div className="absolute inset-0 bg-gradient-to-t from-gray-900 via-gray-900/40 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-500 flex flex-col justify-end p-10">
<div className="translate-y-10 group-hover:translate-y-0 transition-transform duration-500">
<span className="inline-block px-3 py-1 bg-amber-600 text-[10px] font-black uppercase tracking-widest text-white rounded-full mb-4 font-sans">
{project.category}
</span>
<h4 className="text-2xl font-black text-white mb-6 leading-tight font-sans">
{project.title}
</h4>
<div className="flex items-center space-x-2 text-white font-bold text-sm group/btn cursor-pointer font-sans">
<div className="w-12 h-12 bg-white/20 backdrop-blur rounded-full flex items-center justify-center group-hover/btn:bg-amber-600 group-hover/btn:scale-110 transition-all duration-300">
<BaseIcon path={mdiMagnifyPlusOutline} size={24} />
</div>
<span className="group-hover/btn:text-amber-400 transition-colors">Projeyi İncele</span>
</div>
</div>
</div>
</div>
</ScrollReveal>
))}
</div>
<ScrollReveal animation="fade-in-up" delay={400}>
<div className="mt-20 text-center">
<p className="text-gray-500 font-bold mb-8 font-body">Daha fazla proje ve detaylı bilgi için bize ulaşın.</p>
<a
href="https://wa.me/905000000000"
target="_blank"
rel="noreferrer"
className="inline-flex items-center space-x-4 px-10 py-5 bg-amber-600 text-white rounded-2xl font-black hover:bg-amber-700 transition-all shadow-xl shadow-amber-900/20 group hover:-translate-y-1 font-sans"
>
<span>Tüm Projeleri WhatsApp&apos;tan İste</span>
<BaseIcon path={mdiArrowRight} size={24} className="group-hover:translate-x-1 transition-transform" />
</a>
</div>
</ScrollReveal>
</div>
</section>
);
};
export default Projects;

View File

@ -0,0 +1,43 @@
import React, { useRef, ReactNode } from 'react';
import { useIntersectionObserver } from '../../hooks/useIntersectionObserver';
interface ScrollRevealProps {
children: ReactNode;
animation?: 'fade-in-up' | 'fade-in-left' | 'fade-in-right' | 'scale-in' | 'fade-in';
delay?: number;
className?: string;
threshold?: number;
}
const ScrollReveal = ({
children,
animation = 'fade-in-up',
delay = 0,
className = '',
threshold = 0.1
}: ScrollRevealProps) => {
const ref = useRef<HTMLDivElement>(null);
const entry = useIntersectionObserver(ref, {
threshold,
freezeOnceVisible: true
});
const isVisible = !!entry?.isIntersecting;
const animationClass = isVisible ? `animate-${animation}` : 'opacity-0';
return (
<div
ref={ref}
className={`${animationClass} ${className}`}
style={{
animationDelay: `${delay}ms`,
animationFillMode: 'forwards'
}}
>
{children}
</div>
);
};
export default ScrollReveal;

View File

@ -0,0 +1,72 @@
import React from 'react';
import Link from 'next/link';
import BaseIcon from '../BaseIcon';
import ScrollReveal from './ScrollReveal';
import { bekaServices } from '../../data/bekaServices';
const Services = () => {
return (
<section id="hizmetler" className="py-24 bg-gray-50 relative overflow-hidden">
{/* Background Decor */}
<div className="absolute top-0 right-0 w-1/3 h-1/3 bg-amber-500/5 blur-[120px] -z-10"></div>
<div className="absolute bottom-0 left-0 w-1/3 h-1/3 bg-amber-600/5 blur-[120px] -z-10"></div>
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<ScrollReveal animation="fade-in-up">
<div className="text-center mb-16">
<h2 className="text-xs font-black text-amber-600 uppercase tracking-[0.2em] mb-4 font-sans">Uzmanlık Alanlarımız</h2>
<h3 className="text-4xl md:text-5xl font-black text-gray-900 mb-6 leading-tight font-sans">Mekanlarınıza Hayat Veren <br />Uygulamalar</h3>
<p className="text-xl text-gray-500 max-w-2xl mx-auto font-medium font-body">
Beka Kaplama olarak en kaliteli malzemeleri uzman işçilikle birleştirerek yaşam alanlarınıza değer katıyoruz.
</p>
</div>
</ScrollReveal>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
{bekaServices.map((service, index) => (
<ScrollReveal
key={service.id}
animation="fade-in-up"
delay={index * 150}
className="h-full"
>
<div className="bg-white rounded-3xl overflow-hidden shadow-sm hover:shadow-2xl transition-all duration-500 group hover:-translate-y-3 border border-gray-100 flex flex-col h-full active:scale-95">
<div className="relative h-56 overflow-hidden">
<img
src={service.image}
alt={service.title}
className="w-full h-full object-cover group-hover:scale-110 transition-transform duration-700"
/>
<div className="absolute inset-0 bg-gradient-to-t from-black/20 to-transparent"></div>
<div className="absolute top-4 left-4 p-4 bg-white/90 backdrop-blur rounded-2xl shadow-xl transform group-hover:rotate-12 transition-transform duration-500">
<BaseIcon path={service.icon} size={24} className="text-amber-600" />
</div>
</div>
<div className="p-8 flex-grow flex flex-col">
<h4 className="text-2xl font-black text-gray-900 mb-4 group-hover:text-amber-600 transition-colors font-sans">
{service.title}
</h4>
<p className="text-gray-500 leading-relaxed text-sm mb-6 flex-grow font-medium font-body">
{service.shortDescription}
</p>
<div className="mt-auto">
<Link href={`/hizmet/${service.slug}`} className="inline-flex items-center space-x-2 text-amber-600 font-black text-xs uppercase tracking-widest group/btn font-sans">
<span>Detayları İncele</span>
<div className="w-5 h-5 bg-amber-100 rounded-full flex items-center justify-center group-hover/btn:translate-x-1 transition-transform">
<svg className="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="3" d="M9 5l7 7-7 7" />
</svg>
</div>
</Link>
</div>
</div>
</div>
</ScrollReveal>
))}
</div>
</div>
</section>
);
};
export default Services;

View File

@ -0,0 +1,25 @@
import React from 'react';
import { mdiWhatsapp } from '@mdi/js';
import BaseIcon from '../BaseIcon';
const WhatsAppButton = () => {
return (
<a
href="https://wa.me/905000000000"
target="_blank"
rel="noreferrer"
className="fixed bottom-8 right-8 z-[100] p-5 bg-[#25D366] text-white rounded-[1.5rem] shadow-[0_20px_40px_-15px_rgba(37,211,102,0.4)] hover:bg-[#128C7E] transition-all hover:scale-110 active:scale-90 group border-4 border-white active:translate-y-2"
>
<div className="absolute inset-0 bg-[#25D366] rounded-full animate-ping opacity-30 -z-10 group-hover:scale-150 transition-transform duration-1000"></div>
<BaseIcon path={mdiWhatsapp} size={32} />
{/* Tooltip */}
<span className="absolute right-full mr-6 top-1/2 -translate-y-1/2 px-5 py-3 bg-white text-gray-950 rounded-2xl font-black text-xs uppercase tracking-widest shadow-2xl opacity-0 group-hover:opacity-100 translate-x-4 group-hover:translate-x-0 transition-all pointer-events-none whitespace-nowrap border border-gray-100 ring-4 ring-black/5">
WhatsApp Destek Hattı
<div className="absolute top-1/2 -translate-y-1/2 left-full w-2 h-2 bg-white rotate-45 -ml-1 border-r border-t border-gray-100"></div>
</span>
</a>
);
};
export default WhatsAppButton;

View File

@ -1,6 +1,5 @@
import React, {useEffect, useRef} from 'react'
import React, { useEffect, useRef, useState } from 'react'
import Link from 'next/link'
import { useState } from 'react'
import { mdiChevronUp, mdiChevronDown } from '@mdi/js'
import BaseDivider from './BaseDivider'
import BaseIcon from './BaseIcon'
@ -129,4 +128,4 @@ export default function NavBarItem({ item }: Props) {
}
return <div className={componentClass} ref={excludedRef}>{NavBarItemComponentContents}</div>
}
}

View File

@ -12,6 +12,9 @@
@import "_theme.css";
@import '_rich-text.css';
body {
@apply font-body;
}
.introjs-tooltip {
@apply min-w-[400px] max-w-[480px] p-2 !important;
@ -32,4 +35,4 @@
}
.introjs-prevbutton{
@apply bg-transparent border border-blue-600 text-blue-600 !important;
}
}

View File

@ -0,0 +1,88 @@
import { mdiViewDashboardOutline, mdiWall, mdiHomeCityOutline, mdiTexture } from '@mdi/js';
export const bekaServices = [
{
id: 'akustik-panel',
slug: 'akustik-panel',
title: 'Akustik Panel',
shortDescription: 'Ses yalıtımı ve estetiği bir araya getiren modern panel çözümleri.',
description: 'Beka Kaplama olarak sunduğumuz akustik panel çözümleri, mekanlarınızdaki ses yankısını minimize ederken estetik bir görünüm sağlar. Ofisler, ev sinema odaları, stüdyolar ve geniş yaşam alanları için özel olarak tasarlanan panellerimiz, farklı renk ve doku seçenekleriyle her türlü dekorasyona uyum sağlar.',
details: [
'Yüksek ses yutma katsayısı (NRC)',
'Alev geciktirici özellikli kumaş kaplamalar',
'Kolay montaj ve uzun ömürlü kullanım',
'Kişiselleştirilebilir boyut ve renk seçenekleri',
'Çevre dostu ve sağlığa zararsız materyaller'
],
icon: mdiViewDashboardOutline,
image: 'https://images.pexels.com/photos/1571460/pexels-photo-1571460.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2',
gallery: [
'https://images.pexels.com/photos/1571460/pexels-photo-1571460.jpeg?auto=compress&cs=tinysrgb&w=800',
'https://images.pexels.com/photos/1571470/pexels-photo-1571470.jpeg?auto=compress&cs=tinysrgb&w=800',
'https://images.pexels.com/photos/1571460/pexels-photo-1571460.jpeg?auto=compress&cs=tinysrgb&w=800'
]
},
{
id: 'pu-cephe-lambri',
slug: 'pu-cephe-lambri',
title: 'PU Cephe Lambri',
shortDescription: 'Dayanıklı, ısı yalıtımlı ve hafif poliüretan cephe sistemleri.',
description: 'Poliüretan (PU) cephe lambri sistemlerimiz, binalarınızın dış cephesine modern bir dokunuş katarken aynı zamanda üstün ısı yalıtımı sağlar. Hafif yapısı sayesinde binaya ek yük getirmez ve her türlü hava koşuluna karşı dayanıklıdır. Doğal ahşap ve taş görünümlü modellerimizle estetikten ödün vermeden koruma sağlıyoruz.',
details: [
'Mükemmel ısı ve ses yalıtımı',
'Suya, neme ve darbelere dayanıklı yapı',
'Hafif malzeme ile hızlı ve kolay uygulama',
'Boyanabilir yüzey ve zengin model seçenekleri',
'Bakım gerektirmeyen uzun ömürlü çözüm'
],
icon: mdiHomeCityOutline,
image: 'https://images.pexels.com/photos/1571470/pexels-photo-1571470.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2',
gallery: [
'https://images.pexels.com/photos/1571470/pexels-photo-1571470.jpeg?auto=compress&cs=tinysrgb&w=800',
'https://images.pexels.com/photos/1571460/pexels-photo-1571460.jpeg?auto=compress&cs=tinysrgb&w=800',
'https://images.pexels.com/photos/1571470/pexels-photo-1571470.jpeg?auto=compress&cs=tinysrgb&w=800'
]
},
{
id: 'pvc-mermer-plaka',
slug: 'pvc-mermer-plaka',
title: 'PVC Mermer Plaka',
shortDescription: 'Gerçek mermer görünümünde, ekonomik kaplama çözümleri.',
description: 'PVC mermer plaka uygulamalarımız, gerçek mermerin ağırlığı ve yüksek maliyeti olmadan lüks bir görünüm elde etmenizi sağlar. Islak hacimler başta olmak üzere tüm iç mekanlarda güvenle kullanılabilir. Kolay temizlenebilir ve antibakteriyel yapısıyla modern yaşam alanlarının vazgeçilmezidir.',
details: [
'%100 su ve nem dayanıklılığı',
'Gerçekçi mermer ve doğal taş dokusu',
'Antibakteriyel ve kolay temizlenebilir yüzey',
'Hızlı uygulama ve derz gerektirmeyen yapı',
'Yüksek parlaklık ve çizilme direnci'
],
icon: mdiWall,
image: 'https://images.pexels.com/photos/1571460/pexels-photo-1571460.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2',
gallery: [
'https://images.pexels.com/photos/1571460/pexels-photo-1571460.jpeg?auto=compress&cs=tinysrgb&w=800',
'https://images.pexels.com/photos/1571470/pexels-photo-1571470.jpeg?auto=compress&cs=tinysrgb&w=800',
'https://images.pexels.com/photos/1571460/pexels-photo-1571460.jpeg?auto=compress&cs=tinysrgb&w=800'
]
},
{
id: '3d-uygulamalar',
slug: '3d-uygulamalar',
title: '3D Uygulamalar',
shortDescription: 'Mekanlarınıza derinlik katan üç boyutlu duvar kaplamaları.',
description: '3D duvar paneli uygulamalarımızla monoton duvarları sanat eserine dönüştürüyoruz. Işık oyunlarıyla birleşen geometrik ve organik desenler, mekanınıza benzersiz bir derinlik ve karakter katar. Hem ticari mekanlarda hem de evlerde odak noktası oluşturmak için ideal bir tercihtir.',
details: [
'Üç boyutlu görsel derinlik ve doku',
'Özel aydınlatma ile vurgulanabilir desenler',
'Akustik performansa katkı sağlayan yapı',
'Farklı malzeme seçenekleri (Alçı, PU, Polimer)',
'Hızlı dönüşüm sağlayan pratik montaj'
],
icon: mdiTexture,
image: 'https://images.pexels.com/photos/1571470/pexels-photo-1571470.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2',
gallery: [
'https://images.pexels.com/photos/1571470/pexels-photo-1571470.jpeg?auto=compress&cs=tinysrgb&w=800',
'https://images.pexels.com/photos/1571460/pexels-photo-1571460.jpeg?auto=compress&cs=tinysrgb&w=800',
'https://images.pexels.com/photos/1571470/pexels-photo-1571470.jpeg?auto=compress&cs=tinysrgb&w=800'
]
}
];

View File

@ -0,0 +1,41 @@
import { useState, useEffect, RefObject } from 'react';
interface Options extends IntersectionObserverInit {
freezeOnceVisible?: boolean;
}
export function useIntersectionObserver(
elementRef: RefObject<Element>,
{
threshold = 0,
root = null,
rootMargin = '0%',
freezeOnceVisible = false,
}: Options
): IntersectionObserverEntry | undefined {
const [entry, setEntry] = useState<IntersectionObserverEntry>();
const frozen = entry?.isIntersecting && freezeOnceVisible;
const updateEntry = ([entry]: IntersectionObserverEntry[]): void => {
setEntry(entry);
};
useEffect(() => {
const node = elementRef?.current; // DOM Ref
const hasIOSupport = !!window.IntersectionObserver;
if (!hasIOSupport || frozen || !node) return;
const observerParams = { threshold, root, rootMargin };
const observer = new IntersectionObserver(updateEntry, observerParams);
observer.observe(node);
return () => observer.disconnect();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [elementRef?.current, JSON.stringify(threshold), root, rootMargin, frozen]);
return entry;
}

View File

@ -1,5 +1,4 @@
import React, { ReactNode, useEffect } from 'react'
import { useState } from 'react'
import React, { ReactNode, useEffect, useState } from 'react'
import jwt from 'jsonwebtoken';
import { mdiForwardburger, mdiBackburger, mdiMenu } from '@mdi/js'
import menuAside from '../menuAside'
@ -126,4 +125,4 @@ export default function LayoutAuthenticated({
</div>
</div>
)
}
}

View File

@ -180,6 +180,10 @@ function MyApp({ Component, pageProps }: AppPropsWithLayout) {
<meta property="twitter:image:height" content={imageHeight} />
<link rel="icon" href="/favicon.svg" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" />
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600;700&family=Playfair+Display:ital,wght@0,400;0,700;1,400&family=Lato:wght@300;400;700&display=swap" rel="stylesheet" />
</Head>
<ErrorBoundary>
@ -198,4 +202,4 @@ function MyApp({ Component, pageProps }: AppPropsWithLayout) {
)
}
export default appWithTranslation(MyApp);
export default appWithTranslation(MyApp);

View File

@ -0,0 +1,39 @@
import React, { ReactElement } from 'react';
import Head from 'next/head';
import LayoutGuest from '../layouts/Guest';
import { getPageTitle } from '../config';
import Navbar from '../components/Beka/Navbar';
import About from '../components/Beka/About';
import PageHero from '../components/Beka/PageHero';
import Footer from '../components/Beka/Footer';
import WhatsAppButton from '../components/Beka/WhatsAppButton';
export default function Hakkimizda() {
return (
<div className="min-h-screen bg-white font-sans selection:bg-amber-600/30 selection:text-amber-900">
<Head>
<title>{getPageTitle('Hakkımızda | Beka Kaplama')}</title>
<meta name="description" content="Beka Kaplama olarak deneyimli kadromuz ve kaliteli malzemelerimizle mekanlarınıza değer katıyoruz." />
</Head>
<Navbar />
<main className="pt-0">
<PageHero
title="Biz Kimiz?"
subtitle="Modern Vizyon"
image="https://images.pexels.com/photos/1571470/pexels-photo-1571470.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2"
/>
<About />
</main>
<Footer />
<WhatsAppButton />
</div>
);
}
Hakkimizda.getLayout = function getLayout(page: ReactElement) {
return <LayoutGuest>{page}</LayoutGuest>;
};

View File

@ -0,0 +1,166 @@
import React, { ReactElement } from 'react';
import Head from 'next/head';
import { useRouter } from 'next/router';
import Link from 'next/link';
import { mdiArrowLeft, mdiChevronRight, mdiCheckCircleOutline } from '@mdi/js';
import LayoutGuest from '../../layouts/Guest';
import { getPageTitle } from '../../config';
import Navbar from '../../components/Beka/Navbar';
import Footer from '../../components/Beka/Footer';
import WhatsAppButton from '../../components/Beka/WhatsAppButton';
import PageHero from '../../components/Beka/PageHero';
import ScrollReveal from '../../components/Beka/ScrollReveal';
import BaseIcon from '../../components/BaseIcon';
import { bekaServices } from '../../data/bekaServices';
export default function ServiceDetail() {
const router = useRouter();
const { slug } = router.query;
const service = bekaServices.find((s) => s.slug === slug);
if (!service && router.isReady) {
return (
<div className="min-h-screen flex items-center justify-center">
<div className="text-center">
<h1 className="text-4xl font-black mb-4">Hizmet Bulunamadı</h1>
<Link href="/hizmetler" className="text-amber-600 font-bold hover:underline">
Tüm Hizmetlerimize Geri Dön
</Link>
</div>
</div>
);
}
if (!service) return null;
return (
<div className="min-h-screen bg-white font-sans selection:bg-amber-600/30 selection:text-amber-900">
<Head>
<title>{getPageTitle(`${service.title} | Beka Kaplama`)}</title>
<meta name="description" content={service.shortDescription} />
</Head>
<Navbar />
<main className="pt-0">
<PageHero
title={service.title}
subtitle="Hizmet Detayları"
image={service.image}
/>
{/* Breadcrumb */}
<div className="bg-gray-50 border-b border-gray-100">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
<nav className="flex items-center space-x-2 text-sm font-bold text-gray-400 font-sans">
<Link href="/" className="hover:text-amber-600 transition-colors">Ana Sayfa</Link>
<BaseIcon path={mdiChevronRight} size={16} />
<Link href="/hizmetler" className="hover:text-amber-600 transition-colors">Hizmetler</Link>
<BaseIcon path={mdiChevronRight} size={16} />
<span className="text-amber-600">{service.title}</span>
</nav>
</div>
</div>
<section className="py-24">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="grid grid-cols-1 lg:grid-cols-2 gap-20 items-start">
{/* Left Side: Content */}
<ScrollReveal animation="fade-in-left">
<div>
<h2 className="text-xs font-black text-amber-600 uppercase tracking-[0.2em] mb-4 font-sans">Neler Yapıyoruz?</h2>
<h3 className="text-4xl md:text-5xl font-black text-gray-900 mb-8 leading-tight font-sans">
{service.title} <span className="text-amber-600 italic font-serif">Çözümlerimiz</span>
</h3>
<div className="prose prose-lg text-gray-500 mb-12 font-body">
<p className="leading-relaxed mb-6">
{service.description}
</p>
</div>
<div className="space-y-4 mb-12">
{service.details.map((detail, idx) => (
<div key={idx} className="flex items-center space-x-4 p-4 bg-gray-50 rounded-2xl border border-gray-100 font-sans">
<div className="flex-shrink-0 w-8 h-8 bg-amber-600/10 rounded-full flex items-center justify-center text-amber-600">
<BaseIcon path={mdiCheckCircleOutline} size={20} />
</div>
<span className="font-bold text-gray-700">{detail}</span>
</div>
))}
</div>
<Link
href="/iletisim"
className="inline-flex items-center space-x-4 px-10 py-5 bg-gray-900 text-white rounded-2xl font-black hover:bg-amber-600 transition-all shadow-xl shadow-gray-900/20 group hover:-translate-y-1 font-sans"
>
<span>Fiyat Teklifi Alın</span>
<BaseIcon path={mdiArrowLeft} size={24} className="rotate-180 group-hover:translate-x-1 transition-transform" />
</Link>
</div>
</ScrollReveal>
{/* Right Side: Visuals */}
<ScrollReveal animation="fade-in-right" delay={200}>
<div className="space-y-8">
<div className="relative group overflow-hidden rounded-[2.5rem] shadow-2xl">
<img
src={service.image}
alt={service.title}
className="w-full h-full object-cover transition-transform duration-1000 group-hover:scale-105"
/>
<div className="absolute inset-0 bg-gradient-to-t from-gray-900/40 to-transparent"></div>
</div>
<div className="grid grid-cols-2 gap-8">
{service.gallery.slice(1).map((img, idx) => (
<div key={idx} className="relative overflow-hidden rounded-3xl shadow-lg aspect-square">
<img
src={img}
alt={`${service.title} Gallery ${idx}`}
className="w-full h-full object-cover transition-transform duration-700 hover:scale-110"
/>
</div>
))}
</div>
</div>
</ScrollReveal>
</div>
</div>
</section>
{/* Other Services Section */}
<section className="py-24 bg-gray-50">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="text-center mb-16">
<h2 className="text-3xl font-black text-gray-900 font-sans">Diğer Hizmetlerimiz</h2>
</div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
{bekaServices.filter(s => s.id !== service.id).slice(0, 3).map((other) => (
<Link
key={other.id}
href={`/hizmet/${other.slug}`}
className="group bg-white p-8 rounded-3xl border border-gray-100 hover:border-amber-600 transition-all hover:shadow-xl hover:-translate-y-1"
>
<div className="w-14 h-14 bg-amber-600/10 rounded-2xl flex items-center justify-center text-amber-600 mb-6 group-hover:bg-amber-600 group-hover:text-white transition-all">
<BaseIcon path={other.icon} size={28} />
</div>
<h4 className="text-xl font-black text-gray-900 mb-2 font-sans">{other.title}</h4>
<p className="text-gray-500 text-sm font-medium font-body line-clamp-2">{other.shortDescription}</p>
</Link>
))}
</div>
</div>
</section>
</main>
<Footer />
<WhatsAppButton />
</div>
);
}
ServiceDetail.getLayout = function getLayout(page: ReactElement) {
return <LayoutGuest>{page}</LayoutGuest>;
};

View File

@ -0,0 +1,39 @@
import React, { ReactElement } from 'react';
import Head from 'next/head';
import LayoutGuest from '../layouts/Guest';
import { getPageTitle } from '../config';
import Navbar from '../components/Beka/Navbar';
import Services from '../components/Beka/Services';
import PageHero from '../components/Beka/PageHero';
import Footer from '../components/Beka/Footer';
import WhatsAppButton from '../components/Beka/WhatsAppButton';
export default function Hizmetler() {
return (
<div className="min-h-screen bg-white font-sans selection:bg-amber-600/30 selection:text-amber-900">
<Head>
<title>{getPageTitle('Hizmetlerimiz | Beka Kaplama')}</title>
<meta name="description" content="Akustik panel, PU cephe lambri, PVC mermer plaka ve 3D uygulamalar ile mekanlarınıza estetik ve güç katıyoruz." />
</Head>
<Navbar />
<main className="pt-0">
<PageHero
title="Hizmetlerimiz"
subtitle="Uzmanlık Alanlarımız"
image="https://images.pexels.com/photos/1571460/pexels-photo-1571460.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2"
/>
<Services />
</main>
<Footer />
<WhatsAppButton />
</div>
);
}
Hizmetler.getLayout = function getLayout(page: ReactElement) {
return <LayoutGuest>{page}</LayoutGuest>;
};

View File

@ -0,0 +1,39 @@
import React, { ReactElement } from 'react';
import Head from 'next/head';
import LayoutGuest from '../layouts/Guest';
import { getPageTitle } from '../config';
import Navbar from '../components/Beka/Navbar';
import ContactForm from '../components/Beka/ContactForm';
import PageHero from '../components/Beka/PageHero';
import Footer from '../components/Beka/Footer';
import WhatsAppButton from '../components/Beka/WhatsAppButton';
export default function Iletisim() {
return (
<div className="min-h-screen bg-white font-sans selection:bg-amber-600/30 selection:text-amber-900">
<Head>
<title>{getPageTitle('İletişim | Beka Kaplama')}</title>
<meta name="description" content="Ücretsiz keşif ve teklif için bizimle iletişime geçin." />
</Head>
<Navbar />
<main className="pt-0">
<PageHero
title="İletişim"
subtitle="Bize Ulaşın"
image="https://images.pexels.com/photos/1571460/pexels-photo-1571460.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2"
/>
<ContactForm />
</main>
<Footer />
<WhatsAppButton />
</div>
);
}
Iletisim.getLayout = function getLayout(page: ReactElement) {
return <LayoutGuest>{page}</LayoutGuest>;
};

View File

@ -1,166 +1,41 @@
import React, { useEffect, useState } from 'react';
import type { ReactElement } from 'react';
import React, { ReactElement } from 'react';
import Head from 'next/head';
import Link from 'next/link';
import BaseButton from '../components/BaseButton';
import CardBox from '../components/CardBox';
import SectionFullScreen from '../components/SectionFullScreen';
import LayoutGuest from '../layouts/Guest';
import BaseDivider from '../components/BaseDivider';
import BaseButtons from '../components/BaseButtons';
import { getPageTitle } from '../config';
import { useAppSelector } from '../stores/hooks';
import CardBoxComponentTitle from "../components/CardBoxComponentTitle";
import { getPexelsImage, getPexelsVideo } from '../helpers/pexels';
export default function Starter() {
const [illustrationImage, setIllustrationImage] = useState({
src: undefined,
photographer: undefined,
photographer_url: undefined,
})
const [illustrationVideo, setIllustrationVideo] = useState({video_files: []})
const [contentType, setContentType] = useState('image');
const [contentPosition, setContentPosition] = useState('right');
const textColor = useAppSelector((state) => state.style.linkColor);
const title = 'Beka Kaplama Website'
// Fetch Pexels image/video
useEffect(() => {
async function fetchData() {
const image = await getPexelsImage();
const video = await getPexelsVideo();
setIllustrationImage(image);
setIllustrationVideo(video);
}
fetchData();
}, []);
const imageBlock = (image) => (
<div
className='hidden md:flex flex-col justify-end relative flex-grow-0 flex-shrink-0 w-1/3'
style={{
backgroundImage: `${
image
? `url(${image?.src?.original})`
: 'linear-gradient(rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0.5))'
}`,
backgroundSize: 'cover',
backgroundPosition: 'left center',
backgroundRepeat: 'no-repeat',
}}
>
<div className='flex justify-center w-full bg-blue-300/20'>
<a
className='text-[8px]'
href={image?.photographer_url}
target='_blank'
rel='noreferrer'
>
Photo by {image?.photographer} on Pexels
</a>
</div>
</div>
);
const videoBlock = (video) => {
if (video?.video_files?.length > 0) {
return (
<div className='hidden md:flex flex-col justify-end relative flex-grow-0 flex-shrink-0 w-1/3'>
<video
className='absolute top-0 left-0 w-full h-full object-cover'
autoPlay
loop
muted
>
<source src={video?.video_files[0]?.link} type='video/mp4'/>
Your browser does not support the video tag.
</video>
<div className='flex justify-center w-full bg-blue-300/20 z-10'>
<a
className='text-[8px]'
href={video?.user?.url}
target='_blank'
rel='noreferrer'
>
Video by {video.user.name} on Pexels
</a>
</div>
</div>)
}
};
import Navbar from '../components/Beka/Navbar';
import Hero from '../components/Beka/Hero';
import Services from '../components/Beka/Services';
import About from '../components/Beka/About';
import Projects from '../components/Beka/Projects';
import ContactForm from '../components/Beka/ContactForm';
import Footer from '../components/Beka/Footer';
import WhatsAppButton from '../components/Beka/WhatsAppButton';
export default function Home() {
return (
<div
style={
contentPosition === 'background'
? {
backgroundImage: `${
illustrationImage
? `url(${illustrationImage.src?.original})`
: 'linear-gradient(rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0.5))'
}`,
backgroundSize: 'cover',
backgroundPosition: 'left center',
backgroundRepeat: 'no-repeat',
}
: {}
}
>
<div className="min-h-screen bg-white font-sans selection:bg-amber-600/30 selection:text-amber-900">
<Head>
<title>{getPageTitle('Starter Page')}</title>
<title>{getPageTitle('Beka Kaplama | Modern Kaplama Sistemleri')}</title>
<meta name="description" content="Akustik panel, PU cephe lambri, PVC mermer plaka ve 3D uygulamalar ile mekanlarınıza estetik ve güç katıyoruz. Beka Kaplama Sistemleri." />
</Head>
<SectionFullScreen bg='violet'>
<div
className={`flex ${
contentPosition === 'right' ? 'flex-row-reverse' : 'flex-row'
} min-h-screen w-full`}
>
{contentType === 'image' && contentPosition !== 'background'
? imageBlock(illustrationImage)
: null}
{contentType === 'video' && contentPosition !== 'background'
? videoBlock(illustrationVideo)
: null}
<div className='flex items-center justify-center flex-col space-y-4 w-full lg:w-full'>
<CardBox className='w-full md:w-3/5 lg:w-2/3'>
<CardBoxComponentTitle title="Welcome to your Beka Kaplama Website app!"/>
<div className="space-y-3">
<p className='text-center text-gray-500'>This is a React.js/Node.js app generated by the <a className={`${textColor}`} href="https://flatlogic.com/generator">Flatlogic Web App Generator</a></p>
<p className='text-center text-gray-500'>For guides and documentation please check
your local README.md and the <a className={`${textColor}`} href="https://flatlogic.com/documentation">Flatlogic documentation</a></p>
</div>
<BaseButtons>
<BaseButton
href='/login'
label='Login'
color='info'
className='w-full'
/>
</BaseButtons>
</CardBox>
</div>
</div>
</SectionFullScreen>
<div className='bg-black text-white flex flex-col text-center justify-center md:flex-row'>
<p className='py-6 text-sm'>© 2026 <span>{title}</span>. All rights reserved</p>
<Link className='py-6 ml-4 text-sm' href='/privacy-policy/'>
Privacy Policy
</Link>
</div>
<Navbar />
<main>
<Hero />
<About />
<Services />
<Projects />
<ContactForm />
</main>
<Footer />
<WhatsAppButton />
</div>
);
}
Starter.getLayout = function getLayout(page: ReactElement) {
Home.getLayout = function getLayout(page: ReactElement) {
return <LayoutGuest>{page}</LayoutGuest>;
};
};

View File

@ -0,0 +1,39 @@
import React, { ReactElement } from 'react';
import Head from 'next/head';
import LayoutGuest from '../layouts/Guest';
import { getPageTitle } from '../config';
import Navbar from '../components/Beka/Navbar';
import Projects from '../components/Beka/Projects';
import PageHero from '../components/Beka/PageHero';
import Footer from '../components/Beka/Footer';
import WhatsAppButton from '../components/Beka/WhatsAppButton';
export default function Projeler() {
return (
<div className="min-h-screen bg-white font-sans selection:bg-amber-600/30 selection:text-amber-900">
<Head>
<title>{getPageTitle('Projelerimiz | Beka Kaplama')}</title>
<meta name="description" content="Tamamladığımız modern kaplama ve dekorasyon projelerimizden örnekler." />
</Head>
<Navbar />
<main className="pt-0">
<PageHero
title="Projelerimiz"
subtitle="Referanslarımız"
image="https://images.pexels.com/photos/1571470/pexels-photo-1571470.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2"
/>
<Projects />
</main>
<Footer />
<WhatsAppButton />
</div>
);
}
Projeler.getLayout = function getLayout(page: ReactElement) {
return <LayoutGuest>{page}</LayoutGuest>;
};

View File

@ -13,6 +13,11 @@ module.exports = {
gray: 'gray'
},
extend: {
fontFamily: {
sans: ['Montserrat', 'ui-sans-serif', 'system-ui'],
serif: ['Playfair Display', 'ui-serif', 'Georgia'],
body: ['Lato', 'ui-sans-serif', 'system-ui'],
},
zIndex: {
'-1': '-1'
},
@ -35,11 +40,66 @@ module.exports = {
'fade-in': {
from: { opacity: 0 },
to: { opacity: 1 }
},
'fade-in-up': {
'0%': {
opacity: '0',
transform: 'translateY(20px)'
},
'100%': {
opacity: '1',
transform: 'translateY(0)'
},
},
'fade-in-left': {
'0%': {
opacity: '0',
transform: 'translateX(-20px)'
},
'100%': {
opacity: '1',
transform: 'translateX(0)'
},
},
'fade-in-right': {
'0%': {
opacity: '0',
transform: 'translateX(20px)'
},
'100%': {
opacity: '1',
transform: 'translateX(0)'
},
},
'scale-in': {
'0%': {
opacity: '0',
transform: 'scale(0.95)'
},
'100%': {
opacity: '1',
transform: 'scale(1)'
},
},
'bounce-soft': {
'0%, 100%': {
transform: 'translateY(-5%)',
animationTimingFunction: 'cubic-bezier(0.8, 0, 1, 1)'
},
'50%': {
transform: 'translateY(0)',
animationTimingFunction: 'cubic-bezier(0, 0, 0.2, 1)'
}
}
},
animation: {
'fade-out': 'fade-out 250ms ease-in-out',
'fade-in': 'fade-in 250ms ease-in-out'
'fade-in': 'fade-in 250ms ease-in-out',
'fade-in-up': 'fade-in-up 0.6s ease-out forwards',
'fade-in-left': 'fade-in-left 0.6s ease-out forwards',
'fade-in-right': 'fade-in-right 0.6s ease-out forwards',
'scale-in': 'scale-in 0.5s ease-out forwards',
'bounce-soft': 'bounce-soft 3s infinite',
},
colors: {
dark: {
@ -107,4 +167,4 @@ module.exports = {
);
}),
],
}
}