theaimoron's picture
Add 2 files
4e38357 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Story - Social Story Creator</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.fade-in {
animation: fadeIn 0.5s ease-in-out;
}
.symbol-btn:hover {
transform: scale(1.1);
transition: transform 0.2s;
}
.page-preview {
min-height: 200px;
border-radius: 10px;
}
.draggable-item {
cursor: grab;
}
.draggable-item:active {
cursor: grabbing;
}
.instruction-step {
background: rgba(124, 58, 237, 0.1);
border-left: 4px solid #7c3aed;
padding: 10px;
margin-bottom: 10px;
border-radius: 0 4px 4px 0;
}
.example-box {
background: rgba(16, 185, 129, 0.1);
border: 2px dashed #10b981;
border-radius: 8px;
padding: 15px;
margin: 10px 0;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.loading-spinner {
border: 5px solid rgba(255, 255, 255, 0.3);
border-radius: 50%;
border-top: 5px solid #7c3aed;
width: 50px;
height: 50px;
animation: spin 1s linear infinite;
}
.loading-text {
position: relative;
}
.loading-text::after {
content: "...";
position: absolute;
animation: dots 1.5s steps(5, end) infinite;
}
@keyframes dots {
0%, 20% { content: "."; }
40% { content: ".."; }
60%, 100% { content: "..."; }
}
</style>
</head>
<body class="bg-black text-white min-h-screen">
<!-- Welcome Modal -->
<div id="welcomeModal" class="fixed inset-0 bg-black bg-opacity-90 flex items-center justify-center z-50 p-4">
<div class="bg-gray-900 rounded-lg p-6 max-w-2xl w-full mx-4 border-2 border-purple-500">
<div class="text-center mb-6">
<h1 class="text-4xl font-bold text-purple-400 mb-2">
<i class="fas fa-book-open mr-2"></i>Welcome to My Story!
</h1>
<p class="text-xl text-blue-300">Let's create stories and schedules together!</p>
</div>
<div class="mb-6">
<h2 class="text-2xl text-yellow-300 mb-3 font-bold">How to Use This App</h2>
<div class="instruction-step">
<h3 class="text-lg text-pink-400 font-medium"><i class="fas fa-book mr-2"></i>Story Creator</h3>
<p class="text-white">1. Tap on symbols to add them to your story</p>
<p class="text-white">2. Type words to tell your story</p>
<p class="text-white">3. Add sounds and animations to make it fun!</p>
</div>
<div class="instruction-step">
<h3 class="text-lg text-green-400 font-medium"><i class="fas fa-calendar-alt mr-2"></i>Visual Schedule</h3>
<p class="text-white">1. Drag symbols to your schedule</p>
<p class="text-white">2. Type what happens at each step</p>
<p class="text-white">3. See your day in pictures!</p>
</div>
</div>
<div class="example-box">
<h3 class="text-xl text-green-400 font-bold mb-2"><i class="fas fa-lightbulb mr-2"></i>Example Story</h3>
<div class="flex items-center mb-3">
<div class="bg-blue-600 text-white p-3 rounded-full mr-3">
<i class="fas fa-home text-2xl"></i>
</div>
<p class="text-white">"First, I wake up at home."</p>
</div>
<div class="flex items-center mb-3">
<div class="bg-yellow-500 text-white p-3 rounded-full mr-3">
<i class="fas fa-utensils text-2xl"></i>
</div>
<p class="text-white">"Then, I eat breakfast."</p>
</div>
<div class="flex items-center">
<div class="bg-red-500 text-white p-3 rounded-full mr-3">
<i class="fas fa-bus text-2xl"></i>
</div>
<p class="text-white">"Finally, I take the bus to school."</p>
</div>
</div>
<div class="mt-6 text-center">
<button id="startButton" class="bg-purple-600 hover:bg-purple-700 text-white px-8 py-3 rounded-lg text-xl font-bold">
<i class="fas fa-play mr-2"></i>Let's Begin!
</button>
</div>
</div>
</div>
<!-- Loading Screen -->
<div id="loadingScreen" class="fixed inset-0 bg-black bg-opacity-90 flex flex-col items-center justify-center z-50 hidden">
<div class="loading-spinner mb-4"></div>
<h2 class="text-2xl text-purple-400 mb-2">Your story begins now</h2>
<p class="text-blue-300 loading-text">Loading</p>
</div>
<div class="container mx-auto px-4 py-6">
<!-- Header -->
<header class="flex justify-between items-center mb-8">
<h1 class="text-3xl font-bold text-purple-400">
<i class="fas fa-book-open mr-2"></i>My Story
</h1>
<button id="helpBtn" class="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg">
<i class="fas fa-question-circle mr-1"></i>Help
</button>
</header>
<!-- Main App Tabs -->
<div class="flex border-b border-gray-700 mb-6">
<button id="storyTab" class="tab-btn active px-4 py-2 font-medium text-pink-400 border-b-2 border-pink-400">
Story Creator
</button>
<button id="scheduleTab" class="tab-btn px-4 py-2 font-medium text-green-400">
Visual Schedule
</button>
</div>
<!-- Story Creator Section -->
<div id="storyCreator" class="fade-in">
<div class="mb-6">
<label class="block text-yellow-300 mb-2">Story Title</label>
<input type="text" id="storyTitle" class="w-full bg-gray-800 text-white p-3 rounded-lg border border-gray-700 focus:border-purple-500 focus:outline-none" placeholder="Enter your story title">
</div>
<!-- Page Editor -->
<div class="bg-gray-900 p-4 rounded-lg mb-6">
<div class="flex justify-between items-center mb-4">
<h3 class="text-xl text-blue-300">Page Editor</h3>
<div>
<button id="addPageBtn" class="bg-green-600 hover:bg-green-700 text-white px-3 py-1 rounded mr-2">
<i class="fas fa-plus mr-1"></i>Add Page
</button>
<button id="deletePageBtn" class="bg-red-600 hover:bg-red-700 text-white px-3 py-1 rounded">
<i class="fas fa-trash mr-1"></i>Delete
</button>
</div>
</div>
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<!-- Page Preview -->
<div class="bg-gray-800 p-4 page-preview flex flex-col items-center justify-center border-2 border-purple-500">
<p id="currentPageNumber" class="text-purple-300 mb-2">Page 1</p>
<div id="pagePreview" class="w-full h-40 bg-gray-700 rounded flex items-center justify-center text-gray-400">
Your page content will appear here
</div>
<div class="mt-4 flex space-x-2">
<button id="prevPageBtn" class="bg-gray-700 hover:bg-gray-600 text-white px-3 py-1 rounded">
<i class="fas fa-arrow-left"></i>
</button>
<button id="nextPageBtn" class="bg-gray-700 hover:bg-gray-600 text-white px-3 py-1 rounded">
<i class="fas fa-arrow-right"></i>
</button>
</div>
</div>
<!-- Content Editor -->
<div class="col-span-2">
<div class="mb-4">
<label class="block text-yellow-300 mb-2">Page Text</label>
<textarea id="pageText" class="w-full bg-gray-800 text-white p-3 rounded-lg border border-gray-700 focus:border-purple-500 focus:outline-none h-24" placeholder="Enter text for this page"></textarea>
</div>
<div class="mb-4">
<label class="block text-yellow-300 mb-2">Add Symbol</label>
<div class="grid grid-cols-4 gap-2">
<button class="symbol-btn bg-blue-600 hover:bg-blue-700 text-white p-2 rounded">
<i class="fas fa-smile text-2xl"></i>
</button>
<button class="symbol-btn bg-red-500 hover:bg-red-600 text-white p-2 rounded">
<i class="fas fa-heart text-2xl"></i>
</button>
<button class="symbol-btn bg-green-500 hover:bg-green-600 text-white p-2 rounded">
<i class="fas fa-home text-2xl"></i>
</button>
<button class="symbol-btn bg-yellow-500 hover:bg-yellow-600 text-white p-2 rounded">
<i class="fas fa-car text-2xl"></i>
</button>
<button class="symbol-btn bg-purple-500 hover:bg-purple-600 text-white p-2 rounded">
<i class="fas fa-utensils text-2xl"></i>
</button>
<button class="symbol-btn bg-pink-500 hover:bg-pink-600 text-white p-2 rounded">
<i class="fas fa-school text-2xl"></i>
</button>
<button class="symbol-btn bg-indigo-500 hover:bg-indigo-600 text-white p-2 rounded">
<i class="fas fa-bed text-2xl"></i>
</button>
<button class="symbol-btn bg-teal-500 hover:bg-teal-600 text-white p-2 rounded">
<i class="fas fa-bath text-2xl"></i>
</button>
</div>
</div>
<div class="mb-4">
<label class="block text-yellow-300 mb-2">Add Sound</label>
<select id="soundSelect" class="w-full bg-gray-800 text-white p-2 rounded-lg border border-gray-700 focus:border-purple-500 focus:outline-none">
<option value="">No sound</option>
<option value="bell">Bell</option>
<option value="chime">Chime</option>
<option value="ding">Ding</option>
<option value="success">Success</option>
</select>
</div>
<div>
<label class="block text-yellow-300 mb-2">Animation</label>
<div class="flex space-x-2">
<button class="animation-btn bg-gray-700 hover:bg-gray-600 text-white px-3 py-1 rounded" data-animation="fade">
Fade In
</button>
<button class="animation-btn bg-gray-7 hover:bg-gray-600 text-white px-3 py-1 rounded" data-animation="bounce">
Bounce
</button>
<button class="animation-btn bg-gray-700 hover:bg-gray-600 text-white px-3 py-1 rounded" data-animation="shake">
Shake
</button>
</div>
</div>
</div>
</div>
</div>
<!-- Save/Export -->
<div class="flex justify-end space-x-3">
<button id="saveStoryBtn" class="bg-purple-600 hover:bg-purple-700 text-white px-6 py-2 rounded-lg">
<i class="fas fa-save mr-2"></i>Save Story
</button>
<button id="exportStoryBtn" class="bg-green-600 hover:bg-green-700 text-white px-6 py-2 rounded-lg">
<i class="fas fa-file-export mr-2"></i>Export
</button>
</div>
</div>
<!-- Visual Schedule Section (Hidden by default) -->
<div id="visualSchedule" class="hidden fade-in">
<div class="mb-6">
<label class="block text-yellow-300 mb-2">Schedule Title</label>
<input type="text" id="scheduleTitle" class="w-full bg-gray-800 text-white p-3 rounded-lg border border-gray-700 focus:border-purple-500 focus:outline-none" placeholder="Enter your schedule title">
</div>
<div class="bg-gray-900 p-4 rounded-lg mb-6">
<div class="flex justify-between items-center mb-4">
<h3 class="text-xl text-blue-300">Schedule Items</h3>
<button id="addScheduleItemBtn" class="bg-green-600 hover:bg-green-700 text-white px-3 py-1 rounded">
<i class="fas fa-plus mr-1"></i>Add Item
</button>
</div>
<!-- Schedule Items Container -->
<div id="scheduleItemsContainer" class="space-y-3">
<!-- Sample items will be added here -->
</div>
</div>
<!-- Symbol Library for Schedule -->
<div class="mb-6">
<h3 class="text-xl text-blue-300 mb-3">Symbol Library</h3>
<div class="grid grid-cols-6 gap-3">
<div class="symbol-item draggable-item bg-gray-800 p-3 rounded-lg text-center cursor-move" draggable="true" data-symbol="home">
<i class="fas fa-home text-3xl text-yellow-400 mb-1"></i>
<p class="text-sm">Home</p>
</div>
<div class="symbol-item draggable-item bg-gray-800 p-3 rounded-lg text-center cursor-move" draggable="true" data-symbol="school">
<i class="fas fa-school text-3xl text-blue-400 mb-1"></i>
<p class="text-sm">School</p>
</div>
<div class="symbol-item draggable-item bg-gray-800 p-3 rounded-lg text-center cursor-move" draggable="true" data-symbol="eat">
<i class="fas fa-utensils text-3xl text-red-400 mb-1"></i>
<p class="text-sm">Eat</p>
</div>
<div class="symbol-item draggable-item bg-gray-800 p-3 rounded-lg text-center cursor-move" draggable="true" data-symbol="play">
<i class="fas fa-gamepad text-3xl text-green-400 mb-1"></i>
<p class="text-sm">Play</p>
</div>
<div class="symbol-item draggable-item bg-gray-800 p-3 rounded-lg text-center cursor-move" draggable="true" data-symbol="sleep">
<i class="fas fa-bed text-3xl text-purple-400 mb-1"></i>
<p class="text-sm">Sleep</p>
</div>
<div class="symbol-item draggable-item bg-gray-800 p-3 rounded-lg text-center cursor-move" draggable="true" data-symbol="bath">
<i class="fas fa-bath text-3xl text-teal-400 mb-1"></i>
<p class="text-sm">Bath</p>
</div>
</div>
</div>
<!-- Save/Export Schedule -->
<div class="flex justify-end space-x-3">
<button id="saveScheduleBtn" class="bg-purple-600 hover:bg-purple-700 text-white px-6 py-2 rounded-lg">
<i class="fas fa-save mr-2"></i>Save Schedule
</button>
<button id="exportScheduleBtn" class="bg-green-600 hover:bg-green-700 text-white px-6 py-2 rounded-lg">
<i class="fas fa-file-export mr-2"></i>Export
</button>
</div>
</div>
</div>
<!-- Help Modal -->
<div id="helpModal" class="fixed inset-0 bg-black bg-opacity-75 flex items-center justify-center hidden z-50">
<div class="bg-gray-900 rounded-lg p-6 max-w-md w-full mx-4 border border-purple-500">
<div class="flex justify-between items-center mb-4">
<h3 class="text-xl text-purple-400">Help Guide</h3>
<button id="closeHelpModal" class="text-gray-400 hover:text-white">
<i class="fas fa-times"></i>
</button>
</div>
<div class="space-y-3">
<p class="text-blue-300"><i class="fas fa-book mr-2"></i><strong>Story Creator:</strong> Create multi-page stories with text, symbols, sounds and animations.</p>
<p class="text-green-300"><i class="fas fa-calendar-alt mr-2"></i><strong>Visual Schedule:</strong> Create step-by-step schedules with draggable symbols.</p>
<p class="text-yellow-300"><i class="fas fa-icons mr-2"></i>Click on symbols to add them to your story pages.</p>
<p class="text-pink-300"><i class="fas fa-arrows-alt mr-2"></i>Drag and drop symbols in the visual schedule.</p>
<p class="text-gray-400 text-sm mt-4">My Story v1.0 - Basic Tier</p>
</div>
</div>
</div>
<script>
// App State
const appState = {
currentTab: 'story',
currentPage: 1,
pages: [
{
text: '',
symbol: null,
sound: null,
animation: null
}
],
scheduleItems: []
};
// DOM Elements
const welcomeModal = document.getElementById('welcomeModal');
const loadingScreen = document.getElementById('loadingScreen');
const startButton = document.getElementById('startButton');
const storyTab = document.getElementById('storyTab');
const scheduleTab = document.getElementById('scheduleTab');
const storyCreator = document.getElementById('storyCreator');
const visualSchedule = document.getElementById('visualSchedule');
const helpBtn = document.getElementById('helpBtn');
const helpModal = document.getElementById('helpModal');
const closeHelpModal = document.getElementById('closeHelpModal');
const storyTitle = document.getElementById('storyTitle');
const pageText = document.getElementById('pageText');
const currentPageNumber = document.getElementById('currentPageNumber');
const pagePreview = document.getElementById('pagePreview');
const addPageBtn = document.getElementById('addPageBtn');
const deletePageBtn = document.getElementById('deletePageBtn');
const prevPageBtn = document.getElementById('prevPageBtn');
const nextPageBtn = document.getElementById('nextPageBtn');
const soundSelect = document.getElementById('soundSelect');
const saveStoryBtn = document.getElementById('saveStoryBtn');
const exportStoryBtn = document.getElementById('exportStoryBtn');
const scheduleTitle = document.getElementById('scheduleTitle');
const addScheduleItemBtn = document.getElementById('addScheduleItemBtn');
const scheduleItemsContainer = document.getElementById('scheduleItemsContainer');
const saveScheduleBtn = document.getElementById('saveScheduleBtn');
const exportScheduleBtn = document.getElementById('exportScheduleBtn');
const symbolBtns = document.querySelectorAll('.symbol-btn');
const animationBtns = document.querySelectorAll('.animation-btn');
const symbolItems = document.querySelectorAll('.symbol-item');
// Start the app
startButton.addEventListener('click', function() {
welcomeModal.classList.add('hidden');
loadingScreen.classList.remove('hidden');
// Simulate loading for 2 seconds
setTimeout(function() {
loadingScreen.classList.add('hidden');
// Play a welcoming sound
playSound('chime');
}, 2000);
});
// Tab Switching
storyTab.addEventListener('click', () => switchTab('story'));
scheduleTab.addEventListener('click', () => switchTab('schedule'));
function switchTab(tab) {
appState.currentTab = tab;
if (tab === 'story') {
storyTab.classList.add('border-b-2', 'border-pink-400');
scheduleTab.classList.remove('border-b-2', 'border-green-400');
storyCreator.classList.remove('hidden');
visualSchedule.classList.add('hidden');
playSound('ding');
} else {
storyTab.classList.remove('border-b-2', 'border-pink-400');
scheduleTab.classList.add('border-b-2', 'border-green-400');
storyCreator.classList.add('hidden');
visualSchedule.classList.remove('hidden');
playSound('bell');
}
}
// Help Modal
helpBtn.addEventListener('click', () => {
helpModal.classList.remove('hidden');
playSound('ding');
});
closeHelpModal.addEventListener('click', () => {
helpModal.classList.add('hidden');
});
// Story Page Management
addPageBtn.addEventListener('click', addPage);
deletePageBtn.addEventListener('click', deletePage);
prevPageBtn.addEventListener('click', goToPrevPage);
nextPageBtn.addEventListener('click', goToNextPage);
function addPage() {
appState.pages.push({
text: '',
symbol: null,
sound: null,
animation: null
});
appState.currentPage = appState.pages.length;
updatePageDisplay();
playSound('success');
}
function deletePage() {
if (appState.pages.length > 1) {
appState.pages.splice(appState.currentPage - 1, 1);
if (appState.currentPage > appState.pages.length) {
appState.currentPage = appState.pages.length;
}
updatePageDisplay();
playSound('bell');
} else {
alert("You must have at least one page in your story.");
}
}
function goToPrevPage() {
if (appState.currentPage > 1) {
appState.currentPage--;
updatePageDisplay();
playSound('ding');
}
}
function goToNextPage() {
if (appState.currentPage < appState.pages.length) {
appState.currentPage++;
updatePageDisplay();
playSound('ding');
}
}
function updatePageDisplay() {
const currentPageData = appState.pages[appState.currentPage - 1];
// Update page number display
currentPageNumber.textContent = `Page ${appState.currentPage} of ${appState.pages.length}`;
// Update form fields with current page data
pageText.value = currentPageData.text || '';
soundSelect.value = currentPageData.sound || '';
// Update preview
updatePagePreview();
}
function updatePagePreview() {
const currentPageData = appState.pages[appState.currentPage - 1];
let previewHTML = '';
if (currentPageData.text) {
previewHTML += `<p class="text-white mb-2 text-lg">${currentPageData.text}</p>`;
}
if (currentPageData.symbol) {
// This is a simplified version - in a real app, you'd map to actual symbols
previewHTML += `<div class="text-5xl my-3">${getSymbolIcon(currentPageData.symbol)}</div>`;
}
pagePreview.innerHTML = previewHTML || 'Your page content will appear here';
// Apply animation class if exists
if (currentPageData.animation) {
pagePreview.className = 'w-full h-40 bg-gray-700 rounded flex items-center justify-center ' + currentPageData.animation;
} else {
pagePreview.className = 'w-full h-40 bg-gray-700 rounded flex items-center justify-center';
}
}
function getSymbolIcon(symbol) {
// Simplified mapping - in a real app you'd have proper symbol mapping
const icons = {
'smile': 'fa-smile',
'heart': 'fa-heart',
'home': 'fa-home',
'car': 'fa-car',
'utensils': 'fa-utensils',
'school': 'fa-school',
'bed': 'fa-bed',
'bath': 'fa-bath'
};
return `<i class="fas ${icons[symbol] || 'fa-question'}"></i>`;
}
// Form Field Event Listeners
pageText.addEventListener('input', function() {
appState.pages[appState.currentPage - 1].text = this.value;
updatePagePreview();
});
soundSelect.addEventListener('change', function() {
appState.pages[appState.currentPage - 1].sound = this.value;
if (this.value) {
playSound(this.value);
}
});
// Symbol Buttons
symbolBtns.forEach(btn => {
btn.addEventListener('click', function() {
const iconClass = this.querySelector('i').className.split(' ')[1];
const symbol = iconClass.replace('fa-', '');
appState.pages[appState.currentPage - 1].symbol = symbol;
updatePagePreview();
playSound('ding');
});
});
// Animation Buttons
animationBtns.forEach(btn => {
btn.addEventListener('click', function() {
const animation = this.dataset.animation;
appState.pages[appState.currentPage - 1].animation = animation;
updatePagePreview();
playSound('chime');
});
});
// Save/Export Buttons
saveStoryBtn.addEventListener('click', function() {
alert('Story saved successfully!');
playSound('success');
// In a real app, this would save to localStorage or a database
});
exportStoryBtn.addEventListener('click', function() {
alert('Story exported!');
playSound('success');
// In a real app, this would generate a PDF or shareable file
});
// Visual Schedule Functions
addScheduleItemBtn.addEventListener('click', addScheduleItem);
function addScheduleItem() {
const itemId = Date.now();
const itemHTML = `
<div class="schedule-item bg-gray-800 p-3 rounded-lg flex items-center" data-id="${itemId}">
<div class="symbol-placeholder bg-gray-700 w-10 h-10 rounded-full flex items-center justify-center mr-3">
<i class="fas fa-plus text-gray-400"></i>
</div>
<input type="text" class="flex-grow bg-gray-700 text-white p-2 rounded border border-gray-600 focus:border-green-500 focus:outline-none" placeholder="Enter step description">
<button class="delete-schedule-item ml-2 text-red-400 hover:text-red-300">
<i class="fas fa-trash"></i>
</button>
</div>
`;
scheduleItemsContainer.insertAdjacentHTML('beforeend', itemHTML);
appState.scheduleItems.push({
id: itemId,
symbol: null,
text: ''
});
// Add event listener to the delete button
const newItem = scheduleItemsContainer.lastElementChild;
const deleteBtn = newItem.querySelector('.delete-schedule-item');
deleteBtn.addEventListener('click', function() {
deleteScheduleItem(itemId);
});
// Add drop target for symbols
const symbolPlaceholder = newItem.querySelector('.symbol-placeholder');
symbolPlaceholder.addEventListener('dragover', handleDragOver);
symbolPlaceholder.addEventListener('drop', function(e) {
handleDrop(e, itemId);
});
// Add input event listener
const textInput = newItem.querySelector('input');
textInput.addEventListener('input', function() {
updateScheduleItemText(itemId, this.value);
});
playSound('ding');
}
function deleteScheduleItem(itemId) {
const itemIndex = appState.scheduleItems.findIndex(item => item.id === itemId);
if (itemIndex !== -1) {
appState.scheduleItems.splice(itemIndex, 1);
}
const itemElement = document.querySelector(`.schedule-item[data-id="${itemId}"]`);
if (itemElement) {
itemElement.remove();
}
playSound('bell');
}
function updateScheduleItemText(itemId, text) {
const item = appState.scheduleItems.find(item => item.id === item
</html>