This commit is contained in:
Şahan Hasret
2025-11-20 16:50:28 +03:00
parent 08c426f97b
commit c0b7fb463e
15 changed files with 1395 additions and 646 deletions

View File

@@ -1,6 +1,7 @@
'use client';
import { useState } from 'react';
import { dataStore } from '@/lib/dataStore';
interface ComplaintFormProps {
onClose: () => void;
@@ -11,7 +12,7 @@ interface FormData {
email: string;
phone: string;
subject: string;
type: string;
type: 'sikayet' | 'oneri' | 'bilgi';
message: string;
}
@@ -21,15 +22,40 @@ export default function ComplaintForm({ onClose }: ComplaintFormProps) {
email: '',
phone: '',
subject: '',
type: 'dilek',
type: 'oneri',
message: ''
});
const handleSubmit = (e: React.FormEvent) => {
const [isSubmitting, setIsSubmitting] = useState(false);
const [showSuccess, setShowSuccess] = useState(false);
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
alert('Form gönderildi! (Demo)');
handleReset();
onClose();
setIsSubmitting(true);
try {
// dataStore'a kaydet
dataStore.addMessage({
name: formData.name,
email: formData.email,
phone: formData.phone,
subject: formData.subject,
type: formData.type,
message: formData.message
});
setShowSuccess(true);
setTimeout(() => {
handleReset();
setShowSuccess(false);
onClose();
}, 2000);
} catch (error) {
console.error('Form gönderilirken hata:', error);
alert('Mesaj gönderilirken bir hata oluştu. Lütfen tekrar deneyin.');
} finally {
setIsSubmitting(false);
}
};
const handleReset = () => {
@@ -38,7 +64,7 @@ export default function ComplaintForm({ onClose }: ComplaintFormProps) {
email: '',
phone: '',
subject: '',
type: 'dilek',
type: 'oneri',
message: ''
});
};
@@ -70,6 +96,20 @@ export default function ComplaintForm({ onClose }: ComplaintFormProps) {
</button>
</div>
{/* Başarı Mesajı */}
{showSuccess && (
<div className="bg-green-50 border-l-4 border-green-500 p-4 mb-6 animate-fade-in">
<div className="flex items-center">
<svg className="w-5 h-5 text-green-500 mr-3" fill="currentColor" viewBox="0 0 20 20">
<path fillRule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clipRule="evenodd" />
</svg>
<p className="text-sm font-medium text-green-800">
Mesajınız başarıyla gönderildi! En kısa sürede size dönüş yapılacaktır.
</p>
</div>
</div>
)}
{/* Bilgilendirme */}
<div className="bg-blue-50 border-l-4 border-[#00B4D8] p-4 mb-6">
<div className="flex items-start">
@@ -94,9 +134,9 @@ export default function ComplaintForm({ onClose }: ComplaintFormProps) {
<input
type="radio"
name="type"
value="dilek"
checked={formData.type === 'dilek'}
onChange={(e) => setFormData({...formData, type: e.target.value})}
value="oneri"
checked={formData.type === 'oneri'}
onChange={(e) => setFormData({...formData, type: e.target.value as 'oneri'})}
className="w-4 h-4 text-[#00B4D8] border-gray-300 focus:ring-[#00B4D8]"
/>
<span className="ml-2 text-gray-700">Dilek / Öneri</span>
@@ -107,11 +147,22 @@ export default function ComplaintForm({ onClose }: ComplaintFormProps) {
name="type"
value="sikayet"
checked={formData.type === 'sikayet'}
onChange={(e) => setFormData({...formData, type: e.target.value})}
onChange={(e) => setFormData({...formData, type: e.target.value as 'sikayet'})}
className="w-4 h-4 text-[#00B4D8] border-gray-300 focus:ring-[#00B4D8]"
/>
<span className="ml-2 text-gray-700">Şikayet</span>
</label>
<label className="flex items-center cursor-pointer">
<input
type="radio"
name="type"
value="bilgi"
checked={formData.type === 'bilgi'}
onChange={(e) => setFormData({...formData, type: e.target.value as 'bilgi'})}
className="w-4 h-4 text-[#00B4D8] border-gray-300 focus:ring-[#00B4D8]"
/>
<span className="ml-2 text-gray-700">Bilgi Talebi</span>
</label>
</div>
</div>
@@ -215,17 +266,31 @@ export default function ComplaintForm({ onClose }: ComplaintFormProps) {
<div className="flex flex-col sm:flex-row gap-4 pt-4">
<button
type="submit"
className="flex-1 px-6 py-3 bg-[#00B4D8] text-white rounded-lg hover:bg-[#004B87] transition-colors font-semibold shadow-lg hover:shadow-xl flex items-center justify-center space-x-2"
disabled={isSubmitting}
className="flex-1 px-6 py-3 bg-[#00B4D8] text-white rounded-lg hover:bg-[#004B87] transition-colors font-semibold shadow-lg hover:shadow-xl flex items-center justify-center space-x-2 disabled:opacity-50 disabled:cursor-not-allowed"
>
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 19l9 2-9-18-9 18 9-2zm0 0v-8" />
</svg>
<span>Gönder</span>
{isSubmitting ? (
<>
<svg className="animate-spin h-5 w-5 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
<span>Gönderiliyor...</span>
</>
) : (
<>
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 19l9 2-9-18-9 18 9-2zm0 0v-8" />
</svg>
<span>Gönder</span>
</>
)}
</button>
<button
type="button"
onClick={handleReset}
className="px-6 py-3 bg-gray-200 text-gray-700 rounded-lg hover:bg-gray-300 transition-colors font-semibold"
disabled={isSubmitting}
className="px-6 py-3 bg-gray-200 text-gray-700 rounded-lg hover:bg-gray-300 transition-colors font-semibold disabled:opacity-50 disabled:cursor-not-allowed"
>
Temizle
</button>

View File

@@ -1,10 +1,21 @@
'use client';
import { useState, useEffect } from 'react';
import { dataStore, type SiteSettings } from '@/lib/dataStore';
interface ContactSectionProps {
onClose: () => void;
}
export default function ContactSection({ onClose }: ContactSectionProps) {
const [settings, setSettings] = useState<SiteSettings | null>(null);
useEffect(() => {
setSettings(dataStore.getSiteSettings());
}, []);
if (!settings) return null;
return (
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 pt-8 md:pt-32 pb-8">
<div className="bg-white rounded-2xl shadow-2xl p-6 lg:p-8">
@@ -42,8 +53,7 @@ export default function ContactSection({ onClose }: ContactSectionProps) {
<div className="flex-1">
<h3 className="text-lg font-bold text-[#004B87] mb-2">ADRES</h3>
<p className="text-gray-700 leading-relaxed">
Emniyet Mah. Hipodrom Caddesi No: 5<br />
Yenimahalle / Ankara
{settings.contact.address}
</p>
</div>
</div>
@@ -60,10 +70,10 @@ export default function ContactSection({ onClose }: ContactSectionProps) {
<div className="flex-1">
<h3 className="text-lg font-bold text-[#004B87] mb-2">KEP ADRESİ</h3>
<a
href="mailto:ankarabuyuksehirbelediyesi@hs01.kep.tr"
href={`mailto:${settings.contact.kep}`}
className="text-gray-700 hover:text-[#00B4D8] transition-colors break-all"
>
ankarabuyuksehirbelediyesi@hs01.kep.tr
{settings.contact.kep}
</a>
</div>
</div>
@@ -80,10 +90,30 @@ export default function ContactSection({ onClose }: ContactSectionProps) {
<div className="flex-1">
<h3 className="text-lg font-bold text-[#004B87] mb-2">TELEFON</h3>
<a
href="tel:+903125071000"
href={`tel:${settings.contact.phone.replace(/[^0-9+]/g, '')}`}
className="text-xl font-semibold text-gray-700 hover:text-[#00B4D8] transition-colors"
>
+90 (312) 507 10 00
{settings.contact.phone}
</a>
</div>
</div>
</div>
{/* E-posta Kartı */}
<div className="bg-linear-to-br from-purple-50 to-purple-100 rounded-xl p-6 hover:shadow-lg transition-all duration-300">
<div className="flex items-start space-x-4">
<div className="w-16 h-16 bg-purple-600 rounded-xl flex items-center justify-center shrink-0">
<svg className="w-8 h-8 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M16 12a4 4 0 10-8 0 4 4 0 008 0zm0 0v1.5a2.5 2.5 0 005 0V12a9 9 0 10-9 9m4.5-1.206a8.959 8.959 0 01-4.5 1.207" />
</svg>
</div>
<div className="flex-1">
<h3 className="text-lg font-bold text-[#004B87] mb-2">E-POSTA</h3>
<a
href={`mailto:${settings.contact.email}`}
className="text-gray-700 hover:text-[#00B4D8] transition-colors break-all"
>
{settings.contact.email}
</a>
</div>
</div>

View File

@@ -1,7 +1,19 @@
'use client';
import { useState, useEffect } from 'react';
import Link from 'next/link';
import Image from 'next/image';
import { dataStore, type SiteSettings } from '@/lib/dataStore';
export default function Footer() {
const [settings, setSettings] = useState<SiteSettings | null>(null);
useEffect(() => {
setSettings(dataStore.getSiteSettings());
}, []);
if (!settings) return null;
return (
<footer className="bg-linear-to-r from-[#003366] via-[#004B87] to-[#003366] text-white mt-16">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
@@ -80,14 +92,14 @@ export default function Footer() {
<svg className="w-5 h-5 text-[#00B4D8] mt-0.5 shrink-0" fill="currentColor" viewBox="0 0 20 20">
<path fillRule="evenodd" d="M5.05 4.05a7 7 0 119.9 9.9L10 18.9l-4.95-4.95a7 7 0 010-9.9zM10 11a2 2 0 100-4 2 2 0 000 4z" clipRule="evenodd" />
</svg>
<span className="text-gray-300 text-sm">Emniyet, Hipodrom Cd. No:5, 06430 Yenimahalle/Ankara</span>
<span className="text-gray-300 text-sm">{settings.contact.address}</span>
</li>
<li className="flex items-center space-x-3">
<svg className="w-5 h-5 text-[#00B4D8] shrink-0" fill="currentColor" viewBox="0 0 20 20">
<path d="M2 3a1 1 0 011-1h2.153a1 1 0 01.986.836l.74 4.435a1 1 0 01-.54 1.06l-1.548.773a11.037 11.037 0 006.105 6.105l.774-1.548a1 1 0 011.059-.54l4.435.74a1 1 0 01.836.986V17a1 1 0 01-1 1h-2C7.82 18 2 12.18 2 5V3z" />
</svg>
<a href="tel:+903124440644" className="text-gray-300 hover:text-white transition-colors text-sm">
(0312) 507 10 00
<a href={`tel:${settings.contact.phone.replace(/[^0-9+]/g, '')}`} className="text-gray-300 hover:text-white transition-colors text-sm">
{settings.contact.phone}
</a>
</li>
<li className="flex items-center space-x-3">
@@ -95,8 +107,8 @@ export default function Footer() {
<path d="M2.003 5.884L10 9.882l7.997-3.998A2 2 0 0016 4H4a2 2 0 00-1.997 1.884z" />
<path d="M18 8.118l-8 4-8-4V14a2 2 0 002 2h12a2 2 0 002-2V8.118z" />
</svg>
<a href="mailto:ankarabuyuksehirbelediyesi@hs01.kep.tr" className="text-gray-300 hover:text-white transition-colors text-sm">
ankarabuyuksehirbelediyesi@hs01.kep.tr
<a href={`mailto:${settings.contact.kep}`} className="text-gray-300 hover:text-white transition-colors text-sm">
{settings.contact.kep}
</a>
</li>
</ul>
@@ -107,7 +119,7 @@ export default function Footer() {
<div className="flex space-x-3">
{/* Facebook */}
<a
href="https://www.facebook.com/ankarabbld/?locale=tr_TR"
href={settings.social.facebook}
target="_blank"
rel="noopener noreferrer"
className="w-9 h-9 rounded-full bg-[#00B4D8] hover:bg-[#48CAE4] flex items-center justify-center transition-colors"
@@ -119,7 +131,7 @@ export default function Footer() {
</a>
{/* Twitter/X */}
<a
href="https://x.com/ankarabbld?ref_src=twsrc%5Egoogle%7Ctwcamp%5Eserp%7Ctwgr%5Eauthor"
href={settings.social.twitter}
target="_blank"
rel="noopener noreferrer"
className="w-9 h-9 rounded-full bg-[#00B4D8] hover:bg-[#48CAE4] flex items-center justify-center transition-colors"
@@ -131,7 +143,7 @@ export default function Footer() {
</a>
{/* Instagram */}
<a
href="https://www.instagram.com/ankarabbld/"
href={settings.social.instagram}
target="_blank"
rel="noopener noreferrer"
className="w-9 h-9 rounded-full bg-[#00B4D8] hover:bg-[#48CAE4] flex items-center justify-center transition-colors"
@@ -142,17 +154,19 @@ export default function Footer() {
</svg>
</a>
{/* LinkedIn */}
<a
href="https://www.linkedin.com/company/ankara-b%C3%BCy%C3%BCk%C5%9Fehir-belediyesi/?originalSubdomain=tr"
target="_blank"
rel="noopener noreferrer"
className="w-9 h-9 rounded-full bg-[#00B4D8] hover:bg-[#48CAE4] flex items-center justify-center transition-colors"
aria-label="LinkedIn"
>
{settings.social.linkedin && (
<a
href={settings.social.linkedin}
target="_blank"
rel="noopener noreferrer"
className="w-9 h-9 rounded-full bg-[#00B4D8] hover:bg-[#48CAE4] flex items-center justify-center transition-colors"
aria-label="LinkedIn"
>
<svg className="w-4 h-4" fill="currentColor" viewBox="0 0 24 24">
<path d="M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-11 19h-3v-11h3v11zm-1.5-12.268c-.966 0-1.75-.79-1.75-1.764s.784-1.764 1.75-1.764 1.75.79 1.75 1.764-.783 1.764-1.75 1.764zm13.5 12.268h-3v-5.604c0-3.368-4-3.113-4 0v5.604h-3v-11h3v1.765c1.396-2.586 7-2.777 7 2.476v6.759z"/>
</svg>
</a>
</a>
)}
</div>
</div>
</div>
@@ -161,7 +175,7 @@ export default function Footer() {
{/* Alt Bilgi */}
<div className="border-t border-white/10 mt-8 pt-8 text-center">
<p className="text-gray-400 text-sm">
© 2025 T.C. Ankara Büyükşehir Belediyesi - A2 Metro Hattı İnşaat Projesi. Tüm hakları saklıdır.
© {new Date().getFullYear()} {settings.companyInfo.fullName} - Tüm hakları saklıdır.
</p>
</div>
</div>

View File

@@ -1,9 +1,15 @@
import { useState } from 'react';
import { useState, useEffect } from 'react';
import Link from 'next/link';
import Image from 'next/image';
import { dataStore, type SiteSettings } from '@/lib/dataStore';
export default function Header() {
const [isMenuOpen, setIsMenuOpen] = useState(false);
const [settings, setSettings] = useState<SiteSettings | null>(null);
useEffect(() => {
setSettings(dataStore.getSiteSettings());
}, []);
const menuItems = [
{ href: '/', icon: '🏠', title: 'Ana Sayfa', desc: 'Projeye genel bakış' },
@@ -107,26 +113,58 @@ export default function Header() {
<div className="flex items-center space-x-4">
<div className="flex-1">
<p className="text-white/70 text-xs mb-2">Sosyal Medya</p>
<div className="flex space-x-2">
{[
{ icon: 'M23 3a10.9 10.9 0 01-3.14 1.53 4.48 4.48 0 00-7.86 3v1A10.66 10.66 0 013 4s-4 9 5 13a11.64 11.64 0 01-7 2c9 5 20 0 20-11.5a4.5 4.5 0 00-.08-.83A7.72 7.72 0 0023 3z', url: 'https://twitter.com/Ankara_BB' },
{ icon: 'M18 2h-3a5 5 0 00-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 011-1h3z', url: 'https://www.facebook.com/ankarabb' },
{ icon: 'M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zm0-2.163c-3.259 0-3.667.014-4.947.072-4.358.2-6.78 2.618-6.98 6.98-.059 1.281-.073 1.689-.073 4.948 0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98 1.281.058 1.689.072 4.948.072 3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98-1.281-.059-1.69-.073-4.949-.073zm0 5.838c-3.403 0-6.162 2.759-6.162 6.162s2.759 6.163 6.162 6.163 6.162-2.759 6.162-6.163c0-3.403-2.759-6.162-6.162-6.162zm0 10.162c-2.209 0-4-1.79-4-4 0-2.209 1.791-4 4-4s4 1.791 4 4c0 2.21-1.791 4-4 4zm6.406-11.845c-.796 0-1.441.645-1.441 1.44s.645 1.44 1.441 1.44c.795 0 1.439-.645 1.439-1.44s-.644-1.44-1.439-1.44z', url: 'https://www.instagram.com/ankarabb' },
{ icon: 'M16 8a6 6 0 016 6v7h-4v-7a2 2 0 00-2-2 2 2 0 00-2 2v7h-4v-7a6 6 0 016-6zM2 9h4v12H2z M4 2a2 2 0 100 4 2 2 0 000-4z', url: 'https://www.linkedin.com/company/ankara-bb' },
].map((social, i) => (
<a
key={i}
href={social.url}
target="_blank"
rel="noopener noreferrer"
className="w-10 h-10 rounded-lg bg-white/10 hover:bg-white/20 flex items-center justify-center transition-all hover:scale-110"
>
<svg className="w-5 h-5 text-white" fill="currentColor" viewBox="0 0 24 24">
<path d={social.icon} />
</svg>
</a>
))}
</div>
{settings && (
<div className="flex space-x-2">
{settings.social.twitter && (
<a
href={settings.social.twitter}
target="_blank"
rel="noopener noreferrer"
className="w-10 h-10 rounded-lg bg-white/10 hover:bg-white/20 flex items-center justify-center transition-all hover:scale-110"
>
<svg className="w-5 h-5 text-white" fill="currentColor" viewBox="0 0 24 24">
<path d="M23 3a10.9 10.9 0 01-3.14 1.53 4.48 4.48 0 00-7.86 3v1A10.66 10.66 0 013 4s-4 9 5 13a11.64 11.64 0 01-7 2c9 5 20 0 20-11.5a4.5 4.5 0 00-.08-.83A7.72 7.72 0 0023 3z" />
</svg>
</a>
)}
{settings.social.facebook && (
<a
href={settings.social.facebook}
target="_blank"
rel="noopener noreferrer"
className="w-10 h-10 rounded-lg bg-white/10 hover:bg-white/20 flex items-center justify-center transition-all hover:scale-110"
>
<svg className="w-5 h-5 text-white" fill="currentColor" viewBox="0 0 24 24">
<path d="M18 2h-3a5 5 0 00-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 011-1h3z" />
</svg>
</a>
)}
{settings.social.instagram && (
<a
href={settings.social.instagram}
target="_blank"
rel="noopener noreferrer"
className="w-10 h-10 rounded-lg bg-white/10 hover:bg-white/20 flex items-center justify-center transition-all hover:scale-110"
>
<svg className="w-5 h-5 text-white" fill="currentColor" viewBox="0 0 24 24">
<path d="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zm0-2.163c-3.259 0-3.667.014-4.947.072-4.358.2-6.78 2.618-6.98 6.98-.059 1.281-.073 1.689-.073 4.948 0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98 1.281.058 1.689.072 4.948.072 3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98-1.281-.059-1.69-.073-4.949-.073zm0 5.838c-3.403 0-6.162 2.759-6.162 6.162s2.759 6.163 6.162 6.163 6.162-2.759 6.162-6.163c0-3.403-2.759-6.162-6.162-6.162zm0 10.162c-2.209 0-4-1.79-4-4 0-2.209 1.791-4 4-4s4 1.791 4 4c0 2.21-1.791 4-4 4zm6.406-11.845c-.796 0-1.441.645-1.441 1.44s.645 1.44 1.441 1.44c.795 0 1.439-.645 1.439-1.44s-.644-1.44-1.439-1.44z" />
</svg>
</a>
)}
{settings.social.linkedin && (
<a
href={settings.social.linkedin}
target="_blank"
rel="noopener noreferrer"
className="w-10 h-10 rounded-lg bg-white/10 hover:bg-white/20 flex items-center justify-center transition-all hover:scale-110"
>
<svg className="w-5 h-5 text-white" fill="currentColor" viewBox="0 0 24 24">
<path d="M16 8a6 6 0 016 6v7h-4v-7a2 2 0 00-2-2 2 2 0 00-2 2v7h-4v-7a6 6 0 016-6zM2 9h4v12H2z M4 2a2 2 0 100 4 2 2 0 000-4z" />
</svg>
</a>
)}
</div>
)}
</div>
</div>
</div>

View File

@@ -39,28 +39,51 @@ export default function MetroLine() {
}, []);
const getStationStyle = (index: number, station: MetroStation) => {
// Seçili istasyonun index'ini bul
const selectedIndex = selectedStationId
? stations.findIndex(s => s.id === selectedStationId)
: -1;
// Animasyonda şu an bulunulan istasyon (sarı - metro treni burada)
if (index === currentStationIndex) {
return 'w-16 h-16 bg-[#F59E0B] border-4 border-white shadow-2xl scale-110';
}
if (station.status === 'completed' || index < currentStationIndex) {
// Seçili istasyondan ÖNCE olanlar - Tamamlandı (yeşil)
if (selectedIndex !== -1 && index < selectedIndex) {
return 'w-14 h-14 bg-green-500 border-4 border-white shadow-lg';
}
if (station.status === 'in-progress') {
// Seçili istasyon - Şu an inşaat aşamasında (mavi)
if (index === selectedIndex) {
return 'w-14 h-14 bg-blue-500 border-4 border-white shadow-lg';
}
// Seçili istasyondan SONRA olanlar - Planlı (gri)
return 'w-12 h-12 bg-gray-300 border-4 border-dashed border-gray-400 shadow-lg opacity-60';
};
const getTextStyle = (index: number, station: MetroStation) => {
const selectedIndex = selectedStationId
? stations.findIndex(s => s.id === selectedStationId)
: -1;
// Animasyonda şu an bulunulan istasyon
if (index === currentStationIndex) {
return 'text-[#F59E0B] font-bold';
}
if (station.status === 'completed' || index < currentStationIndex) {
// Seçili istasyondan ÖNCE olanlar - Tamamlandı
if (selectedIndex !== -1 && index < selectedIndex) {
return 'text-green-600 font-bold';
}
if (station.status === 'in-progress') {
// Seçili istasyon - İnşaat aşamasında
if (index === selectedIndex) {
return 'text-blue-600 font-bold';
}
// Seçili istasyondan SONRA olanlar - Planlı
return 'text-gray-500 font-semibold';
};
@@ -103,28 +126,36 @@ export default function MetroLine() {
{/* Duraklar Grid - Desktop */}
<div className="grid grid-cols-4 lg:grid-cols-8 gap-6 relative">
{stations.map((station, index) => (
<div key={station.id} className="flex flex-col items-center">
<div className={`relative z-10 rounded-full flex items-center justify-center mb-3 transition-all duration-500 ${getStationStyle(index, station)}`}>
{index === currentStationIndex ? (
<>
{/* Metro simgesi - animasyonlu */}
<svg className="w-8 h-8 text-white" fill="currentColor" viewBox="0 0 24 24">
<path d="M12 2c-4 0-8 .5-8 4v9.5C4 17.43 5.57 19 7.5 19L6 20.5v.5h2l2-2h4l2 2h2v-.5L16.5 19c1.93 0 3.5-1.57 3.5-3.5V6c0-3.5-4-4-8-4zM7.5 17c-.83 0-1.5-.67-1.5-1.5S6.67 14 7.5 14s1.5.67 1.5 1.5S8.33 17 7.5 17zm3.5-6H6V6h5v5zm5.5 6c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zm1.5-6h-5V6h5v5z"/>
{stations.map((station, index) => {
const selectedIndex = selectedStationId
? stations.findIndex(s => s.id === selectedStationId)
: -1;
return (
<div key={station.id} className="flex flex-col items-center">
<div className={`relative z-10 rounded-full flex items-center justify-center mb-3 transition-all duration-500 ${getStationStyle(index, station)}`}>
{index === currentStationIndex ? (
<>
{/* Metro simgesi - animasyonlu */}
<svg className="w-8 h-8 text-white" fill="currentColor" viewBox="0 0 24 24">
<path d="M12 2c-4 0-8 .5-8 4v9.5C4 17.43 5.57 19 7.5 19L6 20.5v.5h2l2-2h4l2 2h2v-.5L16.5 19c1.93 0 3.5-1.57 3.5-3.5V6c0-3.5-4-4-8-4zM7.5 17c-.83 0-1.5-.67-1.5-1.5S6.67 14 7.5 14s1.5.67 1.5 1.5S8.33 17 7.5 17zm3.5-6H6V6h5v5zm5.5 6c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zm1.5-6h-5V6h5v5z"/>
</svg>
{/* Pulse efekti */}
<div className="absolute inset-0 rounded-full bg-[#F59E0B] animate-ping opacity-30"></div>
</>
) : (selectedIndex !== -1 && index < selectedIndex) ? (
// Tamamlandı - Yeşil check
<svg className="w-6 h-6 text-white" fill="currentColor" viewBox="0 0 24 24">
<path d="M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2z"/>
</svg>
{/* Pulse efekti */}
<div className="absolute inset-0 rounded-full bg-[#F59E0B] animate-ping opacity-30"></div>
</>
) : station.status === 'completed' || index < currentStationIndex ? (
<svg className="w-6 h-6 text-white" fill="currentColor" viewBox="0 0 24 24">
<path d="M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2z"/>
</svg>
) : station.status === 'in-progress' ? (
<svg className="w-5 h-5 text-white" fill="currentColor" viewBox="0 0 24 24">
<path d="M12 2c-4 0-8 .5-8 4v9.5C4 17.43 5.57 19 7.5 19L6 20.5v.5h2l2-2h4l2 2h2v-.5L16.5 19c1.93 0 3.5-1.57 3.5-3.5V6c0-3.5-4-4-8-4z"/>
</svg>
) : (
<svg className="w-5 h-5 text-gray-500" fill="currentColor" viewBox="0 0 24 24">
) : (index === selectedIndex) ? (
// Seçili istasyon - İnşaat aşamasında
<svg className="w-5 h-5 text-white" fill="currentColor" viewBox="0 0 24 24">
<path d="M12 2c-4 0-8 .5-8 4v9.5C4 17.43 5.57 19 7.5 19L6 20.5v.5h2l2-2h4l2 2h2v-.5L16.5 19c1.93 0 3.5-1.57 3.5-3.5V6c0-3.5-4-4-8-4z"/>
</svg>
) : (
// Planlı - Gri saat
<svg className="w-5 h-5 text-gray-500" fill="currentColor" viewBox="0 0 24 24">
<path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
</svg>
)}
@@ -134,44 +165,50 @@ export default function MetroLine() {
</span>
<span className={`text-xs transition-all duration-300 ${
index === currentStationIndex ? 'text-[#F59E0B] font-semibold' :
station.status === 'completed' || index < currentStationIndex ? 'text-green-600' :
station.status === 'in-progress' ? 'text-blue-600' : 'text-gray-400'
(selectedIndex !== -1 && index < selectedIndex) ? 'text-green-600' :
(index === selectedIndex) ? 'text-blue-600' : 'text-gray-400'
}`}>
{index === currentStationIndex ? '🚇 Metro Burada' :
station.status === 'completed' || index < currentStationIndex ? '✓ Tamamlandı' :
station.status === 'in-progress' ? '🔄 Devam Ediyor' :
(selectedIndex !== -1 && index < selectedIndex) ? '✓ Tamamlandı' :
(index === selectedIndex) ? '🔄 Devam Ediyor' :
'◯ Planlı'}
</span>
</div>
))}
);
})}
</div>
</div>
{/* Metro Hat - Mobil (Dikey Liste) */}
<div className="md:hidden space-y-3">
{stations.map((station, index) => (
<div key={station.id} className={`flex items-center space-x-3 p-3 rounded-lg transition-all duration-500 ${
{stations.map((station, index) => {
const selectedIndex = selectedStationId
? stations.findIndex(s => s.id === selectedStationId)
: -1;
return (
<div key={station.id} className={`flex items-center space-x-3 p-3 rounded-lg transition-all duration-500 ${
index === currentStationIndex ? 'bg-[#F59E0B]/10 border-2 border-[#F59E0B]' :
station.status === 'completed' || index < currentStationIndex ? 'bg-green-50 border border-green-200' :
station.status === 'in-progress' ? 'bg-blue-50 border border-blue-200' :
(selectedIndex !== -1 && index < selectedIndex) ? 'bg-green-50 border border-green-200' :
(index === selectedIndex) ? 'bg-blue-50 border border-blue-200' :
'bg-gray-50 border border-gray-200'
}`}>
{/* İkon */}
<div className={`rounded-full flex items-center justify-center transition-all duration-500 shrink-0 ${
index === currentStationIndex ? 'w-12 h-12 bg-[#F59E0B]' :
station.status === 'completed' || index < currentStationIndex ? 'w-10 h-10 bg-green-500' :
station.status === 'in-progress' ? 'w-10 h-10 bg-blue-500' :
(selectedIndex !== -1 && index < selectedIndex) ? 'w-10 h-10 bg-green-500' :
(index === selectedIndex) ? 'w-10 h-10 bg-blue-500' :
'w-10 h-10 bg-gray-300'
}`}>
{index === currentStationIndex ? (
<svg className="w-6 h-6 text-white" fill="currentColor" viewBox="0 0 24 24">
<path d="M12 2c-4 0-8 .5-8 4v9.5C4 17.43 5.57 19 7.5 19L6 20.5v.5h2l2-2h4l2 2h2v-.5L16.5 19c1.93 0 3.5-1.57 3.5-3.5V6c0-3.5-4-4-8-4zM7.5 17c-.83 0-1.5-.67-1.5-1.5S6.67 14 7.5 14s1.5.67 1.5 1.5S8.33 17 7.5 17zm3.5-6H6V6h5v5zm5.5 6c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5zm1.5-6h-5V6h5v5z"/>
</svg>
) : station.status === 'completed' || index < currentStationIndex ? (
) : (selectedIndex !== -1 && index < selectedIndex) ? (
<svg className="w-5 h-5 text-white" fill="currentColor" viewBox="0 0 24 24">
<path d="M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2z"/>
</svg>
) : station.status === 'in-progress' ? (
) : (index === selectedIndex) ? (
<svg className="w-4 h-4 text-white" fill="currentColor" viewBox="0 0 24 24">
<path d="M12 2c-4 0-8 .5-8 4v9.5C4 17.43 5.57 19 7.5 19L6 20.5v.5h2l2-2h4l2 2h2v-.5L16.5 19c1.93 0 3.5-1.57 3.5-3.5V6c0-3.5-4-4-8-4z"/>
</svg>
@@ -186,21 +223,21 @@ export default function MetroLine() {
<div className="flex-1">
<h4 className={`font-bold text-sm ${
index === currentStationIndex ? 'text-[#F59E0B]' :
station.status === 'completed' || index < currentStationIndex ? 'text-green-700' :
station.status === 'in-progress' ? 'text-blue-700' :
(selectedIndex !== -1 && index < selectedIndex) ? 'text-green-700' :
(index === selectedIndex) ? 'text-blue-700' :
'text-gray-600'
}`}>
{station.name}
</h4>
<p className={`text-xs ${
index === currentStationIndex ? 'text-[#F59E0B]' :
station.status === 'completed' || index < currentStationIndex ? 'text-green-600' :
station.status === 'in-progress' ? 'text-blue-600' :
(selectedIndex !== -1 && index < selectedIndex) ? 'text-green-600' :
(index === selectedIndex) ? 'text-blue-600' :
'text-gray-500'
}`}>
{index === currentStationIndex ? '🚇 Metro Burada' :
station.status === 'completed' || index < currentStationIndex ? '✓ Tamamlandı' :
station.status === 'in-progress' ? '🔄 Devam Ediyor' :
(selectedIndex !== -1 && index < selectedIndex) ? '✓ Tamamlandı' :
(index === selectedIndex) ? '🔄 Devam Ediyor' :
'◯ Planlı'}
</p>
</div>
@@ -214,7 +251,8 @@ export default function MetroLine() {
}`} style={{ top: '100%', marginLeft: '-1px' }}></div>
)}
</div>
))}
);
})}
</div>
{/* Alt Bilgi */}