$stmt = $pdo->prepare("
SELECT
v.vote_type,
v.created_at,
v.comment,
c.display_name as category_name,
c.name as category_key
FROM user_votes v
JOIN websites w ON v.website_id = w.id
LEFT JOIN voting_categories c ON v.category_id = c.id
WHERE w.domain = ?
AND v.vote_type = 'down'
AND v.created_at >= DATE_SUB(NOW(), INTERVAL 24 HOUR)
ORDER BY v.created_at DESC
");
$stmt->execute([$domain]);
return $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (Exception $e) {
return [];
}
}
/**
* ENHANCED: Get recent checks with intelligent status for each check
* This adds user report analysis to each historical check
*/
function getRecentChecksWithIntelligentStatus($pdo, $domain, $hours = 24) {
try {
// Get the basic hourly checks
$recent_checks = getWebsiteRecentChecksHourly($pdo, $domain, $hours);
if (empty($recent_checks)) {
return [];
}
// Enhance each check with intelligent status
$enhanced_checks = [];
foreach ($recent_checks as $check) {
$check_time = $check['checked_at'];
// Get user reports around this check time (±30 minutes)
$user_reports = getUserReportsAroundTime($pdo, $domain, $check_time);
// Calculate intelligent status for this specific check
$intelligent_status = calculateIntelligentStatusForCheck($check, $user_reports);
// Add intelligent status to the check data
$enhanced_check = array_merge($check, [
'intelligent_status' => $intelligent_status['status'],
'intelligent_message' => $intelligent_status['message'],
'user_reports_count' => count($user_reports),
'confidence' => $intelligent_status['confidence'],
'status_badge_class' => getIntelligentStatusBadgeClass($intelligent_status),
'status_icon' => getIntelligentStatusIcon($intelligent_status)
]);
$enhanced_checks[] = $enhanced_check;
}
return $enhanced_checks;
} catch (Exception $e) {
error_log("Error in getRecentChecksWithIntelligentStatus: " . $e->getMessage());
return [];
}
}
/**
* GET: User reports around a specific check time (only backward-looking)
*/
function getUserReportsAroundTime($pdo, $domain, $check_time, $window_minutes = 30) {
try {
$check_timestamp = strtotime($check_time);
$start_time = date('Y-m-d H:i:s', $check_timestamp - ($window_minutes * 60));
$end_time = $check_time; // Only look backward from check time, not forward
$stmt = $pdo->prepare("
SELECT
v.vote_type,
v.created_at,
v.comment,
c.display_name as category_name,
c.name as category_key
FROM user_votes v
JOIN websites w ON v.website_id = w.id
LEFT JOIN voting_categories c ON v.category_id = c.id
WHERE w.domain = ?
AND v.vote_type = 'down'
AND v.created_at >= ?
AND v.created_at <= ?
ORDER BY v.created_at DESC
");
$stmt->execute([$domain, $start_time, $end_time]);
return $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (Exception $e) {
return [];
}
}
/**
* CALCULATE: Intelligent status for a specific check with enhanced user experience context
*/
function calculateIntelligentStatusForCheck($check, $user_reports) {
$technical_status = $check['status'];
$user_reports_count = count($user_reports);
// Determine intelligent status based on technical status and user reports
$intelligent_status = $technical_status;
$confidence = 'high';
$message = '';
$user_experience_context = '';
if ($technical_status === 'up') {
if ($user_reports_count >= 3) {
$intelligent_status = 'degraded';
$confidence = 'high';
$message = "Server responding but {$user_reports_count} users reported issues";
$user_experience_context = 'Multiple users reporting problems suggests widespread issues that technical monitoring cannot detect.';
} elseif ($user_reports_count >= 2) {
$intelligent_status = 'degraded';
$confidence = 'high';
$message = "Server responding but {$user_reports_count} users reported issues";
$user_experience_context = 'Technical monitoring shows the server is online, but users are experiencing problems. This could indicate performance issues or partial functionality problems.';
} elseif ($user_reports_count >= 1) {
$intelligent_status = 'partial';
$confidence = 'medium';
$message = "Server responding but {$user_reports_count} user(s) reported issues";
$user_experience_context = 'The website appears to be working technically, but some users are reporting problems. This could be due to regional issues, specific features not working, or intermittent problems.';
} else {
$intelligent_status = 'up';
$confidence = 'high';
$message = 'Server responding normally';
$user_experience_context = 'Both technical monitoring and user reports indicate the website is working normally.';
}
} elseif ($technical_status === 'down') {
if ($user_reports_count >= 1) {
$intelligent_status = 'down';
$confidence = 'high';
$message = "Server down - {$user_reports_count} user(s) confirmed issues";
$user_experience_context = 'Both technical monitoring and user reports confirm the website is experiencing problems.';
} else {
$intelligent_status = 'partial';
$confidence = 'medium';
$message = 'Technical issues detected but no user reports';
$user_experience_context = 'Technical monitoring shows server problems, but no user reports yet.';
}
} else {
// For other statuses (slow, error, etc.)
$intelligent_status = $technical_status;
$confidence = 'medium';
$message = 'Technical status with user feedback';
$user_experience_context = 'Technical monitoring indicates issues, and user reports provide additional context.';
}
return [
'status' => $intelligent_status,
'confidence' => $confidence,
'message' => $message,
'user_experience_context' => $user_experience_context,
'user_reports_count' => $user_reports_count,
'technical_status' => $technical_status
];
}
/**
* FORMAT: Enhanced status badge for recent checks
*/
function formatIntelligentStatusBadge($intelligent_status, $user_reports_count = 0) {
$status = $intelligent_status['status'];
$badge_class = getIntelligentStatusBadgeClass($intelligent_status);
$icon = getIntelligentStatusIcon($intelligent_status);
$status_text = '';
switch ($status) {
case 'up':
$status_text = 'Online';
break;
case 'down':
$status_text = 'Offline';
break;
case 'degraded':
$status_text = 'Issues';
break;
case 'partial':
$status_text = 'Partial';
break;
case 'slow':
$status_text = 'Slow';
break;
case 'error':
$status_text = 'Error';
break;
default:
$status_text = 'Unknown';
}
// Add user report indicator if there are reports
$user_indicator = '';
if ($user_reports_count > 0) {
$user_indicator = " ({$user_reports_count} reports) ";
}
return " {$status_text}{$user_indicator} ";
}
/**
* Get 6-hour response time chart data for a website
*/
function getWebsite6HourChartData($pdo, $website_id, $hours = 6) {
try {
$stmt = $pdo->prepare("
SELECT
DATE_FORMAT(checked_at, '%Y-%m-%d %H:00:00') as hour_bucket,
AVG(response_time) as avg_response_time,
COUNT(*) as total_checks,
SUM(CASE WHEN status = 'up' THEN 1 ELSE 0 END) as up_checks,
SUM(CASE WHEN status = 'down' THEN 1 ELSE 0 END) as down_checks
FROM website_checks
WHERE website_id = ?
AND checked_at >= DATE_SUB(NOW(), INTERVAL ? HOUR)
GROUP BY hour_bucket
ORDER BY hour_bucket ASC
");
$stmt->execute([$website_id, $hours]);
return $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (Exception $e) {
return [];
}
}
/**
* DETECT: Status improvement trend by comparing with previous checks
*/
function detectStatusImprovement($pdo, $domain, $current_check, $user_reports, $previous_checks = []) {
$improvement_data = [
'is_improving' => false,
'improvement_type' => '',
'improvement_message' => '',
'previous_status' => '',
'vote_trend' => ''
];
if (empty($previous_checks)) {
return $improvement_data;
}
// Get the most recent previous check
$previous_check = $previous_checks[0];
$current_status = $current_check['status'];
$previous_status = $previous_check['status'];
// Get user reports for previous check (30 minutes before previous check)
$previous_check_time = $previous_check['checked_at'];
$previous_user_reports = getUserReportsAroundTime($pdo, $domain, $previous_check_time, 30);
$previous_reports_count = count($previous_user_reports);
$current_reports_count = count($user_reports);
// Calculate intelligent status for both checks
$current_intelligent = calculateIntelligentStatusForCheck($current_check, $user_reports);
$previous_intelligent = calculateIntelligentStatusForCheck($previous_check, $previous_user_reports);
$current_intelligent_status = $current_intelligent['status'];
$previous_intelligent_status = $previous_intelligent['status'];
// Define status hierarchy (worse to better)
$status_hierarchy = [
'down' => 1,
'error' => 2,
'timeout' => 3,
'degraded' => 4,
'partial' => 5,
'up' => 6
];
$current_level = $status_hierarchy[$current_intelligent_status] ?? 0;
$previous_level = $status_hierarchy[$previous_intelligent_status] ?? 0;
// Check if status is improving
if ($current_level > $previous_level) {
$improvement_data['is_improving'] = true;
$improvement_data['previous_status'] = $previous_intelligent_status;
// Determine improvement type
if ($previous_intelligent_status === 'down' && $current_intelligent_status === 'up') {
$improvement_data['improvement_type'] = 'recovery';
$improvement_data['improvement_message'] = 'Website has recovered from being completely down';
} elseif ($previous_intelligent_status === 'down' && in_array($current_intelligent_status, ['partial', 'degraded'])) {
$improvement_data['improvement_type'] = 'partial_recovery';
$improvement_data['improvement_message'] = 'Website is partially recovering from being down';
} elseif ($previous_intelligent_status === 'degraded' && $current_intelligent_status === 'up') {
$improvement_data['improvement_type'] = 'performance_recovery';
$improvement_data['improvement_message'] = 'Performance issues have been resolved';
} elseif ($previous_intelligent_status === 'partial' && $current_intelligent_status === 'up') {
$improvement_data['improvement_type'] = 'full_recovery';
$improvement_data['improvement_message'] = 'Website has fully recovered from partial issues';
} else {
$improvement_data['improvement_type'] = 'general_improvement';
$improvement_data['improvement_message'] = 'Website status is improving';
}
// Check vote trend (decreasing user reports indicate improvement)
if ($current_reports_count < $previous_reports_count) {
$vote_decrease = $previous_reports_count - $current_reports_count;
$improvement_data['vote_trend'] = "User reports decreased by {$vote_decrease}";
} elseif ($current_reports_count === 0 && $previous_reports_count > 0) {
$improvement_data['vote_trend'] = 'No more user reports of issues';
} elseif ($current_reports_count < $previous_reports_count) {
$improvement_data['vote_trend'] = 'Fewer user reports of issues';
}
}
return $improvement_data;
}
/**
* GET: All votes from all websites with pagination
*/
function getAllVotesWithPagination($pdo, $page = 1, $per_page = 20, $search = '', $vote_type = '', $category_id = '') {
try {
$offset = ($page - 1) * $per_page;
// Build WHERE clause
$where_conditions = [];
$params = [];
if (!empty($search)) {
$where_conditions[] = "(w.domain LIKE ? OR w.display_name LIKE ? OR v.comment LIKE ?)";
$params[] = "%$search%";
$params[] = "%$search%";
$params[] = "%$search%";
}
if (!empty($vote_type)) {
$where_conditions[] = "v.vote_type = ?";
$params[] = $vote_type;
}
if (!empty($category_id)) {
$where_conditions[] = "v.category_id = ?";
$params[] = $category_id;
}
$where_clause = !empty($where_conditions) ? 'WHERE ' . implode(' AND ', $where_conditions) : '';
// Get total count
$count_sql = "SELECT COUNT(*) FROM user_votes v
JOIN websites w ON v.website_id = w.id
LEFT JOIN voting_categories vc ON v.category_id = vc.id
$where_clause";
$count_stmt = $pdo->prepare($count_sql);
$count_stmt->execute($params);
$total_votes = $count_stmt->fetchColumn();
// Get votes with pagination
$sql = "SELECT v.*, w.domain, w.display_name, w.seo_slug, vc.display_name as category_name,
vc.name as category_key, v.location_data
FROM user_votes v
JOIN websites w ON v.website_id = w.id
LEFT JOIN voting_categories vc ON v.category_id = vc.id
$where_clause
ORDER BY v.created_at DESC
LIMIT ? OFFSET ?";
$params[] = $per_page;
$params[] = $offset;
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
$votes = $stmt->fetchAll(PDO::FETCH_ASSOC);
// Calculate pagination info
$total_pages = ceil($total_votes / $per_page);
$has_previous = $page > 1;
$has_next = $page < $total_pages;
return [
'votes' => $votes,
'pagination' => [
'current_page' => $page,
'per_page' => $per_page,
'total_votes' => $total_votes,
'total_pages' => $total_pages,
'has_previous' => $has_previous,
'has_next' => $has_next,
'previous_page' => $page - 1,
'next_page' => $page + 1
]
];
} catch (Exception $e) {
error_log("Error in getAllVotesWithPagination: " . $e->getMessage());
return [
'votes' => [],
'pagination' => [
'current_page' => 1,
'per_page' => $per_page,
'total_votes' => 0,
'total_pages' => 0,
'has_previous' => false,
'has_next' => false,
'previous_page' => 0,
'next_page' => 0
]
];
}
}
/**
* GET: All voting categories for filter dropdown
*/
function getAllVotingCategories($pdo) {
try {
$stmt = $pdo->prepare("SELECT id, display_name, name FROM voting_categories ORDER BY display_name");
$stmt->execute();
return $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (Exception $e) {
error_log("Error in getAllVotingCategories: " . $e->getMessage());
return [];
}
}
/**
* GET: All comments from all websites with pagination
*/
function getAllCommentsWithPagination($pdo, $page = 1, $per_page = 20, $search = '') {
try {
$offset = ($page - 1) * $per_page;
// Build WHERE clause
$where_conditions = [];
$params = [];
if (!empty($search)) {
$where_conditions[] = "(w.domain LIKE ? OR w.display_name LIKE ? OR c.comment LIKE ? OR c.user_name LIKE ?)";
$params[] = "%$search%";
$params[] = "%$search%";
$params[] = "%$search%";
$params[] = "%$search%";
}
$where_clause = !empty($where_conditions) ? 'WHERE ' . implode(' AND ', $where_conditions) : '';
// Get total count
$count_sql = "SELECT COUNT(*) FROM user_comments c
JOIN websites w ON c.website_id = w.id
$where_clause";
$count_stmt = $pdo->prepare($count_sql);
$count_stmt->execute($params);
$total_comments = $count_stmt->fetchColumn();
// Get comments with pagination
$sql = "SELECT c.*, w.domain, w.display_name, w.seo_slug
FROM user_comments c
JOIN websites w ON c.website_id = w.id
$where_clause
ORDER BY c.created_at DESC
LIMIT ? OFFSET ?";
$params[] = $per_page;
$params[] = $offset;
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
$comments = $stmt->fetchAll(PDO::FETCH_ASSOC);
// Calculate pagination info
$total_pages = ceil($total_comments / $per_page);
$has_previous = $page > 1;
$has_next = $page < $total_pages;
return [
'comments' => $comments,
'pagination' => [
'current_page' => $page,
'per_page' => $per_page,
'total_comments' => $total_comments,
'total_pages' => $total_pages,
'has_previous' => $has_previous,
'has_next' => $has_next,
'previous_page' => $page - 1,
'next_page' => $page + 1
]
];
} catch (Exception $e) {
error_log("Error in getAllCommentsWithPagination: " . $e->getMessage());
return [
'comments' => [],
'pagination' => [
'current_page' => 1,
'per_page' => $per_page,
'total_comments' => 0,
'total_pages' => 0,
'has_previous' => false,
'has_next' => false,
'previous_page' => 0,
'next_page' => 0
]
];
}
}
/**
* GET: Total comments count
*/
function getTotalComments($pdo) {
try {
$stmt = $pdo->prepare("SELECT COUNT(*) FROM user_comments");
$stmt->execute();
return $stmt->fetchColumn();
} catch (Exception $e) {
error_log("Error in getTotalComments: " . $e->getMessage());
return 0;
}
}
/**
* Get all categories with pagination
*/
function getAllCategoriesWithPagination($pdo, $page = 1, $per_page = 20) {
try {
$offset = ($page - 1) * $per_page;
// Get categories with website counts
$stmt = $pdo->prepare("
SELECT
c.*,
COUNT(w.id) as website_count,
COUNT(CASE WHEN w.status = 'down' THEN 1 END) as down_websites,
COUNT(CASE WHEN w.status = 'up' THEN 1 END) as up_websites
FROM websites_categories c
LEFT JOIN websites w ON c.slug = w.category AND w.is_active = 1
WHERE c.is_active = 1
GROUP BY c.id
ORDER BY website_count DESC, c.sort_order ASC, c.name ASC
LIMIT ? OFFSET ?
");
$stmt->execute([$per_page, $offset]);
$categories = $stmt->fetchAll(PDO::FETCH_ASSOC);
// Get total count for pagination
$total_stmt = $pdo->query("
SELECT COUNT(*) as total
FROM websites_categories
WHERE is_active = 1
");
$total = $total_stmt->fetch(PDO::FETCH_ASSOC)['total'];
// Calculate pagination info
$total_pages = ceil($total / $per_page);
$pagination = [
'current_page' => $page,
'total_pages' => $total_pages,
'total_items' => $total,
'per_page' => $per_page,
'has_previous' => $page > 1,
'has_next' => $page < $total_pages,
'previous_page' => $page > 1 ? $page - 1 : null,
'next_page' => $page < $total_pages ? $page + 1 : null
];
return [
'categories' => $categories,
'pagination' => $pagination
];
} catch (Exception $e) {
error_log("Error getting categories with pagination: " . $e->getMessage());
return [
'categories' => [],
'pagination' => [
'current_page' => 1,
'total_pages' => 1,
'total_items' => 0,
'per_page' => $per_page,
'has_previous' => false,
'has_next' => false,
'previous_page' => null,
'next_page' => null
]
];
}
}
/**
* Get total number of categories
*/
function getTotalCategories($pdo) {
try {
$stmt = $pdo->query("
SELECT COUNT(*) as total
FROM websites_categories
WHERE is_active = 1
");
return $stmt->fetch(PDO::FETCH_ASSOC)['total'];
} catch (Exception $e) {
error_log("Error getting total categories: " . $e->getMessage());
return 0;
}
}
?>
$current_flag_file = $AVAILABLE_LANGUAGES[$current_lang]['flag_file'];
$html .= ' ';
$html .= $AVAILABLE_LANGUAGES[$current_lang]['name'];
$html .= '';
$html .= '
';
return $html;
}
/**
* Generate URL for different language
*/
function generateLanguageUrl($clean_url, $target_language) {
global $SEO_PATTERNS;
// Ensure SITE_URL is available
if (!defined('SITE_URL')) {
require_once __DIR__ . '/../config/site_config.php';
}
// Get the current request URI
$request_uri = $_SERVER['REQUEST_URI'];
// Check if this is a check URL by looking for domain patterns
$domain = null;
$current_pattern = null;
// First, try to extract domain from the current URL
foreach ($SEO_PATTERNS as $lang => $patterns) {
$pattern = $patterns['check'];
$regex = str_replace('{domain}', '([^\/]+)', $pattern);
// Test against the full request URI
if (preg_match("/\/{$regex}/", $request_uri, $matches)) {
$domain = $matches[1];
$current_pattern = $pattern;
break;
}
}
// If we found a domain, generate the correct URL for target language
if ($domain) {
$target_pattern = $SEO_PATTERNS[$target_language]['check'] ?? $SEO_PATTERNS['en']['check'];
$new_path = str_replace('{domain}', $domain, $target_pattern);
$new_path = $target_language . '/' . $new_path;
$site_url = SITE_URL;
$new_url = $site_url . '/' . $new_path;
return $new_url;
}
// Check if this is a reports page (Romanian)
if (preg_match('/\/ro\/rapoarte$/', $request_uri)) {
$target_pattern = $SEO_PATTERNS[$target_language]['reports'] ?? $SEO_PATTERNS['en']['reports'];
$new_path = $target_language . '/' . $target_pattern;
$site_url = SITE_URL;
$new_url = $site_url . '/' . $new_path;
return $new_url;
}
// Check if this is a reports page (English)
if (preg_match('/\/en\/reports$/', $request_uri)) {
$target_pattern = $SEO_PATTERNS[$target_language]['reports'] ?? $SEO_PATTERNS['en']['reports'];
$new_path = $target_language . '/' . $target_pattern;
$site_url = SITE_URL;
$new_url = $site_url . '/' . $new_path;
return $new_url;
}
// Check if this is a comments page (Romanian)
if (preg_match('/\/ro\/comentarii$/', $request_uri)) {
$target_pattern = $SEO_PATTERNS[$target_language]['comments'] ?? $SEO_PATTERNS['en']['comments'];
$new_path = $target_language . '/' . $target_pattern;
$site_url = SITE_URL;
$new_url = $site_url . '/' . $new_path;
return $new_url;
}
// Check if this is a comments page (English)
if (preg_match('/\/en\/comments$/', $request_uri)) {
$target_pattern = $SEO_PATTERNS[$target_language]['comments'] ?? $SEO_PATTERNS['en']['comments'];
$new_path = $target_language . '/' . $target_pattern;
$site_url = SITE_URL;
$new_url = $site_url . '/' . $new_path;
return $new_url;
}
// Check if this is a categories page (Romanian)
if (preg_match('/\/ro\/categorii$/', $request_uri)) {
$target_pattern = $SEO_PATTERNS[$target_language]['categories'] ?? $SEO_PATTERNS['en']['categories'];
$new_path = $target_language . '/' . $target_pattern;
$site_url = SITE_URL;
$new_url = $site_url . '/' . $new_path;
return $new_url;
}
// Check if this is a categories page (English)
if (preg_match('/\/en\/categories$/', $request_uri)) {
$target_pattern = $SEO_PATTERNS[$target_language]['categories'] ?? $SEO_PATTERNS['en']['categories'];
$new_path = $target_language . '/' . $target_pattern;
$site_url = SITE_URL;
$new_url = $site_url . '/' . $new_path;
return $new_url;
}
// Check if this is a categories pagination URL (Romanian)
if (preg_match('/\/categorii\/pagina\/([0-9]+)/', $request_uri, $matches)) {
$page = $matches[1];
$target_pattern = $SEO_PATTERNS[$target_language]['categories_page'] ?? $SEO_PATTERNS['en']['categories_page'];
$new_path = str_replace('{page}', $page, $target_pattern);
$new_path = $target_language . '/' . $new_path;
$site_url = SITE_URL;
$new_url = $site_url . '/' . $new_path;
return $new_url;
}
// Check if this is a categories pagination URL (English)
if (preg_match('/\/categories\/page\/([0-9]+)/', $request_uri, $matches)) {
$page = $matches[1];
$target_pattern = $SEO_PATTERNS[$target_language]['categories_page'] ?? $SEO_PATTERNS['en']['categories_page'];
$new_path = str_replace('{page}', $page, $target_pattern);
$new_path = $target_language . '/' . $new_path;
$site_url = SITE_URL;
$new_url = $site_url . '/' . $new_path;
return $new_url;
}
// Check if this is a reports pagination URL (Romanian)
if (preg_match('/\/rapoarte\/page\/([0-9]+)/', $request_uri, $matches)) {
$page = $matches[1];
$target_pattern = $SEO_PATTERNS[$target_language]['reports_page'] ?? $SEO_PATTERNS['en']['reports_page'];
$new_path = str_replace('{page}', $page, $target_pattern);
$new_path = $target_language . '/' . $new_path;
$site_url = SITE_URL;
$new_url = $site_url . '/' . $new_path;
return $new_url;
}
// Check if this is a reports pagination URL (English)
if (preg_match('/\/reports\/page\/([0-9]+)/', $request_uri, $matches)) {
$page = $matches[1];
$target_pattern = $SEO_PATTERNS[$target_language]['reports_page'] ?? $SEO_PATTERNS['en']['reports_page'];
$new_path = str_replace('{page}', $page, $target_pattern);
$new_path = $target_language . '/' . $new_path;
$site_url = SITE_URL;
$new_url = $site_url . '/' . $new_path;
return $new_url;
}
// Check if this is a comments pagination URL (Romanian)
if (preg_match('/\/comentarii\/page\/([0-9]+)/', $request_uri, $matches)) {
$page = $matches[1];
$target_pattern = $SEO_PATTERNS[$target_language]['comments_page'] ?? $SEO_PATTERNS['en']['comments_page'];
$new_path = str_replace('{page}', $page, $target_pattern);
$new_path = $target_language . '/' . $new_path;
$site_url = SITE_URL;
$new_url = $site_url . '/' . $new_path;
return $new_url;
}
// Check if this is a comments pagination URL (English)
if (preg_match('/\/comments\/page\/([0-9]+)/', $request_uri, $matches)) {
$page = $matches[1];
$target_pattern = $SEO_PATTERNS[$target_language]['comments_page'] ?? $SEO_PATTERNS['en']['comments_page'];
$new_path = str_replace('{page}', $page, $target_pattern);
$new_path = $target_language . '/' . $new_path;
$site_url = SITE_URL;
$new_url = $site_url . '/' . $new_path;
return $new_url;
}
// Check if this is a category page URL (English)
if (preg_match('/\/category\/([^\/]+)/', $request_uri, $matches)) {
$slug = $matches[1];
$target_pattern = $SEO_PATTERNS[$target_language]['category'] ?? $SEO_PATTERNS['en']['category'];
$new_path = str_replace('{slug}', $slug, $target_pattern);
$new_path = $target_language . '/' . $new_path;
$site_url = SITE_URL;
$new_url = $site_url . '/' . $new_path;
return $new_url;
}
// Check if this is a category page URL (Romanian)
if (preg_match('/\/categorie\/([^\/]+)/', $request_uri, $matches)) {
$slug = $matches[1];
$target_pattern = $SEO_PATTERNS[$target_language]['category'] ?? $SEO_PATTERNS['en']['category'];
$new_path = str_replace('{slug}', $slug, $target_pattern);
$new_path = $target_language . '/' . $new_path;
$site_url = SITE_URL;
$new_url = $site_url . '/' . $new_path;
return $new_url;
}
// Check if this is a category pagination URL (English)
if (preg_match('/\/category\/([^\/]+)\/page\/([0-9]+)/', $request_uri, $matches)) {
$slug = $matches[1];
$page = $matches[2];
$target_pattern = $SEO_PATTERNS[$target_language]['category_page'] ?? $SEO_PATTERNS['en']['category_page'];
$new_path = str_replace('{slug}', $slug, $target_pattern);
$new_path = str_replace('{page}', $page, $new_path);
$new_path = $target_language . '/' . $new_path;
$site_url = SITE_URL;
$new_url = $site_url . '/' . $new_path;
return $new_url;
}
// Check if this is a category pagination URL (Romanian)
if (preg_match('/\/categorie\/([^\/]+)\/pagina\/([0-9]+)/', $request_uri, $matches)) {
$slug = $matches[1];
$page = $matches[2];
$target_pattern = $SEO_PATTERNS[$target_language]['category_page'] ?? $SEO_PATTERNS['en']['category_page'];
$new_path = str_replace('{slug}', $slug, $target_pattern);
$new_path = str_replace('{page}', $page, $new_path);
$new_path = $target_language . '/' . $new_path;
$site_url = SITE_URL;
$new_url = $site_url . '/' . $new_path;
return $new_url;
}
// Fallback: try to extract domain from query parameters
if (isset($_GET['domain'])) {
$domain = $_GET['domain'];
$target_pattern = $SEO_PATTERNS[$target_language]['check'] ?? $SEO_PATTERNS['en']['check'];
$new_path = str_replace('{domain}', $domain, $target_pattern);
$new_path = $target_language . '/' . $new_path;
$site_url = SITE_URL;
$new_url = $site_url . '/' . $new_path;
return $new_url;
}
// Final fallback: just add language prefix to current URL
$parsed_url = parse_url($clean_url);
$path = $parsed_url['path'] ?? '/';
// Clean the path - remove any existing language prefixes
$path = preg_replace('/^\/[a-z]{2}\//', '/', $path);
$path = preg_replace('/^\/[a-z]{2}$/', '/', $path);
if ($target_language !== 'en') {
$path = ltrim($path, '/');
$path = $target_language . '/' . $path;
} else {
$path = ltrim($path, '/');
$path = 'en/' . $path;
}
$site_url = SITE_URL;
$new_url = $site_url . '/' . $path;
// Add query parameters if present
if (isset($parsed_url['query'])) {
$new_url .= '?' . $parsed_url['query'];
}
if (isset($parsed_url['fragment'])) {
$new_url .= '#' . $parsed_url['fragment'];
}
return $new_url;
}
/**
* Generate hreflang URLs for current page
*/
function generateHreflangUrls() {
global $AVAILABLE_LANGUAGES;
// Ensure SITE_URL is available
if (!defined('SITE_URL')) {
require_once __DIR__ . '/../config/site_config.php';
}
$current_lang = getCurrentLanguage();
$clean_url = getCleanCurrentUrl();
$hreflang_urls = [];
// Generate URLs for each available language
foreach ($AVAILABLE_LANGUAGES as $lang_code => $lang_config) {
$url = generateLanguageUrl($clean_url, $lang_code);
$hreflang_urls[$lang_code] = $url;
}
// Add x-default (usually points to English)
$hreflang_urls['x-default'] = $hreflang_urls['en'] ?? $hreflang_urls[$current_lang];
return $hreflang_urls;
}
/**
* Generate hreflang HTML tags
*/
function generateHreflangTags() {
$hreflang_urls = generateHreflangUrls();
$current_lang = getCurrentLanguage();
$html = '';
foreach ($hreflang_urls as $lang => $url) {
// Skip the current language - don't show it as an alternate
if ($lang === $current_lang) {
continue;
}
// For x-default, always use the English version without language prefix
if ($lang === 'x-default') {
// Get the current URL and convert it to English version without language prefix
$clean_url = getCleanCurrentUrl();
$parsed_url = parse_url($clean_url);
$path = $parsed_url['path'] ?? '/';
// Remove language prefix from path
$path = preg_replace('/^\/[a-z]{2}\//', '/', $path);
$path = preg_replace('/^\/[a-z]{2}$/', '/', $path);
// Convert Romanian patterns to English patterns (handle both with and without trailing slash)
$path = preg_replace('/\/categorie(\/|$)/', '/category$1', $path);
$path = preg_replace('/\/categorii(\/|$)/', '/categories$1', $path);
$path = preg_replace('/\/rapoarte(\/|$)/', '/reports$1', $path);
$path = preg_replace('/\/comentarii(\/|$)/', '/comments$1', $path);
$path = preg_replace('/\/pagina(\/|$)/', '/page$1', $path);
// Convert Romanian check page patterns to English
$path = preg_replace('/\/nu-merge-([^\/]+)$/', '/is-$1-down', $path);
$path = preg_replace('/\/este-([^\/]+)$/', '/is-$1-down', $path);
$url = SITE_URL . $path;
// Add query parameters if present
if (isset($parsed_url['query'])) {
$url .= '?' . $parsed_url['query'];
}
if (isset($parsed_url['fragment'])) {
$url .= '#' . $parsed_url['fragment'];
}
}
$html .= ' ' . "\n ";
}
return trim($html);
}
/**
* Initialize language system
*/
function initializeLanguage($forced_language = null) {
// Ensure SITE_URL is available
if (!defined('SITE_URL')) {
require_once __DIR__ . '/../config/site_config.php';
}
// Use forced language if provided, otherwise detect
$detected_lang = $forced_language ?: detectUserLanguage();
// Always set the detected language in session
setUserLanguage($detected_lang);
// Load translations for the detected language
$translations = loadTranslations($detected_lang);
// Debug: Log the language detection process
error_log("Language Detection - Detected: {$detected_lang}, Session: " . ($_SESSION['user_language'] ?? 'not set') . ", URL param: " . ($_GET['lang'] ?? 'not set'));
return [
'code' => $detected_lang,
'config' => getLanguageConfig($detected_lang),
'translations' => $translations
];
}
?>
/**
* Breadcrumb Functions
* Handles dynamic breadcrumb generation with language support
*/
/**
* Detect current page type based on URL
*/
function detectCurrentPageType() {
$request_uri = $_SERVER['REQUEST_URI'];
$path = parse_url($request_uri, PHP_URL_PATH);
// Remove language prefix if present
$path = preg_replace('/^\/[a-z]{2}\//', '/', $path);
$path = preg_replace('/^\/[a-z]{2}$/', '/', $path);
// Remove query string
$path = strtok($path, '?');
// Normalize path
$path = rtrim($path, '/');
if (empty($path)) {
$path = '/';
}
// Detect page type based on URL pattern
if ($path === '/') {
return 'home';
} elseif (preg_match('/^\/is-[^\/]+-down/', $path)) {
return 'check';
} elseif (preg_match('/^\/nu-merge-[^\/]+/', $path)) {
return 'check';
} elseif (preg_match('/^\/category\/([^\/]+)/', $path)) {
return 'category_detail';
} elseif (preg_match('/^\/categorie\/([^\/]+)/', $path)) {
return 'category_detail';
} elseif ($path === '/categories' || $path === '/categorii') {
return 'category';
} elseif ($path === '/reports' || $path === '/rapoarte') {
return 'reports';
} elseif ($path === '/comments' || $path === '/comentarii') {
return 'comments';
} elseif ($path === '/history' || $path === '/istoric') {
return 'history';
} elseif ($path === '/check') {
return 'check_form';
} elseif (preg_match('/^\/search/', $path)) {
return 'search';
}
return 'unknown';
}
/**
* Get breadcrumb structure for page type
*/
function getBreadcrumbStructure($page_type) {
$structures = [
'home' => [
[
'title' => 'breadcrumbs.home',
'url' => '/',
'icon' => 'bi-house',
'current' => true
]
],
'check' => [
[
'title' => 'breadcrumbs.home',
'url' => '/',
'icon' => 'bi-house'
],
[
'title' => 'breadcrumbs.status_check',
'url' => null,
'icon' => 'bi-search',
'current' => true
]
],
'check_form' => [
[
'title' => 'breadcrumbs.home',
'url' => '/',
'icon' => 'bi-house'
],
[
'title' => 'breadcrumbs.status_check',
'url' => '/check',
'icon' => 'bi-search',
'current' => true
]
],
'category' => [
[
'title' => 'breadcrumbs.home',
'url' => '/',
'icon' => 'bi-house'
],
[
'title' => 'breadcrumbs.categories',
'url' => '/categories',
'icon' => 'bi-grid',
'current' => true
]
],
'category_detail' => [
[
'title' => 'breadcrumbs.home',
'url' => '/',
'icon' => 'bi-house'
],
[
'title' => 'breadcrumbs.categories',
'url' => '/categories',
'icon' => 'bi-grid'
],
[
'title' => 'breadcrumbs.category_name',
'url' => null,
'icon' => 'bi-folder',
'current' => true
]
],
'reports' => [
[
'title' => 'breadcrumbs.home',
'url' => '/',
'icon' => 'bi-house'
],
[
'title' => 'breadcrumbs.reports',
'url' => '/reports',
'icon' => 'bi-flag',
'current' => true
]
],
'comments' => [
[
'title' => 'breadcrumbs.home',
'url' => '/',
'icon' => 'bi-house'
],
[
'title' => 'breadcrumbs.comments',
'url' => '/comments',
'icon' => 'bi-chat',
'current' => true
]
],
'history' => [
[
'title' => 'breadcrumbs.home',
'url' => '/',
'icon' => 'bi-house'
],
[
'title' => 'breadcrumbs.history',
'url' => '/history',
'icon' => 'bi-clock',
'current' => true
]
],
'search' => [
[
'title' => 'breadcrumbs.home',
'url' => '/',
'icon' => 'bi-house'
],
[
'title' => 'breadcrumbs.search',
'url' => null,
'icon' => 'bi-search',
'current' => true
]
]
];
return $structures[$page_type] ?? $structures['home'];
}
/**
* Get language-specific URLs for breadcrumbs
*/
function getBreadcrumbUrls($current_lang) {
$urls = [
'en' => [
'home' => '/',
'categories' => '/categories',
'reports' => '/reports',
'comments' => '/comments',
'history' => '/history',
'check' => '/check'
],
'ro' => [
'home' => '/',
'categories' => '/categorii',
'reports' => '/rapoarte',
'comments' => '/comentarii',
'history' => '/istoric',
'check' => '/check'
]
];
return $urls[$current_lang] ?? $urls['en'];
}
/**
* Translate breadcrumb titles
*/
function translateBreadcrumbs($breadcrumb_structure, $translations) {
$translated_breadcrumbs = [];
foreach ($breadcrumb_structure as $breadcrumb) {
$translated_breadcrumb = $breadcrumb;
// Translate title if it's a translation key
if (isset($breadcrumb['title']) && strpos($breadcrumb['title'], 'breadcrumbs.') === 0) {
$key = $breadcrumb['title'];
$translated_breadcrumb['title'] = $translations['breadcrumbs'][substr($key, 12)] ?? $breadcrumb['title'];
}
$translated_breadcrumbs[] = $translated_breadcrumb;
}
return $translated_breadcrumbs;
}
/**
* Apply dynamic data to breadcrumbs
*/
function applyDynamicData($breadcrumbs, $additional_data = []) {
$current_lang = getCurrentLanguage();
$urls = getBreadcrumbUrls($current_lang);
foreach ($breadcrumbs as &$breadcrumb) {
// Apply language-specific URLs
if (isset($breadcrumb['url']) && $breadcrumb['url'] !== null) {
if ($breadcrumb['url'] === '/') {
// Home URL is always /
$breadcrumb['url'] = '/';
} elseif (isset($urls[basename($breadcrumb['url'])])) {
$breadcrumb['url'] = $urls[basename($breadcrumb['url'])];
}
}
// Apply dynamic data
if (isset($additional_data['domain']) && $breadcrumb['title'] === 'breadcrumbs.status_check') {
$breadcrumb['title'] = $additional_data['domain'];
}
if (isset($additional_data['category_name']) && $breadcrumb['title'] === 'breadcrumbs.category_name') {
$breadcrumb['title'] = $additional_data['category_name'];
}
if (isset($additional_data['search_query']) && $breadcrumb['title'] === 'breadcrumbs.search') {
$breadcrumb['title'] = sprintf($translations['breadcrumbs.search_results'] ?? 'Search Results for "%s"', $additional_data['search_query']);
}
}
return $breadcrumbs;
}
/**
* Generate breadcrumbs for current page
*/
function generateBreadcrumbs($page_type = null, $additional_data = []) {
global $translations;
// Detect page type if not provided
if (!$page_type) {
$page_type = detectCurrentPageType();
}
// Get breadcrumb structure
$breadcrumb_structure = getBreadcrumbStructure($page_type);
// Translate breadcrumbs
$breadcrumbs = translateBreadcrumbs($breadcrumb_structure, $translations);
// Apply dynamic data
$breadcrumbs = applyDynamicData($breadcrumbs, $additional_data);
return $breadcrumbs;
}
/**
* Generate JSON-LD structured data for breadcrumbs
*/
function generateBreadcrumbJsonLd($breadcrumbs) {
$itemListElement = [];
$position = 1;
$current_lang = getCurrentLanguage();
// Check if current URL has a language prefix
$request_uri = $_SERVER['REQUEST_URI'];
$has_language_prefix = preg_match('/^\/(en|ro)\//', $request_uri);
foreach ($breadcrumbs as $breadcrumb) {
$item = [
'@type' => 'ListItem',
'position' => $position,
'name' => $breadcrumb['title']
];
if (isset($breadcrumb['url']) && $breadcrumb['url']) {
$url = $breadcrumb['url'];
// Add language prefix if current URL has one or if it's non-English
if (($has_language_prefix || $current_lang !== 'en') && $url !== '/') {
$url = '/' . $current_lang . $url;
}
$item['item'] = SITE_URL . $url;
}
$itemListElement[] = $item;
$position++;
}
return [
'@context' => 'https://schema.org',
'@type' => 'BreadcrumbList',
'itemListElement' => $itemListElement
];
}
/**
* Extract domain from check URL
*/
function extractDomainFromCheckUrl() {
$request_uri = $_SERVER['REQUEST_URI'];
// Try English pattern: /is-{domain}-down
if (preg_match('/\/is-([^\/-]+)-down/', $request_uri, $matches)) {
return $matches[1];
}
// Try Romanian pattern: /nu-merge-{domain}
if (preg_match('/\/nu-merge-([^\/]+)/', $request_uri, $matches)) {
return $matches[1];
}
return null;
}
/**
* Extract category slug from URL
*/
function extractCategorySlugFromUrl() {
$request_uri = $_SERVER['REQUEST_URI'];
// Try English pattern: /category/{slug}
if (preg_match('/\/category\/([^\/]+)/', $request_uri, $matches)) {
return $matches[1];
}
// Try Romanian pattern: /categorie/{slug}
if (preg_match('/\/categorie\/([^\/]+)/', $request_uri, $matches)) {
return $matches[1];
}
return null;
}
?>
orbitz.com este în jos? Verificare Status în Timp Real - ThisIsDown.com
'url' => SITE_URL.'/assets/images/logo.svg',
'width' => 112,
'height' => 112
],
'sameAs' => defined('SOCIAL_LINKS') && isset(SOCIAL_LINKS['facebook'])
? [SOCIAL_LINKS['facebook']]
: [],
'contactPoint' => [
'@type' => 'ContactPoint',
'contactType' => 'general',
'email' => defined('CONTACT_INFO') && isset(CONTACT_INFO['email'])
? CONTACT_INFO['email']
: 'hello@thisisdown.com'
]
]),
JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES
) ?>,
{
"@type": "WebSite",
"@id": "https://thisisdown.com/#website",
"name": "ThisIsDown.com",
"url": "https://thisisdown.com",
"description": "Real-time website status monitoring powered by millions of users and professional analytics",
"publisher": {
"@id": "https://thisisdown.com/#organization"
},
"potentialAction": {
"@type": "SearchAction",
"target": {
"@type": "EntryPoint",
"urlTemplate": "https://thisisdown.com/?q={search_term_string}"
},
"query-input": "required name=search_term_string"
}
},
{
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": [
{
"@type": "ListItem",
"position": 1,
"name": "Home",
"item": "https://thisisdown.com/"
},
{
"@type": "ListItem",
"position": 2,
"name": "Status Check",
"item": "https://thisisdown.com/ro/status-check"
}
]
} ]
}
orbitz.com este în jos?
Verificare status în timp real cu rapoarte comunitare și analize profesionale
orbitz.com
funcționează bine 🎉
Website-ul este online și răspunde normal
Notă: Statusul combină monitorizarea tehnică cu rapoartele de probleme ale utilizatorilor (ferestre de 60 de minute)
Verifică Din Nou
Ultima verificare acum 1 oră
Loading...
Loading recent votes...
21 July 2025
acum 1 oră, Monday
Up - OK
Both technical monitoring and user reports indicate the website is working normally.
0.584s
acum 1 oră, Monday
Up - OK
Both technical monitoring and user reports indicate the website is working normally.
0.770s
acum 2 ore, Monday
Up - OK
Both technical monitoring and user reports indicate the website is working normally.
0.424s
acum 3 ore, Monday
Up - OK
Both technical monitoring and user reports indicate the website is working normally.
0.597s
acum 4 ore, Monday
Up - OK
Both technical monitoring and user reports indicate the website is working normally.
0.523s
acum 5 ore, Monday
Up - OK
Both technical monitoring and user reports indicate the website is working normally.
0.499s
acum 6 ore, Monday
Up - OK
Both technical monitoring and user reports indicate the website is working normally.
0.447s
acum 7 ore, Monday
Up - OK
Both technical monitoring and user reports indicate the website is working normally.
0.518s
acum 8 ore, Monday
Up - OK
Both technical monitoring and user reports indicate the website is working normally.
0.575s
acum 9 ore, Monday
Up - OK
Both technical monitoring and user reports indicate the website is working normally.
0.520s
Loading...
Loading chart data...
Flashscore.com: Real-Time Sports Scores and Live Results
Sports
Livesport Editorial
21 Jul 2025 - 11:30
Like
Share
Comment
Founded in 2006 by Martin Hájek and operated by Livesport Ltd. in the Czech Republic,
Flashscore.com delivers real-time sports results for over 6,000 competitions across 30+ sports.
It supports over 100 countries and 40+ languages, offering live commentary, stats, league standings, and personalized tracking.
The domain flashscore.com
was registered on June 14, 2006 and is managed under CSC Corporate Domains, Inc.
It's hosted on robust infrastructure by Livesport to ensure lightning-fast updates during peak traffic moments like World Cups and Grand Slams.
“Flashscore handles up to 100,000 real-time updates per minute during major events.”
Key Features:
Live Score Updates – Instant results for 30+ sports globally
Match Commentary – Real-time text updates for key matches
Stats & Standings – Team and player performance insights
Favorites Tracker – Follow specific teams and events
Push Notifications – Real-time alerts for goals, sets, or match starts
Multi-Sport Coverage – From football and tennis to darts and snooker
Mobile App – iOS & Android support with full functionality
How to Check if Flashscore.com is Down:
Visit thisisdown.com for uptime stats
Run ping flashscore.com
or traceroute flashscore.com
in your Terminal
Check @FlashscoreCom on Twitter for announcements
Quick Troubleshooting Tips:
Clear browser cache and cookies
Try incognito/private browsing mode
Restart your router or modem
Switch to another internet connection
Use a different browser or device
Fun Facts:
The Flashscore domain was registered in June 2006
Localized in 40+ country domains (e.g., flashscore.co.uk, flashscore.ro)
Served over 1 billion pageviews during UEFA Euro 2024
Flashscore continues to lead the way in fast, reliable sports results delivery. With robust uptime and data accuracy,
it's the ultimate live score companion for sports fans around the world.
Outrages around the world
Outrages
clearStars();
} else {
highlightStars(userRating);
ratingLabel.textContent = ratingLabels[userRating] || 'Select a rating';
}
});
star.addEventListener('click', () => {
userRating = rating;
submitRating(rating);
});
});
function highlightStars(rating) {
stars.forEach((star, index) => {
const starRating = index + 1;
if (starRating <= rating) {
star.classList.add('hover');
star.classList.remove('bi-star');
star.classList.add('bi-star-fill');
} else {
star.classList.remove('hover');
star.classList.remove('bi-star-fill');
star.classList.add('bi-star');
}
});
}
function fillStars(rating) {
stars.forEach((star, index) => {
const starRating = index + 1;
if (starRating <= rating) {
star.classList.add('filled');
star.classList.remove('bi-star');
star.classList.add('bi-star-fill');
} else {
star.classList.remove('filled');
star.classList.remove('bi-star-fill');
star.classList.add('bi-star');
}
});
}
function clearStars() {
stars.forEach(star => {
star.classList.remove('hover', 'active', 'filled');
star.classList.remove('bi-star-fill');
star.classList.add('bi-star');
});
ratingLabel.textContent = 'Selectează o evaluare';
}
function submitRating(rating) {
// Disable stars during submission
stars.forEach(star => {
star.style.pointerEvents = 'none';
});
// Show loading state
ratingLabel.textContent = 'Se trimite...';
// Get reCAPTCHA token first
grecaptcha.ready(function() {
grecaptcha.execute('6LcWF3wrAAAAALb6LaMgPaztq-7ZWUt_ox-wyN9Z', {action: 'rate'}).then(function(token) {
// Submit rating via API
fetch('https://thisisdown.com/api/rate.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
domain: 'orbitz.com',
rating: rating,
recaptcha_token: token
})
})
.then(response => response.json())
.then(data => {
if (data.success) {
// Show success state
starRating.parentElement.classList.add('rating-success');
ratingLabel.textContent = 'Mulțumim pentru evaluare!';
// Show the user's rating by filling the stars
fillStars(rating);
// Animate stars
stars.forEach((star, index) => {
if (index < rating) {
star.classList.add('animate');
setTimeout(() => {
star.classList.remove('animate');
}, 300);
}
});
// Re-enable stars after animation
setTimeout(() => {
stars.forEach(star => {
star.style.pointerEvents = 'auto';
});
}, 1000);
// Reload stats
setTimeout(loadRatingStats, 1000);
} else {
ratingLabel.textContent = data.message || 'Eroare la trimiterea evaluării';
// Re-enable stars
stars.forEach(star => {
star.style.pointerEvents = 'auto';
});
}
})
.catch(error => {
console.error('Error:', error);
ratingLabel.textContent = 'Eroare la trimiterea evaluării';
// Re-enable stars
stars.forEach(star => {
star.style.pointerEvents = 'auto';
});
});
}).catch(error => {
console.error('reCAPTCHA error:', error);
ratingLabel.textContent = 'Eroare la trimiterea evaluării';
// Re-enable stars
stars.forEach(star => {
star.style.pointerEvents = 'auto';
});
});
});
}
function loadUserRating() {
fetch('https://thisisdown.com/api/check_user_rating.php?domain=orbitz.com')
.then(response => response.json())
.then(data => {
if (data.success && data.has_rated) {
userRating = data.rating;
fillStars(data.rating);
ratingLabel.textContent = ratingLabels[data.rating] || 'Your rating';
}
})
.catch(error => {
console.error('Error loading user rating:', error);
});
}
function loadRatingStats() {
fetch('https://thisisdown.com/api/rating_stats.php?domain=orbitz.com')
.then(response => response.json())
.then(data => {
if (data.success) {
averageRating.textContent = data.average_rating || '-';
totalRatings.textContent = data.total_ratings || '0';
}
})
.catch(error => {
console.error('Error loading rating stats:', error);
});
}
// Function to scroll to voting section
function scrollToVoting() {
const votingSection = document.querySelector('.voting-section');
if (votingSection) {
votingSection.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}
}
});