diff --git a/app/page-new.tsx b/app/page-new.tsx new file mode 100644 index 0000000..b590021 --- /dev/null +++ b/app/page-new.tsx @@ -0,0 +1,67 @@ +'use client'; + +import { useState, useEffect } from 'react'; +import Header from "@/components/Header"; +import Footer from "@/components/Footer"; +import HeroSlider from "@/components/HeroSlider"; +import QuickMenuCards from "@/components/QuickMenuCards"; +import LiveStreamSection from "@/components/LiveStreamSection"; +import NewsSection from "@/components/NewsSection"; +import MetroLine from "@/components/MetroLine"; + +export default function Home() { + const [showLiveStream, setShowLiveStream] = useState(false); + const [showNews, setShowNews] = useState(false); + const [showDocuments, setShowDocuments] = useState(false); + const [showMediaGallery, setShowMediaGallery] = useState(false); + const [showComplaintForm, setShowComplaintForm] = useState(false); + const [showContact, setShowContact] = useState(false); + + // Modal açıldığında yukarı kaydır + useEffect(() => { + if (showLiveStream || showNews || showDocuments || showMediaGallery || showComplaintForm || showContact) { + window.scrollTo({ top: 0, behavior: 'smooth' }); + } + }, [showLiveStream, showNews, showDocuments, showMediaGallery, showComplaintForm, showContact]); + + return ( +
+
+ + {/* Hero Slider Section */} + + + {/* Quick Menu Cards */} + setShowLiveStream(!showLiveStream)} + onNewsClick={() => setShowNews(!showNews)} + onDocumentsClick={() => setShowDocuments(!showDocuments)} + onMediaClick={() => setShowMediaGallery(!showMediaGallery)} + onComplaintClick={() => setShowComplaintForm(!showComplaintForm)} + onContactClick={() => setShowContact(!showContact)} + /> + + {/* Live Stream Section */} + setShowLiveStream(false)} + /> + + {/* News Section */} + setShowNews(false)} + showLiveStream={showLiveStream} + /> + + {/* Metro Line Section - Ana içerik */} +
+
+ +
+
+ +
+ ); +} diff --git a/app/page.tsx b/app/page.tsx index 07d0cbd..134396a 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -6,261 +6,56 @@ import Link from 'next/link'; import Header from "@/components/Header"; import MetroLine from "@/components/MetroLine"; import Footer from "@/components/Footer"; -import { newsData } from '@/data/news'; - -// Hero Slider Data - Component dışında tanımla -const heroSlides = [ - { - id: 1, - title: 'Ankara Metro Altyapı Projelerinde Öncü Çözümler', - description: 'Ankara Büyükşehir Belediyesi ile birlikte, modern teknoloji ve mühendislik uzmanlığımızla başkentin ulaşım ağını inşa ediyor, geleceğin metro sistemlerini bugünden hayata geçiriyoruz.', - buttonText: 'Detayları Gör', - buttonLink: '#proje-detay' - }, - { - id: 2, - title: 'A2 Metro Hattı İnşaatında Son Aşamaya Gelindi', - description: '15 istasyonlu A2 Metro Hattı projemiz %75 tamamlandı. 2026 yılında hizmete açılacak modern metro hattımız, günlük 300 bin yolcuya hizmet verecek.', - buttonText: 'İlerlemeyi İzle', - buttonLink: '#metro-hatti' - }, - { - id: 3, - title: 'Çevre Dostu Metro Teknolojileri', - description: 'Yenilenebilir enerji kaynakları ve sürdürülebilir inşaat teknikleri ile çevre dostu metro projelerine imza atıyoruz. Karbon emisyonunu %40 azaltan yenilikçi çözümlerimiz.', - buttonText: 'Yeşil Projeler', - buttonLink: '#cevre' - }, - { - id: 4, - title: 'Güvenli İnşaat, Güvenli Gelecek', - description: 'ISO 45001 sertifikalı iş güvenliği sistemlerimiz ile 2000+ çalışanımızın güvenliğini en üst düzeyde tutuyoruz. Sıfır iş kazası hedefiyle çalışıyoruz.', - buttonText: 'Güvenlik Önlemleri', - buttonLink: '#guvenlik' - } -]; +import DocumentsSection from "@/components/DocumentsSection"; +import MediaGallery from "@/components/MediaGallery"; +import ComplaintForm from "@/components/ComplaintForm"; +import ContactSection from "@/components/ContactSection"; +import { dataStore } from '@/lib/dataStore'; export default function Home() { const [showLiveStream, setShowLiveStream] = useState(false); const [showNews, setShowNews] = useState(false); const [selectedNews, setSelectedNews] = useState(null); const [showDocuments, setShowDocuments] = useState(false); - const [selectedCategory, setSelectedCategory] = useState('all'); const [showMediaGallery, setShowMediaGallery] = useState(false); - const [selectedMediaTab, setSelectedMediaTab] = useState<'all' | 'video' | 'photo'>('all'); - const [selectedMedia, setSelectedMedia] = useState(null); const [showComplaintForm, setShowComplaintForm] = useState(false); - const [complaintFormData, setComplaintFormData] = useState({ - name: '', - email: '', - phone: '', - subject: '', - type: 'dilek', - message: '' - }); const [showContact, setShowContact] = useState(false); const [currentSlide, setCurrentSlide] = useState(0); + + // Gerçek veriler için state + const [heroSlides, setHeroSlides] = useState(dataStore.getSlider()); + const [newsData, setNewsData] = useState(dataStore.getNews()); - // Modal açıldığında yukarı kaydır + // Verileri yükle useEffect(() => { - if (showLiveStream || showNews || showDocuments || showMediaGallery || showComplaintForm || showContact) { - window.scrollTo({ top: 0, behavior: 'smooth' }); - } - }, [showLiveStream, showNews, showDocuments, showMediaGallery, showComplaintForm, showContact]); + setHeroSlides(dataStore.getSlider()); + setNewsData(dataStore.getNews()); + }, []); - // Auto slider + // Modal açıldığında yukarı kaydır - KALDIRILDI (kullanıcı deneyimi için) + // useEffect(() => { + // if (showLiveStream || showNews || showDocuments || showMediaGallery || showComplaintForm || showContact) { + // window.scrollTo({ top: 0, behavior: 'smooth' }); + // } + // }, [showLiveStream, showNews, showDocuments, showMediaGallery, showComplaintForm, showContact]); + + // Auto slider - aktif slider sayısına göre useEffect(() => { + const activeSlides = heroSlides.filter(slide => slide.active); + if (activeSlides.length === 0) return; + const timer = setInterval(() => { - setCurrentSlide((prev) => (prev + 1) % 4); // 4 slide var + setCurrentSlide((prev) => (prev + 1) % activeSlides.length); }, 10000); // 10 saniyede bir değiş return () => clearInterval(timer); - }, []); - - const categories = [ - { id: 'all', name: 'Tümü', icon: '📋' }, - { id: 'ihale', name: 'İhale Belgeleri', icon: '📄' }, - { id: 'teknik', name: 'Teknik Dökümanlar', icon: '📐' }, - { id: 'cevresel', name: 'Çevresel Etki', icon: '🌱' }, - { id: 'raporlar', name: 'İlerleme Raporları', icon: '📊' }, - ]; - - const documents = [ - { - id: 1, - title: "A2 Metro Hattı İhale Şartnamesi", - category: 'ihale', - date: "15 Ocak 2025", - size: "2.4 MB", - type: "PDF", - description: "Metro inşaatı için teknik şartname ve ihale koşulları" - }, - { - id: 2, - title: "Proje Teknik Çizimleri", - category: 'teknik', - date: "10 Şubat 2025", - size: "15.8 MB", - type: "DWG", - description: "Tüm istasyonların teknik mimari çizimleri" - }, - { - id: 3, - title: "Çevresel Etki Değerlendirme Raporu", - category: 'cevresel', - date: "5 Mart 2025", - size: "4.2 MB", - type: "PDF", - description: "Proje çevresel etki analizi ve önlemler" - }, - { - id: 4, - title: "2025 Mart Ayı İlerleme Raporu", - category: 'raporlar', - date: "1 Nisan 2025", - size: "1.8 MB", - type: "PDF", - description: "Aylık proje ilerleme ve istatistikler" - }, - { - id: 5, - title: "Güvenlik Planı ve Prosedürleri", - category: 'teknik', - date: "20 Ocak 2025", - size: "3.1 MB", - type: "PDF", - description: "İnşaat sahası güvenlik protokolleri" - }, - { - id: 6, - title: "İstasyon Tasarım Detayları", - category: 'teknik', - date: "8 Şubat 2025", - size: "8.5 MB", - type: "PDF", - description: "İstasyon iç ve dış mekan tasarım detayları" - }, - { - id: 7, - title: "Finansman Planı", - category: 'ihale', - date: "12 Ocak 2025", - size: "1.2 MB", - type: "XLSX", - description: "Proje bütçe ve finansman dağılımı" - }, - { - id: 8, - title: "2025 Nisan Ayı İlerleme Raporu", - category: 'raporlar', - date: "1 Mayıs 2025", - size: "2.1 MB", - type: "PDF", - description: "Aylık proje ilerleme ve istatistikler" - }, - { - id: 9, - title: "Gürültü ve Titreşim Analizi", - category: 'cevresel', - date: "18 Mart 2025", - size: "3.8 MB", - type: "PDF", - description: "Çevre gürültü ve titreşim ölçüm sonuçları" - }, - ]; - - const filteredDocs = selectedCategory === 'all' - ? documents - : documents.filter(doc => doc.category === selectedCategory); - - const getFileIcon = (type: string) => { - switch (type) { - case 'PDF': return '📕'; - case 'DWG': return '📐'; - case 'XLSX': return '📊'; - default: return '📄'; - } - }; + }, [heroSlides]); // Featured news (ana sayfada gösterilecek haberler) const featuredNews = newsData.filter(news => news.featured).slice(0, 4); - const mediaItems = [ - { - id: 1, - type: 'video', - title: 'A2 Metro Hattı Genel Tanıtım', - thumbnail: 'https://images.pexels.com/photos/17152223/pexels-photo-17152223.jpeg', - videoUrl: 'https://www.youtube.com/embed/b9q88QDEcKg', - date: '15 Ekim 2025', - duration: '5:32', - description: 'A2 Metro Hattı projesinin genel tanıtımı ve istasyonların detayları' - }, - { - id: 2, - type: 'photo', - title: 'Dikimevi İstasyonu İnşaat Çalışmaları', - thumbnail: 'https://images.pexels.com/photos/17302615/pexels-photo-17302615.jpeg', - date: '12 Ekim 2025', - description: 'Dikimevi metro istasyonunda devam eden kazı ve inşaat çalışmaları' - }, - { - id: 3, - type: 'photo', - title: 'Tuzluçayır İstasyonu Temel Atma', - thumbnail: 'https://images.pexels.com/photos/33950678/pexels-photo-33950678.jpeg', - date: '10 Ekim 2025', - description: 'Tuzluçayır istasyonunun temel atma töreni anları' - }, - { - id: 4, - type: 'video', - title: 'Metro İnşaatı İlerleme Raporu', - thumbnail: 'https://images.pexels.com/photos/253647/pexels-photo-253647.jpeg', - videoUrl: 'https://www.youtube.com/embed/b9q88QDEcKg', - date: '8 Ekim 2025', - duration: '8:15', - description: 'Ekim ayı metro inşaatı ilerleme raporu ve gelecek hedefler' - }, - { - id: 5, - type: 'photo', - title: 'Modern İstasyon Tasarımları', - thumbnail: 'https://images.pexels.com/photos/17152223/pexels-photo-17152223.jpeg', - date: '5 Ekim 2025', - description: 'Yeni nesil metro istasyonlarının modern iç mekan tasarımları' - }, - { - id: 6, - type: 'video', - title: 'Çevre Dostu Metro Projesi', - thumbnail: 'https://images.pexels.com/photos/17302615/pexels-photo-17302615.jpeg', - videoUrl: 'https://www.youtube.com/embed/b9q88QDEcKg', - date: '1 Ekim 2025', - duration: '6:45', - description: 'Metro projesinde kullanılan çevre dostu teknolojiler ve sürdürülebilir yaklaşımlar' - }, - { - id: 7, - type: 'photo', - title: 'İşçi Güvenliği Eğitimi', - thumbnail: 'https://images.pexels.com/photos/33950678/pexels-photo-33950678.jpeg', - date: '28 Eylül 2025', - description: 'İnşaat sahalarında iş güvenliği eğitimleri' - }, - { - id: 8, - type: 'photo', - title: 'Ray Döşeme Çalışmaları', - thumbnail: 'https://images.pexels.com/photos/253647/pexels-photo-253647.jpeg', - date: '25 Eylül 2025', - description: 'Metro hattında ray döşeme işlemlerinin başlaması' - }, - ]; - - const filteredMedia = selectedMediaTab === 'all' - ? mediaItems - : mediaItems.filter(item => item.type === selectedMediaTab); + // Aktif slider'ları al + const activeSlides = heroSlides.filter(slide => slide.active); return (
@@ -290,7 +85,7 @@ export default function Home() {
{/* Slider Content */}
- {heroSlides.map((slide, index) => ( + {activeSlides.map((slide, index) => (
{/* Dots */}
- {heroSlides.map((_, index) => ( + {activeSlides.map((_, index) => ( -
- - {/* Kategori Filtreleri */} -
-
- {categories.map((cat) => ( - - ))} -
-
- - {/* Belgeler Grid - 3 sütunlu */} -
- {filteredDocs.map((doc) => ( -
- {/* Dosya İkonu - Üstte ortalı */} -
-
- {getFileIcon(doc.type)} -
-
- - {/* Belge Bilgileri */} -
-

- {doc.title} -

-

- {doc.description} -

-
- 📅 {doc.date} - 📄 {doc.type} - 💾 {doc.size} -
-
- - {/* İndirme Butonu - Alt kısımda */} - -
- ))} -
-
-
- )} + {showDocuments && setShowDocuments(false)} />} {/* Medya Galerisi Bölümü */} - {showMediaGallery && ( -
-
-
-
-
- - - -
-

Medya Galerisi

-
- -
- - {/* Medya Grid veya Detay */} - {selectedMedia === null ? ( - <> - {/* Tab Menü */} -
- - - -
- - {/* Medya Grid */} -
- {filteredMedia.map((item) => ( -
setSelectedMedia(item.id)} - className="bg-gray-50 rounded-xl overflow-hidden hover:shadow-lg transition-all duration-300 hover:-translate-y-2 cursor-pointer group" - > - {/* Thumbnail */} -
- {item.title} - {/* Video Badge */} - {item.type === 'video' && ( -
-
- - - -
-
- )} - {/* Duration Badge */} - {item.type === 'video' && 'duration' in item && ( -
- {item.duration} -
- )} - {/* Photo Badge */} - {item.type === 'photo' && ( -
- FOTO -
- )} -
- - {/* Content */} -
-
- - - - {item.date} -
-

- {item.title} -

-

- {item.description} -

-
-
- ))} -
- - ) : ( - /* Medya Detayı */ -
- {mediaItems.filter(m => m.id === selectedMedia).map((item) => ( -
- {/* Geri Butonu */} - - - {/* Video Player veya Büyük Fotoğraf */} - {item.type === 'video' ? ( -
- -
- ) : ( -
- {item.title} -
- )} - - {/* Bilgiler */} -
- - - - {item.date} - {item.type === 'video' && 'duration' in item && ( - <> - - {item.duration} - - )} -
- -

- {item.title} -

- -

- {item.description} -

- - {/* Paylaş */} -
-
-
- Paylaş: - -
- -
-
-
- ))} -
- )} -
-
- )} + {showMediaGallery && setShowMediaGallery(false)} />} {/* Dilek-Şikayet Formu */} - {showComplaintForm && ( -
-
-
-
-
- - - -
-

Dilek ve Şikayet Formu

-
- -
- - {/* Bilgilendirme */} -
-
- - - -

- A2 Metro Hattı projesi ile ilgili dilek, öneri ve şikayetlerinizi bu form aracılığıyla iletebilirsiniz. Başvurularınız en kısa sürede değerlendirilecektir. -

-
-
- - {/* Form */} -
{ - e.preventDefault(); - alert('Form gönderildi! (Demo)'); - setShowComplaintForm(false); - setComplaintFormData({ - name: '', - email: '', - phone: '', - subject: '', - type: 'dilek', - message: '' - }); - }}> - {/* Başvuru Tipi */} -
- -
- - -
-
- - {/* İki Sütunlu Alan */} -
- {/* Ad Soyad */} -
- - setComplaintFormData({...complaintFormData, name: e.target.value})} - className="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#00B4D8] focus:border-transparent outline-none transition-all text-gray-900 placeholder:text-gray-500" - placeholder="Adınız ve Soyadınız" - /> -
- - {/* E-posta */} -
- - setComplaintFormData({...complaintFormData, email: e.target.value})} - className="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#00B4D8] focus:border-transparent outline-none transition-all text-gray-900 placeholder:text-gray-500" - placeholder="ornek@email.com" - /> -
- - {/* Telefon */} -
- - setComplaintFormData({...complaintFormData, phone: e.target.value})} - className="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#00B4D8] focus:border-transparent outline-none transition-all text-gray-900 placeholder:text-gray-500" - placeholder="0(5__) ___ __ __" - /> -
- - {/* Konu */} -
- - setComplaintFormData({...complaintFormData, subject: e.target.value})} - className="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#00B4D8] focus:border-transparent outline-none transition-all text-gray-900 placeholder:text-gray-500" - placeholder="Başvuru konusu" - /> -
-
- - {/* Mesaj */} -
- - -
- - {/* KVKK Onayı */} -
- - -
- - {/* Butonlar */} -
- - -
-
-
-
- )} + {showComplaintForm && setShowComplaintForm(false)} />} {/* E-İletişim Bölümü */} - {showContact && ( -
-
-
-
-
- - - -
-

İletişim Bilgileri

-
- -
- -
- {/* Sol Taraf - İletişim Kartları */} -
- {/* Adres Kartı */} -
-
-
- - - - -
-
-

ADRES

-

- Emniyet Mah. Hipodrom Caddesi No: 5
- Yenimahalle / Ankara -

-
-
-
- - {/* KEP Adresi Kartı */} -
-
-
- - - -
- -
-
- - {/* Telefon Kartı */} -
-
-
- - - -
- -
-
- - {/* Çalışma Saatleri */} -
-
-
- - - -
-
-

ÇALIŞMA SAATLERİ

-

- Hafta İçi: 08:30 - 17:30
- Hafta Sonu: Kapalı -

-
-
-
-
- - {/* Sağ Taraf - Harita */} -
-

Konum

-
- -
- - {/* Haritada Göster Butonu */} - - - - - Google Maps'te Aç - -
-
-
-
- )} + {showContact && setShowContact(false)} />} {/* Ana İçerik - Kartlar için üstten boşluk */}
diff --git a/app/yonetim-paneli-a2m-secure/dashboard/page.tsx b/app/yonetim-paneli-a2m-secure/dashboard/page.tsx index c6a85ff..70f867d 100644 --- a/app/yonetim-paneli-a2m-secure/dashboard/page.tsx +++ b/app/yonetim-paneli-a2m-secure/dashboard/page.tsx @@ -2,13 +2,10 @@ import { useEffect, useState } from 'react'; import { useRouter } from 'next/navigation'; -import { newsData, categories } from '@/data/news'; +import { dataStore, type SliderItem } from '@/lib/dataStore'; import type { NewsItem } from '@/data/news'; -import { mediaData } from '@/data/media'; import type { MediaItem } from '@/data/media'; -import { documentsData, documentCategories, getFileIcon } from '@/data/documents'; import type { Document } from '@/data/documents'; -import { metroStations, getStatusColor, getStatusText } from '@/data/metroStations'; import type { MetroStation } from '@/data/metroStations'; export default function Dashboard() { @@ -16,23 +13,42 @@ export default function Dashboard() { const [activeSection, setActiveSection] = useState('overview'); const [menuOpen, setMenuOpen] = useState(false); + // Gerçek veriler için state'ler + const [sliderItems, setSliderItems] = useState([]); + const [newsItems, setNewsItems] = useState([]); + const [mediaItems, setMediaItems] = useState([]); + const [documents, setDocuments] = useState([]); + const [metroStations, setMetroStations] = useState([]); + useEffect(() => { const token = localStorage.getItem('admin_token'); if (!token) { router.push('/yonetim-paneli-a2m-secure'); + return; } + + // Verileri yükle + loadData(); }, [router]); + const loadData = () => { + setSliderItems(dataStore.getSlider()); + setNewsItems(dataStore.getNews()); + setMediaItems(dataStore.getMedia()); + setDocuments(dataStore.getDocuments()); + setMetroStations(dataStore.getMetroStations()); + }; + const handleLogout = () => { localStorage.removeItem('admin_token'); router.push('/yonetim-paneli-a2m-secure'); }; const stats = [ - { title: 'Aktif Slider', value: '4', icon: '🎬', color: 'from-[#004B87] to-[#00B4D8]', change: '+1' }, - { title: 'Toplam Haberler', value: newsData.length.toString(), icon: '📰', color: 'from-[#00B4D8] to-[#0096C7]', change: '+2' }, - { title: 'Medya İçeriği', value: mediaData.length.toString(), icon: '�', color: 'from-[#0096C7] to-[#48CAE4]', change: '+3' }, - { title: 'Metro İstasyonları', value: metroStations.length.toString(), icon: '�', color: 'from-[#48CAE4] to-[#90E0EF]', change: '+2' }, + { title: 'Aktif Slider', value: sliderItems.filter(s => s.active).length.toString(), icon: '🎬', color: 'from-[#004B87] to-[#00B4D8]', change: '+1' }, + { title: 'Toplam Haberler', value: newsItems.length.toString(), icon: '📰', color: 'from-[#00B4D8] to-[#0096C7]', change: '+2' }, + { title: 'Medya İçeriği', value: mediaItems.length.toString(), icon: '📸', color: 'from-[#0096C7] to-[#48CAE4]', change: '+3' }, + { title: 'Metro İstasyonları', value: metroStations.length.toString(), icon: '🚇', color: 'from-[#48CAE4] to-[#90E0EF]', change: '+2' }, ]; const menuItems = [ @@ -45,75 +61,328 @@ export default function Dashboard() { { id: 'settings', label: 'Ayarlar', icon: '⚙️' }, ]; - // Slider data - const [sliderItems, setSliderItems] = useState([ - { - id: 1, - title: 'Ankara Metro Altyapı Projelerinde Öncü Çözümler', - description: 'Ankara Büyükşehir Belediyesi ile birlikte, modern teknoloji ve mühendislik uzmanlığımızla başkentin ulaşım ağını inşa ediyor, geleceğin metro sistemlerini bugünden hayata geçiriyoruz.', - buttonText: 'Detayları Gör', - buttonLink: '#proje-detay', - active: true - }, - { - id: 2, - title: 'A2 Metro Hattı İnşaatında Son Aşamaya Gelindi', - description: '15 istasyonlu A2 Metro Hattı projemiz %75 tamamlandı. 2026 yılında hizmete açılacak modern metro hattımız, günlük 300 bin yolcuya hizmet verecek.', - buttonText: 'İlerlemeyi İzle', - buttonLink: '#metro-hatti', - active: true - }, - { - id: 3, - title: 'Çevre Dostu Metro Teknolojileri', - description: 'Yenilenebilir enerji kaynakları ve sürdürülebilir inşaat teknikleri ile çevre dostu metro projelerine imza atıyoruz. Karbon emisyonunu %40 azaltan yenilikçi çözümlerimiz.', - buttonText: 'Yeşil Projeler', - buttonLink: '#cevre', - active: true - }, - { - id: 4, - title: 'Güvenli İnşaat, Güvenli Gelecek', - description: 'ISO 45001 sertifikalı iş güvenliği sistemlerimiz ile 2000+ çalışanımızın güvenliğini en üst düzeyde tutuyoruz. Sıfır iş kazası hedefiyle çalışıyoruz.', - buttonText: 'Güvenlik Önlemleri', - buttonLink: '#guvenlik', - active: true - } - ]); + // Slider management functions + const toggleSlideActive = (id: number) => { + const updated = sliderItems.map(item => + item.id === id ? { ...item, active: !item.active } : item + ); + setSliderItems(updated); + dataStore.setSlider(updated); + }; - // News management state - const [newsList, setNewsList] = useState(newsData); + const updateSlide = (id: number, updates: Partial) => { + const updated = sliderItems.map(item => + item.id === id ? { ...item, ...updates } : item + ); + setSliderItems(updated); + dataStore.setSlider(updated); + }; + + // News management functions + const handleDeleteNews = (id: number) => { + if (confirm('Bu haberi silmek istediğinizden emin misiniz?')) { + dataStore.deleteNews(id); + loadData(); + } + }; + + const handleToggleFeatured = (id: number) => { + const news = newsItems.find(n => n.id === id); + if (news) { + dataStore.updateNews(id, { featured: !news.featured }); + loadData(); + } + }; + + // Media management functions + const handleDeleteMedia = (id: number) => { + if (confirm('Bu medya içeriğini silmek istediğinizden emin misiniz?')) { + dataStore.deleteMedia(id); + loadData(); + } + }; + + // Document management functions + const handleDeleteDocument = (id: number) => { + if (confirm('Bu belgeyi silmek istediğinizden emin misiniz?')) { + dataStore.deleteDocument(id); + loadData(); + } + }; + + // Metro station update function + const handleUpdateStation = (id: number, updates: Partial) => { + dataStore.updateStation(id, updates); + loadData(); + }; + + // Categories + const categories = [ + { id: 'all', name: 'Tümü', icon: '📋' }, + { id: 'construction', name: 'İnşaat', icon: '🏗️' }, + { id: 'announcement', name: 'Duyuru', icon: '📢' }, + { id: 'event', name: 'Etkinlik', icon: '🎉' }, + ]; + + const documentCategories = [ + { id: 'all', name: 'Tümü', icon: '📋' }, + { id: 'technical', name: 'Teknik', icon: '⚙️' }, + { id: 'administrative', name: 'İdari', icon: '📊' }, + { id: 'legal', name: 'Hukuki', icon: '⚖️' }, + { id: 'financial', name: 'Mali', icon: '💰' }, + ]; + + // Form states const [selectedNewsCategory, setSelectedNewsCategory] = useState('all'); const [editingNews, setEditingNews] = useState(null); const [showNewsForm, setShowNewsForm] = useState(false); - - const filteredNewsList = selectedNewsCategory === 'all' - ? newsList - : newsList.filter(news => news.category === selectedNewsCategory); - - // Media management state - const [mediaList, setMediaList] = useState(mediaData); const [selectedMediaType, setSelectedMediaType] = useState<'all' | 'video' | 'photo'>('all'); - - const filteredMediaList = selectedMediaType === 'all' - ? mediaList - : mediaList.filter(media => media.type === selectedMediaType); - - // Documents management state - const [documentsList, setDocumentsList] = useState(documentsData); const [selectedDocCategory, setSelectedDocCategory] = useState('all'); - const filteredDocsList = selectedDocCategory === 'all' - ? documentsList - : documentsList.filter(doc => doc.category === selectedDocCategory); + // Filtered lists + const filteredNewsList = selectedNewsCategory === 'all' + ? newsItems + : newsItems.filter(news => news.category === selectedNewsCategory); - // Metro stations management state - const [stationsList, setStationsList] = useState(metroStations); + const filteredMediaList = selectedMediaType === 'all' + ? mediaItems + : mediaItems.filter(media => media.type === selectedMediaType); + + const filteredDocsList = selectedDocCategory === 'all' + ? documents + : documents.filter(doc => doc.category === selectedDocCategory); + + // Station filtering and selection const [selectedStationStatus, setSelectedStationStatus] = useState<'all' | 'completed' | 'in-progress' | 'planned'>('all'); + const [selectedStationId, setSelectedStationId] = useState(null); + + // Edit modals + const [editingSlide, setEditingSlide] = useState(null); + const [showSlideModal, setShowSlideModal] = useState(false); + const [editingNewsItem, setEditingNewsItem] = useState(null); + const [showNewsModal, setShowNewsModal] = useState(false); + const [editingMediaItem, setEditingMediaItem] = useState(null); + const [showMediaModal, setShowMediaModal] = useState(false); + const [editingDocument, setEditingDocument] = useState(null); + const [showDocumentModal, setShowDocumentModal] = useState(false); + const [editingStation, setEditingStation] = useState(null); + const [showStationModal, setShowStationModal] = useState(false); const filteredStationsList = selectedStationStatus === 'all' - ? stationsList - : stationsList.filter(station => station.status === selectedStationStatus); + ? metroStations + : metroStations.filter(station => station.status === selectedStationStatus); + + const handleStationClick = (stationId: number) => { + const newSelectedId = stationId === selectedStationId ? null : stationId; + setSelectedStationId(newSelectedId); + + // Ana sayfadaki metro animasyonu için seçili istasyonu kaydet + if (newSelectedId !== null) { + localStorage.setItem('metro_selected_station', newSelectedId.toString()); + } else { + localStorage.removeItem('metro_selected_station'); + } + }; + + // Slider edit handlers + const handleEditSlide = (slide: SliderItem) => { + setEditingSlide(slide); + setShowSlideModal(true); + }; + + const handleSaveSlide = (e: React.FormEvent) => { + e.preventDefault(); + if (editingSlide) { + const isNew = !sliderItems.find(s => s.id === editingSlide.id); + if (isNew) { + // Yeni slider ekle + const updated = [...sliderItems, editingSlide]; + setSliderItems(updated); + dataStore.setSlider(updated); + } else { + // Mevcut slider'ı güncelle + updateSlide(editingSlide.id, editingSlide); + } + setShowSlideModal(false); + setEditingSlide(null); + } + }; + + const handleAddSlide = () => { + const newSlide: SliderItem = { + id: Math.max(...sliderItems.map(s => s.id), 0) + 1, + title: '', + description: '', + buttonText: 'Detaylı Bilgi', + buttonLink: '#', + image: '', + active: false + }; + setEditingSlide(newSlide); + setShowSlideModal(true); + }; + + const handleDeleteSlide = (id: number) => { + if (confirm('Bu slider\'ı silmek istediğinizden emin misiniz?')) { + const updated = sliderItems.filter(s => s.id !== id); + setSliderItems(updated); + dataStore.setSlider(updated); + } + }; + + // News edit handlers + const handleAddNews = () => { + const newNews: NewsItem = { + id: Math.max(...newsItems.map(n => n.id), 0) + 1, + title: '', + summary: '', + content: '', + date: new Date().toLocaleDateString('tr-TR'), + image: '', + category: 'announcement', + featured: false + }; + setEditingNewsItem(newNews); + setShowNewsModal(true); + }; + + const handleEditNews = (news: NewsItem) => { + setEditingNewsItem(news); + setShowNewsModal(true); + }; + + const handleSaveNews = (e: React.FormEvent) => { + e.preventDefault(); + if (editingNewsItem) { + const isNew = !newsItems.find(n => n.id === editingNewsItem.id); + if (isNew) { + dataStore.addNews(editingNewsItem); + } else { + dataStore.updateNews(editingNewsItem.id, editingNewsItem); + } + loadData(); + setShowNewsModal(false); + setEditingNewsItem(null); + } + }; + + // Media edit handlers + const handleAddMedia = () => { + const newMedia: MediaItem = { + id: Math.max(...mediaItems.map(m => m.id), 0) + 1, + title: '', + description: '', + type: 'photo', + url: '', + thumbnail: '', + date: new Date().toLocaleDateString('tr-TR'), + category: 'construction' + }; + setEditingMediaItem(newMedia); + setShowMediaModal(true); + }; + + const handleEditMedia = (media: MediaItem) => { + setEditingMediaItem(media); + setShowMediaModal(true); + }; + + const handleSaveMedia = (e: React.FormEvent) => { + e.preventDefault(); + if (editingMediaItem) { + const isNew = !mediaItems.find(m => m.id === editingMediaItem.id); + if (isNew) { + dataStore.addMedia(editingMediaItem); + } else { + dataStore.updateMedia(editingMediaItem.id, editingMediaItem); + } + loadData(); + setShowMediaModal(false); + setEditingMediaItem(null); + } + }; + + // Document edit handlers + const handleAddDocument = () => { + const newDoc: Document = { + id: Math.max(...documents.map(d => d.id), 0) + 1, + title: '', + description: '', + type: 'pdf', + size: '', + date: new Date().toLocaleDateString('tr-TR'), + category: 'technical', + downloadUrl: '#' + }; + setEditingDocument(newDoc); + setShowDocumentModal(true); + }; + + const handleEditDocument = (doc: Document) => { + setEditingDocument(doc); + setShowDocumentModal(true); + }; + + const handleSaveDocument = (e: React.FormEvent) => { + e.preventDefault(); + if (editingDocument) { + const isNew = !documents.find(d => d.id === editingDocument.id); + if (isNew) { + dataStore.addDocument(editingDocument); + } else { + dataStore.updateDocument(editingDocument.id, editingDocument); + } + loadData(); + setShowDocumentModal(false); + setEditingDocument(null); + } + }; + + // Station edit handlers + const handleEditStation = (station: MetroStation) => { + setEditingStation(station); + setShowStationModal(true); + }; + + const handleSaveStation = (e: React.FormEvent) => { + e.preventDefault(); + if (editingStation) { + dataStore.updateStation(editingStation.id, editingStation); + loadData(); + setShowStationModal(false); + setEditingStation(null); + } + }; + + // Helper function for file icons + const getFileIcon = (type: string) => { + switch (type) { + case 'pdf': return '📄'; + case 'doc': return '📝'; + case 'xls': return '📊'; + case 'image': return '🖼️'; + default: return '📁'; + } + }; + + // Helper functions for station status + const getStatusColor = (status: string) => { + switch (status) { + case 'completed': return 'bg-green-500'; + case 'in-progress': return 'bg-yellow-500'; + case 'planned': return 'bg-blue-500'; + default: return 'bg-gray-500'; + } + }; + + const getStatusText = (status: string) => { + switch (status) { + case 'completed': return 'Tamamlandı'; + case 'in-progress': return 'Devam Ediyor'; + case 'planned': return 'Planlandı'; + default: return status; + } + }; return (
@@ -290,7 +559,10 @@ export default function Dashboard() {

Slider Yönetimi

Ana sayfa hero slider içeriklerini yönetin

-

Slide #{slide.id}

- - {slide.active ? '✓ Aktif' : '○ Pasif'} - +
- -
+ - - - + + + +
+
+ + setEditingSlide({ ...editingSlide, title: e.target.value })} + className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-[#00B4D8] focus:border-transparent" + required + /> +
+ +
+ + +
+ + {/* KVKK Onayı */} +
+ + +
+ + {/* Butonlar */} +
+ + +
+
+ + + ); +} diff --git a/components/ContactSection.tsx b/components/ContactSection.tsx new file mode 100644 index 0000000..1a4e2ec --- /dev/null +++ b/components/ContactSection.tsx @@ -0,0 +1,143 @@ +'use client'; + +interface ContactSectionProps { + onClose: () => void; +} + +export default function ContactSection({ onClose }: ContactSectionProps) { + return ( +
+
+
+
+
+ + + +
+

İletişim Bilgileri

+
+ +
+ +
+ {/* Sol Taraf - İletişim Kartları */} +
+ {/* Adres Kartı */} +
+
+
+ + + + +
+
+

ADRES

+

+ Emniyet Mah. Hipodrom Caddesi No: 5
+ Yenimahalle / Ankara +

+
+
+
+ + {/* KEP Adresi Kartı */} +
+
+
+ + + +
+ +
+
+ + {/* Telefon Kartı */} +
+
+
+ + + +
+ +
+
+ + {/* Çalışma Saatleri */} +
+
+
+ + + +
+
+

ÇALIŞMA SAATLERİ

+

+ Hafta İçi: 08:30 - 17:30
+ Hafta Sonu: Kapalı +

+
+
+
+
+ + {/* Sağ Taraf - Harita */} +
+

Konum

+
+ +
+ + {/* Haritada Göster Butonu */} + + + + + Google Maps'te Aç + +
+
+
+
+ ); +} diff --git a/components/DocumentsSection.tsx b/components/DocumentsSection.tsx new file mode 100644 index 0000000..0d74f18 --- /dev/null +++ b/components/DocumentsSection.tsx @@ -0,0 +1,132 @@ +'use client'; + +import { useState, useEffect } from 'react'; +import { dataStore } from '@/lib/dataStore'; +import type { Document } from '@/data/documents'; + +interface DocumentCategory { + id: string; + name: string; + icon: string; +} + +interface DocumentsSectionProps { + onClose: () => void; +} + +export default function DocumentsSection({ onClose }: DocumentsSectionProps) { + const [documents, setDocuments] = useState([]); + const [selectedCategory, setSelectedCategory] = useState('all'); + + const categories: DocumentCategory[] = [ + { id: 'all', name: 'Tümü', icon: '📋' }, + { id: 'ihale', name: 'İhale Belgeleri', icon: '📄' }, + { id: 'teknik', name: 'Teknik Dökümanlar', icon: '📐' }, + { id: 'cevresel', name: 'Çevresel Etki', icon: '🌱' }, + { id: 'raporlar', name: 'İlerleme Raporları', icon: '📊' }, + { id: 'guvenlik', name: 'Güvenlik', icon: '🛡️' }, + ]; + + useEffect(() => { + setDocuments(dataStore.getDocuments()); + }, []); + + const filteredDocs = selectedCategory === 'all' + ? documents + : documents.filter(doc => doc.category === selectedCategory); + + const getFileIcon = (type: string) => { + switch (type) { + case 'PDF': return '📕'; + case 'DWG': return '📐'; + case 'XLSX': return '📊'; + case 'DOCX': return '📝'; + default: return '📄'; + } + }; + + return ( +
+
+
+
+
+ + + +
+

Proje Belgeleri

+
+ +
+ + {/* Kategori Filtreleri */} +
+
+ {categories.map((cat) => ( + + ))} +
+
+ + {/* Belgeler Grid - 3 sütunlu */} +
+ {filteredDocs.map((doc) => ( +
+ {/* Dosya İkonu - Üstte ortalı */} +
+
+ {getFileIcon(doc.type)} +
+
+ + {/* Belge Bilgileri */} +
+

+ {doc.title} +

+

+ {doc.description} +

+
+ 📅 {doc.date} + 📄 {doc.type} + 💾 {doc.size} +
+
+ + {/* İndirme Butonu - Alt kısımda */} + +
+ ))} +
+
+
+ ); +} diff --git a/components/HeroSlider.tsx b/components/HeroSlider.tsx new file mode 100644 index 0000000..8aee690 --- /dev/null +++ b/components/HeroSlider.tsx @@ -0,0 +1,150 @@ +'use client'; + +import { useState, useEffect } from 'react'; + +// Hero Slider Data +const heroSlides = [ + { + id: 1, + title: 'Ankara Metro Altyapı Projelerinde Öncü Çözümler', + description: 'Ankara Büyükşehir Belediyesi ile birlikte, modern teknoloji ve mühendislik uzmanlığımızla başkentin ulaşım ağını inşa ediyor, geleceğin metro sistemlerini bugünden hayata geçiriyoruz.', + buttonText: 'Detayları Gör', + buttonLink: '#proje-detay' + }, + { + id: 2, + title: 'A2 Metro Hattı İnşaatında Son Aşamaya Gelindi', + description: '15 istasyonlu A2 Metro Hattı projemiz %75 tamamlandı. 2026 yılında hizmete açılacak modern metro hattımız, günlük 300 bin yolcuya hizmet verecek.', + buttonText: 'İlerlemeyi İzle', + buttonLink: '#metro-hatti' + }, + { + id: 3, + title: 'Çevre Dostu Metro Teknolojileri', + description: 'Yenilenebilir enerji kaynakları ve sürdürülebilir inşaat teknikleri ile çevre dostu metro projelerine imza atıyoruz. Karbon emisyonunu %40 azaltan yenilikçi çözümlerimiz.', + buttonText: 'Yeşil Projeler', + buttonLink: '#cevre' + }, + { + id: 4, + title: 'Güvenli İnşaat, Güvenli Gelecek', + description: 'ISO 45001 sertifikalı iş güvenliği sistemlerimiz ile 2000+ çalışanımızın güvenliğini en üst düzeyde tutuyoruz. Sıfır iş kazası hedefiyle çalışıyoruz.', + buttonText: 'Güvenlik Önlemleri', + buttonLink: '#guvenlik' + } +]; + +export default function HeroSlider() { + const [currentSlide, setCurrentSlide] = useState(0); + + // Auto slider + useEffect(() => { + const timer = setInterval(() => { + setCurrentSlide((prev) => (prev + 1) % heroSlides.length); + }, 10000); // 10 saniyede bir değiş + + return () => clearInterval(timer); + }, []); + + return ( +
+ {/* Video Background */} +
+ + {/* Dark Overlay */} +
+
+ + {/* Content Overlay */} +
+
+
+ {/* Slider Content */} +
+ {heroSlides.map((slide, index) => ( +
+

+ {slide.title} +

+

+ {slide.description} +

+ + {/* Action Buttons - Mobilde gizle */} +
+ + +
+
+ ))} +
+ + {/* Pagination Dots & Navigation */} +
+ {/* Dots */} +
+ {heroSlides.map((_, index) => ( +
+ + {/* Arrow Navigation */} +
+ + +
+
+
+
+
+
+ ); +} diff --git a/components/LiveStreamSection.tsx b/components/LiveStreamSection.tsx new file mode 100644 index 0000000..13faa7a --- /dev/null +++ b/components/LiveStreamSection.tsx @@ -0,0 +1,46 @@ +'use client'; + +interface LiveStreamSectionProps { + show: boolean; + onClose: () => void; +} + +export default function LiveStreamSection({ show, onClose }: LiveStreamSectionProps) { + if (!show) return null; + + return ( +
+
+
+
+
+

Canlı Yayın

+
+ +
+ + {/* YouTube Video Embed */} +
+ +
+ +

+ A2 Metro Hattı İnşaat Çalışmaları - Canlı Yayın +

+
+
+ ); +} diff --git a/components/MediaGallery.tsx b/components/MediaGallery.tsx new file mode 100644 index 0000000..f106872 --- /dev/null +++ b/components/MediaGallery.tsx @@ -0,0 +1,231 @@ +'use client'; + +import { useState, useEffect } from 'react'; +import Image from 'next/image'; +import { dataStore } from '@/lib/dataStore'; +import type { MediaItem } from '@/data/media'; + +interface MediaGalleryProps { + onClose: () => void; +} + +export default function MediaGallery({ onClose }: MediaGalleryProps) { + const [mediaItems, setMediaItems] = useState([]); + const [selectedMediaTab, setSelectedMediaTab] = useState<'all' | 'video' | 'photo'>('all'); + const [selectedMedia, setSelectedMedia] = useState(null); + + useEffect(() => { + setMediaItems(dataStore.getMedia()); + }, []); + + const filteredMedia = selectedMediaTab === 'all' + ? mediaItems + : mediaItems.filter(item => item.type === selectedMediaTab); + + const handleClose = () => { + setSelectedMedia(null); + setSelectedMediaTab('all'); + onClose(); + }; + + return ( +
+
+
+
+
+ + + +
+

Medya Galerisi

+
+ +
+ + {/* Medya Grid veya Detay */} + {selectedMedia === null ? ( + <> + {/* Tab Menü */} +
+ + + +
+ + {/* Medya Grid */} +
+ {filteredMedia.map((item) => ( +
setSelectedMedia(item.id)} + className="bg-gray-50 rounded-xl overflow-hidden hover:shadow-lg transition-all duration-300 hover:-translate-y-2 cursor-pointer group" + > + {/* Thumbnail */} +
+ {item.title} + {/* Video Badge */} + {item.type === 'video' && ( +
+
+ + + +
+
+ )} + {/* Photo Badge */} + {item.type === 'photo' && ( +
+ FOTO +
+ )} +
+ + {/* Content */} +
+
+ + + + {item.date} +
+

+ {item.title} +

+

+ {item.description} +

+
+
+ ))} +
+ + ) : ( + /* Medya Detayı */ +
+ {mediaItems.filter(m => m.id === selectedMedia).map((item) => ( +
+ {/* Geri Butonu */} + + + {/* Video Player veya Büyük Fotoğraf */} + {item.type === 'video' ? ( +
+ +
+ ) : ( +
+ {item.title} +
+ )} + + {/* Bilgiler */} +
+ + + + {item.date} +
+ +

+ {item.title} +

+ +

+ {item.description} +

+ + {/* Paylaş */} +
+
+
+ Paylaş: + +
+ +
+
+
+ ))} +
+ )} +
+
+ ); +} diff --git a/components/MetroLine.tsx b/components/MetroLine.tsx index f7dddb8..cb44125 100644 --- a/components/MetroLine.tsx +++ b/components/MetroLine.tsx @@ -1,56 +1,74 @@ 'use client'; import { useState, useEffect } from 'react'; +import { dataStore } from '@/lib/dataStore'; +import type { MetroStation } from '@/data/metroStations'; export default function MetroLine() { - const [currentStation, setCurrentStation] = useState(0); + const [stations, setStations] = useState([]); + const [selectedStationId, setSelectedStationId] = useState(null); + const [currentStationIndex, setCurrentStationIndex] = useState(0); - // Metro başlangıçtan Tuzluçayır'a (index 2) kadar ilerler ve durur useEffect(() => { - const interval = setInterval(() => { - setCurrentStation((prev) => { - if (prev < 2) return prev + 1; // Sadece 2'ye kadar ilerle - return 2; // Tuzluçayır'da dur - }); - }, 3000); // Her 3 saniyede bir ilerle + // Metro istasyonlarını yükle + const loadedStations = dataStore.getMetroStations(); + setStations(loadedStations); - return () => clearInterval(interval); + // Admin panelinden seçili istasyonu al + const adminSelectedId = localStorage.getItem('metro_selected_station'); + if (adminSelectedId) { + setSelectedStationId(parseInt(adminSelectedId)); + + // Seçili istasyonun index'ini bul + const selectedIndex = loadedStations.findIndex(s => s.id === parseInt(adminSelectedId)); + if (selectedIndex !== -1) { + // Metro animasyonu başlat + let currentIndex = 0; + const interval = setInterval(() => { + if (currentIndex < selectedIndex) { + currentIndex++; + setCurrentStationIndex(currentIndex); + } else { + clearInterval(interval); + } + }, 2000); // Her 2 saniyede bir ilerle + + return () => clearInterval(interval); + } + } }, []); - const stations = [ - { name: 'ABİDİN PAŞA', status: 'completed' }, - { name: 'AŞIK VEYSEL', status: 'completed' }, - { name: 'TUZLUÇAYIR', status: 'construction' }, - { name: 'GENERAL ZEKİ DOĞAN', status: 'planned' }, - { name: 'FAHRİ KORUTÜRK', status: 'planned' }, - { name: 'CENGİZHAN', status: 'planned' }, - { name: 'AKŞEMSETTİN', status: 'planned' }, - { name: 'NATOYOLU', status: 'planned' }, - ]; - - const getStationStyle = (index: number, status: string) => { - if (index === currentStation) { + const getStationStyle = (index: number, station: MetroStation) => { + if (index === currentStationIndex) { return 'w-16 h-16 bg-[#F59E0B] border-4 border-white shadow-2xl scale-110'; } - if (status === 'completed') { + if (station.status === 'completed' || index < currentStationIndex) { return 'w-14 h-14 bg-green-500 border-4 border-white shadow-lg'; } + if (station.status === 'in-progress') { + return 'w-14 h-14 bg-blue-500 border-4 border-white shadow-lg'; + } return 'w-12 h-12 bg-gray-300 border-4 border-dashed border-gray-400 shadow-lg opacity-60'; }; - const getTextStyle = (index: number, status: string) => { - if (index === currentStation) { + const getTextStyle = (index: number, station: MetroStation) => { + if (index === currentStationIndex) { return 'text-[#F59E0B] font-bold'; } - if (status === 'completed') { + if (station.status === 'completed' || index < currentStationIndex) { return 'text-green-600 font-bold'; } + if (station.status === 'in-progress') { + return 'text-blue-600 font-bold'; + } return 'text-gray-500 font-semibold'; }; - // Her durak arası mesafe için progress hesaplama - const totalStations = stations.length; - const progressPercentage = (currentStation / (totalStations - 1)) * 100; + const progressPercentage = stations.length > 0 ? (currentStationIndex / (stations.length - 1)) * 100 : 0; + + if (stations.length === 0) { + return
Yükleniyor...
; + } return (
@@ -86,9 +104,9 @@ export default function MetroLine() { {/* Duraklar Grid - Desktop */}
{stations.map((station, index) => ( -
-
- {index === currentStation ? ( +
+
+ {index === currentStationIndex ? ( <> {/* Metro simgesi - animasyonlu */} @@ -97,25 +115,31 @@ export default function MetroLine() { {/* Pulse efekti */}
- ) : station.status === 'completed' ? ( + ) : station.status === 'completed' || index < currentStationIndex ? ( + ) : station.status === 'in-progress' ? ( + + + ) : ( )}
- + {station.name} - {index === currentStation ? '🚇 Metro Burada' : - station.status === 'completed' ? '✓ Tamamlandı' : + {index === currentStationIndex ? '🚇 Metro Burada' : + station.status === 'completed' || index < currentStationIndex ? '✓ Tamamlandı' : + station.status === 'in-progress' ? '🔄 Devam Ediyor' : '◯ Planlı'}
@@ -126,25 +150,31 @@ export default function MetroLine() { {/* Metro Hat - Mobil (Dikey Liste) */}
{stations.map((station, index) => ( -
{/* İkon */}
- {index === currentStation ? ( + {index === currentStationIndex ? ( - ) : station.status === 'completed' ? ( + ) : station.status === 'completed' || index < currentStationIndex ? ( + ) : station.status === 'in-progress' ? ( + + + ) : ( @@ -155,19 +185,22 @@ export default function MetroLine() { {/* Bilgi */}

{station.name}

- {index === currentStation ? '🚇 Metro Burada' : - station.status === 'completed' ? '✓ Tamamlandı' : + {index === currentStationIndex ? '🚇 Metro Burada' : + station.status === 'completed' || index < currentStationIndex ? '✓ Tamamlandı' : + station.status === 'in-progress' ? '🔄 Devam Ediyor' : '◯ Planlı'}

@@ -175,8 +208,8 @@ export default function MetroLine() { {/* Bağlantı çizgisi (son istasyon hariç) */} {index < stations.length - 1 && (
)} diff --git a/components/NewsSection.tsx b/components/NewsSection.tsx new file mode 100644 index 0000000..b7bbd6a --- /dev/null +++ b/components/NewsSection.tsx @@ -0,0 +1,165 @@ +'use client'; + +import { useState } from 'react'; +import Image from 'next/image'; +import Link from 'next/link'; +import { newsData } from '@/data/news'; + +interface NewsSectionProps { + show: boolean; + onClose: () => void; + showLiveStream: boolean; +} + +export default function NewsSection({ show, onClose, showLiveStream }: NewsSectionProps) { + const [selectedNews, setSelectedNews] = useState(null); + + if (!show) return null; + + const featuredNews = newsData.filter(news => news.featured).slice(0, 4); + + return ( +
+
+
+
+
+ + + +
+

Son Haberler

+
+
+ + Tümünü Gör + + + + + +
+
+ + {/* Haberler Grid veya Detay */} + {selectedNews === null ? ( +
+ {featuredNews.map((news) => ( +
+ {/* Haber Görseli */} +
+ {news.title} +
+ + {/* Haber İçeriği */} +
+
+ + + + {news.date} +
+

+ {news.title} +

+

+ {news.summary} +

+ +
+
+ ))} +
+ ) : ( + /* Haber Detayı */ +
+ {newsData.filter(n => n.id === selectedNews).map((news) => ( +
+ {/* Geri Butonu */} + + + {/* Detay İçerik */} +
+ {/* Büyük Görsel */} +
+ {news.title} +
+ + {/* Detay Metni */} +
+
+ + + + {news.date} + + {news.author} +
+ +

+ {news.title} +

+ +

+ {news.content} +

+ + {/* Tags */} +
+ {news.tags.map((tag, index) => ( + + #{tag} + + ))} +
+
+
+
+ ))} +
+ )} +
+
+ ); +} diff --git a/components/QuickMenuCards.tsx b/components/QuickMenuCards.tsx new file mode 100644 index 0000000..63fcd2a --- /dev/null +++ b/components/QuickMenuCards.tsx @@ -0,0 +1,105 @@ +'use client'; + +interface QuickMenuCardsProps { + onLiveStreamClick: () => void; + onNewsClick: () => void; + onDocumentsClick: () => void; + onMediaClick: () => void; + onComplaintClick: () => void; + onContactClick: () => void; +} + +export default function QuickMenuCards({ + onLiveStreamClick, + onNewsClick, + onDocumentsClick, + onMediaClick, + onComplaintClick, + onContactClick +}: QuickMenuCardsProps) { + return ( +
+
+
+ {/* Canlı Yayın */} + + + {/* Haberler */} + + + {/* Belgeler */} + + + {/* Medya Galerisi */} + + + {/* Dilek-Şikayet */} + + + {/* E-İletişim */} + +
+
+
+ ); +} diff --git a/data/metroStations.ts b/data/metroStations.ts index dd384d4..32f9729 100644 --- a/data/metroStations.ts +++ b/data/metroStations.ts @@ -15,123 +15,93 @@ export interface MetroStation { export const metroStations: MetroStation[] = [ { id: 1, - name: 'Dikimevi', - status: 'in-progress', - progress: 75, - startDate: '15 Ocak 2024', - expectedCompletion: '30 Haziran 2026', - connections: ['M1', 'M3'], - features: ['Aktarma İstasyonu', 'Otopark', 'Engelsiz Erişim'], - dailyCapacity: '50,000', - image: 'https://images.pexels.com/photos/17152223/pexels-photo-17152223.jpeg' + name: 'ABİDİN PAŞA', + status: 'completed', + progress: 100, + startDate: '10 Ocak 2023', + expectedCompletion: '30 Aralık 2023', + actualCompletion: '25 Aralık 2023', + connections: ['M1'], + features: ['Aktarma İstasyonu', 'Otopark', 'Engelsiz Erişim', 'Ticari Alanlar'], + dailyCapacity: '45,000' }, { id: 2, - name: 'Tuzluçayır', - status: 'in-progress', - progress: 65, - startDate: '1 Şubat 2024', - expectedCompletion: '15 Temmuz 2026', + name: 'AŞIK VEYSEL', + status: 'completed', + progress: 100, + startDate: '15 Şubat 2023', + expectedCompletion: '15 Mart 2024', + actualCompletion: '10 Mart 2024', connections: [], - features: ['Modern Tasarım', 'Güneş Enerjisi', 'Güvenlik Sistemleri'], - dailyCapacity: '35,000', - image: 'https://images.pexels.com/photos/17302615/pexels-photo-17302615.jpeg' + features: ['Modern Tasarım', 'Güvenlik Sistemleri', 'Engelsiz Erişim'], + dailyCapacity: '35,000' }, { id: 3, - name: 'Yenimahalle', + name: 'TUZLUÇAYIR', status: 'in-progress', - progress: 55, - startDate: '15 Mart 2024', - expectedCompletion: '30 Ağustos 2026', - connections: ['M2'], - features: ['Aktarma Merkezi', 'Ticari Alan', 'Otopark'], - dailyCapacity: '45,000', - image: 'https://images.pexels.com/photos/33950678/pexels-photo-33950678.jpeg' + progress: 75, + startDate: '1 Mart 2024', + expectedCompletion: '30 Haziran 2025', + connections: [], + features: ['Modern Tasarım', 'Güneş Enerjisi', 'Güvenlik Sistemleri', 'Engelsiz Erişim'], + dailyCapacity: '40,000' }, { id: 4, - name: 'Demetevler', + name: 'GENERAL ZEKİ DOĞAN', status: 'in-progress', progress: 45, - startDate: '1 Nisan 2024', - expectedCompletion: '15 Eylül 2026', + startDate: '15 Nisan 2024', + expectedCompletion: '30 Eylül 2025', connections: [], - features: ['Modern Mimari', 'LED Aydınlatma', 'Havalandırma'], - dailyCapacity: '30,000', - image: 'https://images.pexels.com/photos/253647/pexels-photo-253647.jpeg' + features: ['Otopark', 'Bisiklet Park Alanı', 'Güvenlik Sistemleri'], + dailyCapacity: '30,000' }, { id: 5, - name: 'Akköprü', - status: 'in-progress', - progress: 40, - startDate: '15 Nisan 2024', - expectedCompletion: '30 Eylül 2026', - connections: [], - features: ['Geniş Peronlar', 'Asansör', 'Güvenlik Kameraları'], - dailyCapacity: '28,000', - image: 'https://images.pexels.com/photos/17152223/pexels-photo-17152223.jpeg' - }, - { - id: 6, - name: 'Şentepe', - status: 'planned', - progress: 25, - startDate: '1 Mayıs 2024', - expectedCompletion: '15 Ekim 2026', - connections: [], - features: ['Çevre Dostu', 'Akıllı Sistemler', 'Engelsiz Erişim'], - dailyCapacity: '25,000', - image: 'https://images.pexels.com/photos/17302615/pexels-photo-17302615.jpeg' - }, - { - id: 7, - name: 'Atatürk', - status: 'planned', - progress: 20, - startDate: '15 Mayıs 2024', - expectedCompletion: '30 Ekim 2026', - connections: ['M1', 'M4'], - features: ['Ana Aktarma', 'AVM Bağlantısı', 'Geniş Alan'], - dailyCapacity: '60,000', - image: 'https://images.pexels.com/photos/33950678/pexels-photo-33950678.jpeg' - }, - { - id: 8, - name: 'Sıhhiye', + name: 'FAHRİ KORUTÜRK', status: 'planned', progress: 15, startDate: '1 Haziran 2024', - expectedCompletion: '15 Kasım 2026', - connections: ['M2', 'M3'], - features: ['Merkezi Konum', 'Hastane Bağlantısı', 'Yüksek Kapasite'], - dailyCapacity: '55,000', - image: 'https://images.pexels.com/photos/253647/pexels-photo-253647.jpeg' + expectedCompletion: '31 Aralık 2025', + connections: [], + features: ['Modern Mimari', 'Yeşil Alan', 'Engelsiz Erişim'], + dailyCapacity: '35,000' }, { - id: 9, - name: 'Kızılay', + id: 6, + name: 'CENGİZHAN', status: 'planned', progress: 10, - startDate: '15 Haziran 2024', - expectedCompletion: '30 Kasım 2026', - connections: ['M1', 'M2', 'M3', 'M4'], - features: ['Merkez İstasyon', 'Çok Katlı', 'Tüm Hatlar'], - dailyCapacity: '80,000', - image: 'https://images.pexels.com/photos/17152223/pexels-photo-17152223.jpeg' + startDate: '1 Ağustos 2024', + expectedCompletion: '28 Şubat 2026', + connections: [], + features: ['Ticari Alanlar', 'Otopark', 'Güvenlik Sistemleri'], + dailyCapacity: '32,000' }, { - id: 10, - name: 'Kocatepe', + id: 7, + name: 'AKŞEMSETTİN', status: 'planned', progress: 5, - startDate: '1 Temmuz 2024', - expectedCompletion: '15 Aralık 2026', + startDate: '1 Ekim 2024', + expectedCompletion: '30 Nisan 2026', connections: [], - features: ['Modern Tasarım', 'Ticari Birimler', 'Güvenlik'], - dailyCapacity: '22,000', - image: 'https://images.pexels.com/photos/17302615/pexels-photo-17302615.jpeg' + features: ['Modern Tasarım', 'Engelsiz Erişim', 'Bisiklet Park Alanı'], + dailyCapacity: '28,000' + }, + { + id: 8, + name: 'NATOYOLU', + status: 'planned', + progress: 5, + startDate: '1 Aralık 2024', + expectedCompletion: '30 Haziran 2026', + connections: ['M2'], + features: ['Aktarma İstasyonu', 'Otopark', 'Ticari Alanlar', 'Modern Tasarım'], + dailyCapacity: '50,000' } ]; diff --git a/lib/dataStore.ts b/lib/dataStore.ts new file mode 100644 index 0000000..e41e337 --- /dev/null +++ b/lib/dataStore.ts @@ -0,0 +1,196 @@ +// Veri yönetimi için localStorage tabanlı store +import { newsData, type NewsItem } from '@/data/news'; +import { mediaData, type MediaItem } from '@/data/media'; +import { documentsData, type Document } from '@/data/documents'; +import { metroStations, type MetroStation } from '@/data/metroStations'; + +export interface SliderItem { + id: number; + title: string; + description: string; + buttonText: string; + buttonLink: string; + active: boolean; +} + +// Default slider data +export const defaultSliderData: SliderItem[] = [ + { + id: 1, + title: 'Ankara Metro Altyapı Projelerinde Öncü Çözümler', + description: 'Ankara Büyükşehir Belediyesi ile birlikte, modern teknoloji ve mühendislik uzmanlığımızla başkentin ulaşım ağını inşa ediyor, geleceğin metro sistemlerini bugünden hayata geçiriyoruz.', + buttonText: 'Detayları Gör', + buttonLink: '#proje-detay', + active: true + }, + { + id: 2, + title: 'A2 Metro Hattı İnşaatında Son Aşamaya Gelindi', + description: '15 istasyonlu A2 Metro Hattı projemiz %75 tamamlandı. 2026 yılında hizmete açılacak modern metro hattımız, günlük 300 bin yolcuya hizmet verecek.', + buttonText: 'İlerlemeyi İzle', + buttonLink: '#metro-hatti', + active: true + }, + { + id: 3, + title: 'Çevre Dostu Metro Teknolojileri', + description: 'Yenilenebilir enerji kaynakları ve sürdürülebilir inşaat teknikleri ile çevre dostu metro projelerine imza atıyoruz. Karbon emisyonunu %40 azaltan yenilikçi çözümlerimiz.', + buttonText: 'Yeşil Projeler', + buttonLink: '#cevre', + active: true + }, + { + id: 4, + title: 'Güvenli İnşaat, Güvenli Gelecek', + description: 'ISO 45001 sertifikalı iş güvenliği sistemlerimiz ile 2000+ çalışanımızın güvenliğini en üst düzeyde tutuyoruz. Sıfır iş kazası hedefiyle çalışıyoruz.', + buttonText: 'Güvenlik Önlemleri', + buttonLink: '#guvenlik', + active: true + } +]; + +// LocalStorage keys +const KEYS = { + SLIDER: 'a2metro_slider', + NEWS: 'a2metro_news', + MEDIA: 'a2metro_media', + DOCUMENTS: 'a2metro_documents', + METRO_STATIONS: 'a2metro_stations', +}; + +// Helper functions +const isBrowser = typeof window !== 'undefined'; + +export const dataStore = { + // Slider + getSlider: (): SliderItem[] => { + if (!isBrowser) return defaultSliderData; + const stored = localStorage.getItem(KEYS.SLIDER); + return stored ? JSON.parse(stored) : defaultSliderData; + }, + setSlider: (data: SliderItem[]) => { + if (isBrowser) { + localStorage.setItem(KEYS.SLIDER, JSON.stringify(data)); + } + }, + + // News + getNews: (): NewsItem[] => { + if (!isBrowser) return newsData; + const stored = localStorage.getItem(KEYS.NEWS); + return stored ? JSON.parse(stored) : newsData; + }, + setNews: (data: NewsItem[]) => { + if (isBrowser) { + localStorage.setItem(KEYS.NEWS, JSON.stringify(data)); + } + }, + addNews: (newsItem: Omit) => { + const current = dataStore.getNews(); + const newItem = { ...newsItem, id: Date.now() }; + dataStore.setNews([newItem, ...current]); + return newItem; + }, + updateNews: (id: number, newsItem: Partial) => { + const current = dataStore.getNews(); + const updated = current.map((item) => + item.id === id ? { ...item, ...newsItem } : item + ); + dataStore.setNews(updated); + }, + deleteNews: (id: number) => { + const current = dataStore.getNews(); + const filtered = current.filter((item) => item.id !== id); + dataStore.setNews(filtered); + }, + + // Media + getMedia: (): MediaItem[] => { + if (!isBrowser) return mediaData; + const stored = localStorage.getItem(KEYS.MEDIA); + return stored ? JSON.parse(stored) : mediaData; + }, + setMedia: (data: MediaItem[]) => { + if (isBrowser) { + localStorage.setItem(KEYS.MEDIA, JSON.stringify(data)); + } + }, + addMedia: (mediaItem: Omit) => { + const current = dataStore.getMedia(); + const newItem = { ...mediaItem, id: Date.now() }; + dataStore.setMedia([newItem, ...current]); + return newItem; + }, + updateMedia: (id: number, mediaItem: Partial) => { + const current = dataStore.getMedia(); + const updated = current.map((item) => + item.id === id ? { ...item, ...mediaItem } : item + ); + dataStore.setMedia(updated); + }, + deleteMedia: (id: number) => { + const current = dataStore.getMedia(); + const filtered = current.filter((item) => item.id !== id); + dataStore.setMedia(filtered); + }, + + // Documents + getDocuments: (): Document[] => { + if (!isBrowser) return documentsData; + const stored = localStorage.getItem(KEYS.DOCUMENTS); + return stored ? JSON.parse(stored) : documentsData; + }, + setDocuments: (data: Document[]) => { + if (isBrowser) { + localStorage.setItem(KEYS.DOCUMENTS, JSON.stringify(data)); + } + }, + addDocument: (document: Omit) => { + const current = dataStore.getDocuments(); + const newItem = { ...document, id: Date.now() }; + dataStore.setDocuments([newItem, ...current]); + return newItem; + }, + updateDocument: (id: number, document: Partial) => { + const current = dataStore.getDocuments(); + const updated = current.map((item) => + item.id === id ? { ...item, ...document } : item + ); + dataStore.setDocuments(updated); + }, + deleteDocument: (id: number) => { + const current = dataStore.getDocuments(); + const filtered = current.filter((item) => item.id !== id); + dataStore.setDocuments(filtered); + }, + + // Metro Stations + getMetroStations: (): MetroStation[] => { + if (!isBrowser) return metroStations; + const stored = localStorage.getItem(KEYS.METRO_STATIONS); + return stored ? JSON.parse(stored) : metroStations; + }, + setMetroStations: (data: MetroStation[]) => { + if (isBrowser) { + localStorage.setItem(KEYS.METRO_STATIONS, JSON.stringify(data)); + } + }, + updateStation: (id: number, station: Partial) => { + const current = dataStore.getMetroStations(); + const updated = current.map((item) => + item.id === id ? { ...item, ...station } : item + ); + dataStore.setMetroStations(updated); + }, + + // Reset all data + resetAll: () => { + if (isBrowser) { + localStorage.removeItem(KEYS.SLIDER); + localStorage.removeItem(KEYS.NEWS); + localStorage.removeItem(KEYS.MEDIA); + localStorage.removeItem(KEYS.DOCUMENTS); + localStorage.removeItem(KEYS.METRO_STATIONS); + } + } +};