556 lines
17 KiB
TypeScript
556 lines
17 KiB
TypeScript
// 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;
|
||
}
|
||
|
||
export interface LiveStreamConfig {
|
||
url: string;
|
||
active: boolean;
|
||
title?: string;
|
||
}
|
||
|
||
export interface Message {
|
||
id: string;
|
||
name: string;
|
||
email: string;
|
||
phone: string;
|
||
subject: string;
|
||
type: 'sikayet' | 'oneri' | 'bilgi';
|
||
message: string;
|
||
date: string;
|
||
read: boolean;
|
||
}
|
||
|
||
export interface FAQ {
|
||
id: number;
|
||
question: string;
|
||
answer: string;
|
||
order: number;
|
||
}
|
||
|
||
export interface Camera {
|
||
id: number;
|
||
name: string;
|
||
location: string;
|
||
videoUrl: string;
|
||
status: 'online' | 'offline';
|
||
viewers?: number;
|
||
order: number;
|
||
}
|
||
|
||
export interface SiteSettings {
|
||
contact: {
|
||
phone: string;
|
||
email: string;
|
||
address: string;
|
||
kep: string;
|
||
};
|
||
social: {
|
||
facebook: string;
|
||
twitter: string;
|
||
instagram: string;
|
||
youtube: string;
|
||
linkedin?: string;
|
||
};
|
||
companyInfo: {
|
||
name: string;
|
||
fullName: string;
|
||
foundedYear: string;
|
||
};
|
||
}
|
||
|
||
// 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
|
||
}
|
||
];
|
||
|
||
// Default FAQ data
|
||
export const defaultFAQData: FAQ[] = [
|
||
{
|
||
id: 1,
|
||
question: 'A2 Metro Hattı projesi ne zaman tamamlanacak?',
|
||
answer: 'A2 Metro Hattı projesinin 2026 yılı sonunda tamamlanması planlanmaktadır. Proje, Dikimevi-Natoyolu güzergâhında 6.5 kilometre uzunluğunda ve 5 istasyonlu bir metro hattı inşasını kapsamaktadır.',
|
||
order: 1
|
||
},
|
||
{
|
||
id: 2,
|
||
question: 'Metro hattı hangi istasyonları kapsayacak?',
|
||
answer: 'A2 Metro Hattı aşağıdaki istasyonları içerecektir: Dikimevi İstasyonu, Tuzluçayır İstasyonu, Natoyolu İstasyonu ve diğer ara istasyonlar. Toplam 5 istasyon bulunacaktır.',
|
||
order: 2
|
||
},
|
||
{
|
||
id: 3,
|
||
question: 'İnşaat çalışmaları sırasında trafik nasıl etkilenecek?',
|
||
answer: 'İnşaat çalışmaları sırasında geçici trafik düzenlemeleri uygulanacaktır. Alternatif güzergâhlar belirlenecek ve yönlendirme levhaları yerleştirilecektir. Vatandaşlarımızın anlayışına sığınıyoruz.',
|
||
order: 3
|
||
},
|
||
{
|
||
id: 4,
|
||
question: 'Proje maliyeti ne kadar?',
|
||
answer: 'A2 Metro Hattı projesinin toplam maliyeti yaklaşık 2.5 milyar TL olarak belirlenmiştir. Bu maliyet, tünel kazısı, istasyon inşaatı, ray döşeme ve elektrik-elektronik sistemleri kapsamaktadır.',
|
||
order: 4
|
||
},
|
||
{
|
||
id: 5,
|
||
question: 'Çevreye etkisi ne olacak?',
|
||
answer: 'Proje, çevre dostu teknolojiler kullanılarak gerçekleştirilmektedir. Çevresel Etki Değerlendirme (ÇED) raporu hazırlanmış ve gerekli izinler alınmıştır. İnşaat sırasında toz kontrolü ve gürültü önleme tedbirleri uygulanacaktır.',
|
||
order: 5
|
||
},
|
||
{
|
||
id: 6,
|
||
question: 'İstasyonlar hangi özelliklere sahip olacak?',
|
||
answer: 'İstasyonlar modern mimari tasarımla, enerji verimliliği, erişilebilirlik ve güvenlik ön planda tutularak inşa edilecektir. Güneş enerjisi panelleri, LED aydınlatma ve akıllı havalandırma sistemleri kullanılacaktır.',
|
||
order: 6
|
||
},
|
||
{
|
||
id: 7,
|
||
question: 'İnşaatta hangi teknolojiler kullanılacak?',
|
||
answer: 'Proje kapsamında TBM (Tunnel Boring Machine) tünel açma makinesi kullanılacaktır. Bu teknoloji sayesinde kazı çalışmaları daha hızlı ve güvenli şekilde gerçekleştirilecektir.',
|
||
order: 7
|
||
},
|
||
{
|
||
id: 8,
|
||
question: 'Proje ilerleme durumu nasıl takip edilebilir?',
|
||
answer: 'Bu web sitesi üzerinden canlı yayın, haberler ve medya galerisi bölümlerinden proje ilerleme durumunu takip edebilirsiniz. Ayrıca aylık ilerleme raporları yayınlanmaktadır.',
|
||
order: 8
|
||
}
|
||
];
|
||
|
||
// Default Camera data
|
||
export const defaultCameraData: Camera[] = [
|
||
{
|
||
id: 1,
|
||
name: 'Dikimevi İstasyonu - Ana Giriş',
|
||
location: 'Dikimevi',
|
||
videoUrl: 'https://www.youtube.com/embed/b9q88QDEcKg?autoplay=1',
|
||
status: 'online',
|
||
viewers: 1243,
|
||
order: 1
|
||
},
|
||
{
|
||
id: 2,
|
||
name: 'Tuzluçayır İstasyonu - İnşaat Sahası',
|
||
location: 'Tuzluçayır',
|
||
videoUrl: 'https://www.youtube.com/embed/b9q88QDEcKg?autoplay=1',
|
||
status: 'online',
|
||
viewers: 856,
|
||
order: 2
|
||
},
|
||
{
|
||
id: 3,
|
||
name: 'A2 Metro Hattı - Tünel Kazı Çalışması',
|
||
location: 'Mamak',
|
||
videoUrl: 'https://www.youtube.com/embed/b9q88QDEcKg?autoplay=1',
|
||
status: 'online',
|
||
viewers: 2134,
|
||
order: 3
|
||
},
|
||
{
|
||
id: 4,
|
||
name: 'İstasyon Binası İç Mekan',
|
||
location: 'Dikimevi',
|
||
videoUrl: 'https://www.youtube.com/embed/b9q88QDEcKg?autoplay=1',
|
||
status: 'online',
|
||
viewers: 534,
|
||
order: 4
|
||
}
|
||
];
|
||
|
||
// LocalStorage keys
|
||
const KEYS = {
|
||
SLIDER: 'a2metro_slider',
|
||
NEWS: 'a2metro_news',
|
||
MEDIA: 'a2metro_media',
|
||
DOCUMENTS: 'a2metro_documents',
|
||
METRO_STATIONS: 'a2metro_stations',
|
||
LIVE_STREAM: 'a2metro_live_stream',
|
||
SITE_SETTINGS: 'a2metro_site_settings',
|
||
MESSAGES: 'a2metro_messages',
|
||
FAQS: 'a2metro_faqs',
|
||
CAMERAS: 'a2metro_cameras'
|
||
};
|
||
|
||
// 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<NewsItem, 'id'>) => {
|
||
const current = dataStore.getNews();
|
||
const newItem = { ...newsItem, id: Date.now() };
|
||
dataStore.setNews([newItem, ...current]);
|
||
return newItem;
|
||
},
|
||
updateNews: (id: number, newsItem: Partial<NewsItem>) => {
|
||
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<MediaItem, 'id'>) => {
|
||
const current = dataStore.getMedia();
|
||
const newItem = { ...mediaItem, id: Date.now() };
|
||
dataStore.setMedia([newItem, ...current]);
|
||
return newItem;
|
||
},
|
||
updateMedia: (id: number, mediaItem: Partial<MediaItem>) => {
|
||
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<Document, 'id'>) => {
|
||
const current = dataStore.getDocuments();
|
||
const newItem = { ...document, id: Date.now() };
|
||
dataStore.setDocuments([newItem, ...current]);
|
||
return newItem;
|
||
},
|
||
updateDocument: (id: number, document: Partial<Document>) => {
|
||
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<MetroStation>) => {
|
||
const current = dataStore.getMetroStations();
|
||
const updated = current.map((item) =>
|
||
item.id === id ? { ...item, ...station } : item
|
||
);
|
||
dataStore.setMetroStations(updated);
|
||
},
|
||
|
||
// Live Stream
|
||
getLiveStream: (): LiveStreamConfig => {
|
||
if (!isBrowser) {
|
||
return {
|
||
url: 'https://www.youtube.com/embed/jfKfPfyJRdk?si=example',
|
||
active: true,
|
||
title: 'Canlı Yayın'
|
||
};
|
||
}
|
||
const stored = localStorage.getItem(KEYS.LIVE_STREAM);
|
||
return stored ? JSON.parse(stored) : {
|
||
url: 'https://www.youtube.com/embed/jfKfPfyJRdk?si=example',
|
||
active: true,
|
||
title: 'Canlı Yayın'
|
||
};
|
||
},
|
||
|
||
setLiveStream: (config: LiveStreamConfig) => {
|
||
if (isBrowser) {
|
||
localStorage.setItem(KEYS.LIVE_STREAM, JSON.stringify(config));
|
||
}
|
||
},
|
||
|
||
// Messages
|
||
getMessages: (): Message[] => {
|
||
if (!isBrowser) return [];
|
||
const stored = localStorage.getItem(KEYS.MESSAGES);
|
||
return stored ? JSON.parse(stored) : [];
|
||
},
|
||
|
||
addMessage: (message: Omit<Message, 'id' | 'date' | 'read'>) => {
|
||
const messages = dataStore.getMessages();
|
||
const newMessage: Message = {
|
||
...message,
|
||
id: Date.now().toString(),
|
||
date: new Date().toISOString(),
|
||
read: false
|
||
};
|
||
messages.unshift(newMessage);
|
||
if (isBrowser) {
|
||
localStorage.setItem(KEYS.MESSAGES, JSON.stringify(messages));
|
||
}
|
||
return newMessage;
|
||
},
|
||
|
||
markMessageAsRead: (id: string) => {
|
||
const messages = dataStore.getMessages();
|
||
const updated = messages.map(msg =>
|
||
msg.id === id ? { ...msg, read: true } : msg
|
||
);
|
||
if (isBrowser) {
|
||
localStorage.setItem(KEYS.MESSAGES, JSON.stringify(updated));
|
||
}
|
||
},
|
||
|
||
deleteMessage: (id: string) => {
|
||
const messages = dataStore.getMessages();
|
||
const filtered = messages.filter(msg => msg.id !== id);
|
||
if (isBrowser) {
|
||
localStorage.setItem(KEYS.MESSAGES, JSON.stringify(filtered));
|
||
}
|
||
},
|
||
|
||
// Site Settings
|
||
getSiteSettings: (): SiteSettings => {
|
||
if (!isBrowser) {
|
||
return {
|
||
contact: {
|
||
phone: '+90 (312) 123 45 67',
|
||
email: 'info@a2metro.com.tr',
|
||
address: 'Ankara Teknokent, Cyberpark C Blok Kat:3 No:301 Çankaya/ANKARA',
|
||
kep: 'a2metro@hs03.kep.tr'
|
||
},
|
||
social: {
|
||
facebook: 'https://facebook.com/a2metro',
|
||
twitter: 'https://twitter.com/a2metro',
|
||
instagram: 'https://instagram.com/a2metro',
|
||
youtube: 'https://youtube.com/@a2metro',
|
||
linkedin: 'https://linkedin.com/company/a2metro'
|
||
},
|
||
companyInfo: {
|
||
name: 'A2 Metro',
|
||
fullName: 'A2 Metro Yapı ve İnşaat A.Ş.',
|
||
foundedYear: '2010'
|
||
}
|
||
};
|
||
}
|
||
const stored = localStorage.getItem(KEYS.SITE_SETTINGS);
|
||
if (stored) return JSON.parse(stored);
|
||
|
||
// Default settings
|
||
const defaultSettings: SiteSettings = {
|
||
contact: {
|
||
phone: '+90 (312) 123 45 67',
|
||
email: 'info@a2metro.com.tr',
|
||
address: 'Ankara Teknokent, Cyberpark C Blok Kat:3 No:301 Çankaya/ANKARA',
|
||
kep: 'a2metro@hs03.kep.tr'
|
||
},
|
||
social: {
|
||
facebook: 'https://facebook.com/a2metro',
|
||
twitter: 'https://twitter.com/a2metro',
|
||
instagram: 'https://instagram.com/a2metro',
|
||
youtube: 'https://youtube.com/@a2metro',
|
||
linkedin: 'https://linkedin.com/company/a2metro'
|
||
},
|
||
companyInfo: {
|
||
name: 'A2 Metro',
|
||
fullName: 'A2 Metro Yapı ve İnşaat A.Ş.',
|
||
foundedYear: '2010'
|
||
}
|
||
};
|
||
localStorage.setItem(KEYS.SITE_SETTINGS, JSON.stringify(defaultSettings));
|
||
return defaultSettings;
|
||
},
|
||
|
||
updateSiteSettings: (settings: Partial<SiteSettings>) => {
|
||
const current = dataStore.getSiteSettings();
|
||
const updated = {
|
||
...current,
|
||
...settings,
|
||
contact: { ...current.contact, ...(settings.contact || {}) },
|
||
social: { ...current.social, ...(settings.social || {}) },
|
||
companyInfo: { ...current.companyInfo, ...(settings.companyInfo || {}) }
|
||
};
|
||
if (isBrowser) {
|
||
localStorage.setItem(KEYS.SITE_SETTINGS, JSON.stringify(updated));
|
||
}
|
||
},
|
||
|
||
// FAQs
|
||
getFAQs: (): FAQ[] => {
|
||
if (!isBrowser) return defaultFAQData;
|
||
const stored = localStorage.getItem(KEYS.FAQS);
|
||
return stored ? JSON.parse(stored) : defaultFAQData;
|
||
},
|
||
|
||
setFAQs: (faqs: FAQ[]) => {
|
||
if (isBrowser) {
|
||
localStorage.setItem(KEYS.FAQS, JSON.stringify(faqs));
|
||
}
|
||
},
|
||
|
||
addFAQ: (faq: Omit<FAQ, 'id'>) => {
|
||
const faqs = dataStore.getFAQs();
|
||
const newFAQ: FAQ = {
|
||
...faq,
|
||
id: faqs.length > 0 ? Math.max(...faqs.map(f => f.id)) + 1 : 1
|
||
};
|
||
dataStore.setFAQs([...faqs, newFAQ]);
|
||
return newFAQ;
|
||
},
|
||
|
||
updateFAQ: (id: number, updates: Partial<FAQ>) => {
|
||
const faqs = dataStore.getFAQs();
|
||
const updated = faqs.map(faq =>
|
||
faq.id === id ? { ...faq, ...updates } : faq
|
||
);
|
||
dataStore.setFAQs(updated);
|
||
},
|
||
|
||
deleteFAQ: (id: number) => {
|
||
const faqs = dataStore.getFAQs();
|
||
dataStore.setFAQs(faqs.filter(faq => faq.id !== id));
|
||
},
|
||
|
||
// Cameras
|
||
getCameras: (): Camera[] => {
|
||
if (!isBrowser) return defaultCameraData;
|
||
const stored = localStorage.getItem(KEYS.CAMERAS);
|
||
return stored ? JSON.parse(stored) : defaultCameraData;
|
||
},
|
||
|
||
setCameras: (cameras: Camera[]) => {
|
||
if (isBrowser) {
|
||
localStorage.setItem(KEYS.CAMERAS, JSON.stringify(cameras));
|
||
}
|
||
},
|
||
|
||
addCamera: (camera: Omit<Camera, 'id'>) => {
|
||
const cameras = dataStore.getCameras();
|
||
const newCamera: Camera = {
|
||
...camera,
|
||
id: cameras.length > 0 ? Math.max(...cameras.map(c => c.id)) + 1 : 1
|
||
};
|
||
dataStore.setCameras([...cameras, newCamera]);
|
||
return newCamera;
|
||
},
|
||
|
||
updateCamera: (id: number, updates: Partial<Camera>) => {
|
||
const cameras = dataStore.getCameras();
|
||
const updated = cameras.map(camera =>
|
||
camera.id === id ? { ...camera, ...updates } : camera
|
||
);
|
||
dataStore.setCameras(updated);
|
||
},
|
||
|
||
deleteCamera: (id: number) => {
|
||
const cameras = dataStore.getCameras();
|
||
dataStore.setCameras(cameras.filter(camera => camera.id !== id));
|
||
},
|
||
|
||
// 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);
|
||
localStorage.removeItem(KEYS.LIVE_STREAM);
|
||
localStorage.removeItem(KEYS.SITE_SETTINGS);
|
||
localStorage.removeItem(KEYS.MESSAGES);
|
||
localStorage.removeItem(KEYS.FAQS);
|
||
localStorage.removeItem(KEYS.CAMERAS);
|
||
}
|
||
}
|
||
};
|