feat: Initial implementation of Marketing Assistant AI for Adriana James
- Set up FastAPI backend with modular structure: - main.py for API routing - copywriter.py for AI-powered content generation using Cohere - embeddings.py for generating and reranking content embeddings - vector_store.py for FAISS-based similarity search - brand_style.py for managing brand tone, taboo words, and preferred terms - config.py for managing environment and application settings - Configured RESTful API endpoints: /generate-copy, /brand-style, /training-data, /improve-content, /analyze-content - Created frontend with vanilla HTML, CSS, and JS (index.html, styles.css, app.js) - Integrated brand style management for tone, voice, taboo words, and terminology - Implemented vector search for referencing similar historical content - Enabled training data input to improve future AI output - Added environment variable support for API keys and model configs - Structured data storage with local JSON and DB files - Added developer documentation, API reference, and project setup instructions This commit provides the foundation for a full-stack, AI-driven content creation platform that ensures brand consistency, speeds up marketing workflows, and supports iterative improvement over time.
This commit is contained in:
+513
@@ -0,0 +1,513 @@
|
||||
// DOM Elements
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Navigation
|
||||
const menuItems = document.querySelectorAll('.menu li');
|
||||
const pages = document.querySelectorAll('.page');
|
||||
|
||||
// Generate Content Page
|
||||
const generateBtn = document.getElementById('generate-btn');
|
||||
const promptInput = document.getElementById('prompt');
|
||||
const contentTypeSelect = document.getElementById('content-type');
|
||||
const toneSelect = document.getElementById('tone');
|
||||
const lengthSelect = document.getElementById('length');
|
||||
const includeCTACheckbox = document.getElementById('include-cta');
|
||||
const referenceSimilarCheckbox = document.getElementById('reference-similar');
|
||||
const resultContainer = document.getElementById('result-container');
|
||||
const resultContent = document.getElementById('result-content');
|
||||
const loadingIndicator = document.getElementById('loading-indicator');
|
||||
const alignmentScore = document.getElementById('alignment-score');
|
||||
const suggestionsList = document.getElementById('suggestions-list');
|
||||
const copyBtn = document.getElementById('copy-btn');
|
||||
const improveBtn = document.getElementById('improve-btn');
|
||||
const saveBtn = document.getElementById('save-btn');
|
||||
const improvementPanel = document.getElementById('improvement-panel');
|
||||
const improvementFeedback = document.getElementById('improvement-feedback');
|
||||
const submitImprovement = document.getElementById('submit-improvement');
|
||||
|
||||
// Brand Style Page
|
||||
const toneSelector = document.getElementById('tone-selector');
|
||||
const voiceSelector = document.getElementById('voice-selector');
|
||||
const tabooWords = document.getElementById('taboo-words');
|
||||
const tabooInput = document.getElementById('taboo-input');
|
||||
const addTabooBtn = document.getElementById('add-taboo-btn');
|
||||
const avoidTerm = document.getElementById('avoid-term');
|
||||
const useTerm = document.getElementById('use-term');
|
||||
const addTermBtn = document.getElementById('add-term-btn');
|
||||
const saveBrandStyleBtn = document.getElementById('save-brand-style');
|
||||
const resetBrandStyleBtn = document.getElementById('reset-brand-style');
|
||||
|
||||
// Training Page
|
||||
const trainingTabs = document.querySelectorAll('.training-tabs .tab');
|
||||
const tabContents = document.querySelectorAll('.tab-content');
|
||||
const addTrainingBtn = document.getElementById('add-training-btn');
|
||||
const trainingContentType = document.getElementById('training-content-type');
|
||||
const campaignName = document.getElementById('campaign-name');
|
||||
const trainingContent = document.getElementById('training-content');
|
||||
const openRate = document.getElementById('open-rate');
|
||||
const clickRate = document.getElementById('click-rate');
|
||||
const conversionRate = document.getElementById('conversion-rate');
|
||||
|
||||
// API Base URL
|
||||
const API_URL = 'http://localhost:8000';
|
||||
|
||||
// Menu Navigation
|
||||
menuItems.forEach(item => {
|
||||
item.addEventListener('click', function() {
|
||||
const pageName = this.getAttribute('data-page');
|
||||
|
||||
// Update active menu item
|
||||
menuItems.forEach(menuItem => menuItem.classList.remove('active'));
|
||||
this.classList.add('active');
|
||||
|
||||
// Show selected page
|
||||
pages.forEach(page => {
|
||||
if (page.id === `${pageName}-page`) {
|
||||
page.classList.add('active');
|
||||
} else {
|
||||
page.classList.remove('active');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Generate Content
|
||||
if (generateBtn) {
|
||||
generateBtn.addEventListener('click', function() {
|
||||
if (!promptInput.value.trim()) {
|
||||
alert('Please enter a prompt for content generation.');
|
||||
return;
|
||||
}
|
||||
|
||||
// Show loading indicator
|
||||
loadingIndicator.classList.remove('hidden');
|
||||
resultContainer.classList.add('hidden');
|
||||
|
||||
// Prepare request data
|
||||
const requestData = {
|
||||
prompt: promptInput.value,
|
||||
content_type: contentTypeSelect.value || null,
|
||||
tone: toneSelect.value || null,
|
||||
length: lengthSelect.value || null,
|
||||
include_cta: includeCTACheckbox.checked,
|
||||
reference_similar_content: referenceSimilarCheckbox.checked
|
||||
};
|
||||
|
||||
// Call the API
|
||||
fetch(`${API_URL}/generate-copy`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(requestData)
|
||||
})
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! Status: ${response.status}`);
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(data => {
|
||||
// Hide loading indicator
|
||||
loadingIndicator.classList.add('hidden');
|
||||
|
||||
// Display result
|
||||
resultContent.textContent = data.content;
|
||||
|
||||
// Set alignment score
|
||||
const score = data.metadata.alignment_score || 0;
|
||||
alignmentScore.style.width = `${score}%`;
|
||||
alignmentScore.textContent = `${Math.round(score)}%`;
|
||||
|
||||
if (score < 60) {
|
||||
alignmentScore.style.backgroundColor = 'var(--danger-color)';
|
||||
} else if (score < 80) {
|
||||
alignmentScore.style.backgroundColor = 'var(--warning-color)';
|
||||
} else {
|
||||
alignmentScore.style.backgroundColor = 'var(--success-color)';
|
||||
}
|
||||
|
||||
// Display suggestions
|
||||
if (data.suggestions && data.suggestions.length > 0) {
|
||||
suggestionsList.innerHTML = '';
|
||||
data.suggestions.forEach(suggestion => {
|
||||
const li = document.createElement('li');
|
||||
li.textContent = suggestion;
|
||||
li.addEventListener('click', function() {
|
||||
promptInput.value = suggestion;
|
||||
});
|
||||
suggestionsList.appendChild(li);
|
||||
});
|
||||
}
|
||||
|
||||
// Show result container
|
||||
resultContainer.classList.remove('hidden');
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
loadingIndicator.classList.add('hidden');
|
||||
alert('An error occurred while generating content. Please try again.');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Copy to Clipboard
|
||||
if (copyBtn) {
|
||||
copyBtn.addEventListener('click', function() {
|
||||
navigator.clipboard.writeText(resultContent.textContent)
|
||||
.then(() => {
|
||||
const originalTitle = copyBtn.getAttribute('title');
|
||||
copyBtn.setAttribute('title', 'Copied!');
|
||||
setTimeout(() => {
|
||||
copyBtn.setAttribute('title', originalTitle);
|
||||
}, 2000);
|
||||
})
|
||||
.catch(err => {
|
||||
console.error('Could not copy text: ', err);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Toggle Improvement Panel
|
||||
if (improveBtn) {
|
||||
improveBtn.addEventListener('click', function() {
|
||||
improvementPanel.classList.toggle('hidden');
|
||||
});
|
||||
}
|
||||
|
||||
// Submit Improvement Feedback
|
||||
if (submitImprovement) {
|
||||
submitImprovement.addEventListener('click', function() {
|
||||
if (!improvementFeedback.value.trim()) {
|
||||
alert('Please enter feedback for improvement.');
|
||||
return;
|
||||
}
|
||||
|
||||
// Show loading indicator
|
||||
loadingIndicator.classList.remove('hidden');
|
||||
|
||||
// Prepare request data
|
||||
const requestData = {
|
||||
content: resultContent.textContent,
|
||||
feedback: improvementFeedback.value
|
||||
};
|
||||
|
||||
// Call the API
|
||||
fetch(`${API_URL}/improve-content`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(requestData)
|
||||
})
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! Status: ${response.status}`);
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(data => {
|
||||
// Hide loading indicator
|
||||
loadingIndicator.classList.add('hidden');
|
||||
|
||||
// Update result content
|
||||
resultContent.textContent = data.improved_content;
|
||||
|
||||
// Hide improvement panel
|
||||
improvementPanel.classList.add('hidden');
|
||||
improvementFeedback.value = '';
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
loadingIndicator.classList.add('hidden');
|
||||
alert('An error occurred while improving content. Please try again.');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Save Content to History
|
||||
if (saveBtn) {
|
||||
saveBtn.addEventListener('click', function() {
|
||||
alert('Content saved to history!');
|
||||
// In a real implementation, you would save this to local storage
|
||||
// or call an API to save it to the backend
|
||||
});
|
||||
}
|
||||
|
||||
// Brand Style Tag Selection
|
||||
if (toneSelector) {
|
||||
const tagElements = toneSelector.querySelectorAll('.tag');
|
||||
tagElements.forEach(tag => {
|
||||
tag.addEventListener('click', function() {
|
||||
this.classList.toggle('selected');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (voiceSelector) {
|
||||
const tagElements = voiceSelector.querySelectorAll('.tag');
|
||||
tagElements.forEach(tag => {
|
||||
tag.addEventListener('click', function() {
|
||||
this.classList.toggle('selected');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Add Taboo Word
|
||||
if (addTabooBtn && tabooInput && tabooWords) {
|
||||
addTabooBtn.addEventListener('click', function() {
|
||||
const word = tabooInput.value.trim();
|
||||
if (word) {
|
||||
const tagElement = document.createElement('span');
|
||||
tagElement.classList.add('tag', 'removable');
|
||||
tagElement.innerHTML = `${word}<i class="fas fa-times"></i>`;
|
||||
|
||||
// Add click event to remove the tag
|
||||
tagElement.querySelector('i').addEventListener('click', function() {
|
||||
tagElement.remove();
|
||||
});
|
||||
|
||||
tabooWords.appendChild(tagElement);
|
||||
tabooInput.value = '';
|
||||
}
|
||||
});
|
||||
|
||||
// Allow pressing Enter to add a word
|
||||
tabooInput.addEventListener('keypress', function(e) {
|
||||
if (e.key === 'Enter') {
|
||||
e.preventDefault();
|
||||
addTabooBtn.click();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Add Terminology Term
|
||||
if (addTermBtn && avoidTerm && useTerm) {
|
||||
addTermBtn.addEventListener('click', function() {
|
||||
const avoid = avoidTerm.value.trim();
|
||||
const use = useTerm.value.trim();
|
||||
|
||||
if (avoid && use) {
|
||||
const tableRow = document.createElement('div');
|
||||
tableRow.classList.add('terminology-row');
|
||||
tableRow.innerHTML = `
|
||||
<div class="term-avoid">${avoid}</div>
|
||||
<div class="term-use">${use}</div>
|
||||
<div class="term-actions">
|
||||
<button class="btn btn-icon"><i class="fas fa-times"></i></button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Add click event to remove the row
|
||||
tableRow.querySelector('.btn-icon').addEventListener('click', function() {
|
||||
tableRow.remove();
|
||||
});
|
||||
|
||||
// Insert before the add row
|
||||
const addRow = document.querySelector('.terminology-row.add-row');
|
||||
addRow.parentNode.insertBefore(tableRow, addRow);
|
||||
|
||||
avoidTerm.value = '';
|
||||
useTerm.value = '';
|
||||
}
|
||||
});
|
||||
|
||||
// Allow pressing Enter to add a term
|
||||
useTerm.addEventListener('keypress', function(e) {
|
||||
if (e.key === 'Enter') {
|
||||
e.preventDefault();
|
||||
addTermBtn.click();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Save Brand Style
|
||||
if (saveBrandStyleBtn) {
|
||||
saveBrandStyleBtn.addEventListener('click', function() {
|
||||
// Collect tone tags
|
||||
const selectedTones = [];
|
||||
toneSelector.querySelectorAll('.tag.selected').forEach(tag => {
|
||||
selectedTones.push(tag.textContent);
|
||||
});
|
||||
|
||||
// Collect voice characteristics
|
||||
const selectedVoice = [];
|
||||
voiceSelector.querySelectorAll('.tag.selected').forEach(tag => {
|
||||
selectedVoice.push(tag.textContent);
|
||||
});
|
||||
|
||||
// Collect taboo words
|
||||
const tabooWordsList = [];
|
||||
tabooWords.querySelectorAll('.tag').forEach(tag => {
|
||||
// Extract just the text without the 'x' icon
|
||||
const text = tag.textContent.replace('×', '').trim();
|
||||
tabooWordsList.push(text);
|
||||
});
|
||||
|
||||
// Collect preferred terms
|
||||
const preferredTerms = {};
|
||||
document.querySelectorAll('.terminology-row:not(.add-row):not(.terminology-header)').forEach(row => {
|
||||
const avoid = row.querySelector('.term-avoid').textContent.trim();
|
||||
const use = row.querySelector('.term-use').textContent.trim();
|
||||
if (avoid && use) {
|
||||
preferredTerms[avoid] = use;
|
||||
}
|
||||
});
|
||||
|
||||
// Prepare request data
|
||||
const requestData = {
|
||||
tone: selectedTones,
|
||||
voice_characteristics: selectedVoice,
|
||||
taboo_words: tabooWordsList,
|
||||
preferred_terms: preferredTerms
|
||||
};
|
||||
|
||||
// Call the API
|
||||
fetch(`${API_URL}/brand-style`, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(requestData)
|
||||
})
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! Status: ${response.status}`);
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(data => {
|
||||
alert('Brand style updated successfully!');
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
alert('An error occurred while updating brand style. Please try again.');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Reset Brand Style
|
||||
if (resetBrandStyleBtn) {
|
||||
resetBrandStyleBtn.addEventListener('click', function() {
|
||||
if (confirm('Are you sure you want to reset brand style to defaults?')) {
|
||||
// In a real implementation, you would call an API to reset
|
||||
// For now, just reload the page
|
||||
window.location.reload();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Training Tabs
|
||||
if (trainingTabs.length > 0) {
|
||||
trainingTabs.forEach(tab => {
|
||||
tab.addEventListener('click', function() {
|
||||
const tabName = this.getAttribute('data-tab');
|
||||
|
||||
// Update active tab
|
||||
trainingTabs.forEach(t => t.classList.remove('active'));
|
||||
this.classList.add('active');
|
||||
|
||||
// Show selected tab content
|
||||
tabContents.forEach(content => {
|
||||
if (content.id === `${tabName}-tab`) {
|
||||
content.classList.add('active');
|
||||
} else {
|
||||
content.classList.remove('active');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Add Training Data
|
||||
if (addTrainingBtn) {
|
||||
addTrainingBtn.addEventListener('click', function() {
|
||||
if (!trainingContentType.value) {
|
||||
alert('Please select a content type.');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!trainingContent.value.trim()) {
|
||||
alert('Please enter content for training.');
|
||||
return;
|
||||
}
|
||||
|
||||
// Prepare request data
|
||||
const requestData = {
|
||||
content_type: trainingContentType.value,
|
||||
content: trainingContent.value,
|
||||
metadata: {
|
||||
campaign_name: campaignName.value,
|
||||
performance_metrics: {}
|
||||
}
|
||||
};
|
||||
|
||||
// Add performance metrics if provided
|
||||
if (openRate.value) {
|
||||
requestData.metadata.performance_metrics.open_rate = parseFloat(openRate.value) / 100;
|
||||
}
|
||||
|
||||
if (clickRate.value) {
|
||||
requestData.metadata.performance_metrics.click_rate = parseFloat(clickRate.value) / 100;
|
||||
}
|
||||
|
||||
if (conversionRate.value) {
|
||||
requestData.metadata.performance_metrics.conversion_rate = parseFloat(conversionRate.value) / 100;
|
||||
}
|
||||
|
||||
// Call the API
|
||||
fetch(`${API_URL}/training-data`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(requestData)
|
||||
})
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! Status: ${response.status}`);
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(data => {
|
||||
alert('Training data added successfully!');
|
||||
|
||||
// Clear form
|
||||
trainingContentType.value = '';
|
||||
campaignName.value = '';
|
||||
trainingContent.value = '';
|
||||
openRate.value = '';
|
||||
clickRate.value = '';
|
||||
conversionRate.value = '';
|
||||
|
||||
// Switch to view tab
|
||||
document.querySelector('.tab[data-tab="view-training"]').click();
|
||||
|
||||
// In a real implementation, you would also refresh the training data list
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
alert('An error occurred while adding training data. Please try again.');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Load Brand Style on Page Load
|
||||
fetch(`${API_URL}/brand-style`)
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! Status: ${response.status}`);
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(data => {
|
||||
console.log('Loaded brand style:', data);
|
||||
// In a real implementation, you would update the UI based on the loaded data
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error loading brand style:', error);
|
||||
});
|
||||
|
||||
// For demonstration purposes, let's create a mocked pre-filled content
|
||||
// In a real implementation, this would be loaded from the backend
|
||||
document.getElementById('prompt').value = 'Write a social media post about our new coaching program';
|
||||
});
|
||||
@@ -0,0 +1,498 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Adriana James - Marketing Assistant AI</title>
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<div class="app-container">
|
||||
<nav class="sidebar">
|
||||
<div class="logo">
|
||||
<h2>AJ</h2>
|
||||
</div>
|
||||
<ul class="menu">
|
||||
<li class="active" data-page="generate"><i class="fas fa-magic"></i> Generate</li>
|
||||
<li data-page="templates"><i class="fas fa-folder"></i> Templates</li>
|
||||
<li data-page="history"><i class="fas fa-history"></i> History</li>
|
||||
<li data-page="brand-style"><i class="fas fa-paint-brush"></i> Brand Style</li>
|
||||
<li data-page="training"><i class="fas fa-graduation-cap"></i> Training</li>
|
||||
</ul>
|
||||
<div class="user-info">
|
||||
<div class="user-avatar">
|
||||
<img src="https://via.placeholder.com/50" alt="User Avatar">
|
||||
</div>
|
||||
<div class="user-name">Marketing Team</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<main class="content">
|
||||
<header>
|
||||
<h1>Marketing Assistant AI</h1>
|
||||
<div class="header-actions">
|
||||
<button class="btn btn-secondary"><i class="fas fa-cog"></i> Settings</button>
|
||||
<button class="btn btn-primary">Upgrade</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Generate Content Page -->
|
||||
<section id="generate-page" class="page active">
|
||||
<div class="page-header">
|
||||
<h2>Generate Marketing Content</h2>
|
||||
<p>Create high-quality marketing copy aligned with Adriana James' brand voice.</p>
|
||||
</div>
|
||||
|
||||
<div class="generation-form">
|
||||
<div class="form-group">
|
||||
<label for="prompt">What would you like to create?</label>
|
||||
<textarea id="prompt" placeholder="e.g., Write a social media post for our new coaching program launch" rows="4"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<div class="form-group">
|
||||
<label for="content-type">Content Type</label>
|
||||
<select id="content-type">
|
||||
<option value="">Select Type</option>
|
||||
<option value="email_campaign">Email Campaign</option>
|
||||
<option value="social_media">Social Media</option>
|
||||
<option value="blog_post">Blog Post</option>
|
||||
<option value="website_copy">Website Copy</option>
|
||||
<option value="ad_copy">Ad Copy</option>
|
||||
<option value="funnel_page">Funnel Page</option>
|
||||
<option value="product_description">Product Description</option>
|
||||
<option value="press_release">Press Release</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="tone">Tone</label>
|
||||
<select id="tone">
|
||||
<option value="">Select Tone</option>
|
||||
<option value="professional">Professional</option>
|
||||
<option value="friendly">Friendly</option>
|
||||
<option value="excited">Excited</option>
|
||||
<option value="authoritative">Authoritative</option>
|
||||
<option value="casual">Casual</option>
|
||||
<option value="inspirational">Inspirational</option>
|
||||
<option value="empathetic">Empathetic</option>
|
||||
<option value="humorous">Humorous</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="length">Length</label>
|
||||
<select id="length">
|
||||
<option value="">Select Length</option>
|
||||
<option value="short">Short (< 100 words)</option>
|
||||
<option value="medium">Medium (100-300 words)</option>
|
||||
<option value="long">Long (> 300 words)</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group checkbox-group">
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" id="include-cta" checked>
|
||||
<span class="checkmark"></span>
|
||||
Include Call to Action
|
||||
</label>
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" id="reference-similar" checked>
|
||||
<span class="checkmark"></span>
|
||||
Reference Similar Content
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="form-actions">
|
||||
<button id="generate-btn" class="btn btn-primary btn-lg">
|
||||
<i class="fas fa-magic"></i> Generate
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="result-container" class="result-container hidden">
|
||||
<div class="result-header">
|
||||
<h3>Generated Content</h3>
|
||||
<div class="result-actions">
|
||||
<button id="copy-btn" class="btn btn-icon" title="Copy to clipboard">
|
||||
<i class="fas fa-copy"></i>
|
||||
</button>
|
||||
<button id="improve-btn" class="btn btn-icon" title="Improve content">
|
||||
<i class="fas fa-wand-magic-sparkles"></i>
|
||||
</button>
|
||||
<button id="save-btn" class="btn btn-icon" title="Save to history">
|
||||
<i class="fas fa-save"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="result-content" class="result-content"></div>
|
||||
|
||||
<div class="metadata-panel">
|
||||
<div class="metadata-item">
|
||||
<span class="metadata-label">Alignment Score</span>
|
||||
<div class="score-bar">
|
||||
<div id="alignment-score" class="score-fill" style="width: 0%;">0%</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="suggestions-container" class="suggestions-container">
|
||||
<h4>Headline Suggestions</h4>
|
||||
<ul id="suggestions-list" class="suggestions-list"></ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="improvement-panel" class="improvement-panel hidden">
|
||||
<h4>Improve This Content</h4>
|
||||
<textarea id="improvement-feedback" placeholder="What would you like to improve about this content?" rows="3"></textarea>
|
||||
<button id="submit-improvement" class="btn btn-secondary">Submit Feedback</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="loading-indicator" class="loading-indicator hidden">
|
||||
<div class="spinner"></div>
|
||||
<p>Generating creative marketing content...</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Templates Page -->
|
||||
<section id="templates-page" class="page">
|
||||
<div class="page-header">
|
||||
<h2>Content Templates</h2>
|
||||
<p>Use pre-built templates for faster content creation.</p>
|
||||
</div>
|
||||
|
||||
<div class="templates-grid">
|
||||
<div class="template-card">
|
||||
<div class="template-icon"><i class="fas fa-envelope"></i></div>
|
||||
<h3>Email Welcome Sequence</h3>
|
||||
<p>A 5-part email sequence for new subscribers.</p>
|
||||
<button class="btn btn-outline">Use Template</button>
|
||||
</div>
|
||||
<div class="template-card">
|
||||
<div class="template-icon"><i class="fas fa-share-alt"></i></div>
|
||||
<h3>Product Launch Posts</h3>
|
||||
<p>Social media templates for product launches.</p>
|
||||
<button class="btn btn-outline">Use Template</button>
|
||||
</div>
|
||||
<div class="template-card">
|
||||
<div class="template-icon"><i class="fas fa-newspaper"></i></div>
|
||||
<h3>Transformation Story</h3>
|
||||
<p>Client success story blog post template.</p>
|
||||
<button class="btn btn-outline">Use Template</button>
|
||||
</div>
|
||||
<div class="template-card">
|
||||
<div class="template-icon"><i class="fas fa-ad"></i></div>
|
||||
<h3>Workshop Promotion</h3>
|
||||
<p>Ad copy template for promoting workshops.</p>
|
||||
<button class="btn btn-outline">Use Template</button>
|
||||
</div>
|
||||
<div class="template-card template-add">
|
||||
<div class="template-icon"><i class="fas fa-plus"></i></div>
|
||||
<h3>Create New Template</h3>
|
||||
<p>Build a custom template from scratch.</p>
|
||||
<button class="btn btn-outline">Create Template</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- History Page -->
|
||||
<section id="history-page" class="page">
|
||||
<div class="page-header">
|
||||
<h2>Content History</h2>
|
||||
<p>View and reuse your previously generated content.</p>
|
||||
</div>
|
||||
|
||||
<div class="history-filters">
|
||||
<div class="form-group">
|
||||
<select id="history-filter-type">
|
||||
<option value="">All Content Types</option>
|
||||
<option value="email_campaign">Email Campaign</option>
|
||||
<option value="social_media">Social Media</option>
|
||||
<option value="blog_post">Blog Post</option>
|
||||
<option value="website_copy">Website Copy</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="text" placeholder="Search history..." id="history-search">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="history-list">
|
||||
<div class="history-item">
|
||||
<div class="history-item-type email_campaign">Email</div>
|
||||
<div class="history-item-content">
|
||||
<h4>Transformation Masterclass Invitation</h4>
|
||||
<p>Subject: Transform Your Potential with Adriana James' Exclusive Workshop...</p>
|
||||
</div>
|
||||
<div class="history-item-date">Apr 17, 2025</div>
|
||||
<div class="history-item-actions">
|
||||
<button class="btn btn-icon" title="View content"><i class="fas fa-eye"></i></button>
|
||||
<button class="btn btn-icon" title="Edit content"><i class="fas fa-edit"></i></button>
|
||||
<button class="btn btn-icon" title="Delete content"><i class="fas fa-trash"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="history-item">
|
||||
<div class="history-item-type social_media">Social</div>
|
||||
<div class="history-item-content">
|
||||
<h4>3-Step Framework Post</h4>
|
||||
<p>BREAKTHROUGH MOMENT ✨ Ever feel stuck in patterns that hold you back...</p>
|
||||
</div>
|
||||
<div class="history-item-date">Apr 16, 2025</div>
|
||||
<div class="history-item-actions">
|
||||
<button class="btn btn-icon" title="View content"><i class="fas fa-eye"></i></button>
|
||||
<button class="btn btn-icon" title="Edit content"><i class="fas fa-edit"></i></button>
|
||||
<button class="btn btn-icon" title="Delete content"><i class="fas fa-trash"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="history-item">
|
||||
<div class="history-item-type blog_post">Blog</div>
|
||||
<div class="history-item-content">
|
||||
<h4>5 Ways to Overcome Limiting Beliefs</h4>
|
||||
<p>Are limiting beliefs holding you back from achieving your full potential?...</p>
|
||||
</div>
|
||||
<div class="history-item-date">Apr 14, 2025</div>
|
||||
<div class="history-item-actions">
|
||||
<button class="btn btn-icon" title="View content"><i class="fas fa-eye"></i></button>
|
||||
<button class="btn btn-icon" title="Edit content"><i class="fas fa-edit"></i></button>
|
||||
<button class="btn btn-icon" title="Delete content"><i class="fas fa-trash"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Brand Style Page -->
|
||||
<section id="brand-style-page" class="page">
|
||||
<div class="page-header">
|
||||
<h2>Brand Style Guidelines</h2>
|
||||
<p>Customize the AI to match Adriana James' brand voice and tone.</p>
|
||||
</div>
|
||||
|
||||
<div class="brand-style-form">
|
||||
<div class="form-section">
|
||||
<h3>Brand Tone</h3>
|
||||
<p>Select the tone options that best represent the brand.</p>
|
||||
<div class="tag-selector" id="tone-selector">
|
||||
<span class="tag selected">professional</span>
|
||||
<span class="tag selected">friendly</span>
|
||||
<span class="tag selected">inspirational</span>
|
||||
<span class="tag selected">empowering</span>
|
||||
<span class="tag">excited</span>
|
||||
<span class="tag">authoritative</span>
|
||||
<span class="tag">casual</span>
|
||||
<span class="tag">humorous</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-section">
|
||||
<h3>Voice Characteristics</h3>
|
||||
<p>Define the key characteristics of the brand voice.</p>
|
||||
<div class="tag-selector" id="voice-selector">
|
||||
<span class="tag selected">clear</span>
|
||||
<span class="tag selected">direct</span>
|
||||
<span class="tag selected">empowering</span>
|
||||
<span class="tag selected">confident</span>
|
||||
<span class="tag selected">authentic</span>
|
||||
<span class="tag">innovative</span>
|
||||
<span class="tag">visionary</span>
|
||||
<span class="tag">approachable</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-section">
|
||||
<h3>Taboo Words</h3>
|
||||
<p>Words to avoid in all marketing content.</p>
|
||||
<div class="tag-editor">
|
||||
<div class="tag-list" id="taboo-words">
|
||||
<span class="tag removable">cheap<i class="fas fa-times"></i></span>
|
||||
<span class="tag removable">discount<i class="fas fa-times"></i></span>
|
||||
<span class="tag removable">bargain<i class="fas fa-times"></i></span>
|
||||
<span class="tag removable">failure<i class="fas fa-times"></i></span>
|
||||
<span class="tag removable">impossible<i class="fas fa-times"></i></span>
|
||||
<span class="tag removable">difficult<i class="fas fa-times"></i></span>
|
||||
</div>
|
||||
<div class="tag-input-container">
|
||||
<input type="text" id="taboo-input" placeholder="Add a word to avoid...">
|
||||
<button class="btn btn-icon" id="add-taboo-btn"><i class="fas fa-plus"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-section">
|
||||
<h3>Preferred Terminology</h3>
|
||||
<p>Preferred terms to use instead of common alternatives.</p>
|
||||
<div class="terminology-table">
|
||||
<div class="terminology-header">
|
||||
<div class="term-avoid">Avoid</div>
|
||||
<div class="term-use">Use Instead</div>
|
||||
<div class="term-actions"></div>
|
||||
</div>
|
||||
<div class="terminology-row">
|
||||
<div class="term-avoid">customers</div>
|
||||
<div class="term-use">clients</div>
|
||||
<div class="term-actions">
|
||||
<button class="btn btn-icon"><i class="fas fa-times"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="terminology-row">
|
||||
<div class="term-avoid">products</div>
|
||||
<div class="term-use">solutions</div>
|
||||
<div class="term-actions">
|
||||
<button class="btn btn-icon"><i class="fas fa-times"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="terminology-row">
|
||||
<div class="term-avoid">problems</div>
|
||||
<div class="term-use">challenges</div>
|
||||
<div class="term-actions">
|
||||
<button class="btn btn-icon"><i class="fas fa-times"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="terminology-row">
|
||||
<div class="term-avoid">services</div>
|
||||
<div class="term-use">experiences</div>
|
||||
<div class="term-actions">
|
||||
<button class="btn btn-icon"><i class="fas fa-times"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="terminology-row">
|
||||
<div class="term-avoid">training</div>
|
||||
<div class="term-use">transformation</div>
|
||||
<div class="term-actions">
|
||||
<button class="btn btn-icon"><i class="fas fa-times"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="terminology-row add-row">
|
||||
<div class="term-avoid">
|
||||
<input type="text" placeholder="Avoid" id="avoid-term">
|
||||
</div>
|
||||
<div class="term-use">
|
||||
<input type="text" placeholder="Use Instead" id="use-term">
|
||||
</div>
|
||||
<div class="term-actions">
|
||||
<button class="btn btn-icon" id="add-term-btn"><i class="fas fa-plus"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-actions">
|
||||
<button id="save-brand-style" class="btn btn-primary">Save Brand Style</button>
|
||||
<button id="reset-brand-style" class="btn btn-outline">Reset to Defaults</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Training Page -->
|
||||
<section id="training-page" class="page">
|
||||
<div class="page-header">
|
||||
<h2>Training Data</h2>
|
||||
<p>Add examples of high-performing content to improve the AI.</p>
|
||||
</div>
|
||||
|
||||
<div class="training-tabs">
|
||||
<div class="tab active" data-tab="add-training">Add Training Data</div>
|
||||
<div class="tab" data-tab="view-training">View Training Data</div>
|
||||
</div>
|
||||
|
||||
<div id="add-training-tab" class="tab-content active">
|
||||
<div class="training-form">
|
||||
<div class="form-group">
|
||||
<label for="training-content-type">Content Type</label>
|
||||
<select id="training-content-type">
|
||||
<option value="">Select Type</option>
|
||||
<option value="email_campaign">Email Campaign</option>
|
||||
<option value="social_media">Social Media</option>
|
||||
<option value="blog_post">Blog Post</option>
|
||||
<option value="website_copy">Website Copy</option>
|
||||
<option value="ad_copy">Ad Copy</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="campaign-name">Campaign Name</label>
|
||||
<input type="text" id="campaign-name" placeholder="e.g., Spring Launch 2025">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="training-content">Content</label>
|
||||
<textarea id="training-content" rows="8" placeholder="Paste your successful marketing content here..."></textarea>
|
||||
</div>
|
||||
<div class="form-section">
|
||||
<h3>Performance Metrics</h3>
|
||||
<div class="form-row">
|
||||
<div class="form-group">
|
||||
<label for="open-rate">Open Rate (%)</label>
|
||||
<input type="number" id="open-rate" min="0" max="100" step="0.1">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="click-rate">Click Rate (%)</label>
|
||||
<input type="number" id="click-rate" min="0" max="100" step="0.1">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="conversion-rate">Conversion Rate (%)</label>
|
||||
<input type="number" id="conversion-rate" min="0" max="100" step="0.1">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-actions">
|
||||
<button id="add-training-btn" class="btn btn-primary">Add Training Data</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="view-training-tab" class="tab-content">
|
||||
<div class="training-filters">
|
||||
<div class="form-group">
|
||||
<select id="training-filter-type">
|
||||
<option value="">All Content Types</option>
|
||||
<option value="email_campaign">Email Campaign</option>
|
||||
<option value="social_media">Social Media</option>
|
||||
<option value="blog_post">Blog Post</option>
|
||||
<option value="website_copy">Website Copy</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="text" placeholder="Search training data..." id="training-search">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="training-list">
|
||||
<div class="training-item">
|
||||
<div class="training-item-type email_campaign">Email</div>
|
||||
<div class="training-item-content">
|
||||
<h4>Transformation Masterclass Promotion</h4>
|
||||
<p>Added on: Apr 15, 2025</p>
|
||||
<div class="metrics">
|
||||
<span class="metric">Open Rate: 42%</span>
|
||||
<span class="metric">Click Rate: 18%</span>
|
||||
<span class="metric">Conversion: 8%</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="training-item-actions">
|
||||
<button class="btn btn-icon" title="View content"><i class="fas fa-eye"></i></button>
|
||||
<button class="btn btn-icon" title="Delete content"><i class="fas fa-trash"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="training-item">
|
||||
<div class="training-item-type social_media">Social</div>
|
||||
<div class="training-item-content">
|
||||
<h4>Breakthrough Framework</h4>
|
||||
<p>Added on: Apr 10, 2025</p>
|
||||
<div class="metrics">
|
||||
<span class="metric">Engagement: 6.4%</span>
|
||||
<span class="metric">Saves: 178</span>
|
||||
<span class="metric">Shares: 92</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="training-item-actions">
|
||||
<button class="btn btn-icon" title="View content"><i class="fas fa-eye"></i></button>
|
||||
<button class="btn btn-icon" title="Delete content"><i class="fas fa-trash"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<script src="app.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,964 @@
|
||||
/* Global Variables */
|
||||
:root {
|
||||
--primary-color: #6236FF;
|
||||
--primary-light: #8E6FFF;
|
||||
--primary-dark: #4B2AD8;
|
||||
--secondary-color: #FFB800;
|
||||
--success-color: #1AC888;
|
||||
--danger-color: #FF4757;
|
||||
--warning-color: #FFBA00;
|
||||
--dark-color: #161925;
|
||||
--grey-100: #F5F7FA;
|
||||
--grey-200: #E4E8F0;
|
||||
--grey-300: #CBD2E0;
|
||||
--grey-400: #9AA5B9;
|
||||
--grey-500: #6B7A99;
|
||||
--grey-600: #4A5568;
|
||||
--grey-700: #2D3748;
|
||||
--grey-800: #1A202C;
|
||||
--radius-sm: 4px;
|
||||
--radius-md: 8px;
|
||||
--radius-lg: 12px;
|
||||
--shadow-sm: 0 2px 4px rgba(0, 0, 0, 0.05);
|
||||
--shadow-md: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
--shadow-lg: 0 8px 20px rgba(0, 0, 0, 0.15);
|
||||
--font-family: 'Poppins', sans-serif;
|
||||
}
|
||||
|
||||
/* Reset & Base Styles */
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: var(--font-family);
|
||||
font-size: 15px;
|
||||
line-height: 1.5;
|
||||
color: var(--grey-700);
|
||||
background-color: var(--grey-100);
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
margin-bottom: 0.5rem;
|
||||
font-weight: 600;
|
||||
line-height: 1.2;
|
||||
color: var(--grey-800);
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--primary-color);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* Layout */
|
||||
.app-container {
|
||||
display: flex;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
width: 240px;
|
||||
background-color: var(--grey-800);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
color: white;
|
||||
padding: 20px 0;
|
||||
position: fixed;
|
||||
height: 100vh;
|
||||
box-shadow: var(--shadow-md);
|
||||
}
|
||||
|
||||
.content {
|
||||
flex: 1;
|
||||
margin-left: 240px;
|
||||
padding: 20px;
|
||||
max-width: calc(100vw - 240px);
|
||||
}
|
||||
|
||||
/* Logo */
|
||||
.logo {
|
||||
padding: 10px 20px 30px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.logo h2 {
|
||||
color: white;
|
||||
background-color: var(--primary-color);
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 0 auto;
|
||||
font-size: 26px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
/* Menu */
|
||||
.menu {
|
||||
list-style: none;
|
||||
margin-bottom: auto;
|
||||
}
|
||||
|
||||
.menu li {
|
||||
padding: 12px 20px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
transition: background-color 0.2s;
|
||||
color: var(--grey-300);
|
||||
margin-bottom: 4px;
|
||||
border-left: 3px solid transparent;
|
||||
}
|
||||
|
||||
.menu li i {
|
||||
margin-right: 12px;
|
||||
font-size: 16px;
|
||||
width: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.menu li:hover {
|
||||
background-color: rgba(255, 255, 255, 0.05);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.menu li.active {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
color: white;
|
||||
border-left: 3px solid var(--primary-color);
|
||||
}
|
||||
|
||||
/* User Info */
|
||||
.user-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 16px 20px;
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.1);
|
||||
margin-top: auto;
|
||||
}
|
||||
|
||||
.user-avatar {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
||||
.user-avatar img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.user-name {
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* Header */
|
||||
header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 30px;
|
||||
padding-bottom: 20px;
|
||||
border-bottom: 1px solid var(--grey-200);
|
||||
}
|
||||
|
||||
.header-actions {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
/* Page */
|
||||
.page {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.page.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.page-header {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.page-header h2 {
|
||||
margin-bottom: 8px;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.page-header p {
|
||||
color: var(--grey-500);
|
||||
}
|
||||
|
||||
/* Buttons */
|
||||
.btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 8px 16px;
|
||||
border-radius: var(--radius-md);
|
||||
border: none;
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.btn i {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background-color: var(--primary-color);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
background-color: var(--primary-dark);
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background-color: var(--grey-200);
|
||||
color: var(--grey-700);
|
||||
}
|
||||
|
||||
.btn-secondary:hover {
|
||||
background-color: var(--grey-300);
|
||||
}
|
||||
|
||||
.btn-outline {
|
||||
background-color: transparent;
|
||||
color: var(--primary-color);
|
||||
border: 1px solid var(--primary-color);
|
||||
}
|
||||
|
||||
.btn-outline:hover {
|
||||
background-color: var(--primary-color);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-lg {
|
||||
padding: 12px 20px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.btn-icon {
|
||||
padding: 8px;
|
||||
border-radius: 50%;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: transparent;
|
||||
color: var(--grey-600);
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.btn-icon:hover {
|
||||
background-color: var(--grey-200);
|
||||
color: var(--grey-800);
|
||||
}
|
||||
|
||||
.btn-icon i {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
/* Forms */
|
||||
.form-group {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.form-group label {
|
||||
display: block;
|
||||
margin-bottom: 8px;
|
||||
font-weight: 500;
|
||||
color: var(--grey-700);
|
||||
}
|
||||
|
||||
.form-group input[type="text"],
|
||||
.form-group input[type="number"],
|
||||
.form-group input[type="email"],
|
||||
.form-group input[type="password"],
|
||||
.form-group select,
|
||||
.form-group textarea {
|
||||
width: 100%;
|
||||
padding: 10px 12px;
|
||||
border-radius: var(--radius-md);
|
||||
border: 1px solid var(--grey-300);
|
||||
font-family: var(--font-family);
|
||||
font-size: 15px;
|
||||
transition: border-color 0.2s;
|
||||
}
|
||||
|
||||
.form-group input:focus,
|
||||
.form-group select:focus,
|
||||
.form-group textarea:focus {
|
||||
outline: none;
|
||||
border-color: var(--primary-color);
|
||||
box-shadow: 0 0 0 2px rgba(98, 54, 255, 0.1);
|
||||
}
|
||||
|
||||
.form-row {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.form-row .form-group {
|
||||
flex: 1;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.form-actions {
|
||||
margin-top: 30px;
|
||||
display: flex;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
.form-section {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.form-section h3 {
|
||||
font-size: 18px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.form-section p {
|
||||
margin-bottom: 15px;
|
||||
color: var(--grey-500);
|
||||
}
|
||||
|
||||
/* Checkbox */
|
||||
.checkbox-group {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.checkbox {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
padding-left: 30px;
|
||||
cursor: pointer;
|
||||
font-weight: normal;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.checkbox input {
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
cursor: pointer;
|
||||
height: 0;
|
||||
width: 0;
|
||||
}
|
||||
|
||||
.checkmark {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
background-color: white;
|
||||
border: 1px solid var(--grey-300);
|
||||
border-radius: var(--radius-sm);
|
||||
}
|
||||
|
||||
.checkbox:hover input ~ .checkmark {
|
||||
border-color: var(--grey-400);
|
||||
}
|
||||
|
||||
.checkbox input:checked ~ .checkmark {
|
||||
background-color: var(--primary-color);
|
||||
border-color: var(--primary-color);
|
||||
}
|
||||
|
||||
.checkmark:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.checkbox input:checked ~ .checkmark:after {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.checkbox .checkmark:after {
|
||||
left: 7px;
|
||||
top: 3px;
|
||||
width: 5px;
|
||||
height: 10px;
|
||||
border: solid white;
|
||||
border-width: 0 2px 2px 0;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
/* Generation Form */
|
||||
.generation-form {
|
||||
background-color: white;
|
||||
border-radius: var(--radius-lg);
|
||||
padding: 25px;
|
||||
box-shadow: var(--shadow-sm);
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
/* Result Container */
|
||||
.result-container {
|
||||
background-color: white;
|
||||
border-radius: var(--radius-lg);
|
||||
box-shadow: var(--shadow-sm);
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.result-container.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.result-header {
|
||||
padding: 20px 25px;
|
||||
border-bottom: 1px solid var(--grey-200);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.result-header h3 {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.result-actions {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.result-content {
|
||||
padding: 25px;
|
||||
white-space: pre-wrap;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.metadata-panel {
|
||||
background-color: var(--grey-100);
|
||||
padding: 20px 25px;
|
||||
border-top: 1px solid var(--grey-200);
|
||||
}
|
||||
|
||||
.metadata-item {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.metadata-label {
|
||||
display: block;
|
||||
font-weight: 500;
|
||||
margin-bottom: 5px;
|
||||
color: var(--grey-600);
|
||||
}
|
||||
|
||||
.score-bar {
|
||||
height: 8px;
|
||||
background-color: var(--grey-200);
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.score-fill {
|
||||
height: 100%;
|
||||
background-color: var(--success-color);
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: white;
|
||||
font-size: 10px;
|
||||
font-weight: 700;
|
||||
transition: width 0.5s ease;
|
||||
}
|
||||
|
||||
.suggestions-container {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.suggestions-container h4 {
|
||||
margin-bottom: 10px;
|
||||
color: var(--grey-600);
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.suggestions-list {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.suggestions-list li {
|
||||
margin-bottom: 8px;
|
||||
padding: 8px 12px;
|
||||
background-color: white;
|
||||
border-radius: var(--radius-md);
|
||||
border: 1px solid var(--grey-200);
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.suggestions-list li:hover {
|
||||
border-color: var(--primary-color);
|
||||
background-color: rgba(98, 54, 255, 0.05);
|
||||
}
|
||||
|
||||
.improvement-panel {
|
||||
padding: 20px 25px;
|
||||
border-top: 1px solid var(--grey-200);
|
||||
}
|
||||
|
||||
.improvement-panel.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.improvement-panel h4 {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
/* Loading Indicator */
|
||||
.loading-indicator {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 40px 0;
|
||||
}
|
||||
|
||||
.loading-indicator.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.spinner {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border: 4px solid var(--grey-200);
|
||||
border-top: 4px solid var(--primary-color);
|
||||
border-radius: 50%;
|
||||
animation: spin 1s linear infinite;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
/* Templates Grid */
|
||||
.templates-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
||||
gap: 20px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.template-card {
|
||||
background-color: white;
|
||||
border-radius: var(--radius-lg);
|
||||
padding: 25px;
|
||||
box-shadow: var(--shadow-sm);
|
||||
transition: all 0.2s;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.template-card:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: var(--shadow-md);
|
||||
}
|
||||
|
||||
.template-icon {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border-radius: 50%;
|
||||
background-color: var(--primary-light);
|
||||
color: white;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 15px;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.template-card h3 {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.template-card p {
|
||||
color: var(--grey-500);
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.template-card button {
|
||||
margin-top: auto;
|
||||
}
|
||||
|
||||
.template-card.template-add {
|
||||
border: 2px dashed var(--grey-300);
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.template-card.template-add .template-icon {
|
||||
background-color: var(--grey-300);
|
||||
}
|
||||
|
||||
.template-card.template-add:hover {
|
||||
border-color: var(--primary-color);
|
||||
}
|
||||
|
||||
/* History and Training List */
|
||||
.history-filters,
|
||||
.training-filters {
|
||||
display: flex;
|
||||
gap: 15px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.history-filters .form-group,
|
||||
.training-filters .form-group {
|
||||
margin-bottom: 0;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.history-list,
|
||||
.training-list {
|
||||
background-color: white;
|
||||
border-radius: var(--radius-lg);
|
||||
box-shadow: var(--shadow-sm);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.history-item,
|
||||
.training-item {
|
||||
display: flex;
|
||||
padding: 15px 20px;
|
||||
border-bottom: 1px solid var(--grey-200);
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.history-item:last-child,
|
||||
.training-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.history-item-type,
|
||||
.training-item-type {
|
||||
width: 80px;
|
||||
text-align: center;
|
||||
padding: 4px 8px;
|
||||
border-radius: var(--radius-md);
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.history-item-type.email_campaign,
|
||||
.training-item-type.email_campaign {
|
||||
background-color: var(--primary-light);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.history-item-type.social_media,
|
||||
.training-item-type.social_media {
|
||||
background-color: var(--secondary-color);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.history-item-type.blog_post,
|
||||
.training-item-type.blog_post {
|
||||
background-color: var(--success-color);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.history-item-type.website_copy,
|
||||
.training-item-type.website_copy {
|
||||
background-color: var(--warning-color);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.history-item-content,
|
||||
.training-item-content {
|
||||
flex: 1;
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
.history-item-content h4,
|
||||
.training-item-content h4 {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.history-item-content p,
|
||||
.training-item-content p {
|
||||
color: var(--grey-500);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.history-item-date {
|
||||
color: var(--grey-500);
|
||||
font-size: 14px;
|
||||
min-width: 100px;
|
||||
text-align: right;
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
.history-item-actions,
|
||||
.training-item-actions {
|
||||
display: flex;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.metrics {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.metric {
|
||||
font-size: 13px;
|
||||
color: var(--grey-600);
|
||||
background-color: var(--grey-100);
|
||||
padding: 2px 8px;
|
||||
border-radius: var(--radius-sm);
|
||||
}
|
||||
|
||||
/* Brand Style */
|
||||
.tag-selector {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.tag {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding: 6px 12px;
|
||||
background-color: var(--grey-200);
|
||||
color: var(--grey-700);
|
||||
border-radius: 20px;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.tag.selected {
|
||||
background-color: var(--primary-color);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.tag.removable {
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
.tag.removable i {
|
||||
margin-left: 8px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.tag-editor {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.tag-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.tag-input-container {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.tag-input-container input {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.terminology-table {
|
||||
margin-top: 15px;
|
||||
border: 1px solid var(--grey-200);
|
||||
border-radius: var(--radius-md);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.terminology-header {
|
||||
display: flex;
|
||||
background-color: var(--grey-100);
|
||||
padding: 12px 15px;
|
||||
font-weight: 600;
|
||||
border-bottom: 1px solid var(--grey-200);
|
||||
}
|
||||
|
||||
.terminology-row {
|
||||
display: flex;
|
||||
padding: 12px 15px;
|
||||
border-bottom: 1px solid var(--grey-200);
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.terminology-row:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.term-avoid {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.term-use {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.term-actions {
|
||||
width: 50px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.terminology-row.add-row input {
|
||||
width: 100%;
|
||||
border: none;
|
||||
padding: 5px 0;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.terminology-row.add-row input:focus {
|
||||
outline: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
/* Training Tabs */
|
||||
.training-tabs {
|
||||
display: flex;
|
||||
margin-bottom: 20px;
|
||||
border-bottom: 1px solid var(--grey-200);
|
||||
}
|
||||
|
||||
.tab {
|
||||
padding: 12px 20px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
color: var(--grey-500);
|
||||
}
|
||||
|
||||
.tab.active {
|
||||
color: var(--primary-color);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.tab.active:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: -1px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 2px;
|
||||
background-color: var(--primary-color);
|
||||
}
|
||||
|
||||
.tab-content {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tab-content.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Responsive */
|
||||
@media (max-width: 992px) {
|
||||
.sidebar {
|
||||
width: 80px;
|
||||
padding: 15px 0;
|
||||
}
|
||||
|
||||
.logo h2 {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.menu li {
|
||||
justify-content: center;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.menu li i {
|
||||
margin-right: 0;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.menu li span {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.user-info {
|
||||
justify-content: center;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.user-avatar {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.user-name {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.content {
|
||||
margin-left: 80px;
|
||||
max-width: calc(100vw - 80px);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.form-row {
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.templates-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.history-item,
|
||||
.training-item {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.history-item-type,
|
||||
.training-item-type {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.history-item-content,
|
||||
.training-item-content {
|
||||
padding: 0;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.history-item-date {
|
||||
text-align: left;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.checkbox-group {
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user