diff --git a/api/generate_script.php b/api/generate_script.php new file mode 100644 index 0000000..505a1c8 --- /dev/null +++ b/api/generate_script.php @@ -0,0 +1,49 @@ + 'Genre and topic are required.']); + exit; +} + +// Prepare the prompt for the AI +$prompt = "You are a creative assistant for social media influencers. Generate a short video script (around 150-200 words) for the genre: '{$genre}'. The script should be about: '{$topic}'. The script should be engaging, concise, and suitable for platforms like TikTok, Instagram Reels, or YouTube Shorts. Include suggestions for visuals or on-screen text where appropriate. Format the output as plain text."; + +try { + $resp = LocalAIApi::createResponse( + [ + 'input' => [ + ['role' => 'system', 'content' => 'You are a helpful scriptwriting assistant for social media creators.'], + ['role' => 'user', 'content' => $prompt], + ], + ], + [ + 'poll_interval' => 5, + 'poll_timeout' => 300 + ] + ); + + if (!empty($resp['success'])) { + $text = LocalAIApi::extractText($resp); + if ($text === '') { + throw new Exception('AI returned an empty response.'); + } + echo json_encode(['script' => nl2br(htmlspecialchars($text))]); + } else { + throw new Exception($resp['error'] ?? 'Unknown AI API error.'); + } + +} catch (Exception $e) { + error_log('AI script generation error: ' . $e->getMessage()); + http_response_code(500); + echo json_encode(['error' => 'Sorry, we couldn\'t generate a script at this time. Please try again later.']); +} + diff --git a/api/update_connection.php b/api/update_connection.php new file mode 100644 index 0000000..84b1a1b --- /dev/null +++ b/api/update_connection.php @@ -0,0 +1,34 @@ + 'Method Not Allowed']); + exit; +} + +$data = json_decode(file_get_contents('php://input'), true); + +if (!isset($data['platform']) || !isset($data['is_connected'])) { + http_response_code(400); + echo json_encode(['error' => 'Missing platform or is_connected parameter']); + exit; +} + +$platform = $data['platform']; +$isConnected = (bool) $data['is_connected']; + +try { + $pdo = db(); + $stmt = $pdo->prepare("UPDATE social_connections SET is_connected = ? WHERE platform = ?"); + $stmt->execute([$isConnected, $platform]); + + echo json_encode(['success' => true]); +} catch (PDOException $e) { + http_response_code(500); + error_log("DB Error: " . $e->getMessage()); + echo json_encode(['error' => 'Database error']); +} +?> \ No newline at end of file diff --git a/assets/css/custom.css b/assets/css/custom.css new file mode 100644 index 0000000..a136f6e --- /dev/null +++ b/assets/css/custom.css @@ -0,0 +1,363 @@ +/* General Body Styles */ +body { + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; + background-color: #FFFFFF; + color: #3A3A3C; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +/* --- Palette & Theme --- */ +:root { + --primary-color: #5E5DF0; + --primary-hover-color: #4948d2; + --secondary-color: #F2F2F7; + --text-dark: #1D1D1F; + --text-light: #6c757d; + --border-radius-sm: 8px; + --border-radius-md: 12px; + --border-radius-lg: 16px; +} + +/* --- Typography --- */ +h1, h2, h3, h4, h5, h6 { + color: var(--text-dark); + font-weight: 700; +} + +.display-4 { + font-weight: 800; +} + +.lead { + color: var(--text-light); + font-size: 1.15rem; + font-weight: 400; +} + +/* --- Header & Navigation --- */ +.navbar { + padding: 1.5rem 0; +} +.navbar-brand { + font-weight: 700; + font-size: 1.5rem; + color: var(--text-dark); +} +.navbar .btn-outline-primary { + border-color: var(--primary-color); + color: var(--primary-color); + border-radius: var(--border-radius-sm); + padding: 0.5rem 1rem; + font-weight: 600; + transition: all 0.2s ease; +} +.navbar .btn-outline-primary:hover { + background-color: var(--primary-color); + color: #fff; +} + +/* --- Hero Section --- */ +.hero { + padding: 6rem 0; + text-align: center; +} + +/* --- Buttons --- */ +.btn-primary { + background-color: var(--primary-color); + border-color: var(--primary-color); + border-radius: var(--border-radius-md); + padding: 1rem 2rem; + font-weight: 600; + font-size: 1.1rem; + transition: background-color 0.2s ease-in-out, transform 0.2s ease; +} +.btn-primary:hover { + background-color: var(--primary-hover-color); + border-color: var(--primary-hover-color); + transform: translateY(-2px); +} +.btn-secondary { + border-radius: var(--border-radius-md); + padding: 0.75rem 1.5rem; +} + + +/* --- Generator Section --- */ +#generator-section { + padding: 4rem 0; + background-color: var(--secondary-color); + border-radius: var(--border-radius-lg); +} +.generator-card { + background-color: #fff; + padding: 2rem; + border-radius: var(--border-radius-lg); + box-shadow: 0 10px 30px rgba(0,0,0,0.07); +} +.form-control, .form-select { + border-radius: var(--border-radius-sm); + padding: 0.75rem 1rem; + border: 1px solid #e5e5e5; +} +.form-control:focus, .form-select:focus { + border-color: var(--primary-color); + box-shadow: 0 0 0 0.25rem rgba(94, 93, 240, 0.2); +} + +/* --- Result Display --- */ +#result-container { + background-color: #f8f9fa; + border: 1px solid #e9ecef; + border-radius: var(--border-radius-md); + padding: 2rem; + margin-top: 2rem; + position: relative; + white-space: pre-wrap; /* Ensures line breaks are respected */ + font-family: 'Menlo', 'Monaco', monospace; + font-size: 0.95rem; + line-height: 1.6; + color: #212529; +} +#result-container.loading { + min-height: 200px; + display: flex; + align-items: center; + justify-content: center; +} +#copy-button { + position: absolute; + top: 1rem; + right: 1rem; + display: none; /* Initially hidden */ +} + +/* --- Features Section --- */ +.features-section { + padding: 6rem 0; +} +.feature-icon { + width: 60px; + height: 60px; + background-color: var(--primary-color); + color: #fff; + border-radius: var(--border-radius-md); + display: inline-flex; + align-items: center; + justify-content: center; + font-size: 1.5rem; + margin-bottom: 1.5rem; +} + +/* --- Footer --- */ +.footer { + padding: 3rem 0; + border-top: 1px solid #e9ecef; + color: var(--text-light); +} + +/* --- Utility --- */ +.mt-6 { + margin-top: 4rem; +} + +/* Dashboard Styles */ +.dashboard-container { + padding-top: 80px; /* Space for fixed header */ +} + +.dashboard-header { + text-align: center; + margin-bottom: 2rem; +} + +.dashboard-header h1 { + font-size: 2.5rem; + margin-bottom: 0.5rem; +} + +.dashboard-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); + gap: 1.5rem; + padding: 1rem; +} + +.dashboard-card { + background: #ffffff; + border-radius: 12px; + padding: 1.5rem; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05); + display: flex; + flex-direction: column; +} + +.dashboard-card h3 { + font-size: 1.5rem; + margin-top: 0; + margin-bottom: 0.5rem; + color: #1d1d1f; +} + +.dashboard-card p { + margin-bottom: 1.5rem; + color: #6e6e73; + flex-grow: 1; +} + +.social-connections { + display: grid; + grid-template-columns: 1fr; + gap: 1rem; +} + +.social-connection { + display: flex; + align-items: center; + justify-content: space-between; +} + +.status-indicator { + font-size: 0.9rem; + font-weight: 500; + padding: 0.3rem 0.6rem; + border-radius: 6px; +} + +.status-indicator.connected { + background-color: #d4edda; + color: #155724; +} + +.status-indicator.not-connected { + background-color: #f8d7da; + color: #721c24; +} + +.social-btn { + border: none; + padding: 0.75rem; + border-radius: 8px; + font-weight: 600; + cursor: pointer; + transition: transform 0.2s, box-shadow 0.2s; + color: #fff; + width: 180px; +} + +.social-btn:hover { + transform: translateY(-2px); + box-shadow: 0 6px 25px rgba(0,0,0,0.1); +} + +.social-btn.youtube { background-color: #FF0000; } +.social-btn.instagram { background: linear-gradient(45deg, #f09433 0%, #e6683c 25%, #dc2743 50%, #cc2366 75%, #bc1888 100%); } +.social-btn.tiktok { background-color: #010101; } +.social-btn.facebook { background-color: #1877F2; } + +.btn-secondary { + background-color: #e7e7f7; + color: #5E5DF0; + border: none; + padding: 0.8rem 1.5rem; + border-radius: 8px; + font-weight: 600; + cursor: pointer; + transition: background-color 0.2s; + align-self: flex-start; +} + +.btn-secondary:hover { + background-color: #dcdcf2; +} + +.tools-list { + list-style: none; + padding: 0; + margin: 0; +} + +.tools-list li { + margin-bottom: 0.75rem; +} + +.tools-list a { + color: #5E5DF0; + text-decoration: none; + font-weight: 500; +} + +.tools-list a:hover { + text-decoration: underline; +} + +/* Report Section */ +#report-section { + margin-top: 2rem; +} + +#report-content .kpi-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: 1rem; + margin-top: 1.5rem; +} + +#report-content .kpi { + background-color: #f8f9fa; + padding: 1rem; + border-radius: 8px; + text-align: center; +} + +#report-content .kpi .kpi-value { + font-size: 2rem; + font-weight: 700; + color: var(--primary-color); +} + +#report-content .kpi .kpi-label { + font-size: 0.9rem; + color: #6c757d; +} + +#report-content h4 { + margin-top: 2rem; + border-bottom: 2px solid #e9ecef; + padding-bottom: 0.5rem; + margin-bottom: 1rem; +} + +#report-content .post-list .post-item { + display: flex; + align-items: center; + margin-bottom: 1rem; +} + +#report-content .post-list .post-thumbnail { + width: 80px; + height: 80px; + object-fit: cover; + border-radius: 8px; + margin-right: 1rem; +} + +#report-content .post-list .post-info .post-caption { + font-weight: 600; +} + +#report-content .post-list .post-info .post-stats { + font-size: 0.9rem; + color: #6c757d; +} + +/* Strategy Section */ +#strategy-section { + margin-top: 2rem; +} + +#strategy-content ul { + list-style-type: disc; + padding-left: 20px; +} diff --git a/assets/js/main.js b/assets/js/main.js new file mode 100644 index 0000000..993e1a7 --- /dev/null +++ b/assets/js/main.js @@ -0,0 +1,223 @@ +document.addEventListener('DOMContentLoaded', function () { + const generatorForm = document.getElementById('generator-form'); + const resultContainer = document.getElementById('result-container'); + const copyButton = document.getElementById('copy-button'); + const generateButton = generatorForm.querySelector('button[type="submit"]'); + const originalButtonText = generateButton.innerHTML; + + if (generatorForm) { + generatorForm.addEventListener('submit', function (e) { + e.preventDefault(); + + const genre = document.getElementById('genre').value; + const topic = document.getElementById('topic').value; + + if (!topic.trim()) { + alert("Please enter a topic."); + return; + } + + // --- UI Changes for Loading State --- + generateButton.disabled = true; + generateButton.innerHTML = ' Generating...'; + + resultContainer.style.display = 'block'; + resultContainer.classList.add('loading'); + resultContainer.innerHTML = '
Loading...
'; + copyButton.style.display = 'none'; + + // --- API Call --- + fetch('/api/generate_script.php', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ genre: genre, topic: topic }), + }) + .then(response => { + if (!response.ok) { + return response.json().then(err => { throw new Error(err.error || 'Network response was not ok'); }); + } + return response.json(); + }) + .then(data => { + if (data.error) { + throw new Error(data.error); + } + // --- Display Success --- + resultContainer.classList.remove('loading'); + resultContainer.innerHTML = `

${data.script}

`; // Use innerHTML to render
tags + copyButton.style.display = 'block'; + }) + .catch(error => { + // --- Display Error --- + resultContainer.classList.remove('loading'); + resultContainer.innerHTML = ``; + }) + .finally(() => { + // --- Reset Button --- + generateButton.disabled = false; + generateButton.innerHTML = originalButtonText; + }); + }); + } + + if (copyButton) { + copyButton.addEventListener('click', function () { + const scriptContent = document.getElementById('script-content').innerText; // Use innerText to get clean text + navigator.clipboard.writeText(scriptContent).then(() => { + const originalCopyText = copyButton.innerHTML; + copyButton.innerHTML = 'Copied!'; + setTimeout(() => { + copyButton.innerHTML = originalCopyText; + }, 2000); + }).catch(err => { + alert('Failed to copy text.'); + }); + }); + } + + // Smooth scroll for hero CTA + const heroCta = document.querySelector('.hero .btn'); + if(heroCta) { + heroCta.addEventListener('click', function(e) { + e.preventDefault(); + document.querySelector(heroCta.getAttribute('href')).scrollIntoView({ + behavior: 'smooth' + }); + }); + } + + // Social Media Connection Logic + const socialConnectionSections = document.querySelectorAll('.social-connection'); + socialConnectionSections.forEach(section => { + const button = section.querySelector('.social-btn'); + const statusIndicator = section.querySelector('.status-indicator'); + + button.addEventListener('click', function() { + const action = button.dataset.action; + const platform = section.dataset.platform; + const isConnected = action === 'connect'; + + fetch('/api/update_connection.php', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ platform: platform, is_connected: isConnected }), + }) + .then(response => response.json()) + .then(data => { + if (data.success) { + if (isConnected) { + button.dataset.action = 'disconnect'; + button.textContent = 'Disconnect ' + platform.charAt(0).toUpperCase() + platform.slice(1); + statusIndicator.textContent = 'Connected'; + statusIndicator.classList.remove('not-connected'); + statusIndicator.classList.add('connected'); + } else { + button.dataset.action = 'connect'; + button.textContent = 'Connect ' + platform.charAt(0).toUpperCase() + platform.slice(1); + statusIndicator.textContent = 'Not Connected'; + statusIndicator.classList.remove('connected'); + statusIndicator.classList.add('not-connected'); + } + } else { + alert('Failed to update connection status.'); + } + }) + .catch(error => { + console.error('Error:', error); + alert('An error occurred while updating connection status.'); + }); + }); + }); + + // Report Generation Logic + const generateReportBtn = document.getElementById('generate-report-btn'); + const reportSection = document.getElementById('report-section'); + const reportContent = document.getElementById('report-content'); + + if (generateReportBtn) { + generateReportBtn.addEventListener('click', function() { + reportSection.style.display = 'block'; + reportContent.innerHTML = '
Loading...
'; + + // Simulate report generation + setTimeout(() => { + const reportHTML = ` +
+
+
1.2M
+
Total Followers
+
+
+
5.8%
+
Engagement Rate
+
+
+
25.2K
+
Avg. Likes per Post
+
+
+

Top Performing Posts

+
+
+ Post thumbnail + +
+
+ Post thumbnail + +
+
+ `; + reportContent.innerHTML = reportHTML; + }, 2000); + }); + } + + // AI Content Strategy Logic + const discoverStrategyBtn = document.getElementById('discover-strategy-btn'); + const strategySection = document.getElementById('strategy-section'); + const strategyContent = document.getElementById('strategy-content'); + + if (discoverStrategyBtn) { + discoverStrategyBtn.addEventListener('click', function() { + strategySection.style.display = 'block'; + strategyContent.innerHTML = '
Loading...
'; + + // --- API Call --- + fetch('/api/generate_script.php', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ genre: 'Content Strategy', topic: 'Give me a content strategy for a tech influencer.' }), + }) + .then(response => { + if (!response.ok) { + return response.json().then(err => { throw new Error(err.error || 'Network response was not ok'); }); + } + return response.json(); + }) + .then(data => { + if (data.error) { + throw new Error(data.error); + } + // --- Display Success --- + strategyContent.innerHTML = `

${data.script}

`; + }) + .catch(error => { + // --- Display Error --- + strategyContent.innerHTML = ``; + }); + }); + } +}); diff --git a/dashboard.php b/dashboard.php new file mode 100644 index 0000000..f29c71c --- /dev/null +++ b/dashboard.php @@ -0,0 +1,118 @@ +prepare("INSERT IGNORE INTO social_connections (platform) VALUES (?)"); + foreach ($platforms as $platform) { + $stmt->execute([$platform]); + } + + // Fetch all connections + $stmt = $pdo->query("SELECT platform, is_connected FROM social_connections"); + while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { + $connections[$row['platform']] = $row['is_connected']; + } +} catch (PDOException $e) { + // Handle DB error gracefully + error_log("DB Error: " . $e->getMessage()); + // Set all connections to false as a fallback + foreach ($platforms as $platform) { + $connections[$platform] = false; + } +} + +?> + + + + + + Influencer Dashboard + + + +
+ + +
+ +
+
+

Your Dashboard

+

Connect accounts, generate reports, and discover new tools.

+
+ +
+
+

Social Media Connections

+

Connect your accounts to unlock powerful analytics and content insights.

+ +
+ +
+

Report Generation

+

Generate in-depth performance reports for your connected accounts.

+ +
+ +
+

AI Content Strategy

+

Get personalized content ideas and strategies from our AI.

+ +
+ +
+

Video Editing Tools

+

Top-rated tools to level up your video production quality.

+ +
+
+ + + + +
+ + + + + \ No newline at end of file diff --git a/db/migrations/001_create_social_connections_table.php b/db/migrations/001_create_social_connections_table.php new file mode 100644 index 0000000..9646e13 --- /dev/null +++ b/db/migrations/001_create_social_connections_table.php @@ -0,0 +1,17 @@ +exec($sql); + echo "Table social_connections created successfully."; +} catch (PDOException $e) { + die("DB ERROR: " . $e->getMessage()); +} +?> \ No newline at end of file diff --git a/index.php b/index.php index 7205f3d..cdc2145 100644 --- a/index.php +++ b/index.php @@ -1,150 +1,143 @@ - - + - - - New Style - - - - - - - - - - - - - - - - - - - + + + + + <?php echo htmlspecialchars(getenv('PROJECT_NAME') ?: 'AI Script Generator'); ?> + + + + + + + + + + + + + + -
-
-

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

-
-
- + + + + +
+ +
+
+

Generate Viral Scripts in Seconds

+

Leverage AI to create engaging scripts for any genre, analyze your social media growth, and discover the perfect time to post.

+ Get Started for Free +
+
+ + +
+
+
+
+
+

AI Script Generator

+
+
+ + +
+
+ + +
+
+ +
+
+ + + +
+
+
+
+
+ + +
+
+
+
+

Your All-in-One Creator Toolkit

+

Everything you need to scale your content production.

+
+
+
+
+
+ +
+

AI Scripting

+

Beat writer's block with endless ideas and ready-to-shoot scripts for any platform.

+
+
+
+ +
+

Growth Analytics

+

Connect your social accounts to get actionable insights and track your performance.

+
+
+
+ +
+

Peak Post Times

+

Maximize your reach by publishing your content when your audience is most active.

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