diff --git a/api/index.php b/api/index.php new file mode 100644 index 0000000..6e1e33b --- /dev/null +++ b/api/index.php @@ -0,0 +1,60 @@ + 'Query is empty']); + exit; +} + +$resp = LocalAIApi::createResponse( + [ + 'input' => [ + ['role' => 'system', 'content' => 'You are a travel agent specializing in Poland. The user is looking for: ' . $query . '. Provide a travel suggestion with a title and a description. Your response must be in JSON format, like this: {"title": "...", "description": "..."}'], + ['role' => 'user', 'content' => $query], + ], + ] +); + +if (!empty($resp['success'])) { + $text = LocalAIApi::extractText($resp); + $aiResponse = json_decode($text, true); + + if (json_last_error() !== JSON_ERROR_NONE) { + // If the response is not a valid JSON, we try to extract the title and description manually + // This is a fallback mechanism + $title = "AI Generated Response"; + $description = $text; + } else { + $title = $aiResponse['title'] ?? 'AI Generated Response'; + $description = $aiResponse['description'] ?? 'No description available.'; + } + + $pexelsUrl = 'https://api.pexels.com/v1/search?query=' . urlencode($title) . '&orientation=landscape&per_page=1&page=1'; + $pexelsData = pexels_get($pexelsUrl); + + $imageUrl = 'https://images.pexels.com/photos/1699030/pexels-photo-1699030.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1'; // Default image + if ($pexelsData && !empty($pexelsData['photos'])) { + $photo = $pexelsData['photos'][0]; + $imageUrl = $photo['src']['large2x'] ?? ($photo['src']['large'] ?? $photo['src']['original']); + } + + echo json_encode([ + 'title' => $title, + 'description' => $description, + 'image' => $imageUrl + ]); +} else { + error_log('AI error: ' . ($resp['error'] ?? 'unknown')); + echo json_encode(['error' => 'Failed to get AI response']); +} diff --git a/assets/css/custom.css b/assets/css/custom.css new file mode 100644 index 0000000..2f307cc --- /dev/null +++ b/assets/css/custom.css @@ -0,0 +1,44 @@ +body { + background-color: #F3F4F6; + font-family: 'Helvetica Neue', Arial, sans-serif; +} + +.hero { + background: linear-gradient(to right, #3B82F6, #10B981); + color: white; + padding: 4rem 2rem; + text-align: center; +} + +.hero h1 { + font-family: Georgia, 'Times New Roman', serif; + font-size: 3rem; + font-weight: bold; +} + +.card { + border-radius: 0.5rem; + border: none; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); +} + +.btn-primary { + background-color: #3B82F6; + border-color: #3B82F6; + border-radius: 0.5rem; + padding: 0.75rem 1.5rem; + font-weight: bold; +} + +.form-control { + border-radius: 0.5rem; + padding: 0.75rem 1.5rem; +} + +#suggestion-card { + display: none; +} + +#loading { + display: none; +} \ No newline at end of file diff --git a/assets/js/main.js b/assets/js/main.js new file mode 100644 index 0000000..e45b5ca --- /dev/null +++ b/assets/js/main.js @@ -0,0 +1,40 @@ +document.getElementById('suggestion-form').addEventListener('submit', function(e) { + e.preventDefault(); + const query = document.getElementById('query').value; + const suggestionCard = document.getElementById('suggestion-card'); + const loading = document.getElementById('loading'); + const suggestionImage = document.getElementById('suggestion-image'); + const suggestionTitle = document.getElementById('suggestion-title'); + const suggestionText = document.getElementById('suggestion-text'); + + suggestionCard.style.display = 'none'; + loading.style.display = 'block'; + + fetch('api/index.php', { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ query: query }) + }) + .then(response => response.json()) + .then(data => { + if (data.error) { + alert(data.error); + loading.style.display = 'none'; + return; + } + + suggestionImage.src = data.image; + suggestionTitle.textContent = data.title; + suggestionText.textContent = data.description; + + loading.style.display = 'none'; + suggestionCard.style.display = 'block'; + }) + .catch(error => { + console.error('Error:', error); + loading.style.display = 'none'; + alert('An error occurred while fetching the suggestion.'); + }); +}); \ No newline at end of file diff --git a/includes/pexels.php b/includes/pexels.php new file mode 100644 index 0000000..c680d19 --- /dev/null +++ b/includes/pexels.php @@ -0,0 +1,26 @@ + 0 ? $k : 'Vc99rnmOhHhJAbgGQoKLZtsaIVfkeownoQNbTj78VemUjKh08ZYRbf18'; + } + function pexels_get($url) { + $ch = curl_init(); + curl_setopt_array($ch, [ + CURLOPT_URL => $url, + CURLOPT_RETURNTRANSFER => true, + CURLOPT_HTTPHEADER => [ 'Authorization: '. pexels_key() ], + CURLOPT_TIMEOUT => 15, + ]); + $resp = curl_exec($ch); + $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); + curl_close($ch); + if ($code >= 200 && $code < 300 && $resp) return json_decode($resp, true); + return null; + } + function download_to($srcUrl, $destPath) { + $data = file_get_contents($srcUrl); + if ($data === false) return false; + if (!is_dir(dirname($destPath))) mkdir(dirname($destPath), 0775, true); + return file_put_contents($destPath, $data) !== false; + } + \ No newline at end of file diff --git a/index.php b/index.php index 7205f3d..e9e9bb9 100644 --- a/index.php +++ b/index.php @@ -1,150 +1,57 @@ - - + - - - New Style - - - - - - - - - - - - - - - - - - - + + + AI Travel Agent + + -
-
-

Analyzing your requirements and generating your website…

-
- Loading… -
-

AI is collecting your requirements and applying the first changes.

-

This page will update automatically as the plan is implemented.

-

Runtime: PHP — UTC

+ +
+
+

Your Personal AI Travel Agent for Poland

+

Discover amazing places, historical sites, and hidden gems.

+
-
- + +
+
+
+
+
+
+
+ + +
+ +
+
+
+
+
+ +
+
+
+
+ Loading... +
+

Thinking...

+
+
+ Suggestion Image +
+
+

+
+
+
+
+
+ + - + \ No newline at end of file