Autotutorial / index.html
luigi12345's picture
Update index.html
3ca1cd5 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="viewport-fit=cover, width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>Autotutorial.ai</title>
<link rel="manifest" href="manifest.json"> <!-- Create this file for PWA -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<!-- Ionic CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ionic/core@7/css/ionic.bundle.css">
<!-- Google Fonts (Inter) -->
<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;500;600;700&display=swap" rel="stylesheet">
<style>
:root {
--ion-font-family: 'Inter', sans-serif;
/* Define app-specific colors (based on previous designs, refined)*/
--app-primary: #4f46e5; /* Indigo-600 from Tailwind/Radix */
--app-primary-rgb: 79,70,229;
--app-primary-contrast: #ffffff;
--app-primary-contrast-rgb: 255,255,255;
--app-primary-shade: #4640cc; /* Slightly darker shade */
--app-primary-tint: #615ce6; /* Slightly lighter tint */
--ion-color-primary: var(--app-primary);
--ion-color-primary-rgb: var(--app-primary-rgb);
--ion-color-primary-contrast: var(--app-primary-contrast);
--ion-color-primary-contrast-rgb: var(--app-primary-contrast-rgb);
--ion-color-primary-shade: var(--app-primary-shade);
--ion-color-primary-tint: var(--app-primary-tint);
}
/* Global Style Tweaks */
body {
font-family: var(--ion-font-family);
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.video-preview-container {
border-radius: var(--ion-border-radius);
overflow: hidden;
position: relative; /* For overlay */
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); /* Subtle shadow */
}
.video-title-overlay {
position: absolute;
bottom: 16px;
left: 16px;
color: white;
font-size: 1.2em;
font-weight: 600;
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
}
.hidden {
display: none !important;
}
</style>
</head>
<body>
<ion-app>
<ion-header>
<ion-toolbar color="primary">
<ion-title>Autotutorial.ai</ion-title>
<ion-buttons slot="end">
<ion-button id="helpButton">
<ion-icon slot="icon-only" name="help-circle"></ion-icon>
</ion-button>
</ion-buttons>
</ion-toolbar>
</ion-header>
<ion-content class="ion-padding">
<!-- Main Content: Generate Tutorial -->
<div id="generate-content">
<ion-card>
<ion-card-header>
<ion-card-title>Generate Tutorial</ion-card-title>
<ion-card-subtitle>Create a new video tutorial</ion-card-subtitle>
</ion-card-header>
<ion-card-content>
<ion-list lines="full">
<ion-item>
<ion-label position="floating">Tutorial Topic</ion-label>
<ion-input id="tutorialTopic" value="CSS Grid Layout"></ion-input>
</ion-item>
<ion-item>
<ion-label>Duration</ion-label>
<ion-select id="tutorialDuration" value="10">
<ion-select-option value="5">5 Minutes</ion-select-option>
<ion-select-option value="10">10 Minutes</ion-select-option>
<ion-select-option value="15">15 Minutes</ion-select-option>
<ion-select-option value="20">20 Minutes</ion-select-option>
</ion-select>
</ion-item>
<ion-item>
<ion-label position="floating">OpenAI API Key (Optional)</ion-label>
<ion-input id="openaiApiKey" type="text" placeholder="sk-..." value="sk-DEMO_OPENAI_KEY"></ion-input>
</ion-item>
<ion-item>
<ion-label position="floating">Video Gen. API Key (Optional)</ion-label>
<ion-input id="videoGenApiKey" type="text" placeholder="vg-..." value="vg-DEMO_VIDEO_KEY"></ion-input>
</ion-item>
</ion-list>
<ion-button id="generateButton" expand="block" color="primary" style="margin-top: 20px;">
<ion-icon slot="start" name="play-circle"></ion-icon>
Generate
</ion-button>
<ion-button id="resetButton" expand="block" color="medium" style="margin-top: 10px;" class="hidden">
<ion-icon slot="start" name="refresh"></ion-icon>
Reset
</ion-button>
</ion-card-content>
</ion-card>
<ion-card id="statusCard" class="hidden">
<ion-card-header>
<ion-card-title>Status</ion-card-title>
</ion-card-header>
<ion-card-content>
<ion-list id="statusList"></ion-list>
<ion-progress-bar id="progressBar" type="indeterminate"></ion-progress-bar> <!-- Changed to indeterminate -->
<ion-text color="danger" id="errorMessage" class="hidden"></ion-text>
</ion-card-content>
</ion-card>
<ion-card id="previewCard" class="hidden">
<ion-card-header>
<ion-card-title>Tutorial Preview</ion-card-title>
</ion-card-header>
<ion-card-content>
<div class="video-preview-container">
<video id="tutorialVideo" controls width="100%" preload="metadata">
<source src="https://vjs.zencdn.net/v/oceans.mp4" type="video/mp4"> <!-- Better demo video -->
Your browser does not support the video tag.
</video>
<div id="videoTitleOverlay" class="video-title-overlay"></div>
</div>
<ion-button expand="block" id="downloadButton" style="margin-top: 16px;">
<ion-icon slot="start" name="download"></ion-icon>
Download (Demo)
</ion-button>
</ion-card-content>
</ion-card>
</div>
<!-- Tutorial History (Initially Hidden) -->
<div id="history-content" class="hidden">
<ion-card>
<ion-card-header>
<ion-card-title>Tutorial History</ion-card-title>
<ion-card-subtitle>View your past tutorials</ion-card-subtitle>
</ion-card-header>
<ion-card-content>
<ion-list id="historyList">
<ion-item button class="history-item" data-title="React Hooks Guide">
<ion-label>React Hooks Guide</ion-label>
<ion-note slot="end">Oct 28, 2023</ion-note> <!-- Use ion-note for date -->
</ion-item>
<ion-item button class="history-item" data-title="Vue.js Composition API">
<ion-label>Vue.js Composition API</ion-label>
<ion-note slot="end">Oct 27, 2023</ion-note>
</ion-item>
<ion-item button class="history-item" data-title="Python for Data Science">
<ion-label>Python for Data Science</ion-label>
<ion-note slot="end">Oct 26, 2023</ion-note>
</ion-item>
</ion-list>
<ion-text color="medium">
<p>This is a simulated history for demo purposes.</p>
</ion-text>
</ion-card-content>
</ion-card>
</div>
<!-- Settings (Initially Hidden) -->
<div id="settings-content" class="hidden">
<ion-card>
<ion-card-header>
<ion-card-title>Settings</ion-card-title>
<ion-card-subtitle>Configure app preferences</ion-card-subtitle>
</ion-card-header>
<ion-card-content>
<ion-list lines="full">
<ion-item>
<ion-label>Default Duration</ion-label>
<ion-select id="defaultDuration" value="10">
<ion-select-option value="5">5 Minutes</ion-select-option>
<ion-select-option value="10">10 Minutes</ion-select-option>
<ion-select-option value="15">15 Minutes</ion-select-option>
<ion-select-option value="20">20 Minutes</ion-select-option>
</ion-select>
</ion-item>
<ion-item>
<ion-label>Default Quality</ion-label>
<ion-select id="defaultQuality" value="720p">
<ion-select-option value="720p">720p</ion-select-option>
<ion-select-option value="1080p">1080p</ion-select-option>
<ion-select-option value="4k">4K (Premium)</ion-select-option>
</ion-select>
</ion-item>
<ion-item>
<ion-label>Voiceover Language</ion-label>
<ion-select id="defaultVoiceover" value="en-US">
<ion-select-option value="en-US">English (US)</ion-select-option>
<ion-select-option value="en-GB">English (UK)</ion-select-option>
<ion-select-option value="es-ES">Spanish (ES)</ion-select-option>
</ion-select>
</ion-item>
<ion-item>
<ion-label>Output Format</ion-label>
<ion-select id="defaultOutput" value="mp4">
<ion-select-option value="mp4">MP4</ion-select-option>
<ion-select-option value="mov">MOV</ion-select-option>
<ion-select-option value="webm">WebM</ion-select-option>
</ion-select>
</ion-item>
</ion-list>
<ion-button id="applySettingsButton" expand="block" style="margin-top: 20px;">
<ion-icon slot="start" name="save"></ion-icon>
Apply Settings
</ion-button>
</ion-card-content>
</ion-card>
</div>
<!-- Help Modal (Initially Hidden) -->
<ion-modal id="helpModal" trigger="helpButton">
<ion-header>
<ion-toolbar>
<ion-title>Help & Support</ion-title>
<ion-buttons slot="end">
<ion-button onclick="closeHelpModal()">
<ion-icon slot="icon-only" name="close"></ion-icon>
</ion-button>
</ion-buttons>
</ion-toolbar>
</ion-header>
<ion-content class="ion-padding">
<p>Welcome to Autotutorial.ai, the app that makes creating video tutorials a breeze!</p>
<p><strong>Getting Started:</strong></p>
<ol>
<li>Navigate to the <strong>Generate Tutorial</strong> section.</li>
<li>Enter the topic of your tutorial in the <strong>Tutorial Topic</strong> field.</li>
<li>Select your desired tutorial length using the <strong>Duration</strong> dropdown.</li>
<li><em>(Optional)</em> If you have API keys for OpenAI and a video generation service, you can enter them in the respective fields for enhanced tutorial creation. This is not required for basic functionality.</li>
<li>Click the <strong>Generate</strong> button to start the automated tutorial creation process.</li>
<li>Monitor the <strong>Status</strong> section to see the progress of your tutorial generation.</li>
<li>Once complete, preview your generated tutorial in the <strong>Tutorial Preview</strong> section.</li>
</ol>
<p><strong>Tutorial History</strong> allows you to view a list of your previously generated tutorials (simulated in this demo).</p>
<p><strong>Settings</strong> let you configure default preferences for new tutorials (also simulated in this demo).</p>
<p>For any questions or support, please contact us at: <a href="mailto:[email protected]">[email protected]</a></p>
</ion-content>
</ion-modal>
</ion-content>
<ion-footer>
<ion-toolbar>
<ion-tabs>
<ion-tab-bar slot="bottom">
<ion-tab-button tab="generate" onclick="showSection('generate')">
<ion-icon name="play-circle"></ion-icon>
<ion-label>Generate</ion-label>
</ion-tab-button>
<ion-tab-button tab="history" onclick="showSection('history')">
<ion-icon name="time"></ion-icon>
<ion-label>History</ion-label>
</ion-tab-button>
<ion-tab-button tab="settings" onclick="showSection('settings')">
<ion-icon name="settings"></ion-icon>
<ion-label>Settings</ion-label>
</ion-tab-button>
</ion-tab-bar>
</ion-tabs>
</ion-toolbar>
</ion-footer>
</ion-app>
<!-- Ionic JavaScript -->
<script type="module" src="https://cdn.jsdelivr.net/npm/@ionic/core@7/dist/ionic/ionic.esm.js"></script>
<script nomodule src="https://cdn.jsdelivr.net/npm/@ionic/core@7/dist/ionic/ionic.js"></script>
<script>
function showSection(sectionId) {
// Hide all content sections
document.getElementById('generate-content').classList.add('hidden');
document.getElementById('history-content').classList.add('hidden');
document.getElementById('settings-content').classList.add('hidden');
// Remove active class from all tab buttons. Important for visual state.
document.querySelectorAll('ion-tab-button').forEach(btn => btn.classList.remove('tab-selected'));
// Show the selected section
document.getElementById(`${sectionId}-content`).classList.remove('hidden');
// Highlight active tab button
document.querySelector(`ion-tab-button[tab="${sectionId}"]`).classList.add('tab-selected');
// Hide preview and status cards when switching tabs *away* from generate
if (sectionId !== 'generate') {
document.getElementById('previewCard').classList.add('hidden');
document.getElementById('statusCard').classList.add('hidden');
}
}
function closeHelpModal() {
const modal = document.getElementById('helpModal');
modal.dismiss();
}
document.addEventListener('DOMContentLoaded', () => {
const generateButton = document.getElementById('generateButton');
const resetButton = document.getElementById('resetButton');
const statusCard = document.getElementById('statusCard');
const statusList = document.getElementById('statusList');
const progressBar = document.getElementById('progressBar');
const previewCard = document.getElementById('previewCard');
const videoTitleOverlay = document.getElementById('videoTitleOverlay');
const tutorialVideo = document.getElementById('tutorialVideo');
const errorMessage = document.getElementById('errorMessage');
// History click handler (simulated "load")
const historyList = document.getElementById('historyList');
historyList.addEventListener('click', (event) => {
const item = event.target.closest('.history-item'); // Find closest item
if (item) {
const title = item.dataset.title;
videoTitleOverlay.textContent = title;
previewCard.classList.remove('hidden'); // Show preview card
// You could simulate loading different videos here if you have multiple sources
// tutorialVideo.src = 'another_video.mp4';
// tutorialVideo.load();
statusCard.classList.remove('hidden'); // Show status
statusList.innerHTML = `<ion-item><ion-label color="primary">Loading ${title}...</ion-label></ion-item>`; // Show loading message
}
});
// Apply Settings simulation
document.getElementById('applySettingsButton').addEventListener('click', () => {
// Simulate setting changes (could visually update UI elements if desired)
statusCard.classList.remove('hidden');
statusList.innerHTML = `<ion-item><ion-label color="success">Settings applied!</ion-label></ion-item>`;
});
// Generate Button Click Handler
generateButton.addEventListener('click', () => {
const topic = document.getElementById('tutorialTopic').value;
const duration = document.getElementById('tutorialDuration').value;
const openaiKey = document.getElementById('openaiApiKey').value;
const videoGenKey = document.getElementById('videoGenApiKey').value;
// Clear previous status and error messages
statusList.innerHTML = '';
errorMessage.textContent = '';
errorMessage.classList.add('hidden');
// Show status and progress bar
statusCard.classList.remove('hidden');
progressBar.type = 'indeterminate'; // Start indeterminate
// Hide preview card (until generation is complete)
previewCard.classList.add('hidden');
// Hide Generate, show Reset
generateButton.classList.add('hidden');
resetButton.classList.remove('hidden');
const steps = [
{ message: "Analyzing Topic...", delay: 800 },
{ message: "Generating Script Outline (AI)...", delay: 1500 },
{ message: "Writing Script Content (AI)...", delay: 2200 },
{ message: "Synthesizing Voiceover (AI)...", delay: 1800 },
{ message: "Selecting Relevant Visuals...", delay: 1600 },
{ message: "Assembling Video Scenes...", delay: 2400 },
{ message: "Adding Transitions and Effects...", delay: 1500 },
{ message: "Rendering Final Video...", delay: 3000 }
];
let currentStep = 0;
function simulateStep() {
if (currentStep < steps.length) {
const listItem = document.createElement('ion-item');
listItem.innerHTML = `<ion-label>${steps[currentStep].message}</ion-label>`;
statusList.appendChild(listItem);
// Simulate varying delays
const delay = steps[currentStep].delay + (Math.random() * 500 - 250); // +/- 250ms variation
setTimeout(() => {
currentStep++;
simulateStep();
}, delay);
} else {
// Generation "complete"
progressBar.type = 'determinate'; // Switch to determinate for final "fill"
progressBar.value = 1; // Set to 100%
statusList.innerHTML = `<ion-item><ion-label color="success">Tutorial generation complete!</ion-label></ion-item>`;
videoTitleOverlay.textContent = `${topic} (${duration} min)`;
previewCard.classList.remove('hidden');
// Show generate, hide reset
generateButton.classList.remove('hidden');
resetButton.classList.add('hidden');
}
}
simulateStep();
});
// Reset Button Click Handler
resetButton.addEventListener('click', () => {
// Clear form fields
document.getElementById('tutorialTopic').value = '';
document.getElementById('tutorialDuration').value = '10';
document.getElementById('openaiApiKey').value = '';
document.getElementById('videoGenApiKey').value = '';
// Hide status, error, and preview cards
statusCard.classList.add('hidden');
errorMessage.classList.add('hidden');
previewCard.classList.add('hidden');
// Clear status list
statusList.innerHTML = '';
// Reset progress bar
progressBar.value = 0;
progressBar.type = 'indeterminate';
// Show Generate, hide Reset
generateButton.classList.remove('hidden');
resetButton.classList.add('hidden');
});
document.getElementById('downloadButton').addEventListener('click', () => {
// Simulate download
statusCard.classList.remove('hidden');
statusList.innerHTML = `<ion-item><ion-label color="primary">Downloading (simulated)...</ion-label></ion-item>`;
});
});
</script>
</body>
</html>