Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fba6335153 |
0
account.php
Normal file
0
account.php
Normal file
63
api/auth.php
Normal file
63
api/auth.php
Normal file
@ -0,0 +1,63 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../includes/db.php';
|
||||
require_once __DIR__ . '/../includes/auth.php';
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
$action = $_GET['action'] ?? '';
|
||||
|
||||
switch ($action) {
|
||||
case 'register':
|
||||
$data = json_decode(file_get_contents('php://input'), true);
|
||||
if (empty($data['username']) || empty($data['password'])) {
|
||||
echo json_encode(['error' => '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']);
|
||||
}
|
||||
0
api/directions.php
Normal file
0
api/directions.php
Normal file
81
api/generate.php
Normal file
81
api/generate.php
Normal file
@ -0,0 +1,81 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../includes/db.php';
|
||||
require_once __DIR__ . '/../includes/auth.php';
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
http_response_code(405);
|
||||
echo json_encode(['error' => '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]);
|
||||
67
api/place-details.php
Normal file
67
api/place-details.php
Normal file
@ -0,0 +1,67 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../includes/db.php';
|
||||
header('Content-Type: application/json');
|
||||
|
||||
$place_id = $_GET['place_id'] ?? '';
|
||||
$name = $_GET['name'] ?? '';
|
||||
$category = $_GET['category'] ?? '';
|
||||
|
||||
if (empty($place_id)) {
|
||||
echo json_encode(['error' => '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);
|
||||
30
api/place-photo.php
Normal file
30
api/place-photo.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
/**
|
||||
* api/place-photo.php
|
||||
* Handles image redirection based on photo_reference and API key availability.
|
||||
*/
|
||||
|
||||
$photoReference = $_GET['photo_reference'] ?? null;
|
||||
$apiKey = getenv('GOOGLE_MAPS_API_KEY');
|
||||
$unsplashUrls = [
|
||||
'https://images.unsplash.com/photo-1544833316-64d88e00182a?w=800',
|
||||
'https://images.unsplash.com/photo-1570168007204-dfb528c6958f?w=800',
|
||||
'https://images.unsplash.com/photo-1524231757912-21f4fe3a7200?w=800'
|
||||
];
|
||||
|
||||
if (empty($photoReference)) {
|
||||
// Redirect to random Unsplash Kapadokya photo
|
||||
header('Location: ' . $unsplashUrls[array_rand($unsplashUrls)]);
|
||||
exit;
|
||||
}
|
||||
|
||||
if (!empty($apiKey)) {
|
||||
// Redirect to Google Places Photo
|
||||
$url = "https://maps.googleapis.com/maps/api/place/photo?maxwidth=800&photo_reference=" . urlencode($photoReference) . "&key=" . urlencode($apiKey);
|
||||
header('Location: ' . $url);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Fallback: Redirect to random Unsplash photo if no API key
|
||||
header('Location: ' . $unsplashUrls[array_rand($unsplashUrls)]);
|
||||
exit;
|
||||
73
api/trips.php
Normal file
73
api/trips.php
Normal file
@ -0,0 +1,73 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../includes/db.php';
|
||||
require_once __DIR__ . '/../includes/auth.php';
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if (!isLoggedIn()) {
|
||||
http_response_code(401);
|
||||
echo json_encode(['error' => '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()]);
|
||||
}
|
||||
0
assets/css/style.css
Normal file
0
assets/css/style.css
Normal file
44
db/migrations/001_init_schema.sql
Normal file
44
db/migrations/001_init_schema.sql
Normal file
@ -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
|
||||
);
|
||||
0
explore.php
Normal file
0
explore.php
Normal file
10
includes/auth.php
Normal file
10
includes/auth.php
Normal file
@ -0,0 +1,10 @@
|
||||
<?php
|
||||
session_start();
|
||||
function isLoggedIn() { return isset($_SESSION['user_id']); }
|
||||
function requireLogin() {
|
||||
if (!isLoggedIn()) {
|
||||
header('Location: /login.php?redirect=' . urlencode($_SERVER['REQUEST_URI']));
|
||||
exit;
|
||||
}
|
||||
}
|
||||
function currentUser() { return ['id' => $_SESSION['user_id'], 'username' => $_SESSION['username']]; }
|
||||
7
includes/db.php
Normal file
7
includes/db.php
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
$host = $_ENV['DB_HOST'] ?? 'localhost';
|
||||
$db = $_ENV['DB_NAME'] ?? 'kapadokya';
|
||||
$user = $_ENV['DB_USER'] ?? 'root';
|
||||
$pass = $_ENV['DB_PASS'] ?? '';
|
||||
$pdo = new PDO("mysql:host=$host;dbname=$db;charset=utf8mb4", $user, $pass);
|
||||
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
0
includes/footer.php
Normal file
0
includes/footer.php
Normal file
0
includes/header.php
Normal file
0
includes/header.php
Normal file
0
planner.php
Normal file
0
planner.php
Normal file
0
trip/view.php
Normal file
0
trip/view.php
Normal file
Loading…
x
Reference in New Issue
Block a user