Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bb9ecddfa5 | ||
|
|
e444f992d1 | ||
|
|
7985ade2ba |
285
assets/css/custom.css
Normal file
285
assets/css/custom.css
Normal file
@ -0,0 +1,285 @@
|
||||
body {
|
||||
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
||||
background-color: #F8F9FA;
|
||||
color: #343A40;
|
||||
}
|
||||
|
||||
.hero {
|
||||
background: linear-gradient(45deg, #007BFF, #0056b3);
|
||||
color: white;
|
||||
padding: 100px 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.hero h1 {
|
||||
font-family: Georgia, 'Times New Roman', Times, serif;
|
||||
font-size: 3.5rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.features {
|
||||
padding: 80px 0;
|
||||
}
|
||||
|
||||
.feature-icon {
|
||||
font-size: 3rem;
|
||||
color: #007BFF;
|
||||
}
|
||||
|
||||
#invite-form-section {
|
||||
padding: 80px 0;
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
|
||||
.toast-container {
|
||||
position: fixed;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
z-index: 1050;
|
||||
}
|
||||
|
||||
/* Dashboard Styles */
|
||||
.dashboard-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 16px 32px;
|
||||
background-color: #FFFFFF;
|
||||
border-bottom: 1px solid #DEE2E6;
|
||||
}
|
||||
|
||||
.dashboard-header .logo a {
|
||||
font-family: Georgia, 'Times New Roman', Times, serif;
|
||||
font-size: 1.5rem;
|
||||
font-weight: bold;
|
||||
color: #007BFF;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.dashboard-nav a {
|
||||
margin-left: 24px;
|
||||
text-decoration: none;
|
||||
color: #6C757D;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.dashboard-nav a.active {
|
||||
color: #007BFF;
|
||||
}
|
||||
|
||||
.logout-btn {
|
||||
border: 1px solid #007BFF;
|
||||
padding: 8px 16px;
|
||||
border-radius: 4px;
|
||||
color: #007BFF;
|
||||
}
|
||||
|
||||
.logout-btn:hover {
|
||||
background-color: #007BFF;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.dashboard-main {
|
||||
padding: 32px;
|
||||
}
|
||||
|
||||
.dashboard-title {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.dashboard-title h1 {
|
||||
font-family: Georgia, 'Times New Roman', Times, serif;
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
|
||||
.date-range-picker {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border: 1px solid #DEE2E6;
|
||||
padding: 8px 12px;
|
||||
border-radius: 4px;
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
|
||||
.date-range-picker input {
|
||||
border: none;
|
||||
outline: none;
|
||||
font-size: 1rem;
|
||||
color: #6C757D;
|
||||
}
|
||||
|
||||
.date-range-picker svg {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.metrics-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
||||
gap: 24px;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.metric-card {
|
||||
background-color: #FFFFFF;
|
||||
padding: 24px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #DEE2E6;
|
||||
}
|
||||
|
||||
.metric-title {
|
||||
font-size: 1rem;
|
||||
color: #6C757D;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.metric-value {
|
||||
font-size: 2rem;
|
||||
font-weight: bold;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.metric-change {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.metric-change.positive {
|
||||
color: #28A745;
|
||||
}
|
||||
|
||||
.metric-change.negative {
|
||||
color: #DC3545;
|
||||
}
|
||||
|
||||
.chart-section {
|
||||
background-color: #FFFFFF;
|
||||
padding: 24px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #DEE2E6;
|
||||
}
|
||||
|
||||
.chart-title {
|
||||
font-size: 1.25rem;
|
||||
font-weight: bold;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.chart {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
align-items: flex-end;
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
.chart-bar-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.chart-bar {
|
||||
width: 70%;
|
||||
background: linear-gradient(to top, #007BFF, #0056b3);
|
||||
border-radius: 4px 4px 0 0;
|
||||
transition: height 0.5s ease-in-out;
|
||||
}
|
||||
|
||||
.chart-label {
|
||||
margin-top: 8px;
|
||||
font-size: 0.875rem;
|
||||
color: #6C757D;
|
||||
}
|
||||
|
||||
.integration-connect {
|
||||
margin-bottom: 32px;
|
||||
padding: 24px;
|
||||
background-color: #FFFFFF;
|
||||
border: 1px solid #DEE2E6;
|
||||
border-radius: 8px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.btn {
|
||||
padding: 12px 24px;
|
||||
font-size: 1rem;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
font-weight: 500;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background-color: #007BFF;
|
||||
color: #FFFFFF;
|
||||
border: 1px solid #007BFF;
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
background-color: #0056b3;
|
||||
border-color: #0056b3;
|
||||
}
|
||||
|
||||
.ga-status-connected {
|
||||
color: #28A745;
|
||||
font-weight: bold;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background-color: #6C757D;
|
||||
color: #FFFFFF;
|
||||
border: 1px solid #6C757D;
|
||||
}
|
||||
|
||||
.ga-property-id-section {
|
||||
background-color: #FFFFFF;
|
||||
padding: 24px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #DEE2E6;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.ga-data-section {
|
||||
background-color: #FFFFFF;
|
||||
padding: 24px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #DEE2E6;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
.ga-data-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
.ga-data-card {
|
||||
background-color: #F8F9FA;
|
||||
padding: 24px;
|
||||
border-radius: 8px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.ga-data-card h3 {
|
||||
font-size: 1rem;
|
||||
color: #6C757D;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.ga-data-value {
|
||||
font-size: 2rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.demo-notice {
|
||||
background-color: #FFF3CD;
|
||||
color: #856404;
|
||||
padding: 16px;
|
||||
border: 1px solid #FFEEBA;
|
||||
border-radius: 4px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
62
assets/js/main.js
Normal file
62
assets/js/main.js
Normal file
@ -0,0 +1,62 @@
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
const inviteForm = document.getElementById('invite-form');
|
||||
if (inviteForm) {
|
||||
inviteForm.addEventListener('submit', function (e) {
|
||||
e.preventDefault();
|
||||
const email = document.getElementById('email').value;
|
||||
const formData = new FormData();
|
||||
formData.append('email', email);
|
||||
|
||||
fetch('request_invite.php', {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
showToast(data.message, data.success ? 'success' : 'error');
|
||||
if (data.success) {
|
||||
inviteForm.reset();
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
showToast('An unexpected error occurred.', 'error');
|
||||
console.error('Error:', error);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function showToast(message, type) {
|
||||
const toastContainer = document.getElementById('toast-container');
|
||||
if (!toastContainer) return;
|
||||
|
||||
const toast = document.createElement('div');
|
||||
toast.className = `toast align-items-center text-white bg-${type === 'success' ? 'success' : 'danger'} border-0 show`;
|
||||
toast.setAttribute('role', 'alert');
|
||||
toast.setAttribute('aria-live', 'assertive');
|
||||
toast.setAttribute('aria-atomic', 'true');
|
||||
|
||||
const toastBody = document.createElement('div');
|
||||
toastBody.className = 'd-flex';
|
||||
toastBody.innerHTML = `<div class="toast-body">${message}</div><button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast" aria-label="Close"></button>`;
|
||||
|
||||
toast.appendChild(toastBody);
|
||||
toastContainer.appendChild(toast);
|
||||
|
||||
const bsToast = new bootstrap.Toast(toast);
|
||||
bsToast.show();
|
||||
|
||||
setTimeout(() => {
|
||||
bsToast.hide();
|
||||
setTimeout(() => toast.remove(), 500);
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
|
||||
anchor.addEventListener('click', function (e) {
|
||||
e.preventDefault();
|
||||
document.querySelector(this.getAttribute('href')).scrollIntoView({
|
||||
behavior: 'smooth'
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
1
config/.gitignore
vendored
Normal file
1
config/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
google.php
|
||||
266
dashboard.php
Normal file
266
dashboard.php
Normal file
@ -0,0 +1,266 @@
|
||||
<?php
|
||||
// dashboard.php
|
||||
|
||||
// Start session to store GA data and manage state
|
||||
session_start();
|
||||
|
||||
// Configuration and token management
|
||||
$google_analytics_connected = file_exists('db/google_tokens.json');
|
||||
$ga_property_id = null;
|
||||
$ga_data = null;
|
||||
$ga_error = null;
|
||||
|
||||
// Handle GA Property ID submission
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['ga_property_id'])) {
|
||||
$property_id = trim($_POST['ga_property_id']);
|
||||
if (!empty($property_id)) {
|
||||
file_put_contents('db/ga_property_id.txt', $property_id);
|
||||
// Clear previous GA data on new ID
|
||||
if (isset($_SESSION['ga_data'])) unset($_SESSION['ga_data']);
|
||||
if (isset($_SESSION['ga_error'])) unset($_SESSION['ga_error']);
|
||||
|
||||
// Set a flag to indicate we need to fetch data
|
||||
$_SESSION['ga_fetch_required'] = true;
|
||||
|
||||
header('Location: dashboard.php');
|
||||
exit();
|
||||
}
|
||||
}
|
||||
|
||||
// Load GA Property ID if it exists
|
||||
if (file_exists('db/ga_property_id.txt')) {
|
||||
$ga_property_id = file_get_contents('db/ga_property_id.txt');
|
||||
}
|
||||
|
||||
// --- GOOGLE ANALYTICS DATA FETCHING ---
|
||||
// Fetch data only if connected, property ID is set, and a fetch is required
|
||||
if ($google_analytics_connected && $ga_property_id && isset($_SESSION['ga_fetch_required'])) {
|
||||
unset($_SESSION['ga_fetch_required']); // Unset the flag to prevent re-fetching on every page load
|
||||
|
||||
require_once 'google-config.php';
|
||||
$tokens_json = file_get_contents('db/google_tokens.json');
|
||||
$tokens = json_decode($tokens_json, true);
|
||||
|
||||
if (!is_array($tokens) || !isset($tokens['access_token']) || !isset($tokens['refresh_token'])) {
|
||||
$_SESSION['ga_error'] = "Google token file is corrupt or invalid. Please disconnect and reconnect.";
|
||||
error_log("Invalid google_tokens.json content: " . $tokens_json);
|
||||
header('Location: dashboard.php');
|
||||
exit();
|
||||
}
|
||||
|
||||
$access_token = $tokens['access_token'];
|
||||
$refresh_token = $tokens['refresh_token'];
|
||||
|
||||
// --- 1. Refresh Access Token ---
|
||||
$token_url = 'https://oauth2.googleapis.com/token';
|
||||
$token_params = [
|
||||
'client_id' => GOOGLE_CLIENT_ID,
|
||||
'client_secret' => GOOGLE_CLIENT_SECRET,
|
||||
'refresh_token' => $refresh_token,
|
||||
'grant_type' => 'refresh_token'
|
||||
];
|
||||
|
||||
$ch = curl_init($token_url);
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($token_params));
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
$response = curl_exec($ch);
|
||||
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
|
||||
if ($http_code == 200) {
|
||||
$new_token_data = json_decode($response, true);
|
||||
if (isset($new_token_data['access_token'])) {
|
||||
$tokens['access_token'] = $new_token_data['access_token'];
|
||||
file_put_contents('db/google_tokens.json', json_encode($tokens));
|
||||
$access_token = $new_token_data['access_token'];
|
||||
|
||||
// --- 2. Fetch Data from Google Analytics Data API ---
|
||||
$analytics_api_url = "https://analyticsdata.googleapis.com/v1beta/properties/{$ga_property_id}:runReport";
|
||||
|
||||
$api_request_body = [
|
||||
'dateRanges' => [['startDate' => '28daysAgo', 'endDate' => 'today']],
|
||||
'metrics' => [
|
||||
['name' => 'sessions'],
|
||||
['name' => 'totalUsers'],
|
||||
['name' => 'screenPageViews'],
|
||||
['name' => 'bounceRate']
|
||||
]
|
||||
];
|
||||
|
||||
$ch_analytics = curl_init($analytics_api_url);
|
||||
curl_setopt($ch_analytics, CURLOPT_HTTPHEADER, [
|
||||
'Authorization: Bearer ' . $access_token,
|
||||
'Content-Type: application/json'
|
||||
]);
|
||||
curl_setopt($ch_analytics, CURLOPT_POST, true);
|
||||
curl_setopt($ch_analytics, CURLOPT_POSTFIELDS, json_encode($api_request_body));
|
||||
curl_setopt($ch_analytics, CURLOPT_RETURNTRANSFER, true);
|
||||
|
||||
$analytics_response = curl_exec($ch_analytics);
|
||||
$analytics_http_code = curl_getinfo($ch_analytics, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch_analytics);
|
||||
|
||||
if ($analytics_http_code == 200) {
|
||||
$report = json_decode($analytics_response, true);
|
||||
if (isset($report['rows'][0]['metricValues'])) {
|
||||
$metricValues = $report['rows'][0]['metricValues'];
|
||||
$_SESSION['ga_data'] = [
|
||||
'sessions' => $metricValues[0]['value'] ?? '0',
|
||||
'users' => $metricValues[1]['value'] ?? '0',
|
||||
'page_views' => $metricValues[2]['value'] ?? '0',
|
||||
'bounce_rate' => isset($metricValues[3]['value']) ? round($metricValues[3]['value'] * 100, 2) . '%' : '0%',
|
||||
];
|
||||
} else {
|
||||
$_SESSION['ga_error'] = "No data returned from Analytics. Check if the property ID is correct and has recent data.";
|
||||
}
|
||||
} else {
|
||||
$error_response = json_decode($analytics_response, true);
|
||||
$error_message = "HTTP {$analytics_http_code}";
|
||||
if (is_array($error_response) && isset($error_response['error']['message'])) {
|
||||
$error_message = $error_response['error']['message'];
|
||||
} else {
|
||||
error_log("Unknown Google API Error. Code: {$analytics_http_code}. Response: " . $analytics_response);
|
||||
}
|
||||
$_SESSION['ga_error'] = "Error fetching Analytics data: " . $error_message;
|
||||
}
|
||||
} else {
|
||||
$_SESSION['ga_error'] = "Failed to refresh token, new access token not found.";
|
||||
}
|
||||
} else {
|
||||
$_SESSION['ga_error'] = "Error refreshing Google token. Please try disconnecting and reconnecting.";
|
||||
}
|
||||
|
||||
// Redirect to clean the URL and prevent re-submission
|
||||
header('Location: dashboard.php');
|
||||
exit();
|
||||
}
|
||||
|
||||
// Load data from session if available
|
||||
if (isset($_SESSION['ga_data'])) {
|
||||
$ga_data = $_SESSION['ga_data'];
|
||||
unset($_SESSION['ga_data']); // Clear after loading
|
||||
}
|
||||
if (isset($_SESSION['ga_error'])) {
|
||||
$ga_error = $_SESSION['ga_error'];
|
||||
unset($_SESSION['ga_error']); // Clear after loading
|
||||
}
|
||||
|
||||
|
||||
// Dummy data for other sections (can be replaced later)
|
||||
$client_name = "Example Client";
|
||||
$chart_data = [
|
||||
"labels" => ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
|
||||
"values" => [5000, 5500, 6200, 7100, 8000, 8500, 9200, 9800, 10500, 11200, 12000, 12345],
|
||||
];
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title><?php echo htmlspecialchars($client_name); ?> - Marketing Dashboard</title>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Georgia:wght@700&family=Helvetica+Neue:wght@400&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="assets/css/custom.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<header class="dashboard-header">
|
||||
<div class="logo">
|
||||
<a href="index.php">AgencyMoguls</a>
|
||||
</div>
|
||||
<nav class="dashboard-nav">
|
||||
<a href="#overview" class="active">Overview</a>
|
||||
<a href="#reports">Reports</a>
|
||||
<a href="#settings">Settings</a>
|
||||
<a href="index.php" class="logout-btn">Logout</a>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<main class="dashboard-main">
|
||||
<div class="integration-connect">
|
||||
<?php if ($google_analytics_connected): ?>
|
||||
<div class="ga-status-connected">Connected to Google Analytics</div>
|
||||
<a href="google_disconnect.php" class="btn btn-secondary">Disconnect</a>
|
||||
<?php else: ?>
|
||||
<a href="google_auth.php" class="btn btn-primary">Connect to Google Analytics</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<div class="dashboard-title">
|
||||
<h1><?php echo htmlspecialchars($client_name); ?>'s Dashboard</h1>
|
||||
<div class="date-range-picker">
|
||||
<input type="text" value="Last 28 Days">
|
||||
<svg width="14" height="8" viewBox="0 0 14 8" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M1 1L7 7L13 1" stroke="#6C757D" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if ($google_analytics_connected): ?>
|
||||
<?php if (!$ga_property_id): ?>
|
||||
<section class="ga-property-id-section">
|
||||
<h2>Enter your Google Analytics Property ID</h2>
|
||||
<p>This is required to fetch data from your Analytics account.</p>
|
||||
<form method="POST" action="dashboard.php">
|
||||
<input type="text" name="ga_property_id" placeholder="Enter your Property ID (e.g., 123456789)" required>
|
||||
<button type="submit" class="btn btn-primary">Save and Fetch Data</button>
|
||||
</form>
|
||||
</section>
|
||||
<?php else: ?>
|
||||
<section class="ga-data-section">
|
||||
<h2>Google Analytics Overview <span class="ga-property-id">(Property ID: <?php echo htmlspecialchars($ga_property_id); ?>)</span></h2>
|
||||
|
||||
<?php if ($ga_error): ?>
|
||||
<div class="ga-error-notice">
|
||||
<strong>Error:</strong> <?php echo htmlspecialchars($ga_error); ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($ga_data): ?>
|
||||
<div class="ga-data-grid">
|
||||
<div class="ga-data-card">
|
||||
<h3>Sessions</h3>
|
||||
<p class="ga-data-value"><?php echo htmlspecialchars($ga_data['sessions']); ?></p>
|
||||
</div>
|
||||
<div class="ga-data-card">
|
||||
<h3>Users</h3>
|
||||
<p class="ga-data-value"><?php echo htmlspecialchars($ga_data['users']); ?></p>
|
||||
</div>
|
||||
<div class="ga-data-card">
|
||||
<h3>Page Views</h3>
|
||||
<p class="ga-data-value"><?php echo htmlspecialchars($ga_data['page_views']); ?></p>
|
||||
</div>
|
||||
<div class="ga-data-card">
|
||||
<h3>Bounce Rate</h3>
|
||||
<p class="ga-data-value"><?php echo htmlspecialchars($ga_data['bounce_rate']); ?></p>
|
||||
</div>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div class="ga-loading-notice">
|
||||
Attempting to fetch live data from Google Analytics... If this message persists, please check your Property ID or try reconnecting.
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</section>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<section class="chart-section">
|
||||
<div class="chart-container">
|
||||
<h2 class="chart-title">Sessions Over Time (Sample)</h2>
|
||||
<div class="chart">
|
||||
<?php
|
||||
$max_value = max($chart_data['values']);
|
||||
foreach ($chart_data['values'] as $index => $value):
|
||||
$height_percentage = ($value / $max_value) * 100;
|
||||
?>
|
||||
<div class="chart-bar-wrapper">
|
||||
<div class="chart-bar" style="height: <?php echo $height_percentage; ?>%;"></div>
|
||||
<span class="chart-label"><?php echo $chart_data['labels'][$index]; ?></span>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</main>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
1
db/ga_property_id.txt
Normal file
1
db/ga_property_id.txt
Normal file
@ -0,0 +1 @@
|
||||
G-XE06RVWK6S
|
||||
1
db/google_tokens.json
Normal file
1
db/google_tokens.json
Normal file
@ -0,0 +1 @@
|
||||
{"access_token":"ya29.a0ATi6K2uk0Gb_RDk8IRqUCYlK4xhbAoOR6sM6T9fudqgQtVDahmlHDshpy5sKcqUtpmhCT5HBPWrDfaSb1GALm5iSkbRagO0Sq_drZfhFYA4G22OwS1J418mYgBsI0BS4_SdYO8Biwy-U2nhATQMqkBqxUAnETW9Vp_7qgmgbPYIp01MCqXJ9b_5CJm-673rL4GT2YlcaCgYKAXQSARYSFQHGX2MivzBSL3ClF2zW9KP5SQnJ8g0206","expires_in":3599,"refresh_token":"1\/\/04GWLH1ZGkD_lCgYIARAAGAQSNwF-L9Ir2NCtmqTH8Cxr8O5uXkkX4TvTzC2dXXFTrS7amm1DVPKtlfupCJyvopZHDy2wY5blJoI","scope":"https:\/\/www.googleapis.com\/auth\/analytics.readonly","token_type":"Bearer"}
|
||||
1
db/perm_test.txt
Normal file
1
db/perm_test.txt
Normal file
@ -0,0 +1 @@
|
||||
test
|
||||
5
google-config.php
Normal file
5
google-config.php
Normal file
@ -0,0 +1,5 @@
|
||||
<?php
|
||||
// config/google.php
|
||||
define('GOOGLE_CLIENT_ID', '711888153406-074gd97v22f8nqq9dr3cjlo761pts4s9.apps.googleusercontent.com');
|
||||
define('GOOGLE_CLIENT_SECRET', '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');
|
||||
define('GOOGLE_REDIRECT_URI', 'https://'. $_SERVER['HTTP_HOST'] . '/google_callback.php');
|
||||
17
google_auth.php
Normal file
17
google_auth.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
session_start();
|
||||
unset($_SESSION['google_access_token']);
|
||||
|
||||
require_once 'google-config.php';
|
||||
|
||||
$auth_url = 'https://accounts.google.com/o/oauth2/v2/auth?' . http_build_query([
|
||||
'client_id' => GOOGLE_CLIENT_ID,
|
||||
'redirect_uri' => GOOGLE_REDIRECT_URI,
|
||||
'response_type' => 'code',
|
||||
'scope' => 'https://www.googleapis.com/auth/analytics.readonly',
|
||||
'access_type' => 'offline',
|
||||
'prompt' => 'consent'
|
||||
]);
|
||||
|
||||
header('Location: ' . $auth_url);
|
||||
exit();
|
||||
81
google_callback.php
Normal file
81
google_callback.php
Normal file
@ -0,0 +1,81 @@
|
||||
<?php
|
||||
error_reporting(E_ALL);
|
||||
ini_set('display_errors', 1);
|
||||
file_put_contents('logs/debug.log', "Callback script started\n", FILE_APPEND);
|
||||
|
||||
session_start();
|
||||
|
||||
|
||||
require_once 'google-config.php';
|
||||
|
||||
function log_error($message) {
|
||||
$log_file = 'logs/google_auth.log';
|
||||
$timestamp = date('Y-m-d H:i:s');
|
||||
// Ensure the log directory exists
|
||||
if (!is_dir(dirname($log_file))) {
|
||||
mkdir(dirname($log_file), 0775, true);
|
||||
}
|
||||
file_put_contents($log_file, "[$timestamp] $message\n", FILE_APPEND);
|
||||
}
|
||||
|
||||
if (isset($_GET['code'])) {
|
||||
$code = $_GET['code'];
|
||||
|
||||
$token_url = 'https://oauth2.googleapis.com/token';
|
||||
$token_params = [
|
||||
'code' => $code,
|
||||
'client_id' => GOOGLE_CLIENT_ID,
|
||||
'client_secret' => GOOGLE_CLIENT_SECRET,
|
||||
'redirect_uri' => GOOGLE_REDIRECT_URI,
|
||||
'grant_type' => 'authorization_code'
|
||||
];
|
||||
|
||||
$ch = curl_init($token_url);
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($token_params));
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
|
||||
$response = curl_exec($ch);
|
||||
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
$curl_error = curl_error($ch);
|
||||
curl_close($ch);
|
||||
|
||||
if ($curl_error) {
|
||||
log_error("cURL Error: " . $curl_error);
|
||||
echo "An error occurred. Please try again later. (Code: 1)";
|
||||
exit();
|
||||
}
|
||||
|
||||
if ($http_code == 200) {
|
||||
$token_data = json_decode($response, true);
|
||||
|
||||
if (json_last_error() !== JSON_ERROR_NONE) {
|
||||
log_error("Failed to decode JSON response: " . $response);
|
||||
echo "An error occurred. Please try again later. (Code: 2)";
|
||||
exit();
|
||||
}
|
||||
|
||||
// Ensure the db directory exists
|
||||
if (!is_dir(dirname('db/google_tokens.json'))) {
|
||||
mkdir(dirname('db/google_tokens.json'), 0775, true);
|
||||
}
|
||||
|
||||
if (file_put_contents('db/google_tokens.json', json_encode($token_data)) === false) {
|
||||
log_error("Failed to write tokens to db/google_tokens.json");
|
||||
echo "An error occurred. Please try again later. (Code: 3)";
|
||||
exit();
|
||||
}
|
||||
|
||||
$_SESSION['google_access_token'] = $token_data['access_token'];
|
||||
|
||||
header('Location: dashboard.php');
|
||||
exit();
|
||||
|
||||
} else {
|
||||
log_error("Error fetching access token. HTTP Code: " . $http_code . ", Response: " . $response);
|
||||
echo "An error occurred while trying to connect to Google. Please check your credentials in setup.php and try again.";
|
||||
}
|
||||
} else {
|
||||
log_error("Authorization code not found in callback.");
|
||||
echo "Authorization code not found.";
|
||||
}
|
||||
7
google_disconnect.php
Normal file
7
google_disconnect.php
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
if (file_exists('db/google_tokens.json')) {
|
||||
unlink('db/google_tokens.json');
|
||||
}
|
||||
|
||||
header('Location: dashboard.php');
|
||||
exit();
|
||||
237
index.php
237
index.php
@ -1,150 +1,97 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
@ini_set('display_errors', '1');
|
||||
@error_reporting(E_ALL);
|
||||
@date_default_timezone_set('UTC');
|
||||
|
||||
$phpVersion = PHP_VERSION;
|
||||
$now = date('Y-m-d H:i:s');
|
||||
?>
|
||||
<!doctype html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>New Style</title>
|
||||
<?php
|
||||
// Read project preview data from environment
|
||||
$projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? '';
|
||||
$projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
|
||||
?>
|
||||
<?php if ($projectDescription): ?>
|
||||
<!-- Meta description -->
|
||||
<meta name="description" content='<?= htmlspecialchars($projectDescription) ?>' />
|
||||
<!-- Open Graph meta tags -->
|
||||
<meta property="og:description" content="<?= htmlspecialchars($projectDescription) ?>" />
|
||||
<!-- Twitter meta tags -->
|
||||
<meta property="twitter:description" content="<?= htmlspecialchars($projectDescription) ?>" />
|
||||
<?php endif; ?>
|
||||
<?php if ($projectImageUrl): ?>
|
||||
<!-- Open Graph image -->
|
||||
<meta property="og:image" content="<?= htmlspecialchars($projectImageUrl) ?>" />
|
||||
<!-- Twitter image -->
|
||||
<meta property="twitter:image" content="<?= htmlspecialchars($projectImageUrl) ?>" />
|
||||
<?php endif; ?>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
:root {
|
||||
--bg-color-start: #6a11cb;
|
||||
--bg-color-end: #2575fc;
|
||||
--text-color: #ffffff;
|
||||
--card-bg-color: rgba(255, 255, 255, 0.01);
|
||||
--card-border-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: 'Inter', sans-serif;
|
||||
background: linear-gradient(45deg, var(--bg-color-start), var(--bg-color-end));
|
||||
color: var(--text-color);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-height: 100vh;
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
body::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100"><path d="M-10 10L110 10M10 -10L10 110" stroke-width="1" stroke="rgba(255,255,255,0.05)"/></svg>');
|
||||
animation: bg-pan 20s linear infinite;
|
||||
z-index: -1;
|
||||
}
|
||||
@keyframes bg-pan {
|
||||
0% { background-position: 0% 0%; }
|
||||
100% { background-position: 100% 100%; }
|
||||
}
|
||||
main {
|
||||
padding: 2rem;
|
||||
}
|
||||
.card {
|
||||
background: var(--card-bg-color);
|
||||
border: 1px solid var(--card-border-color);
|
||||
border-radius: 16px;
|
||||
padding: 2rem;
|
||||
backdrop-filter: blur(20px);
|
||||
-webkit-backdrop-filter: blur(20px);
|
||||
box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
.loader {
|
||||
margin: 1.25rem auto 1.25rem;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
border: 3px solid rgba(255, 255, 255, 0.25);
|
||||
border-top-color: #fff;
|
||||
border-radius: 50%;
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
@keyframes spin {
|
||||
from { transform: rotate(0deg); }
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
.hint {
|
||||
opacity: 0.9;
|
||||
}
|
||||
.sr-only {
|
||||
position: absolute;
|
||||
width: 1px; height: 1px;
|
||||
padding: 0; margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
white-space: nowrap; border: 0;
|
||||
}
|
||||
h1 {
|
||||
font-size: 3rem;
|
||||
font-weight: 700;
|
||||
margin: 0 0 1rem;
|
||||
letter-spacing: -1px;
|
||||
}
|
||||
p {
|
||||
margin: 0.5rem 0;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
code {
|
||||
background: rgba(0,0,0,0.2);
|
||||
padding: 2px 6px;
|
||||
border-radius: 4px;
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
||||
}
|
||||
footer {
|
||||
position: absolute;
|
||||
bottom: 1rem;
|
||||
font-size: 0.8rem;
|
||||
opacity: 0.7;
|
||||
}
|
||||
</style>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Agency Marketing Dashboard</title>
|
||||
<meta name="description" content="Built with Flatlogic Generator">
|
||||
<meta name="keywords" content="marketing reporting, client dashboard, seo reporting, ppc analytics, social media performance, automated reports, agency tools, keyword tracking, backlink monitoring, site audit, Built with Flatlogic Generator">
|
||||
<meta property="og:title" content="Agency Marketing Dashboard">
|
||||
<meta property="og:description" content="Built with Flatlogic Generator">
|
||||
<meta property="og:image" content="">
|
||||
<meta name="twitter:card" content="summary_large_image">
|
||||
<meta name="twitter:image" content="">
|
||||
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
||||
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<div class="card">
|
||||
<h1>Analyzing your requirements and generating your website…</h1>
|
||||
<div class="loader" role="status" aria-live="polite" aria-label="Applying initial changes">
|
||||
<span class="sr-only">Loading…</span>
|
||||
</div>
|
||||
<p class="hint"><?= ($_SERVER['HTTP_HOST'] ?? '') === 'appwizzy.com' ? 'AppWizzy' : 'Flatlogic' ?> AI is collecting your requirements and applying the first changes.</p>
|
||||
<p class="hint">This page will update automatically as the plan is implemented.</p>
|
||||
<p>Runtime: PHP <code><?= htmlspecialchars($phpVersion) ?></code> — UTC <code><?= htmlspecialchars($now) ?></code></p>
|
||||
</div>
|
||||
</main>
|
||||
<footer>
|
||||
Page updated: <?= htmlspecialchars($now) ?> (UTC)
|
||||
</footer>
|
||||
|
||||
<header class="navbar navbar-expand-lg navbar-light bg-white shadow-sm">
|
||||
<div class="container">
|
||||
<a class="navbar-brand" href="#">AgencyAnalytics</a>
|
||||
<div>
|
||||
<a href="dashboard.php" class="btn btn-secondary">View Dashboard</a>
|
||||
<a href="#invite-form-section" class="btn btn-primary">Request Invite</a>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<section class="hero">
|
||||
<div class="container">
|
||||
<h1>Automated Client Reporting for Marketing Agencies</h1>
|
||||
<p class="lead">Save time, track performance, and create custom, branded reports with ease.</p>
|
||||
<a href="#invite-form-section" class="btn btn-light btn-lg mt-3">Get Started</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="features text-center">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-4 mb-4">
|
||||
<i data-feather="bar-chart-2" class="feature-icon mb-3"></i>
|
||||
<h3>All-in-One Dashboards</h3>
|
||||
<p>Connect all your marketing channels and see your data in one place.</p>
|
||||
</div>
|
||||
<div class="col-md-4 mb-4">
|
||||
<i data-feather="file-text" class="feature-icon mb-3"></i>
|
||||
<h3>Automated Reports</h3>
|
||||
<p>Create beautiful, custom reports and schedule them to send automatically.</p>
|
||||
</div>
|
||||
<div class="col-md-4 mb-4">
|
||||
<i data-feather="briefcase" class="feature-icon mb-3"></i>
|
||||
<h3>Branded for Your Agency</h3>
|
||||
<p>White-label the platform with your own logo and branding.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="invite-form-section">
|
||||
<div class="container text-center">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6">
|
||||
<h2>Request an Invitation</h2>
|
||||
<p>Get exclusive access to the platform.</p>
|
||||
<form id="invite-form">
|
||||
<div class="input-group mb-3">
|
||||
<input type="email" id="email" class="form-control form-control-lg" placeholder="Enter your email" required>
|
||||
<button class="btn btn-primary" type="submit">Request Invite</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<footer class="text-center py-4">
|
||||
<div class="container">
|
||||
<p class="text-muted">© <?php echo date("Y"); ?> AgencyAnalytics. All rights reserved.</p>
|
||||
<p class="text-muted small">
|
||||
<a href="privacy.php">Privacy Policy</a> · <a href="terms.php">Terms of Service</a>
|
||||
</p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<div id="toast-container" class="toast-container"></div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="assets/js/main.js?v=<?php echo time(); ?>"></script>
|
||||
<script>
|
||||
feather.replace();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
2
logs/debug.log
Normal file
2
logs/debug.log
Normal file
@ -0,0 +1,2 @@
|
||||
Callback script started
|
||||
Callback script started
|
||||
4
logs/google_auth.log
Normal file
4
logs/google_auth.log
Normal file
@ -0,0 +1,4 @@
|
||||
[2025-11-18 19:43:05] Error fetching access token. HTTP Code: 400, Response: {
|
||||
"error": "invalid_grant",
|
||||
"error_description": "Bad Request"
|
||||
}
|
||||
1
logs/perm_test.txt
Normal file
1
logs/perm_test.txt
Normal file
@ -0,0 +1 @@
|
||||
test
|
||||
43
privacy.php
Normal file
43
privacy.php
Normal file
@ -0,0 +1,43 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Privacy Policy</title>
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container mt-5">
|
||||
<h1>Privacy Policy</h1>
|
||||
<p><em>Last updated: <?php echo date("F j, Y"); ?></em></p>
|
||||
|
||||
<div class="alert alert-warning">
|
||||
<strong>Disclaimer:</strong> This is a template and not legal advice. You should replace this content with your own privacy policy.
|
||||
</div>
|
||||
|
||||
<h2>Introduction</h2>
|
||||
<p>Welcome to our application. We are committed to protecting your privacy. This Privacy Policy explains how we collect, use, disclose, and safeguard your information when you use our application.</p>
|
||||
|
||||
<h2>Information We Collect</h2>
|
||||
<p>We may collect information about you in a variety of ways. The information we may collect via the Application includes:</p>
|
||||
<ul>
|
||||
<li><strong>Personal Data:</strong> Personally identifiable information, such as your name, shipping address, email address, and telephone number, and demographic information, such as your age, gender, hometown, and interests, that you voluntarily give to us when you register with the Application.</li>
|
||||
<li><strong>Data from Google Analytics:</strong> We connect to your Google Analytics account to retrieve and display your website traffic data. We only request read-only access and do not store your data permanently on our servers.</li>
|
||||
</ul>
|
||||
|
||||
<h2>Use of Your Information</h2>
|
||||
<p>Having accurate information about you permits us to provide you with a smooth, efficient, and customized experience. Specifically, we may use information collected about you via the Application to:</p>
|
||||
<ul>
|
||||
<li>Create and manage your account.</li>
|
||||
<li>Display your Google Analytics data on a personal dashboard.</li>
|
||||
<li>Email you regarding your account or order.</li>
|
||||
</ul>
|
||||
|
||||
<h2>Contact Us</h2>
|
||||
<p>If you have questions or comments about this Privacy Policy, please contact us.</p>
|
||||
|
||||
<hr>
|
||||
<a href="index.php">Back to Home</a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
30
request_invite.php
Normal file
30
request_invite.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/mail/MailService.php';
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
echo json_encode(['success' => false, 'message' => 'Invalid request method.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
|
||||
|
||||
if (!$email) {
|
||||
echo json_encode(['success' => false, 'message' => 'Please provide a valid email address.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$to = getenv('MAIL_TO') ?: 'admin@example.com'; // Fallback email
|
||||
$subject = 'New Invite Request';
|
||||
$body = "A new invite request has been received from: {$email}";
|
||||
$name = 'Invite Request Form';
|
||||
|
||||
$result = MailService::sendContactMessage($name, $email, $body, $to, $subject);
|
||||
|
||||
if ($result['success']) {
|
||||
echo json_encode(['success' => true, 'message' => 'Thank you! Your invite request has been received.']);
|
||||
} else {
|
||||
error_log('MailService Error: ' . $result['error']);
|
||||
echo json_encode(['success' => false, 'message' => 'Sorry, there was an error sending your request. Please try again later.']);
|
||||
}
|
||||
101
setup.php
Normal file
101
setup.php
Normal file
@ -0,0 +1,101 @@
|
||||
<?php
|
||||
$config_file = 'google-config.php';
|
||||
$error_message = '';
|
||||
$success_message = '';
|
||||
|
||||
// Check if the form has been submitted
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
// Get the submitted values
|
||||
$client_id = $_POST['client_id'] ?? '';
|
||||
$client_secret = $_POST['client_secret'] ?? '';
|
||||
|
||||
if (!empty($client_id) && !empty($client_secret)) {
|
||||
// Read the existing config file
|
||||
$config_content = file_get_contents($config_file);
|
||||
|
||||
if ($config_content !== false) {
|
||||
// Replace the placeholder values
|
||||
$config_content = preg_replace("/define\('GOOGLE_CLIENT_ID', '.*'\);/", "define('GOOGLE_CLIENT_ID', '$client_id');", $config_content);
|
||||
$config_content = preg_replace("/define\('GOOGLE_CLIENT_SECRET', '.*'\);/", "define('GOOGLE_CLIENT_SECRET', '$client_secret');", $config_content);
|
||||
|
||||
// Write the updated content back to the file
|
||||
if (file_put_contents($config_file, $config_content) !== false) {
|
||||
$success_message = 'Your Google API credentials have been saved successfully!';
|
||||
} else {
|
||||
$error_message = 'Error: Unable to write to the configuration file. Please check file permissions.';
|
||||
}
|
||||
} else {
|
||||
$error_message = 'Error: Unable to read the configuration file.';
|
||||
}
|
||||
} else {
|
||||
$error_message = 'Please provide both Client ID and Client Secret.';
|
||||
}
|
||||
}
|
||||
|
||||
// Read the current values to display them (or placeholders)
|
||||
$current_client_id = '';
|
||||
$current_client_secret = '';
|
||||
if (file_exists($config_file)) {
|
||||
$config_content = file_get_contents($config_file);
|
||||
if (preg_match("/define\('GOOGLE_CLIENT_ID', '(.*)'\);/", $config_content, $matches)) {
|
||||
$current_client_id = $matches[1];
|
||||
}
|
||||
if (preg_match("/define\('GOOGLE_CLIENT_SECRET', '(.*)'\);/", $config_content, $matches)) {
|
||||
$current_client_secret = $matches[1];
|
||||
}
|
||||
}
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Google API Setup</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<style>
|
||||
body {
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
.setup-container {
|
||||
max-width: 600px;
|
||||
margin: 50px auto;
|
||||
padding: 30px;
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="setup-container">
|
||||
<h2 class="text-center mb-4">Google API Setup</h2>
|
||||
|
||||
<?php if ($error_message): ?>
|
||||
<div class="alert alert-danger"><?php echo $error_message; ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($success_message): ?>
|
||||
<div class="alert alert-success"><?php echo $success_message; ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<form method="POST" action="setup.php">
|
||||
<div class="mb-3">
|
||||
<label for="client_id" class="form-label">Google Client ID</label>
|
||||
<input type="text" class="form-control" id="client_id" name="client_id" value="<?php echo htmlspecialchars($current_client_id); ?>" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="client_secret" class="form-label">Google Client Secret</label>
|
||||
<input type="password" class="form-control" id="client_secret" name="client_secret" value="<?php echo htmlspecialchars($current_client_secret); ?>" required>
|
||||
</div>
|
||||
<div class="d-grid">
|
||||
<button type="submit" class="btn btn-primary">Save Credentials</button>
|
||||
</div>
|
||||
</form>
|
||||
<div class="text-center mt-3">
|
||||
<a href="index.php">Back to Home</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
46
terms.php
Normal file
46
terms.php
Normal file
@ -0,0 +1,46 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Terms of Service</title>
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container mt-5">
|
||||
<h1>Terms of Service</h1>
|
||||
<p><em>Last updated: <?php echo date("F j, Y"); ?></em></p>
|
||||
|
||||
<div class="alert alert-warning">
|
||||
<strong>Disclaimer:</strong> This is a template and not legal advice. You should replace this content with your own terms of service.
|
||||
</div>
|
||||
|
||||
<h2>1. Agreement to Terms</h2>
|
||||
<p>By using our application, you agree to be bound by these Terms of Service. If you do not agree to these Terms, do not use the application.</p>
|
||||
|
||||
<h2>2. License to Use</h2>
|
||||
<p>We grant you a limited, non-exclusive, non-transferable, revocable license to use the application for your personal, non-commercial purposes, subject to these Terms.</p>
|
||||
|
||||
<h2>3. User Accounts</h2>
|
||||
<p>When you create an account with us, you must provide us with information that is accurate, complete, and current at all times. Failure to do so constitutes a breach of the Terms, which may result in immediate termination of your account on our Service.</p>
|
||||
|
||||
<h2>4. Intellectual Property</h2>
|
||||
<p>The Service and its original content, features, and functionality are and will remain the exclusive property of the application owner and its licensors.</p>
|
||||
|
||||
<h2>5. Termination</h2>
|
||||
<p>We may terminate or suspend your account immediately, without prior notice or liability, for any reason whatsoever, including without limitation if you breach the Terms.</p>
|
||||
|
||||
<h2>6. Governing Law</h2>
|
||||
<p>These Terms shall be governed and construed in accordance with the laws of the jurisdiction in which the application owner is based, without regard to its conflict of law provisions.</p>
|
||||
|
||||
<h2>7. Changes to Terms</h2>
|
||||
<p>We reserve the right, at our sole discretion, to modify or replace these Terms at any time. We will provide at least 30 days' notice prior to any new terms taking effect.</p>
|
||||
|
||||
<h2>Contact Us</h2>
|
||||
<p>If you have any questions about these Terms, please contact us.</p>
|
||||
|
||||
<hr>
|
||||
<a href="index.php">Back to Home</a>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
x
Reference in New Issue
Block a user