From fba6335153c931a6f87d8d1d3ac116dbcf35a1dc Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Wed, 4 Mar 2026 16:24:17 +0000 Subject: [PATCH] Autosave: 20260304-162416 --- account.php | 0 api/auth.php | 63 ++++++++++++++++++++++++ api/directions.php | 0 api/generate.php | 81 +++++++++++++++++++++++++++++++ api/place-details.php | 67 +++++++++++++++++++++++++ api/place-photo.php | 30 ++++++++++++ api/trips.php | 73 ++++++++++++++++++++++++++++ assets/css/style.css | 0 db/migrations/001_init_schema.sql | 44 +++++++++++++++++ explore.php | 0 includes/auth.php | 10 ++++ includes/db.php | 7 +++ includes/footer.php | 0 includes/header.php | 0 login.php | 0 planner.php | 0 trip/view.php | 0 17 files changed, 375 insertions(+) create mode 100644 account.php create mode 100644 api/auth.php create mode 100644 api/directions.php create mode 100644 api/generate.php create mode 100644 api/place-details.php create mode 100644 api/place-photo.php create mode 100644 api/trips.php create mode 100644 assets/css/style.css create mode 100644 db/migrations/001_init_schema.sql create mode 100644 explore.php create mode 100644 includes/auth.php create mode 100644 includes/db.php create mode 100644 includes/footer.php create mode 100644 includes/header.php create mode 100644 login.php create mode 100644 planner.php create mode 100644 trip/view.php diff --git a/account.php b/account.php new file mode 100644 index 0000000..e69de29 diff --git a/api/auth.php b/api/auth.php new file mode 100644 index 0000000..68a17a3 --- /dev/null +++ b/api/auth.php @@ -0,0 +1,63 @@ + 'Missing credentials']); + exit; + } + + try { + $stmt = $pdo->prepare("INSERT INTO users (username, password_hash) VALUES (?, ?)"); + $stmt->execute([$data['username'], password_hash($data['password'], PASSWORD_DEFAULT)]); + $userId = $pdo->lastInsertId(); + + $_SESSION['user_id'] = $userId; + $_SESSION['username'] = $data['username']; + + echo json_encode(['success' => true, 'user' => ['id' => $userId, 'username' => $data['username']]]); + } catch (PDOException $e) { + echo json_encode(['error' => 'Registration failed: ' . $e->getMessage()]); + } + break; + + case 'login': + $data = json_decode(file_get_contents('php://input'), true); + $stmt = $pdo->prepare("SELECT id, username, password_hash FROM users WHERE username = ?"); + $stmt->execute([$data['username'] ?? '']); + $user = $stmt->fetch(PDO::FETCH_ASSOC); + + if ($user && password_verify($data['password'] ?? '', $user['password_hash'])) { + $_SESSION['user_id'] = $user['id']; + $_SESSION['username'] = $user['username']; + echo json_encode(['success' => true, 'user' => ['id' => $user['id'], 'username' => $user['username']]]); + } else { + http_response_code(401); + echo json_encode(['error' => 'Invalid credentials']); + } + break; + + case 'logout': + session_destroy(); + echo json_encode(['success' => true]); + break; + + case 'me': + if (isLoggedIn()) { + echo json_encode(['user' => currentUser()]); + } else { + echo json_encode(['user' => null]); + } + break; + + default: + http_response_code(400); + echo json_encode(['error' => 'Invalid action']); +} diff --git a/api/directions.php b/api/directions.php new file mode 100644 index 0000000..e69de29 diff --git a/api/generate.php b/api/generate.php new file mode 100644 index 0000000..996d18d --- /dev/null +++ b/api/generate.php @@ -0,0 +1,81 @@ + 'Method not allowed']); + exit; +} + +$input = json_decode(file_get_contents('php://input'), true); + +// 1. Generate Itinerary (Mock fallback if API keys are missing) +function getMockItinerary($input) { + return [ + 'days' => [ + [ + 'day' => 1, + 'items' => [ + ['place_name' => 'Göreme Açık Hava Müzesi', 'category' => 'History', 'estimated_duration_minutes' => 120, 'description' => 'Historical cave churches.'], + ['place_name' => 'Paşabağları', 'category' => 'Nature', 'estimated_duration_minutes' => 90, 'description' => 'Fairy chimneys.'] + ] + ] + ] + ]; +} + +// 2. Google Places Lookup (Cache Check) +function getPlaceDetails($pdo, $placeName) { + $normalized = strtolower(trim($placeName)); + + $stmt = $pdo->prepare("SELECT * FROM places_cache WHERE place_name_normalized = ?"); + $stmt->execute([$normalized]); + $cached = $stmt->fetch(PDO::FETCH_ASSOC); + + if ($cached) return $cached; + + $apiKey = getenv('GOOGLE_MAPS_API_KEY'); + if (!$apiKey) return null; + + $url = "https://maps.googleapis.com/maps/api/place/textsearch/json?query=" . urlencode($placeName . " Cappadocia") . "&key=" . $apiKey; + $response = json_decode(file_get_contents($url), true); + + if (!empty($response['results'])) { + $r = $response['results'][0]; + $data = [ + 'place_name_normalized' => $normalized, + 'place_id' => $r['place_id'], + 'name' => $r['name'], + 'formatted_address' => $r['formatted_address'], + 'lat' => $r['geometry']['location']['lat'], + 'lng' => $r['geometry']['location']['lng'], + 'rating' => $r['rating'] ?? 0, + 'photo_reference' => $r['photos'][0]['photo_reference'] ?? null + ]; + + $stmt = $pdo->prepare("INSERT INTO places_cache (place_name_normalized, place_id, name, formatted_address, lat, lng, rating, photo_reference) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"); + $stmt->execute(array_values($data)); + return $data; + } + return null; +} + +// Logic: Attempt OpenAI, fallback to mock +$itinerary = getMockItinerary($input); // Simplified for now + +// Enrich with Places +foreach ($itinerary['days'] as &$day) { + foreach ($day['items'] as &$item) { + $details = getPlaceDetails($pdo, $item['place_name']); + if ($details) { + $item['place_id'] = $details['place_id']; + $item['lat'] = $details['lat']; + $item['lng'] = $details['lng']; + } + } +} + +echo json_encode(['success' => true, 'itinerary' => $itinerary]); diff --git a/api/place-details.php b/api/place-details.php new file mode 100644 index 0000000..8d3bdea --- /dev/null +++ b/api/place-details.php @@ -0,0 +1,67 @@ + 'place_id is required']); + exit; +} + +// 1. Check Cache +$stmt = $pdo->prepare("SELECT details FROM place_details_cache WHERE place_id = ?"); +$stmt->execute([$place_id]); +$cached = $stmt->fetchColumn(); + +if ($cached) { + echo json_encode(json_decode($cached)); + exit; +} + +// 2. Google Places Details API +$apiKey = getenv('GOOGLE_MAPS_API_KEY'); +$url = "https://maps.googleapis.com/maps/api/place/details/json?place_id=$place_id&fields=name,rating,user_ratings_total,reviews,opening_hours,editorial_summary&language=tr&key=$apiKey"; +$ch = curl_init($url); +curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); +$response = curl_exec($ch); +curl_close($ch); +$data = json_decode($response, true); + +if (!isset($data['result'])) { + echo json_encode(['error' => 'Failed to fetch details']); + exit; +} + +$result = $data['result']; + +// 3. Generate Content (Placeholder / Logic for AI) +// In a real production app, call OpenAI API here if configured. +// Using static fallback as requested for now. +$aiContent = [ + 'why_visit' => ["Kapadokya'nın eşsiz güzelliklerini keşfedin", "Tarihi dokusuyla büyülenin", "Unutulmaz fotoğraflar çekin"], + 'tips' => ["Sabah erken saatlerde ziyaret etmenizi öneririz.", "Rahat ayakkabılar giyin.", "Güneş kreminizi yanınıza alın.", "Yerel rehberlerden bilgi alabilirsiniz."], + 'summary' => "{$result['name']}, bölgedeki en ilgi çekici ve kültürel açıdan zengin noktalardan biridir. Ziyaretçilerine hem doğal güzellikler hem de tarihi deneyimler sunmaktadır." +]; + +$finalResponse = [ + 'place_id' => $place_id, + 'name' => $result['name'] ?? $name, + 'summary' => $aiContent['summary'], + 'rating' => $result['rating'] ?? 0, + 'total_ratings' => $result['user_ratings_total'] ?? 0, + 'is_open_now' => $result['opening_hours']['open_now'] ?? null, + 'opening_hours' => $result['opening_hours']['weekday_text'] ?? [], + 'why_visit' => $aiContent['why_visit'], + 'tips' => $aiContent['tips'], + 'reviews' => $result['reviews'] ?? [] +]; + +// 5. Cache +$stmt = $pdo->prepare("INSERT IGNORE INTO place_details_cache (place_id, details) VALUES (?, ?)"); +$stmt->execute([$place_id, json_encode($finalResponse)]); + +// 6. Respond +echo json_encode($finalResponse); diff --git a/api/place-photo.php b/api/place-photo.php new file mode 100644 index 0000000..961c5ca --- /dev/null +++ b/api/place-photo.php @@ -0,0 +1,30 @@ + 'Unauthorized']); + exit; +} + +$action = $_GET['action'] ?? ''; +$user_id = $_SESSION['user_id']; + +try { + switch ($action) { + case 'list': + $stmt = $pdo->prepare("SELECT * FROM trips WHERE user_id = ? ORDER BY created_at DESC"); + $stmt->execute([$user_id]); + echo json_encode(['trips' => $stmt->fetchAll(PDO::FETCH_ASSOC)]); + break; + + case 'get': + $id = $_GET['id'] ?? ''; + $stmt = $pdo->prepare("SELECT * FROM trips WHERE id = ? AND user_id = ?"); + $stmt->execute([$id, $user_id]); + $trip = $stmt->fetch(PDO::FETCH_ASSOC); + if (!$trip) { + http_response_code(404); + echo json_encode(['error' => 'Trip not found']); + } else { + echo json_encode(['trip' => $trip]); + } + break; + + case 'create': + $data = json_decode(file_get_contents('php://input'), true); + $stmt = $pdo->prepare("INSERT INTO trips (user_id, title, start_date, end_date, preferences, itinerary) VALUES (?, ?, ?, ?, ?, ?)"); + $stmt->execute([ + $user_id, + $data['title'], + $data['start_date'], + $data['end_date'], + json_encode($data['preferences']), + json_encode($data['itinerary']) + ]); + echo json_encode(['success' => true, 'trip_id' => $pdo->lastInsertId()]); + break; + + case 'update': + $id = $_GET['id'] ?? ''; + $data = json_decode(file_get_contents('php://input'), true); + $stmt = $pdo->prepare("UPDATE trips SET itinerary = ? WHERE id = ? AND user_id = ?"); + $stmt->execute([json_encode($data['itinerary']), $id, $user_id]); + echo json_encode(['success' => true]); + break; + + case 'delete': + $id = $_GET['id'] ?? ''; + $stmt = $pdo->prepare("DELETE FROM trips WHERE id = ? AND user_id = ?"); + $stmt->execute([$id, $user_id]); + echo json_encode(['success' => true]); + break; + + default: + http_response_code(400); + echo json_encode(['error' => 'Invalid action']); + } +} catch (Exception $e) { + http_response_code(500); + echo json_encode(['error' => $e->getMessage()]); +} diff --git a/assets/css/style.css b/assets/css/style.css new file mode 100644 index 0000000..e69de29 diff --git a/db/migrations/001_init_schema.sql b/db/migrations/001_init_schema.sql new file mode 100644 index 0000000..2b4af04 --- /dev/null +++ b/db/migrations/001_init_schema.sql @@ -0,0 +1,44 @@ +CREATE TABLE IF NOT EXISTS users ( + id INT AUTO_INCREMENT PRIMARY KEY, + username VARCHAR(50) UNIQUE NOT NULL, + password_hash VARCHAR(255) NOT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); + +CREATE TABLE IF NOT EXISTS trips ( + id VARCHAR(36) PRIMARY KEY, + user_id INT NOT NULL, + title VARCHAR(255) NOT NULL, + destination VARCHAR(255) DEFAULT 'Cappadocia', + start_date DATE NOT NULL, + end_date DATE NOT NULL, + preferences JSON, + itinerary JSON, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS places_cache ( + place_name_normalized VARCHAR(255) PRIMARY KEY, + place_id VARCHAR(255), + name VARCHAR(255), + formatted_address TEXT, + lat FLOAT, + lng FLOAT, + rating FLOAT, + photo_reference TEXT, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); + +CREATE TABLE IF NOT EXISTS place_details_cache ( + place_id VARCHAR(255) PRIMARY KEY, + details JSON NOT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); + +CREATE TABLE IF NOT EXISTS directions_cache ( + cache_key VARCHAR(500) PRIMARY KEY, + response JSON NOT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); diff --git a/explore.php b/explore.php new file mode 100644 index 0000000..e69de29 diff --git a/includes/auth.php b/includes/auth.php new file mode 100644 index 0000000..2df15ad --- /dev/null +++ b/includes/auth.php @@ -0,0 +1,10 @@ + $_SESSION['user_id'], 'username' => $_SESSION['username']]; } diff --git a/includes/db.php b/includes/db.php new file mode 100644 index 0000000..ee6a919 --- /dev/null +++ b/includes/db.php @@ -0,0 +1,7 @@ +setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); diff --git a/includes/footer.php b/includes/footer.php new file mode 100644 index 0000000..e69de29 diff --git a/includes/header.php b/includes/header.php new file mode 100644 index 0000000..e69de29 diff --git a/login.php b/login.php new file mode 100644 index 0000000..e69de29 diff --git a/planner.php b/planner.php new file mode 100644 index 0000000..e69de29 diff --git a/trip/view.php b/trip/view.php new file mode 100644 index 0000000..e69de29